diff --git a/.lintstagedrc b/.lintstagedrc
deleted file mode 100644
index a8a47eb..0000000
--- a/.lintstagedrc
+++ /dev/null
@@ -1,4 +0,0 @@
-{
- "*.{j,t}s": ["eslint", "prettier --write"],
- "src/schemas/{*,**/*}.ts": ["eslint", "prettier --write", "tsc -b -v", "node scripts/schema.js", "node scripts/openapi.js" ]
-}
diff --git a/.lintstagedrc.js b/.lintstagedrc.js
new file mode 100644
index 0000000..76ea0b0
--- /dev/null
+++ b/.lintstagedrc.js
@@ -0,0 +1,4 @@
+module.exports = {
+ "*.{j,t}s": ["eslint", "prettier --write"],
+ "src/schemas/{*,**/*}.ts": [() => "tsc -b -v", () => "node scripts/schema.js", () => "node scripts/openapi.js"],
+};
diff --git a/.prettierrc.json b/.prettierrc.json
index 6172f0c..ebfbac3 100644
--- a/.prettierrc.json
+++ b/.prettierrc.json
@@ -1,13 +1,13 @@
{
- "trailingComma": "all",
- "tabWidth": 4,
- "semi": true,
- "arrowParens": "always",
- "bracketSameLine": false,
- "bracketSpacing": true,
- "quoteProps": "as-needed",
- "useTabs": false,
- "singleQuote": false,
- "endOfLine": "auto",
- "printWidth": 180
+ "trailingComma": "all",
+ "tabWidth": 4,
+ "semi": true,
+ "arrowParens": "always",
+ "bracketSameLine": false,
+ "bracketSpacing": true,
+ "quoteProps": "as-needed",
+ "useTabs": false,
+ "singleQuote": false,
+ "endOfLine": "auto",
+ "printWidth": 180
}
diff --git a/eslint.config.mjs b/eslint.config.mjs
index d0c0658..17e64dc 100644
--- a/eslint.config.mjs
+++ b/eslint.config.mjs
@@ -9,35 +9,35 @@
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);
const compat = new FlatCompat({
- baseDirectory: __dirname,
- recommendedConfig: js.configs.recommended,
- allConfig: js.configs.all,
+ baseDirectory: __dirname,
+ recommendedConfig: js.configs.recommended,
+ allConfig: js.configs.all,
});
export default [
- {
- ignores: ["**/node_modules", "**/dist", "**/README.md", "**/COPYING", "**/scripts/", "**/assets", "**/extra/"],
- },
- ...compat.extends("eslint:recommended", "plugin:@typescript-eslint/recommended"),
- {
- plugins: {
- "@typescript-eslint": typescriptEslint,
- },
+ {
+ ignores: ["**/node_modules", "**/dist", "**/README.md", "**/COPYING", "**/scripts/", "**/assets", "**/extra/"],
+ },
+ ...compat.extends("eslint:recommended", "plugin:@typescript-eslint/recommended"),
+ {
+ plugins: {
+ "@typescript-eslint": typescriptEslint,
+ },
- languageOptions: {
- globals: {
- ...globals.node,
- },
+ languageOptions: {
+ globals: {
+ ...globals.node,
+ },
- parser: tsParser,
- },
+ parser: tsParser,
+ },
- rules: {
- "no-mixed-spaces-and-tabs": "off",
- "@typescript-eslint/no-inferrable-types": "off", // Required by typeorm
- "@typescript-eslint/no-var-requires": "off", // Sometimes requred by typeorm to resolve circular deps
- "@typescript-eslint/no-require-imports": "off",
- "@typescript-eslint/no-unused-vars": "off",
- },
- },
+ rules: {
+ "no-mixed-spaces-and-tabs": "off",
+ "@typescript-eslint/no-inferrable-types": "off", // Required by typeorm
+ "@typescript-eslint/no-var-requires": "off", // Sometimes requred by typeorm to resolve circular deps
+ "@typescript-eslint/no-require-imports": "off",
+ "@typescript-eslint/no-unused-vars": "off",
+ },
+ },
];
diff --git a/package-lock.json b/package-lock.json
index ed7b29c..2c0a698 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,10195 +1,10195 @@
{
- "name": "spacebar-server",
- "version": "1.0.0",
- "lockfileVersion": 3,
- "requires": true,
- "packages": {
- "": {
- "name": "spacebar-server",
- "version": "1.0.0",
- "hasInstallScript": true,
- "license": "AGPL-3.0-only",
- "dependencies": {
- "@aws-sdk/client-s3": "^3.953.0",
- "@toondepauw/node-zstd": "^1.2.0",
- "ajv": "^8.17.1",
- "ajv-formats": "^3.0.1",
- "amqplib": "^0.10.9",
- "bcrypt": "^6.0.0",
- "body-parser": "^2.2.1",
- "chalk": "^5.6.2",
- "cheerio": "^1.1.2",
- "cookie-parser": "^1.4.7",
- "discord-protos": "^1.2.90",
- "dotenv": "^17.2.3",
- "email-providers": "^2.19.0",
- "exif-be-gone": "^1.5.1",
- "express": "^5.2.1",
- "fast-zlib": "^2.0.1",
- "fido2-lib": "^3.5.5",
- "file-type": "^21.1.1",
- "form-data": "^4.0.5",
- "i18next": "^25.7.3",
- "i18next-fs-backend": "^2.6.1",
- "i18next-http-middleware": "^3.9.0",
- "image-size": "^2.0.2",
- "json-bigint": "^1.0.0",
- "jsonwebtoken": "^9.0.3",
- "module-alias": "^2.2.3",
- "morgan": "^1.10.1",
- "ms": "^2.1.3",
- "multer": "^2.0.2",
- "murmurhash-js": "^1.0.0",
- "node-2fa": "^2.0.3",
- "pg": "^8.16.3",
- "pg-query-stream": "^4.10.3",
- "picocolors": "^1.1.1",
- "probe-image-size": "^7.2.3",
- "reflect-metadata": "^0.2.2",
- "sqlite3": "^5.1.7",
- "tslib": "^2.8.1",
- "typeorm": "^0.3.28",
- "wretch": "^2.11.1",
- "ws": "^8.18.3"
- },
- "devDependencies": {
- "@eslint/eslintrc": "^3.3.3",
- "@eslint/js": "^9.14.0",
- "@spacebarchat/spacebar-webrtc-types": "^1.0.1",
- "@types/amqplib": "^0.10.8",
- "@types/bcrypt": "^6.0.0",
- "@types/body-parser": "^1.19.6",
- "@types/cookie-parser": "^1.4.10",
- "@types/express": "^5.0.6",
- "@types/i18next-node-fs-backend": "^2.1.5",
- "@types/json-bigint": "^1.0.4",
- "@types/jsonwebtoken": "^9.0.10",
- "@types/module-alias": "^2.0.4",
- "@types/morgan": "^1.9.10",
- "@types/multer": "^2.0.0",
- "@types/murmurhash-js": "^1.0.6",
- "@types/node": "^24.10.4",
- "@types/nodemailer": "^7.0.4",
- "@types/probe-image-size": "^7.2.5",
- "@types/sharp": "^0.31.1",
- "@types/ws": "^8.18.1",
- "@typescript-eslint/eslint-plugin": "^8.50.0",
- "@typescript-eslint/parser": "^8.50.0",
- "eslint": "^9.39.2",
- "globals": "^16.5.0",
- "husky": "^9.1.7",
- "patch-package": "^8.0.1",
- "prettier": "^3.7.4",
- "pretty-quick": "^4.2.2",
- "ts-node": "^10.9.2",
- "typescript": "^5.9.3",
- "typescript-json-schema": "^0.65.1"
- },
- "optionalDependencies": {
- "@sendgrid/mail": "^8.1.6",
- "@yukikaze-bot/erlpack": "^1.0.1",
- "jimp": "^1.6.0",
- "mailgun.js": "^12.4.0",
- "node-mailjet": "^6.0.11",
- "nodemailer": "^7.0.11"
- }
- },
- "node_modules/@aws-crypto/crc32": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz",
- "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/util": "^5.2.0",
- "@aws-sdk/types": "^3.222.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=16.0.0"
- }
- },
- "node_modules/@aws-crypto/crc32c": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz",
- "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/util": "^5.2.0",
- "@aws-sdk/types": "^3.222.0",
- "tslib": "^2.6.2"
- }
- },
- "node_modules/@aws-crypto/sha1-browser": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz",
- "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/supports-web-crypto": "^5.2.0",
- "@aws-crypto/util": "^5.2.0",
- "@aws-sdk/types": "^3.222.0",
- "@aws-sdk/util-locate-window": "^3.0.0",
- "@smithy/util-utf8": "^2.0.0",
- "tslib": "^2.6.2"
- }
- },
- "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
- "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
- "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/is-array-buffer": "^2.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
- "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/util-buffer-from": "^2.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/sha256-browser": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz",
- "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/sha256-js": "^5.2.0",
- "@aws-crypto/supports-web-crypto": "^5.2.0",
- "@aws-crypto/util": "^5.2.0",
- "@aws-sdk/types": "^3.222.0",
- "@aws-sdk/util-locate-window": "^3.0.0",
- "@smithy/util-utf8": "^2.0.0",
- "tslib": "^2.6.2"
- }
- },
- "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
- "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
- "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/is-array-buffer": "^2.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
- "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/util-buffer-from": "^2.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/sha256-js": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz",
- "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/util": "^5.2.0",
- "@aws-sdk/types": "^3.222.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=16.0.0"
- }
- },
- "node_modules/@aws-crypto/supports-web-crypto": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz",
- "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- }
- },
- "node_modules/@aws-crypto/util": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz",
- "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "^3.222.0",
- "@smithy/util-utf8": "^2.0.0",
- "tslib": "^2.6.2"
- }
- },
- "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
- "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
- "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/is-array-buffer": "^2.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
- "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/util-buffer-from": "^2.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=14.0.0"
- }
- },
- "node_modules/@aws-sdk/client-s3": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.953.0.tgz",
- "integrity": "sha512-Lxxdhq5nt6ONulu1UHbIS0tVIar7itXv1m4TJfkVzuSm/yQzxIwnFkLtgW/0P5KIE+FS1yUoE2lS+dJBS1PLFw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/sha1-browser": "5.2.0",
- "@aws-crypto/sha256-browser": "5.2.0",
- "@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/credential-provider-node": "3.953.0",
- "@aws-sdk/middleware-bucket-endpoint": "3.953.0",
- "@aws-sdk/middleware-expect-continue": "3.953.0",
- "@aws-sdk/middleware-flexible-checksums": "3.953.0",
- "@aws-sdk/middleware-host-header": "3.953.0",
- "@aws-sdk/middleware-location-constraint": "3.953.0",
- "@aws-sdk/middleware-logger": "3.953.0",
- "@aws-sdk/middleware-recursion-detection": "3.953.0",
- "@aws-sdk/middleware-sdk-s3": "3.953.0",
- "@aws-sdk/middleware-ssec": "3.953.0",
- "@aws-sdk/middleware-user-agent": "3.953.0",
- "@aws-sdk/region-config-resolver": "3.953.0",
- "@aws-sdk/signature-v4-multi-region": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@aws-sdk/util-endpoints": "3.953.0",
- "@aws-sdk/util-user-agent-browser": "3.953.0",
- "@aws-sdk/util-user-agent-node": "3.953.0",
- "@smithy/config-resolver": "^4.4.4",
- "@smithy/core": "^3.19.0",
- "@smithy/eventstream-serde-browser": "^4.2.6",
- "@smithy/eventstream-serde-config-resolver": "^4.3.6",
- "@smithy/eventstream-serde-node": "^4.2.6",
- "@smithy/fetch-http-handler": "^5.3.7",
- "@smithy/hash-blob-browser": "^4.2.7",
- "@smithy/hash-node": "^4.2.6",
- "@smithy/hash-stream-node": "^4.2.6",
- "@smithy/invalid-dependency": "^4.2.6",
- "@smithy/md5-js": "^4.2.6",
- "@smithy/middleware-content-length": "^4.2.6",
- "@smithy/middleware-endpoint": "^4.3.15",
- "@smithy/middleware-retry": "^4.4.15",
- "@smithy/middleware-serde": "^4.2.7",
- "@smithy/middleware-stack": "^4.2.6",
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/node-http-handler": "^4.4.6",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/smithy-client": "^4.10.0",
- "@smithy/types": "^4.10.0",
- "@smithy/url-parser": "^4.2.6",
- "@smithy/util-base64": "^4.3.0",
- "@smithy/util-body-length-browser": "^4.2.0",
- "@smithy/util-body-length-node": "^4.2.1",
- "@smithy/util-defaults-mode-browser": "^4.3.14",
- "@smithy/util-defaults-mode-node": "^4.2.17",
- "@smithy/util-endpoints": "^3.2.6",
- "@smithy/util-middleware": "^4.2.6",
- "@smithy/util-retry": "^4.2.6",
- "@smithy/util-stream": "^4.5.7",
- "@smithy/util-utf8": "^4.2.0",
- "@smithy/util-waiter": "^4.2.6",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/client-sesv2": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sesv2/-/client-sesv2-3.953.0.tgz",
- "integrity": "sha512-8GkTGBfFB6UbaGpXt2ZgYql+prCYLBQeSQYGb+vBZ8TnU6L6badhC8g9QkCYO2ul6rm02+MBrFgcNx40NSAsoA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/sha256-browser": "5.2.0",
- "@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/credential-provider-node": "3.953.0",
- "@aws-sdk/middleware-host-header": "3.953.0",
- "@aws-sdk/middleware-logger": "3.953.0",
- "@aws-sdk/middleware-recursion-detection": "3.953.0",
- "@aws-sdk/middleware-user-agent": "3.953.0",
- "@aws-sdk/region-config-resolver": "3.953.0",
- "@aws-sdk/signature-v4-multi-region": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@aws-sdk/util-endpoints": "3.953.0",
- "@aws-sdk/util-user-agent-browser": "3.953.0",
- "@aws-sdk/util-user-agent-node": "3.953.0",
- "@smithy/config-resolver": "^4.4.4",
- "@smithy/core": "^3.19.0",
- "@smithy/fetch-http-handler": "^5.3.7",
- "@smithy/hash-node": "^4.2.6",
- "@smithy/invalid-dependency": "^4.2.6",
- "@smithy/middleware-content-length": "^4.2.6",
- "@smithy/middleware-endpoint": "^4.3.15",
- "@smithy/middleware-retry": "^4.4.15",
- "@smithy/middleware-serde": "^4.2.7",
- "@smithy/middleware-stack": "^4.2.6",
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/node-http-handler": "^4.4.6",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/smithy-client": "^4.10.0",
- "@smithy/types": "^4.10.0",
- "@smithy/url-parser": "^4.2.6",
- "@smithy/util-base64": "^4.3.0",
- "@smithy/util-body-length-browser": "^4.2.0",
- "@smithy/util-body-length-node": "^4.2.1",
- "@smithy/util-defaults-mode-browser": "^4.3.14",
- "@smithy/util-defaults-mode-node": "^4.2.17",
- "@smithy/util-endpoints": "^3.2.6",
- "@smithy/util-middleware": "^4.2.6",
- "@smithy/util-retry": "^4.2.6",
- "@smithy/util-utf8": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/client-sso": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.953.0.tgz",
- "integrity": "sha512-WU8XtORGnhy1JjTLflcGcNGU329pmwl/2claTVGp7vrgUKyreQV9Ke3BkMuUPYLOGO/Znstzc1VbUT9ORH3+WQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/sha256-browser": "5.2.0",
- "@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/middleware-host-header": "3.953.0",
- "@aws-sdk/middleware-logger": "3.953.0",
- "@aws-sdk/middleware-recursion-detection": "3.953.0",
- "@aws-sdk/middleware-user-agent": "3.953.0",
- "@aws-sdk/region-config-resolver": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@aws-sdk/util-endpoints": "3.953.0",
- "@aws-sdk/util-user-agent-browser": "3.953.0",
- "@aws-sdk/util-user-agent-node": "3.953.0",
- "@smithy/config-resolver": "^4.4.4",
- "@smithy/core": "^3.19.0",
- "@smithy/fetch-http-handler": "^5.3.7",
- "@smithy/hash-node": "^4.2.6",
- "@smithy/invalid-dependency": "^4.2.6",
- "@smithy/middleware-content-length": "^4.2.6",
- "@smithy/middleware-endpoint": "^4.3.15",
- "@smithy/middleware-retry": "^4.4.15",
- "@smithy/middleware-serde": "^4.2.7",
- "@smithy/middleware-stack": "^4.2.6",
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/node-http-handler": "^4.4.6",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/smithy-client": "^4.10.0",
- "@smithy/types": "^4.10.0",
- "@smithy/url-parser": "^4.2.6",
- "@smithy/util-base64": "^4.3.0",
- "@smithy/util-body-length-browser": "^4.2.0",
- "@smithy/util-body-length-node": "^4.2.1",
- "@smithy/util-defaults-mode-browser": "^4.3.14",
- "@smithy/util-defaults-mode-node": "^4.2.17",
- "@smithy/util-endpoints": "^3.2.6",
- "@smithy/util-middleware": "^4.2.6",
- "@smithy/util-retry": "^4.2.6",
- "@smithy/util-utf8": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/core": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.953.0.tgz",
- "integrity": "sha512-hnz4ukn+XupuotZcFAyCIX41QqEWSHc8zf4gN4l5qVP2M8YCyZkLLZ5t5LaWLJkUFbOUU2w4SuGpUp+5ddtSkw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.953.0",
- "@aws-sdk/xml-builder": "3.953.0",
- "@smithy/core": "^3.19.0",
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/property-provider": "^4.2.6",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/signature-v4": "^5.3.6",
- "@smithy/smithy-client": "^4.10.0",
- "@smithy/types": "^4.10.0",
- "@smithy/util-base64": "^4.3.0",
- "@smithy/util-middleware": "^4.2.6",
- "@smithy/util-utf8": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-env": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.953.0.tgz",
- "integrity": "sha512-ahOxDxvaKUf99LU9iRmRtPW2HLmsR+ix2WyzRGl1PpLltiRLMbKJHj5Tu2xyOsgLxs8tefK9D1j0SUgPk8GJ6g==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@smithy/property-provider": "^4.2.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-http": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.953.0.tgz",
- "integrity": "sha512-kYQEcJpJLiT+1ZdsQDMrIs2o3YydxdAIDdLUxbIwks1+WQz2sCr9b94ld19aMZ0rejosASO0J3dfY0lt3Tfl+Q==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@smithy/fetch-http-handler": "^5.3.7",
- "@smithy/node-http-handler": "^4.4.6",
- "@smithy/property-provider": "^4.2.6",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/smithy-client": "^4.10.0",
- "@smithy/types": "^4.10.0",
- "@smithy/util-stream": "^4.5.7",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-ini": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.953.0.tgz",
- "integrity": "sha512-5cy6b3VntBvhRCanwohRtR0wbKKUd6JfIsnuXImB4JcZa2iMW5tDW0LhNangYZ9wrrM7sJol6cKHtUW9LNemFQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/credential-provider-env": "3.953.0",
- "@aws-sdk/credential-provider-http": "3.953.0",
- "@aws-sdk/credential-provider-login": "3.953.0",
- "@aws-sdk/credential-provider-process": "3.953.0",
- "@aws-sdk/credential-provider-sso": "3.953.0",
- "@aws-sdk/credential-provider-web-identity": "3.953.0",
- "@aws-sdk/nested-clients": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@smithy/credential-provider-imds": "^4.2.6",
- "@smithy/property-provider": "^4.2.6",
- "@smithy/shared-ini-file-loader": "^4.4.1",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-login": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.953.0.tgz",
- "integrity": "sha512-Drf4v7uBKnU/nY/qgQD9ZA2zD5gjQEatxQajQHUN54erDSQ2rB5ApNuTnc2cyNwaxURnQvO1J72mwO6P5lIpsg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/nested-clients": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@smithy/property-provider": "^4.2.6",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/shared-ini-file-loader": "^4.4.1",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-node": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.953.0.tgz",
- "integrity": "sha512-/3gUap/QwAV/U3RPStcSjdiksDboTdcz82qajfhURhtAe9iEdoKJy7vTYqg75eX7IjpgBwLGajt0URasUofrPg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/credential-provider-env": "3.953.0",
- "@aws-sdk/credential-provider-http": "3.953.0",
- "@aws-sdk/credential-provider-ini": "3.953.0",
- "@aws-sdk/credential-provider-process": "3.953.0",
- "@aws-sdk/credential-provider-sso": "3.953.0",
- "@aws-sdk/credential-provider-web-identity": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@smithy/credential-provider-imds": "^4.2.6",
- "@smithy/property-provider": "^4.2.6",
- "@smithy/shared-ini-file-loader": "^4.4.1",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-process": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.953.0.tgz",
- "integrity": "sha512-YeqzqxzBzXnqdzn4pBuoXeCmWrXOLIu5owAowUc4dOvHmtlpXxB3beJdQ9g/Ky6fG6iaAPKO1vrCEoHNjM85Dw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@smithy/property-provider": "^4.2.6",
- "@smithy/shared-ini-file-loader": "^4.4.1",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-sso": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.953.0.tgz",
- "integrity": "sha512-Kp/49vAJweixMo3q85eVpq1JO9KgKc6A+f8/8WDkN5CkMsfKQcGJZbO5JtuJfzar4pPmRKbgOeOP1qQsOmfyfw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/client-sso": "3.953.0",
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/token-providers": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@smithy/property-provider": "^4.2.6",
- "@smithy/shared-ini-file-loader": "^4.4.1",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/credential-provider-web-identity": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.953.0.tgz",
- "integrity": "sha512-V8SpGVtNjQZboHjb/GLM4L3/6O/AZJFtwJ8fiBaemKMTntl8haioZlQHDklWixR9s9zthOdFsCDs1+92ndUBRw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/nested-clients": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@smithy/property-provider": "^4.2.6",
- "@smithy/shared-ini-file-loader": "^4.4.1",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-bucket-endpoint": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.953.0.tgz",
- "integrity": "sha512-YHVRIOowtGIl/L2WuS83FgRlm31tU0aL1yryWaFtF+AFjA5BIeiFkxIZqaRGxJpJvFEBdohsyq6Ipv5mgWfezg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.953.0",
- "@aws-sdk/util-arn-parser": "3.953.0",
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/types": "^4.10.0",
- "@smithy/util-config-provider": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-expect-continue": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.953.0.tgz",
- "integrity": "sha512-BQTVXrypQ0rbb7au/Hk4IS5GaJZlwk6O44Rjk6Kxb0IvGQhSurNTuesFiJx1sLbf+w+T31saPtODcfQQERqhCQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.953.0",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-flexible-checksums": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.953.0.tgz",
- "integrity": "sha512-wpCoYg2ok0oSOupFiSPPiXvAhnXce2FkqMt/Bao+kyG3yx26NVG/4/PBftTDVCsJwuDvX/Fw8EuwbAXVmmYLCg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/crc32": "5.2.0",
- "@aws-crypto/crc32c": "5.2.0",
- "@aws-crypto/util": "5.2.0",
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@smithy/is-array-buffer": "^4.2.0",
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/types": "^4.10.0",
- "@smithy/util-middleware": "^4.2.6",
- "@smithy/util-stream": "^4.5.7",
- "@smithy/util-utf8": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-host-header": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.953.0.tgz",
- "integrity": "sha512-jTGhfkONav+r4E6HLOrl5SzBqDmPByUYCkyB/c/3TVb8jX3wAZx8/q9bphKpCh+G5ARi3IdbSisgkZrJYqQ19Q==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.953.0",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-location-constraint": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.953.0.tgz",
- "integrity": "sha512-h0urrbteIQEybyIISaJfQLZ/+/lJPRzPWAQT4epvzfgv/4MKZI7K83dK7SfTwAooVKFBHiCMok2Cf0iHDt07Kw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.953.0",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-logger": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.953.0.tgz",
- "integrity": "sha512-PlWdVYgcuptkIC0ZKqVUhWNtSHXJSx7U9V8J7dJjRmsXC40X7zpEycvrkzDMJjeTDGcCceYbyYAg/4X1lkcIMw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.953.0",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-recursion-detection": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.953.0.tgz",
- "integrity": "sha512-cmIJx0gWeesUKK4YwgE+VQL3mpACr3/J24fbwnc1Z5tntC86b+HQFzU5vsBDw6lLwyD46dBgWdsXFh1jL+ZaFw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.953.0",
- "@aws/lambda-invoke-store": "^0.2.2",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-sdk-s3": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.953.0.tgz",
- "integrity": "sha512-qubXS4GeDdoF7nqq2KEqW6jG7OjifwNfb/m6o5b6o7ZF2OSBr1MqyLykDWqnLjLI4NmM4qRPl5oTDGV0kBqoDA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@aws-sdk/util-arn-parser": "3.953.0",
- "@smithy/core": "^3.19.0",
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/signature-v4": "^5.3.6",
- "@smithy/smithy-client": "^4.10.0",
- "@smithy/types": "^4.10.0",
- "@smithy/util-config-provider": "^4.2.0",
- "@smithy/util-middleware": "^4.2.6",
- "@smithy/util-stream": "^4.5.7",
- "@smithy/util-utf8": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-ssec": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.953.0.tgz",
- "integrity": "sha512-OrhG1kcQ9zZh3NS3RovR028N0+UndQ957zF1k5HPLeFLwFwQN1uPOufzzPzAyXIIKtR69ARFsQI4mstZS4DMvw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.953.0",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/middleware-user-agent": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.953.0.tgz",
- "integrity": "sha512-xZSU54cEHlIvRTUewyTAajb4WJPdbBd1mIaDYOzac07+vsfMuCREQ5CheQ3inoBfqske7QOX+mIjLpVV4azAnw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@aws-sdk/util-endpoints": "3.953.0",
- "@smithy/core": "^3.19.0",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/nested-clients": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.953.0.tgz",
- "integrity": "sha512-YEBI0b/4ezNkw5W4+RBRUoueFzqEPPrnkh/3LBqeJ7RWZTymBhxlpoLo6Gfxw9LxtDgv2vZ5K5rgC4/6Ly8ADg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/sha256-browser": "5.2.0",
- "@aws-crypto/sha256-js": "5.2.0",
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/middleware-host-header": "3.953.0",
- "@aws-sdk/middleware-logger": "3.953.0",
- "@aws-sdk/middleware-recursion-detection": "3.953.0",
- "@aws-sdk/middleware-user-agent": "3.953.0",
- "@aws-sdk/region-config-resolver": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@aws-sdk/util-endpoints": "3.953.0",
- "@aws-sdk/util-user-agent-browser": "3.953.0",
- "@aws-sdk/util-user-agent-node": "3.953.0",
- "@smithy/config-resolver": "^4.4.4",
- "@smithy/core": "^3.19.0",
- "@smithy/fetch-http-handler": "^5.3.7",
- "@smithy/hash-node": "^4.2.6",
- "@smithy/invalid-dependency": "^4.2.6",
- "@smithy/middleware-content-length": "^4.2.6",
- "@smithy/middleware-endpoint": "^4.3.15",
- "@smithy/middleware-retry": "^4.4.15",
- "@smithy/middleware-serde": "^4.2.7",
- "@smithy/middleware-stack": "^4.2.6",
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/node-http-handler": "^4.4.6",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/smithy-client": "^4.10.0",
- "@smithy/types": "^4.10.0",
- "@smithy/url-parser": "^4.2.6",
- "@smithy/util-base64": "^4.3.0",
- "@smithy/util-body-length-browser": "^4.2.0",
- "@smithy/util-body-length-node": "^4.2.1",
- "@smithy/util-defaults-mode-browser": "^4.3.14",
- "@smithy/util-defaults-mode-node": "^4.2.17",
- "@smithy/util-endpoints": "^3.2.6",
- "@smithy/util-middleware": "^4.2.6",
- "@smithy/util-retry": "^4.2.6",
- "@smithy/util-utf8": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/region-config-resolver": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.953.0.tgz",
- "integrity": "sha512-5MJgnsc+HLO+le0EK1cy92yrC7kyhGZSpaq8PcQvKs9qtXCXT5Tb6tMdkr5Y07JxYsYOV1omWBynvL6PWh08tQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.953.0",
- "@smithy/config-resolver": "^4.4.4",
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/signature-v4-multi-region": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.953.0.tgz",
- "integrity": "sha512-9xDZTrUveWHLJDiXWW7UdrjtdoqlWijQlxIWRMAlxruqdXJDSRkn6taSAs7fGRwHJfxjiDsn84Fcqwx5Lw55zg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/middleware-sdk-s3": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/signature-v4": "^5.3.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/token-providers": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.953.0.tgz",
- "integrity": "sha512-4FWWR3lDDuIftmCEWpGejfkJu2J1VG2MUktChQshADXABfVfM0fsT7OYlO7Sy106nOe9upE4uQTWXg9YT/6ssw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/core": "3.953.0",
- "@aws-sdk/nested-clients": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@smithy/property-provider": "^4.2.6",
- "@smithy/shared-ini-file-loader": "^4.4.1",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/types": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz",
- "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/util-arn-parser": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.953.0.tgz",
- "integrity": "sha512-9hqdKkn4OvYzzaLryq2xnwcrPc8ziY34i9szUdgBfSqEC6pBxbY9/lLXmrgzfwMSL2Z7/v2go4Od0p5eukKLMQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/util-endpoints": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.953.0.tgz",
- "integrity": "sha512-rjaS6jrFksopXvNg6YeN+D1lYwhcByORNlFuYesFvaQNtPOufbE5tJL4GJ3TMXyaY0uFR28N5BHHITPyWWfH/g==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.953.0",
- "@smithy/types": "^4.10.0",
- "@smithy/url-parser": "^4.2.6",
- "@smithy/util-endpoints": "^3.2.6",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/util-locate-window": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.953.0.tgz",
- "integrity": "sha512-mPxK+I1LcrgC/RSa3G5AMAn8eN2Ay0VOgw8lSRmV1jCtO+iYvNeCqOdxoJUjOW6I5BA4niIRWqVORuRP07776Q==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws-sdk/util-user-agent-browser": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.953.0.tgz",
- "integrity": "sha512-UF5NeqYesWuFao+u7LJvpV1SJCaLml5BtFZKUdTnNNMeN6jvV+dW/eQoFGpXF94RCqguX0XESmRuRRPQp+/rzQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/types": "3.953.0",
- "@smithy/types": "^4.10.0",
- "bowser": "^2.11.0",
- "tslib": "^2.6.2"
- }
- },
- "node_modules/@aws-sdk/util-user-agent-node": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.953.0.tgz",
- "integrity": "sha512-HjJ0Nq/57kg0QCjt8mwBAK6C34njKezy9ItUNcrWITzrBZv7ikQtyqM1pindAIzgLaBb7ly/0kbJqMY+NPbcJA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-sdk/middleware-user-agent": "3.953.0",
- "@aws-sdk/types": "3.953.0",
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- },
- "peerDependencies": {
- "aws-crt": ">=1.0.0"
- },
- "peerDependenciesMeta": {
- "aws-crt": {
- "optional": true
- }
- }
- },
- "node_modules/@aws-sdk/xml-builder": {
- "version": "3.953.0",
- "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.953.0.tgz",
- "integrity": "sha512-Zmrj21jQ2OeOJGr9spPiN00aQvXa/WUqRXcTVENhrMt+OFoSOfDFpYhUj9NQ09QmQ8KMWFoWuWW6iKurNqLvAA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "fast-xml-parser": "5.2.5",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@aws/lambda-invoke-store": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.2.tgz",
- "integrity": "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=18.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/@borewit/text-codec": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.1.1.tgz",
- "integrity": "sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA==",
- "license": "MIT",
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "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/@cspotcode/source-map-support": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
- "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/trace-mapping": "0.3.9"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "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.2",
- "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
- "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
- }
- },
- "node_modules/@eslint/config-array": {
- "version": "0.21.1",
- "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
- "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@eslint/object-schema": "^2.1.7",
- "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.4.2",
- "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
- "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@eslint/core": "^0.17.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- }
- },
- "node_modules/@eslint/core": {
- "version": "0.17.0",
- "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
- "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
- "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.3",
- "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
- "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
- "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.1",
- "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/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "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/eslintrc/node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@eslint/js": {
- "version": "9.39.2",
- "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz",
- "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
- "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.7",
- "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
- "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- }
- },
- "node_modules/@eslint/plugin-kit": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
- "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "@eslint/core": "^0.17.0",
- "levn": "^0.4.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- }
- },
- "node_modules/@gar/promisify": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
- "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/@hexagon/base64": {
- "version": "1.1.28",
- "resolved": "https://registry.npmjs.org/@hexagon/base64/-/base64-1.1.28.tgz",
- "integrity": "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==",
- "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/@isaacs/cliui": {
- "version": "8.0.2",
- "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
- "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
- "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"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
- "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-regex?sponsor=1"
- }
- },
- "node_modules/@isaacs/cliui/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==",
- "license": "MIT",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/@isaacs/cliui/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==",
- "license": "MIT"
- },
- "node_modules/@isaacs/cliui/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==",
- "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/@isaacs/cliui/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==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
- "node_modules/@isaacs/cliui/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==",
- "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/@jimp/core": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/core/-/core-1.6.0.tgz",
- "integrity": "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/file-ops": "1.6.0",
- "@jimp/types": "1.6.0",
- "@jimp/utils": "1.6.0",
- "await-to-js": "^3.0.0",
- "exif-parser": "^0.1.12",
- "file-type": "^16.0.0",
- "mime": "3"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/core/node_modules/file-type": {
- "version": "16.5.4",
- "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz",
- "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "readable-web-to-node-stream": "^3.0.0",
- "strtok3": "^6.2.4",
- "token-types": "^4.1.1"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/file-type?sponsor=1"
- }
- },
- "node_modules/@jimp/core/node_modules/strtok3": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz",
- "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@tokenizer/token": "^0.3.0",
- "peek-readable": "^4.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/@jimp/core/node_modules/token-types": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz",
- "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@tokenizer/token": "^0.3.0",
- "ieee754": "^1.2.1"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/@jimp/diff": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/diff/-/diff-1.6.0.tgz",
- "integrity": "sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/plugin-resize": "1.6.0",
- "@jimp/types": "1.6.0",
- "@jimp/utils": "1.6.0",
- "pixelmatch": "^5.3.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/file-ops": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/file-ops/-/file-ops-1.6.0.tgz",
- "integrity": "sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/js-bmp": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/js-bmp/-/js-bmp-1.6.0.tgz",
- "integrity": "sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/types": "1.6.0",
- "@jimp/utils": "1.6.0",
- "bmp-ts": "^1.0.9"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/js-gif": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/js-gif/-/js-gif-1.6.0.tgz",
- "integrity": "sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/types": "1.6.0",
- "gifwrap": "^0.10.1",
- "omggif": "^1.0.10"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/js-jpeg": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/js-jpeg/-/js-jpeg-1.6.0.tgz",
- "integrity": "sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/types": "1.6.0",
- "jpeg-js": "^0.4.4"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/js-png": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/js-png/-/js-png-1.6.0.tgz",
- "integrity": "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/types": "1.6.0",
- "pngjs": "^7.0.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/js-tiff": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/js-tiff/-/js-tiff-1.6.0.tgz",
- "integrity": "sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/types": "1.6.0",
- "utif2": "^4.1.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-blit": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-1.6.0.tgz",
- "integrity": "sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/types": "1.6.0",
- "@jimp/utils": "1.6.0",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-blur": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-1.6.0.tgz",
- "integrity": "sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/utils": "1.6.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-circle": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-1.6.0.tgz",
- "integrity": "sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/types": "1.6.0",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-color": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-1.6.0.tgz",
- "integrity": "sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/types": "1.6.0",
- "@jimp/utils": "1.6.0",
- "tinycolor2": "^1.6.0",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-contain": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-1.6.0.tgz",
- "integrity": "sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/plugin-blit": "1.6.0",
- "@jimp/plugin-resize": "1.6.0",
- "@jimp/types": "1.6.0",
- "@jimp/utils": "1.6.0",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-cover": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-1.6.0.tgz",
- "integrity": "sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/plugin-crop": "1.6.0",
- "@jimp/plugin-resize": "1.6.0",
- "@jimp/types": "1.6.0",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-crop": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-1.6.0.tgz",
- "integrity": "sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/types": "1.6.0",
- "@jimp/utils": "1.6.0",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-displace": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-1.6.0.tgz",
- "integrity": "sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/types": "1.6.0",
- "@jimp/utils": "1.6.0",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-dither": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-1.6.0.tgz",
- "integrity": "sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/types": "1.6.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-fisheye": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-1.6.0.tgz",
- "integrity": "sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/types": "1.6.0",
- "@jimp/utils": "1.6.0",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-flip": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-1.6.0.tgz",
- "integrity": "sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/types": "1.6.0",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-hash": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-hash/-/plugin-hash-1.6.0.tgz",
- "integrity": "sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/js-bmp": "1.6.0",
- "@jimp/js-jpeg": "1.6.0",
- "@jimp/js-png": "1.6.0",
- "@jimp/js-tiff": "1.6.0",
- "@jimp/plugin-color": "1.6.0",
- "@jimp/plugin-resize": "1.6.0",
- "@jimp/types": "1.6.0",
- "@jimp/utils": "1.6.0",
- "any-base": "^1.1.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-mask": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-1.6.0.tgz",
- "integrity": "sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/types": "1.6.0",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-print": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-1.6.0.tgz",
- "integrity": "sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/js-jpeg": "1.6.0",
- "@jimp/js-png": "1.6.0",
- "@jimp/plugin-blit": "1.6.0",
- "@jimp/types": "1.6.0",
- "parse-bmfont-ascii": "^1.0.6",
- "parse-bmfont-binary": "^1.0.6",
- "parse-bmfont-xml": "^1.1.6",
- "simple-xml-to-json": "^1.2.2",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-quantize": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-quantize/-/plugin-quantize-1.6.0.tgz",
- "integrity": "sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "image-q": "^4.0.0",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-resize": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-1.6.0.tgz",
- "integrity": "sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/types": "1.6.0",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-rotate": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-1.6.0.tgz",
- "integrity": "sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/plugin-crop": "1.6.0",
- "@jimp/plugin-resize": "1.6.0",
- "@jimp/types": "1.6.0",
- "@jimp/utils": "1.6.0",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/plugin-threshold": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-1.6.0.tgz",
- "integrity": "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/plugin-color": "1.6.0",
- "@jimp/plugin-hash": "1.6.0",
- "@jimp/types": "1.6.0",
- "@jimp/utils": "1.6.0",
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/types": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/types/-/types-1.6.0.tgz",
- "integrity": "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "zod": "^3.23.8"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jimp/utils": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-1.6.0.tgz",
- "integrity": "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/types": "1.6.0",
- "tinycolor2": "^1.6.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/@jridgewell/resolve-uri": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
- "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
- "devOptional": true,
- "license": "MIT",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
- "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/@jridgewell/trace-mapping": {
- "version": "0.3.9",
- "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
- "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "@jridgewell/resolve-uri": "^3.0.3",
- "@jridgewell/sourcemap-codec": "^1.4.10"
- }
- },
- "node_modules/@mapbox/node-pre-gyp": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
- "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
- "license": "BSD-3-Clause",
- "optional": true,
- "dependencies": {
- "detect-libc": "^2.0.0",
- "https-proxy-agent": "^5.0.0",
- "make-dir": "^3.1.0",
- "node-fetch": "^2.6.7",
- "nopt": "^5.0.0",
- "npmlog": "^5.0.1",
- "rimraf": "^3.0.2",
- "semver": "^7.3.5",
- "tar": "^6.1.11"
- },
- "bin": {
- "node-pre-gyp": "bin/node-pre-gyp"
- }
- },
- "node_modules/@noble/hashes": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz",
- "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==",
- "license": "MIT",
- "engines": {
- "node": ">= 16"
- },
- "funding": {
- "url": "https://paulmillr.com/funding/"
- }
- },
- "node_modules/@npmcli/fs": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz",
- "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "@gar/promisify": "^1.0.1",
- "semver": "^7.3.5"
- }
- },
- "node_modules/@npmcli/move-file": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz",
- "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==",
- "deprecated": "This functionality has been moved to @npmcli/fs",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "mkdirp": "^1.0.4",
- "rimraf": "^3.0.2"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@npmcli/move-file/node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "license": "MIT",
- "optional": true,
- "bin": {
- "mkdirp": "bin/cmd.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/@peculiar/asn1-schema": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.6.0.tgz",
- "integrity": "sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg==",
- "license": "MIT",
- "dependencies": {
- "asn1js": "^3.0.6",
- "pvtsutils": "^1.3.6",
- "tslib": "^2.8.1"
- }
- },
- "node_modules/@peculiar/json-schema": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz",
- "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==",
- "license": "MIT",
- "dependencies": {
- "tslib": "^2.0.0"
- },
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/@peculiar/webcrypto": {
- "version": "1.4.6",
- "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.6.tgz",
- "integrity": "sha512-YBcMfqNSwn3SujUJvAaySy5tlYbYm6tVt9SKoXu8BaTdKGROiJDgPR3TXpZdAKUfklzm3lRapJEAltiMQtBgZg==",
- "license": "MIT",
- "dependencies": {
- "@peculiar/asn1-schema": "^2.3.8",
- "@peculiar/json-schema": "^1.1.12",
- "pvtsutils": "^1.3.5",
- "tslib": "^2.6.2",
- "webcrypto-core": "^1.7.9"
- },
- "engines": {
- "node": ">=10.12.0"
- }
- },
- "node_modules/@pkgjs/parseargs": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
- "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/@pkgr/core": {
- "version": "0.2.9",
- "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
- "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/pkgr"
- }
- },
- "node_modules/@protobuf-ts/runtime": {
- "version": "2.11.1",
- "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime/-/runtime-2.11.1.tgz",
- "integrity": "sha512-KuDaT1IfHkugM2pyz+FwiY80ejWrkH1pAtOBOZFuR6SXEFTsnb/jiQWQ1rCIrcKx2BtyxnxW6BWwsVSA/Ie+WQ==",
- "license": "(Apache-2.0 AND BSD-3-Clause)"
- },
- "node_modules/@sendgrid/client": {
- "version": "8.1.6",
- "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-8.1.6.tgz",
- "integrity": "sha512-/BHu0hqwXNHr2aLhcXU7RmmlVqrdfrbY9KpaNj00KZHlVOVoRxRVrpOCabIB+91ISXJ6+mLM9vpaVUhK6TwBWA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@sendgrid/helpers": "^8.0.0",
- "axios": "^1.12.0"
- },
- "engines": {
- "node": ">=12.*"
- }
- },
- "node_modules/@sendgrid/helpers": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-8.0.0.tgz",
- "integrity": "sha512-Ze7WuW2Xzy5GT5WRx+yEv89fsg/pgy3T1E3FS0QEx0/VvRmigMZ5qyVGhJz4SxomegDkzXv/i0aFPpHKN8qdAA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "deepmerge": "^4.2.2"
- },
- "engines": {
- "node": ">= 12.0.0"
- }
- },
- "node_modules/@sendgrid/mail": {
- "version": "8.1.6",
- "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-8.1.6.tgz",
- "integrity": "sha512-/ZqxUvKeEztU9drOoPC/8opEPOk+jLlB2q4+xpx6HVLq6aFu3pMpalkTpAQz8XfRfpLp8O25bh6pGPcHDCYpqg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@sendgrid/client": "^8.1.5",
- "@sendgrid/helpers": "^8.0.0"
- },
- "engines": {
- "node": ">=12.*"
- }
- },
- "node_modules/@smithy/abort-controller": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.6.tgz",
- "integrity": "sha512-P7JD4J+wxHMpGxqIg6SHno2tPkZbBUBLbPpR5/T1DEUvw/mEaINBMaPFZNM7lA+ToSCZ36j6nMHa+5kej+fhGg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/chunked-blob-reader": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.2.0.tgz",
- "integrity": "sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/chunked-blob-reader-native": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.2.1.tgz",
- "integrity": "sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/util-base64": "^4.3.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/config-resolver": {
- "version": "4.4.4",
- "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.4.tgz",
- "integrity": "sha512-s3U5ChS21DwU54kMmZ0UJumoS5cg0+rGVZvN6f5Lp6EbAVi0ZyP+qDSHdewfmXKUgNK1j3z45JyzulkDukrjAA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/types": "^4.10.0",
- "@smithy/util-config-provider": "^4.2.0",
- "@smithy/util-endpoints": "^3.2.6",
- "@smithy/util-middleware": "^4.2.6",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/core": {
- "version": "3.19.0",
- "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.19.0.tgz",
- "integrity": "sha512-Y9oHXpBcXQgYHOcAEmxjkDilUbSTkgKjoHYed3WaYUH8jngq8lPWDBSpjHblJ9uOgBdy5mh3pzebrScDdYr29w==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/middleware-serde": "^4.2.7",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/types": "^4.10.0",
- "@smithy/util-base64": "^4.3.0",
- "@smithy/util-body-length-browser": "^4.2.0",
- "@smithy/util-middleware": "^4.2.6",
- "@smithy/util-stream": "^4.5.7",
- "@smithy/util-utf8": "^4.2.0",
- "@smithy/uuid": "^1.1.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/credential-provider-imds": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.6.tgz",
- "integrity": "sha512-xBmawExyTzOjbhzkZwg+vVm/khg28kG+rj2sbGlULjFd1jI70sv/cbpaR0Ev4Yfd6CpDUDRMe64cTqR//wAOyA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/property-provider": "^4.2.6",
- "@smithy/types": "^4.10.0",
- "@smithy/url-parser": "^4.2.6",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/eventstream-codec": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.6.tgz",
- "integrity": "sha512-OZfsI+YRG26XZik/jKMMg37acnBSbUiK/8nETW3uM3mLj+0tMmFXdHQw1e5WEd/IHN8BGOh3te91SNDe2o4RHg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@aws-crypto/crc32": "5.2.0",
- "@smithy/types": "^4.10.0",
- "@smithy/util-hex-encoding": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/eventstream-serde-browser": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.6.tgz",
- "integrity": "sha512-6OiaAaEbLB6dEkRbQyNzFSJv5HDvly3Mc6q/qcPd2uS/g3szR8wAIkh7UndAFKfMypNSTuZ6eCBmgCLR5LacTg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/eventstream-serde-universal": "^4.2.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/eventstream-serde-config-resolver": {
- "version": "4.3.6",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.6.tgz",
- "integrity": "sha512-xP5YXbOVRVN8A4pDnSUkEUsL9fYFU6VNhxo8tgr13YnMbf3Pn4xVr+hSyLVjS1Frfi1Uk03ET5Bwml4+0CeYEw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/eventstream-serde-node": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.6.tgz",
- "integrity": "sha512-jhH7nJuaOpnTFcuZpWK9dqb6Ge2yGi1okTo0W6wkJrfwAm2vwmO74tF1v07JmrSyHBcKLQATEexclJw9K1Vj7w==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/eventstream-serde-universal": "^4.2.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/eventstream-serde-universal": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.6.tgz",
- "integrity": "sha512-olIfZ230B64TvPD6b0tPvrEp2eB0FkyL3KvDlqF4RVmIc/kn3orzXnV6DTQdOOW5UU+M5zKY3/BU47X420/oPw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/eventstream-codec": "^4.2.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/fetch-http-handler": {
- "version": "5.3.7",
- "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.7.tgz",
- "integrity": "sha512-fcVap4QwqmzQwQK9QU3keeEpCzTjnP9NJ171vI7GnD7nbkAIcP9biZhDUx88uRH9BabSsQDS0unUps88uZvFIQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/querystring-builder": "^4.2.6",
- "@smithy/types": "^4.10.0",
- "@smithy/util-base64": "^4.3.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/hash-blob-browser": {
- "version": "4.2.7",
- "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.2.7.tgz",
- "integrity": "sha512-CIbCTGGX5CI7tfewBPSYD9ycp2Vb2GW5xnXD1n7GcO9mu37EN7A6DvCHM9MX7pOeS1adMn5D+1yRwI3eABVbcA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/chunked-blob-reader": "^5.2.0",
- "@smithy/chunked-blob-reader-native": "^4.2.1",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/hash-node": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.6.tgz",
- "integrity": "sha512-k3Dy9VNR37wfMh2/1RHkFf/e0rMyN0pjY0FdyY6ItJRjENYyVPRMwad6ZR1S9HFm6tTuIOd9pqKBmtJ4VHxvxg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "@smithy/util-buffer-from": "^4.2.0",
- "@smithy/util-utf8": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/hash-stream-node": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.2.6.tgz",
- "integrity": "sha512-+3T8LkH39YIhYHsv/Ec8lF+92nykZpU+XMBvAyXF/uLcTp86pxa5oSJk1vzaRY9N++qgDLYjzJ6OVbtAgDGwfw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "@smithy/util-utf8": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/invalid-dependency": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.6.tgz",
- "integrity": "sha512-E4t/V/q2T46RY21fpfznd1iSLTvCXKNKo4zJ1QuEFN4SE9gKfu2vb6bgq35LpufkQ+SETWIC7ZAf2GGvTlBaMQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/is-array-buffer": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz",
- "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/md5-js": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.6.tgz",
- "integrity": "sha512-ZXeh8UmH31JdcNsrQ1o9v1IVuva9JFwxIc6zTMxWX7wcmWvVR7Ai9aUEw5LraNKqdkAsb06clpM2sRH4Iy55Sg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "@smithy/util-utf8": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-content-length": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.6.tgz",
- "integrity": "sha512-0cjqjyfj+Gls30ntq45SsBtqF3dfJQCeqQPyGz58Pk8OgrAr5YiB7ZvDzjCA94p4r6DCI4qLm7FKobqBjf515w==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-endpoint": {
- "version": "4.4.0",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.0.tgz",
- "integrity": "sha512-M6qWfUNny6NFNy8amrCGIb9TfOMUkHVtg9bHtEFGRgfH7A7AtPpn/fcrToGPjVDK1ECuMVvqGQOXcZxmu9K+7A==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/core": "^3.19.0",
- "@smithy/middleware-serde": "^4.2.7",
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/shared-ini-file-loader": "^4.4.1",
- "@smithy/types": "^4.10.0",
- "@smithy/url-parser": "^4.2.6",
- "@smithy/util-middleware": "^4.2.6",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-retry": {
- "version": "4.4.16",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.16.tgz",
- "integrity": "sha512-XPpNhNRzm3vhYm7YCsyw3AtmWggJbg1wNGAoqb7NBYr5XA5isMRv14jgbYyUV6IvbTBFZQdf2QpeW43LrRdStQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/service-error-classification": "^4.2.6",
- "@smithy/smithy-client": "^4.10.1",
- "@smithy/types": "^4.10.0",
- "@smithy/util-middleware": "^4.2.6",
- "@smithy/util-retry": "^4.2.6",
- "@smithy/uuid": "^1.1.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-serde": {
- "version": "4.2.7",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.7.tgz",
- "integrity": "sha512-PFMVHVPgtFECeu4iZ+4SX6VOQT0+dIpm4jSPLLL6JLSkp9RohGqKBKD0cbiXdeIFS08Forp0UHI6kc0gIHenSA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/middleware-stack": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.6.tgz",
- "integrity": "sha512-JSbALU3G+JS4kyBZPqnJ3hxIYwOVRV7r9GNQMS6j5VsQDo5+Es5nddLfr9TQlxZLNHPvKSh+XSB0OuWGfSWFcA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/node-config-provider": {
- "version": "4.3.6",
- "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.6.tgz",
- "integrity": "sha512-fYEyL59Qe82Ha1p97YQTMEQPJYmBS+ux76foqluaTVWoG9Px5J53w6NvXZNE3wP7lIicLDF7Vj1Em18XTX7fsA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/property-provider": "^4.2.6",
- "@smithy/shared-ini-file-loader": "^4.4.1",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/node-http-handler": {
- "version": "4.4.6",
- "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.6.tgz",
- "integrity": "sha512-Gsb9jf4ido5BhPfani4ggyrKDd3ZK+vTFWmUaZeFg5G3E5nhFmqiTzAIbHqmPs1sARuJawDiGMGR/nY+Gw6+aQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/abort-controller": "^4.2.6",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/querystring-builder": "^4.2.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/property-provider": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.6.tgz",
- "integrity": "sha512-a/tGSLPtaia2krbRdwR4xbZKO8lU67DjMk/jfY4QKt4PRlKML+2tL/gmAuhNdFDioO6wOq0sXkfnddNFH9mNUA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/protocol-http": {
- "version": "5.3.6",
- "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.6.tgz",
- "integrity": "sha512-qLRZzP2+PqhE3OSwvY2jpBbP0WKTZ9opTsn+6IWYI0SKVpbG+imcfNxXPq9fj5XeaUTr7odpsNpK6dmoiM1gJQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/querystring-builder": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.6.tgz",
- "integrity": "sha512-MeM9fTAiD3HvoInK/aA8mgJaKQDvm8N0dKy6EiFaCfgpovQr4CaOkJC28XqlSRABM+sHdSQXbC8NZ0DShBMHqg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "@smithy/util-uri-escape": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/querystring-parser": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.6.tgz",
- "integrity": "sha512-YmWxl32SQRw/kIRccSOxzS/Ib8/b5/f9ex0r5PR40jRJg8X1wgM3KrR2In+8zvOGVhRSXgvyQpw9yOSlmfmSnA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/service-error-classification": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.6.tgz",
- "integrity": "sha512-Q73XBrzJlGTut2nf5RglSntHKgAG0+KiTJdO5QQblLfr4TdliGwIAha1iZIjwisc3rA5ulzqwwsYC6xrclxVQg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/shared-ini-file-loader": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.1.tgz",
- "integrity": "sha512-tph+oQYPbpN6NamF030hx1gb5YN2Plog+GLaRHpoEDwp8+ZPG26rIJvStG9hkWzN2HBn3HcWg0sHeB0tmkYzqA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/signature-v4": {
- "version": "5.3.6",
- "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.6.tgz",
- "integrity": "sha512-P1TXDHuQMadTMTOBv4oElZMURU4uyEhxhHfn+qOc2iofW9Rd4sZtBGx58Lzk112rIGVEYZT8eUMK4NftpewpRA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/is-array-buffer": "^4.2.0",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/types": "^4.10.0",
- "@smithy/util-hex-encoding": "^4.2.0",
- "@smithy/util-middleware": "^4.2.6",
- "@smithy/util-uri-escape": "^4.2.0",
- "@smithy/util-utf8": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/smithy-client": {
- "version": "4.10.1",
- "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.10.1.tgz",
- "integrity": "sha512-1ovWdxzYprhq+mWqiGZlt3kF69LJthuQcfY9BIyHx9MywTFKzFapluku1QXoaBB43GCsLDxNqS+1v30ure69AA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/core": "^3.19.0",
- "@smithy/middleware-endpoint": "^4.4.0",
- "@smithy/middleware-stack": "^4.2.6",
- "@smithy/protocol-http": "^5.3.6",
- "@smithy/types": "^4.10.0",
- "@smithy/util-stream": "^4.5.7",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/types": {
- "version": "4.10.0",
- "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.10.0.tgz",
- "integrity": "sha512-K9mY7V/f3Ul+/Gz4LJANZ3vJ/yiBIwCyxe0sPT4vNJK63Srvd+Yk1IzP0t+nE7XFSpIGtzR71yljtnqpUTYFlQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/url-parser": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.6.tgz",
- "integrity": "sha512-tVoyzJ2vXp4R3/aeV4EQjBDmCuWxRa8eo3KybL7Xv4wEM16nObYh7H1sNfcuLWHAAAzb0RVyxUz1S3sGj4X+Tg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/querystring-parser": "^4.2.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-base64": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.0.tgz",
- "integrity": "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/util-buffer-from": "^4.2.0",
- "@smithy/util-utf8": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-body-length-browser": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.0.tgz",
- "integrity": "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-body-length-node": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.1.tgz",
- "integrity": "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-buffer-from": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.0.tgz",
- "integrity": "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/is-array-buffer": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-config-provider": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.0.tgz",
- "integrity": "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-defaults-mode-browser": {
- "version": "4.3.15",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.15.tgz",
- "integrity": "sha512-LiZQVAg/oO8kueX4c+oMls5njaD2cRLXRfcjlTYjhIqmwHnCwkQO5B3dMQH0c5PACILxGAQf6Mxsq7CjlDc76A==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/property-provider": "^4.2.6",
- "@smithy/smithy-client": "^4.10.1",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-defaults-mode-node": {
- "version": "4.2.18",
- "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.18.tgz",
- "integrity": "sha512-Kw2J+KzYm9C9Z9nY6+W0tEnoZOofstVCMTshli9jhQbQCy64rueGfKzPfuFBnVUqZD9JobxTh2DzHmPkp/Va/Q==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/config-resolver": "^4.4.4",
- "@smithy/credential-provider-imds": "^4.2.6",
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/property-provider": "^4.2.6",
- "@smithy/smithy-client": "^4.10.1",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-endpoints": {
- "version": "3.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.6.tgz",
- "integrity": "sha512-v60VNM2+mPvgHCBXEfMCYrQ0RepP6u6xvbAkMenfe4Mi872CqNkJzgcnQL837e8NdeDxBgrWQRTluKq5Lqdhfg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/node-config-provider": "^4.3.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-hex-encoding": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.0.tgz",
- "integrity": "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-middleware": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.6.tgz",
- "integrity": "sha512-qrvXUkxBSAFomM3/OEMuDVwjh4wtqK8D2uDZPShzIqOylPst6gor2Cdp6+XrH4dyksAWq/bE2aSDYBTTnj0Rxg==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-retry": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.6.tgz",
- "integrity": "sha512-x7CeDQLPQ9cb6xN7fRJEjlP9NyGW/YeXWc4j/RUhg4I+H60F0PEeRc2c/z3rm9zmsdiMFzpV/rT+4UHW6KM1SA==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/service-error-classification": "^4.2.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-stream": {
- "version": "4.5.7",
- "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.7.tgz",
- "integrity": "sha512-Uuy4S5Aj4oF6k1z+i2OtIBJUns4mlg29Ph4S+CqjR+f4XXpSFVgTCYLzMszHJTicYDBxKFtwq2/QSEDSS5l02A==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/fetch-http-handler": "^5.3.7",
- "@smithy/node-http-handler": "^4.4.6",
- "@smithy/types": "^4.10.0",
- "@smithy/util-base64": "^4.3.0",
- "@smithy/util-buffer-from": "^4.2.0",
- "@smithy/util-hex-encoding": "^4.2.0",
- "@smithy/util-utf8": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-uri-escape": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.0.tgz",
- "integrity": "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-utf8": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.0.tgz",
- "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/util-buffer-from": "^4.2.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/util-waiter": {
- "version": "4.2.6",
- "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.6.tgz",
- "integrity": "sha512-xU9HwUSik9UUCJmm530yvBy0AwlQFICveKmqvaaTukKkXEAhyiBdHtSrhPrH3rH+uz0ykyaE3LdgsX86C6mDCQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "@smithy/abort-controller": "^4.2.6",
- "@smithy/types": "^4.10.0",
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@smithy/uuid": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.0.tgz",
- "integrity": "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==",
- "license": "Apache-2.0",
- "dependencies": {
- "tslib": "^2.6.2"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/@spacebarchat/spacebar-webrtc-types": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@spacebarchat/spacebar-webrtc-types/-/spacebar-webrtc-types-1.0.1.tgz",
- "integrity": "sha512-WfBRUN2520w7o5vU9HNDug9alNvydQP7H/jwAy8LeHTHwlMMUw/60A54FQDIAtsahw787fR3QZ83UGjhKDzDTg==",
- "dev": true,
- "license": "AGPL-3.0-only"
- },
- "node_modules/@sqltools/formatter": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz",
- "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==",
- "license": "MIT"
- },
- "node_modules/@tokenizer/inflate": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz",
- "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.4.3",
- "token-types": "^6.1.1"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/@tokenizer/token": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
- "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
- "license": "MIT"
- },
- "node_modules/@toondepauw/node-zstd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd/-/node-zstd-1.2.0.tgz",
- "integrity": "sha512-vVDvPUstF9gKEX+Kqp654bL+4UNus6pkmY8mlcJQpIw/Sn6sO9fl1PEwxB0d0unH5PmVfBUicf1lOXu74OLrCg==",
- "license": "MIT",
- "engines": {
- "node": ">= 14"
- },
- "optionalDependencies": {
- "@toondepauw/node-zstd-darwin-arm64": "1.2.0",
- "@toondepauw/node-zstd-darwin-x64": "1.2.0",
- "@toondepauw/node-zstd-freebsd-x64": "1.2.0",
- "@toondepauw/node-zstd-linux-arm64-gnu": "1.2.0",
- "@toondepauw/node-zstd-linux-arm64-musl": "1.2.0",
- "@toondepauw/node-zstd-linux-x64-gnu": "1.2.0",
- "@toondepauw/node-zstd-linux-x64-musl": "1.2.0",
- "@toondepauw/node-zstd-win32-x64-msvc": "1.2.0"
- }
- },
- "node_modules/@toondepauw/node-zstd-darwin-arm64": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-darwin-arm64/-/node-zstd-darwin-arm64-1.2.0.tgz",
- "integrity": "sha512-fdBGlRSrf19M1+IJ98aJCLK6/HKQRnRlhE5i6EZ7kVfD2r6h5Bq9NqHAmQ5MgwtmfB9VMmiIrQAMIxKVeT54pg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@toondepauw/node-zstd-darwin-x64": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-darwin-x64/-/node-zstd-darwin-x64-1.2.0.tgz",
- "integrity": "sha512-ZVu4zkQUgCQ8z1lLd7/LZzIYDKL48tPguIN8L4SRfLuWWlTq2/4OT6AmchztDbe5soLCDuw64t5X5otDvgsGJA==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "darwin"
- ],
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@toondepauw/node-zstd-freebsd-x64": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-freebsd-x64/-/node-zstd-freebsd-x64-1.2.0.tgz",
- "integrity": "sha512-kDK+l3uP7htiWvM/klY32siEGIBk3K5Da4/DcXV2q/Vp+Ph86FWpQRzC46wJIpJB60xEU67pxFGLBH/8/RB02g==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "freebsd"
- ],
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@toondepauw/node-zstd-linux-arm64-gnu": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-linux-arm64-gnu/-/node-zstd-linux-arm64-gnu-1.2.0.tgz",
- "integrity": "sha512-KteUWam7McA0moNiRgu7KSgPu3FE+KXuh3ObqWoco5JK53Sp4Pgr/q1IYsdN6TYYbgJMkJpof62NIbyi6tnVfg==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@toondepauw/node-zstd-linux-arm64-musl": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-linux-arm64-musl/-/node-zstd-linux-arm64-musl-1.2.0.tgz",
- "integrity": "sha512-KjbGOXvPmorhWGD4kEVjdBz/gJgUOw1Eu0xziBwsq03URrI0XSDAY6YiJZpZtGnSjm7XonEpnBZcVwXH1HZz3Q==",
- "cpu": [
- "arm64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@toondepauw/node-zstd-linux-x64-gnu": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-linux-x64-gnu/-/node-zstd-linux-x64-gnu-1.2.0.tgz",
- "integrity": "sha512-qNJDZGd/jplK/1J+8V87dYdrviAxNt1iwI/SQ0JR3HTz5Jdbu+BnVB9oMklCc/bGWa8zTkiZkl/EwA3gtbpo+Q==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@toondepauw/node-zstd-linux-x64-musl": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-linux-x64-musl/-/node-zstd-linux-x64-musl-1.2.0.tgz",
- "integrity": "sha512-Cw1qnMXde8caitDMbk0vWrqnVHTSK+JB/Dp3XnZghQjBrD7JLj2qNzh0eTkxNFa+nijbo8HyyslWGswCugYZCw==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "linux"
- ],
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@toondepauw/node-zstd-win32-x64-msvc": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-win32-x64-msvc/-/node-zstd-win32-x64-msvc-1.2.0.tgz",
- "integrity": "sha512-7cD2/R7DLZHMxHTsQNtOX3vJCT4qd74a3nWjYYthJ89gqXwwEoC8BwttQxvHd0qCZ3S/cZ/BYoTikXMwMNmCEg==",
- "cpu": [
- "x64"
- ],
- "license": "MIT",
- "optional": true,
- "os": [
- "win32"
- ],
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/@tootallnate/once": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
- "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/@tsconfig/node10": {
- "version": "1.0.12",
- "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
- "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/@tsconfig/node12": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
- "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/@tsconfig/node14": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
- "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/@tsconfig/node16": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
- "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/@types/amqplib": {
- "version": "0.10.8",
- "resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.10.8.tgz",
- "integrity": "sha512-vtDp8Pk1wsE/AuQ8/Rgtm6KUZYqcnTgNvEHwzCkX8rL7AGsC6zqAfKAAJhUZXFhM/Pp++tbnUHiam/8vVpPztA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/bcrypt": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-6.0.0.tgz",
- "integrity": "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/body-parser": {
- "version": "1.19.6",
- "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
- "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/connect": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@types/connect": {
- "version": "3.4.38",
- "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
- "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/cookie-parser": {
- "version": "1.4.10",
- "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.10.tgz",
- "integrity": "sha512-B4xqkqfZ8Wek+rCOeRxsjMS9OgvzebEzzLYw7NHYuvzb7IdxOkI0ZHGgeEBX4PUM7QGVvNSK60T3OvWj3YfBRg==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "@types/express": "*"
- }
- },
- "node_modules/@types/estree": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
- "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/express": {
- "version": "5.0.6",
- "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz",
- "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@types/body-parser": "*",
- "@types/express-serve-static-core": "^5.0.0",
- "@types/serve-static": "^2"
- }
- },
- "node_modules/@types/express-serve-static-core": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.0.tgz",
- "integrity": "sha512-jnHMsrd0Mwa9Cf4IdOzbz543y4XJepXrbia2T4b6+spXC2We3t1y6K44D3mR8XMFSXMCf3/l7rCgddfx7UNVBA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*",
- "@types/qs": "*",
- "@types/range-parser": "*",
- "@types/send": "*"
- }
- },
- "node_modules/@types/http-errors": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
- "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/i18next-node-fs-backend": {
- "version": "2.1.5",
- "resolved": "https://registry.npmjs.org/@types/i18next-node-fs-backend/-/i18next-node-fs-backend-2.1.5.tgz",
- "integrity": "sha512-qLuS9SIlAnywXSzCIDi/TTm3DWzLKqLcd5O8K/OSX1Hif6soTu5H+GwZ9Jneoe0gRq6orwaPEe9d0dcmeAFLzA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "i18next": ">=17.0.11"
- }
- },
- "node_modules/@types/json-bigint": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/@types/json-bigint/-/json-bigint-1.0.4.tgz",
- "integrity": "sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/json-schema": {
- "version": "7.0.15",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
- "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/jsonwebtoken": {
- "version": "9.0.10",
- "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz",
- "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/ms": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@types/module-alias": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/@types/module-alias/-/module-alias-2.0.4.tgz",
- "integrity": "sha512-5+G/QXO/DvHZw60FjvbDzO4JmlD/nG5m2/vVGt25VN1eeP3w2bCoks1Wa7VuptMPM1TxJdx6RjO70N9Fw0nZPA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/morgan": {
- "version": "1.9.10",
- "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.10.tgz",
- "integrity": "sha512-sS4A1zheMvsADRVfT0lYbJ4S9lmsey8Zo2F7cnbYjWHP67Q0AwMYuuzLlkIM2N8gAbb9cubhIVFwcIN2XyYCkA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/ms": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
- "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/multer": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz",
- "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/express": "*"
- }
- },
- "node_modules/@types/murmurhash-js": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/@types/murmurhash-js/-/murmurhash-js-1.0.6.tgz",
- "integrity": "sha512-P2RRwRpevEKO0FrK5xNjxBywg0Br24tEv8K2+iWg56PtcCUNGAkaaOWKBQiUpofA8H/gmgdHXrcvSgp2uXCVAQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/needle": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/@types/needle/-/needle-3.3.0.tgz",
- "integrity": "sha512-UFIuc1gdyzAqeVUYpSL+cliw2MmU/ZUhVZKE7Zo4wPbgc8hbljeKSnn6ls6iG8r5jpegPXLUIhJ+Wb2kLVs8cg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/node": {
- "version": "24.10.4",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.4.tgz",
- "integrity": "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "undici-types": "~7.16.0"
- }
- },
- "node_modules/@types/nodemailer": {
- "version": "7.0.4",
- "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-7.0.4.tgz",
- "integrity": "sha512-ee8fxWqOchH+Hv6MDDNNy028kwvVnLplrStm4Zf/3uHWw5zzo8FoYYeffpJtGs2wWysEumMH0ZIdMGMY1eMAow==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@aws-sdk/client-sesv2": "^3.839.0",
- "@types/node": "*"
- }
- },
- "node_modules/@types/notp": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/@types/notp/-/notp-2.0.5.tgz",
- "integrity": "sha512-ZsZS0PYUa6ZE4K3yOGerBvaxCp4ePf6ZmkFbPeilcqz2Ui/lmXox7KlRt7XZkXzqUgXhFLkc09ixyVmFLCU3gQ==",
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/probe-image-size": {
- "version": "7.2.5",
- "resolved": "https://registry.npmjs.org/@types/probe-image-size/-/probe-image-size-7.2.5.tgz",
- "integrity": "sha512-9Bg6d/GNnjmhMMxadDstwrSlquuuLf0jQuPszbU6n3QUfybif3V/ryD3J2i9iaiC5JB/FU/8E41n88SM/UB+Tg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/needle": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@types/qs": {
- "version": "6.14.0",
- "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
- "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/range-parser": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
- "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/@types/send": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
- "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/serve-static": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz",
- "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/http-errors": "*",
- "@types/node": "*"
- }
- },
- "node_modules/@types/sharp": {
- "version": "0.31.1",
- "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.31.1.tgz",
- "integrity": "sha512-5nWwamN9ZFHXaYEincMSuza8nNfOof8nmO+mcI+Agx1uMUk4/pQnNIcix+9rLPXzKrm1pS34+6WRDbDV0Jn7ag==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@types/ws": {
- "version": "8.18.1",
- "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
- "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@types/node": "*"
- }
- },
- "node_modules/@typescript-eslint/eslint-plugin": {
- "version": "8.50.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.50.0.tgz",
- "integrity": "sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@eslint-community/regexpp": "^4.10.0",
- "@typescript-eslint/scope-manager": "8.50.0",
- "@typescript-eslint/type-utils": "8.50.0",
- "@typescript-eslint/utils": "8.50.0",
- "@typescript-eslint/visitor-keys": "8.50.0",
- "ignore": "^7.0.0",
- "natural-compare": "^1.4.0",
- "ts-api-utils": "^2.1.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "@typescript-eslint/parser": "^8.50.0",
- "eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <6.0.0"
- }
- },
- "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
- "version": "7.0.5",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
- "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/@typescript-eslint/parser": {
- "version": "8.50.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.50.0.tgz",
- "integrity": "sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@typescript-eslint/scope-manager": "8.50.0",
- "@typescript-eslint/types": "8.50.0",
- "@typescript-eslint/typescript-estree": "8.50.0",
- "@typescript-eslint/visitor-keys": "8.50.0",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <6.0.0"
- }
- },
- "node_modules/@typescript-eslint/project-service": {
- "version": "8.50.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.50.0.tgz",
- "integrity": "sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/tsconfig-utils": "^8.50.0",
- "@typescript-eslint/types": "^8.50.0",
- "debug": "^4.3.4"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
- }
- },
- "node_modules/@typescript-eslint/scope-manager": {
- "version": "8.50.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.50.0.tgz",
- "integrity": "sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "8.50.0",
- "@typescript-eslint/visitor-keys": "8.50.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/tsconfig-utils": {
- "version": "8.50.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.50.0.tgz",
- "integrity": "sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
- }
- },
- "node_modules/@typescript-eslint/type-utils": {
- "version": "8.50.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.50.0.tgz",
- "integrity": "sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "8.50.0",
- "@typescript-eslint/typescript-estree": "8.50.0",
- "@typescript-eslint/utils": "8.50.0",
- "debug": "^4.3.4",
- "ts-api-utils": "^2.1.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <6.0.0"
- }
- },
- "node_modules/@typescript-eslint/types": {
- "version": "8.50.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.50.0.tgz",
- "integrity": "sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree": {
- "version": "8.50.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.50.0.tgz",
- "integrity": "sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/project-service": "8.50.0",
- "@typescript-eslint/tsconfig-utils": "8.50.0",
- "@typescript-eslint/types": "8.50.0",
- "@typescript-eslint/visitor-keys": "8.50.0",
- "debug": "^4.3.4",
- "minimatch": "^9.0.4",
- "semver": "^7.6.0",
- "tinyglobby": "^0.2.15",
- "ts-api-utils": "^2.1.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4 <6.0.0"
- }
- },
- "node_modules/@typescript-eslint/typescript-estree/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/@typescript-eslint/typescript-estree/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/@typescript-eslint/utils": {
- "version": "8.50.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.50.0.tgz",
- "integrity": "sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.7.0",
- "@typescript-eslint/scope-manager": "8.50.0",
- "@typescript-eslint/types": "8.50.0",
- "@typescript-eslint/typescript-estree": "8.50.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- },
- "peerDependencies": {
- "eslint": "^8.57.0 || ^9.0.0",
- "typescript": ">=4.8.4 <6.0.0"
- }
- },
- "node_modules/@typescript-eslint/visitor-keys": {
- "version": "8.50.0",
- "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.50.0.tgz",
- "integrity": "sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@typescript-eslint/types": "8.50.0",
- "eslint-visitor-keys": "^4.2.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/typescript-eslint"
- }
- },
- "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
- "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/@yarnpkg/lockfile": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
- "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
- "dev": true,
- "license": "BSD-2-Clause"
- },
- "node_modules/@yukikaze-bot/erlpack": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/@yukikaze-bot/erlpack/-/erlpack-1.0.1.tgz",
- "integrity": "sha512-PCJ2lGCf8DsQtrE411PY+NTsolK48l4InNn1kcBo0iUllKZYGLqeqXEWGA/INrmwanKcoYkU4pBySqUFLQDEoA==",
- "hasInstallScript": true,
- "license": "Apache-2.0",
- "optional": true,
- "dependencies": {
- "@mapbox/node-pre-gyp": "^1.0.5",
- "node-addon-api": "^4.0.0"
- }
- },
- "node_modules/abbrev": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
- "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
- "license": "ISC",
- "optional": true
- },
- "node_modules/abort-controller": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
- "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "event-target-shim": "^5.0.0"
- },
- "engines": {
- "node": ">=6.5"
- }
- },
- "node_modules/accepts": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
- "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
- "license": "MIT",
- "dependencies": {
- "mime-types": "^3.0.0",
- "negotiator": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/acorn": {
- "version": "8.15.0",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
- "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
- "devOptional": true,
- "license": "MIT",
- "peer": true,
- "bin": {
- "acorn": "bin/acorn"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/acorn-jsx": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
- "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
- "dev": true,
- "license": "MIT",
- "peerDependencies": {
- "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
- }
- },
- "node_modules/acorn-walk": {
- "version": "8.3.4",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
- "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "acorn": "^8.11.0"
- },
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/agent-base": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
- "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "debug": "4"
- },
- "engines": {
- "node": ">= 6.0.0"
- }
- },
- "node_modules/agentkeepalive": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
- "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "humanize-ms": "^1.2.1"
- },
- "engines": {
- "node": ">= 8.0.0"
- }
- },
- "node_modules/aggregate-error": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
- "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "clean-stack": "^2.0.0",
- "indent-string": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "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==",
- "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/ajv-formats": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
- "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
- "license": "MIT",
- "dependencies": {
- "ajv": "^8.0.0"
- },
- "peerDependencies": {
- "ajv": "^8.0.0"
- },
- "peerDependenciesMeta": {
- "ajv": {
- "optional": true
- }
- }
- },
- "node_modules/amqplib": {
- "version": "0.10.9",
- "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.9.tgz",
- "integrity": "sha512-jwSftI4QjS3mizvnSnOrPGYiUnm1vI2OP1iXeOUz5pb74Ua0nbf6nPyyTzuiCLEE3fMpaJORXh2K/TQ08H5xGA==",
- "license": "MIT",
- "dependencies": {
- "buffer-more-ints": "~1.0.0",
- "url-parse": "~1.5.10"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "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==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/ansi-styles": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
- "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
- "license": "MIT",
- "dependencies": {
- "color-convert": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/chalk/ansi-styles?sponsor=1"
- }
- },
- "node_modules/ansis": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz",
- "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==",
- "license": "ISC",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/any-base": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz",
- "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/app-root-path": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz",
- "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==",
- "license": "MIT",
- "engines": {
- "node": ">= 6.0.0"
- }
- },
- "node_modules/append-field": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
- "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
- "license": "MIT"
- },
- "node_modules/aproba": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz",
- "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==",
- "license": "ISC",
- "optional": true
- },
- "node_modules/are-we-there-yet": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
- "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "delegates": "^1.0.0",
- "readable-stream": "^3.6.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/arg": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
- "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/argparse": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
- "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
- "dev": true,
- "license": "Python-2.0"
- },
- "node_modules/asn1js": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.7.tgz",
- "integrity": "sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "pvtsutils": "^1.3.6",
- "pvutils": "^1.1.3",
- "tslib": "^2.8.1"
- },
- "engines": {
- "node": ">=12.0.0"
- }
- },
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
- "license": "MIT"
- },
- "node_modules/available-typed-arrays": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
- "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
- "license": "MIT",
- "dependencies": {
- "possible-typed-array-names": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/await-to-js": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz",
- "integrity": "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/axios": {
- "version": "1.13.2",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
- "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "follow-redirects": "^1.15.6",
- "form-data": "^4.0.4",
- "proxy-from-env": "^1.1.0"
- }
- },
- "node_modules/balanced-match": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
- "license": "MIT"
- },
- "node_modules/base-64": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
- "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/base64-js": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
- "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
- "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/basic-auth": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
- "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "5.1.2"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/basic-auth/node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "license": "MIT"
- },
- "node_modules/bcrypt": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz",
- "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==",
- "hasInstallScript": true,
- "license": "MIT",
- "dependencies": {
- "node-addon-api": "^8.3.0",
- "node-gyp-build": "^4.8.4"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "node_modules/bcrypt/node_modules/node-addon-api": {
- "version": "8.5.0",
- "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz",
- "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==",
- "license": "MIT",
- "engines": {
- "node": "^18 || ^20 || >= 21"
- }
- },
- "node_modules/bignumber.js": {
- "version": "9.3.1",
- "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
- "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
- "license": "MIT",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/bindings": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
- "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
- "license": "MIT",
- "dependencies": {
- "file-uri-to-path": "1.0.0"
- }
- },
- "node_modules/bl": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
- "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
- "license": "MIT",
- "dependencies": {
- "buffer": "^5.5.0",
- "inherits": "^2.0.4",
- "readable-stream": "^3.4.0"
- }
- },
- "node_modules/bmp-ts": {
- "version": "1.0.9",
- "resolved": "https://registry.npmjs.org/bmp-ts/-/bmp-ts-1.0.9.tgz",
- "integrity": "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/body-parser": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz",
- "integrity": "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==",
- "license": "MIT",
- "dependencies": {
- "bytes": "^3.1.2",
- "content-type": "^1.0.5",
- "debug": "^4.4.3",
- "http-errors": "^2.0.0",
- "iconv-lite": "^0.7.0",
- "on-finished": "^2.4.1",
- "qs": "^6.14.0",
- "raw-body": "^3.0.1",
- "type-is": "^2.0.1"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/boolbase": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
- "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
- "license": "ISC"
- },
- "node_modules/bowser": {
- "version": "2.13.1",
- "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.13.1.tgz",
- "integrity": "sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==",
- "license": "MIT"
- },
- "node_modules/brace-expansion": {
- "version": "1.1.12",
- "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
- "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
- "devOptional": true,
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
- }
- },
- "node_modules/braces": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
- "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fill-range": "^7.1.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/buffer": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
- "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
- "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",
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.1.13"
- }
- },
- "node_modules/buffer-equal-constant-time": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
- "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
- "license": "BSD-3-Clause"
- },
- "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==",
- "license": "MIT"
- },
- "node_modules/buffer-more-ints": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz",
- "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==",
- "license": "MIT"
- },
- "node_modules/busboy": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
- "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
- "dependencies": {
- "streamsearch": "^1.1.0"
- },
- "engines": {
- "node": ">=10.16.0"
- }
- },
- "node_modules/bytes": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
- "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/bytestreamjs": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/bytestreamjs/-/bytestreamjs-2.0.1.tgz",
- "integrity": "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/cacache": {
- "version": "15.3.0",
- "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz",
- "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "@npmcli/fs": "^1.0.0",
- "@npmcli/move-file": "^1.0.1",
- "chownr": "^2.0.0",
- "fs-minipass": "^2.0.0",
- "glob": "^7.1.4",
- "infer-owner": "^1.0.4",
- "lru-cache": "^6.0.0",
- "minipass": "^3.1.1",
- "minipass-collect": "^1.0.2",
- "minipass-flush": "^1.0.5",
- "minipass-pipeline": "^1.2.2",
- "mkdirp": "^1.0.3",
- "p-map": "^4.0.0",
- "promise-inflight": "^1.0.1",
- "rimraf": "^3.0.2",
- "ssri": "^8.0.1",
- "tar": "^6.0.2",
- "unique-filename": "^1.1.1"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/cacache/node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "license": "MIT",
- "optional": true,
- "bin": {
- "mkdirp": "bin/cmd.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/call-bind": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
- "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.0",
- "es-define-property": "^1.0.0",
- "get-intrinsic": "^1.2.4",
- "set-function-length": "^1.2.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/call-bind-apply-helpers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
- "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/call-bound": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
- "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "get-intrinsic": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/callsites": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
- "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/cbor-extract": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/cbor-extract/-/cbor-extract-2.2.0.tgz",
- "integrity": "sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==",
- "hasInstallScript": true,
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "node-gyp-build-optional-packages": "5.1.1"
- },
- "bin": {
- "download-cbor-prebuilds": "bin/download-prebuilds.js"
- },
- "optionalDependencies": {
- "@cbor-extract/cbor-extract-darwin-arm64": "2.2.0",
- "@cbor-extract/cbor-extract-darwin-x64": "2.2.0",
- "@cbor-extract/cbor-extract-linux-arm": "2.2.0",
- "@cbor-extract/cbor-extract-linux-arm64": "2.2.0",
- "@cbor-extract/cbor-extract-linux-x64": "2.2.0",
- "@cbor-extract/cbor-extract-win32-x64": "2.2.0"
- }
- },
- "node_modules/cbor-x": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/cbor-x/-/cbor-x-1.6.0.tgz",
- "integrity": "sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg==",
- "license": "MIT",
- "optionalDependencies": {
- "cbor-extract": "^2.2.0"
- }
- },
- "node_modules/chalk": {
- "version": "5.6.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
- "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
- "license": "MIT",
- "engines": {
- "node": "^12.17.0 || ^14.13 || >=16.0.0"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/cheerio": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.1.2.tgz",
- "integrity": "sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==",
- "license": "MIT",
- "dependencies": {
- "cheerio-select": "^2.1.0",
- "dom-serializer": "^2.0.0",
- "domhandler": "^5.0.3",
- "domutils": "^3.2.2",
- "encoding-sniffer": "^0.2.1",
- "htmlparser2": "^10.0.0",
- "parse5": "^7.3.0",
- "parse5-htmlparser2-tree-adapter": "^7.1.0",
- "parse5-parser-stream": "^7.1.2",
- "undici": "^7.12.0",
- "whatwg-mimetype": "^4.0.0"
- },
- "engines": {
- "node": ">=20.18.1"
- },
- "funding": {
- "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
- }
- },
- "node_modules/cheerio-select": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
- "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "boolbase": "^1.0.0",
- "css-select": "^5.1.0",
- "css-what": "^6.1.0",
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.3",
- "domutils": "^3.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/fb55"
- }
- },
- "node_modules/chownr": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
- "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/ci-info": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
- "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
- "dev": true,
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/sibiraj-s"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/clean-stack": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
- "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/cliui": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
- "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
- "license": "ISC",
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.1",
- "wrap-ansi": "^7.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
- "license": "MIT",
- "dependencies": {
- "color-name": "~1.1.4"
- },
- "engines": {
- "node": ">=7.0.0"
- }
- },
- "node_modules/color-name": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
- "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
- "license": "MIT"
- },
- "node_modules/color-support": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
- "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
- "license": "ISC",
- "optional": true,
- "bin": {
- "color-support": "bin.js"
- }
- },
- "node_modules/combined-stream": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
- "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
- "license": "MIT",
- "dependencies": {
- "delayed-stream": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/concat-stream": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
- "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
- "engines": [
- "node >= 6.0"
- ],
- "license": "MIT",
- "dependencies": {
- "buffer-from": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.0.2",
- "typedarray": "^0.0.6"
- }
- },
- "node_modules/console-control-strings": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
- "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
- "license": "ISC",
- "optional": true
- },
- "node_modules/content-disposition": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
- "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/content-type": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
- "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie": {
- "version": "0.7.2",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
- "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/cookie-parser": {
- "version": "1.4.7",
- "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
- "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
- "license": "MIT",
- "dependencies": {
- "cookie": "0.7.2",
- "cookie-signature": "1.0.6"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
- "license": "MIT"
- },
- "node_modules/create-require": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
- "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/cross-spawn": {
- "version": "7.0.6",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
- "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
- "license": "MIT",
- "dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/css-select": {
- "version": "5.2.2",
- "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
- "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "boolbase": "^1.0.0",
- "css-what": "^6.1.0",
- "domhandler": "^5.0.2",
- "domutils": "^3.0.1",
- "nth-check": "^2.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/fb55"
- }
- },
- "node_modules/css-what": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
- "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">= 6"
- },
- "funding": {
- "url": "https://github.com/sponsors/fb55"
- }
- },
- "node_modules/dayjs": {
- "version": "1.11.19",
- "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
- "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==",
- "license": "MIT"
- },
- "node_modules/debug": {
- "version": "4.4.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
- "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.3"
- },
- "engines": {
- "node": ">=6.0"
- },
- "peerDependenciesMeta": {
- "supports-color": {
- "optional": true
- }
- }
- },
- "node_modules/decompress-response": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
- "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
- "license": "MIT",
- "dependencies": {
- "mimic-response": "^3.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/dedent": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz",
- "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==",
- "license": "MIT",
- "peerDependencies": {
- "babel-plugin-macros": "^3.1.0"
- },
- "peerDependenciesMeta": {
- "babel-plugin-macros": {
- "optional": true
- }
- }
- },
- "node_modules/deep-extend": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
- "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
- "license": "MIT",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/deep-is": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
- "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
- "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==",
- "license": "MIT",
- "optional": true,
- "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",
- "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
- "license": "MIT",
- "dependencies": {
- "es-define-property": "^1.0.0",
- "es-errors": "^1.3.0",
- "gopd": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/delayed-stream": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/delegates": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
- "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/depd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
- "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/detect-libc": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
- "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
- "license": "Apache-2.0",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/diff": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
- "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
- "devOptional": true,
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.3.1"
- }
- },
- "node_modules/discord-protos": {
- "version": "1.2.90",
- "resolved": "https://registry.npmjs.org/discord-protos/-/discord-protos-1.2.90.tgz",
- "integrity": "sha512-7W57dYO3ohAseS2k46UpGq+1b8FDuXIRz0WlxoWI6cgESuIPI6DCXfwc3tDeEaps81kfyOnBrT0LdNX+TrE/oQ==",
- "license": "MIT",
- "dependencies": {
- "@protobuf-ts/runtime": "^2.9.6"
- }
- },
- "node_modules/dom-serializer": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
- "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
- "license": "MIT",
- "dependencies": {
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.2",
- "entities": "^4.2.0"
- },
- "funding": {
- "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
- }
- },
- "node_modules/domelementtype": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
- "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/fb55"
- }
- ],
- "license": "BSD-2-Clause"
- },
- "node_modules/domhandler": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
- "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "domelementtype": "^2.3.0"
- },
- "engines": {
- "node": ">= 4"
- },
- "funding": {
- "url": "https://github.com/fb55/domhandler?sponsor=1"
- }
- },
- "node_modules/domutils": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
- "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "dom-serializer": "^2.0.0",
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.3"
- },
- "funding": {
- "url": "https://github.com/fb55/domutils?sponsor=1"
- }
- },
- "node_modules/dotenv": {
- "version": "17.2.3",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz",
- "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://dotenvx.com"
- }
- },
- "node_modules/dunder-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
- "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.1",
- "es-errors": "^1.3.0",
- "gopd": "^1.2.0"
- },
- "engines": {
- "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==",
- "license": "MIT"
- },
- "node_modules/ecdsa-sig-formatter": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
- "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/ee-first": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
- "license": "MIT"
- },
- "node_modules/email-providers": {
- "version": "2.19.0",
- "resolved": "https://registry.npmjs.org/email-providers/-/email-providers-2.19.0.tgz",
- "integrity": "sha512-HwDo7NLmBWXHtnXlediIbI1x+WSgTszWi35TZxlGhW49iW/dZkzC78f4RD/8osLY2Rqh62sgD2ufduKRO54Raw==",
- "license": "ISC",
- "engines": {
- "node": ">=16"
- }
- },
- "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==",
- "license": "MIT"
- },
- "node_modules/encodeurl": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
- "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/encoding": {
- "version": "0.1.13",
- "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
- "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "iconv-lite": "^0.6.2"
- }
- },
- "node_modules/encoding-sniffer": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz",
- "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==",
- "license": "MIT",
- "dependencies": {
- "iconv-lite": "^0.6.3",
- "whatwg-encoding": "^3.1.1"
- },
- "funding": {
- "url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
- }
- },
- "node_modules/encoding-sniffer/node_modules/iconv-lite": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
- "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/encoding/node_modules/iconv-lite": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
- "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/end-of-stream": {
- "version": "1.4.5",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
- "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
- "license": "MIT",
- "dependencies": {
- "once": "^1.4.0"
- }
- },
- "node_modules/entities": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
- "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=0.12"
- },
- "funding": {
- "url": "https://github.com/fb55/entities?sponsor=1"
- }
- },
- "node_modules/env-paths": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
- "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/err-code": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
- "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/es-define-property": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
- "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-errors": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
- "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-object-atoms": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
- "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/es-set-tostringtag": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
- "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.6",
- "has-tostringtag": "^1.0.2",
- "hasown": "^2.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/escalade": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
- "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/escape-html": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
- "license": "MIT"
- },
- "node_modules/escape-string-regexp": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
- "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/eslint": {
- "version": "9.39.2",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz",
- "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@eslint-community/eslint-utils": "^4.8.0",
- "@eslint-community/regexpp": "^4.12.1",
- "@eslint/config-array": "^0.21.1",
- "@eslint/config-helpers": "^0.4.2",
- "@eslint/core": "^0.17.0",
- "@eslint/eslintrc": "^3.3.1",
- "@eslint/js": "9.39.2",
- "@eslint/plugin-kit": "^0.4.1",
- "@humanfs/node": "^0.16.6",
- "@humanwhocodes/module-importer": "^1.0.1",
- "@humanwhocodes/retry": "^0.4.2",
- "@types/estree": "^1.0.6",
- "ajv": "^6.12.4",
- "chalk": "^4.0.0",
- "cross-spawn": "^7.0.6",
- "debug": "^4.3.2",
- "escape-string-regexp": "^4.0.0",
- "eslint-scope": "^8.4.0",
- "eslint-visitor-keys": "^4.2.1",
- "espree": "^10.4.0",
- "esquery": "^1.5.0",
- "esutils": "^2.0.2",
- "fast-deep-equal": "^3.1.3",
- "file-entry-cache": "^8.0.0",
- "find-up": "^5.0.0",
- "glob-parent": "^6.0.2",
- "ignore": "^5.2.0",
- "imurmurhash": "^0.1.4",
- "is-glob": "^4.0.0",
- "json-stable-stringify-without-jsonify": "^1.0.1",
- "lodash.merge": "^4.6.2",
- "minimatch": "^3.1.2",
- "natural-compare": "^1.4.0",
- "optionator": "^0.9.3"
- },
- "bin": {
- "eslint": "bin/eslint.js"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://eslint.org/donate"
- },
- "peerDependencies": {
- "jiti": "*"
- },
- "peerDependenciesMeta": {
- "jiti": {
- "optional": true
- }
- }
- },
- "node_modules/eslint-scope": {
- "version": "8.4.0",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
- "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "esrecurse": "^4.3.0",
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-visitor-keys": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
- "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint/node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fast-deep-equal": "^3.1.1",
- "fast-json-stable-stringify": "^2.0.0",
- "json-schema-traverse": "^0.4.1",
- "uri-js": "^4.2.2"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/epoberezkin"
- }
- },
- "node_modules/eslint/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/eslint/node_modules/eslint-visitor-keys": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
- "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint/node_modules/json-schema-traverse": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
- "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/espree": {
- "version": "10.4.0",
- "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
- "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "acorn": "^8.15.0",
- "acorn-jsx": "^5.3.2",
- "eslint-visitor-keys": "^4.2.1"
- },
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/espree/node_modules/eslint-visitor-keys": {
- "version": "4.2.1",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
- "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
- "dev": true,
- "license": "Apache-2.0",
- "engines": {
- "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
- },
- "funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/esquery": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
- "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "estraverse": "^5.1.0"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/esrecurse": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
- "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "estraverse": "^5.2.0"
- },
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/estraverse": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
- "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true,
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/esutils": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
- "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
- "dev": true,
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/etag": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/event-target-shim": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
- "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/events": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
- "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=0.8.x"
- }
- },
- "node_modules/exif-be-gone": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/exif-be-gone/-/exif-be-gone-1.5.1.tgz",
- "integrity": "sha512-+fV9PoomNVR5Hmp0n1c0ZVl78/GaFrpnC0t7q4F9Aey8NcL+7Lutcez8KY2Ni30NWpvgLXawqiRFFwtdo4QgFg==",
- "license": "ISC",
- "bin": {
- "exif-be-gone": "cli.js"
- }
- },
- "node_modules/exif-parser": {
- "version": "0.1.12",
- "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
- "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==",
- "optional": true
- },
- "node_modules/expand-template": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
- "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
- "license": "(MIT OR WTFPL)",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/express": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
- "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
- "license": "MIT",
- "dependencies": {
- "accepts": "^2.0.0",
- "body-parser": "^2.2.1",
- "content-disposition": "^1.0.0",
- "content-type": "^1.0.5",
- "cookie": "^0.7.1",
- "cookie-signature": "^1.2.1",
- "debug": "^4.4.0",
- "depd": "^2.0.0",
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "etag": "^1.8.1",
- "finalhandler": "^2.1.0",
- "fresh": "^2.0.0",
- "http-errors": "^2.0.0",
- "merge-descriptors": "^2.0.0",
- "mime-types": "^3.0.0",
- "on-finished": "^2.4.1",
- "once": "^1.4.0",
- "parseurl": "^1.3.3",
- "proxy-addr": "^2.0.7",
- "qs": "^6.14.0",
- "range-parser": "^1.2.1",
- "router": "^2.2.0",
- "send": "^1.1.0",
- "serve-static": "^2.2.0",
- "statuses": "^2.0.1",
- "type-is": "^2.0.1",
- "vary": "^1.1.2"
- },
- "engines": {
- "node": ">= 18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/express/node_modules/cookie-signature": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
- "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
- "license": "MIT",
- "engines": {
- "node": ">=6.6.0"
- }
- },
- "node_modules/fast-deep-equal": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
- "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
- "license": "MIT"
- },
- "node_modules/fast-json-stable-stringify": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/fast-levenshtein": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
- "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
- "dev": true,
- "license": "MIT"
- },
- "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==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/fastify"
- },
- {
- "type": "opencollective",
- "url": "https://opencollective.com/fastify"
- }
- ],
- "license": "BSD-3-Clause"
- },
- "node_modules/fast-xml-parser": {
- "version": "5.2.5",
- "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz",
- "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/NaturalIntelligence"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "strnum": "^2.1.0"
- },
- "bin": {
- "fxparser": "src/cli/cli.js"
- }
- },
- "node_modules/fast-zlib": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/fast-zlib/-/fast-zlib-2.0.1.tgz",
- "integrity": "sha512-DCoYgNagM2Bt1VIpXpdGnRx4LzqJeYG0oh6Nf/7cWo6elTXkFGMw9CrRCYYUIapYNrozYMoyDRflx9mgT3Awyw==",
- "license": "MIT",
- "funding": {
- "type": "patreon",
- "url": "https://patreon.com/timotejroiko"
- }
- },
- "node_modules/fido2-lib": {
- "version": "3.5.5",
- "resolved": "https://registry.npmjs.org/fido2-lib/-/fido2-lib-3.5.5.tgz",
- "integrity": "sha512-XEXa+kRyQEq4Yse5bG+4rrvsxfOMp+ihzI2Uxi0/6OJ4ZaUdNKl8fBGDoyFZu/TKjCJGcL182/jf+UoyMSf9ow==",
- "license": "MIT",
- "dependencies": {
- "@hexagon/base64": "~1.1.28",
- "@peculiar/webcrypto": "~1.4.6",
- "asn1js": "~3.0.6",
- "cbor-x": "~1.6.0",
- "jose": "^6.1.0",
- "pkijs": "~3.3.2",
- "punycode.js": "^2.3.1",
- "tldts": "~7.0.17"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/file-entry-cache": {
- "version": "8.0.0",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
- "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "flat-cache": "^4.0.0"
- },
- "engines": {
- "node": ">=16.0.0"
- }
- },
- "node_modules/file-type": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.1.1.tgz",
- "integrity": "sha512-ifJXo8zUqbQ/bLbl9sFoqHNTNWbnPY1COImFfM6CCy7z+E+jC1eY9YfOKkx0fckIg+VljAy2/87T61fp0+eEkg==",
- "license": "MIT",
- "dependencies": {
- "@tokenizer/inflate": "^0.4.1",
- "strtok3": "^10.3.4",
- "token-types": "^6.1.1",
- "uint8array-extras": "^1.4.0"
- },
- "engines": {
- "node": ">=20"
- },
- "funding": {
- "url": "https://github.com/sindresorhus/file-type?sponsor=1"
- }
- },
- "node_modules/file-uri-to-path": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
- "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
- "license": "MIT"
- },
- "node_modules/fill-range": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
- "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/finalhandler": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
- "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.4.0",
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "on-finished": "^2.4.1",
- "parseurl": "^1.3.3",
- "statuses": "^2.0.1"
- },
- "engines": {
- "node": ">= 18.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/find-up": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
- "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "locate-path": "^6.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/find-yarn-workspace-root": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz",
- "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==",
- "dev": true,
- "license": "Apache-2.0",
- "dependencies": {
- "micromatch": "^4.0.2"
- }
- },
- "node_modules/flat-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
- "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "flatted": "^3.2.9",
- "keyv": "^4.5.4"
- },
- "engines": {
- "node": ">=16"
- }
- },
- "node_modules/flatted": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
- "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
- "dev": true,
- "license": "ISC"
- },
- "node_modules/follow-redirects": {
- "version": "1.15.11",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
- "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
- "funding": [
- {
- "type": "individual",
- "url": "https://github.com/sponsors/RubenVerborgh"
- }
- ],
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=4.0"
- },
- "peerDependenciesMeta": {
- "debug": {
- "optional": true
- }
- }
- },
- "node_modules/for-each": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
- "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
- "license": "MIT",
- "dependencies": {
- "is-callable": "^1.2.7"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "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==",
- "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/foreground-child/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==",
- "license": "ISC",
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/form-data": {
- "version": "4.0.5",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
- "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
- "license": "MIT",
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.8",
- "es-set-tostringtag": "^2.1.0",
- "hasown": "^2.0.2",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/form-data/node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/form-data/node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fresh": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
- "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/fs-constants": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
- "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
- "license": "MIT"
- },
- "node_modules/fs-extra": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
- "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.2.0",
- "jsonfile": "^6.0.1",
- "universalify": "^2.0.0"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/fs-minipass": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
- "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
- "license": "ISC",
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/fs.realpath": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "devOptional": true,
- "license": "ISC"
- },
- "node_modules/function-bind": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
- "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/gauge": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
- "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "aproba": "^1.0.3 || ^2.0.0",
- "color-support": "^1.1.2",
- "console-control-strings": "^1.0.0",
- "has-unicode": "^2.0.1",
- "object-assign": "^4.1.1",
- "signal-exit": "^3.0.0",
- "string-width": "^4.2.3",
- "strip-ansi": "^6.0.1",
- "wide-align": "^1.1.2"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/get-caller-file": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
- "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
- "license": "ISC",
- "engines": {
- "node": "6.* || 8.* || >= 10.*"
- }
- },
- "node_modules/get-intrinsic": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
- "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
- "license": "MIT",
- "dependencies": {
- "call-bind-apply-helpers": "^1.0.2",
- "es-define-property": "^1.0.1",
- "es-errors": "^1.3.0",
- "es-object-atoms": "^1.1.1",
- "function-bind": "^1.1.2",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-symbols": "^1.1.0",
- "hasown": "^2.0.2",
- "math-intrinsics": "^1.1.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-proto": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
- "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
- "license": "MIT",
- "dependencies": {
- "dunder-proto": "^1.0.1",
- "es-object-atoms": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/gifwrap": {
- "version": "0.10.1",
- "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz",
- "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "image-q": "^4.0.0",
- "omggif": "^1.0.10"
- }
- },
- "node_modules/github-from-package": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
- "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
- "license": "MIT"
- },
- "node_modules/glob": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
- "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
- "devOptional": true,
- "license": "ISC",
- "dependencies": {
- "fs.realpath": "^1.0.0",
- "inflight": "^1.0.4",
- "inherits": "2",
- "minimatch": "^3.1.1",
- "once": "^1.3.0",
- "path-is-absolute": "^1.0.0"
- },
- "engines": {
- "node": "*"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/glob-parent": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
- "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
- "license": "ISC",
- "dependencies": {
- "is-glob": "^4.0.3"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/globals": {
- "version": "16.5.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz",
- "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/gopd": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
- "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "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==",
- "devOptional": true,
- "license": "ISC"
- },
- "node_modules/has-flag": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
- "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/has-property-descriptors": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
- "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
- "license": "MIT",
- "dependencies": {
- "es-define-property": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-symbols": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
- "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-tostringtag": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
- "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
- "license": "MIT",
- "dependencies": {
- "has-symbols": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/has-unicode": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
- "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
- "license": "ISC",
- "optional": true
- },
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
- "license": "MIT",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/htmlparser2": {
- "version": "10.0.0",
- "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz",
- "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==",
- "funding": [
- "https://github.com/fb55/htmlparser2?sponsor=1",
- {
- "type": "github",
- "url": "https://github.com/sponsors/fb55"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "domelementtype": "^2.3.0",
- "domhandler": "^5.0.3",
- "domutils": "^3.2.1",
- "entities": "^6.0.0"
- }
- },
- "node_modules/htmlparser2/node_modules/entities": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
- "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=0.12"
- },
- "funding": {
- "url": "https://github.com/fb55/entities?sponsor=1"
- }
- },
- "node_modules/http-cache-semantics": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
- "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
- "license": "BSD-2-Clause",
- "optional": true
- },
- "node_modules/http-errors": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
- "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
- "license": "MIT",
- "dependencies": {
- "depd": "~2.0.0",
- "inherits": "~2.0.4",
- "setprototypeof": "~1.2.0",
- "statuses": "~2.0.2",
- "toidentifier": "~1.0.1"
- },
- "engines": {
- "node": ">= 0.8"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/http-proxy-agent": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
- "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@tootallnate/once": "1",
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/https-proxy-agent": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
- "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "agent-base": "6",
- "debug": "4"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/humanize-ms": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
- "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "ms": "^2.0.0"
- }
- },
- "node_modules/husky": {
- "version": "9.1.7",
- "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
- "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "husky": "bin.js"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/typicode"
- }
- },
- "node_modules/i18next": {
- "version": "25.7.3",
- "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.7.3.tgz",
- "integrity": "sha512-2XaT+HpYGuc2uTExq9TVRhLsso+Dxym6PWaKpn36wfBmTI779OQ7iP/XaZHzrnGyzU4SHpFrTYLKfVyBfAhVNA==",
- "funding": [
- {
- "type": "individual",
- "url": "https://locize.com"
- },
- {
- "type": "individual",
- "url": "https://locize.com/i18next.html"
- },
- {
- "type": "individual",
- "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "@babel/runtime": "^7.28.4"
- },
- "peerDependencies": {
- "typescript": "^5"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
- }
- },
- "node_modules/i18next-fs-backend": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-2.6.1.tgz",
- "integrity": "sha512-eYWTX7QT7kJ0sZyCPK6x1q+R63zvNKv2D6UdbMf15A8vNb2ZLyw4NNNZxPFwXlIv/U+oUtg8SakW6ZgJZcoqHQ==",
- "license": "MIT"
- },
- "node_modules/i18next-http-middleware": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/i18next-http-middleware/-/i18next-http-middleware-3.9.0.tgz",
- "integrity": "sha512-hM56al/hnQ8a6Us5uRvw/en1gSI3vePqBUa9nX4+ISvIHOU/li7ffu11FrI2aR83nphTe6ofo7mxhVu0PLAe2w==",
- "license": "MIT"
- },
- "node_modules/iconv-lite": {
- "version": "0.7.1",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz",
- "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/ieee754": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
- "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
- "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": "BSD-3-Clause"
- },
- "node_modules/ignore": {
- "version": "5.3.2",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
- "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/image-q": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz",
- "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@types/node": "16.9.1"
- }
- },
- "node_modules/image-q/node_modules/@types/node": {
- "version": "16.9.1",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz",
- "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/image-size": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/image-size/-/image-size-2.0.2.tgz",
- "integrity": "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w==",
- "license": "MIT",
- "bin": {
- "image-size": "bin/image-size.js"
- },
- "engines": {
- "node": ">=16.x"
- }
- },
- "node_modules/import-fresh": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
- "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "parent-module": "^1.0.0",
- "resolve-from": "^4.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/imurmurhash": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
- "devOptional": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.8.19"
- }
- },
- "node_modules/indent-string": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
- "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/infer-owner": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
- "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
- "license": "ISC",
- "optional": true
- },
- "node_modules/inflight": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
- "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
- "devOptional": true,
- "license": "ISC",
- "dependencies": {
- "once": "^1.3.0",
- "wrappy": "1"
- }
- },
- "node_modules/inherits": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
- "license": "ISC"
- },
- "node_modules/ini": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
- "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
- "license": "ISC"
- },
- "node_modules/ip-address": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
- "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/is-callable": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
- "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-docker": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
- "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
- "dev": true,
- "license": "MIT",
- "bin": {
- "is-docker": "cli.js"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/is-extglob": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "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==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/is-glob": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
- "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-extglob": "^2.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-lambda": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
- "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/is-number": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
- "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/is-promise": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
- "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
- "license": "MIT"
- },
- "node_modules/is-typed-array": {
- "version": "1.1.15",
- "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
- "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
- "license": "MIT",
- "dependencies": {
- "which-typed-array": "^1.1.16"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-wsl": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
- "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-docker": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/isarray": {
- "version": "2.0.5",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
- "license": "MIT"
- },
- "node_modules/isexe": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "license": "ISC"
- },
- "node_modules/jackspeak": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
- "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "@isaacs/cliui": "^8.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- },
- "optionalDependencies": {
- "@pkgjs/parseargs": "^0.11.0"
- }
- },
- "node_modules/jimp": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/jimp/-/jimp-1.6.0.tgz",
- "integrity": "sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "@jimp/core": "1.6.0",
- "@jimp/diff": "1.6.0",
- "@jimp/js-bmp": "1.6.0",
- "@jimp/js-gif": "1.6.0",
- "@jimp/js-jpeg": "1.6.0",
- "@jimp/js-png": "1.6.0",
- "@jimp/js-tiff": "1.6.0",
- "@jimp/plugin-blit": "1.6.0",
- "@jimp/plugin-blur": "1.6.0",
- "@jimp/plugin-circle": "1.6.0",
- "@jimp/plugin-color": "1.6.0",
- "@jimp/plugin-contain": "1.6.0",
- "@jimp/plugin-cover": "1.6.0",
- "@jimp/plugin-crop": "1.6.0",
- "@jimp/plugin-displace": "1.6.0",
- "@jimp/plugin-dither": "1.6.0",
- "@jimp/plugin-fisheye": "1.6.0",
- "@jimp/plugin-flip": "1.6.0",
- "@jimp/plugin-hash": "1.6.0",
- "@jimp/plugin-mask": "1.6.0",
- "@jimp/plugin-print": "1.6.0",
- "@jimp/plugin-quantize": "1.6.0",
- "@jimp/plugin-resize": "1.6.0",
- "@jimp/plugin-rotate": "1.6.0",
- "@jimp/plugin-threshold": "1.6.0",
- "@jimp/types": "1.6.0",
- "@jimp/utils": "1.6.0"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/jose": {
- "version": "6.1.3",
- "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz",
- "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/panva"
- }
- },
- "node_modules/jpeg-js": {
- "version": "0.4.4",
- "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz",
- "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==",
- "license": "BSD-3-Clause",
- "optional": true
- },
- "node_modules/js-yaml": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
- "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "argparse": "^2.0.1"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/json-bigint": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
- "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
- "license": "MIT",
- "dependencies": {
- "bignumber.js": "^9.0.0"
- }
- },
- "node_modules/json-buffer": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
- "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/json-schema-traverse": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
- "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
- "license": "MIT"
- },
- "node_modules/json-stable-stringify": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz",
- "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "isarray": "^2.0.5",
- "jsonify": "^0.0.1",
- "object-keys": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/json-stable-stringify-without-jsonify": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
- "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "dev": true,
- "license": "MIT"
- },
- "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/jsonify": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz",
- "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==",
- "dev": true,
- "license": "Public Domain",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/jsonwebtoken": {
- "version": "9.0.3",
- "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz",
- "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==",
- "license": "MIT",
- "dependencies": {
- "jws": "^4.0.1",
- "lodash.includes": "^4.3.0",
- "lodash.isboolean": "^3.0.3",
- "lodash.isinteger": "^4.0.4",
- "lodash.isnumber": "^3.0.3",
- "lodash.isplainobject": "^4.0.6",
- "lodash.isstring": "^4.0.1",
- "lodash.once": "^4.0.0",
- "ms": "^2.1.1",
- "semver": "^7.5.4"
- },
- "engines": {
- "node": ">=12",
- "npm": ">=6"
- }
- },
- "node_modules/jwa": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
- "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
- "license": "MIT",
- "dependencies": {
- "buffer-equal-constant-time": "^1.0.1",
- "ecdsa-sig-formatter": "1.0.11",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/jws": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
- "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
- "license": "MIT",
- "dependencies": {
- "jwa": "^2.0.1",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/keyv": {
- "version": "4.5.4",
- "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
- "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "json-buffer": "3.0.1"
- }
- },
- "node_modules/klaw-sync": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
- "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "graceful-fs": "^4.1.11"
- }
- },
- "node_modules/levn": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
- "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "prelude-ls": "^1.2.1",
- "type-check": "~0.4.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/locate-path": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
- "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-locate": "^5.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/lodash.includes": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
- "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
- "license": "MIT"
- },
- "node_modules/lodash.isboolean": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
- "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
- "license": "MIT"
- },
- "node_modules/lodash.isinteger": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
- "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
- "license": "MIT"
- },
- "node_modules/lodash.isnumber": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
- "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
- "license": "MIT"
- },
- "node_modules/lodash.isplainobject": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
- "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
- "license": "MIT"
- },
- "node_modules/lodash.isstring": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
- "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
- "license": "MIT"
- },
- "node_modules/lodash.merge": {
- "version": "4.6.2",
- "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
- "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
- "license": "MIT"
- },
- "node_modules/lodash.once": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
- "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
- "license": "MIT"
- },
- "node_modules/lru-cache": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
- "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/mailgun.js": {
- "version": "12.4.0",
- "resolved": "https://registry.npmjs.org/mailgun.js/-/mailgun.js-12.4.0.tgz",
- "integrity": "sha512-3Mwvwo02PUmFkW0zxSwvTjHBFCaMLb903RuQaEkTU8Z8medItb7Ey0K3XXLVDErArbEjPoRRqxPDdzWqXaokfQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "axios": "^1.12.1",
- "base-64": "^1.0.0",
- "url-join": "^4.0.1"
- },
- "engines": {
- "node": ">=18.0.0"
- }
- },
- "node_modules/make-dir": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
- "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "semver": "^6.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/make-dir/node_modules/semver": {
- "version": "6.3.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
- "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
- "license": "ISC",
- "optional": true,
- "bin": {
- "semver": "bin/semver.js"
- }
- },
- "node_modules/make-error": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
- "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
- "devOptional": true,
- "license": "ISC"
- },
- "node_modules/make-fetch-happen": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
- "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "agentkeepalive": "^4.1.3",
- "cacache": "^15.2.0",
- "http-cache-semantics": "^4.1.0",
- "http-proxy-agent": "^4.0.1",
- "https-proxy-agent": "^5.0.0",
- "is-lambda": "^1.0.1",
- "lru-cache": "^6.0.0",
- "minipass": "^3.1.3",
- "minipass-collect": "^1.0.2",
- "minipass-fetch": "^1.3.2",
- "minipass-flush": "^1.0.5",
- "minipass-pipeline": "^1.2.4",
- "negotiator": "^0.6.2",
- "promise-retry": "^2.0.1",
- "socks-proxy-agent": "^6.0.0",
- "ssri": "^8.0.0"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/make-fetch-happen/node_modules/negotiator": {
- "version": "0.6.4",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
- "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/math-intrinsics": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
- "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/media-typer": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
- "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/merge-descriptors": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
- "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/micromatch": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
- "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "braces": "^3.0.3",
- "picomatch": "^2.3.1"
- },
- "engines": {
- "node": ">=8.6"
- }
- },
- "node_modules/mime": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
- "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
- "license": "MIT",
- "optional": true,
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/mime-db": {
- "version": "1.54.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
- "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/mime-types": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
- "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "^1.54.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/mimic-response": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
- "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
- "devOptional": true,
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^1.1.7"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/minimist": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
- "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
- "license": "MIT",
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/minipass": {
- "version": "3.3.6",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
- "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
- "license": "ISC",
- "dependencies": {
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/minipass-collect": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
- "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/minipass-fetch": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz",
- "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "minipass": "^3.1.0",
- "minipass-sized": "^1.0.3",
- "minizlib": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- },
- "optionalDependencies": {
- "encoding": "^0.1.12"
- }
- },
- "node_modules/minipass-flush": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
- "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/minipass-pipeline": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
- "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/minipass-sized": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
- "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "minipass": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/minizlib": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
- "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
- "license": "MIT",
- "dependencies": {
- "minipass": "^3.0.0",
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/mkdirp": {
- "version": "0.5.6",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
- "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
- "license": "MIT",
- "dependencies": {
- "minimist": "^1.2.6"
- },
- "bin": {
- "mkdirp": "bin/cmd.js"
- }
- },
- "node_modules/mkdirp-classic": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
- "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
- "license": "MIT"
- },
- "node_modules/module-alias": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.3.tgz",
- "integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==",
- "license": "MIT"
- },
- "node_modules/morgan": {
- "version": "1.10.1",
- "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz",
- "integrity": "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==",
- "license": "MIT",
- "dependencies": {
- "basic-auth": "~2.0.1",
- "debug": "2.6.9",
- "depd": "~2.0.0",
- "on-finished": "~2.3.0",
- "on-headers": "~1.1.0"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/morgan/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/morgan/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/morgan/node_modules/on-finished": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
- "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
- "license": "MIT",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/mri": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
- "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ms": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
- "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
- "license": "MIT"
- },
- "node_modules/multer": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz",
- "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==",
- "license": "MIT",
- "dependencies": {
- "append-field": "^1.0.0",
- "busboy": "^1.6.0",
- "concat-stream": "^2.0.0",
- "mkdirp": "^0.5.6",
- "object-assign": "^4.1.1",
- "type-is": "^1.6.18",
- "xtend": "^4.0.2"
- },
- "engines": {
- "node": ">= 10.16.0"
- }
- },
- "node_modules/multer/node_modules/media-typer": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/multer/node_modules/mime-db": {
- "version": "1.52.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
- "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/multer/node_modules/mime-types": {
- "version": "2.1.35",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
- "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
- "license": "MIT",
- "dependencies": {
- "mime-db": "1.52.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/multer/node_modules/type-is": {
- "version": "1.6.18",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
- "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
- "license": "MIT",
- "dependencies": {
- "media-typer": "0.3.0",
- "mime-types": "~2.1.24"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/murmurhash-js": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz",
- "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==",
- "license": "MIT"
- },
- "node_modules/napi-build-utils": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
- "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
- "license": "MIT"
- },
- "node_modules/natural-compare": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/needle": {
- "version": "2.9.1",
- "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz",
- "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==",
- "license": "MIT",
- "dependencies": {
- "debug": "^3.2.6",
- "iconv-lite": "^0.4.4",
- "sax": "^1.2.4"
- },
- "bin": {
- "needle": "bin/needle"
- },
- "engines": {
- "node": ">= 4.4.x"
- }
- },
- "node_modules/needle/node_modules/debug": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
- "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
- "license": "MIT",
- "dependencies": {
- "ms": "^2.1.1"
- }
- },
- "node_modules/needle/node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/negotiator": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
- "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/node-2fa": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/node-2fa/-/node-2fa-2.0.3.tgz",
- "integrity": "sha512-PQldrOhjuoZyoydMvMSctllPN1ZPZ1/NwkEcgYwY9faVqE/OymxR+3awPpbWZxm6acLKqvmNqQmdqTsqYyflFw==",
- "license": "Apache-2.0",
- "dependencies": {
- "@types/notp": "^2.0.0",
- "notp": "^2.0.3",
- "thirty-two": "1.0.2",
- "tslib": "^2.1.0"
- }
- },
- "node_modules/node-abi": {
- "version": "3.85.0",
- "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz",
- "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==",
- "license": "MIT",
- "dependencies": {
- "semver": "^7.3.5"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/node-addon-api": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz",
- "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/node-fetch": {
- "version": "2.7.0",
- "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
- "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "whatwg-url": "^5.0.0"
- },
- "engines": {
- "node": "4.x || >=6.0.0"
- },
- "peerDependencies": {
- "encoding": "^0.1.0"
- },
- "peerDependenciesMeta": {
- "encoding": {
- "optional": true
- }
- }
- },
- "node_modules/node-gyp": {
- "version": "8.4.1",
- "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz",
- "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "env-paths": "^2.2.0",
- "glob": "^7.1.4",
- "graceful-fs": "^4.2.6",
- "make-fetch-happen": "^9.1.0",
- "nopt": "^5.0.0",
- "npmlog": "^6.0.0",
- "rimraf": "^3.0.2",
- "semver": "^7.3.5",
- "tar": "^6.1.2",
- "which": "^2.0.2"
- },
- "bin": {
- "node-gyp": "bin/node-gyp.js"
- },
- "engines": {
- "node": ">= 10.12.0"
- }
- },
- "node_modules/node-gyp-build": {
- "version": "4.8.4",
- "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
- "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
- "license": "MIT",
- "bin": {
- "node-gyp-build": "bin.js",
- "node-gyp-build-optional": "optional.js",
- "node-gyp-build-test": "build-test.js"
- }
- },
- "node_modules/node-gyp-build-optional-packages": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz",
- "integrity": "sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "detect-libc": "^2.0.1"
- },
- "bin": {
- "node-gyp-build-optional-packages": "bin.js",
- "node-gyp-build-optional-packages-optional": "optional.js",
- "node-gyp-build-optional-packages-test": "build-test.js"
- }
- },
- "node_modules/node-gyp/node_modules/are-we-there-yet": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz",
- "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "delegates": "^1.0.0",
- "readable-stream": "^3.6.0"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/node-gyp/node_modules/gauge": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz",
- "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "aproba": "^1.0.3 || ^2.0.0",
- "color-support": "^1.1.3",
- "console-control-strings": "^1.1.0",
- "has-unicode": "^2.0.1",
- "signal-exit": "^3.0.7",
- "string-width": "^4.2.3",
- "strip-ansi": "^6.0.1",
- "wide-align": "^1.1.5"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/node-gyp/node_modules/npmlog": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz",
- "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "are-we-there-yet": "^3.0.0",
- "console-control-strings": "^1.1.0",
- "gauge": "^4.0.3",
- "set-blocking": "^2.0.0"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/node-mailjet": {
- "version": "6.0.11",
- "resolved": "https://registry.npmjs.org/node-mailjet/-/node-mailjet-6.0.11.tgz",
- "integrity": "sha512-5UaawWhpJc1uFxUl9a07jE8a4ZOax5hj7XYC0LFYyWOP8Rp0I8XvjbiQ6gy/ns7KSw0hqmjytP85GQsdVGEx5g==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "axios": "^1.12.0",
- "json-bigint": "^1.0.0",
- "url-join": "^4.0.0"
- },
- "engines": {
- "node": ">= 12.0.0",
- "npm": ">= 6.9.0"
- }
- },
- "node_modules/nodemailer": {
- "version": "7.0.11",
- "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.11.tgz",
- "integrity": "sha512-gnXhNRE0FNhD7wPSCGhdNh46Hs6nm+uTyg+Kq0cZukNQiYdnCsoQjodNP9BQVG9XrcK/v6/MgpAPBUFyzh9pvw==",
- "license": "MIT-0",
- "optional": true,
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/nopt": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
- "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "abbrev": "1"
- },
- "bin": {
- "nopt": "bin/nopt.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/notp": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/notp/-/notp-2.0.3.tgz",
- "integrity": "sha512-oBig/2uqkjQ5AkBuw4QJYwkEWa/q+zHxI5/I5z6IeP2NT0alpJFsP/trrfCC+9xOAgQSZXssNi962kp5KBmypQ==",
- "engines": {
- "node": "> v0.6.0"
- }
- },
- "node_modules/npmlog": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
- "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
- "deprecated": "This package is no longer supported.",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "are-we-there-yet": "^2.0.0",
- "console-control-strings": "^1.1.0",
- "gauge": "^3.0.0",
- "set-blocking": "^2.0.0"
- }
- },
- "node_modules/nth-check": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
- "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
- "license": "BSD-2-Clause",
- "dependencies": {
- "boolbase": "^1.0.0"
- },
- "funding": {
- "url": "https://github.com/fb55/nth-check?sponsor=1"
- }
- },
- "node_modules/object-assign": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-inspect": {
- "version": "1.13.4",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
- "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object-keys": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
- "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/omggif": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz",
- "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/on-finished": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
- "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
- "license": "MIT",
- "dependencies": {
- "ee-first": "1.1.1"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/on-headers": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
- "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/once": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
- "license": "ISC",
- "dependencies": {
- "wrappy": "1"
- }
- },
- "node_modules/open": {
- "version": "7.4.2",
- "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
- "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-docker": "^2.0.0",
- "is-wsl": "^2.1.1"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/optionator": {
- "version": "0.9.4",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
- "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "deep-is": "^0.1.3",
- "fast-levenshtein": "^2.0.6",
- "levn": "^0.4.1",
- "prelude-ls": "^1.2.1",
- "type-check": "^0.4.0",
- "word-wrap": "^1.2.5"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/p-limit": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
- "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "yocto-queue": "^0.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-locate": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
- "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "p-limit": "^3.0.2"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/p-map": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
- "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "aggregate-error": "^3.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "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==",
- "license": "BlueOak-1.0.0"
- },
- "node_modules/pako": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
- "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
- "license": "(MIT AND Zlib)",
- "optional": true
- },
- "node_modules/parent-module": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
- "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "callsites": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/parse-bmfont-ascii": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz",
- "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/parse-bmfont-binary": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz",
- "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/parse-bmfont-xml": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz",
- "integrity": "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "xml-parse-from-string": "^1.0.0",
- "xml2js": "^0.5.0"
- }
- },
- "node_modules/parse5": {
- "version": "7.3.0",
- "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
- "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
- "license": "MIT",
- "dependencies": {
- "entities": "^6.0.0"
- },
- "funding": {
- "url": "https://github.com/inikulin/parse5?sponsor=1"
- }
- },
- "node_modules/parse5-htmlparser2-tree-adapter": {
- "version": "7.1.0",
- "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
- "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
- "license": "MIT",
- "dependencies": {
- "domhandler": "^5.0.3",
- "parse5": "^7.0.0"
- },
- "funding": {
- "url": "https://github.com/inikulin/parse5?sponsor=1"
- }
- },
- "node_modules/parse5-parser-stream": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
- "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
- "license": "MIT",
- "dependencies": {
- "parse5": "^7.0.0"
- },
- "funding": {
- "url": "https://github.com/inikulin/parse5?sponsor=1"
- }
- },
- "node_modules/parse5/node_modules/entities": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
- "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=0.12"
- },
- "funding": {
- "url": "https://github.com/fb55/entities?sponsor=1"
- }
- },
- "node_modules/parseurl": {
- "version": "1.3.3",
- "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
- "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/patch-package": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz",
- "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@yarnpkg/lockfile": "^1.1.0",
- "chalk": "^4.1.2",
- "ci-info": "^3.7.0",
- "cross-spawn": "^7.0.3",
- "find-yarn-workspace-root": "^2.0.0",
- "fs-extra": "^10.0.0",
- "json-stable-stringify": "^1.0.2",
- "klaw-sync": "^6.0.0",
- "minimist": "^1.2.6",
- "open": "^7.4.2",
- "semver": "^7.5.3",
- "slash": "^2.0.0",
- "tmp": "^0.2.4",
- "yaml": "^2.2.2"
- },
- "bin": {
- "patch-package": "index.js"
- },
- "engines": {
- "node": ">=14",
- "npm": ">5"
- }
- },
- "node_modules/patch-package/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
- }
- },
- "node_modules/path-equal": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/path-equal/-/path-equal-1.2.5.tgz",
- "integrity": "sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/path-exists": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
- "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-is-absolute": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
- "devOptional": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/path-scurry": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
- "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
- "license": "BlueOak-1.0.0",
- "dependencies": {
- "lru-cache": "^10.2.0",
- "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
- },
- "engines": {
- "node": ">=16 || 14 >=14.18"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/path-scurry/node_modules/lru-cache": {
- "version": "10.4.3",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
- "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
- "license": "ISC"
- },
- "node_modules/path-scurry/node_modules/minipass": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
- "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "license": "ISC",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
- "node_modules/path-to-regexp": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
- "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==",
- "license": "MIT",
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/peek-readable": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz",
- "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/pg": {
- "version": "8.16.3",
- "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz",
- "integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "pg-connection-string": "^2.9.1",
- "pg-pool": "^3.10.1",
- "pg-protocol": "^1.10.3",
- "pg-types": "2.2.0",
- "pgpass": "1.0.5"
- },
- "engines": {
- "node": ">= 16.0.0"
- },
- "optionalDependencies": {
- "pg-cloudflare": "^1.2.7"
- },
- "peerDependencies": {
- "pg-native": ">=3.0.1"
- },
- "peerDependenciesMeta": {
- "pg-native": {
- "optional": true
- }
- }
- },
- "node_modules/pg-cloudflare": {
- "version": "1.2.7",
- "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.7.tgz",
- "integrity": "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/pg-connection-string": {
- "version": "2.9.1",
- "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz",
- "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==",
- "license": "MIT"
- },
- "node_modules/pg-cursor": {
- "version": "2.15.3",
- "resolved": "https://registry.npmjs.org/pg-cursor/-/pg-cursor-2.15.3.tgz",
- "integrity": "sha512-eHw63TsiGtFEfAd7tOTZ+TLy+i/2ePKS20H84qCQ+aQ60pve05Okon9tKMC+YN3j6XyeFoHnaim7Lt9WVafQsA==",
- "license": "MIT",
- "peerDependencies": {
- "pg": "^8"
- }
- },
- "node_modules/pg-int8": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
- "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
- "license": "ISC",
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/pg-pool": {
- "version": "3.10.1",
- "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz",
- "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==",
- "license": "MIT",
- "peerDependencies": {
- "pg": ">=8.0"
- }
- },
- "node_modules/pg-protocol": {
- "version": "1.10.3",
- "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz",
- "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==",
- "license": "MIT"
- },
- "node_modules/pg-query-stream": {
- "version": "4.10.3",
- "resolved": "https://registry.npmjs.org/pg-query-stream/-/pg-query-stream-4.10.3.tgz",
- "integrity": "sha512-h2utrzpOIzeT9JfaqfvBbVuvCfBjH86jNfVrGGTbyepKAIOyTfDew0lAt8bbJjs9n/I5bGDl7S2sx6h5hPyJxw==",
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "pg-cursor": "^2.15.3"
- },
- "peerDependencies": {
- "pg": "^8"
- }
- },
- "node_modules/pg-types": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
- "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
- "license": "MIT",
- "dependencies": {
- "pg-int8": "1.0.1",
- "postgres-array": "~2.0.0",
- "postgres-bytea": "~1.0.0",
- "postgres-date": "~1.0.4",
- "postgres-interval": "^1.1.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/pgpass": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
- "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
- "license": "MIT",
- "dependencies": {
- "split2": "^4.1.0"
- }
- },
- "node_modules/picocolors": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
- "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
- "license": "ISC"
- },
- "node_modules/picomatch": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
- "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/pixelmatch": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.3.0.tgz",
- "integrity": "sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "pngjs": "^6.0.0"
- },
- "bin": {
- "pixelmatch": "bin/pixelmatch"
- }
- },
- "node_modules/pixelmatch/node_modules/pngjs": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz",
- "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=12.13.0"
- }
- },
- "node_modules/pkijs": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.3.3.tgz",
- "integrity": "sha512-+KD8hJtqQMYoTuL1bbGOqxb4z+nZkTAwVdNtWwe8Tc2xNbEmdJYIYoc6Qt0uF55e6YW6KuTHw1DjQ18gMhzepw==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "@noble/hashes": "1.4.0",
- "asn1js": "^3.0.6",
- "bytestreamjs": "^2.0.1",
- "pvtsutils": "^1.3.6",
- "pvutils": "^1.1.3",
- "tslib": "^2.8.1"
- },
- "engines": {
- "node": ">=16.0.0"
- }
- },
- "node_modules/pngjs": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz",
- "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=14.19.0"
- }
- },
- "node_modules/possible-typed-array-names": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
- "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/postgres-array": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
- "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/postgres-bytea": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
- "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/postgres-date": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
- "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/postgres-interval": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
- "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
- "license": "MIT",
- "dependencies": {
- "xtend": "^4.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/prebuild-install": {
- "version": "7.1.3",
- "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
- "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
- "license": "MIT",
- "dependencies": {
- "detect-libc": "^2.0.0",
- "expand-template": "^2.0.3",
- "github-from-package": "0.0.0",
- "minimist": "^1.2.3",
- "mkdirp-classic": "^0.5.3",
- "napi-build-utils": "^2.0.0",
- "node-abi": "^3.3.0",
- "pump": "^3.0.0",
- "rc": "^1.2.7",
- "simple-get": "^4.0.0",
- "tar-fs": "^2.0.0",
- "tunnel-agent": "^0.6.0"
- },
- "bin": {
- "prebuild-install": "bin.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/prelude-ls": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
- "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/prettier": {
- "version": "3.7.4",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz",
- "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==",
- "dev": true,
- "license": "MIT",
- "peer": true,
- "bin": {
- "prettier": "bin/prettier.cjs"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://github.com/prettier/prettier?sponsor=1"
- }
- },
- "node_modules/pretty-quick": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-4.2.2.tgz",
- "integrity": "sha512-uAh96tBW1SsD34VhhDmWuEmqbpfYc/B3j++5MC/6b3Cb8Ow7NJsvKFhg0eoGu2xXX+o9RkahkTK6sUdd8E7g5w==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "@pkgr/core": "^0.2.7",
- "ignore": "^7.0.5",
- "mri": "^1.2.0",
- "picocolors": "^1.1.1",
- "picomatch": "^4.0.2",
- "tinyexec": "^0.3.2",
- "tslib": "^2.8.1"
- },
- "bin": {
- "pretty-quick": "lib/cli.mjs"
- },
- "engines": {
- "node": ">=14"
- },
- "funding": {
- "url": "https://opencollective.com/pretty-quick"
- },
- "peerDependencies": {
- "prettier": "^3.0.0"
- }
- },
- "node_modules/pretty-quick/node_modules/ignore": {
- "version": "7.0.5",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
- "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/pretty-quick/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/probe-image-size": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/probe-image-size/-/probe-image-size-7.2.3.tgz",
- "integrity": "sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w==",
- "license": "MIT",
- "dependencies": {
- "lodash.merge": "^4.6.2",
- "needle": "^2.5.2",
- "stream-parser": "~0.3.1"
- }
- },
- "node_modules/process": {
- "version": "0.11.10",
- "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
- "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 0.6.0"
- }
- },
- "node_modules/promise-inflight": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
- "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
- "license": "ISC",
- "optional": true
- },
- "node_modules/promise-retry": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
- "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "err-code": "^2.0.2",
- "retry": "^0.12.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "license": "MIT",
- "dependencies": {
- "forwarded": "0.2.0",
- "ipaddr.js": "1.9.1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/proxy-from-env": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/pump": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
- "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
- "license": "MIT",
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
- "node_modules/punycode": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
- "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/punycode.js": {
- "version": "2.3.1",
- "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
- "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/pvtsutils": {
- "version": "1.3.6",
- "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz",
- "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==",
- "license": "MIT",
- "dependencies": {
- "tslib": "^2.8.1"
- }
- },
- "node_modules/pvutils": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz",
- "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==",
- "license": "MIT",
- "engines": {
- "node": ">=16.0.0"
- }
- },
- "node_modules/qs": {
- "version": "6.14.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
- "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
- "license": "BSD-3-Clause",
- "dependencies": {
- "side-channel": "^1.1.0"
- },
- "engines": {
- "node": ">=0.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/querystringify": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
- "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
- "license": "MIT"
- },
- "node_modules/range-parser": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
- "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/raw-body": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
- "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
- "license": "MIT",
- "dependencies": {
- "bytes": "~3.1.2",
- "http-errors": "~2.0.1",
- "iconv-lite": "~0.7.0",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/rc": {
- "version": "1.2.8",
- "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
- "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
- "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
- "dependencies": {
- "deep-extend": "^0.6.0",
- "ini": "~1.3.0",
- "minimist": "^1.2.0",
- "strip-json-comments": "~2.0.1"
- },
- "bin": {
- "rc": "cli.js"
- }
- },
- "node_modules/rc/node_modules/strip-json-comments": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
- "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/readable-stream": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
- "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
- "license": "MIT",
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/readable-web-to-node-stream": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz",
- "integrity": "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "readable-stream": "^4.7.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/readable-web-to-node-stream/node_modules/buffer": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
- "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
- "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",
- "optional": true,
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.2.1"
- }
- },
- "node_modules/readable-web-to-node-stream/node_modules/readable-stream": {
- "version": "4.7.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz",
- "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "abort-controller": "^3.0.0",
- "buffer": "^6.0.3",
- "events": "^3.3.0",
- "process": "^0.11.10",
- "string_decoder": "^1.3.0"
- },
- "engines": {
- "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
- }
- },
- "node_modules/reflect-metadata": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
- "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==",
- "license": "Apache-2.0"
- },
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "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==",
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/requires-port": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
- "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
- "license": "MIT"
- },
- "node_modules/resolve-from": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
- "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/retry": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
- "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 4"
- }
- },
- "node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/router": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
- "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.4.0",
- "depd": "^2.0.0",
- "is-promise": "^4.0.0",
- "parseurl": "^1.3.3",
- "path-to-regexp": "^8.0.0"
- },
- "engines": {
- "node": ">= 18"
- }
- },
- "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==",
- "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-stable-stringify": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
- "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/safer-buffer": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
- "license": "MIT"
- },
- "node_modules/sax": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz",
- "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==",
- "license": "BlueOak-1.0.0"
- },
- "node_modules/semver": {
- "version": "7.7.3",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
- "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
- "license": "ISC",
- "bin": {
- "semver": "bin/semver.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/send": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
- "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
- "license": "MIT",
- "dependencies": {
- "debug": "^4.4.3",
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "etag": "^1.8.1",
- "fresh": "^2.0.0",
- "http-errors": "^2.0.1",
- "mime-types": "^3.0.2",
- "ms": "^2.1.3",
- "on-finished": "^2.4.1",
- "range-parser": "^1.2.1",
- "statuses": "^2.0.2"
- },
- "engines": {
- "node": ">= 18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/serve-static": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
- "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
- "license": "MIT",
- "dependencies": {
- "encodeurl": "^2.0.0",
- "escape-html": "^1.0.3",
- "parseurl": "^1.3.3",
- "send": "^1.2.0"
- },
- "engines": {
- "node": ">= 18"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/express"
- }
- },
- "node_modules/set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
- "license": "ISC",
- "optional": true
- },
- "node_modules/set-function-length": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
- "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
- "license": "MIT",
- "dependencies": {
- "define-data-property": "^1.1.4",
- "es-errors": "^1.3.0",
- "function-bind": "^1.1.2",
- "get-intrinsic": "^1.2.4",
- "gopd": "^1.0.1",
- "has-property-descriptors": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/setprototypeof": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
- "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
- "license": "ISC"
- },
- "node_modules/sha.js": {
- "version": "2.4.12",
- "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz",
- "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==",
- "license": "(MIT AND BSD-3-Clause)",
- "dependencies": {
- "inherits": "^2.0.4",
- "safe-buffer": "^5.2.1",
- "to-buffer": "^1.2.0"
- },
- "bin": {
- "sha.js": "bin.js"
- },
- "engines": {
- "node": ">= 0.10"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "license": "MIT",
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "license": "MIT",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/side-channel": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
- "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3",
- "side-channel-list": "^1.0.0",
- "side-channel-map": "^1.0.1",
- "side-channel-weakmap": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-list": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
- "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
- "license": "MIT",
- "dependencies": {
- "es-errors": "^1.3.0",
- "object-inspect": "^1.13.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-map": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
- "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/side-channel-weakmap": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
- "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.2",
- "es-errors": "^1.3.0",
- "get-intrinsic": "^1.2.5",
- "object-inspect": "^1.13.3",
- "side-channel-map": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
- "license": "ISC",
- "optional": true
- },
- "node_modules/simple-concat": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
- "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
- "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/simple-get": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
- "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
- "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",
- "dependencies": {
- "decompress-response": "^6.0.0",
- "once": "^1.3.1",
- "simple-concat": "^1.0.0"
- }
- },
- "node_modules/simple-xml-to-json": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/simple-xml-to-json/-/simple-xml-to-json-1.2.3.tgz",
- "integrity": "sha512-kWJDCr9EWtZ+/EYYM5MareWj2cRnZGF93YDNpH4jQiHB+hBIZnfPFSQiVMzZOdk+zXWqTZ/9fTeQNu2DqeiudA==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=20.12.2"
- }
- },
- "node_modules/slash": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
- "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/smart-buffer": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
- "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">= 6.0.0",
- "npm": ">= 3.0.0"
- }
- },
- "node_modules/socks": {
- "version": "2.8.7",
- "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz",
- "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "ip-address": "^10.0.1",
- "smart-buffer": "^4.2.0"
- },
- "engines": {
- "node": ">= 10.0.0",
- "npm": ">= 3.0.0"
- }
- },
- "node_modules/socks-proxy-agent": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz",
- "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "agent-base": "^6.0.2",
- "debug": "^4.3.3",
- "socks": "^2.6.2"
- },
- "engines": {
- "node": ">= 10"
- }
- },
- "node_modules/split2": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
- "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
- "license": "ISC",
- "engines": {
- "node": ">= 10.x"
- }
- },
- "node_modules/sql-highlight": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/sql-highlight/-/sql-highlight-6.1.0.tgz",
- "integrity": "sha512-ed7OK4e9ywpE7pgRMkMQmZDPKSVdm0oX5IEtZiKnFucSF0zu6c80GZBe38UqHuVhTWJ9xsKgSMjCG2bml86KvA==",
- "funding": [
- "https://github.com/scriptcoded/sql-highlight?sponsor=1",
- {
- "type": "github",
- "url": "https://github.com/sponsors/scriptcoded"
- }
- ],
- "license": "MIT",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/sqlite3": {
- "version": "5.1.7",
- "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz",
- "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==",
- "hasInstallScript": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "bindings": "^1.5.0",
- "node-addon-api": "^7.0.0",
- "prebuild-install": "^7.1.1",
- "tar": "^6.1.11"
- },
- "optionalDependencies": {
- "node-gyp": "8.x"
- },
- "peerDependencies": {
- "node-gyp": "8.x"
- },
- "peerDependenciesMeta": {
- "node-gyp": {
- "optional": true
- }
- }
- },
- "node_modules/sqlite3/node_modules/node-addon-api": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
- "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
- "license": "MIT"
- },
- "node_modules/ssri": {
- "version": "8.0.1",
- "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
- "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "minipass": "^3.1.1"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/statuses": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
- "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/stream-parser": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz",
- "integrity": "sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==",
- "license": "MIT",
- "dependencies": {
- "debug": "2"
- }
- },
- "node_modules/stream-parser/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "license": "MIT",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/stream-parser/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "license": "MIT"
- },
- "node_modules/streamsearch": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
- "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
- "engines": {
- "node": ">=10.0.0"
- }
- },
- "node_modules/string_decoder": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
- "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
- "license": "MIT",
- "dependencies": {
- "safe-buffer": "~5.2.0"
- }
- },
- "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==",
- "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": {
- "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==",
- "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/strip-ansi": {
- "version": "6.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
- "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "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==",
- "license": "MIT",
- "dependencies": {
- "ansi-regex": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/strip-json-comments": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
- "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/strnum": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.2.tgz",
- "integrity": "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/NaturalIntelligence"
- }
- ],
- "license": "MIT"
- },
- "node_modules/strtok3": {
- "version": "10.3.4",
- "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz",
- "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==",
- "license": "MIT",
- "dependencies": {
- "@tokenizer/token": "^0.3.0"
- },
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/supports-color": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
- "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/tar": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
- "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
- "license": "ISC",
- "dependencies": {
- "chownr": "^2.0.0",
- "fs-minipass": "^2.0.0",
- "minipass": "^5.0.0",
- "minizlib": "^2.1.1",
- "mkdirp": "^1.0.3",
- "yallist": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/tar-fs": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
- "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==",
- "license": "MIT",
- "dependencies": {
- "chownr": "^1.1.1",
- "mkdirp-classic": "^0.5.2",
- "pump": "^3.0.0",
- "tar-stream": "^2.1.4"
- }
- },
- "node_modules/tar-fs/node_modules/chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
- "license": "ISC"
- },
- "node_modules/tar-stream": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
- "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
- "license": "MIT",
- "dependencies": {
- "bl": "^4.0.3",
- "end-of-stream": "^1.4.1",
- "fs-constants": "^1.0.0",
- "inherits": "^2.0.3",
- "readable-stream": "^3.1.1"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/tar/node_modules/minipass": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
- "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
- "license": "ISC",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/tar/node_modules/mkdirp": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
- "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
- "license": "MIT",
- "bin": {
- "mkdirp": "bin/cmd.js"
- },
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/thirty-two": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz",
- "integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==",
- "engines": {
- "node": ">=0.2.6"
- }
- },
- "node_modules/tinycolor2": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
- "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/tinyexec": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
- "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/tinyglobby": {
- "version": "0.2.15",
- "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
- "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "fdir": "^6.5.0",
- "picomatch": "^4.0.3"
- },
- "engines": {
- "node": ">=12.0.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/SuperchupuDev"
- }
- },
- "node_modules/tinyglobby/node_modules/fdir": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
- "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=12.0.0"
- },
- "peerDependencies": {
- "picomatch": "^3 || ^4"
- },
- "peerDependenciesMeta": {
- "picomatch": {
- "optional": true
- }
- }
- },
- "node_modules/tinyglobby/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",
- "peer": true,
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/jonschlinkert"
- }
- },
- "node_modules/tldts": {
- "version": "7.0.19",
- "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.19.tgz",
- "integrity": "sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==",
- "license": "MIT",
- "dependencies": {
- "tldts-core": "^7.0.19"
- },
- "bin": {
- "tldts": "bin/cli.js"
- }
- },
- "node_modules/tldts-core": {
- "version": "7.0.19",
- "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.19.tgz",
- "integrity": "sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==",
- "license": "MIT"
- },
- "node_modules/tmp": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
- "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=14.14"
- }
- },
- "node_modules/to-buffer": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz",
- "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==",
- "license": "MIT",
- "dependencies": {
- "isarray": "^2.0.5",
- "safe-buffer": "^5.2.1",
- "typed-array-buffer": "^1.0.3"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/to-regex-range": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
- "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "is-number": "^7.0.0"
- },
- "engines": {
- "node": ">=8.0"
- }
- },
- "node_modules/toidentifier": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
- "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
- "license": "MIT",
- "engines": {
- "node": ">=0.6"
- }
- },
- "node_modules/token-types": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.1.tgz",
- "integrity": "sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==",
- "license": "MIT",
- "dependencies": {
- "@borewit/text-codec": "^0.1.0",
- "@tokenizer/token": "^0.3.0",
- "ieee754": "^1.2.1"
- },
- "engines": {
- "node": ">=14.16"
- },
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/Borewit"
- }
- },
- "node_modules/tr46": {
- "version": "0.0.3",
- "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
- "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/ts-api-utils": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
- "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=18.12"
- },
- "peerDependencies": {
- "typescript": ">=4.8.4"
- }
- },
- "node_modules/ts-node": {
- "version": "10.9.2",
- "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
- "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
- "devOptional": true,
- "license": "MIT",
- "peer": true,
- "dependencies": {
- "@cspotcode/source-map-support": "^0.8.0",
- "@tsconfig/node10": "^1.0.7",
- "@tsconfig/node12": "^1.0.7",
- "@tsconfig/node14": "^1.0.0",
- "@tsconfig/node16": "^1.0.2",
- "acorn": "^8.4.1",
- "acorn-walk": "^8.1.1",
- "arg": "^4.1.0",
- "create-require": "^1.1.0",
- "diff": "^4.0.1",
- "make-error": "^1.1.1",
- "v8-compile-cache-lib": "^3.0.1",
- "yn": "3.1.1"
- },
- "bin": {
- "ts-node": "dist/bin.js",
- "ts-node-cwd": "dist/bin-cwd.js",
- "ts-node-esm": "dist/bin-esm.js",
- "ts-node-script": "dist/bin-script.js",
- "ts-node-transpile-only": "dist/bin-transpile.js",
- "ts-script": "dist/bin-script-deprecated.js"
- },
- "peerDependencies": {
- "@swc/core": ">=1.2.50",
- "@swc/wasm": ">=1.2.50",
- "@types/node": "*",
- "typescript": ">=2.7"
- },
- "peerDependenciesMeta": {
- "@swc/core": {
- "optional": true
- },
- "@swc/wasm": {
- "optional": true
- }
- }
- },
- "node_modules/tslib": {
- "version": "2.8.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
- "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
- "license": "0BSD"
- },
- "node_modules/tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
- "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
- "license": "Apache-2.0",
- "dependencies": {
- "safe-buffer": "^5.0.1"
- },
- "engines": {
- "node": "*"
- }
- },
- "node_modules/type-check": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
- "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "prelude-ls": "^1.2.1"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/type-is": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
- "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
- "license": "MIT",
- "dependencies": {
- "content-type": "^1.0.5",
- "media-typer": "^1.1.0",
- "mime-types": "^3.0.0"
- },
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/typed-array-buffer": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
- "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
- "license": "MIT",
- "dependencies": {
- "call-bound": "^1.0.3",
- "es-errors": "^1.3.0",
- "is-typed-array": "^1.1.14"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/typedarray": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
- "license": "MIT"
- },
- "node_modules/typeorm": {
- "version": "0.3.28",
- "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.28.tgz",
- "integrity": "sha512-6GH7wXhtfq2D33ZuRXYwIsl/qM5685WZcODZb7noOOcRMteM9KF2x2ap3H0EBjnSV0VO4gNAfJT5Ukp0PkOlvg==",
- "license": "MIT",
- "dependencies": {
- "@sqltools/formatter": "^1.2.5",
- "ansis": "^4.2.0",
- "app-root-path": "^3.1.0",
- "buffer": "^6.0.3",
- "dayjs": "^1.11.19",
- "debug": "^4.4.3",
- "dedent": "^1.7.0",
- "dotenv": "^16.6.1",
- "glob": "^10.5.0",
- "reflect-metadata": "^0.2.2",
- "sha.js": "^2.4.12",
- "sql-highlight": "^6.1.0",
- "tslib": "^2.8.1",
- "uuid": "^11.1.0",
- "yargs": "^17.7.2"
- },
- "bin": {
- "typeorm": "cli.js",
- "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js",
- "typeorm-ts-node-esm": "cli-ts-node-esm.js"
- },
- "engines": {
- "node": ">=16.13.0"
- },
- "funding": {
- "url": "https://opencollective.com/typeorm"
- },
- "peerDependencies": {
- "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0 || ^8.0.0",
- "@sap/hana-client": "^2.14.22",
- "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0",
- "ioredis": "^5.0.4",
- "mongodb": "^5.8.0 || ^6.0.0",
- "mssql": "^9.1.1 || ^10.0.0 || ^11.0.0 || ^12.0.0",
- "mysql2": "^2.2.5 || ^3.0.1",
- "oracledb": "^6.3.0",
- "pg": "^8.5.1",
- "pg-native": "^3.0.0",
- "pg-query-stream": "^4.0.0",
- "redis": "^3.1.1 || ^4.0.0 || ^5.0.14",
- "sql.js": "^1.4.0",
- "sqlite3": "^5.0.3",
- "ts-node": "^10.7.0",
- "typeorm-aurora-data-api-driver": "^2.0.0 || ^3.0.0"
- },
- "peerDependenciesMeta": {
- "@google-cloud/spanner": {
- "optional": true
- },
- "@sap/hana-client": {
- "optional": true
- },
- "better-sqlite3": {
- "optional": true
- },
- "ioredis": {
- "optional": true
- },
- "mongodb": {
- "optional": true
- },
- "mssql": {
- "optional": true
- },
- "mysql2": {
- "optional": true
- },
- "oracledb": {
- "optional": true
- },
- "pg": {
- "optional": true
- },
- "pg-native": {
- "optional": true
- },
- "pg-query-stream": {
- "optional": true
- },
- "redis": {
- "optional": true
- },
- "sql.js": {
- "optional": true
- },
- "sqlite3": {
- "optional": true
- },
- "ts-node": {
- "optional": true
- },
- "typeorm-aurora-data-api-driver": {
- "optional": true
- }
- }
- },
- "node_modules/typeorm/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==",
- "license": "MIT",
- "dependencies": {
- "balanced-match": "^1.0.0"
- }
- },
- "node_modules/typeorm/node_modules/buffer": {
- "version": "6.0.3",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
- "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
- "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",
- "dependencies": {
- "base64-js": "^1.3.1",
- "ieee754": "^1.2.1"
- }
- },
- "node_modules/typeorm/node_modules/dotenv": {
- "version": "16.6.1",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
- "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
- "license": "BSD-2-Clause",
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://dotenvx.com"
- }
- },
- "node_modules/typeorm/node_modules/glob": {
- "version": "10.5.0",
- "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
- "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
- "license": "ISC",
- "dependencies": {
- "foreground-child": "^3.1.0",
- "jackspeak": "^3.1.2",
- "minimatch": "^9.0.4",
- "minipass": "^7.1.2",
- "package-json-from-dist": "^1.0.0",
- "path-scurry": "^1.11.1"
- },
- "bin": {
- "glob": "dist/esm/bin.mjs"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/typeorm/node_modules/minimatch": {
- "version": "9.0.5",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
- "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
- "license": "ISC",
- "dependencies": {
- "brace-expansion": "^2.0.1"
- },
- "engines": {
- "node": ">=16 || 14 >=14.17"
- },
- "funding": {
- "url": "https://github.com/sponsors/isaacs"
- }
- },
- "node_modules/typeorm/node_modules/minipass": {
- "version": "7.1.2",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
- "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
- "license": "ISC",
- "engines": {
- "node": ">=16 || 14 >=14.17"
- }
- },
- "node_modules/typescript": {
- "version": "5.9.3",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
- "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
- "devOptional": true,
- "license": "Apache-2.0",
- "peer": true,
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/typescript-json-schema": {
- "version": "0.65.1",
- "resolved": "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.65.1.tgz",
- "integrity": "sha512-tuGH7ff2jPaUYi6as3lHyHcKpSmXIqN7/mu50x3HlYn0EHzLpmt3nplZ7EuhUkO0eqDRc9GqWNkfjgBPIS9kxg==",
- "dev": true,
- "license": "BSD-3-Clause",
- "dependencies": {
- "@types/json-schema": "^7.0.9",
- "@types/node": "^18.11.9",
- "glob": "^7.1.7",
- "path-equal": "^1.2.5",
- "safe-stable-stringify": "^2.2.0",
- "ts-node": "^10.9.1",
- "typescript": "~5.5.0",
- "yargs": "^17.1.1"
- },
- "bin": {
- "typescript-json-schema": "bin/typescript-json-schema"
- }
- },
- "node_modules/typescript-json-schema/node_modules/@types/node": {
- "version": "18.19.130",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz",
- "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==",
- "dev": true,
- "license": "MIT",
- "dependencies": {
- "undici-types": "~5.26.4"
- }
- },
- "node_modules/typescript-json-schema/node_modules/typescript": {
- "version": "5.5.4",
- "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
- "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
- "dev": true,
- "license": "Apache-2.0",
- "bin": {
- "tsc": "bin/tsc",
- "tsserver": "bin/tsserver"
- },
- "engines": {
- "node": ">=14.17"
- }
- },
- "node_modules/typescript-json-schema/node_modules/undici-types": {
- "version": "5.26.5",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
- "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
- "dev": true,
- "license": "MIT"
- },
- "node_modules/uint8array-extras": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz",
- "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/undici": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz",
- "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==",
- "license": "MIT",
- "engines": {
- "node": ">=20.18.1"
- }
- },
- "node_modules/undici-types": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
- "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
- "license": "MIT"
- },
- "node_modules/unique-filename": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
- "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "unique-slug": "^2.0.0"
- }
- },
- "node_modules/unique-slug": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
- "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "imurmurhash": "^0.1.4"
- }
- },
- "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/unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/uri-js": {
- "version": "4.4.1",
- "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
- "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
- "dev": true,
- "license": "BSD-2-Clause",
- "dependencies": {
- "punycode": "^2.1.0"
- }
- },
- "node_modules/url-join": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
- "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/url-parse": {
- "version": "1.5.10",
- "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
- "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
- "license": "MIT",
- "dependencies": {
- "querystringify": "^2.1.1",
- "requires-port": "^1.0.0"
- }
- },
- "node_modules/utif2": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz",
- "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "pako": "^1.0.11"
- }
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
- "license": "MIT"
- },
- "node_modules/uuid": {
- "version": "11.1.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
- "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
- "funding": [
- "https://github.com/sponsors/broofa",
- "https://github.com/sponsors/ctavan"
- ],
- "license": "MIT",
- "bin": {
- "uuid": "dist/esm/bin/uuid"
- }
- },
- "node_modules/v8-compile-cache-lib": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
- "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
- "devOptional": true,
- "license": "MIT"
- },
- "node_modules/vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
- "license": "MIT",
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/webcrypto-core": {
- "version": "1.8.1",
- "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.8.1.tgz",
- "integrity": "sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A==",
- "license": "MIT",
- "dependencies": {
- "@peculiar/asn1-schema": "^2.3.13",
- "@peculiar/json-schema": "^1.1.12",
- "asn1js": "^3.0.5",
- "pvtsutils": "^1.3.5",
- "tslib": "^2.7.0"
- }
- },
- "node_modules/webidl-conversions": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
- "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
- "license": "BSD-2-Clause",
- "optional": true
- },
- "node_modules/whatwg-encoding": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
- "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
- "license": "MIT",
- "dependencies": {
- "iconv-lite": "0.6.3"
- },
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/whatwg-encoding/node_modules/iconv-lite": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
- "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
- "license": "MIT",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/whatwg-mimetype": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
- "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
- "license": "MIT",
- "engines": {
- "node": ">=18"
- }
- },
- "node_modules/whatwg-url": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
- "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "tr46": "~0.0.3",
- "webidl-conversions": "^3.0.0"
- }
- },
- "node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "license": "ISC",
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
- "node_modules/which-typed-array": {
- "version": "1.1.19",
- "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
- "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
- "license": "MIT",
- "dependencies": {
- "available-typed-arrays": "^1.0.7",
- "call-bind": "^1.0.8",
- "call-bound": "^1.0.4",
- "for-each": "^0.3.5",
- "get-proto": "^1.0.1",
- "gopd": "^1.2.0",
- "has-tostringtag": "^1.0.2"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/wide-align": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
- "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
- "license": "ISC",
- "optional": true,
- "dependencies": {
- "string-width": "^1.0.2 || 2 || 3 || 4"
- }
- },
- "node_modules/word-wrap": {
- "version": "1.2.5",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
- "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
- "license": "MIT",
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "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==",
- "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/wrappy": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
- "license": "ISC"
- },
- "node_modules/wretch": {
- "version": "2.11.1",
- "resolved": "https://registry.npmjs.org/wretch/-/wretch-2.11.1.tgz",
- "integrity": "sha512-rJejp30zE8Igs4Mvo4pxXaiOKdSIGYLxyVaY+jZTlAMfQyi/hZsDwMRa9R09N0iS9Q8cLvplKfHwwyBv6XRWsg==",
- "license": "MIT",
- "engines": {
- "node": ">=14"
- }
- },
- "node_modules/ws": {
- "version": "8.18.3",
- "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
- "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
- "license": "MIT",
- "engines": {
- "node": ">=10.0.0"
- },
- "peerDependencies": {
- "bufferutil": "^4.0.1",
- "utf-8-validate": ">=5.0.2"
- },
- "peerDependenciesMeta": {
- "bufferutil": {
- "optional": true
- },
- "utf-8-validate": {
- "optional": true
- }
- }
- },
- "node_modules/xml-parse-from-string": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz",
- "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==",
- "license": "MIT",
- "optional": true
- },
- "node_modules/xml2js": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
- "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
- "license": "MIT",
- "optional": true,
- "dependencies": {
- "sax": ">=0.6.0",
- "xmlbuilder": "~11.0.0"
- },
- "engines": {
- "node": ">=4.0.0"
- }
- },
- "node_modules/xmlbuilder": {
- "version": "11.0.1",
- "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
- "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
- "license": "MIT",
- "optional": true,
- "engines": {
- "node": ">=4.0"
- }
- },
- "node_modules/xtend": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
- "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
- "license": "MIT",
- "engines": {
- "node": ">=0.4"
- }
- },
- "node_modules/y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "license": "ISC",
- "engines": {
- "node": ">=10"
- }
- },
- "node_modules/yallist": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
- "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "license": "ISC"
- },
- "node_modules/yaml": {
- "version": "2.8.2",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
- "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
- "dev": true,
- "license": "ISC",
- "bin": {
- "yaml": "bin.mjs"
- },
- "engines": {
- "node": ">= 14.6"
- },
- "funding": {
- "url": "https://github.com/sponsors/eemeli"
- }
- },
- "node_modules/yargs": {
- "version": "17.7.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
- "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
- "license": "MIT",
- "dependencies": {
- "cliui": "^8.0.1",
- "escalade": "^3.1.1",
- "get-caller-file": "^2.0.5",
- "require-directory": "^2.1.1",
- "string-width": "^4.2.3",
- "y18n": "^5.0.5",
- "yargs-parser": "^21.1.1"
- },
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yargs-parser": {
- "version": "21.1.1",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
- "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
- "license": "ISC",
- "engines": {
- "node": ">=12"
- }
- },
- "node_modules/yn": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
- "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
- "devOptional": true,
- "license": "MIT",
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/yocto-queue": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
- "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
- "dev": true,
- "license": "MIT",
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/zod": {
- "version": "3.25.76",
- "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
- "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
- "license": "MIT",
- "optional": true,
- "funding": {
- "url": "https://github.com/sponsors/colinhacks"
- }
- }
- }
+ "name": "spacebar-server",
+ "version": "1.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "spacebar-server",
+ "version": "1.0.0",
+ "hasInstallScript": true,
+ "license": "AGPL-3.0-only",
+ "dependencies": {
+ "@aws-sdk/client-s3": "^3.953.0",
+ "@toondepauw/node-zstd": "^1.2.0",
+ "ajv": "^8.17.1",
+ "ajv-formats": "^3.0.1",
+ "amqplib": "^0.10.9",
+ "bcrypt": "^6.0.0",
+ "body-parser": "^2.2.1",
+ "chalk": "^5.6.2",
+ "cheerio": "^1.1.2",
+ "cookie-parser": "^1.4.7",
+ "discord-protos": "^1.2.90",
+ "dotenv": "^17.2.3",
+ "email-providers": "^2.19.0",
+ "exif-be-gone": "^1.5.1",
+ "express": "^5.2.1",
+ "fast-zlib": "^2.0.1",
+ "fido2-lib": "^3.5.5",
+ "file-type": "^21.1.1",
+ "form-data": "^4.0.5",
+ "i18next": "^25.7.3",
+ "i18next-fs-backend": "^2.6.1",
+ "i18next-http-middleware": "^3.9.0",
+ "image-size": "^2.0.2",
+ "json-bigint": "^1.0.0",
+ "jsonwebtoken": "^9.0.3",
+ "module-alias": "^2.2.3",
+ "morgan": "^1.10.1",
+ "ms": "^2.1.3",
+ "multer": "^2.0.2",
+ "murmurhash-js": "^1.0.0",
+ "node-2fa": "^2.0.3",
+ "pg": "^8.16.3",
+ "pg-query-stream": "^4.10.3",
+ "picocolors": "^1.1.1",
+ "probe-image-size": "^7.2.3",
+ "reflect-metadata": "^0.2.2",
+ "sqlite3": "^5.1.7",
+ "tslib": "^2.8.1",
+ "typeorm": "^0.3.28",
+ "wretch": "^2.11.1",
+ "ws": "^8.18.3"
+ },
+ "devDependencies": {
+ "@eslint/eslintrc": "^3.3.3",
+ "@eslint/js": "^9.14.0",
+ "@spacebarchat/spacebar-webrtc-types": "^1.0.1",
+ "@types/amqplib": "^0.10.8",
+ "@types/bcrypt": "^6.0.0",
+ "@types/body-parser": "^1.19.6",
+ "@types/cookie-parser": "^1.4.10",
+ "@types/express": "^5.0.6",
+ "@types/i18next-node-fs-backend": "^2.1.5",
+ "@types/json-bigint": "^1.0.4",
+ "@types/jsonwebtoken": "^9.0.10",
+ "@types/module-alias": "^2.0.4",
+ "@types/morgan": "^1.9.10",
+ "@types/multer": "^2.0.0",
+ "@types/murmurhash-js": "^1.0.6",
+ "@types/node": "^24.10.4",
+ "@types/nodemailer": "^7.0.4",
+ "@types/probe-image-size": "^7.2.5",
+ "@types/sharp": "^0.31.1",
+ "@types/ws": "^8.18.1",
+ "@typescript-eslint/eslint-plugin": "^8.50.0",
+ "@typescript-eslint/parser": "^8.50.0",
+ "eslint": "^9.39.2",
+ "globals": "^16.5.0",
+ "husky": "^9.1.7",
+ "patch-package": "^8.0.1",
+ "prettier": "^3.7.4",
+ "pretty-quick": "^4.2.2",
+ "ts-node": "^10.9.2",
+ "typescript": "^5.9.3",
+ "typescript-json-schema": "^0.65.1"
+ },
+ "optionalDependencies": {
+ "@sendgrid/mail": "^8.1.6",
+ "@yukikaze-bot/erlpack": "^1.0.1",
+ "jimp": "^1.6.0",
+ "mailgun.js": "^12.4.0",
+ "node-mailjet": "^6.0.11",
+ "nodemailer": "^7.0.11"
+ }
+ },
+ "node_modules/@aws-crypto/crc32": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-5.2.0.tgz",
+ "integrity": "sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/crc32c": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz",
+ "integrity": "sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/sha1-browser": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz",
+ "integrity": "sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/supports-web-crypto": "^5.2.0",
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "@aws-sdk/util-locate-window": "^3.0.0",
+ "@smithy/util-utf8": "^2.0.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/is-array-buffer": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
+ "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-buffer-from": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
+ "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha1-browser/node_modules/@smithy/util-utf8": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
+ "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-browser": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz",
+ "integrity": "sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-js": "^5.2.0",
+ "@aws-crypto/supports-web-crypto": "^5.2.0",
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "@aws-sdk/util-locate-window": "^3.0.0",
+ "@smithy/util-utf8": "^2.0.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/is-array-buffer": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
+ "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-buffer-from": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
+ "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-browser/node_modules/@smithy/util-utf8": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
+ "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/sha256-js": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz",
+ "integrity": "sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/util": "^5.2.0",
+ "@aws-sdk/types": "^3.222.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/supports-web-crypto": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz",
+ "integrity": "sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/util": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-5.2.0.tgz",
+ "integrity": "sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "^3.222.0",
+ "@smithy/util-utf8": "^2.0.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-crypto/util/node_modules/@smithy/is-array-buffer": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz",
+ "integrity": "sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/util/node_modules/@smithy/util-buffer-from": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz",
+ "integrity": "sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-crypto/util/node_modules/@smithy/util-utf8": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-2.3.0.tgz",
+ "integrity": "sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^2.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-s3": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.953.0.tgz",
+ "integrity": "sha512-Lxxdhq5nt6ONulu1UHbIS0tVIar7itXv1m4TJfkVzuSm/yQzxIwnFkLtgW/0P5KIE+FS1yUoE2lS+dJBS1PLFw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha1-browser": "5.2.0",
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/credential-provider-node": "3.953.0",
+ "@aws-sdk/middleware-bucket-endpoint": "3.953.0",
+ "@aws-sdk/middleware-expect-continue": "3.953.0",
+ "@aws-sdk/middleware-flexible-checksums": "3.953.0",
+ "@aws-sdk/middleware-host-header": "3.953.0",
+ "@aws-sdk/middleware-location-constraint": "3.953.0",
+ "@aws-sdk/middleware-logger": "3.953.0",
+ "@aws-sdk/middleware-recursion-detection": "3.953.0",
+ "@aws-sdk/middleware-sdk-s3": "3.953.0",
+ "@aws-sdk/middleware-ssec": "3.953.0",
+ "@aws-sdk/middleware-user-agent": "3.953.0",
+ "@aws-sdk/region-config-resolver": "3.953.0",
+ "@aws-sdk/signature-v4-multi-region": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-endpoints": "3.953.0",
+ "@aws-sdk/util-user-agent-browser": "3.953.0",
+ "@aws-sdk/util-user-agent-node": "3.953.0",
+ "@smithy/config-resolver": "^4.4.4",
+ "@smithy/core": "^3.19.0",
+ "@smithy/eventstream-serde-browser": "^4.2.6",
+ "@smithy/eventstream-serde-config-resolver": "^4.3.6",
+ "@smithy/eventstream-serde-node": "^4.2.6",
+ "@smithy/fetch-http-handler": "^5.3.7",
+ "@smithy/hash-blob-browser": "^4.2.7",
+ "@smithy/hash-node": "^4.2.6",
+ "@smithy/hash-stream-node": "^4.2.6",
+ "@smithy/invalid-dependency": "^4.2.6",
+ "@smithy/md5-js": "^4.2.6",
+ "@smithy/middleware-content-length": "^4.2.6",
+ "@smithy/middleware-endpoint": "^4.3.15",
+ "@smithy/middleware-retry": "^4.4.15",
+ "@smithy/middleware-serde": "^4.2.7",
+ "@smithy/middleware-stack": "^4.2.6",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/node-http-handler": "^4.4.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.0",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.14",
+ "@smithy/util-defaults-mode-node": "^4.2.17",
+ "@smithy/util-endpoints": "^3.2.6",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-retry": "^4.2.6",
+ "@smithy/util-stream": "^4.5.7",
+ "@smithy/util-utf8": "^4.2.0",
+ "@smithy/util-waiter": "^4.2.6",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sesv2": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sesv2/-/client-sesv2-3.953.0.tgz",
+ "integrity": "sha512-8GkTGBfFB6UbaGpXt2ZgYql+prCYLBQeSQYGb+vBZ8TnU6L6badhC8g9QkCYO2ul6rm02+MBrFgcNx40NSAsoA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/credential-provider-node": "3.953.0",
+ "@aws-sdk/middleware-host-header": "3.953.0",
+ "@aws-sdk/middleware-logger": "3.953.0",
+ "@aws-sdk/middleware-recursion-detection": "3.953.0",
+ "@aws-sdk/middleware-user-agent": "3.953.0",
+ "@aws-sdk/region-config-resolver": "3.953.0",
+ "@aws-sdk/signature-v4-multi-region": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-endpoints": "3.953.0",
+ "@aws-sdk/util-user-agent-browser": "3.953.0",
+ "@aws-sdk/util-user-agent-node": "3.953.0",
+ "@smithy/config-resolver": "^4.4.4",
+ "@smithy/core": "^3.19.0",
+ "@smithy/fetch-http-handler": "^5.3.7",
+ "@smithy/hash-node": "^4.2.6",
+ "@smithy/invalid-dependency": "^4.2.6",
+ "@smithy/middleware-content-length": "^4.2.6",
+ "@smithy/middleware-endpoint": "^4.3.15",
+ "@smithy/middleware-retry": "^4.4.15",
+ "@smithy/middleware-serde": "^4.2.7",
+ "@smithy/middleware-stack": "^4.2.6",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/node-http-handler": "^4.4.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.0",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.14",
+ "@smithy/util-defaults-mode-node": "^4.2.17",
+ "@smithy/util-endpoints": "^3.2.6",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-retry": "^4.2.6",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/client-sso": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.953.0.tgz",
+ "integrity": "sha512-WU8XtORGnhy1JjTLflcGcNGU329pmwl/2claTVGp7vrgUKyreQV9Ke3BkMuUPYLOGO/Znstzc1VbUT9ORH3+WQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/middleware-host-header": "3.953.0",
+ "@aws-sdk/middleware-logger": "3.953.0",
+ "@aws-sdk/middleware-recursion-detection": "3.953.0",
+ "@aws-sdk/middleware-user-agent": "3.953.0",
+ "@aws-sdk/region-config-resolver": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-endpoints": "3.953.0",
+ "@aws-sdk/util-user-agent-browser": "3.953.0",
+ "@aws-sdk/util-user-agent-node": "3.953.0",
+ "@smithy/config-resolver": "^4.4.4",
+ "@smithy/core": "^3.19.0",
+ "@smithy/fetch-http-handler": "^5.3.7",
+ "@smithy/hash-node": "^4.2.6",
+ "@smithy/invalid-dependency": "^4.2.6",
+ "@smithy/middleware-content-length": "^4.2.6",
+ "@smithy/middleware-endpoint": "^4.3.15",
+ "@smithy/middleware-retry": "^4.4.15",
+ "@smithy/middleware-serde": "^4.2.7",
+ "@smithy/middleware-stack": "^4.2.6",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/node-http-handler": "^4.4.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.0",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.14",
+ "@smithy/util-defaults-mode-node": "^4.2.17",
+ "@smithy/util-endpoints": "^3.2.6",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-retry": "^4.2.6",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/core": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.953.0.tgz",
+ "integrity": "sha512-hnz4ukn+XupuotZcFAyCIX41QqEWSHc8zf4gN4l5qVP2M8YCyZkLLZ5t5LaWLJkUFbOUU2w4SuGpUp+5ddtSkw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/xml-builder": "3.953.0",
+ "@smithy/core": "^3.19.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/signature-v4": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.0",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-env": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.953.0.tgz",
+ "integrity": "sha512-ahOxDxvaKUf99LU9iRmRtPW2HLmsR+ix2WyzRGl1PpLltiRLMbKJHj5Tu2xyOsgLxs8tefK9D1j0SUgPk8GJ6g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-http": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.953.0.tgz",
+ "integrity": "sha512-kYQEcJpJLiT+1ZdsQDMrIs2o3YydxdAIDdLUxbIwks1+WQz2sCr9b94ld19aMZ0rejosASO0J3dfY0lt3Tfl+Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/fetch-http-handler": "^5.3.7",
+ "@smithy/node-http-handler": "^4.4.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.0",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-stream": "^4.5.7",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-ini": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.953.0.tgz",
+ "integrity": "sha512-5cy6b3VntBvhRCanwohRtR0wbKKUd6JfIsnuXImB4JcZa2iMW5tDW0LhNangYZ9wrrM7sJol6cKHtUW9LNemFQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/credential-provider-env": "3.953.0",
+ "@aws-sdk/credential-provider-http": "3.953.0",
+ "@aws-sdk/credential-provider-login": "3.953.0",
+ "@aws-sdk/credential-provider-process": "3.953.0",
+ "@aws-sdk/credential-provider-sso": "3.953.0",
+ "@aws-sdk/credential-provider-web-identity": "3.953.0",
+ "@aws-sdk/nested-clients": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/credential-provider-imds": "^4.2.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-login": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-login/-/credential-provider-login-3.953.0.tgz",
+ "integrity": "sha512-Drf4v7uBKnU/nY/qgQD9ZA2zD5gjQEatxQajQHUN54erDSQ2rB5ApNuTnc2cyNwaxURnQvO1J72mwO6P5lIpsg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/nested-clients": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-node": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.953.0.tgz",
+ "integrity": "sha512-/3gUap/QwAV/U3RPStcSjdiksDboTdcz82qajfhURhtAe9iEdoKJy7vTYqg75eX7IjpgBwLGajt0URasUofrPg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/credential-provider-env": "3.953.0",
+ "@aws-sdk/credential-provider-http": "3.953.0",
+ "@aws-sdk/credential-provider-ini": "3.953.0",
+ "@aws-sdk/credential-provider-process": "3.953.0",
+ "@aws-sdk/credential-provider-sso": "3.953.0",
+ "@aws-sdk/credential-provider-web-identity": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/credential-provider-imds": "^4.2.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-process": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.953.0.tgz",
+ "integrity": "sha512-YeqzqxzBzXnqdzn4pBuoXeCmWrXOLIu5owAowUc4dOvHmtlpXxB3beJdQ9g/Ky6fG6iaAPKO1vrCEoHNjM85Dw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-sso": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.953.0.tgz",
+ "integrity": "sha512-Kp/49vAJweixMo3q85eVpq1JO9KgKc6A+f8/8WDkN5CkMsfKQcGJZbO5JtuJfzar4pPmRKbgOeOP1qQsOmfyfw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/client-sso": "3.953.0",
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/token-providers": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/credential-provider-web-identity": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.953.0.tgz",
+ "integrity": "sha512-V8SpGVtNjQZboHjb/GLM4L3/6O/AZJFtwJ8fiBaemKMTntl8haioZlQHDklWixR9s9zthOdFsCDs1+92ndUBRw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/nested-clients": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-bucket-endpoint": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.953.0.tgz",
+ "integrity": "sha512-YHVRIOowtGIl/L2WuS83FgRlm31tU0aL1yryWaFtF+AFjA5BIeiFkxIZqaRGxJpJvFEBdohsyq6Ipv5mgWfezg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-arn-parser": "3.953.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-config-provider": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-expect-continue": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.953.0.tgz",
+ "integrity": "sha512-BQTVXrypQ0rbb7au/Hk4IS5GaJZlwk6O44Rjk6Kxb0IvGQhSurNTuesFiJx1sLbf+w+T31saPtODcfQQERqhCQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-flexible-checksums": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.953.0.tgz",
+ "integrity": "sha512-wpCoYg2ok0oSOupFiSPPiXvAhnXce2FkqMt/Bao+kyG3yx26NVG/4/PBftTDVCsJwuDvX/Fw8EuwbAXVmmYLCg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/crc32": "5.2.0",
+ "@aws-crypto/crc32c": "5.2.0",
+ "@aws-crypto/util": "5.2.0",
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/is-array-buffer": "^4.2.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-stream": "^4.5.7",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-host-header": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.953.0.tgz",
+ "integrity": "sha512-jTGhfkONav+r4E6HLOrl5SzBqDmPByUYCkyB/c/3TVb8jX3wAZx8/q9bphKpCh+G5ARi3IdbSisgkZrJYqQ19Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-location-constraint": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.953.0.tgz",
+ "integrity": "sha512-h0urrbteIQEybyIISaJfQLZ/+/lJPRzPWAQT4epvzfgv/4MKZI7K83dK7SfTwAooVKFBHiCMok2Cf0iHDt07Kw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-logger": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.953.0.tgz",
+ "integrity": "sha512-PlWdVYgcuptkIC0ZKqVUhWNtSHXJSx7U9V8J7dJjRmsXC40X7zpEycvrkzDMJjeTDGcCceYbyYAg/4X1lkcIMw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-recursion-detection": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.953.0.tgz",
+ "integrity": "sha512-cmIJx0gWeesUKK4YwgE+VQL3mpACr3/J24fbwnc1Z5tntC86b+HQFzU5vsBDw6lLwyD46dBgWdsXFh1jL+ZaFw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@aws/lambda-invoke-store": "^0.2.2",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-sdk-s3": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.953.0.tgz",
+ "integrity": "sha512-qubXS4GeDdoF7nqq2KEqW6jG7OjifwNfb/m6o5b6o7ZF2OSBr1MqyLykDWqnLjLI4NmM4qRPl5oTDGV0kBqoDA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-arn-parser": "3.953.0",
+ "@smithy/core": "^3.19.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/signature-v4": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.0",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-config-provider": "^4.2.0",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-stream": "^4.5.7",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-ssec": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-ssec/-/middleware-ssec-3.953.0.tgz",
+ "integrity": "sha512-OrhG1kcQ9zZh3NS3RovR028N0+UndQ957zF1k5HPLeFLwFwQN1uPOufzzPzAyXIIKtR69ARFsQI4mstZS4DMvw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/middleware-user-agent": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.953.0.tgz",
+ "integrity": "sha512-xZSU54cEHlIvRTUewyTAajb4WJPdbBd1mIaDYOzac07+vsfMuCREQ5CheQ3inoBfqske7QOX+mIjLpVV4azAnw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-endpoints": "3.953.0",
+ "@smithy/core": "^3.19.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/nested-clients": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/nested-clients/-/nested-clients-3.953.0.tgz",
+ "integrity": "sha512-YEBI0b/4ezNkw5W4+RBRUoueFzqEPPrnkh/3LBqeJ7RWZTymBhxlpoLo6Gfxw9LxtDgv2vZ5K5rgC4/6Ly8ADg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/sha256-browser": "5.2.0",
+ "@aws-crypto/sha256-js": "5.2.0",
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/middleware-host-header": "3.953.0",
+ "@aws-sdk/middleware-logger": "3.953.0",
+ "@aws-sdk/middleware-recursion-detection": "3.953.0",
+ "@aws-sdk/middleware-user-agent": "3.953.0",
+ "@aws-sdk/region-config-resolver": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@aws-sdk/util-endpoints": "3.953.0",
+ "@aws-sdk/util-user-agent-browser": "3.953.0",
+ "@aws-sdk/util-user-agent-node": "3.953.0",
+ "@smithy/config-resolver": "^4.4.4",
+ "@smithy/core": "^3.19.0",
+ "@smithy/fetch-http-handler": "^5.3.7",
+ "@smithy/hash-node": "^4.2.6",
+ "@smithy/invalid-dependency": "^4.2.6",
+ "@smithy/middleware-content-length": "^4.2.6",
+ "@smithy/middleware-endpoint": "^4.3.15",
+ "@smithy/middleware-retry": "^4.4.15",
+ "@smithy/middleware-serde": "^4.2.7",
+ "@smithy/middleware-stack": "^4.2.6",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/node-http-handler": "^4.4.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/smithy-client": "^4.10.0",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-body-length-node": "^4.2.1",
+ "@smithy/util-defaults-mode-browser": "^4.3.14",
+ "@smithy/util-defaults-mode-node": "^4.2.17",
+ "@smithy/util-endpoints": "^3.2.6",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-retry": "^4.2.6",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/region-config-resolver": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.953.0.tgz",
+ "integrity": "sha512-5MJgnsc+HLO+le0EK1cy92yrC7kyhGZSpaq8PcQvKs9qtXCXT5Tb6tMdkr5Y07JxYsYOV1omWBynvL6PWh08tQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/config-resolver": "^4.4.4",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/signature-v4-multi-region": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.953.0.tgz",
+ "integrity": "sha512-9xDZTrUveWHLJDiXWW7UdrjtdoqlWijQlxIWRMAlxruqdXJDSRkn6taSAs7fGRwHJfxjiDsn84Fcqwx5Lw55zg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/middleware-sdk-s3": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/signature-v4": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/token-providers": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.953.0.tgz",
+ "integrity": "sha512-4FWWR3lDDuIftmCEWpGejfkJu2J1VG2MUktChQshADXABfVfM0fsT7OYlO7Sy106nOe9upE4uQTWXg9YT/6ssw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/core": "3.953.0",
+ "@aws-sdk/nested-clients": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/types": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.953.0.tgz",
+ "integrity": "sha512-M9Iwg9kTyqTErI0vOTVVpcnTHWzS3VplQppy8MuL02EE+mJ0BIwpWfsaAPQW+/XnVpdNpWZTsHcNE29f1+hR8g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-arn-parser": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-arn-parser/-/util-arn-parser-3.953.0.tgz",
+ "integrity": "sha512-9hqdKkn4OvYzzaLryq2xnwcrPc8ziY34i9szUdgBfSqEC6pBxbY9/lLXmrgzfwMSL2Z7/v2go4Od0p5eukKLMQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-endpoints": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.953.0.tgz",
+ "integrity": "sha512-rjaS6jrFksopXvNg6YeN+D1lYwhcByORNlFuYesFvaQNtPOufbE5tJL4GJ3TMXyaY0uFR28N5BHHITPyWWfH/g==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
+ "@smithy/util-endpoints": "^3.2.6",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-locate-window": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.953.0.tgz",
+ "integrity": "sha512-mPxK+I1LcrgC/RSa3G5AMAn8eN2Ay0VOgw8lSRmV1jCtO+iYvNeCqOdxoJUjOW6I5BA4niIRWqVORuRP07776Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws-sdk/util-user-agent-browser": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.953.0.tgz",
+ "integrity": "sha512-UF5NeqYesWuFao+u7LJvpV1SJCaLml5BtFZKUdTnNNMeN6jvV+dW/eQoFGpXF94RCqguX0XESmRuRRPQp+/rzQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/types": "^4.10.0",
+ "bowser": "^2.11.0",
+ "tslib": "^2.6.2"
+ }
+ },
+ "node_modules/@aws-sdk/util-user-agent-node": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.953.0.tgz",
+ "integrity": "sha512-HjJ0Nq/57kg0QCjt8mwBAK6C34njKezy9ItUNcrWITzrBZv7ikQtyqM1pindAIzgLaBb7ly/0kbJqMY+NPbcJA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-sdk/middleware-user-agent": "3.953.0",
+ "@aws-sdk/types": "3.953.0",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "peerDependencies": {
+ "aws-crt": ">=1.0.0"
+ },
+ "peerDependenciesMeta": {
+ "aws-crt": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@aws-sdk/xml-builder": {
+ "version": "3.953.0",
+ "resolved": "https://registry.npmjs.org/@aws-sdk/xml-builder/-/xml-builder-3.953.0.tgz",
+ "integrity": "sha512-Zmrj21jQ2OeOJGr9spPiN00aQvXa/WUqRXcTVENhrMt+OFoSOfDFpYhUj9NQ09QmQ8KMWFoWuWW6iKurNqLvAA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "fast-xml-parser": "5.2.5",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@aws/lambda-invoke-store": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@aws/lambda-invoke-store/-/lambda-invoke-store-0.2.2.tgz",
+ "integrity": "sha512-C0NBLsIqzDIae8HFw9YIrIBsbc0xTiOtt7fAukGPnqQ/+zZNaq+4jhuccltK0QuWHBnNm/a6kLIRA6GFiM10eg==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.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/@borewit/text-codec": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/@borewit/text-codec/-/text-codec-0.1.1.tgz",
+ "integrity": "sha512-5L/uBxmjaCIX5h8Z+uu+kA9BQLkc/Wl06UGR5ajNRxu+/XjonB5i8JpgFMrPj3LXTCPA0pv8yxUvbUi+QthGGA==",
+ "license": "MIT",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "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/@cspotcode/source-map-support": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "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.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.1",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
+ "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.7",
+ "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.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
+ "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.3",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.3.tgz",
+ "integrity": "sha512-Kr+LPIUVKz2qkx1HAMH8q1q6azbqBAsXJUxBl/ODDuVPX45Z9DfwB8tPjTi6nNZ8BuM3nbJxC5zCAg5elnBUTQ==",
+ "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.1",
+ "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/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "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/eslintrc/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.39.2",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz",
+ "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
+ "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.7",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@gar/promisify": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz",
+ "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/@hexagon/base64": {
+ "version": "1.1.28",
+ "resolved": "https://registry.npmjs.org/@hexagon/base64/-/base64-1.1.28.tgz",
+ "integrity": "sha512-lhqDEAvWixy3bZ+UOYbPwUbBkwBq5C1LAJ/xPC8Oi+lL54oyakv/npbA0aU2hgCsx/1NUd4IBvV03+aUBWxerw==",
+ "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/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "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"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@isaacs/cliui/node_modules/ansi-regex": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz",
+ "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/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==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/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==",
+ "license": "MIT"
+ },
+ "node_modules/@isaacs/cliui/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==",
+ "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/@isaacs/cliui/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==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/@isaacs/cliui/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==",
+ "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/@jimp/core": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/core/-/core-1.6.0.tgz",
+ "integrity": "sha512-EQQlKU3s9QfdJqiSrZWNTxBs3rKXgO2W+GxNXDtwchF3a4IqxDheFX1ti+Env9hdJXDiYLp2jTRjlxhPthsk8w==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/file-ops": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "await-to-js": "^3.0.0",
+ "exif-parser": "^0.1.12",
+ "file-type": "^16.0.0",
+ "mime": "3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/core/node_modules/file-type": {
+ "version": "16.5.4",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-16.5.4.tgz",
+ "integrity": "sha512-/yFHK0aGjFEgDJjEKP0pWCplsPFPhwyfwevf/pVxiN0tmE4L9LmwWxWukdJSHdoCli4VgQLehjJtwQBnqmsKcw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "readable-web-to-node-stream": "^3.0.0",
+ "strtok3": "^6.2.4",
+ "token-types": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/file-type?sponsor=1"
+ }
+ },
+ "node_modules/@jimp/core/node_modules/strtok3": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-6.3.0.tgz",
+ "integrity": "sha512-fZtbhtvI9I48xDSywd/somNqgUHl2L2cstmXCCif0itOf96jeW18MBSyrLuNicYQVkvpOxkZtkzujiTJ9LW5Jw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@tokenizer/token": "^0.3.0",
+ "peek-readable": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/@jimp/core/node_modules/token-types": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/token-types/-/token-types-4.2.1.tgz",
+ "integrity": "sha512-6udB24Q737UD/SDsKAHI9FCRP7Bqc9D/MQUV02ORQg5iskjtLJlZJNdN4kKtcdtwCeWIwIHDGaUsTsCCAa8sFQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@tokenizer/token": "^0.3.0",
+ "ieee754": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/@jimp/diff": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/diff/-/diff-1.6.0.tgz",
+ "integrity": "sha512-+yUAQ5gvRC5D1WHYxjBHZI7JBRusGGSLf8AmPRPCenTzh4PA+wZ1xv2+cYqQwTfQHU5tXYOhA0xDytfHUf1Zyw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/plugin-resize": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "pixelmatch": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/file-ops": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/file-ops/-/file-ops-1.6.0.tgz",
+ "integrity": "sha512-Dx/bVDmgnRe1AlniRpCKrGRm5YvGmUwbDzt+MAkgmLGf+jvBT75hmMEZ003n9HQI/aPnm/YKnXjg/hOpzNCpHQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/js-bmp": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/js-bmp/-/js-bmp-1.6.0.tgz",
+ "integrity": "sha512-FU6Q5PC/e3yzLyBDXupR3SnL3htU7S3KEs4e6rjDP6gNEOXRFsWs6YD3hXuXd50jd8ummy+q2WSwuGkr8wi+Gw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "bmp-ts": "^1.0.9"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/js-gif": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/js-gif/-/js-gif-1.6.0.tgz",
+ "integrity": "sha512-N9CZPHOrJTsAUoWkWZstLPpwT5AwJ0wge+47+ix3++SdSL/H2QzyMqxbcDYNFe4MoI5MIhATfb0/dl/wmX221g==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "gifwrap": "^0.10.1",
+ "omggif": "^1.0.10"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/js-jpeg": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/js-jpeg/-/js-jpeg-1.6.0.tgz",
+ "integrity": "sha512-6vgFDqeusblf5Pok6B2DUiMXplH8RhIKAryj1yn+007SIAQ0khM1Uptxmpku/0MfbClx2r7pnJv9gWpAEJdMVA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "jpeg-js": "^0.4.4"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/js-png": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/js-png/-/js-png-1.6.0.tgz",
+ "integrity": "sha512-AbQHScy3hDDgMRNfG0tPjL88AV6qKAILGReIa3ATpW5QFjBKpisvUaOqhzJ7Reic1oawx3Riyv152gaPfqsBVg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "pngjs": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/js-tiff": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/js-tiff/-/js-tiff-1.6.0.tgz",
+ "integrity": "sha512-zhReR8/7KO+adijj3h0ZQUOiun3mXUv79zYEAKvE0O+rP7EhgtKvWJOZfRzdZSNv0Pu1rKtgM72qgtwe2tFvyw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "utif2": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-blit": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-blit/-/plugin-blit-1.6.0.tgz",
+ "integrity": "sha512-M+uRWl1csi7qilnSK8uxK4RJMSuVeBiO1AY0+7APnfUbQNZm6hCe0CCFv1Iyw1D/Dhb8ph8fQgm5mwM0eSxgVA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-blur": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-blur/-/plugin-blur-1.6.0.tgz",
+ "integrity": "sha512-zrM7iic1OTwUCb0g/rN5y+UnmdEsT3IfuCXCJJNs8SZzP0MkZ1eTvuwK9ZidCuMo4+J3xkzCidRwYXB5CyGZTw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/utils": "1.6.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-circle": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-circle/-/plugin-circle-1.6.0.tgz",
+ "integrity": "sha512-xt1Gp+LtdMKAXfDp3HNaG30SPZW6AQ7dtAtTnoRKorRi+5yCJjKqXRgkewS5bvj8DEh87Ko1ydJfzqS3P2tdWw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/types": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-color": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-color/-/plugin-color-1.6.0.tgz",
+ "integrity": "sha512-J5q8IVCpkBsxIXM+45XOXTrsyfblyMZg3a9eAo0P7VPH4+CrvyNQwaYatbAIamSIN1YzxmO3DkIZXzRjFSz1SA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "tinycolor2": "^1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-contain": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-contain/-/plugin-contain-1.6.0.tgz",
+ "integrity": "sha512-oN/n+Vdq/Qg9bB4yOBOxtY9IPAtEfES8J1n9Ddx+XhGBYT1/QTU/JYkGaAkIGoPnyYvmLEDqMz2SGihqlpqfzQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/plugin-blit": "1.6.0",
+ "@jimp/plugin-resize": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-cover": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-cover/-/plugin-cover-1.6.0.tgz",
+ "integrity": "sha512-Iow0h6yqSC269YUJ8HC3Q/MpCi2V55sMlbkkTTx4zPvd8mWZlC0ykrNDeAy9IJegrQ7v5E99rJwmQu25lygKLA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/plugin-crop": "1.6.0",
+ "@jimp/plugin-resize": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-crop": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-crop/-/plugin-crop-1.6.0.tgz",
+ "integrity": "sha512-KqZkEhvs+21USdySCUDI+GFa393eDIzbi1smBqkUPTE+pRwSWMAf01D5OC3ZWB+xZsNla93BDS9iCkLHA8wang==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-displace": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-displace/-/plugin-displace-1.6.0.tgz",
+ "integrity": "sha512-4Y10X9qwr5F+Bo5ME356XSACEF55485j5nGdiyJ9hYzjQP9nGgxNJaZ4SAOqpd+k5sFaIeD7SQ0Occ26uIng5Q==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-dither": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-dither/-/plugin-dither-1.6.0.tgz",
+ "integrity": "sha512-600d1RxY0pKwgyU0tgMahLNKsqEcxGdbgXadCiVCoGd6V6glyCvkNrnnwC0n5aJ56Htkj88PToSdF88tNVZEEQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/types": "1.6.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-fisheye": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-fisheye/-/plugin-fisheye-1.6.0.tgz",
+ "integrity": "sha512-E5QHKWSCBFtpgZarlmN3Q6+rTQxjirFqo44ohoTjzYVrDI6B6beXNnPIThJgPr0Y9GwfzgyarKvQuQuqCnnfbA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-flip": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-flip/-/plugin-flip-1.6.0.tgz",
+ "integrity": "sha512-/+rJVDuBIVOgwoyVkBjUFHtP+wmW0r+r5OQ2GpatQofToPVbJw1DdYWXlwviSx7hvixTWLKVgRWQ5Dw862emDg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/types": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-hash": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-hash/-/plugin-hash-1.6.0.tgz",
+ "integrity": "sha512-wWzl0kTpDJgYVbZdajTf+4NBSKvmI3bRI8q6EH9CVeIHps9VWVsUvEyb7rpbcwVLWYuzDtP2R0lTT6WeBNQH9Q==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/js-bmp": "1.6.0",
+ "@jimp/js-jpeg": "1.6.0",
+ "@jimp/js-png": "1.6.0",
+ "@jimp/js-tiff": "1.6.0",
+ "@jimp/plugin-color": "1.6.0",
+ "@jimp/plugin-resize": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "any-base": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-mask": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-mask/-/plugin-mask-1.6.0.tgz",
+ "integrity": "sha512-Cwy7ExSJMZszvkad8NV8o/Z92X2kFUFM8mcDAhNVxU0Q6tA0op2UKRJY51eoK8r6eds/qak3FQkXakvNabdLnA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/types": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-print": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-print/-/plugin-print-1.6.0.tgz",
+ "integrity": "sha512-zarTIJi8fjoGMSI/M3Xh5yY9T65p03XJmPsuNet19K/Q7mwRU6EV2pfj+28++2PV2NJ+htDF5uecAlnGyxFN2A==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/js-jpeg": "1.6.0",
+ "@jimp/js-png": "1.6.0",
+ "@jimp/plugin-blit": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "parse-bmfont-ascii": "^1.0.6",
+ "parse-bmfont-binary": "^1.0.6",
+ "parse-bmfont-xml": "^1.1.6",
+ "simple-xml-to-json": "^1.2.2",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-quantize": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-quantize/-/plugin-quantize-1.6.0.tgz",
+ "integrity": "sha512-EmzZ/s9StYQwbpG6rUGBCisc3f64JIhSH+ncTJd+iFGtGo0YvSeMdAd+zqgiHpfZoOL54dNavZNjF4otK+mvlg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "image-q": "^4.0.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-resize": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-resize/-/plugin-resize-1.6.0.tgz",
+ "integrity": "sha512-uSUD1mqXN9i1SGSz5ov3keRZ7S9L32/mAQG08wUwZiEi5FpbV0K8A8l1zkazAIZi9IJzLlTauRNU41Mi8IF9fA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-rotate": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-rotate/-/plugin-rotate-1.6.0.tgz",
+ "integrity": "sha512-JagdjBLnUZGSG4xjCLkIpQOZZ3Mjbg8aGCCi4G69qR+OjNpOeGI7N2EQlfK/WE8BEHOW5vdjSyglNqcYbQBWRw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/plugin-crop": "1.6.0",
+ "@jimp/plugin-resize": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/plugin-threshold": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/plugin-threshold/-/plugin-threshold-1.6.0.tgz",
+ "integrity": "sha512-M59m5dzLoHOVWdM41O8z9SyySzcDn43xHseOH0HavjsfQsT56GGCC4QzU1banJidbUrePhzoEdS42uFE8Fei8w==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/plugin-color": "1.6.0",
+ "@jimp/plugin-hash": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0",
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/types": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/types/-/types-1.6.0.tgz",
+ "integrity": "sha512-7UfRsiKo5GZTAATxm2qQ7jqmUXP0DxTArztllTcYdyw6Xi5oT4RaoXynVtCD4UyLK5gJgkZJcwonoijrhYFKfg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "zod": "^3.23.8"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jimp/utils": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@jimp/utils/-/utils-1.6.0.tgz",
+ "integrity": "sha512-gqFTGEosKbOkYF/WFj26jMHOI5OH2jeP1MmC/zbK6BF6VJBf8rIC5898dPfSzZEbSA0wbbV5slbntWVc5PKLFA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/types": "1.6.0",
+ "tinycolor2": "^1.6.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@mapbox/node-pre-gyp": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@mapbox/node-pre-gyp/-/node-pre-gyp-1.0.11.tgz",
+ "integrity": "sha512-Yhlar6v9WQgUp/He7BdgzOz8lqMQ8sU+jkCq7Wx8Myc5YFJLbEe7lgui/V7G1qB1DJykHSGwreceSaD60Y0PUQ==",
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "https-proxy-agent": "^5.0.0",
+ "make-dir": "^3.1.0",
+ "node-fetch": "^2.6.7",
+ "nopt": "^5.0.0",
+ "npmlog": "^5.0.1",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.5",
+ "tar": "^6.1.11"
+ },
+ "bin": {
+ "node-pre-gyp": "bin/node-pre-gyp"
+ }
+ },
+ "node_modules/@noble/hashes": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz",
+ "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@npmcli/fs": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz",
+ "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "@gar/promisify": "^1.0.1",
+ "semver": "^7.3.5"
+ }
+ },
+ "node_modules/@npmcli/move-file": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz",
+ "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==",
+ "deprecated": "This functionality has been moved to @npmcli/fs",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "mkdirp": "^1.0.4",
+ "rimraf": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@npmcli/move-file/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "license": "MIT",
+ "optional": true,
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@peculiar/asn1-schema": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.6.0.tgz",
+ "integrity": "sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg==",
+ "license": "MIT",
+ "dependencies": {
+ "asn1js": "^3.0.6",
+ "pvtsutils": "^1.3.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/json-schema": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/@peculiar/json-schema/-/json-schema-1.1.12.tgz",
+ "integrity": "sha512-coUfuoMeIB7B8/NMekxaDzLhaYmp0HZNPEjYRm9goRou8UZIC3z21s0sL9AWoCw4EG876QyO3kYrc61WNF9B/w==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/@peculiar/webcrypto": {
+ "version": "1.4.6",
+ "resolved": "https://registry.npmjs.org/@peculiar/webcrypto/-/webcrypto-1.4.6.tgz",
+ "integrity": "sha512-YBcMfqNSwn3SujUJvAaySy5tlYbYm6tVt9SKoXu8BaTdKGROiJDgPR3TXpZdAKUfklzm3lRapJEAltiMQtBgZg==",
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.3.8",
+ "@peculiar/json-schema": "^1.1.12",
+ "pvtsutils": "^1.3.5",
+ "tslib": "^2.6.2",
+ "webcrypto-core": "^1.7.9"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@pkgr/core": {
+ "version": "0.2.9",
+ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.9.tgz",
+ "integrity": "sha512-QNqXyfVS2wm9hweSYD2O7F0G06uurj9kZ96TRQE5Y9hU7+tgdZwIkbAKc5Ocy1HxEY2kuDQa6cQ1WRs/O5LFKA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/pkgr"
+ }
+ },
+ "node_modules/@protobuf-ts/runtime": {
+ "version": "2.11.1",
+ "resolved": "https://registry.npmjs.org/@protobuf-ts/runtime/-/runtime-2.11.1.tgz",
+ "integrity": "sha512-KuDaT1IfHkugM2pyz+FwiY80ejWrkH1pAtOBOZFuR6SXEFTsnb/jiQWQ1rCIrcKx2BtyxnxW6BWwsVSA/Ie+WQ==",
+ "license": "(Apache-2.0 AND BSD-3-Clause)"
+ },
+ "node_modules/@sendgrid/client": {
+ "version": "8.1.6",
+ "resolved": "https://registry.npmjs.org/@sendgrid/client/-/client-8.1.6.tgz",
+ "integrity": "sha512-/BHu0hqwXNHr2aLhcXU7RmmlVqrdfrbY9KpaNj00KZHlVOVoRxRVrpOCabIB+91ISXJ6+mLM9vpaVUhK6TwBWA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@sendgrid/helpers": "^8.0.0",
+ "axios": "^1.12.0"
+ },
+ "engines": {
+ "node": ">=12.*"
+ }
+ },
+ "node_modules/@sendgrid/helpers": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/@sendgrid/helpers/-/helpers-8.0.0.tgz",
+ "integrity": "sha512-Ze7WuW2Xzy5GT5WRx+yEv89fsg/pgy3T1E3FS0QEx0/VvRmigMZ5qyVGhJz4SxomegDkzXv/i0aFPpHKN8qdAA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "deepmerge": "^4.2.2"
+ },
+ "engines": {
+ "node": ">= 12.0.0"
+ }
+ },
+ "node_modules/@sendgrid/mail": {
+ "version": "8.1.6",
+ "resolved": "https://registry.npmjs.org/@sendgrid/mail/-/mail-8.1.6.tgz",
+ "integrity": "sha512-/ZqxUvKeEztU9drOoPC/8opEPOk+jLlB2q4+xpx6HVLq6aFu3pMpalkTpAQz8XfRfpLp8O25bh6pGPcHDCYpqg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@sendgrid/client": "^8.1.5",
+ "@sendgrid/helpers": "^8.0.0"
+ },
+ "engines": {
+ "node": ">=12.*"
+ }
+ },
+ "node_modules/@smithy/abort-controller": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-4.2.6.tgz",
+ "integrity": "sha512-P7JD4J+wxHMpGxqIg6SHno2tPkZbBUBLbPpR5/T1DEUvw/mEaINBMaPFZNM7lA+ToSCZ36j6nMHa+5kej+fhGg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/chunked-blob-reader": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader/-/chunked-blob-reader-5.2.0.tgz",
+ "integrity": "sha512-WmU0TnhEAJLWvfSeMxBNe5xtbselEO8+4wG0NtZeL8oR21WgH1xiO37El+/Y+H/Ie4SCwBy3MxYWmOYaGgZueA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/chunked-blob-reader-native": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-4.2.1.tgz",
+ "integrity": "sha512-lX9Ay+6LisTfpLid2zZtIhSEjHMZoAR5hHCR4H7tBz/Zkfr5ea8RcQ7Tk4mi0P76p4cN+Btz16Ffno7YHpKXnQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-base64": "^4.3.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/config-resolver": {
+ "version": "4.4.4",
+ "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-4.4.4.tgz",
+ "integrity": "sha512-s3U5ChS21DwU54kMmZ0UJumoS5cg0+rGVZvN6f5Lp6EbAVi0ZyP+qDSHdewfmXKUgNK1j3z45JyzulkDukrjAA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-config-provider": "^4.2.0",
+ "@smithy/util-endpoints": "^3.2.6",
+ "@smithy/util-middleware": "^4.2.6",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/core": {
+ "version": "3.19.0",
+ "resolved": "https://registry.npmjs.org/@smithy/core/-/core-3.19.0.tgz",
+ "integrity": "sha512-Y9oHXpBcXQgYHOcAEmxjkDilUbSTkgKjoHYed3WaYUH8jngq8lPWDBSpjHblJ9uOgBdy5mh3pzebrScDdYr29w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/middleware-serde": "^4.2.7",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-body-length-browser": "^4.2.0",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-stream": "^4.5.7",
+ "@smithy/util-utf8": "^4.2.0",
+ "@smithy/uuid": "^1.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/credential-provider-imds": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-4.2.6.tgz",
+ "integrity": "sha512-xBmawExyTzOjbhzkZwg+vVm/khg28kG+rj2sbGlULjFd1jI70sv/cbpaR0Ev4Yfd6CpDUDRMe64cTqR//wAOyA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-codec": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-4.2.6.tgz",
+ "integrity": "sha512-OZfsI+YRG26XZik/jKMMg37acnBSbUiK/8nETW3uM3mLj+0tMmFXdHQw1e5WEd/IHN8BGOh3te91SNDe2o4RHg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@aws-crypto/crc32": "5.2.0",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-hex-encoding": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-browser": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-4.2.6.tgz",
+ "integrity": "sha512-6OiaAaEbLB6dEkRbQyNzFSJv5HDvly3Mc6q/qcPd2uS/g3szR8wAIkh7UndAFKfMypNSTuZ6eCBmgCLR5LacTg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/eventstream-serde-universal": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-config-resolver": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-4.3.6.tgz",
+ "integrity": "sha512-xP5YXbOVRVN8A4pDnSUkEUsL9fYFU6VNhxo8tgr13YnMbf3Pn4xVr+hSyLVjS1Frfi1Uk03ET5Bwml4+0CeYEw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-node": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-node/-/eventstream-serde-node-4.2.6.tgz",
+ "integrity": "sha512-jhH7nJuaOpnTFcuZpWK9dqb6Ge2yGi1okTo0W6wkJrfwAm2vwmO74tF1v07JmrSyHBcKLQATEexclJw9K1Vj7w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/eventstream-serde-universal": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/eventstream-serde-universal": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-4.2.6.tgz",
+ "integrity": "sha512-olIfZ230B64TvPD6b0tPvrEp2eB0FkyL3KvDlqF4RVmIc/kn3orzXnV6DTQdOOW5UU+M5zKY3/BU47X420/oPw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/eventstream-codec": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/fetch-http-handler": {
+ "version": "5.3.7",
+ "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-5.3.7.tgz",
+ "integrity": "sha512-fcVap4QwqmzQwQK9QU3keeEpCzTjnP9NJ171vI7GnD7nbkAIcP9biZhDUx88uRH9BabSsQDS0unUps88uZvFIQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/querystring-builder": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-base64": "^4.3.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-blob-browser": {
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-blob-browser/-/hash-blob-browser-4.2.7.tgz",
+ "integrity": "sha512-CIbCTGGX5CI7tfewBPSYD9ycp2Vb2GW5xnXD1n7GcO9mu37EN7A6DvCHM9MX7pOeS1adMn5D+1yRwI3eABVbcA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/chunked-blob-reader": "^5.2.0",
+ "@smithy/chunked-blob-reader-native": "^4.2.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-node": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-4.2.6.tgz",
+ "integrity": "sha512-k3Dy9VNR37wfMh2/1RHkFf/e0rMyN0pjY0FdyY6ItJRjENYyVPRMwad6ZR1S9HFm6tTuIOd9pqKBmtJ4VHxvxg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-buffer-from": "^4.2.0",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/hash-stream-node": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/hash-stream-node/-/hash-stream-node-4.2.6.tgz",
+ "integrity": "sha512-+3T8LkH39YIhYHsv/Ec8lF+92nykZpU+XMBvAyXF/uLcTp86pxa5oSJk1vzaRY9N++qgDLYjzJ6OVbtAgDGwfw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/invalid-dependency": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-4.2.6.tgz",
+ "integrity": "sha512-E4t/V/q2T46RY21fpfznd1iSLTvCXKNKo4zJ1QuEFN4SE9gKfu2vb6bgq35LpufkQ+SETWIC7ZAf2GGvTlBaMQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/is-array-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-4.2.0.tgz",
+ "integrity": "sha512-DZZZBvC7sjcYh4MazJSGiWMI2L7E0oCiRHREDzIxi/M2LY79/21iXt6aPLHge82wi5LsuRF5A06Ds3+0mlh6CQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/md5-js": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/md5-js/-/md5-js-4.2.6.tgz",
+ "integrity": "sha512-ZXeh8UmH31JdcNsrQ1o9v1IVuva9JFwxIc6zTMxWX7wcmWvVR7Ai9aUEw5LraNKqdkAsb06clpM2sRH4Iy55Sg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-content-length": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-4.2.6.tgz",
+ "integrity": "sha512-0cjqjyfj+Gls30ntq45SsBtqF3dfJQCeqQPyGz58Pk8OgrAr5YiB7ZvDzjCA94p4r6DCI4qLm7FKobqBjf515w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-endpoint": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-4.4.0.tgz",
+ "integrity": "sha512-M6qWfUNny6NFNy8amrCGIb9TfOMUkHVtg9bHtEFGRgfH7A7AtPpn/fcrToGPjVDK1ECuMVvqGQOXcZxmu9K+7A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.19.0",
+ "@smithy/middleware-serde": "^4.2.7",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/url-parser": "^4.2.6",
+ "@smithy/util-middleware": "^4.2.6",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-retry": {
+ "version": "4.4.16",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-4.4.16.tgz",
+ "integrity": "sha512-XPpNhNRzm3vhYm7YCsyw3AtmWggJbg1wNGAoqb7NBYr5XA5isMRv14jgbYyUV6IvbTBFZQdf2QpeW43LrRdStQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/service-error-classification": "^4.2.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-retry": "^4.2.6",
+ "@smithy/uuid": "^1.1.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-serde": {
+ "version": "4.2.7",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-4.2.7.tgz",
+ "integrity": "sha512-PFMVHVPgtFECeu4iZ+4SX6VOQT0+dIpm4jSPLLL6JLSkp9RohGqKBKD0cbiXdeIFS08Forp0UHI6kc0gIHenSA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/middleware-stack": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-4.2.6.tgz",
+ "integrity": "sha512-JSbALU3G+JS4kyBZPqnJ3hxIYwOVRV7r9GNQMS6j5VsQDo5+Es5nddLfr9TQlxZLNHPvKSh+XSB0OuWGfSWFcA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/node-config-provider": {
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-4.3.6.tgz",
+ "integrity": "sha512-fYEyL59Qe82Ha1p97YQTMEQPJYmBS+ux76foqluaTVWoG9Px5J53w6NvXZNE3wP7lIicLDF7Vj1Em18XTX7fsA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/shared-ini-file-loader": "^4.4.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/node-http-handler": {
+ "version": "4.4.6",
+ "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-4.4.6.tgz",
+ "integrity": "sha512-Gsb9jf4ido5BhPfani4ggyrKDd3ZK+vTFWmUaZeFg5G3E5nhFmqiTzAIbHqmPs1sARuJawDiGMGR/nY+Gw6+aQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/abort-controller": "^4.2.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/querystring-builder": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/property-provider": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-4.2.6.tgz",
+ "integrity": "sha512-a/tGSLPtaia2krbRdwR4xbZKO8lU67DjMk/jfY4QKt4PRlKML+2tL/gmAuhNdFDioO6wOq0sXkfnddNFH9mNUA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/protocol-http": {
+ "version": "5.3.6",
+ "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-5.3.6.tgz",
+ "integrity": "sha512-qLRZzP2+PqhE3OSwvY2jpBbP0WKTZ9opTsn+6IWYI0SKVpbG+imcfNxXPq9fj5XeaUTr7odpsNpK6dmoiM1gJQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/querystring-builder": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-4.2.6.tgz",
+ "integrity": "sha512-MeM9fTAiD3HvoInK/aA8mgJaKQDvm8N0dKy6EiFaCfgpovQr4CaOkJC28XqlSRABM+sHdSQXbC8NZ0DShBMHqg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-uri-escape": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/querystring-parser": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-4.2.6.tgz",
+ "integrity": "sha512-YmWxl32SQRw/kIRccSOxzS/Ib8/b5/f9ex0r5PR40jRJg8X1wgM3KrR2In+8zvOGVhRSXgvyQpw9yOSlmfmSnA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/service-error-classification": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-4.2.6.tgz",
+ "integrity": "sha512-Q73XBrzJlGTut2nf5RglSntHKgAG0+KiTJdO5QQblLfr4TdliGwIAha1iZIjwisc3rA5ulzqwwsYC6xrclxVQg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/shared-ini-file-loader": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-4.4.1.tgz",
+ "integrity": "sha512-tph+oQYPbpN6NamF030hx1gb5YN2Plog+GLaRHpoEDwp8+ZPG26rIJvStG9hkWzN2HBn3HcWg0sHeB0tmkYzqA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/signature-v4": {
+ "version": "5.3.6",
+ "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-5.3.6.tgz",
+ "integrity": "sha512-P1TXDHuQMadTMTOBv4oElZMURU4uyEhxhHfn+qOc2iofW9Rd4sZtBGx58Lzk112rIGVEYZT8eUMK4NftpewpRA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^4.2.0",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-hex-encoding": "^4.2.0",
+ "@smithy/util-middleware": "^4.2.6",
+ "@smithy/util-uri-escape": "^4.2.0",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/smithy-client": {
+ "version": "4.10.1",
+ "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-4.10.1.tgz",
+ "integrity": "sha512-1ovWdxzYprhq+mWqiGZlt3kF69LJthuQcfY9BIyHx9MywTFKzFapluku1QXoaBB43GCsLDxNqS+1v30ure69AA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/core": "^3.19.0",
+ "@smithy/middleware-endpoint": "^4.4.0",
+ "@smithy/middleware-stack": "^4.2.6",
+ "@smithy/protocol-http": "^5.3.6",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-stream": "^4.5.7",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/types": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/@smithy/types/-/types-4.10.0.tgz",
+ "integrity": "sha512-K9mY7V/f3Ul+/Gz4LJANZ3vJ/yiBIwCyxe0sPT4vNJK63Srvd+Yk1IzP0t+nE7XFSpIGtzR71yljtnqpUTYFlQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/url-parser": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-4.2.6.tgz",
+ "integrity": "sha512-tVoyzJ2vXp4R3/aeV4EQjBDmCuWxRa8eo3KybL7Xv4wEM16nObYh7H1sNfcuLWHAAAzb0RVyxUz1S3sGj4X+Tg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/querystring-parser": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-base64": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-4.3.0.tgz",
+ "integrity": "sha512-GkXZ59JfyxsIwNTWFnjmFEI8kZpRNIBfxKjv09+nkAWPt/4aGaEWMM04m4sxgNVWkbt2MdSvE3KF/PfX4nFedQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^4.2.0",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-body-length-browser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-4.2.0.tgz",
+ "integrity": "sha512-Fkoh/I76szMKJnBXWPdFkQJl2r9SjPt3cMzLdOB6eJ4Pnpas8hVoWPYemX/peO0yrrvldgCUVJqOAjUrOLjbxg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-body-length-node": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-4.2.1.tgz",
+ "integrity": "sha512-h53dz/pISVrVrfxV1iqXlx5pRg3V2YWFcSQyPyXZRrZoZj4R4DeWRDo1a7dd3CPTcFi3kE+98tuNyD2axyZReA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-buffer-from": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-4.2.0.tgz",
+ "integrity": "sha512-kAY9hTKulTNevM2nlRtxAG2FQ3B2OR6QIrPY3zE5LqJy1oxzmgBGsHLWTcNhWXKchgA0WHW+mZkQrng/pgcCew==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/is-array-buffer": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-config-provider": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-4.2.0.tgz",
+ "integrity": "sha512-YEjpl6XJ36FTKmD+kRJJWYvrHeUvm5ykaUS5xK+6oXffQPHeEM4/nXlZPe+Wu0lsgRUcNZiliYNh/y7q9c2y6Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-defaults-mode-browser": {
+ "version": "4.3.15",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-4.3.15.tgz",
+ "integrity": "sha512-LiZQVAg/oO8kueX4c+oMls5njaD2cRLXRfcjlTYjhIqmwHnCwkQO5B3dMQH0c5PACILxGAQf6Mxsq7CjlDc76A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-defaults-mode-node": {
+ "version": "4.2.18",
+ "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-4.2.18.tgz",
+ "integrity": "sha512-Kw2J+KzYm9C9Z9nY6+W0tEnoZOofstVCMTshli9jhQbQCy64rueGfKzPfuFBnVUqZD9JobxTh2DzHmPkp/Va/Q==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/config-resolver": "^4.4.4",
+ "@smithy/credential-provider-imds": "^4.2.6",
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/property-provider": "^4.2.6",
+ "@smithy/smithy-client": "^4.10.1",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-endpoints": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-3.2.6.tgz",
+ "integrity": "sha512-v60VNM2+mPvgHCBXEfMCYrQ0RepP6u6xvbAkMenfe4Mi872CqNkJzgcnQL837e8NdeDxBgrWQRTluKq5Lqdhfg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/node-config-provider": "^4.3.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-hex-encoding": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-4.2.0.tgz",
+ "integrity": "sha512-CCQBwJIvXMLKxVbO88IukazJD9a4kQ9ZN7/UMGBjBcJYvatpWk+9g870El4cB8/EJxfe+k+y0GmR9CAzkF+Nbw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-middleware": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-4.2.6.tgz",
+ "integrity": "sha512-qrvXUkxBSAFomM3/OEMuDVwjh4wtqK8D2uDZPShzIqOylPst6gor2Cdp6+XrH4dyksAWq/bE2aSDYBTTnj0Rxg==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-retry": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-4.2.6.tgz",
+ "integrity": "sha512-x7CeDQLPQ9cb6xN7fRJEjlP9NyGW/YeXWc4j/RUhg4I+H60F0PEeRc2c/z3rm9zmsdiMFzpV/rT+4UHW6KM1SA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/service-error-classification": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-stream": {
+ "version": "4.5.7",
+ "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-4.5.7.tgz",
+ "integrity": "sha512-Uuy4S5Aj4oF6k1z+i2OtIBJUns4mlg29Ph4S+CqjR+f4XXpSFVgTCYLzMszHJTicYDBxKFtwq2/QSEDSS5l02A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/fetch-http-handler": "^5.3.7",
+ "@smithy/node-http-handler": "^4.4.6",
+ "@smithy/types": "^4.10.0",
+ "@smithy/util-base64": "^4.3.0",
+ "@smithy/util-buffer-from": "^4.2.0",
+ "@smithy/util-hex-encoding": "^4.2.0",
+ "@smithy/util-utf8": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-uri-escape": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-4.2.0.tgz",
+ "integrity": "sha512-igZpCKV9+E/Mzrpq6YacdTQ0qTiLm85gD6N/IrmyDvQFA4UnU3d5g3m8tMT/6zG/vVkWSU+VxeUyGonL62DuxA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-utf8": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-4.2.0.tgz",
+ "integrity": "sha512-zBPfuzoI8xyBtR2P6WQj63Rz8i3AmfAaJLuNG8dWsfvPe8lO4aCPYLn879mEgHndZH1zQ2oXmG8O1GGzzaoZiw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/util-buffer-from": "^4.2.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/util-waiter": {
+ "version": "4.2.6",
+ "resolved": "https://registry.npmjs.org/@smithy/util-waiter/-/util-waiter-4.2.6.tgz",
+ "integrity": "sha512-xU9HwUSik9UUCJmm530yvBy0AwlQFICveKmqvaaTukKkXEAhyiBdHtSrhPrH3rH+uz0ykyaE3LdgsX86C6mDCQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@smithy/abort-controller": "^4.2.6",
+ "@smithy/types": "^4.10.0",
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@smithy/uuid": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@smithy/uuid/-/uuid-1.1.0.tgz",
+ "integrity": "sha512-4aUIteuyxtBUhVdiQqcDhKFitwfd9hqoSDYY2KRXiWtgoWJ9Bmise+KfEPDiVHWeJepvF8xJO9/9+WDIciMFFw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "tslib": "^2.6.2"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/@spacebarchat/spacebar-webrtc-types": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@spacebarchat/spacebar-webrtc-types/-/spacebar-webrtc-types-1.0.1.tgz",
+ "integrity": "sha512-WfBRUN2520w7o5vU9HNDug9alNvydQP7H/jwAy8LeHTHwlMMUw/60A54FQDIAtsahw787fR3QZ83UGjhKDzDTg==",
+ "dev": true,
+ "license": "AGPL-3.0-only"
+ },
+ "node_modules/@sqltools/formatter": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz",
+ "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==",
+ "license": "MIT"
+ },
+ "node_modules/@tokenizer/inflate": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@tokenizer/inflate/-/inflate-0.4.1.tgz",
+ "integrity": "sha512-2mAv+8pkG6GIZiF1kNg1jAjh27IDxEPKwdGul3snfztFerfPGI1LjDezZp3i7BElXompqEtPmoPx6c2wgtWsOA==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.3",
+ "token-types": "^6.1.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/@tokenizer/token": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/@tokenizer/token/-/token-0.3.0.tgz",
+ "integrity": "sha512-OvjF+z51L3ov0OyAU0duzsYuvO01PH7x4t6DJx+guahgTnBHkhJdG7soQeTSFLWN3efnHyibZ4Z8l2EuWwJN3A==",
+ "license": "MIT"
+ },
+ "node_modules/@toondepauw/node-zstd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd/-/node-zstd-1.2.0.tgz",
+ "integrity": "sha512-vVDvPUstF9gKEX+Kqp654bL+4UNus6pkmY8mlcJQpIw/Sn6sO9fl1PEwxB0d0unH5PmVfBUicf1lOXu74OLrCg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 14"
+ },
+ "optionalDependencies": {
+ "@toondepauw/node-zstd-darwin-arm64": "1.2.0",
+ "@toondepauw/node-zstd-darwin-x64": "1.2.0",
+ "@toondepauw/node-zstd-freebsd-x64": "1.2.0",
+ "@toondepauw/node-zstd-linux-arm64-gnu": "1.2.0",
+ "@toondepauw/node-zstd-linux-arm64-musl": "1.2.0",
+ "@toondepauw/node-zstd-linux-x64-gnu": "1.2.0",
+ "@toondepauw/node-zstd-linux-x64-musl": "1.2.0",
+ "@toondepauw/node-zstd-win32-x64-msvc": "1.2.0"
+ }
+ },
+ "node_modules/@toondepauw/node-zstd-darwin-arm64": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-darwin-arm64/-/node-zstd-darwin-arm64-1.2.0.tgz",
+ "integrity": "sha512-fdBGlRSrf19M1+IJ98aJCLK6/HKQRnRlhE5i6EZ7kVfD2r6h5Bq9NqHAmQ5MgwtmfB9VMmiIrQAMIxKVeT54pg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@toondepauw/node-zstd-darwin-x64": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-darwin-x64/-/node-zstd-darwin-x64-1.2.0.tgz",
+ "integrity": "sha512-ZVu4zkQUgCQ8z1lLd7/LZzIYDKL48tPguIN8L4SRfLuWWlTq2/4OT6AmchztDbe5soLCDuw64t5X5otDvgsGJA==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@toondepauw/node-zstd-freebsd-x64": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-freebsd-x64/-/node-zstd-freebsd-x64-1.2.0.tgz",
+ "integrity": "sha512-kDK+l3uP7htiWvM/klY32siEGIBk3K5Da4/DcXV2q/Vp+Ph86FWpQRzC46wJIpJB60xEU67pxFGLBH/8/RB02g==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@toondepauw/node-zstd-linux-arm64-gnu": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-linux-arm64-gnu/-/node-zstd-linux-arm64-gnu-1.2.0.tgz",
+ "integrity": "sha512-KteUWam7McA0moNiRgu7KSgPu3FE+KXuh3ObqWoco5JK53Sp4Pgr/q1IYsdN6TYYbgJMkJpof62NIbyi6tnVfg==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@toondepauw/node-zstd-linux-arm64-musl": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-linux-arm64-musl/-/node-zstd-linux-arm64-musl-1.2.0.tgz",
+ "integrity": "sha512-KjbGOXvPmorhWGD4kEVjdBz/gJgUOw1Eu0xziBwsq03URrI0XSDAY6YiJZpZtGnSjm7XonEpnBZcVwXH1HZz3Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@toondepauw/node-zstd-linux-x64-gnu": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-linux-x64-gnu/-/node-zstd-linux-x64-gnu-1.2.0.tgz",
+ "integrity": "sha512-qNJDZGd/jplK/1J+8V87dYdrviAxNt1iwI/SQ0JR3HTz5Jdbu+BnVB9oMklCc/bGWa8zTkiZkl/EwA3gtbpo+Q==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@toondepauw/node-zstd-linux-x64-musl": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-linux-x64-musl/-/node-zstd-linux-x64-musl-1.2.0.tgz",
+ "integrity": "sha512-Cw1qnMXde8caitDMbk0vWrqnVHTSK+JB/Dp3XnZghQjBrD7JLj2qNzh0eTkxNFa+nijbo8HyyslWGswCugYZCw==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@toondepauw/node-zstd-win32-x64-msvc": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@toondepauw/node-zstd-win32-x64-msvc/-/node-zstd-win32-x64-msvc-1.2.0.tgz",
+ "integrity": "sha512-7cD2/R7DLZHMxHTsQNtOX3vJCT4qd74a3nWjYYthJ89gqXwwEoC8BwttQxvHd0qCZ3S/cZ/BYoTikXMwMNmCEg==",
+ "cpu": [
+ "x64"
+ ],
+ "license": "MIT",
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/@tootallnate/once": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz",
+ "integrity": "sha512-RbzJvlNzmRq5c3O09UipeuXno4tA1FE6ikOjxZK0tuxVv3412l64l5t1W5pj4+rJq9vpkm/kwiR07aZXnsKPxw==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/@tsconfig/node10": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.12.tgz",
+ "integrity": "sha512-UCYBaeFvM11aU2y3YPZ//O5Rhj+xKyzy7mvcIoAjASbigy8mHMryP5cK7dgjlz2hWxh1g5pLw084E0a/wlUSFQ==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node12": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
+ "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node14": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
+ "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/@tsconfig/node16": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
+ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/amqplib": {
+ "version": "0.10.8",
+ "resolved": "https://registry.npmjs.org/@types/amqplib/-/amqplib-0.10.8.tgz",
+ "integrity": "sha512-vtDp8Pk1wsE/AuQ8/Rgtm6KUZYqcnTgNvEHwzCkX8rL7AGsC6zqAfKAAJhUZXFhM/Pp++tbnUHiam/8vVpPztA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/bcrypt": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/@types/bcrypt/-/bcrypt-6.0.0.tgz",
+ "integrity": "sha512-/oJGukuH3D2+D+3H4JWLaAsJ/ji86dhRidzZ/Od7H/i8g+aCmvkeCc6Ni/f9uxGLSQVCRZkX2/lqEFG2BvWtlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.6",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
+ "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.38",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
+ "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/cookie-parser": {
+ "version": "1.4.10",
+ "resolved": "https://registry.npmjs.org/@types/cookie-parser/-/cookie-parser-1.4.10.tgz",
+ "integrity": "sha512-B4xqkqfZ8Wek+rCOeRxsjMS9OgvzebEzzLYw7NHYuvzb7IdxOkI0ZHGgeEBX4PUM7QGVvNSK60T3OvWj3YfBRg==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "@types/express": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/express": {
+ "version": "5.0.6",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-5.0.6.tgz",
+ "integrity": "sha512-sKYVuV7Sv9fbPIt/442koC7+IIwK5olP1KWeD88e/idgoJqDm3JV/YUiPwkoKK92ylff2MGxSz1CSjsXelx0YA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^5.0.0",
+ "@types/serve-static": "^2"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.0.tgz",
+ "integrity": "sha512-jnHMsrd0Mwa9Cf4IdOzbz543y4XJepXrbia2T4b6+spXC2We3t1y6K44D3mR8XMFSXMCf3/l7rCgddfx7UNVBA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/http-errors": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
+ "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/i18next-node-fs-backend": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@types/i18next-node-fs-backend/-/i18next-node-fs-backend-2.1.5.tgz",
+ "integrity": "sha512-qLuS9SIlAnywXSzCIDi/TTm3DWzLKqLcd5O8K/OSX1Hif6soTu5H+GwZ9Jneoe0gRq6orwaPEe9d0dcmeAFLzA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "i18next": ">=17.0.11"
+ }
+ },
+ "node_modules/@types/json-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@types/json-bigint/-/json-bigint-1.0.4.tgz",
+ "integrity": "sha512-ydHooXLbOmxBbubnA7Eh+RpBzuaIiQjh8WGJYQB50JFGFrdxW7JzVlyEV7fAXw0T2sqJ1ysTneJbiyNLqZRAag==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/jsonwebtoken": {
+ "version": "9.0.10",
+ "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.10.tgz",
+ "integrity": "sha512-asx5hIG9Qmf/1oStypjanR7iKTv0gXQ1Ov/jfrX6kS/EO0OFni8orbmGCn0672NHR3kXHwpAwR+B368ZGN/2rA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/ms": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/module-alias": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@types/module-alias/-/module-alias-2.0.4.tgz",
+ "integrity": "sha512-5+G/QXO/DvHZw60FjvbDzO4JmlD/nG5m2/vVGt25VN1eeP3w2bCoks1Wa7VuptMPM1TxJdx6RjO70N9Fw0nZPA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/morgan": {
+ "version": "1.9.10",
+ "resolved": "https://registry.npmjs.org/@types/morgan/-/morgan-1.9.10.tgz",
+ "integrity": "sha512-sS4A1zheMvsADRVfT0lYbJ4S9lmsey8Zo2F7cnbYjWHP67Q0AwMYuuzLlkIM2N8gAbb9cubhIVFwcIN2XyYCkA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/ms": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@types/ms/-/ms-2.1.0.tgz",
+ "integrity": "sha512-GsCCIZDE/p3i96vtEqx+7dBUGXrc7zeSK3wwPHIaRThS+9OhWIXRqzs4d6k1SVU8g91DrNRWxWUGhp5KXQb2VA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/multer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@types/multer/-/multer-2.0.0.tgz",
+ "integrity": "sha512-C3Z9v9Evij2yST3RSBktxP9STm6OdMc5uR1xF1SGr98uv8dUlAL2hqwrZ3GVB3uyMyiegnscEK6PGtYvNrjTjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/express": "*"
+ }
+ },
+ "node_modules/@types/murmurhash-js": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/murmurhash-js/-/murmurhash-js-1.0.6.tgz",
+ "integrity": "sha512-P2RRwRpevEKO0FrK5xNjxBywg0Br24tEv8K2+iWg56PtcCUNGAkaaOWKBQiUpofA8H/gmgdHXrcvSgp2uXCVAQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/needle": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/@types/needle/-/needle-3.3.0.tgz",
+ "integrity": "sha512-UFIuc1gdyzAqeVUYpSL+cliw2MmU/ZUhVZKE7Zo4wPbgc8hbljeKSnn6ls6iG8r5jpegPXLUIhJ+Wb2kLVs8cg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/node": {
+ "version": "24.10.4",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-24.10.4.tgz",
+ "integrity": "sha512-vnDVpYPMzs4wunl27jHrfmwojOGKya0xyM3sH+UE5iv5uPS6vX7UIoh6m+vQc5LGBq52HBKPIn/zcSZVzeDEZg==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "undici-types": "~7.16.0"
+ }
+ },
+ "node_modules/@types/nodemailer": {
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/@types/nodemailer/-/nodemailer-7.0.4.tgz",
+ "integrity": "sha512-ee8fxWqOchH+Hv6MDDNNy028kwvVnLplrStm4Zf/3uHWw5zzo8FoYYeffpJtGs2wWysEumMH0ZIdMGMY1eMAow==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@aws-sdk/client-sesv2": "^3.839.0",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/notp": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@types/notp/-/notp-2.0.5.tgz",
+ "integrity": "sha512-ZsZS0PYUa6ZE4K3yOGerBvaxCp4ePf6ZmkFbPeilcqz2Ui/lmXox7KlRt7XZkXzqUgXhFLkc09ixyVmFLCU3gQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/probe-image-size": {
+ "version": "7.2.5",
+ "resolved": "https://registry.npmjs.org/@types/probe-image-size/-/probe-image-size-7.2.5.tgz",
+ "integrity": "sha512-9Bg6d/GNnjmhMMxadDstwrSlquuuLf0jQuPszbU6n3QUfybif3V/ryD3J2i9iaiC5JB/FU/8E41n88SM/UB+Tg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/needle": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/qs": {
+ "version": "6.14.0",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.14.0.tgz",
+ "integrity": "sha512-eOunJqu0K1923aExK6y8p6fsihYEn/BYuQ4g0CxAAgFc4b/ZLN4CrsRZ55srTdqoiLzU2B2evC+apEIxprEzkQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
+ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/send": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
+ "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/serve-static": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-2.2.0.tgz",
+ "integrity": "sha512-8mam4H1NHLtu7nmtalF7eyBH14QyOASmcxHhSfEoRyr0nP/YdoesEtU+uSRvMe96TW/HPTtkoKqQLl53N7UXMQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/sharp": {
+ "version": "0.31.1",
+ "resolved": "https://registry.npmjs.org/@types/sharp/-/sharp-0.31.1.tgz",
+ "integrity": "sha512-5nWwamN9ZFHXaYEincMSuza8nNfOof8nmO+mcI+Agx1uMUk4/pQnNIcix+9rLPXzKrm1pS34+6WRDbDV0Jn7ag==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/ws": {
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
+ "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.50.0.tgz",
+ "integrity": "sha512-O7QnmOXYKVtPrfYzMolrCTfkezCJS9+ljLdKW/+DCvRsc3UAz+sbH6Xcsv7p30+0OwUbeWfUDAQE0vpabZ3QLg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "8.50.0",
+ "@typescript-eslint/type-utils": "8.50.0",
+ "@typescript-eslint/utils": "8.50.0",
+ "@typescript-eslint/visitor-keys": "8.50.0",
+ "ignore": "^7.0.0",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.50.0",
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.50.0.tgz",
+ "integrity": "sha512-6/cmF2piao+f6wSxUsJLZjck7OQsYyRtcOZS02k7XINSNlz93v6emM8WutDQSXnroG2xwYlEVHJI+cPA7CPM3Q==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.50.0",
+ "@typescript-eslint/types": "8.50.0",
+ "@typescript-eslint/typescript-estree": "8.50.0",
+ "@typescript-eslint/visitor-keys": "8.50.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.50.0.tgz",
+ "integrity": "sha512-Cg/nQcL1BcoTijEWyx4mkVC56r8dj44bFDvBdygifuS20f3OZCHmFbjF34DPSi07kwlFvqfv/xOLnJ5DquxSGQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.50.0",
+ "@typescript-eslint/types": "^8.50.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.50.0.tgz",
+ "integrity": "sha512-xCwfuCZjhIqy7+HKxBLrDVT5q/iq7XBVBXLn57RTIIpelLtEIZHXAF/Upa3+gaCpeV1NNS5Z9A+ID6jn50VD4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.50.0",
+ "@typescript-eslint/visitor-keys": "8.50.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.50.0.tgz",
+ "integrity": "sha512-vxd3G/ybKTSlm31MOA96gqvrRGv9RJ7LGtZCn2Vrc5htA0zCDvcMqUkifcjrWNNKXHUU3WCkYOzzVSFBd0wa2w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.50.0.tgz",
+ "integrity": "sha512-7OciHT2lKCewR0mFoBrvZJ4AXTMe/sYOe87289WAViOocEmDjjv8MvIOT2XESuKj9jp8u3SZYUSh89QA4S1kQw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.50.0",
+ "@typescript-eslint/typescript-estree": "8.50.0",
+ "@typescript-eslint/utils": "8.50.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.50.0.tgz",
+ "integrity": "sha512-iX1mgmGrXdANhhITbpp2QQM2fGehBse9LbTf0sidWK6yg/NE+uhV5dfU1g6EYPlcReYmkE9QLPq/2irKAmtS9w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.50.0.tgz",
+ "integrity": "sha512-W7SVAGBR/IX7zm1t70Yujpbk+zdPq/u4soeFSknWFdXIFuWsBGBOUu/Tn/I6KHSKvSh91OiMuaSnYp3mtPt5IQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/project-service": "8.50.0",
+ "@typescript-eslint/tsconfig-utils": "8.50.0",
+ "@typescript-eslint/types": "8.50.0",
+ "@typescript-eslint/visitor-keys": "8.50.0",
+ "debug": "^4.3.4",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "tinyglobby": "^0.2.15",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/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/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.50.0.tgz",
+ "integrity": "sha512-87KgUXET09CRjGCi2Ejxy3PULXna63/bMYv72tCAlDJC3Yqwln0HiFJ3VJMst2+mEtNtZu5oFvX4qJGjKsnAgg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.7.0",
+ "@typescript-eslint/scope-manager": "8.50.0",
+ "@typescript-eslint/types": "8.50.0",
+ "@typescript-eslint/typescript-estree": "8.50.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <6.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.50.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.50.0.tgz",
+ "integrity": "sha512-Xzmnb58+Db78gT/CCj/PVCvK+zxbnsw6F+O1oheYszJbBSdEjVhQi3C/Xttzxgi/GLmpvOggRs1RFpiJ8+c34Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.50.0",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@yarnpkg/lockfile": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@yarnpkg/lockfile/-/lockfile-1.1.0.tgz",
+ "integrity": "sha512-GpSwvyXOcOOlV70vbnzjj4fW5xW/FdUF6nQEt1ENy7m4ZCczi1+/buVUPAqmGfqznsORNFzUMjctTIp8a9tuCQ==",
+ "dev": true,
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/@yukikaze-bot/erlpack": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@yukikaze-bot/erlpack/-/erlpack-1.0.1.tgz",
+ "integrity": "sha512-PCJ2lGCf8DsQtrE411PY+NTsolK48l4InNn1kcBo0iUllKZYGLqeqXEWGA/INrmwanKcoYkU4pBySqUFLQDEoA==",
+ "hasInstallScript": true,
+ "license": "Apache-2.0",
+ "optional": true,
+ "dependencies": {
+ "@mapbox/node-pre-gyp": "^1.0.5",
+ "node-addon-api": "^4.0.0"
+ }
+ },
+ "node_modules/abbrev": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz",
+ "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz",
+ "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-types": "^3.0.0",
+ "negotiator": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/acorn-walk": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
+ "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.11.0"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz",
+ "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/agentkeepalive": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.6.0.tgz",
+ "integrity": "sha512-kja8j7PjmncONqaTsB8fQ+wE2mSU2DJ9D4XKoJ5PFWIdRMa6SLSN1ff4mOr4jCbfRSsxR4keIiySJU0N9T5hIQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "humanize-ms": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/aggregate-error": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz",
+ "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "clean-stack": "^2.0.0",
+ "indent-string": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "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/ajv-formats": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-3.0.1.tgz",
+ "integrity": "sha512-8iUql50EUR+uUcdRQ3HDqa6EVyo3docL8g5WJ3FNcWmu62IbkGUue/pEyLBW8VGKKucTPgqeks4fIU1DA4yowQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/amqplib": {
+ "version": "0.10.9",
+ "resolved": "https://registry.npmjs.org/amqplib/-/amqplib-0.10.9.tgz",
+ "integrity": "sha512-jwSftI4QjS3mizvnSnOrPGYiUnm1vI2OP1iXeOUz5pb74Ua0nbf6nPyyTzuiCLEE3fMpaJORXh2K/TQ08H5xGA==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-more-ints": "~1.0.0",
+ "url-parse": "~1.5.10"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "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==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/ansis": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/ansis/-/ansis-4.2.0.tgz",
+ "integrity": "sha512-HqZ5rWlFjGiV0tDm3UxxgNRqsOTniqoKZu0pIAfh7TZQMGuZK+hH0drySty0si0QXj1ieop4+SkSfPZBPPkHig==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/any-base": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/any-base/-/any-base-1.1.0.tgz",
+ "integrity": "sha512-uMgjozySS8adZZYePpaWs8cxB9/kdzmpX6SgJZ+wbz1K5eYk5QMYDVJaZKhxyIHUdnnJkfR7SVgStgH7LkGUyg==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/app-root-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz",
+ "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/append-field": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz",
+ "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==",
+ "license": "MIT"
+ },
+ "node_modules/aproba": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/aproba/-/aproba-2.1.0.tgz",
+ "integrity": "sha512-tLIEcj5GuR2RSTnxNKdkK0dJ/GrC7P38sUkiDmDuHfsHmbagTFAxDVIBltoklXEVIQ/f14IL8IMJ5pn9Hez1Ew==",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/are-we-there-yet": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-2.0.0.tgz",
+ "integrity": "sha512-Ci/qENmwHnsYo9xKIcUJN5LeDKdJ6R1Z1j9V/J5wyq8nh/mYPEpIKJbBZXtZjG04HiK7zV/p6Vs9952MrMeUIw==",
+ "deprecated": "This package is no longer supported.",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/arg": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "dev": true,
+ "license": "Python-2.0"
+ },
+ "node_modules/asn1js": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.7.tgz",
+ "integrity": "sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "pvtsutils": "^1.3.6",
+ "pvutils": "^1.1.3",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/await-to-js": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/await-to-js/-/await-to-js-3.0.0.tgz",
+ "integrity": "sha512-zJAaP9zxTcvTHRlejau3ZOY4V7SRpiByf3/dxx2uyKxxor19tpmpV2QRsTKikckwhaPmr2dVpxxMr7jOCYVp5g==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/axios": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
+ "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.4",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "license": "MIT"
+ },
+ "node_modules/base-64": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/base-64/-/base-64-1.0.0.tgz",
+ "integrity": "sha512-kwDPIFCGx0NZHog36dj+tHiwP4QMzsZ3AgMViUBKI0+V5n4U0ufTCUMhnQ04diaRI8EX/QcPfql7zlhZ7j4zgg==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/base64-js": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz",
+ "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==",
+ "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/basic-auth": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz",
+ "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/basic-auth/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "license": "MIT"
+ },
+ "node_modules/bcrypt": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/bcrypt/-/bcrypt-6.0.0.tgz",
+ "integrity": "sha512-cU8v/EGSrnH+HnxV2z0J7/blxH8gq7Xh2JFT6Aroax7UohdmiJJlxApMxtKfuI7z68NvvVcmR78k2LbT6efhRg==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "dependencies": {
+ "node-addon-api": "^8.3.0",
+ "node-gyp-build": "^4.8.4"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "node_modules/bcrypt/node_modules/node-addon-api": {
+ "version": "8.5.0",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-8.5.0.tgz",
+ "integrity": "sha512-/bRZty2mXUIFY/xU5HLvveNHlswNJej+RnxBjOMkidWfwZzgTbPG1E3K5TOxRLOR+5hX7bSofy8yf1hZevMS8A==",
+ "license": "MIT",
+ "engines": {
+ "node": "^18 || ^20 || >= 21"
+ }
+ },
+ "node_modules/bignumber.js": {
+ "version": "9.3.1",
+ "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.3.1.tgz",
+ "integrity": "sha512-Ko0uX15oIUS7wJ3Rb30Fs6SkVbLmPBAKdlm7q9+ak9bbIeFf0MwuBsQV6z7+X768/cHsfg+WlysDWJcmthjsjQ==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/bindings": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
+ "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "file-uri-to-path": "1.0.0"
+ }
+ },
+ "node_modules/bl": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
+ }
+ },
+ "node_modules/bmp-ts": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/bmp-ts/-/bmp-ts-1.0.9.tgz",
+ "integrity": "sha512-cTEHk2jLrPyi+12M3dhpEbnnPOsaZuq7C45ylbbQIiWgDFZq4UVYPEY5mlqjvsj/6gJv9qX5sa+ebDzLXT28Vw==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/body-parser": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz",
+ "integrity": "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "^3.1.2",
+ "content-type": "^1.0.5",
+ "debug": "^4.4.3",
+ "http-errors": "^2.0.0",
+ "iconv-lite": "^0.7.0",
+ "on-finished": "^2.4.1",
+ "qs": "^6.14.0",
+ "raw-body": "^3.0.1",
+ "type-is": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "license": "ISC"
+ },
+ "node_modules/bowser": {
+ "version": "2.13.1",
+ "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.13.1.tgz",
+ "integrity": "sha512-OHawaAbjwx6rqICCKgSG0SAnT05bzd7ppyKLVUITZpANBaaMFBAsaNkto3LoQ31tyFP5kNujE8Cdx85G9VzOkw==",
+ "license": "MIT"
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "devOptional": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
+ "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",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
+ }
+ },
+ "node_modules/buffer-equal-constant-time": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz",
+ "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==",
+ "license": "BSD-3-Clause"
+ },
+ "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==",
+ "license": "MIT"
+ },
+ "node_modules/buffer-more-ints": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/buffer-more-ints/-/buffer-more-ints-1.0.0.tgz",
+ "integrity": "sha512-EMetuGFz5SLsT0QTnXzINh4Ksr+oo4i+UGTXEshiGCQWnsgSs7ZhJ8fzlwQ+OzEMs0MpDAMr1hxnblp5a4vcHg==",
+ "license": "MIT"
+ },
+ "node_modules/busboy": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz",
+ "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==",
+ "dependencies": {
+ "streamsearch": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=10.16.0"
+ }
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/bytestreamjs": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/bytestreamjs/-/bytestreamjs-2.0.1.tgz",
+ "integrity": "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==",
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/cacache": {
+ "version": "15.3.0",
+ "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz",
+ "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "@npmcli/fs": "^1.0.0",
+ "@npmcli/move-file": "^1.0.1",
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "glob": "^7.1.4",
+ "infer-owner": "^1.0.4",
+ "lru-cache": "^6.0.0",
+ "minipass": "^3.1.1",
+ "minipass-collect": "^1.0.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.2",
+ "mkdirp": "^1.0.3",
+ "p-map": "^4.0.0",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^3.0.2",
+ "ssri": "^8.0.1",
+ "tar": "^6.0.2",
+ "unique-filename": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/cacache/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "license": "MIT",
+ "optional": true,
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
+ "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.0",
+ "es-define-property": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cbor-extract": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/cbor-extract/-/cbor-extract-2.2.0.tgz",
+ "integrity": "sha512-Ig1zM66BjLfTXpNgKpvBePq271BPOvu8MR0Jl080yG7Jsl+wAZunfrwiwA+9ruzm/WEdIV5QF/bjDZTqyAIVHA==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "node-gyp-build-optional-packages": "5.1.1"
+ },
+ "bin": {
+ "download-cbor-prebuilds": "bin/download-prebuilds.js"
+ },
+ "optionalDependencies": {
+ "@cbor-extract/cbor-extract-darwin-arm64": "2.2.0",
+ "@cbor-extract/cbor-extract-darwin-x64": "2.2.0",
+ "@cbor-extract/cbor-extract-linux-arm": "2.2.0",
+ "@cbor-extract/cbor-extract-linux-arm64": "2.2.0",
+ "@cbor-extract/cbor-extract-linux-x64": "2.2.0",
+ "@cbor-extract/cbor-extract-win32-x64": "2.2.0"
+ }
+ },
+ "node_modules/cbor-x": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/cbor-x/-/cbor-x-1.6.0.tgz",
+ "integrity": "sha512-0kareyRwHSkL6ws5VXHEf8uY1liitysCVJjlmhaLG+IXLqhSaOO+t63coaso7yjwEzWZzLy8fJo06gZDVQM9Qg==",
+ "license": "MIT",
+ "optionalDependencies": {
+ "cbor-extract": "^2.2.0"
+ }
+ },
+ "node_modules/chalk": {
+ "version": "5.6.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz",
+ "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==",
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/cheerio": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.1.2.tgz",
+ "integrity": "sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==",
+ "license": "MIT",
+ "dependencies": {
+ "cheerio-select": "^2.1.0",
+ "dom-serializer": "^2.0.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.2.2",
+ "encoding-sniffer": "^0.2.1",
+ "htmlparser2": "^10.0.0",
+ "parse5": "^7.3.0",
+ "parse5-htmlparser2-tree-adapter": "^7.1.0",
+ "parse5-parser-stream": "^7.1.2",
+ "undici": "^7.12.0",
+ "whatwg-mimetype": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=20.18.1"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
+ }
+ },
+ "node_modules/cheerio-select": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
+ "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-select": "^5.1.0",
+ "css-what": "^6.1.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/chownr": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz",
+ "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/clean-stack": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz",
+ "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
+ },
+ "node_modules/color-support": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz",
+ "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==",
+ "license": "ISC",
+ "optional": true,
+ "bin": {
+ "color-support": "bin.js"
+ }
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/concat-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz",
+ "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==",
+ "engines": [
+ "node >= 6.0"
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.0.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "node_modules/console-control-strings": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz",
+ "integrity": "sha512-ty/fTekppD2fIwRvnZAVdeOiGd1c7YXEixbgJTNzqcxJWKQnjJ/V1bNEEE6hygpM3WjwHFUVK6HTjWSzV4a8sQ==",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/content-disposition": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz",
+ "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-parser": {
+ "version": "1.4.7",
+ "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.7.tgz",
+ "integrity": "sha512-nGUvgXnotP3BsjiLX2ypbQnWoGUPIIfHQNZkkC668ntrzGWEZVW70HDEB1qnNGMicPje6EttlIgzo51YSwNQGw==",
+ "license": "MIT",
+ "dependencies": {
+ "cookie": "0.7.2",
+ "cookie-signature": "1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
+ "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
+ "license": "MIT"
+ },
+ "node_modules/create-require": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/css-select": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.2.2.tgz",
+ "integrity": "sha512-TizTzUddG/xYLA3NXodFM0fSbNizXjOKhqiQQwvhlspadZokn1KDy0NZFS0wuEubIYAV5/c1/lAr0TaaFXEXzw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.1.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
+ "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/dayjs": {
+ "version": "1.11.19",
+ "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.19.tgz",
+ "integrity": "sha512-t5EcLVS6QPBNqM2z8fakk/NKel+Xzshgt8FFKAn+qwlD1pzZWxh0nVCrvFK7ZDb6XucZeF9z8C7CBWTRIVApAw==",
+ "license": "MIT"
+ },
+ "node_modules/debug": {
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decompress-response": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz",
+ "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==",
+ "license": "MIT",
+ "dependencies": {
+ "mimic-response": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/dedent": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.7.0.tgz",
+ "integrity": "sha512-HGFtf8yhuhGhqO07SV79tRp+br4MnbdjeVxotpn1QBl30pcLLCQjX5b2295ll0fv8RKDKsmWYrl05usHM9CewQ==",
+ "license": "MIT",
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-extend": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz",
+ "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "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==",
+ "license": "MIT",
+ "optional": true,
+ "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",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/delegates": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz",
+ "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz",
+ "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==",
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/diff": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz",
+ "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==",
+ "devOptional": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/discord-protos": {
+ "version": "1.2.90",
+ "resolved": "https://registry.npmjs.org/discord-protos/-/discord-protos-1.2.90.tgz",
+ "integrity": "sha512-7W57dYO3ohAseS2k46UpGq+1b8FDuXIRz0WlxoWI6cgESuIPI6DCXfwc3tDeEaps81kfyOnBrT0LdNX+TrE/oQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@protobuf-ts/runtime": "^2.9.6"
+ }
+ },
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.2.2.tgz",
+ "integrity": "sha512-6kZKyUajlDuqlHKVX1w7gyslj9MPIXzIFiz/rGu35uC1wMi+kMhQwGhl4lt9unC9Vb9INnY9Z3/ZA3+FhASLaw==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/dotenv": {
+ "version": "17.2.3",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz",
+ "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "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==",
+ "license": "MIT"
+ },
+ "node_modules/ecdsa-sig-formatter": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz",
+ "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "license": "MIT"
+ },
+ "node_modules/email-providers": {
+ "version": "2.19.0",
+ "resolved": "https://registry.npmjs.org/email-providers/-/email-providers-2.19.0.tgz",
+ "integrity": "sha512-HwDo7NLmBWXHtnXlediIbI1x+WSgTszWi35TZxlGhW49iW/dZkzC78f4RD/8osLY2Rqh62sgD2ufduKRO54Raw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "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==",
+ "license": "MIT"
+ },
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/encoding": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz",
+ "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "iconv-lite": "^0.6.2"
+ }
+ },
+ "node_modules/encoding-sniffer": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.1.tgz",
+ "integrity": "sha512-5gvq20T6vfpekVtqrYQsSCFZ1wEg5+wW0/QaZMWkFr6BqD3NfKs0rLCx4rrVlSWJeZb5NBJgVLswK/w2MWU+Gw==",
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "^0.6.3",
+ "whatwg-encoding": "^3.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
+ }
+ },
+ "node_modules/encoding-sniffer/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/encoding/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/end-of-stream": {
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
+ "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/env-paths": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz",
+ "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/err-code": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz",
+ "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "license": "MIT"
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.39.2",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz",
+ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.1",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.39.2",
+ "@eslint/plugin-kit": "^0.4.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/eslint/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree/node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/exif-be-gone": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/exif-be-gone/-/exif-be-gone-1.5.1.tgz",
+ "integrity": "sha512-+fV9PoomNVR5Hmp0n1c0ZVl78/GaFrpnC0t7q4F9Aey8NcL+7Lutcez8KY2Ni30NWpvgLXawqiRFFwtdo4QgFg==",
+ "license": "ISC",
+ "bin": {
+ "exif-be-gone": "cli.js"
+ }
+ },
+ "node_modules/exif-parser": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/exif-parser/-/exif-parser-0.1.12.tgz",
+ "integrity": "sha512-c2bQfLNbMzLPmzQuOr8fy0csy84WmwnER81W88DzTp9CYNPJ6yzOj2EZAh9pywYpqHnshVLHQJ8WzldAyfY+Iw==",
+ "optional": true
+ },
+ "node_modules/expand-template": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/expand-template/-/expand-template-2.0.3.tgz",
+ "integrity": "sha512-XYfuKMvj4O35f/pOXLObndIRvyQ+/+6AhODh+OKWj9S9498pHHn/IMszH+gt0fBCRWMNfk1ZSp5x3AifmnI2vg==",
+ "license": "(MIT OR WTFPL)",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/express": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz",
+ "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==",
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "^2.0.0",
+ "body-parser": "^2.2.1",
+ "content-disposition": "^1.0.0",
+ "content-type": "^1.0.5",
+ "cookie": "^0.7.1",
+ "cookie-signature": "^1.2.1",
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "finalhandler": "^2.1.0",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.0",
+ "merge-descriptors": "^2.0.0",
+ "mime-types": "^3.0.0",
+ "on-finished": "^2.4.1",
+ "once": "^1.4.0",
+ "parseurl": "^1.3.3",
+ "proxy-addr": "^2.0.7",
+ "qs": "^6.14.0",
+ "range-parser": "^1.2.1",
+ "router": "^2.2.0",
+ "send": "^1.1.0",
+ "serve-static": "^2.2.0",
+ "statuses": "^2.0.1",
+ "type-is": "^2.0.1",
+ "vary": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/express/node_modules/cookie-signature": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz",
+ "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.6.0"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "license": "MIT"
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/fast-xml-parser": {
+ "version": "5.2.5",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-5.2.5.tgz",
+ "integrity": "sha512-pfX9uG9Ki0yekDHx2SiuRIyFdyAr1kMIMitPvb0YBo8SUfKvia7w7FIyd/l6av85pFYRhZscS75MwMnbvY+hcQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "strnum": "^2.1.0"
+ },
+ "bin": {
+ "fxparser": "src/cli/cli.js"
+ }
+ },
+ "node_modules/fast-zlib": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/fast-zlib/-/fast-zlib-2.0.1.tgz",
+ "integrity": "sha512-DCoYgNagM2Bt1VIpXpdGnRx4LzqJeYG0oh6Nf/7cWo6elTXkFGMw9CrRCYYUIapYNrozYMoyDRflx9mgT3Awyw==",
+ "license": "MIT",
+ "funding": {
+ "type": "patreon",
+ "url": "https://patreon.com/timotejroiko"
+ }
+ },
+ "node_modules/fido2-lib": {
+ "version": "3.5.5",
+ "resolved": "https://registry.npmjs.org/fido2-lib/-/fido2-lib-3.5.5.tgz",
+ "integrity": "sha512-XEXa+kRyQEq4Yse5bG+4rrvsxfOMp+ihzI2Uxi0/6OJ4ZaUdNKl8fBGDoyFZu/TKjCJGcL182/jf+UoyMSf9ow==",
+ "license": "MIT",
+ "dependencies": {
+ "@hexagon/base64": "~1.1.28",
+ "@peculiar/webcrypto": "~1.4.6",
+ "asn1js": "~3.0.6",
+ "cbor-x": "~1.6.0",
+ "jose": "^6.1.0",
+ "pkijs": "~3.3.2",
+ "punycode.js": "^2.3.1",
+ "tldts": "~7.0.17"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/file-type": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/file-type/-/file-type-21.1.1.tgz",
+ "integrity": "sha512-ifJXo8zUqbQ/bLbl9sFoqHNTNWbnPY1COImFfM6CCy7z+E+jC1eY9YfOKkx0fckIg+VljAy2/87T61fp0+eEkg==",
+ "license": "MIT",
+ "dependencies": {
+ "@tokenizer/inflate": "^0.4.1",
+ "strtok3": "^10.3.4",
+ "token-types": "^6.1.1",
+ "uint8array-extras": "^1.4.0"
+ },
+ "engines": {
+ "node": ">=20"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/file-type?sponsor=1"
+ }
+ },
+ "node_modules/file-uri-to-path": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
+ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
+ "license": "MIT"
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz",
+ "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "on-finished": "^2.4.1",
+ "parseurl": "^1.3.3",
+ "statuses": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/find-yarn-workspace-root": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/find-yarn-workspace-root/-/find-yarn-workspace-root-2.0.0.tgz",
+ "integrity": "sha512-1IMnbjt4KzsQfnhnzNd8wUEgXZ44IzZaZmnLYx7D5FZlaHt2gW20Cri8Q+E/t5tIj4+epTBub+2Zxu/vNILzqQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "micromatch": "^4.0.2"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.11",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz",
+ "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/for-each": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "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==",
+ "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/foreground-child/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==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/form-data/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz",
+ "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/fs-constants": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz",
+ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
+ "license": "MIT"
+ },
+ "node_modules/fs-extra": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz",
+ "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/fs-minipass": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz",
+ "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==",
+ "license": "ISC",
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "devOptional": true,
+ "license": "ISC"
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gauge": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz",
+ "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==",
+ "deprecated": "This package is no longer supported.",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.2",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.1",
+ "object-assign": "^4.1.1",
+ "signal-exit": "^3.0.0",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "license": "ISC",
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/gifwrap": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/gifwrap/-/gifwrap-0.10.1.tgz",
+ "integrity": "sha512-2760b1vpJHNmLzZ/ubTtNnEx5WApN/PYWJvXvgS+tL1egTTthayFYIQQNi136FLEDcN/IyEY2EcGpIITD6eYUw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "image-q": "^4.0.0",
+ "omggif": "^1.0.10"
+ }
+ },
+ "node_modules/github-from-package": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/github-from-package/-/github-from-package-0.0.0.tgz",
+ "integrity": "sha512-SyHy3T1v2NUXn29OsWdxmK6RwHD+vkj3v8en8AOBZ1wBQ/hCAQ5bAQTD02kW4W9tUp/3Qh6J8r9EvntiyCmOOw==",
+ "license": "MIT"
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "devOptional": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "16.5.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz",
+ "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "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==",
+ "devOptional": true,
+ "license": "ISC"
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "license": "MIT",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-unicode": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz",
+ "integrity": "sha512-8Rf9Y83NBReMnx0gFzA8JImQACstCYWUplepDa9xprwwtmgEZUF0h/i5xSA625zB/I37EtrswSST6OXxwaaIJQ==",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/htmlparser2": {
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-10.0.0.tgz",
+ "integrity": "sha512-TwAZM+zE5Tq3lrEHvOlvwgj1XLWQCtaaibSN11Q+gGBAS7Y1uZSWwXXRe4iF6OXnaq1riyQAPFOBtYc77Mxq0g==",
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.2.1",
+ "entities": "^6.0.0"
+ }
+ },
+ "node_modules/htmlparser2/node_modules/entities": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
+ "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/http-cache-semantics": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.2.0.tgz",
+ "integrity": "sha512-dTxcvPXqPvXBQpq5dUr6mEMJX4oIEFv6bwom3FDwKRDsuIjjJGANqhBuoAn9c1RQJIdAKav33ED65E2ys+87QQ==",
+ "license": "BSD-2-Clause",
+ "optional": true
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
+ "license": "MIT",
+ "dependencies": {
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/http-proxy-agent": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz",
+ "integrity": "sha512-k0zdNgqWTGA6aeIRVpvfVob4fL52dTfaehylg0Y4UvSySvOq/Y+BOyPrgpUrA7HylqvU8vIZGsRuXmspskV0Tg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@tootallnate/once": "1",
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz",
+ "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "agent-base": "6",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "ms": "^2.0.0"
+ }
+ },
+ "node_modules/husky": {
+ "version": "9.1.7",
+ "resolved": "https://registry.npmjs.org/husky/-/husky-9.1.7.tgz",
+ "integrity": "sha512-5gs5ytaNjBrh5Ow3zrvdUUY+0VxIuWVL4i9irt6friV+BqdCfmV11CQTWMiBYWHbXhco+J1kHfTOUkePhCDvMA==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "husky": "bin.js"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/typicode"
+ }
+ },
+ "node_modules/i18next": {
+ "version": "25.7.3",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-25.7.3.tgz",
+ "integrity": "sha512-2XaT+HpYGuc2uTExq9TVRhLsso+Dxym6PWaKpn36wfBmTI779OQ7iP/XaZHzrnGyzU4SHpFrTYLKfVyBfAhVNA==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://locize.com"
+ },
+ {
+ "type": "individual",
+ "url": "https://locize.com/i18next.html"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "@babel/runtime": "^7.28.4"
+ },
+ "peerDependencies": {
+ "typescript": "^5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/i18next-fs-backend": {
+ "version": "2.6.1",
+ "resolved": "https://registry.npmjs.org/i18next-fs-backend/-/i18next-fs-backend-2.6.1.tgz",
+ "integrity": "sha512-eYWTX7QT7kJ0sZyCPK6x1q+R63zvNKv2D6UdbMf15A8vNb2ZLyw4NNNZxPFwXlIv/U+oUtg8SakW6ZgJZcoqHQ==",
+ "license": "MIT"
+ },
+ "node_modules/i18next-http-middleware": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/i18next-http-middleware/-/i18next-http-middleware-3.9.0.tgz",
+ "integrity": "sha512-hM56al/hnQ8a6Us5uRvw/en1gSI3vePqBUa9nX4+ISvIHOU/li7ffu11FrI2aR83nphTe6ofo7mxhVu0PLAe2w==",
+ "license": "MIT"
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz",
+ "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/ieee754": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/ieee754/-/ieee754-1.2.1.tgz",
+ "integrity": "sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==",
+ "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": "BSD-3-Clause"
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/image-q": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/image-q/-/image-q-4.0.0.tgz",
+ "integrity": "sha512-PfJGVgIfKQJuq3s0tTDOKtztksibuUEbJQIYT3by6wctQo+Rdlh7ef4evJ5NCdxY4CfMbvFkocEwbl4BF8RlJw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@types/node": "16.9.1"
+ }
+ },
+ "node_modules/image-q/node_modules/@types/node": {
+ "version": "16.9.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-16.9.1.tgz",
+ "integrity": "sha512-QpLcX9ZSsq3YYUUnD3nFDY8H7wctAhQj/TFKL8Ya8v5fMm3CFXxo8zStsLAl780ltoYoo1WvKUVGBQK+1ifr7g==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/image-size": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/image-size/-/image-size-2.0.2.tgz",
+ "integrity": "sha512-IRqXKlaXwgSMAMtpNzZa1ZAe8m+Sa1770Dhk8VkSsP9LS+iHD62Zd8FQKs8fbPiagBE7BzoFX23cxFnwshpV6w==",
+ "license": "MIT",
+ "bin": {
+ "image-size": "bin/image-size.js"
+ },
+ "engines": {
+ "node": ">=16.x"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/infer-owner": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
+ "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "devOptional": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "license": "ISC"
+ },
+ "node_modules/ip-address": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.1.0.tgz",
+ "integrity": "sha512-XXADHxXmvT9+CRxhXg56LJovE+bmWnEWB78LB83VZTprKTmaC5QfruXocxzTZ2Kl0DNwKuBdlIhjL8LeY8Sf8Q==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-lambda": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz",
+ "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-promise": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz",
+ "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==",
+ "license": "MIT"
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+ "license": "MIT",
+ "dependencies": {
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "license": "MIT"
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "license": "ISC"
+ },
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/jimp": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/jimp/-/jimp-1.6.0.tgz",
+ "integrity": "sha512-YcwCHw1kiqEeI5xRpDlPPBGL2EOpBKLwO4yIBJcXWHPj5PnA5urGq0jbyhM5KoNpypQ6VboSoxc9D8HyfvngSg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "@jimp/core": "1.6.0",
+ "@jimp/diff": "1.6.0",
+ "@jimp/js-bmp": "1.6.0",
+ "@jimp/js-gif": "1.6.0",
+ "@jimp/js-jpeg": "1.6.0",
+ "@jimp/js-png": "1.6.0",
+ "@jimp/js-tiff": "1.6.0",
+ "@jimp/plugin-blit": "1.6.0",
+ "@jimp/plugin-blur": "1.6.0",
+ "@jimp/plugin-circle": "1.6.0",
+ "@jimp/plugin-color": "1.6.0",
+ "@jimp/plugin-contain": "1.6.0",
+ "@jimp/plugin-cover": "1.6.0",
+ "@jimp/plugin-crop": "1.6.0",
+ "@jimp/plugin-displace": "1.6.0",
+ "@jimp/plugin-dither": "1.6.0",
+ "@jimp/plugin-fisheye": "1.6.0",
+ "@jimp/plugin-flip": "1.6.0",
+ "@jimp/plugin-hash": "1.6.0",
+ "@jimp/plugin-mask": "1.6.0",
+ "@jimp/plugin-print": "1.6.0",
+ "@jimp/plugin-quantize": "1.6.0",
+ "@jimp/plugin-resize": "1.6.0",
+ "@jimp/plugin-rotate": "1.6.0",
+ "@jimp/plugin-threshold": "1.6.0",
+ "@jimp/types": "1.6.0",
+ "@jimp/utils": "1.6.0"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/jose": {
+ "version": "6.1.3",
+ "resolved": "https://registry.npmjs.org/jose/-/jose-6.1.3.tgz",
+ "integrity": "sha512-0TpaTfihd4QMNwrz/ob2Bp7X04yuxJkjRGi4aKmOqwhov54i6u79oCv7T+C7lo70MKH6BesI3vscD1yb/yzKXQ==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/panva"
+ }
+ },
+ "node_modules/jpeg-js": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/jpeg-js/-/jpeg-js-0.4.4.tgz",
+ "integrity": "sha512-WZzeDOEtTOBK4Mdsar0IqEU5sMr3vSV2RqkAIzUEV2BHnUfKGyswWFPFwK5EeDo93K3FohSHbLAjj0s1Wzd+dg==",
+ "license": "BSD-3-Clause",
+ "optional": true
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/json-bigint": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-bigint/-/json-bigint-1.0.0.tgz",
+ "integrity": "sha512-SiPv/8VpZuWbvLSMtTDU8hEfrZWg/mH/nV/b4o0CYbSxu1UIQPLdwKOCIyLQX+VIPO5vrLX3i8qtqFyhdPSUSQ==",
+ "license": "MIT",
+ "dependencies": {
+ "bignumber.js": "^9.0.0"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "license": "MIT"
+ },
+ "node_modules/json-stable-stringify": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify/-/json-stable-stringify-1.3.0.tgz",
+ "integrity": "sha512-qtYiSSFlwot9XHtF9bD9c7rwKjr+RecWT//ZnPvSmEjpV5mmPOCN4j8UjY5hbjNkOwZ/jQv3J6R1/pL7RwgMsg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "isarray": "^2.0.5",
+ "jsonify": "^0.0.1",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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/jsonify": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/jsonify/-/jsonify-0.0.1.tgz",
+ "integrity": "sha512-2/Ki0GcmuqSrgFyelQq9M05y7PS0mEwuIzrf3f1fPqkVDVRvZrPZtVSMHxdgo8Aq0sxAOb/cr2aqqA3LeWHVPg==",
+ "dev": true,
+ "license": "Public Domain",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/jsonwebtoken": {
+ "version": "9.0.3",
+ "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.3.tgz",
+ "integrity": "sha512-MT/xP0CrubFRNLNKvxJ2BYfy53Zkm++5bX9dtuPbqAeQpTVe0MQTFhao8+Cp//EmJp244xt6Drw/GVEGCUj40g==",
+ "license": "MIT",
+ "dependencies": {
+ "jws": "^4.0.1",
+ "lodash.includes": "^4.3.0",
+ "lodash.isboolean": "^3.0.3",
+ "lodash.isinteger": "^4.0.4",
+ "lodash.isnumber": "^3.0.3",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.isstring": "^4.0.1",
+ "lodash.once": "^4.0.0",
+ "ms": "^2.1.1",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=12",
+ "npm": ">=6"
+ }
+ },
+ "node_modules/jwa": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/jwa/-/jwa-2.0.1.tgz",
+ "integrity": "sha512-hRF04fqJIP8Abbkq5NKGN0Bbr3JxlQ+qhZufXVr0DvujKy93ZCbXZMHDL4EOtodSbCWxOqR8MS1tXA5hwqCXDg==",
+ "license": "MIT",
+ "dependencies": {
+ "buffer-equal-constant-time": "^1.0.1",
+ "ecdsa-sig-formatter": "1.0.11",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/jws": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/jws/-/jws-4.0.1.tgz",
+ "integrity": "sha512-EKI/M/yqPncGUUh44xz0PxSidXFr/+r0pA70+gIYhjv+et7yxM+s29Y+VGDkovRofQem0fs7Uvf4+YmAdyRduA==",
+ "license": "MIT",
+ "dependencies": {
+ "jwa": "^2.0.1",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/klaw-sync": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/klaw-sync/-/klaw-sync-6.0.0.tgz",
+ "integrity": "sha512-nIeuVSzdCCs6TDPTqI8w1Yre34sSq7AkZ4B3sfOBbI2CgVSB4Du4aLQijFU2+lhAFCwt9+42Hel6lQNIv6AntQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "graceful-fs": "^4.1.11"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash.includes": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.includes/-/lodash.includes-4.3.0.tgz",
+ "integrity": "sha512-W3Bx6mdkRTGtlJISOvVD/lbqjTlPPUDTMnlXZFnVwi9NKJ6tiAk6LVdlhZMm17VZisqhKcgzpO5Wz91PCt5b0w==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isboolean": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isboolean/-/lodash.isboolean-3.0.3.tgz",
+ "integrity": "sha512-Bz5mupy2SVbPHURB98VAcw+aHh4vRV5IPNhILUCsOzRmsTmSQ17jIuqopAentWoehktxGd9e/hbIXq980/1QJg==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isinteger": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lodash.isinteger/-/lodash.isinteger-4.0.4.tgz",
+ "integrity": "sha512-DBwtEWN2caHQ9/imiNeEA5ys1JoRtRfY3d7V9wkqtbycnAmTvRRmbHKDV4a0EYc678/dia0jrte4tjYwVBaZUA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isnumber": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/lodash.isnumber/-/lodash.isnumber-3.0.3.tgz",
+ "integrity": "sha512-QYqzpfwO3/CWf3XP+Z+tkQsfaLL/EnUlXWVkIk5FUPc4sBdTehEqZONuyRt2P67PXAk+NXmTBcc97zw9t1FQrw==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.isstring": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.isstring/-/lodash.isstring-4.0.1.tgz",
+ "integrity": "sha512-0wJxfxH1wgO3GrbuP+dTTk7op+6L41QCXbGINEmD+ny/G/eCqGzxyCsh7159S+mgDDcoarnBw6PC1PS5+wUGgw==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.once": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz",
+ "integrity": "sha512-Sb487aTOCr9drQVL8pIxOzVhafOjZN9UU54hiN8PU3uAiSV7lx1yYNpbNmex2PK6dSJoNTSJUUswT651yww3Mg==",
+ "license": "MIT"
+ },
+ "node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/mailgun.js": {
+ "version": "12.4.0",
+ "resolved": "https://registry.npmjs.org/mailgun.js/-/mailgun.js-12.4.0.tgz",
+ "integrity": "sha512-3Mwvwo02PUmFkW0zxSwvTjHBFCaMLb903RuQaEkTU8Z8medItb7Ey0K3XXLVDErArbEjPoRRqxPDdzWqXaokfQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "axios": "^1.12.1",
+ "base-64": "^1.0.0",
+ "url-join": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
+ "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "semver": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "license": "ISC",
+ "optional": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+ "devOptional": true,
+ "license": "ISC"
+ },
+ "node_modules/make-fetch-happen": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz",
+ "integrity": "sha512-+zopwDy7DNknmwPQplem5lAZX/eCOzSvSNNcSKm5eVwTkOBzoktEfXsa9L23J/GIRhxRsaxzkPEhrJEpE2F4Gg==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "agentkeepalive": "^4.1.3",
+ "cacache": "^15.2.0",
+ "http-cache-semantics": "^4.1.0",
+ "http-proxy-agent": "^4.0.1",
+ "https-proxy-agent": "^5.0.0",
+ "is-lambda": "^1.0.1",
+ "lru-cache": "^6.0.0",
+ "minipass": "^3.1.3",
+ "minipass-collect": "^1.0.2",
+ "minipass-fetch": "^1.3.2",
+ "minipass-flush": "^1.0.5",
+ "minipass-pipeline": "^1.2.4",
+ "negotiator": "^0.6.2",
+ "promise-retry": "^2.0.1",
+ "socks-proxy-agent": "^6.0.0",
+ "ssri": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/make-fetch-happen/node_modules/negotiator": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
+ "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/media-typer": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz",
+ "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz",
+ "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-3.0.0.tgz",
+ "integrity": "sha512-jSCU7/VB1loIWBZe14aEYHU/+1UMEHoaO7qxCOVJOw9GgH72VAWppxNcjU+x9a2k3GSIBXNKxXQFqRvvZ7vr3A==",
+ "license": "MIT",
+ "optional": true,
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz",
+ "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "^1.54.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/mimic-response": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz",
+ "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "devOptional": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-collect": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz",
+ "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-fetch": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/minipass-fetch/-/minipass-fetch-1.4.1.tgz",
+ "integrity": "sha512-CGH1eblLq26Y15+Azk7ey4xh0J/XfJfrCox5LDJiKqI2Q2iwOLOKrlmIaODiSQS8d18jalF6y2K2ePUm0CmShw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.1.0",
+ "minipass-sized": "^1.0.3",
+ "minizlib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "optionalDependencies": {
+ "encoding": "^0.1.12"
+ }
+ },
+ "node_modules/minipass-flush": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz",
+ "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/minipass-pipeline": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz",
+ "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minipass-sized": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/minipass-sized/-/minipass-sized-1.0.3.tgz",
+ "integrity": "sha512-MbkQQ2CTiBMlA2Dm/5cY+9SWFEN8pzzOXi6rlM5Xxq0Yqbda5ZQy9sU75a673FE9ZK0Zsbr6Y5iP6u9nktfg2g==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/minizlib": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz",
+ "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==",
+ "license": "MIT",
+ "dependencies": {
+ "minipass": "^3.0.0",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/mkdirp": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz",
+ "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==",
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "^1.2.6"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
+ },
+ "node_modules/mkdirp-classic": {
+ "version": "0.5.3",
+ "resolved": "https://registry.npmjs.org/mkdirp-classic/-/mkdirp-classic-0.5.3.tgz",
+ "integrity": "sha512-gKLcREMhtuZRwRAfqP3RFW+TK4JqApVBtOIftVgjuABpAtpxhPGaDcfvbhNvD0B8iD1oUr/txX35NjcaY6Ns/A==",
+ "license": "MIT"
+ },
+ "node_modules/module-alias": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.2.3.tgz",
+ "integrity": "sha512-23g5BFj4zdQL/b6tor7Ji+QY4pEfNH784BMslY9Qb0UnJWRAt+lQGLYmRaM0KDBwIG23ffEBELhZDP2rhi9f/Q==",
+ "license": "MIT"
+ },
+ "node_modules/morgan": {
+ "version": "1.10.1",
+ "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.10.1.tgz",
+ "integrity": "sha512-223dMRJtI/l25dJKWpgij2cMtywuG/WiUKXdvwfbhGKBhy1puASqXwFzmWZ7+K73vUPoR7SS2Qz2cI/g9MKw0A==",
+ "license": "MIT",
+ "dependencies": {
+ "basic-auth": "~2.0.1",
+ "debug": "2.6.9",
+ "depd": "~2.0.0",
+ "on-finished": "~2.3.0",
+ "on-headers": "~1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/morgan/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/morgan/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/morgan/node_modules/on-finished": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
+ "integrity": "sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/mri": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz",
+ "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
+ },
+ "node_modules/multer": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/multer/-/multer-2.0.2.tgz",
+ "integrity": "sha512-u7f2xaZ/UG8oLXHvtF/oWTRvT44p9ecwBBqTwgJVq0+4BW1g8OW01TyMEGWBHbyMOYVHXslaut7qEQ1meATXgw==",
+ "license": "MIT",
+ "dependencies": {
+ "append-field": "^1.0.0",
+ "busboy": "^1.6.0",
+ "concat-stream": "^2.0.0",
+ "mkdirp": "^0.5.6",
+ "object-assign": "^4.1.1",
+ "type-is": "^1.6.18",
+ "xtend": "^4.0.2"
+ },
+ "engines": {
+ "node": ">= 10.16.0"
+ }
+ },
+ "node_modules/multer/node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/multer/node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/multer/node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/multer/node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "license": "MIT",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/murmurhash-js": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz",
+ "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==",
+ "license": "MIT"
+ },
+ "node_modules/napi-build-utils": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-2.0.0.tgz",
+ "integrity": "sha512-GEbrYkbfF7MoNaoh2iGG84Mnf/WZfB0GdGEsM8wz7Expx/LlWf5U8t9nvJKXSp3qr5IsEbK04cBGhol/KwOsWA==",
+ "license": "MIT"
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/needle": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz",
+ "integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^3.2.6",
+ "iconv-lite": "^0.4.4",
+ "sax": "^1.2.4"
+ },
+ "bin": {
+ "needle": "bin/needle"
+ },
+ "engines": {
+ "node": ">= 4.4.x"
+ }
+ },
+ "node_modules/needle/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/needle/node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/negotiator": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz",
+ "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/node-2fa": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/node-2fa/-/node-2fa-2.0.3.tgz",
+ "integrity": "sha512-PQldrOhjuoZyoydMvMSctllPN1ZPZ1/NwkEcgYwY9faVqE/OymxR+3awPpbWZxm6acLKqvmNqQmdqTsqYyflFw==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/notp": "^2.0.0",
+ "notp": "^2.0.3",
+ "thirty-two": "1.0.2",
+ "tslib": "^2.1.0"
+ }
+ },
+ "node_modules/node-abi": {
+ "version": "3.85.0",
+ "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.85.0.tgz",
+ "integrity": "sha512-zsFhmbkAzwhTft6nd3VxcG0cvJsT70rL+BIGHWVq5fi6MwGrHwzqKaxXE+Hl2GmnGItnDKPPkO5/LQqjVkIdFg==",
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^7.3.5"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/node-addon-api": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-4.3.0.tgz",
+ "integrity": "sha512-73sE9+3UaLYYFmDsFZnqCInzPyh3MqIwZO9cw58yIqAZhONrrabrYyYe3TuIqtIiOuTXVhsGau8hcrhhwSsDIQ==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-gyp": {
+ "version": "8.4.1",
+ "resolved": "https://registry.npmjs.org/node-gyp/-/node-gyp-8.4.1.tgz",
+ "integrity": "sha512-olTJRgUtAb/hOXG0E93wZDs5YiJlgbXxTwQAFHyNlRsXQnYzUaF2aGgujZbw+hR8aF4ZG/rST57bWMWD16jr9w==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "env-paths": "^2.2.0",
+ "glob": "^7.1.4",
+ "graceful-fs": "^4.2.6",
+ "make-fetch-happen": "^9.1.0",
+ "nopt": "^5.0.0",
+ "npmlog": "^6.0.0",
+ "rimraf": "^3.0.2",
+ "semver": "^7.3.5",
+ "tar": "^6.1.2",
+ "which": "^2.0.2"
+ },
+ "bin": {
+ "node-gyp": "bin/node-gyp.js"
+ },
+ "engines": {
+ "node": ">= 10.12.0"
+ }
+ },
+ "node_modules/node-gyp-build": {
+ "version": "4.8.4",
+ "resolved": "https://registry.npmjs.org/node-gyp-build/-/node-gyp-build-4.8.4.tgz",
+ "integrity": "sha512-LA4ZjwlnUblHVgq0oBF3Jl/6h/Nvs5fzBLwdEF4nuxnFdsfajde4WfxtJr3CaiH+F6ewcIB/q4jQ4UzPyid+CQ==",
+ "license": "MIT",
+ "bin": {
+ "node-gyp-build": "bin.js",
+ "node-gyp-build-optional": "optional.js",
+ "node-gyp-build-test": "build-test.js"
+ }
+ },
+ "node_modules/node-gyp-build-optional-packages": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/node-gyp-build-optional-packages/-/node-gyp-build-optional-packages-5.1.1.tgz",
+ "integrity": "sha512-+P72GAjVAbTxjjwUmwjVrqrdZROD4nf8KgpBoDxqXXTiYZZt/ud60dE5yvCSr9lRO8e8yv6kgJIC0K0PfZFVQw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "detect-libc": "^2.0.1"
+ },
+ "bin": {
+ "node-gyp-build-optional-packages": "bin.js",
+ "node-gyp-build-optional-packages-optional": "optional.js",
+ "node-gyp-build-optional-packages-test": "build-test.js"
+ }
+ },
+ "node_modules/node-gyp/node_modules/are-we-there-yet": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-3.0.1.tgz",
+ "integrity": "sha512-QZW4EDmGwlYur0Yyf/b2uGucHQMa8aFUP7eu9ddR73vvhFyt4V0Vl3QHPcTNJ8l6qYOBdxgXdnBXQrHilfRQBg==",
+ "deprecated": "This package is no longer supported.",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^3.6.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/node-gyp/node_modules/gauge": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/gauge/-/gauge-4.0.4.tgz",
+ "integrity": "sha512-f9m+BEN5jkg6a0fZjleidjN51VE1X+mPFQ2DJ0uv1V39oCLCbsGe6yjbBnp7eK7z/+GAon99a3nHuqbuuthyPg==",
+ "deprecated": "This package is no longer supported.",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "aproba": "^1.0.3 || ^2.0.0",
+ "color-support": "^1.1.3",
+ "console-control-strings": "^1.1.0",
+ "has-unicode": "^2.0.1",
+ "signal-exit": "^3.0.7",
+ "string-width": "^4.2.3",
+ "strip-ansi": "^6.0.1",
+ "wide-align": "^1.1.5"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/node-gyp/node_modules/npmlog": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-6.0.2.tgz",
+ "integrity": "sha512-/vBvz5Jfr9dT/aFWd0FIRf+T/Q2WBsLENygUaFUqstqsycmZAP/t5BvFJTK0viFmSUxiUKTUplWy5vt+rvKIxg==",
+ "deprecated": "This package is no longer supported.",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "are-we-there-yet": "^3.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^4.0.3",
+ "set-blocking": "^2.0.0"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/node-mailjet": {
+ "version": "6.0.11",
+ "resolved": "https://registry.npmjs.org/node-mailjet/-/node-mailjet-6.0.11.tgz",
+ "integrity": "sha512-5UaawWhpJc1uFxUl9a07jE8a4ZOax5hj7XYC0LFYyWOP8Rp0I8XvjbiQ6gy/ns7KSw0hqmjytP85GQsdVGEx5g==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "axios": "^1.12.0",
+ "json-bigint": "^1.0.0",
+ "url-join": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 12.0.0",
+ "npm": ">= 6.9.0"
+ }
+ },
+ "node_modules/nodemailer": {
+ "version": "7.0.11",
+ "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-7.0.11.tgz",
+ "integrity": "sha512-gnXhNRE0FNhD7wPSCGhdNh46Hs6nm+uTyg+Kq0cZukNQiYdnCsoQjodNP9BQVG9XrcK/v6/MgpAPBUFyzh9pvw==",
+ "license": "MIT-0",
+ "optional": true,
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/nopt": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz",
+ "integrity": "sha512-Tbj67rffqceeLpcRXrT7vKAN8CwfPeIBgM7E6iBkmKLV7bEMwpGgYLGv0jACUsECaa/vuxP0IjEont6umdMgtQ==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "abbrev": "1"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/notp": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/notp/-/notp-2.0.3.tgz",
+ "integrity": "sha512-oBig/2uqkjQ5AkBuw4QJYwkEWa/q+zHxI5/I5z6IeP2NT0alpJFsP/trrfCC+9xOAgQSZXssNi962kp5KBmypQ==",
+ "engines": {
+ "node": "> v0.6.0"
+ }
+ },
+ "node_modules/npmlog": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-5.0.1.tgz",
+ "integrity": "sha512-AqZtDUWOMKs1G/8lwylVjrdYgqA4d9nu8hc+0gzRxlDb1I10+FHBGMXs6aiQHFdCUUlqH99MUMuLfzWDNDtfxw==",
+ "deprecated": "This package is no longer supported.",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "are-we-there-yet": "^2.0.0",
+ "console-control-strings": "^1.1.0",
+ "gauge": "^3.0.0",
+ "set-blocking": "^2.0.0"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/omggif": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/omggif/-/omggif-1.0.10.tgz",
+ "integrity": "sha512-LMJTtvgc/nugXj0Vcrrs68Mn2D1r0zf630VNtqtpI1FEO7e+O9FP4gqs9AcnBaSEeoHIPm28u6qgPR0oyEpGSw==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "license": "MIT",
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/on-headers": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
+ "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/open": {
+ "version": "7.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-7.4.2.tgz",
+ "integrity": "sha512-MVHddDVweXZF3awtlAS+6pgKLlm/JgxZ90+/NBurBoQctVOOB/zDdVjcyPzQ+0laDGbsWgrRkflI65sQeOgT9Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-docker": "^2.0.0",
+ "is-wsl": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-map": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz",
+ "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "aggregate-error": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "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==",
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/pako": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
+ "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
+ "license": "(MIT AND Zlib)",
+ "optional": true
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-bmfont-ascii": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/parse-bmfont-ascii/-/parse-bmfont-ascii-1.0.6.tgz",
+ "integrity": "sha512-U4RrVsUFCleIOBsIGYOMKjn9PavsGOXxbvYGtMOEfnId0SVNsgehXh1DxUdVPLoxd5mvcEtvmKs2Mmf0Mpa1ZA==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/parse-bmfont-binary": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/parse-bmfont-binary/-/parse-bmfont-binary-1.0.6.tgz",
+ "integrity": "sha512-GxmsRea0wdGdYthjuUeWTMWPqm2+FAd4GI8vCvhgJsFnoGhTrLhXDDupwTo7rXVAgaLIGoVHDZS9p/5XbSqeWA==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/parse-bmfont-xml": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/parse-bmfont-xml/-/parse-bmfont-xml-1.1.6.tgz",
+ "integrity": "sha512-0cEliVMZEhrFDwMh4SxIyVJpqYoOWDJ9P895tFuS+XuNzI5UBmBk5U5O4KuJdTnZpSBI4LFA2+ZiJaiwfSwlMA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "xml-parse-from-string": "^1.0.0",
+ "xml2js": "^0.5.0"
+ }
+ },
+ "node_modules/parse5": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.3.0.tgz",
+ "integrity": "sha512-IInvU7fabl34qmi9gY8XOVxhYyMyuH2xUNpb2q8/Y+7552KlejkRvqvD19nMoUW/uQGGbqNpA6Tufu5FL5BZgw==",
+ "license": "MIT",
+ "dependencies": {
+ "entities": "^6.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5-htmlparser2-tree-adapter": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
+ "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
+ "license": "MIT",
+ "dependencies": {
+ "domhandler": "^5.0.3",
+ "parse5": "^7.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5-parser-stream": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
+ "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
+ "license": "MIT",
+ "dependencies": {
+ "parse5": "^7.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5/node_modules/entities": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-6.0.1.tgz",
+ "integrity": "sha512-aN97NXWF6AWBTahfVOIrB/NShkzi5H7F9r1s9mD3cDj4Ko5f2qhhVoYMibXF7GlLveb/D2ioWay8lxI97Ven3g==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/patch-package": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/patch-package/-/patch-package-8.0.1.tgz",
+ "integrity": "sha512-VsKRIA8f5uqHQ7NGhwIna6Bx6D9s/1iXlA1hthBVBEbkq+t4kXD0HHt+rJhf/Z+Ci0F/HCB2hvn0qLdLG+Qxlw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@yarnpkg/lockfile": "^1.1.0",
+ "chalk": "^4.1.2",
+ "ci-info": "^3.7.0",
+ "cross-spawn": "^7.0.3",
+ "find-yarn-workspace-root": "^2.0.0",
+ "fs-extra": "^10.0.0",
+ "json-stable-stringify": "^1.0.2",
+ "klaw-sync": "^6.0.0",
+ "minimist": "^1.2.6",
+ "open": "^7.4.2",
+ "semver": "^7.5.3",
+ "slash": "^2.0.0",
+ "tmp": "^0.2.4",
+ "yaml": "^2.2.2"
+ },
+ "bin": {
+ "patch-package": "index.js"
+ },
+ "engines": {
+ "node": ">=14",
+ "npm": ">5"
+ }
+ },
+ "node_modules/patch-package/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/path-equal": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/path-equal/-/path-equal-1.2.5.tgz",
+ "integrity": "sha512-i73IctDr3F2W+bsOWDyyVm/lqsXO47aY9nsFZUjTT/aljSbkxHxxCoyZ9UUrM8jK0JVod+An+rl48RCsvWM+9g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "license": "BlueOak-1.0.0",
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "license": "ISC"
+ },
+ "node_modules/path-scurry/node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/path-to-regexp": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz",
+ "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==",
+ "license": "MIT",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/peek-readable": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/peek-readable/-/peek-readable-4.1.0.tgz",
+ "integrity": "sha512-ZI3LnwUv5nOGbQzD9c2iDG6toheuXSZP5esSHBjopsXH4dg19soufvpUGA3uohi5anFtGb2lhAVdHzH6R/Evvg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/pg": {
+ "version": "8.16.3",
+ "resolved": "https://registry.npmjs.org/pg/-/pg-8.16.3.tgz",
+ "integrity": "sha512-enxc1h0jA/aq5oSDMvqyW3q89ra6XIIDZgCX9vkMrnz5DFTw/Ny3Li2lFQ+pt3L6MCgm/5o2o8HW9hiJji+xvw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "pg-connection-string": "^2.9.1",
+ "pg-pool": "^3.10.1",
+ "pg-protocol": "^1.10.3",
+ "pg-types": "2.2.0",
+ "pgpass": "1.0.5"
+ },
+ "engines": {
+ "node": ">= 16.0.0"
+ },
+ "optionalDependencies": {
+ "pg-cloudflare": "^1.2.7"
+ },
+ "peerDependencies": {
+ "pg-native": ">=3.0.1"
+ },
+ "peerDependenciesMeta": {
+ "pg-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/pg-cloudflare": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/pg-cloudflare/-/pg-cloudflare-1.2.7.tgz",
+ "integrity": "sha512-YgCtzMH0ptvZJslLM1ffsY4EuGaU0cx4XSdXLRFae8bPP4dS5xL1tNB3k2o/N64cHJpwU7dxKli/nZ2lUa5fLg==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/pg-connection-string": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.9.1.tgz",
+ "integrity": "sha512-nkc6NpDcvPVpZXxrreI/FOtX3XemeLl8E0qFr6F2Lrm/I8WOnaWNhIPK2Z7OHpw7gh5XJThi6j6ppgNoaT1w4w==",
+ "license": "MIT"
+ },
+ "node_modules/pg-cursor": {
+ "version": "2.15.3",
+ "resolved": "https://registry.npmjs.org/pg-cursor/-/pg-cursor-2.15.3.tgz",
+ "integrity": "sha512-eHw63TsiGtFEfAd7tOTZ+TLy+i/2ePKS20H84qCQ+aQ60pve05Okon9tKMC+YN3j6XyeFoHnaim7Lt9WVafQsA==",
+ "license": "MIT",
+ "peerDependencies": {
+ "pg": "^8"
+ }
+ },
+ "node_modules/pg-int8": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/pg-int8/-/pg-int8-1.0.1.tgz",
+ "integrity": "sha512-WCtabS6t3c8SkpDBUlb1kjOs7l66xsGdKpIPZsg4wR+B3+u9UAum2odSsF9tnvxg80h4ZxLWMy4pRjOsFIqQpw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/pg-pool": {
+ "version": "3.10.1",
+ "resolved": "https://registry.npmjs.org/pg-pool/-/pg-pool-3.10.1.tgz",
+ "integrity": "sha512-Tu8jMlcX+9d8+QVzKIvM/uJtp07PKr82IUOYEphaWcoBhIYkoHpLXN3qO59nAI11ripznDsEzEv8nUxBVWajGg==",
+ "license": "MIT",
+ "peerDependencies": {
+ "pg": ">=8.0"
+ }
+ },
+ "node_modules/pg-protocol": {
+ "version": "1.10.3",
+ "resolved": "https://registry.npmjs.org/pg-protocol/-/pg-protocol-1.10.3.tgz",
+ "integrity": "sha512-6DIBgBQaTKDJyxnXaLiLR8wBpQQcGWuAESkRBX/t6OwA8YsqP+iVSiond2EDy6Y/dsGk8rh/jtax3js5NeV7JQ==",
+ "license": "MIT"
+ },
+ "node_modules/pg-query-stream": {
+ "version": "4.10.3",
+ "resolved": "https://registry.npmjs.org/pg-query-stream/-/pg-query-stream-4.10.3.tgz",
+ "integrity": "sha512-h2utrzpOIzeT9JfaqfvBbVuvCfBjH86jNfVrGGTbyepKAIOyTfDew0lAt8bbJjs9n/I5bGDl7S2sx6h5hPyJxw==",
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "pg-cursor": "^2.15.3"
+ },
+ "peerDependencies": {
+ "pg": "^8"
+ }
+ },
+ "node_modules/pg-types": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/pg-types/-/pg-types-2.2.0.tgz",
+ "integrity": "sha512-qTAAlrEsl8s4OiEQY69wDvcMIdQN6wdz5ojQiOy6YRMuynxenON0O5oCpJI6lshc6scgAY8qvJ2On/p+CXY0GA==",
+ "license": "MIT",
+ "dependencies": {
+ "pg-int8": "1.0.1",
+ "postgres-array": "~2.0.0",
+ "postgres-bytea": "~1.0.0",
+ "postgres-date": "~1.0.4",
+ "postgres-interval": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pgpass": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/pgpass/-/pgpass-1.0.5.tgz",
+ "integrity": "sha512-FdW9r/jQZhSeohs1Z3sI1yxFQNFvMcnmfuj4WBMUTxOrAyLMaTcE1aAMBiTlbMNaXvBCQuVi0R7hd8udDSP7ug==",
+ "license": "MIT",
+ "dependencies": {
+ "split2": "^4.1.0"
+ }
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==",
+ "license": "ISC"
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pixelmatch": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/pixelmatch/-/pixelmatch-5.3.0.tgz",
+ "integrity": "sha512-o8mkY4E/+LNUf6LzX96ht6k6CEDi65k9G2rjMtBe9Oo+VPKSvl+0GKHuH/AlG+GA5LPG/i5hrekkxUc3s2HU+Q==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "pngjs": "^6.0.0"
+ },
+ "bin": {
+ "pixelmatch": "bin/pixelmatch"
+ }
+ },
+ "node_modules/pixelmatch/node_modules/pngjs": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-6.0.0.tgz",
+ "integrity": "sha512-TRzzuFRRmEoSW/p1KVAmiOgPco2Irlah+bGFCeNfJXxxYGwSw7YwAOAcd7X28K/m5bjBWKsC29KyoMfHbypayg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=12.13.0"
+ }
+ },
+ "node_modules/pkijs": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.3.3.tgz",
+ "integrity": "sha512-+KD8hJtqQMYoTuL1bbGOqxb4z+nZkTAwVdNtWwe8Tc2xNbEmdJYIYoc6Qt0uF55e6YW6KuTHw1DjQ18gMhzepw==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@noble/hashes": "1.4.0",
+ "asn1js": "^3.0.6",
+ "bytestreamjs": "^2.0.1",
+ "pvtsutils": "^1.3.6",
+ "pvutils": "^1.1.3",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/pngjs": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/pngjs/-/pngjs-7.0.0.tgz",
+ "integrity": "sha512-LKWqWJRhstyYo9pGvgor/ivk2w94eSjE3RGVuzLGlr3NmD8bf7RcYGze1mNdEHRP6TRP6rMuDHk5t44hnTRyow==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=14.19.0"
+ }
+ },
+ "node_modules/possible-typed-array-names": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
+ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/postgres-array": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-array/-/postgres-array-2.0.0.tgz",
+ "integrity": "sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postgres-bytea": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/postgres-bytea/-/postgres-bytea-1.0.0.tgz",
+ "integrity": "sha512-xy3pmLuQqRBZBXDULy7KbaitYqLcmxigw14Q5sj8QBVLqEwXfeybIKVWiqAXTlcvdvb0+xkOtDbfQMOf4lST1w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-date": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/postgres-date/-/postgres-date-1.0.7.tgz",
+ "integrity": "sha512-suDmjLVQg78nMK2UZ454hAG+OAW+HQPZ6n++TNDUX+L0+uUlLywnoxJKDou51Zm+zTCjrCl0Nq6J9C5hP9vK/Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/postgres-interval": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/postgres-interval/-/postgres-interval-1.2.0.tgz",
+ "integrity": "sha512-9ZhXKM/rw350N1ovuWHbGxnGh/SNJ4cnxHiM0rxE4VN41wsg8P8zWn9hv/buK00RP4WvlOyr/RBDiptyxVbkZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "xtend": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/prebuild-install": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.3.tgz",
+ "integrity": "sha512-8Mf2cbV7x1cXPUILADGI3wuhfqWvtiLA1iclTDbFRZkgRQS0NqsPZphna9V+HyTEadheuPmjaJMsbzKQFOzLug==",
+ "license": "MIT",
+ "dependencies": {
+ "detect-libc": "^2.0.0",
+ "expand-template": "^2.0.3",
+ "github-from-package": "0.0.0",
+ "minimist": "^1.2.3",
+ "mkdirp-classic": "^0.5.3",
+ "napi-build-utils": "^2.0.0",
+ "node-abi": "^3.3.0",
+ "pump": "^3.0.0",
+ "rc": "^1.2.7",
+ "simple-get": "^4.0.0",
+ "tar-fs": "^2.0.0",
+ "tunnel-agent": "^0.6.0"
+ },
+ "bin": {
+ "prebuild-install": "bin.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.7.4",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.7.4.tgz",
+ "integrity": "sha512-v6UNi1+3hSlVvv8fSaoUbggEM5VErKmmpGA7Pl3HF8V6uKY7rvClBOJlH6yNwQtfTueNkGVpOv/mtWL9L4bgRA==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/pretty-quick": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/pretty-quick/-/pretty-quick-4.2.2.tgz",
+ "integrity": "sha512-uAh96tBW1SsD34VhhDmWuEmqbpfYc/B3j++5MC/6b3Cb8Ow7NJsvKFhg0eoGu2xXX+o9RkahkTK6sUdd8E7g5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@pkgr/core": "^0.2.7",
+ "ignore": "^7.0.5",
+ "mri": "^1.2.0",
+ "picocolors": "^1.1.1",
+ "picomatch": "^4.0.2",
+ "tinyexec": "^0.3.2",
+ "tslib": "^2.8.1"
+ },
+ "bin": {
+ "pretty-quick": "lib/cli.mjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://opencollective.com/pretty-quick"
+ },
+ "peerDependencies": {
+ "prettier": "^3.0.0"
+ }
+ },
+ "node_modules/pretty-quick/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/pretty-quick/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/probe-image-size": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/probe-image-size/-/probe-image-size-7.2.3.tgz",
+ "integrity": "sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w==",
+ "license": "MIT",
+ "dependencies": {
+ "lodash.merge": "^4.6.2",
+ "needle": "^2.5.2",
+ "stream-parser": "~0.3.1"
+ }
+ },
+ "node_modules/process": {
+ "version": "0.11.10",
+ "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
+ "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 0.6.0"
+ }
+ },
+ "node_modules/promise-inflight": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
+ "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/promise-retry": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/promise-retry/-/promise-retry-2.0.1.tgz",
+ "integrity": "sha512-y+WKFlBR8BGXnsNlIHFGPZmyDf3DFMoLhaflAnyZgV6rG6xu+JwesTo2Q9R6XwYmtmwAFCkAk3e35jEdoeh/3g==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "err-code": "^2.0.2",
+ "retry": "^0.12.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/pump": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.3.tgz",
+ "integrity": "sha512-todwxLMY7/heScKmntwQG8CXVkWUOdYxIvY2s0VWAAMh/nd8SoYiRaKjlr7+iCs984f2P8zvrfWcDDYVb73NfA==",
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/punycode.js": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode.js/-/punycode.js-2.3.1.tgz",
+ "integrity": "sha512-uxFIHU0YlHYhDQtV4R9J6a52SLx28BCjT+4ieh7IGbgwVJWO+km431c4yRlREUAsAmt/uMjQUyQHNEPf0M39CA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pvtsutils": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz",
+ "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==",
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/pvutils": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz",
+ "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.14.0",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz",
+ "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/querystringify": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
+ "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
+ "license": "MIT"
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz",
+ "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==",
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.7.0",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/rc": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz",
+ "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==",
+ "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
+ "node_modules/rc/node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz",
+ "integrity": "sha512-4gB8na07fecVVkOI6Rs4e7T6NOTki5EmL7TUduTs6bu3EdnSycntVJ4re8kgZA+wx9IueI2Y11bfbgwtzuE0KQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/readable-web-to-node-stream": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/readable-web-to-node-stream/-/readable-web-to-node-stream-3.0.4.tgz",
+ "integrity": "sha512-9nX56alTf5bwXQ3ZDipHJhusu9NTQJ/CVPtb/XHAJCXihZeitfJvIRS4GqQ/mfIoOE3IelHMrpayVrosdHBuLw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "readable-stream": "^4.7.0"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/readable-web-to-node-stream/node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "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",
+ "optional": true,
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/readable-web-to-node-stream/node_modules/readable-stream": {
+ "version": "4.7.0",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.7.0.tgz",
+ "integrity": "sha512-oIGGmcpTLwPga8Bn6/Z75SVaH1z5dUut2ibSyAMVhmUggWpmDn2dapB0n7f8nwaSiRtepAsfJyfXIO5DCVAODg==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "abort-controller": "^3.0.0",
+ "buffer": "^6.0.3",
+ "events": "^3.3.0",
+ "process": "^0.11.10",
+ "string_decoder": "^1.3.0"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ }
+ },
+ "node_modules/reflect-metadata": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
+ "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "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==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "license": "MIT"
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/rimraf": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
+ "deprecated": "Rimraf versions prior to v4 are no longer supported",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/router": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz",
+ "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.0",
+ "depd": "^2.0.0",
+ "is-promise": "^4.0.0",
+ "parseurl": "^1.3.3",
+ "path-to-regexp": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
+ "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==",
+ "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-stable-stringify": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/safe-stable-stringify/-/safe-stable-stringify-2.5.0.tgz",
+ "integrity": "sha512-b3rppTKm9T+PsVCBEOUR46GWI7fdOs00VKZ1+9c1EWDaDMvjQc6tUwuFyIprgGgTcWoVHSKrU8H31ZHA2e0RHA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
+ },
+ "node_modules/sax": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.3.tgz",
+ "integrity": "sha512-yqYn1JhPczigF94DMS+shiDMjDowYO6y9+wB/4WgO0Y19jWYk0lQ4tuG5KI7kj4FTp1wxPj5IFfcrz/s1c3jjQ==",
+ "license": "BlueOak-1.0.0"
+ },
+ "node_modules/semver": {
+ "version": "7.7.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz",
+ "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==",
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/send": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz",
+ "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "^4.4.3",
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "etag": "^1.8.1",
+ "fresh": "^2.0.0",
+ "http-errors": "^2.0.1",
+ "mime-types": "^3.0.2",
+ "ms": "^2.1.3",
+ "on-finished": "^2.4.1",
+ "range-parser": "^1.2.1",
+ "statuses": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/serve-static": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz",
+ "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==",
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "^2.0.0",
+ "escape-html": "^1.0.3",
+ "parseurl": "^1.3.3",
+ "send": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/set-blocking": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
+ "integrity": "sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "license": "ISC"
+ },
+ "node_modules/sha.js": {
+ "version": "2.4.12",
+ "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.12.tgz",
+ "integrity": "sha512-8LzC5+bvI45BjpfXU8V5fdU2mfeKiQe1D1gIMn7XUlF3OTUrpdJpPPH4EMAnF0DsHHdSZqCdSss5qCmJKuiO3w==",
+ "license": "(MIT AND BSD-3-Clause)",
+ "dependencies": {
+ "inherits": "^2.0.4",
+ "safe-buffer": "^5.2.1",
+ "to-buffer": "^1.2.0"
+ },
+ "bin": {
+ "sha.js": "bin.js"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "license": "ISC",
+ "optional": true
+ },
+ "node_modules/simple-concat": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/simple-concat/-/simple-concat-1.0.1.tgz",
+ "integrity": "sha512-cSFtAPtRhljv69IK0hTVZQ+OfE9nePi/rtJmw5UjHeVyVroEqJXP1sFztKUy1qU+xvz3u/sfYJLa947b7nAN2Q==",
+ "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/simple-get": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/simple-get/-/simple-get-4.0.1.tgz",
+ "integrity": "sha512-brv7p5WgH0jmQJr1ZDDfKDOSeWWg+OVypG99A/5vYGPqJ6pxiaHLy8nxtFjBA7oMa01ebA9gfh1uMCFqOuXxvA==",
+ "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",
+ "dependencies": {
+ "decompress-response": "^6.0.0",
+ "once": "^1.3.1",
+ "simple-concat": "^1.0.0"
+ }
+ },
+ "node_modules/simple-xml-to-json": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/simple-xml-to-json/-/simple-xml-to-json-1.2.3.tgz",
+ "integrity": "sha512-kWJDCr9EWtZ+/EYYM5MareWj2cRnZGF93YDNpH4jQiHB+hBIZnfPFSQiVMzZOdk+zXWqTZ/9fTeQNu2DqeiudA==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=20.12.2"
+ }
+ },
+ "node_modules/slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/smart-buffer": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/smart-buffer/-/smart-buffer-4.2.0.tgz",
+ "integrity": "sha512-94hK0Hh8rPqQl2xXc3HsaBoOXKV20MToPkcXvwbISWLEs+64sBq5kFgn2kJDHb1Pry9yrP0dxrCI9RRci7RXKg==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">= 6.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks": {
+ "version": "2.8.7",
+ "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.7.tgz",
+ "integrity": "sha512-HLpt+uLy/pxB+bum/9DzAgiKS8CX1EvbWxI4zlmgGCExImLdiad2iCwXT5Z4c9c3Eq8rP2318mPW2c+QbtjK8A==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "ip-address": "^10.0.1",
+ "smart-buffer": "^4.2.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0",
+ "npm": ">= 3.0.0"
+ }
+ },
+ "node_modules/socks-proxy-agent": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/socks-proxy-agent/-/socks-proxy-agent-6.2.1.tgz",
+ "integrity": "sha512-a6KW9G+6B3nWZ1yB8G7pJwL3ggLy1uTzKAgCb7ttblwqdz9fMGJUuTy3uFzEP48FAs9FLILlmzDlE2JJhVQaXQ==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "agent-base": "^6.0.2",
+ "debug": "^4.3.3",
+ "socks": "^2.6.2"
+ },
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/split2": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/split2/-/split2-4.2.0.tgz",
+ "integrity": "sha512-UcjcJOWknrNkF6PLX83qcHM6KHgVKNkV62Y8a5uYDVv9ydGQVwAHMKqHdJje1VTWpljG0WYpCDhrCdAOYH4TWg==",
+ "license": "ISC",
+ "engines": {
+ "node": ">= 10.x"
+ }
+ },
+ "node_modules/sql-highlight": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/sql-highlight/-/sql-highlight-6.1.0.tgz",
+ "integrity": "sha512-ed7OK4e9ywpE7pgRMkMQmZDPKSVdm0oX5IEtZiKnFucSF0zu6c80GZBe38UqHuVhTWJ9xsKgSMjCG2bml86KvA==",
+ "funding": [
+ "https://github.com/scriptcoded/sql-highlight?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/scriptcoded"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/sqlite3": {
+ "version": "5.1.7",
+ "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-5.1.7.tgz",
+ "integrity": "sha512-GGIyOiFaG+TUra3JIfkI/zGP8yZYLPQ0pl1bH+ODjiX57sPhrLU5sQJn1y9bDKZUFYkX1crlrPfSYt0BKKdkog==",
+ "hasInstallScript": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "bindings": "^1.5.0",
+ "node-addon-api": "^7.0.0",
+ "prebuild-install": "^7.1.1",
+ "tar": "^6.1.11"
+ },
+ "optionalDependencies": {
+ "node-gyp": "8.x"
+ },
+ "peerDependencies": {
+ "node-gyp": "8.x"
+ },
+ "peerDependenciesMeta": {
+ "node-gyp": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/sqlite3/node_modules/node-addon-api": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
+ "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+ "license": "MIT"
+ },
+ "node_modules/ssri": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
+ "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "minipass": "^3.1.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/statuses": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/stream-parser": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz",
+ "integrity": "sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==",
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2"
+ }
+ },
+ "node_modules/stream-parser/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/stream-parser/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
+ },
+ "node_modules/streamsearch": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz",
+ "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "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==",
+ "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": {
+ "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==",
+ "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/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "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==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/strnum": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/strnum/-/strnum-2.1.2.tgz",
+ "integrity": "sha512-l63NF9y/cLROq/yqKXSLtcMeeyOfnSQlfMSlzFt/K73oIaD8DGaQWd7Z34X9GPiKqP5rbSh84Hl4bOlLcjiSrQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/NaturalIntelligence"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/strtok3": {
+ "version": "10.3.4",
+ "resolved": "https://registry.npmjs.org/strtok3/-/strtok3-10.3.4.tgz",
+ "integrity": "sha512-KIy5nylvC5le1OdaaoCJ07L+8iQzJHGH6pWDuzS+d07Cu7n1MZ2x26P8ZKIWfbK02+XIL8Mp4RkWeqdUCrDMfg==",
+ "license": "MIT",
+ "dependencies": {
+ "@tokenizer/token": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tar": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz",
+ "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==",
+ "license": "ISC",
+ "dependencies": {
+ "chownr": "^2.0.0",
+ "fs-minipass": "^2.0.0",
+ "minipass": "^5.0.0",
+ "minizlib": "^2.1.1",
+ "mkdirp": "^1.0.3",
+ "yallist": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/tar-fs": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.1.4.tgz",
+ "integrity": "sha512-mDAjwmZdh7LTT6pNleZ05Yt65HC3E+NiQzl672vQG38jIrehtJk/J3mNwIg+vShQPcLF/LV7CMnDW6vjj6sfYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "chownr": "^1.1.1",
+ "mkdirp-classic": "^0.5.2",
+ "pump": "^3.0.0",
+ "tar-stream": "^2.1.4"
+ }
+ },
+ "node_modules/tar-fs/node_modules/chownr": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
+ "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
+ "license": "ISC"
+ },
+ "node_modules/tar-stream": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz",
+ "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==",
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^4.0.3",
+ "end-of-stream": "^1.4.1",
+ "fs-constants": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/tar/node_modules/minipass": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz",
+ "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/tar/node_modules/mkdirp": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz",
+ "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==",
+ "license": "MIT",
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/thirty-two": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/thirty-two/-/thirty-two-1.0.2.tgz",
+ "integrity": "sha512-OEI0IWCe+Dw46019YLl6V10Us5bi574EvlJEOcAkB29IzQ/mYD1A6RyNHLjZPiHCmuodxvgF6U+vZO1L15lxVA==",
+ "engines": {
+ "node": ">=0.2.6"
+ }
+ },
+ "node_modules/tinycolor2": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
+ "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/tinyexec": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-0.3.2.tgz",
+ "integrity": "sha512-KQQR9yN7R5+OSwaK0XQoj22pwHoTlgYqmUscPYoknOoWCWfj/5/ABTMRi69FrKU5ffPVh5QcFikpWJI/P1ocHA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/tinyglobby": {
+ "version": "0.2.15",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz",
+ "integrity": "sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
+ }
+ },
+ "node_modules/tinyglobby/node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tinyglobby/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",
+ "peer": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/tldts": {
+ "version": "7.0.19",
+ "resolved": "https://registry.npmjs.org/tldts/-/tldts-7.0.19.tgz",
+ "integrity": "sha512-8PWx8tvC4jDB39BQw1m4x8y5MH1BcQ5xHeL2n7UVFulMPH/3Q0uiamahFJ3lXA0zO2SUyRXuVVbWSDmstlt9YA==",
+ "license": "MIT",
+ "dependencies": {
+ "tldts-core": "^7.0.19"
+ },
+ "bin": {
+ "tldts": "bin/cli.js"
+ }
+ },
+ "node_modules/tldts-core": {
+ "version": "7.0.19",
+ "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-7.0.19.tgz",
+ "integrity": "sha512-lJX2dEWx0SGH4O6p+7FPwYmJ/bu1JbcGJ8RLaG9b7liIgZ85itUVEPbMtWRVrde/0fnDPEPHW10ZsKW3kVsE9A==",
+ "license": "MIT"
+ },
+ "node_modules/tmp": {
+ "version": "0.2.5",
+ "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.5.tgz",
+ "integrity": "sha512-voyz6MApa1rQGUxT3E+BK7/ROe8itEx7vD8/HEvt4xwXucvQ5G5oeEiHkmHZJuBO21RpOf+YYm9MOivj709jow==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/to-buffer": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/to-buffer/-/to-buffer-1.2.2.tgz",
+ "integrity": "sha512-db0E3UJjcFhpDhAF4tLo03oli3pwl3dbnzXOUIlRKrp+ldk/VUxzpWYZENsw2SZiuBjHAk7DfB0VU7NKdpb6sw==",
+ "license": "MIT",
+ "dependencies": {
+ "isarray": "^2.0.5",
+ "safe-buffer": "^5.2.1",
+ "typed-array-buffer": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/token-types": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/token-types/-/token-types-6.1.1.tgz",
+ "integrity": "sha512-kh9LVIWH5CnL63Ipf0jhlBIy0UsrMj/NJDfpsy1SqOXlLKEVyXXYrnFxFT1yOOYVGBSApeVnjPw/sBz5BfEjAQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@borewit/text-codec": "^0.1.0",
+ "@tokenizer/token": "^0.3.0",
+ "ieee754": "^1.2.1"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/Borewit"
+ }
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/ts-api-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
+ "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4"
+ }
+ },
+ "node_modules/ts-node": {
+ "version": "10.9.2",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
+ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
+ "devOptional": true,
+ "license": "MIT",
+ "peer": true,
+ "dependencies": {
+ "@cspotcode/source-map-support": "^0.8.0",
+ "@tsconfig/node10": "^1.0.7",
+ "@tsconfig/node12": "^1.0.7",
+ "@tsconfig/node14": "^1.0.0",
+ "@tsconfig/node16": "^1.0.2",
+ "acorn": "^8.4.1",
+ "acorn-walk": "^8.1.1",
+ "arg": "^4.1.0",
+ "create-require": "^1.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "v8-compile-cache-lib": "^3.0.1",
+ "yn": "3.1.1"
+ },
+ "bin": {
+ "ts-node": "dist/bin.js",
+ "ts-node-cwd": "dist/bin-cwd.js",
+ "ts-node-esm": "dist/bin-esm.js",
+ "ts-node-script": "dist/bin-script.js",
+ "ts-node-transpile-only": "dist/bin-transpile.js",
+ "ts-script": "dist/bin-script-deprecated.js"
+ },
+ "peerDependencies": {
+ "@swc/core": ">=1.2.50",
+ "@swc/wasm": ">=1.2.50",
+ "@types/node": "*",
+ "typescript": ">=2.7"
+ },
+ "peerDependenciesMeta": {
+ "@swc/core": {
+ "optional": true
+ },
+ "@swc/wasm": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
+ "node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
+ "integrity": "sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz",
+ "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==",
+ "license": "MIT",
+ "dependencies": {
+ "content-type": "^1.0.5",
+ "media-typer": "^1.1.0",
+ "mime-types": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
+ "license": "MIT"
+ },
+ "node_modules/typeorm": {
+ "version": "0.3.28",
+ "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.28.tgz",
+ "integrity": "sha512-6GH7wXhtfq2D33ZuRXYwIsl/qM5685WZcODZb7noOOcRMteM9KF2x2ap3H0EBjnSV0VO4gNAfJT5Ukp0PkOlvg==",
+ "license": "MIT",
+ "dependencies": {
+ "@sqltools/formatter": "^1.2.5",
+ "ansis": "^4.2.0",
+ "app-root-path": "^3.1.0",
+ "buffer": "^6.0.3",
+ "dayjs": "^1.11.19",
+ "debug": "^4.4.3",
+ "dedent": "^1.7.0",
+ "dotenv": "^16.6.1",
+ "glob": "^10.5.0",
+ "reflect-metadata": "^0.2.2",
+ "sha.js": "^2.4.12",
+ "sql-highlight": "^6.1.0",
+ "tslib": "^2.8.1",
+ "uuid": "^11.1.0",
+ "yargs": "^17.7.2"
+ },
+ "bin": {
+ "typeorm": "cli.js",
+ "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js",
+ "typeorm-ts-node-esm": "cli-ts-node-esm.js"
+ },
+ "engines": {
+ "node": ">=16.13.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/typeorm"
+ },
+ "peerDependencies": {
+ "@google-cloud/spanner": "^5.18.0 || ^6.0.0 || ^7.0.0 || ^8.0.0",
+ "@sap/hana-client": "^2.14.22",
+ "better-sqlite3": "^8.0.0 || ^9.0.0 || ^10.0.0 || ^11.0.0 || ^12.0.0",
+ "ioredis": "^5.0.4",
+ "mongodb": "^5.8.0 || ^6.0.0",
+ "mssql": "^9.1.1 || ^10.0.0 || ^11.0.0 || ^12.0.0",
+ "mysql2": "^2.2.5 || ^3.0.1",
+ "oracledb": "^6.3.0",
+ "pg": "^8.5.1",
+ "pg-native": "^3.0.0",
+ "pg-query-stream": "^4.0.0",
+ "redis": "^3.1.1 || ^4.0.0 || ^5.0.14",
+ "sql.js": "^1.4.0",
+ "sqlite3": "^5.0.3",
+ "ts-node": "^10.7.0",
+ "typeorm-aurora-data-api-driver": "^2.0.0 || ^3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@google-cloud/spanner": {
+ "optional": true
+ },
+ "@sap/hana-client": {
+ "optional": true
+ },
+ "better-sqlite3": {
+ "optional": true
+ },
+ "ioredis": {
+ "optional": true
+ },
+ "mongodb": {
+ "optional": true
+ },
+ "mssql": {
+ "optional": true
+ },
+ "mysql2": {
+ "optional": true
+ },
+ "oracledb": {
+ "optional": true
+ },
+ "pg": {
+ "optional": true
+ },
+ "pg-native": {
+ "optional": true
+ },
+ "pg-query-stream": {
+ "optional": true
+ },
+ "redis": {
+ "optional": true
+ },
+ "sql.js": {
+ "optional": true
+ },
+ "sqlite3": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ },
+ "typeorm-aurora-data-api-driver": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/typeorm/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==",
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/typeorm/node_modules/buffer": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz",
+ "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==",
+ "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",
+ "dependencies": {
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.2.1"
+ }
+ },
+ "node_modules/typeorm/node_modules/dotenv": {
+ "version": "16.6.1",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.6.1.tgz",
+ "integrity": "sha512-uBq4egWHTcTt33a72vpSG0z3HnPuIl6NqYcTrKEg2azoEyl2hpW0zqlxysq2pK9HlDIHyHyakeYaYnSAwd8bow==",
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://dotenvx.com"
+ }
+ },
+ "node_modules/typeorm/node_modules/glob": {
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.5.0.tgz",
+ "integrity": "sha512-DfXN8DfhJ7NH3Oe7cFmu3NCu1wKbkReJ8TorzSAFbSKrlNaQSKfIzqYqVY8zlbs2NLBbWpRiU52GX2PbaBVNkg==",
+ "license": "ISC",
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/typeorm/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/typeorm/node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.9.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz",
+ "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==",
+ "devOptional": true,
+ "license": "Apache-2.0",
+ "peer": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/typescript-json-schema": {
+ "version": "0.65.1",
+ "resolved": "https://registry.npmjs.org/typescript-json-schema/-/typescript-json-schema-0.65.1.tgz",
+ "integrity": "sha512-tuGH7ff2jPaUYi6as3lHyHcKpSmXIqN7/mu50x3HlYn0EHzLpmt3nplZ7EuhUkO0eqDRc9GqWNkfjgBPIS9kxg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "@types/node": "^18.11.9",
+ "glob": "^7.1.7",
+ "path-equal": "^1.2.5",
+ "safe-stable-stringify": "^2.2.0",
+ "ts-node": "^10.9.1",
+ "typescript": "~5.5.0",
+ "yargs": "^17.1.1"
+ },
+ "bin": {
+ "typescript-json-schema": "bin/typescript-json-schema"
+ }
+ },
+ "node_modules/typescript-json-schema/node_modules/@types/node": {
+ "version": "18.19.130",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.130.tgz",
+ "integrity": "sha512-GRaXQx6jGfL8sKfaIDD6OupbIHBr9jv7Jnaml9tB7l4v068PAOXqfcujMMo5PhbIs6ggR1XODELqahT2R8v0fg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/typescript-json-schema/node_modules/typescript": {
+ "version": "5.5.4",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.5.4.tgz",
+ "integrity": "sha512-Mtq29sKDAEYP7aljRgtPOpTvOfbwRWlS6dPRzwjdE+C0R4brX/GUyhHSecbHMFLNBLcJIPt9nl9yG5TZ1weH+Q==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/typescript-json-schema/node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/uint8array-extras": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/uint8array-extras/-/uint8array-extras-1.5.0.tgz",
+ "integrity": "sha512-rvKSBiC5zqCCiDZ9kAOszZcDvdAHwwIKJG33Ykj43OKcWsnmcBRL09YTU4nOeHZ8Y2a7l1MgTd08SBe9A8Qj6A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/undici": {
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-7.16.0.tgz",
+ "integrity": "sha512-QEg3HPMll0o3t2ourKwOeUAZ159Kn9mx5pnzHRQO8+Wixmh88YdZRiIwat0iNzNNXn0yoEtXJqFpyW7eM8BV7g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.18.1"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "7.16.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.16.0.tgz",
+ "integrity": "sha512-Zz+aZWSj8LE6zoxD+xrjh4VfkIG8Ya6LvYkZqtUQGJPZjYl53ypCaUwWqo7eI0x66KBGeRo+mlBEkMSeSZ38Nw==",
+ "license": "MIT"
+ },
+ "node_modules/unique-filename": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
+ "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "node_modules/unique-slug": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
+ "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "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/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/url-join": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/url-join/-/url-join-4.0.1.tgz",
+ "integrity": "sha512-jk1+QP6ZJqyOiuEI9AEWQfju/nB2Pw466kbA0LEZljHwKeMgd9WrAEgEGxjPDD2+TNbbb37rTyhEfrCXfuKXnA==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/url-parse": {
+ "version": "1.5.10",
+ "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
+ "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
+ "license": "MIT",
+ "dependencies": {
+ "querystringify": "^2.1.1",
+ "requires-port": "^1.0.0"
+ }
+ },
+ "node_modules/utif2": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/utif2/-/utif2-4.1.0.tgz",
+ "integrity": "sha512-+oknB9FHrJ7oW7A2WZYajOcv4FcDR4CfoGB0dPNfxbi4GO05RRnFmt5oa23+9w32EanrYcSJWspUiJkLMs+37w==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "pako": "^1.0.11"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "license": "MIT"
+ },
+ "node_modules/uuid": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-11.1.0.tgz",
+ "integrity": "sha512-0/A9rDy9P7cJ+8w1c9WD9V//9Wj15Ce2MPz8Ri6032usz+NfePxx5AcN3bN+r6ZL6jEo066/yNYB3tn4pQEx+A==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/esm/bin/uuid"
+ }
+ },
+ "node_modules/v8-compile-cache-lib": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
+ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
+ "devOptional": true,
+ "license": "MIT"
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/webcrypto-core": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/webcrypto-core/-/webcrypto-core-1.8.1.tgz",
+ "integrity": "sha512-P+x1MvlNCXlKbLSOY4cYrdreqPG5hbzkmawbcXLKN/mf6DZW0SdNNkZ+sjwsqVkI4A4Ko2sPZmkZtCKY58w83A==",
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.3.13",
+ "@peculiar/json-schema": "^1.1.12",
+ "asn1js": "^3.0.5",
+ "pvtsutils": "^1.3.5",
+ "tslib": "^2.7.0"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "license": "BSD-2-Clause",
+ "optional": true
+ },
+ "node_modules/whatwg-encoding": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
+ "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-encoding/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/whatwg-mimetype": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+ "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.19",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.19.tgz",
+ "integrity": "sha512-rEvr90Bck4WZt9HHFC4DJMsjvu7x+r6bImz0/BrbWb7A2djJ8hnZMrWnHo9F8ssv0OMErasDhftrfROTyqSDrw==",
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "for-each": "^0.3.5",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/wide-align": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.5.tgz",
+ "integrity": "sha512-eDMORYaPNZ4sQIuuYPDHdQvf4gyCF9rEEV/yPxGfwPkRodwEgiMUUXTx/dex+Me0wxx53S+NgUHaP7y3MGlDmg==",
+ "license": "ISC",
+ "optional": true,
+ "dependencies": {
+ "string-width": "^1.0.2 || 2 || 3 || 4"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "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==",
+ "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/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
+ },
+ "node_modules/wretch": {
+ "version": "2.11.1",
+ "resolved": "https://registry.npmjs.org/wretch/-/wretch-2.11.1.tgz",
+ "integrity": "sha512-rJejp30zE8Igs4Mvo4pxXaiOKdSIGYLxyVaY+jZTlAMfQyi/hZsDwMRa9R09N0iS9Q8cLvplKfHwwyBv6XRWsg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/ws": {
+ "version": "8.18.3",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.3.tgz",
+ "integrity": "sha512-PEIGCY5tSlUt50cqyMXfCzX+oOPqN0vuGqWzbcJ2xvnkzkq46oOpz7dQaTDBdfICb4N14+GARUDw2XV2N4tvzg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xml-parse-from-string": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/xml-parse-from-string/-/xml-parse-from-string-1.0.1.tgz",
+ "integrity": "sha512-ErcKwJTF54uRzzNMXq2X5sMIy88zJvfN2DmdoQvy7PAFJ+tPRU6ydWuOKNMyfmOjdyBQTFREi60s0Y0SyI0G0g==",
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/xml2js": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.5.0.tgz",
+ "integrity": "sha512-drPFnkQJik/O+uPKpqSgr22mpuFHqKdbS835iAQrUC73L2F5WkboIRd63ai/2Yg6I1jzifPFKH2NTK+cfglkIA==",
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~11.0.0"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/xmlbuilder": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "license": "MIT",
+ "optional": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/xtend": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
+ "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
+ "license": "ISC"
+ },
+ "node_modules/yaml": {
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.2.tgz",
+ "integrity": "sha512-mplynKqc1C2hTVYxd0PU2xQAc22TI1vShAYGksCCfxbn/dFwnHTNi1bvYsBTkhdUNtGIf5xNOg938rrSSYvS9A==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/eemeli"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "license": "ISC",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+ "devOptional": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zod": {
+ "version": "3.25.76",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.25.76.tgz",
+ "integrity": "sha512-gzUt/qt81nXsFGKIFcC3YnfEAx5NkunCfnDlvuBSSFS02bcXu4Lmea0AFIUwbLWxWPx3d9p8S5QoaujKcNQxcQ==",
+ "license": "MIT",
+ "optional": true,
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ }
+ }
}
diff --git a/package.json b/package.json
index 5482ae7..c08b79a 100644
--- a/package.json
+++ b/package.json
@@ -1,135 +1,135 @@
{
- "name": "spacebar-server",
- "version": "1.0.0",
- "description": "A Spacebar server written in Node.js",
- "scripts": {
- "prepare": "husky install",
- "postinstall": "patch-package",
- "start": "node --enable-source-maps dist/bundle/start.js",
- "start:api": "node --enable-source-maps dist/api/start.js",
- "start:cdn": "node --enable-source-maps dist/cdn/start.js",
- "start:gateway": "node --enable-source-maps dist/gateway/start.js",
- "build": "npm run build:src && npm run generate:schema && npm run generate:openapi",
- "build:src": "tsc -b -v",
- "watch": "tsc -w -b .",
- "test": "node scripts/test.js",
- "lint": "eslint .",
- "setup": "npm run build && npm run generate:schema",
- "sync:db": "npm run build && node scripts/syncronise.js",
- "generate:rights": "node scripts/rights.js",
- "generate:schema": "node scripts/schema.js",
- "generate:migration": "node -r dotenv/config -r module-alias/register node_modules/typeorm/cli.js migration:generate -d dist/util/util/Database.js",
- "generate:openapi": "node scripts/openapi.js",
- "add:license": "node scripts/license.js",
- "migrate-from-staging": "node -r dotenv/config -r module-alias/register scripts/stagingMigration/index.js",
- "node:tests": "npm run build:src && node -r dotenv/config -r module-alias/register --enable-source-maps --test --experimental-test-coverage dist/**/*.test.js"
- },
- "main": "dist/bundle/index.js",
- "types": "src/bundle/index.ts",
- "repository": {
- "type": "git",
- "url": "git+https://github.com/spacebarchat/server.git"
- },
- "author": "Spacebar",
- "license": "AGPL-3.0-only",
- "bugs": {
- "url": "https://github.com/spacebarchat/server/issues"
- },
- "imports": {
- "#*": "./dist/*/index.js"
- },
- "homepage": "https://spacebar.chat",
- "devDependencies": {
- "@eslint/eslintrc": "^3.3.3",
- "@eslint/js": "^9.14.0",
- "@spacebarchat/spacebar-webrtc-types": "^1.0.1",
- "@types/amqplib": "^0.10.8",
- "@types/bcrypt": "^6.0.0",
- "@types/body-parser": "^1.19.6",
- "@types/cookie-parser": "^1.4.10",
- "@types/express": "^5.0.6",
- "@types/i18next-node-fs-backend": "^2.1.5",
- "@types/json-bigint": "^1.0.4",
- "@types/jsonwebtoken": "^9.0.10",
- "@types/module-alias": "^2.0.4",
- "@types/morgan": "^1.9.10",
- "@types/multer": "^2.0.0",
- "@types/murmurhash-js": "^1.0.6",
- "@types/node": "^24.10.4",
- "@types/nodemailer": "^7.0.4",
- "@types/probe-image-size": "^7.2.5",
- "@types/sharp": "^0.31.1",
- "@types/ws": "^8.18.1",
- "@typescript-eslint/eslint-plugin": "^8.50.0",
- "@typescript-eslint/parser": "^8.50.0",
- "eslint": "^9.39.2",
- "globals": "^16.5.0",
- "husky": "^9.1.7",
- "patch-package": "^8.0.1",
- "prettier": "^3.7.4",
- "pretty-quick": "^4.2.2",
- "ts-node": "^10.9.2",
- "typescript": "^5.9.3",
- "typescript-json-schema": "^0.65.1"
- },
- "dependencies": {
- "@aws-sdk/client-s3": "^3.953.0",
- "@toondepauw/node-zstd": "^1.2.0",
- "ajv": "^8.17.1",
- "ajv-formats": "^3.0.1",
- "amqplib": "^0.10.9",
- "bcrypt": "^6.0.0",
- "body-parser": "^2.2.1",
- "chalk": "^5.6.2",
- "cheerio": "^1.1.2",
- "cookie-parser": "^1.4.7",
- "discord-protos": "^1.2.90",
- "dotenv": "^17.2.3",
- "email-providers": "^2.19.0",
- "exif-be-gone": "^1.5.1",
- "express": "^5.2.1",
- "fast-zlib": "^2.0.1",
- "fido2-lib": "^3.5.5",
- "file-type": "^21.1.1",
- "form-data": "^4.0.5",
- "i18next": "^25.7.3",
- "i18next-fs-backend": "^2.6.1",
- "i18next-http-middleware": "^3.9.0",
- "image-size": "^2.0.2",
- "json-bigint": "^1.0.0",
- "jsonwebtoken": "^9.0.3",
- "module-alias": "^2.2.3",
- "morgan": "^1.10.1",
- "ms": "^2.1.3",
- "multer": "^2.0.2",
- "murmurhash-js": "^1.0.0",
- "node-2fa": "^2.0.3",
- "pg": "^8.16.3",
- "pg-query-stream": "^4.10.3",
- "picocolors": "^1.1.1",
- "probe-image-size": "^7.2.3",
- "reflect-metadata": "^0.2.2",
- "sqlite3": "^5.1.7",
- "tslib": "^2.8.1",
- "typeorm": "^0.3.28",
- "wretch": "^2.11.1",
- "ws": "^8.18.3"
- },
- "_moduleAliases": {
- "@spacebar/api": "dist/api",
- "@spacebar/cdn": "dist/cdn",
- "@spacebar/gateway": "dist/gateway",
- "@spacebar/util": "dist/util",
- "@spacebar/webrtc": "dist/webrtc",
- "@spacebar/schemas": "dist/schemas",
- "lambert-server": "dist/util/util/lambert-server"
- },
- "optionalDependencies": {
- "@sendgrid/mail": "^8.1.6",
- "@yukikaze-bot/erlpack": "^1.0.1",
- "jimp": "^1.6.0",
- "mailgun.js": "^12.4.0",
- "node-mailjet": "^6.0.11",
- "nodemailer": "^7.0.11"
- }
+ "name": "spacebar-server",
+ "version": "1.0.0",
+ "description": "A Spacebar server written in Node.js",
+ "scripts": {
+ "prepare": "husky install",
+ "postinstall": "patch-package",
+ "start": "node --enable-source-maps dist/bundle/start.js",
+ "start:api": "node --enable-source-maps dist/api/start.js",
+ "start:cdn": "node --enable-source-maps dist/cdn/start.js",
+ "start:gateway": "node --enable-source-maps dist/gateway/start.js",
+ "build": "npm run build:src && npm run generate:schema && npm run generate:openapi",
+ "build:src": "tsc -b -v",
+ "watch": "tsc -w -b .",
+ "test": "node scripts/test.js",
+ "lint": "eslint .",
+ "setup": "npm run build && npm run generate:schema",
+ "sync:db": "npm run build && node scripts/syncronise.js",
+ "generate:rights": "node scripts/rights.js",
+ "generate:schema": "node scripts/schema.js",
+ "generate:migration": "node -r dotenv/config -r module-alias/register node_modules/typeorm/cli.js migration:generate -d dist/util/util/Database.js",
+ "generate:openapi": "node scripts/openapi.js",
+ "add:license": "node scripts/license.js",
+ "migrate-from-staging": "node -r dotenv/config -r module-alias/register scripts/stagingMigration/index.js",
+ "node:tests": "npm run build:src && node -r dotenv/config -r module-alias/register --enable-source-maps --test --experimental-test-coverage dist/**/*.test.js"
+ },
+ "main": "dist/bundle/index.js",
+ "types": "src/bundle/index.ts",
+ "repository": {
+ "type": "git",
+ "url": "git+https://github.com/spacebarchat/server.git"
+ },
+ "author": "Spacebar",
+ "license": "AGPL-3.0-only",
+ "bugs": {
+ "url": "https://github.com/spacebarchat/server/issues"
+ },
+ "imports": {
+ "#*": "./dist/*/index.js"
+ },
+ "homepage": "https://spacebar.chat",
+ "devDependencies": {
+ "@eslint/eslintrc": "^3.3.3",
+ "@eslint/js": "^9.14.0",
+ "@spacebarchat/spacebar-webrtc-types": "^1.0.1",
+ "@types/amqplib": "^0.10.8",
+ "@types/bcrypt": "^6.0.0",
+ "@types/body-parser": "^1.19.6",
+ "@types/cookie-parser": "^1.4.10",
+ "@types/express": "^5.0.6",
+ "@types/i18next-node-fs-backend": "^2.1.5",
+ "@types/json-bigint": "^1.0.4",
+ "@types/jsonwebtoken": "^9.0.10",
+ "@types/module-alias": "^2.0.4",
+ "@types/morgan": "^1.9.10",
+ "@types/multer": "^2.0.0",
+ "@types/murmurhash-js": "^1.0.6",
+ "@types/node": "^24.10.4",
+ "@types/nodemailer": "^7.0.4",
+ "@types/probe-image-size": "^7.2.5",
+ "@types/sharp": "^0.31.1",
+ "@types/ws": "^8.18.1",
+ "@typescript-eslint/eslint-plugin": "^8.50.0",
+ "@typescript-eslint/parser": "^8.50.0",
+ "eslint": "^9.39.2",
+ "globals": "^16.5.0",
+ "husky": "^9.1.7",
+ "patch-package": "^8.0.1",
+ "prettier": "^3.7.4",
+ "pretty-quick": "^4.2.2",
+ "ts-node": "^10.9.2",
+ "typescript": "^5.9.3",
+ "typescript-json-schema": "^0.65.1"
+ },
+ "dependencies": {
+ "@aws-sdk/client-s3": "^3.953.0",
+ "@toondepauw/node-zstd": "^1.2.0",
+ "ajv": "^8.17.1",
+ "ajv-formats": "^3.0.1",
+ "amqplib": "^0.10.9",
+ "bcrypt": "^6.0.0",
+ "body-parser": "^2.2.1",
+ "chalk": "^5.6.2",
+ "cheerio": "^1.1.2",
+ "cookie-parser": "^1.4.7",
+ "discord-protos": "^1.2.90",
+ "dotenv": "^17.2.3",
+ "email-providers": "^2.19.0",
+ "exif-be-gone": "^1.5.1",
+ "express": "^5.2.1",
+ "fast-zlib": "^2.0.1",
+ "fido2-lib": "^3.5.5",
+ "file-type": "^21.1.1",
+ "form-data": "^4.0.5",
+ "i18next": "^25.7.3",
+ "i18next-fs-backend": "^2.6.1",
+ "i18next-http-middleware": "^3.9.0",
+ "image-size": "^2.0.2",
+ "json-bigint": "^1.0.0",
+ "jsonwebtoken": "^9.0.3",
+ "module-alias": "^2.2.3",
+ "morgan": "^1.10.1",
+ "ms": "^2.1.3",
+ "multer": "^2.0.2",
+ "murmurhash-js": "^1.0.0",
+ "node-2fa": "^2.0.3",
+ "pg": "^8.16.3",
+ "pg-query-stream": "^4.10.3",
+ "picocolors": "^1.1.1",
+ "probe-image-size": "^7.2.3",
+ "reflect-metadata": "^0.2.2",
+ "sqlite3": "^5.1.7",
+ "tslib": "^2.8.1",
+ "typeorm": "^0.3.28",
+ "wretch": "^2.11.1",
+ "ws": "^8.18.3"
+ },
+ "_moduleAliases": {
+ "@spacebar/api": "dist/api",
+ "@spacebar/cdn": "dist/cdn",
+ "@spacebar/gateway": "dist/gateway",
+ "@spacebar/util": "dist/util",
+ "@spacebar/webrtc": "dist/webrtc",
+ "@spacebar/schemas": "dist/schemas",
+ "lambert-server": "dist/util/util/lambert-server"
+ },
+ "optionalDependencies": {
+ "@sendgrid/mail": "^8.1.6",
+ "@yukikaze-bot/erlpack": "^1.0.1",
+ "jimp": "^1.6.0",
+ "mailgun.js": "^12.4.0",
+ "node-mailjet": "^6.0.11",
+ "nodemailer": "^7.0.11"
+ }
}
diff --git a/scripts/genIndex.js b/scripts/genIndex.js
index c1b6822..e4601f3 100644
--- a/scripts/genIndex.js
+++ b/scripts/genIndex.js
@@ -41,29 +41,29 @@
// node scripts/genIndex.js /path/to/dir
const targetDir = process.argv[2];
if (!targetDir) {
- console.error("Please provide a target directory.");
- process.exit(1);
+ console.error("Please provide a target directory.");
+ process.exit(1);
}
if (fs.existsSync(path.join(targetDir, "index.js")) || fs.existsSync(path.join(targetDir, "index.ts"))) {
- console.error("index.js or index.ts already exists in the target directory.");
- process.exit(1);
+ console.error("index.js or index.ts already exists in the target directory.");
+ process.exit(1);
}
const dirs = fs.readdirSync(targetDir).filter((f) => fs.statSync(path.join(targetDir, f)).isDirectory());
for (const dir of dirs) {
- content += `export * from "./${dir}";\n`;
+ content += `export * from "./${dir}";\n`;
}
const files = fs.readdirSync(targetDir).filter((f) => f.endsWith(".js") || f.endsWith(".ts"));
for (const file of files) {
- const filePath = path.join(targetDir, file);
- const stat = fs.statSync(filePath);
- if (stat.isFile()) {
- const ext = path.extname(file);
- const base = path.basename(file, ext);
- content += `export * from "./${base}";\n`;
- }
+ const filePath = path.join(targetDir, file);
+ const stat = fs.statSync(filePath);
+ if (stat.isFile()) {
+ const ext = path.extname(file);
+ const base = path.basename(file, ext);
+ content += `export * from "./${base}";\n`;
+ }
}
fs.writeFileSync(path.join(targetDir, "index.ts"), content);
diff --git a/scripts/license.js b/scripts/license.js
index 380a3ed..0cc9b09 100644
--- a/scripts/license.js
+++ b/scripts/license.js
@@ -12,43 +12,43 @@
const SPACEBAR_SOURCE_DIR = Path.join(__dirname, "..", "src");
const SPACEBAR_SCRIPTS_DIR = Path.join(__dirname);
const SPACEBAR_LICENSE_PREAMBLE = fs
- .readFileSync(Path.join(__dirname, "util", "licensePreamble.txt"))
- .toString()
- .split("\r") // remove windows bs
- .join("") // ^
- .split("\n")
- .map((x) => `\t${x}`)
- .join("\n");
+ .readFileSync(Path.join(__dirname, "util", "licensePreamble.txt"))
+ .toString()
+ .split("\r") // remove windows bs
+ .join("") // ^
+ .split("\n")
+ .map((x) => `\t${x}`)
+ .join("\n");
const languageCommentStrings = {
- js: ["/*", "*/"],
- ts: ["/*", "*/"],
+ js: ["/*", "*/"],
+ ts: ["/*", "*/"],
};
const addToDir = (dir) => {
- const files = walk(dir, Object.keys(languageCommentStrings));
+ const files = walk(dir, Object.keys(languageCommentStrings));
- for (let path of files) {
- const file = fs.readFileSync(path).toString().split("\r").join("");
- const fileType = path.slice(path.lastIndexOf(".") + 1);
- const commentStrings = languageCommentStrings[fileType];
- if (!commentStrings) continue;
+ for (let path of files) {
+ const file = fs.readFileSync(path).toString().split("\r").join("");
+ const fileType = path.slice(path.lastIndexOf(".") + 1);
+ const commentStrings = languageCommentStrings[fileType];
+ if (!commentStrings) continue;
- const preamble = commentStrings[0] + "\n" + SPACEBAR_LICENSE_PREAMBLE + "\n" + commentStrings[1];
+ const preamble = commentStrings[0] + "\n" + SPACEBAR_LICENSE_PREAMBLE + "\n" + commentStrings[1];
- if (file.startsWith(preamble)) {
- continue;
- }
+ if (file.startsWith(preamble)) {
+ continue;
+ }
- // This is kind of lame.
- if (file.includes("@fc-license-skip") && path != __filename) {
- console.log(`skipping ${path} as it has a different license.`);
- continue;
- }
+ // This is kind of lame.
+ if (file.includes("@fc-license-skip") && path != __filename) {
+ console.log(`skipping ${path} as it has a different license.`);
+ continue;
+ }
- console.log(`writing to ${path}`);
- fs.writeFileSync(path, preamble + "\n\n" + file);
- }
+ console.log(`writing to ${path}`);
+ fs.writeFileSync(path, preamble + "\n\n" + file);
+ }
};
addToDir(SPACEBAR_SOURCE_DIR);
diff --git a/scripts/openapi.js b/scripts/openapi.js
index 39396d8..5afee15 100644
--- a/scripts/openapi.js
+++ b/scripts/openapi.js
@@ -32,227 +32,227 @@
const schemas = JSON.parse(fs.readFileSync(SchemaPath, { encoding: "utf8" }));
let specification = {
- openapi: "3.1.0",
- info: {
- title: "Spacebar Server",
- description:
- "Spacebar is a Discord.com server implementation and extension, with the goal of complete feature parity with Discord.com, all while adding some additional goodies, security, privacy, and configuration options.",
- license: {
- name: "AGPLV3",
- url: "https://www.gnu.org/licenses/agpl-3.0.en.html",
- },
- version: "1.0.0",
- },
- externalDocs: {
- description: "Spacebar Docs",
- url: "https://docs.spacebar.chat",
- },
- servers: [
- {
- url: "https://old.server.spacebar.chat/api/",
- description: "Official Spacebar Instance",
- },
- ],
- components: {
- securitySchemes: {
- bearer: {
- type: "http",
- scheme: "bearer",
- description: "Bearer/Bot prefixes are not required.",
- bearerFormat: "JWT",
- in: "header",
- },
- },
- },
- tags: [],
- paths: {},
+ openapi: "3.1.0",
+ info: {
+ title: "Spacebar Server",
+ description:
+ "Spacebar is a Discord.com server implementation and extension, with the goal of complete feature parity with Discord.com, all while adding some additional goodies, security, privacy, and configuration options.",
+ license: {
+ name: "AGPLV3",
+ url: "https://www.gnu.org/licenses/agpl-3.0.en.html",
+ },
+ version: "1.0.0",
+ },
+ externalDocs: {
+ description: "Spacebar Docs",
+ url: "https://docs.spacebar.chat",
+ },
+ servers: [
+ {
+ url: "https://old.server.spacebar.chat/api/",
+ description: "Official Spacebar Instance",
+ },
+ ],
+ components: {
+ securitySchemes: {
+ bearer: {
+ type: "http",
+ scheme: "bearer",
+ description: "Bearer/Bot prefixes are not required.",
+ bearerFormat: "JWT",
+ in: "header",
+ },
+ },
+ },
+ tags: [],
+ paths: {},
};
const schemaRegEx = new RegExp(/^[\w.]+$/);
function combineSchemas(schemas) {
- let definitions = {};
+ let definitions = {};
- for (const name in schemas) {
- definitions = {
- ...definitions,
- ...schemas[name].definitions,
- [name]: {
- ...schemas[name],
- definitions: undefined,
- $schema: undefined,
- },
- };
- }
+ for (const name in schemas) {
+ definitions = {
+ ...definitions,
+ ...schemas[name].definitions,
+ [name]: {
+ ...schemas[name],
+ definitions: undefined,
+ $schema: undefined,
+ },
+ };
+ }
- for (const key in definitions) {
- if (!schemaRegEx.test(key)) {
- console.error(` \x1b[5m${bgRedBright("ERROR")}\x1b[25m Invalid schema name: ${key}, context:`, definitions[key]);
- continue;
- }
- specification.components = specification.components || {};
- specification.components.schemas = specification.components.schemas || {};
- specification.components.schemas[key] = definitions[key];
- delete definitions[key].additionalProperties;
- delete definitions[key].$schema;
- const definition = definitions[key];
+ for (const key in definitions) {
+ if (!schemaRegEx.test(key)) {
+ console.error(` \x1b[5m${bgRedBright("ERROR")}\x1b[25m Invalid schema name: ${key}, context:`, definitions[key]);
+ continue;
+ }
+ specification.components = specification.components || {};
+ specification.components.schemas = specification.components.schemas || {};
+ specification.components.schemas[key] = definitions[key];
+ delete definitions[key].additionalProperties;
+ delete definitions[key].$schema;
+ const definition = definitions[key];
- if (typeof definition.properties === "object") {
- for (const property of Object.values(definition.properties)) {
- if (Array.isArray(property.type)) {
- if (property.type.includes("null")) {
- property.type = property.type.find((x) => x !== "null");
- property.nullable = true;
- }
- }
- }
- }
- }
+ if (typeof definition.properties === "object") {
+ for (const property of Object.values(definition.properties)) {
+ if (Array.isArray(property.type)) {
+ if (property.type.includes("null")) {
+ property.type = property.type.find((x) => x !== "null");
+ property.nullable = true;
+ }
+ }
+ }
+ }
+ }
- return definitions;
+ return definitions;
}
function getTag(key) {
- return key.match(/\/([\w-]+)/)[1];
+ return key.match(/\/([\w-]+)/)[1];
}
function apiRoutes(missingRoutes) {
- const routes = getRouteDescriptions();
+ const routes = getRouteDescriptions();
- // populate tags
- const tags = Array.from(routes.keys())
- .map((x) => getTag(x))
- .sort((a, b) => a.localeCompare(b));
- specification.tags = [...new Set(tags)].map((x) => ({ name: x }));
+ // populate tags
+ const tags = Array.from(routes.keys())
+ .map((x) => getTag(x))
+ .sort((a, b) => a.localeCompare(b));
+ specification.tags = [...new Set(tags)].map((x) => ({ name: x }));
- routes.forEach((route, pathAndMethod) => {
- const [p, method] = pathAndMethod.split("|");
- const path = p.replace(/:(\w+)/g, "{$1}");
+ routes.forEach((route, pathAndMethod) => {
+ const [p, method] = pathAndMethod.split("|");
+ const path = p.replace(/:(\w+)/g, "{$1}");
- let obj = specification.paths[path]?.[method] || {};
- obj["x-right-required"] = route.right;
- obj["x-permission-required"] = route.permission;
- obj["x-fires-event"] = route.event;
+ let obj = specification.paths[path]?.[method] || {};
+ obj["x-right-required"] = route.right;
+ obj["x-permission-required"] = route.permission;
+ obj["x-fires-event"] = route.event;
- if (
- !NO_AUTHORIZATION_ROUTES.some((x) => {
- if (typeof x === "string") return (method.toUpperCase() + " " + path).startsWith(x);
- return x.test(method.toUpperCase() + " " + path);
- })
- ) {
- obj.security = [{ bearer: [] }];
- }
+ if (
+ !NO_AUTHORIZATION_ROUTES.some((x) => {
+ if (typeof x === "string") return (method.toUpperCase() + " " + path).startsWith(x);
+ return x.test(method.toUpperCase() + " " + path);
+ })
+ ) {
+ obj.security = [{ bearer: [] }];
+ }
- if (route.description) obj.description = route.description;
- if (route.summary) obj.summary = route.summary;
- if (route.deprecated) obj.deprecated = route.deprecated;
+ if (route.description) obj.description = route.description;
+ if (route.summary) obj.summary = route.summary;
+ if (route.deprecated) obj.deprecated = route.deprecated;
- if (route.requestBody) {
- obj.requestBody = {
- required: true,
- content: {
- "application/json": {
- schema: {
- $ref: `#/components/schemas/${route.requestBody}`,
- },
- },
- },
- };
- }
+ if (route.requestBody) {
+ obj.requestBody = {
+ required: true,
+ content: {
+ "application/json": {
+ schema: {
+ $ref: `#/components/schemas/${route.requestBody}`,
+ },
+ },
+ },
+ };
+ }
- if (route.responses) {
- obj.responses = {};
+ if (route.responses) {
+ obj.responses = {};
- for (const [k, v] of Object.entries(route.responses)) {
- if (v.body)
- obj.responses[k] = {
- description: obj?.responses?.[k]?.description || "",
- content: {
- "application/json": {
- schema: {
- $ref: `#/components/schemas/${v.body}`,
- },
- },
- },
- };
- else
- obj.responses[k] = {
- description: obj?.responses?.[k]?.description || "No description available",
- };
- }
- } else {
- obj.responses = {
- default: {
- description: "No description available",
- },
- };
- }
+ for (const [k, v] of Object.entries(route.responses)) {
+ if (v.body)
+ obj.responses[k] = {
+ description: obj?.responses?.[k]?.description || "",
+ content: {
+ "application/json": {
+ schema: {
+ $ref: `#/components/schemas/${v.body}`,
+ },
+ },
+ },
+ };
+ else
+ obj.responses[k] = {
+ description: obj?.responses?.[k]?.description || "No description available",
+ };
+ }
+ } else {
+ obj.responses = {
+ default: {
+ description: "No description available",
+ },
+ };
+ }
- // handles path parameters
- if (p.includes(":")) {
- obj.parameters = p.match(/:\w+/g)?.map((x) => ({
- name: x.replace(":", ""),
- in: "path",
- required: true,
- schema: { type: "string" },
- description: x.replace(":", ""),
- }));
- }
+ // handles path parameters
+ if (p.includes(":")) {
+ obj.parameters = p.match(/:\w+/g)?.map((x) => ({
+ name: x.replace(":", ""),
+ in: "path",
+ required: true,
+ schema: { type: "string" },
+ description: x.replace(":", ""),
+ }));
+ }
- if (route.query) {
- // map to array
- const query = Object.entries(route.query).map(([k, v]) => ({
- name: k,
- in: "query",
- required: v.required,
- schema: { type: v.type },
- description: v.description,
- }));
+ if (route.query) {
+ // map to array
+ const query = Object.entries(route.query).map(([k, v]) => ({
+ name: k,
+ in: "query",
+ required: v.required,
+ schema: { type: v.type },
+ description: v.description,
+ }));
- obj.parameters = [...(obj.parameters || []), ...query];
- }
+ obj.parameters = [...(obj.parameters || []), ...query];
+ }
- obj.tags = [...new Set([...(obj.tags || []), getTag(p)])];
+ obj.tags = [...new Set([...(obj.tags || []), getTag(p)])];
- if (missingRoutes.additional.includes(path.replace(/\/$/, ""))) {
- obj["x-badges"] = [
- {
- label: "Spacebar-only",
- color: "red",
- },
- ];
- }
+ if (missingRoutes.additional.includes(path.replace(/\/$/, ""))) {
+ obj["x-badges"] = [
+ {
+ label: "Spacebar-only",
+ color: "red",
+ },
+ ];
+ }
- specification.paths[path] = Object.assign(specification.paths[path] || {}, {
- [method]: obj,
- });
- });
+ specification.paths[path] = Object.assign(specification.paths[path] || {}, {
+ [method]: obj,
+ });
+ });
}
async function main() {
- console.log("Generating OpenAPI Specification...");
+ console.log("Generating OpenAPI Specification...");
- const routesRes = await fetch("https://github.com/spacebarchat/missing-routes/raw/main/missing.json", {
- headers: {
- Accept: "application/json",
- },
- });
- const missingRoutes = await routesRes.json();
+ const routesRes = await fetch("https://github.com/spacebarchat/missing-routes/raw/main/missing.json", {
+ headers: {
+ Accept: "application/json",
+ },
+ });
+ const missingRoutes = await routesRes.json();
- combineSchemas(schemas);
- apiRoutes(missingRoutes);
+ combineSchemas(schemas);
+ apiRoutes(missingRoutes);
- fs.writeFileSync(openapiPath, JSON.stringify(specification, null, 4).replaceAll("#/definitions", "#/components/schemas").replaceAll("bigint", "number"));
- console.log("Wrote OpenAPI specification to", openapiPath);
- const elapsedMs = Number(totalSw.elapsed().totalMilliseconds + "." + totalSw.elapsed().microseconds);
- console.log(
- "Specification contains",
- Object.keys(specification.paths).length,
- "paths and",
- Object.keys(specification.components.schemas).length,
- "schemas in",
- elapsedMs,
- "ms.",
- );
+ fs.writeFileSync(openapiPath, JSON.stringify(specification, null, 4).replaceAll("#/definitions", "#/components/schemas").replaceAll("bigint", "number"));
+ console.log("Wrote OpenAPI specification to", openapiPath);
+ const elapsedMs = Number(totalSw.elapsed().totalMilliseconds + "." + totalSw.elapsed().microseconds);
+ console.log(
+ "Specification contains",
+ Object.keys(specification.paths).length,
+ "paths and",
+ Object.keys(specification.components.schemas).length,
+ "schemas in",
+ elapsedMs,
+ "ms.",
+ );
}
main();
diff --git a/scripts/schema.js b/scripts/schema.js
index 1779c8d..67c5563 100644
--- a/scripts/schema.js
+++ b/scripts/schema.js
@@ -24,10 +24,10 @@
const conWarn = console.warn;
console.warn = (...args) => {
- // silence some expected warnings
- if (args[0] === "initializer is expression for property id") return;
- if (args[0].startsWith("unknown initializer for property ") && args[0].endsWith("[object Object]")) return;
- conWarn(...args);
+ // silence some expected warnings
+ if (args[0] === "initializer is expression for property id") return;
+ if (args[0].startsWith("unknown initializer for property ") && args[0].endsWith("[object Object]")) return;
+ conWarn(...args);
};
const path = require("path");
@@ -41,27 +41,27 @@
// @type {TJS.PartialArgs}
const settings = {
- required: true,
- ignoreErrors: true,
- excludePrivate: true,
- defaultNumberType: "integer",
- noExtraProps: true,
- defaultProps: false,
- useTypeOfKeyword: true, // should help catch functions?
+ required: true,
+ ignoreErrors: true,
+ excludePrivate: true,
+ defaultNumberType: "integer",
+ noExtraProps: true,
+ defaultProps: false,
+ useTypeOfKeyword: true, // should help catch functions?
};
const baseClassProperties = [
- // BaseClass methods
- "toJSON",
- "hasId",
- "save",
- "remove",
- "softRemove",
- "recover",
- "reload",
- "assign",
- "_do_validate", // ?
- "hasId", // ?
+ // BaseClass methods
+ "toJSON",
+ "hasId",
+ "save",
+ "remove",
+ "softRemove",
+ "recover",
+ "reload",
+ "assign",
+ "_do_validate", // ?
+ "hasId", // ?
];
const ExcludeAndWarn = [...exclusionList.manualWarn, ...exclusionList.manualWarnRe.map((r) => new RegExp(r))];
@@ -69,315 +69,315 @@
const Included = [...exclusionList.include, ...exclusionList.includeRe.map((r) => new RegExp(r))];
const excludedLambdas = [
- (n, s) => {
- // attempt to import
- if (JSON.stringify(s).includes(`#/definitions/import(`)) {
- console.log(`\r${redBright("[WARN]")} Omitting schema ${n} as it attempted to use import().`);
- exclusionList.auto.push({ value: n, reason: "Uses import()" });
- return true;
- }
- },
- (n, s) => {
- if (JSON.stringify(s).includes(process.cwd())) {
- console.log(`\r${redBright("[WARN]")} Omitting schema ${n} as it leaked $PWD.`);
- exclusionList.auto.push({ value: n, reason: "Leaked $PWD" });
- return true;
- }
- },
- (n, s) => {
- if (JSON.stringify(s).includes(process.env.HOME)) {
- console.log(`\r${redBright("[WARN]")} Omitting schema ${n} as it leaked a $HOME path.`);
- exclusionList.auto.push({ value: n, reason: "Leaked $HOME" });
- return true;
- }
- },
- (n, s) => {
- if (s["$ref"] === `#/definitions/${n}`) {
- console.log(`\r${redBright("[WARN]")} Omitting schema ${n} as it is a self-reference only schema.`);
- exclusionList.auto.push({ value: n, reason: "Self-reference only schema" });
- // fs.writeFileSync(`fucked/${n}.json`, JSON.stringify(s, null, 4));
- return true;
- }
- },
- (n, s) => {
- if (s.description?.match(/Smithy/)) {
- console.log(`\r${redBright("[WARN]")} Omitting schema ${n} as it appears to be an AWS Smithy schema.`);
- exclusionList.auto.push({ value: n, reason: "AWS Smithy schema" });
- return true;
- }
- },
- (n, s) => {
- if (s.description?.startsWith("
")) {
- console.log(`\r${redBright("[WARN]")} Omitting schema ${n} as we don't use HTML paragraphs for descriptions.`);
- exclusionList.auto.push({ value: n, reason: "HTML paragraph in description" });
- return true;
- }
- },
- (n, s) => {
- if (s.properties && Object.keys(s.properties).every((x) => x[0] === x[0].toUpperCase())) {
- console.log(`\r${redBright("[WARN]")} Omitting schema ${n} as all its properties have uppercase characters.`);
- exclusionList.auto.push({ value: n, reason: "Schema with only uppercase properties" });
- return true;
- }
- },
- // (n, s) => {
- // if (JSON.stringify(s).length <= 300) {
- // console.log({n, s});
- // }
- // }
+ (n, s) => {
+ // attempt to import
+ if (JSON.stringify(s).includes(`#/definitions/import(`)) {
+ console.log(`\r${redBright("[WARN]")} Omitting schema ${n} as it attempted to use import().`);
+ exclusionList.auto.push({ value: n, reason: "Uses import()" });
+ return true;
+ }
+ },
+ (n, s) => {
+ if (JSON.stringify(s).includes(process.cwd())) {
+ console.log(`\r${redBright("[WARN]")} Omitting schema ${n} as it leaked $PWD.`);
+ exclusionList.auto.push({ value: n, reason: "Leaked $PWD" });
+ return true;
+ }
+ },
+ (n, s) => {
+ if (JSON.stringify(s).includes(process.env.HOME)) {
+ console.log(`\r${redBright("[WARN]")} Omitting schema ${n} as it leaked a $HOME path.`);
+ exclusionList.auto.push({ value: n, reason: "Leaked $HOME" });
+ return true;
+ }
+ },
+ (n, s) => {
+ if (s["$ref"] === `#/definitions/${n}`) {
+ console.log(`\r${redBright("[WARN]")} Omitting schema ${n} as it is a self-reference only schema.`);
+ exclusionList.auto.push({ value: n, reason: "Self-reference only schema" });
+ // fs.writeFileSync(`fucked/${n}.json`, JSON.stringify(s, null, 4));
+ return true;
+ }
+ },
+ (n, s) => {
+ if (s.description?.match(/Smithy/)) {
+ console.log(`\r${redBright("[WARN]")} Omitting schema ${n} as it appears to be an AWS Smithy schema.`);
+ exclusionList.auto.push({ value: n, reason: "AWS Smithy schema" });
+ return true;
+ }
+ },
+ (n, s) => {
+ if (s.description?.startsWith("
")) {
+ console.log(`\r${redBright("[WARN]")} Omitting schema ${n} as we don't use HTML paragraphs for descriptions.`);
+ exclusionList.auto.push({ value: n, reason: "HTML paragraph in description" });
+ return true;
+ }
+ },
+ (n, s) => {
+ if (s.properties && Object.keys(s.properties).every((x) => x[0] === x[0].toUpperCase())) {
+ console.log(`\r${redBright("[WARN]")} Omitting schema ${n} as all its properties have uppercase characters.`);
+ exclusionList.auto.push({ value: n, reason: "Schema with only uppercase properties" });
+ return true;
+ }
+ },
+ // (n, s) => {
+ // if (JSON.stringify(s).length <= 300) {
+ // console.log({n, s});
+ // }
+ // }
];
function includesMatch(haystack, needles, log = false) {
- for (const needle of needles) {
- const match = needle instanceof RegExp ? needle.test(haystack) : haystack === needle;
- if (match) {
- if (log) console.warn(redBright("[WARN]:"), "Excluding schema", haystack, "due to match with", needle);
- return needle;
- }
- }
- return null;
+ for (const needle of needles) {
+ const match = needle instanceof RegExp ? needle.test(haystack) : haystack === needle;
+ if (match) {
+ if (log) console.warn(redBright("[WARN]:"), "Excluding schema", haystack, "due to match with", needle);
+ return needle;
+ }
+ }
+ return null;
}
async function main() {
- const stepSw = Stopwatch.startNew();
+ const stepSw = Stopwatch.startNew();
- process.stdout.write("Loading program... ");
- const program = TJS.programFromConfig(path.join(__dirname, "..", "tsconfig.json"), walk(path.join(__dirname, "..", "src", "schemas")));
- const generator = TJS.buildGenerator(program, settings);
- if (!generator || !program) {
- console.log(redBright("Failed to create schema generator."));
- return;
- }
+ process.stdout.write("Loading program... ");
+ const program = TJS.programFromConfig(path.join(__dirname, "..", "tsconfig.json"), walk(path.join(__dirname, "..", "src", "schemas")));
+ const generator = TJS.buildGenerator(program, settings);
+ if (!generator || !program) {
+ console.log(redBright("Failed to create schema generator."));
+ return;
+ }
- const elapsedLoad = stepSw.getElapsedAndReset();
- process.stdout.write("Done in " + yellowBright(elapsedLoad.totalMilliseconds + "." + elapsedLoad.microseconds) + " ms\n");
+ const elapsedLoad = stepSw.getElapsedAndReset();
+ process.stdout.write("Done in " + yellowBright(elapsedLoad.totalMilliseconds + "." + elapsedLoad.microseconds) + " ms\n");
- process.stdout.write("Generating schema list... ");
- let schemas = generator.getUserSymbols().filter((x) => {
- return (
- (x.endsWith("Schema") || x.endsWith("Response") || x.startsWith("API")) &&
- // !ExcludeAndWarn.some((exc) => {
- // const match = exc instanceof RegExp ? exc.test(x) : x === exc;
- // if (match) console.warn("Warning: Excluding schema", x);
- // return match;
- // }) &&
- // !Excluded.some((exc) => (exc instanceof RegExp ? exc.test(x) : x === exc))
- (includesMatch(x, Included) || (!includesMatch(x, ExcludeAndWarn, true) && !includesMatch(x, Excluded)))
- );
- });
- //.sort((a,b) => a.localeCompare(b));
+ process.stdout.write("Generating schema list... ");
+ let schemas = generator.getUserSymbols().filter((x) => {
+ return (
+ (x.endsWith("Schema") || x.endsWith("Response") || x.startsWith("API")) &&
+ // !ExcludeAndWarn.some((exc) => {
+ // const match = exc instanceof RegExp ? exc.test(x) : x === exc;
+ // if (match) console.warn("Warning: Excluding schema", x);
+ // return match;
+ // }) &&
+ // !Excluded.some((exc) => (exc instanceof RegExp ? exc.test(x) : x === exc))
+ (includesMatch(x, Included) || (!includesMatch(x, ExcludeAndWarn, true) && !includesMatch(x, Excluded)))
+ );
+ });
+ //.sort((a,b) => a.localeCompare(b));
- const elapsedList = stepSw.getElapsedAndReset();
- process.stdout.write("Done in " + yellowBright(elapsedList.totalMilliseconds + "." + elapsedList.microseconds) + " ms\n");
- console.log("Found", yellowBright(schemas.length), "schemas to process.");
+ const elapsedList = stepSw.getElapsedAndReset();
+ process.stdout.write("Done in " + yellowBright(elapsedList.totalMilliseconds + "." + elapsedList.microseconds) + " ms\n");
+ console.log("Found", yellowBright(schemas.length), "schemas to process.");
- let definitions = {};
- let nestedDefinitions = {};
- let writePromises = [];
+ let definitions = {};
+ let nestedDefinitions = {};
+ let writePromises = [];
- if (process.env.WRITE_SCHEMA_DIR === "true") {
- fs.rmSync("schemas_orig", { recursive: true, force: true });
- fs.mkdirSync("schemas_orig");
+ if (process.env.WRITE_SCHEMA_DIR === "true") {
+ fs.rmSync("schemas_orig", { recursive: true, force: true });
+ fs.mkdirSync("schemas_orig");
- fs.rmSync("schemas_nested", { recursive: true, force: true });
- fs.mkdirSync("schemas_nested");
+ fs.rmSync("schemas_nested", { recursive: true, force: true });
+ fs.mkdirSync("schemas_nested");
- fs.rmSync("schemas_final", { recursive: true, force: true });
- fs.mkdirSync("schemas_final");
- }
+ fs.rmSync("schemas_final", { recursive: true, force: true });
+ fs.mkdirSync("schemas_final");
+ }
- const schemaSw = Stopwatch.startNew();
- for (const name of schemas) {
- process.stdout.write(`Processing schema ${name}... `);
- const part = TJS.generateSchema(program, name, settings, [], generator);
- if (!part) continue;
+ const schemaSw = Stopwatch.startNew();
+ for (const name of schemas) {
+ process.stdout.write(`Processing schema ${name}... `);
+ const part = TJS.generateSchema(program, name, settings, [], generator);
+ if (!part) continue;
- if (definitions[name]) {
- process.stdout.write(yellow(` [ERROR] Duplicate schema name detected: ${name}. Overwriting previous schema.`));
- }
+ if (definitions[name]) {
+ process.stdout.write(yellow(` [ERROR] Duplicate schema name detected: ${name}. Overwriting previous schema.`));
+ }
- if (!includesMatch(name, Included) && excludedLambdas.some((fn) => fn(name, part))) {
- continue;
- }
+ if (!includesMatch(name, Included) && excludedLambdas.some((fn) => fn(name, part))) {
+ continue;
+ }
- if (process.env.WRITE_SCHEMA_DIR === "true") writePromises.push(async () => await fsp.writeFile(path.join("schemas_orig", `${name}.json`), JSON.stringify(part, null, 4)));
+ if (process.env.WRITE_SCHEMA_DIR === "true") writePromises.push(async () => await fsp.writeFile(path.join("schemas_orig", `${name}.json`), JSON.stringify(part, null, 4)));
- // testing:
- function mergeDefs(schemaName, schema) {
- if (schema.definitions) {
- // schema["x-sb-defs"] = Object.keys(schema.definitions);
- process.stdout.write(cyanBright("Processing nested... "));
- for (const defKey in schema.definitions) {
- if (definitions[defKey] && deepEqual(definitions[defKey], schema.definitions[defKey])) {
- // console.log("Definition", defKey, "from schema", schemaName, "is identical to existing definition, skipping.");
- schema.definitions = Object.fromEntries(Object.entries(schema.definitions).filter(([k, v]) => k !== defKey));
- process.stdout.write(greenBright("T"));
- } else if (!nestedDefinitions[defKey]) {
- nestedDefinitions[defKey] = schema.definitions[defKey];
- schema.definitions = Object.fromEntries(Object.entries(schema.definitions).filter(([k, v]) => k !== defKey));
- // console.log("Tracking sub-definition", defKey, "from schema", schemaName);
- process.stdout.write(green("N"));
- } else if (!deepEqual(nestedDefinitions[defKey], schema.definitions[defKey])) {
- console.log(redBright("[ERROR]"), "Conflicting nested definition for", defKey, "found in schema", schemaName);
- console.log(columnizedObjectDiff(nestedDefinitions[defKey], schema.definitions[defKey], true));
- } else {
- // console.log("Definition", defKey, "from schema", schemaName, "is identical to existing definition, skipping.");
- schema.definitions = Object.fromEntries(Object.entries(schema.definitions).filter(([k, v]) => k !== defKey));
- process.stdout.write(greenBright("M"));
- }
- }
- if (Object.keys(schema.definitions).length === 0) {
- process.stdout.write(greenBright("✓ "));
- delete schema.definitions;
- } else {
- console.log("Remaining definitions in schema", schemaName, "after merge:", Object.keys(schema.definitions));
- }
- }
- }
- mergeDefs(name, part);
+ // testing:
+ function mergeDefs(schemaName, schema) {
+ if (schema.definitions) {
+ // schema["x-sb-defs"] = Object.keys(schema.definitions);
+ process.stdout.write(cyanBright("Processing nested... "));
+ for (const defKey in schema.definitions) {
+ if (definitions[defKey] && deepEqual(definitions[defKey], schema.definitions[defKey])) {
+ // console.log("Definition", defKey, "from schema", schemaName, "is identical to existing definition, skipping.");
+ schema.definitions = Object.fromEntries(Object.entries(schema.definitions).filter(([k, v]) => k !== defKey));
+ process.stdout.write(greenBright("T"));
+ } else if (!nestedDefinitions[defKey]) {
+ nestedDefinitions[defKey] = schema.definitions[defKey];
+ schema.definitions = Object.fromEntries(Object.entries(schema.definitions).filter(([k, v]) => k !== defKey));
+ // console.log("Tracking sub-definition", defKey, "from schema", schemaName);
+ process.stdout.write(green("N"));
+ } else if (!deepEqual(nestedDefinitions[defKey], schema.definitions[defKey])) {
+ console.log(redBright("[ERROR]"), "Conflicting nested definition for", defKey, "found in schema", schemaName);
+ console.log(columnizedObjectDiff(nestedDefinitions[defKey], schema.definitions[defKey], true));
+ } else {
+ // console.log("Definition", defKey, "from schema", schemaName, "is identical to existing definition, skipping.");
+ schema.definitions = Object.fromEntries(Object.entries(schema.definitions).filter(([k, v]) => k !== defKey));
+ process.stdout.write(greenBright("M"));
+ }
+ }
+ if (Object.keys(schema.definitions).length === 0) {
+ process.stdout.write(greenBright("✓ "));
+ delete schema.definitions;
+ } else {
+ console.log("Remaining definitions in schema", schemaName, "after merge:", Object.keys(schema.definitions));
+ }
+ }
+ }
+ mergeDefs(name, part);
- const elapsed = schemaSw.getElapsedAndReset();
- process.stdout.write(
- "Done in " + yellowBright(elapsed.totalMilliseconds + "." + elapsed.microseconds) + " ms, " + yellowBright(JSON.stringify(part).length) + " bytes (unformatted) ",
- );
- if (elapsed.totalMilliseconds >= 20) console.log(bgRedBright("\x1b[5m[SLOW]\x1b[25m"));
- else console.log();
+ const elapsed = schemaSw.getElapsedAndReset();
+ process.stdout.write(
+ "Done in " + yellowBright(elapsed.totalMilliseconds + "." + elapsed.microseconds) + " ms, " + yellowBright(JSON.stringify(part).length) + " bytes (unformatted) ",
+ );
+ if (elapsed.totalMilliseconds >= 20) console.log(bgRedBright("\x1b[5m[SLOW]\x1b[25m"));
+ else console.log();
- definitions = { ...definitions, [name]: { ...part } };
- }
- console.log("Processed", Object.keys(definitions).length, "schemas in", Number(stepSw.elapsed().totalMilliseconds + "." + stepSw.elapsed().microseconds), "ms.");
+ definitions = { ...definitions, [name]: { ...part } };
+ }
+ console.log("Processed", Object.keys(definitions).length, "schemas in", Number(stepSw.elapsed().totalMilliseconds + "." + stepSw.elapsed().microseconds), "ms.");
- console.log("Merging nested definitions into main definitions...");
- let isNewLine = true;
- for (const defKey in nestedDefinitions) {
- if (!includesMatch(defKey, Included, false)) {
- const bannedMatch = includesMatch(defKey, ExcludeAndWarn, false) ?? includesMatch(defKey, Excluded, false);
- if (bannedMatch !== null) {
- // console.log(yellowBright("\n[WARN]"), "Skipping nested definition", defKey, "as it matched a banned format.");
- console.log((isNewLine ? "" : "\n") + redBright("WARNING") + " Excluding schema " + yellowBright(defKey) + " due to match with " + redBright(bannedMatch));
- isNewLine = true;
- continue;
- }
- }
+ console.log("Merging nested definitions into main definitions...");
+ let isNewLine = true;
+ for (const defKey in nestedDefinitions) {
+ if (!includesMatch(defKey, Included, false)) {
+ const bannedMatch = includesMatch(defKey, ExcludeAndWarn, false) ?? includesMatch(defKey, Excluded, false);
+ if (bannedMatch !== null) {
+ // console.log(yellowBright("\n[WARN]"), "Skipping nested definition", defKey, "as it matched a banned format.");
+ console.log((isNewLine ? "" : "\n") + redBright("WARNING") + " Excluding schema " + yellowBright(defKey) + " due to match with " + redBright(bannedMatch));
+ isNewLine = true;
+ continue;
+ }
+ }
- nestedDefinitions[defKey]["$schema"] = "http://json-schema.org/draft-07/schema#";
- if (definitions[defKey]) {
- if (!deepEqual(definitions[defKey], nestedDefinitions[defKey])) {
- if (Object.keys(definitions[defKey]).every((k) => k === "$ref" || k === "$schema")) {
- definitions[defKey] = nestedDefinitions[defKey];
- console.log(yellowBright("\nWARNING"), "Overwriting definition for", defKey, "with nested definition (ref/schema only).");
- isNewLine = true;
- } else {
- console.log(redBright("\nERROR"), "Conflicting definition for", defKey, "found in main definitions.");
- console.log(columnizedObjectDiff(definitions[defKey], nestedDefinitions[defKey], true));
- console.log("Keys:", Object.keys(definitions[defKey]), Object.keys(nestedDefinitions[defKey]));
- isNewLine = true;
- }
- } else {
- // console.log("Definition", defKey, "is identical to existing definition, skipping.");
- }
- } else {
- definitions[defKey] = nestedDefinitions[defKey];
- if (isNewLine) {
- process.stdout.write("Adding nested definitions to main definitions: ");
- isNewLine = false;
- } else process.stdout.write("\x1b[4D, ");
- process.stdout.write(yellowBright(defKey) + "... ");
- }
- }
+ nestedDefinitions[defKey]["$schema"] = "http://json-schema.org/draft-07/schema#";
+ if (definitions[defKey]) {
+ if (!deepEqual(definitions[defKey], nestedDefinitions[defKey])) {
+ if (Object.keys(definitions[defKey]).every((k) => k === "$ref" || k === "$schema")) {
+ definitions[defKey] = nestedDefinitions[defKey];
+ console.log(yellowBright("\nWARNING"), "Overwriting definition for", defKey, "with nested definition (ref/schema only).");
+ isNewLine = true;
+ } else {
+ console.log(redBright("\nERROR"), "Conflicting definition for", defKey, "found in main definitions.");
+ console.log(columnizedObjectDiff(definitions[defKey], nestedDefinitions[defKey], true));
+ console.log("Keys:", Object.keys(definitions[defKey]), Object.keys(nestedDefinitions[defKey]));
+ isNewLine = true;
+ }
+ } else {
+ // console.log("Definition", defKey, "is identical to existing definition, skipping.");
+ }
+ } else {
+ definitions[defKey] = nestedDefinitions[defKey];
+ if (isNewLine) {
+ process.stdout.write("Adding nested definitions to main definitions: ");
+ isNewLine = false;
+ } else process.stdout.write("\x1b[4D, ");
+ process.stdout.write(yellowBright(defKey) + "... ");
+ }
+ }
- deleteOneOfKindUndefinedRecursive(definitions, "$");
- for (const defKey in definitions) {
- filterSchema(definitions[defKey]);
- }
+ deleteOneOfKindUndefinedRecursive(definitions, "$");
+ for (const defKey in definitions) {
+ filterSchema(definitions[defKey]);
+ }
- if (process.env.WRITE_SCHEMA_DIR === "true") {
- await Promise.all(writePromises);
- await Promise.all(
- Object.keys(definitions).map(async (name) => {
- await fsp.writeFile(path.join("schemas_final", `${name}.json`), JSON.stringify(definitions[name], null, 4));
- // console.log("Wrote schema", name, "to schemas/");
- }),
- );
- await Promise.all(
- Object.keys(nestedDefinitions).map(async (name) => {
- await fsp.writeFile(path.join("schemas_nested", `${name}.json`), JSON.stringify(nestedDefinitions[name], null, 4));
- // console.log("Wrote schema", name, "to schemas_nested/");
- }),
- );
- }
+ if (process.env.WRITE_SCHEMA_DIR === "true") {
+ await Promise.all(writePromises);
+ await Promise.all(
+ Object.keys(definitions).map(async (name) => {
+ await fsp.writeFile(path.join("schemas_final", `${name}.json`), JSON.stringify(definitions[name], null, 4));
+ // console.log("Wrote schema", name, "to schemas/");
+ }),
+ );
+ await Promise.all(
+ Object.keys(nestedDefinitions).map(async (name) => {
+ await fsp.writeFile(path.join("schemas_nested", `${name}.json`), JSON.stringify(nestedDefinitions[name], null, 4));
+ // console.log("Wrote schema", name, "to schemas_nested/");
+ }),
+ );
+ }
- fs.writeFileSync(schemaPath, JSON.stringify(definitions, null, 4));
- fs.writeFileSync(__dirname + "/schemaExclusions.json", JSON.stringify(exclusionList, null, 4));
- const elapsedMs = Number(totalSw.elapsed().totalMilliseconds + "." + totalSw.elapsed().microseconds);
- console.log("\nSuccessfully wrote", Object.keys(definitions).length, "schemas to", schemaPath, "in", elapsedMs, "ms,", fs.statSync(schemaPath).size, "bytes.");
+ fs.writeFileSync(schemaPath, JSON.stringify(definitions, null, 4));
+ fs.writeFileSync(__dirname + "/schemaExclusions.json", JSON.stringify(exclusionList, null, 4));
+ const elapsedMs = Number(totalSw.elapsed().totalMilliseconds + "." + totalSw.elapsed().microseconds);
+ console.log("\nSuccessfully wrote", Object.keys(definitions).length, "schemas to", schemaPath, "in", elapsedMs, "ms,", fs.statSync(schemaPath).size, "bytes.");
}
function deleteOneOfKindUndefinedRecursive(obj, path) {
- if (obj?.type === "object" && obj?.properties?.oneofKind?.type === "undefined") return true;
+ if (obj?.type === "object" && obj?.properties?.oneofKind?.type === "undefined") return true;
- for (const key in obj) {
- if (typeof obj[key] === "object" && deleteOneOfKindUndefinedRecursive(obj[key], path + "." + key)) {
- console.log("Deleting", path, key);
- delete obj[key];
- }
- }
+ for (const key in obj) {
+ if (typeof obj[key] === "object" && deleteOneOfKindUndefinedRecursive(obj[key], path + "." + key)) {
+ console.log("Deleting", path, key);
+ delete obj[key];
+ }
+ }
- return false;
+ return false;
}
function filterSchema(schema) {
- // this is a hack. we may want to check if its a @column instead
- if (schema.properties) {
- for (let key in schema.properties) {
- if (baseClassProperties.includes(key)) {
- delete schema.properties[key];
- }
- }
- }
+ // this is a hack. we may want to check if its a @column instead
+ if (schema.properties) {
+ for (let key in schema.properties) {
+ if (baseClassProperties.includes(key)) {
+ delete schema.properties[key];
+ }
+ }
+ }
- if (schema.required) schema.required = schema.required.filter((x) => !baseClassProperties.includes(x));
+ if (schema.required) schema.required = schema.required.filter((x) => !baseClassProperties.includes(x));
- // recurse into own definitions
- if (schema.definitions) {
- console.log(redBright("WARNING"), "Schema has own definitions, recursing into them to filter base class properties:", Object.keys(schema.definitions));
- for (const defKey in schema.definitions) {
- filterSchema(schema.definitions[defKey]);
- }
- }
+ // recurse into own definitions
+ if (schema.definitions) {
+ console.log(redBright("WARNING"), "Schema has own definitions, recursing into them to filter base class properties:", Object.keys(schema.definitions));
+ for (const defKey in schema.definitions) {
+ filterSchema(schema.definitions[defKey]);
+ }
+ }
}
function deepEqual(a, b) {
- if (a === b) return true;
+ if (a === b) return true;
- if (typeof a !== "object" || typeof b !== "object" || a == null || b == null) {
- return false;
- }
+ if (typeof a !== "object" || typeof b !== "object" || a == null || b == null) {
+ return false;
+ }
- const keysA = Object.keys(a);
- const keysB = Object.keys(b);
+ const keysA = Object.keys(a);
+ const keysB = Object.keys(b);
- if (keysA.length !== keysB.length) return false;
+ if (keysA.length !== keysB.length) return false;
- for (const key of keysA) {
- if (!keysB.includes(key) || (typeof a[key] === typeof b[key] && !deepEqual(a[key], b[key]))) {
- return false;
- }
- }
+ for (const key of keysA) {
+ if (!keysB.includes(key) || (typeof a[key] === typeof b[key] && !deepEqual(a[key], b[key]))) {
+ return false;
+ }
+ }
- return true;
+ return true;
}
function columnizedObjectDiff(a, b, trackEqual = false) {
- const diffs = { left: {}, right: {}, ...(trackEqual ? { equal: {} } : {}) };
- const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
- for (const key of keys) {
- if (!deepEqual(a[key], b[key])) {
- diffs.left[key] = a[key];
- diffs.right[key] = b[key];
- } else if (trackEqual) diffs.equal[key] = a[key];
- }
- return diffs;
+ const diffs = { left: {}, right: {}, ...(trackEqual ? { equal: {} } : {}) };
+ const keys = new Set([...Object.keys(a), ...Object.keys(b)]);
+ for (const key of keys) {
+ if (!deepEqual(a[key], b[key])) {
+ diffs.left[key] = a[key];
+ diffs.right[key] = b[key];
+ } else if (trackEqual) diffs.equal[key] = a[key];
+ }
+ return diffs;
}
main();
diff --git a/scripts/schemaExclusions.json b/scripts/schemaExclusions.json
index 389cb4f..64e2bbf 100644
--- a/scripts/schemaExclusions.json
+++ b/scripts/schemaExclusions.json
@@ -1,409 +1,415 @@
{
- "include": ["MessageInteractionSchema"],
- "includeRe": ["^MessageComponentType\\..*"],
- "manual": [
- "DefaultSchema",
- "Schema",
- "EntitySchema",
- "ReadableStream",
- "SomeJSONSchema",
- "UncheckedPartialSchema",
- "PartialSchema",
- "UncheckedPropertiesSchema",
- "PropertiesSchema",
- "AsyncSchema",
- "AnySchema",
- "SMTPConnection.CustomAuthenticationResponse",
- "TransportMakeRequestResponse",
- "StaticSchema",
- "CSVImportResponse",
- "NewMultipleMembersResponse",
- "EventsResponse",
- "NotificationAPIResponse",
- "MetricsAPIResponse",
- "ValidationResponse",
- "MultipleValidationJobsListResponse",
- "UpdateRouteResponse",
- "MessagesSendAPIResponse",
- "APIWebhook",
- "WebhookResponse",
- "WebhookValidationResponse",
- "MessageResponse",
- "ConnectionSettingsResponse",
- "UpdatedDKIMSelectorResponse",
- "UpdatedWebPrefixResponse",
- "APIResponse",
- "APIErrorOptions",
- "APIErrorType",
- "ListTagsForResourceResponse",
- "GetContactResponse",
- "LibraryResponse",
- "LibraryLocalResponse",
- "SchemaTraits",
- "TraitsSchema",
- "AbuseIpDbCheckResponse",
- "IpDataIpLookupResponse"
- ],
- "manualRe": [
- ".*\\.Response$",
- "^(Http2Server|Server|Express|(Resolved|)Http|Client|_|)Response$",
- ".*\\..*",
- "^Axios.*",
- "^Internal",
- "^Record<",
- "^Omit<",
- "^ListContact(s|Lists)Response$",
- "^APIKeyConfiguration\\..*",
- "^AccountSetting\\..*",
- "^BulkContactManagement\\..*",
- "^Campaign.*",
- "^Contact.*",
- "^DNS\\..*",
- "^Delete.*",
- "^Destroy.*",
- "^Template\\..*",
- "^Webhook\\..*",
- "^(BigDecimal|BigInteger|Blob|Boolean|Document|Error|LazyRequest|List|Map|Normalized|Numeric|StreamingBlob|TimestampDateTime|TimestampHttpDate|TimestampEpochSeconds|Simple)Schema",
- "^((Create|Update)Contact(|List))Response$",
- "^(T|Unt)agResourceResponse$",
- "^Put",
- "^Inbox",
- "^Seed",
- "^DomainTag",
- "^IpPool",
- "DomainTemplate",
- "^\\$",
- "^Suppression",
- "^Mail(|ing)List",
- "DomainTracking",
- "UpdatedDomain",
- "ConfigurationSet",
- "ContactList",
- "^IPR",
- "^Job"
- ],
- "manualWarn": [],
- "manualWarnRe": [".*<.*>$"],
- "auto": [
- {
- "value": "StringSchema",
- "reason": "AWS Smithy schema"
- },
- {
- "value": "TimestampDefaultSchema",
- "reason": "AWS Smithy schema"
- },
- {
- "value": "StaticSimpleSchema",
- "reason": "Self-reference only schema"
- },
- {
- "value": "StaticListSchema",
- "reason": "Self-reference only schema"
- },
- {
- "value": "StaticMapSchema",
- "reason": "Self-reference only schema"
- },
- {
- "value": "StaticStructureSchema",
- "reason": "Self-reference only schema"
- },
- {
- "value": "StaticErrorSchema",
- "reason": "Self-reference only schema"
- },
- {
- "value": "StaticOperationSchema",
- "reason": "Self-reference only schema"
- },
- {
- "value": "UnitSchema",
- "reason": "AWS Smithy schema"
- },
- {
- "value": "MemberSchema",
- "reason": "Self-reference only schema"
- },
- {
- "value": "StructureSchema",
- "reason": "Self-reference only schema"
- },
- {
- "value": "OperationSchema",
- "reason": "Self-reference only schema"
- },
- {
- "value": "BatchGetMetricDataResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "CancelExportJobResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "CreateCustomVerificationEmailTemplateResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "CreateDedicatedIpPoolResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "CreateDeliverabilityTestReportResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "CreateEmailIdentityResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "CreateEmailIdentityPolicyResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "CreateEmailTemplateResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "CreateExportJobResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "CreateImportJobResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "CreateMultiRegionEndpointResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "CreateTenantResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "CreateTenantResourceAssociationResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetAccountResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetBlacklistReportsResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetCustomVerificationEmailTemplateResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetDedicatedIpResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetDedicatedIpPoolResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetDedicatedIpsResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetDeliverabilityDashboardOptionsResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetDeliverabilityTestReportResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetDomainDeliverabilityCampaignResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetDomainStatisticsReportResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetEmailIdentityResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetEmailIdentityPoliciesResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetEmailTemplateResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetExportJobResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetImportJobResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetMessageInsightsResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetMultiRegionEndpointResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetReputationEntityResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetSuppressedDestinationResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "GetTenantResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListCustomVerificationEmailTemplatesResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListDedicatedIpPoolsResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListDeliverabilityTestReportsResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListDomainDeliverabilityCampaignsResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListEmailIdentitiesResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListEmailTemplatesResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListExportJobsResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListImportJobsResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListMultiRegionEndpointsResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListRecommendationsResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListReputationEntitiesResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListResourceTenantsResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListSuppressedDestinationsResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListTenantResourcesResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "ListTenantsResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "SendBulkEmailResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "SendCustomVerificationEmailResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "SendEmailResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "TestRenderEmailTemplateResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "UpdateCustomVerificationEmailTemplateResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "UpdateEmailIdentityPolicyResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "UpdateEmailTemplateResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "UpdateReputationEntityCustomerManagedStatusResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "UpdateReputationEntityPolicyResponse",
- "reason": "HTML paragraph in description"
- },
- {
- "value": "UpdatedDKIMAuthorityResponse",
- "reason": "Uses import()"
- },
- {
- "value": "ListRecipientResponse",
- "reason": "Schema with only uppercase properties"
- },
- {
- "value": "TemplateResponse",
- "reason": "Schema with only uppercase properties"
- },
- {
- "value": "TemplateDetailContentResponse",
- "reason": "Schema with only uppercase properties"
- },
- {
- "value": "EventCallbackUrlResponse",
- "reason": "Schema with only uppercase properties"
- },
- {
- "value": "ParseRouteResponse",
- "reason": "Schema with only uppercase properties"
- },
- {
- "value": "SenderResponse",
- "reason": "Schema with only uppercase properties"
- },
- {
- "value": "MetaSenderResponse",
- "reason": "Schema with only uppercase properties"
- },
- {
- "value": "ApiKeyResponse",
- "reason": "Schema with only uppercase properties"
- },
- {
- "value": "MyProfileResponse",
- "reason": "Schema with only uppercase properties"
- },
- {
- "value": "UserResponse",
- "reason": "Schema with only uppercase properties"
- }
- ]
-}
+ "include": [
+ "MessageInteractionSchema"
+ ],
+ "includeRe": [
+ "^MessageComponentType\\..*"
+ ],
+ "manual": [
+ "DefaultSchema",
+ "Schema",
+ "EntitySchema",
+ "ReadableStream",
+ "SomeJSONSchema",
+ "UncheckedPartialSchema",
+ "PartialSchema",
+ "UncheckedPropertiesSchema",
+ "PropertiesSchema",
+ "AsyncSchema",
+ "AnySchema",
+ "SMTPConnection.CustomAuthenticationResponse",
+ "TransportMakeRequestResponse",
+ "StaticSchema",
+ "CSVImportResponse",
+ "NewMultipleMembersResponse",
+ "EventsResponse",
+ "NotificationAPIResponse",
+ "MetricsAPIResponse",
+ "ValidationResponse",
+ "MultipleValidationJobsListResponse",
+ "UpdateRouteResponse",
+ "MessagesSendAPIResponse",
+ "APIWebhook",
+ "WebhookResponse",
+ "WebhookValidationResponse",
+ "MessageResponse",
+ "ConnectionSettingsResponse",
+ "UpdatedDKIMSelectorResponse",
+ "UpdatedWebPrefixResponse",
+ "APIResponse",
+ "APIErrorOptions",
+ "APIErrorType",
+ "ListTagsForResourceResponse",
+ "GetContactResponse",
+ "LibraryResponse",
+ "LibraryLocalResponse",
+ "SchemaTraits",
+ "TraitsSchema",
+ "AbuseIpDbCheckResponse",
+ "IpDataIpLookupResponse"
+ ],
+ "manualRe": [
+ ".*\\.Response$",
+ "^(Http2Server|Server|Express|(Resolved|)Http|Client|_|)Response$",
+ ".*\\..*",
+ "^Axios.*",
+ "^Internal",
+ "^Record<",
+ "^Omit<",
+ "^ListContact(s|Lists)Response$",
+ "^APIKeyConfiguration\\..*",
+ "^AccountSetting\\..*",
+ "^BulkContactManagement\\..*",
+ "^Campaign.*",
+ "^Contact.*",
+ "^DNS\\..*",
+ "^Delete.*",
+ "^Destroy.*",
+ "^Template\\..*",
+ "^Webhook\\..*",
+ "^(BigDecimal|BigInteger|Blob|Boolean|Document|Error|LazyRequest|List|Map|Normalized|Numeric|StreamingBlob|TimestampDateTime|TimestampHttpDate|TimestampEpochSeconds|Simple)Schema",
+ "^((Create|Update)Contact(|List))Response$",
+ "^(T|Unt)agResourceResponse$",
+ "^Put",
+ "^Inbox",
+ "^Seed",
+ "^DomainTag",
+ "^IpPool",
+ "DomainTemplate",
+ "^\\$",
+ "^Suppression",
+ "^Mail(|ing)List",
+ "DomainTracking",
+ "UpdatedDomain",
+ "ConfigurationSet",
+ "ContactList",
+ "^IPR",
+ "^Job"
+ ],
+ "manualWarn": [],
+ "manualWarnRe": [
+ ".*<.*>$"
+ ],
+ "auto": [
+ {
+ "value": "StringSchema",
+ "reason": "AWS Smithy schema"
+ },
+ {
+ "value": "TimestampDefaultSchema",
+ "reason": "AWS Smithy schema"
+ },
+ {
+ "value": "StaticSimpleSchema",
+ "reason": "Self-reference only schema"
+ },
+ {
+ "value": "StaticListSchema",
+ "reason": "Self-reference only schema"
+ },
+ {
+ "value": "StaticMapSchema",
+ "reason": "Self-reference only schema"
+ },
+ {
+ "value": "StaticStructureSchema",
+ "reason": "Self-reference only schema"
+ },
+ {
+ "value": "StaticErrorSchema",
+ "reason": "Self-reference only schema"
+ },
+ {
+ "value": "StaticOperationSchema",
+ "reason": "Self-reference only schema"
+ },
+ {
+ "value": "UnitSchema",
+ "reason": "AWS Smithy schema"
+ },
+ {
+ "value": "MemberSchema",
+ "reason": "Self-reference only schema"
+ },
+ {
+ "value": "StructureSchema",
+ "reason": "Self-reference only schema"
+ },
+ {
+ "value": "OperationSchema",
+ "reason": "Self-reference only schema"
+ },
+ {
+ "value": "BatchGetMetricDataResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "CancelExportJobResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "CreateCustomVerificationEmailTemplateResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "CreateDedicatedIpPoolResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "CreateDeliverabilityTestReportResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "CreateEmailIdentityResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "CreateEmailIdentityPolicyResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "CreateEmailTemplateResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "CreateExportJobResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "CreateImportJobResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "CreateMultiRegionEndpointResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "CreateTenantResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "CreateTenantResourceAssociationResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetAccountResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetBlacklistReportsResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetCustomVerificationEmailTemplateResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetDedicatedIpResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetDedicatedIpPoolResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetDedicatedIpsResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetDeliverabilityDashboardOptionsResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetDeliverabilityTestReportResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetDomainDeliverabilityCampaignResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetDomainStatisticsReportResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetEmailIdentityResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetEmailIdentityPoliciesResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetEmailTemplateResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetExportJobResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetImportJobResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetMessageInsightsResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetMultiRegionEndpointResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetReputationEntityResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetSuppressedDestinationResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "GetTenantResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListCustomVerificationEmailTemplatesResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListDedicatedIpPoolsResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListDeliverabilityTestReportsResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListDomainDeliverabilityCampaignsResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListEmailIdentitiesResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListEmailTemplatesResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListExportJobsResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListImportJobsResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListMultiRegionEndpointsResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListRecommendationsResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListReputationEntitiesResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListResourceTenantsResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListSuppressedDestinationsResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListTenantResourcesResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "ListTenantsResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "SendBulkEmailResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "SendCustomVerificationEmailResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "SendEmailResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "TestRenderEmailTemplateResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "UpdateCustomVerificationEmailTemplateResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "UpdateEmailIdentityPolicyResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "UpdateEmailTemplateResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "UpdateReputationEntityCustomerManagedStatusResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "UpdateReputationEntityPolicyResponse",
+ "reason": "HTML paragraph in description"
+ },
+ {
+ "value": "UpdatedDKIMAuthorityResponse",
+ "reason": "Uses import()"
+ },
+ {
+ "value": "ListRecipientResponse",
+ "reason": "Schema with only uppercase properties"
+ },
+ {
+ "value": "TemplateResponse",
+ "reason": "Schema with only uppercase properties"
+ },
+ {
+ "value": "TemplateDetailContentResponse",
+ "reason": "Schema with only uppercase properties"
+ },
+ {
+ "value": "EventCallbackUrlResponse",
+ "reason": "Schema with only uppercase properties"
+ },
+ {
+ "value": "ParseRouteResponse",
+ "reason": "Schema with only uppercase properties"
+ },
+ {
+ "value": "SenderResponse",
+ "reason": "Schema with only uppercase properties"
+ },
+ {
+ "value": "MetaSenderResponse",
+ "reason": "Schema with only uppercase properties"
+ },
+ {
+ "value": "ApiKeyResponse",
+ "reason": "Schema with only uppercase properties"
+ },
+ {
+ "value": "MyProfileResponse",
+ "reason": "Schema with only uppercase properties"
+ },
+ {
+ "value": "UserResponse",
+ "reason": "Schema with only uppercase properties"
+ }
+ ]
+}
\ No newline at end of file
diff --git a/scripts/stress/identify.js b/scripts/stress/identify.js
index 478643f..08d8d5d 100644
--- a/scripts/stress/identify.js
+++ b/scripts/stress/identify.js
@@ -8,45 +8,45 @@
const TOTAL_ITERATIONS = process.env.ITER ? parseInt(process.env.ITER) : 500;
const doTimedIdentify = () =>
- new Promise((resolve) => {
- let start;
- const ws = new WebSocket(ENDPOINT);
- ws.on("message", (data) => {
- const parsed = JSON.parse(data);
+ new Promise((resolve) => {
+ let start;
+ const ws = new WebSocket(ENDPOINT);
+ ws.on("message", (data) => {
+ const parsed = JSON.parse(data);
- switch (parsed.op) {
- case OPCODES.Hello:
- // send identify
- start = performance.now();
- ws.send(
- JSON.stringify({
- op: OPCODES.Identify,
- d: {
- token: TOKEN,
- properties: {},
- },
- }),
- );
- break;
- case OPCODES.Dispatch:
- if (parsed.t == "READY") {
- ws.close();
- return resolve(performance.now() - start);
- }
+ switch (parsed.op) {
+ case OPCODES.Hello:
+ // send identify
+ start = performance.now();
+ ws.send(
+ JSON.stringify({
+ op: OPCODES.Identify,
+ d: {
+ token: TOKEN,
+ properties: {},
+ },
+ }),
+ );
+ break;
+ case OPCODES.Dispatch:
+ if (parsed.t == "READY") {
+ ws.close();
+ return resolve(performance.now() - start);
+ }
- break;
- }
- });
- });
+ break;
+ }
+ });
+ });
(async () => {
- const perfs = [];
- while (perfs.length < TOTAL_ITERATIONS) {
- const ret = await doTimedIdentify();
- perfs.push(ret);
- // console.log(`${perfs.length}/${TOTAL_ITERATIONS} - this: ${Math.floor(ret)}ms`)
- }
+ const perfs = [];
+ while (perfs.length < TOTAL_ITERATIONS) {
+ const ret = await doTimedIdentify();
+ perfs.push(ret);
+ // console.log(`${perfs.length}/${TOTAL_ITERATIONS} - this: ${Math.floor(ret)}ms`)
+ }
- const avg = perfs.reduce((prev, curr) => prev + curr) / (perfs.length - 1);
- console.log(`Average identify time: ${Math.floor(avg * 100) / 100}ms`);
+ const avg = perfs.reduce((prev, curr) => prev + curr) / (perfs.length - 1);
+ console.log(`Average identify time: ${Math.floor(avg * 100) / 100}ms`);
})();
diff --git a/scripts/stress/login.js b/scripts/stress/login.js
index 5cb254d..830d6a4 100644
--- a/scripts/stress/login.js
+++ b/scripts/stress/login.js
@@ -1,16 +1,16 @@
const ENDPOINT = process.env.API || "http://localhost:3001";
async function main() {
- const ret = await fetch(`${ENDPOINT}/api/auth/login`, {
- method: "POST",
- body: JSON.stringify({
- login: process.argv[2],
- password: process.argv[3],
- }),
- headers: { "content-type": "application/json " },
- });
+ const ret = await fetch(`${ENDPOINT}/api/auth/login`, {
+ method: "POST",
+ body: JSON.stringify({
+ login: process.argv[2],
+ password: process.argv[3],
+ }),
+ headers: { "content-type": "application/json " },
+ });
- console.log((await ret.json()).token);
+ console.log((await ret.json()).token);
}
main();
diff --git a/scripts/stress/users.js b/scripts/stress/users.js
index 67fa3ec..2fc41ea 100644
--- a/scripts/stress/users.js
+++ b/scripts/stress/users.js
@@ -21,22 +21,22 @@
const endpoint = process.env.API || "http://localhost:3001";
async function main() {
- for (let i = 0; i < count; i++) {
- fetch(`${endpoint}/api/auth/register`, {
- method: "POST",
- body: JSON.stringify({
- fingerprint: `${i}.wR8vi8lGlFBJerErO9LG5NViJFw`,
- username: `test${i}`,
- invite: null,
- consent: true,
- date_of_birth: "2000-01-01",
- gift_code_sku_id: null,
- captcha_key: null,
- }),
- headers: { "content-type": "application/json" },
- });
- console.log(i);
- }
+ for (let i = 0; i < count; i++) {
+ fetch(`${endpoint}/api/auth/register`, {
+ method: "POST",
+ body: JSON.stringify({
+ fingerprint: `${i}.wR8vi8lGlFBJerErO9LG5NViJFw`,
+ username: `test${i}`,
+ invite: null,
+ consent: true,
+ date_of_birth: "2000-01-01",
+ gift_code_sku_id: null,
+ captcha_key: null,
+ }),
+ headers: { "content-type": "application/json" },
+ });
+ console.log(i);
+ }
}
main();
diff --git a/scripts/syncronise.js b/scripts/syncronise.js
index 1f3ed11..58c1802 100644
--- a/scripts/syncronise.js
+++ b/scripts/syncronise.js
@@ -30,9 +30,9 @@
const { initDatabase } = require("..");
(async () => {
- const db = await initDatabase();
- console.log("synchronising");
- await db.synchronize();
- console.log("done");
- db.destroy();
+ const db = await initDatabase();
+ console.log("synchronising");
+ await db.synchronize();
+ console.log("done");
+ db.destroy();
})();
diff --git a/scripts/test.js b/scripts/test.js
index c79e336..3f94413 100644
--- a/scripts/test.js
+++ b/scripts/test.js
@@ -29,34 +29,34 @@
process.env.CONFIG_PATH = cfgFile;
fs.writeFileSync(
- cfgFile,
- JSON.stringify({
- api: { endpointPublic: "http://localhost:3001/api/v9/" },
- cdn: { endpointPublic: "http://localhost:3001/", endpointPrivate: "http://localhost:3001/" },
- gateway: { endpointPublic: "ws://localhost:3001/" },
- }),
+ cfgFile,
+ JSON.stringify({
+ api: { endpointPublic: "http://localhost:3001/api/v9/" },
+ cdn: { endpointPublic: "http://localhost:3001/", endpointPrivate: "http://localhost:3001/" },
+ gateway: { endpointPublic: "ws://localhost:3001/" },
+ }),
);
const server = spawn("node", [path.join(__dirname, "..", "dist", "bundle", "start.js")]);
server.stdout.on("data", (data) => {
- process.stdout.write(data);
+ process.stdout.write(data);
- if (data.toString().toLowerCase().includes("listening")) {
- // we good :)
- console.log("we good");
- server.kill();
- process.exit();
- }
+ if (data.toString().toLowerCase().includes("listening")) {
+ // we good :)
+ console.log("we good");
+ server.kill();
+ process.exit();
+ }
});
server.stderr.on("data", (err) => {
- process.stdout.write(err);
- // we bad :(
- process.kill(1);
+ process.stdout.write(err);
+ // we bad :(
+ process.kill(1);
});
server.on("close", (code) => {
- console.log("closed with code", code);
- process.exit(code);
+ console.log("closed with code", code);
+ process.exit(code);
});
diff --git a/scripts/util/getRouteDescriptions.js b/scripts/util/getRouteDescriptions.js
index 1f27141..87f1d4e 100644
--- a/scripts/util/getRouteDescriptions.js
+++ b/scripts/util/getRouteDescriptions.js
@@ -15,24 +15,24 @@
*/
function colorizeMethod(method) {
- switch (method.toLowerCase()) {
- case "get":
- return greenBright(method.toUpperCase());
- case "post":
- return yellowBright(method.toUpperCase());
- case "put":
- return blueBright(method.toUpperCase());
- case "delete":
- return redBright(method.toUpperCase());
- case "patch":
- return yellowBright(method.toUpperCase());
- default:
- return method.toUpperCase();
- }
+ switch (method.toLowerCase()) {
+ case "get":
+ return greenBright(method.toUpperCase());
+ case "post":
+ return yellowBright(method.toUpperCase());
+ case "put":
+ return blueBright(method.toUpperCase());
+ case "delete":
+ return redBright(method.toUpperCase());
+ case "patch":
+ return yellowBright(method.toUpperCase());
+ default:
+ return method.toUpperCase();
+ }
}
function formatPath(path) {
- return path.replace(/:(\w+)/g, underline(":$1")).replace(/#(\w+)/g, underline("#$1"));
+ return path.replace(/:(\w+)/g, underline(":$1")).replace(/#(\w+)/g, underline("#$1"));
}
/**
@@ -43,45 +43,45 @@
* @param args
*/
function proxy(file, apiMethod, apiPathPrefix, apiPath, ...args) {
- const opts = args.find((x) => x?.prototype?.OPTS_MARKER == true);
- if (!opts)
- return console.error(
- ` \x1b[5m${bgRedBright("ERROR")}\x1b[25m ${file.replace(path.resolve(__dirname, "..", "..", "dist"), "/src")} has route without route() description middleware: ${colorizeMethod(apiMethod)} ${formatPath(apiPath)}`,
- );
+ const opts = args.find((x) => x?.prototype?.OPTS_MARKER == true);
+ if (!opts)
+ return console.error(
+ ` \x1b[5m${bgRedBright("ERROR")}\x1b[25m ${file.replace(path.resolve(__dirname, "..", "..", "dist"), "/src")} has route without route() description middleware: ${colorizeMethod(apiMethod)} ${formatPath(apiPath)}`,
+ );
- console.log(`${colorizeMethod(apiMethod).padStart("DELETE".length + 10)} ${formatPath(apiPathPrefix + apiPath)}`);
- opts.file = file.replace("/dist/", "/src/").replace(".js", ".ts");
- routes.set(apiPathPrefix + apiPath + "|" + apiMethod, opts());
+ console.log(`${colorizeMethod(apiMethod).padStart("DELETE".length + 10)} ${formatPath(apiPathPrefix + apiPath)}`);
+ opts.file = file.replace("/dist/", "/src/").replace(".js", ".ts");
+ routes.set(apiPathPrefix + apiPath + "|" + apiMethod, opts());
}
express.Router = () => {
- return Object.fromEntries(methods.map((method) => [method, proxy.bind(null, currentFile, method, currentPath)]));
+ return Object.fromEntries(methods.map((method) => [method, proxy.bind(null, currentFile, method, currentPath)]));
};
RouteUtility.route = (opts) => {
- const func = function () {
- return opts;
- };
- func.prototype.OPTS_MARKER = true;
- return func;
+ const func = function () {
+ return opts;
+ };
+ func.prototype.OPTS_MARKER = true;
+ return func;
};
module.exports = function getRouteDescriptions() {
- const root = path.join(__dirname, "..", "..", "dist", "api", "routes", "/");
- traverseDirectory({ dirname: root, recursive: true }, (file) => {
- currentFile = file;
+ const root = path.join(__dirname, "..", "..", "dist", "api", "routes", "/");
+ traverseDirectory({ dirname: root, recursive: true }, (file) => {
+ currentFile = file;
- currentPath = file.replace(root.slice(0, -1), "");
- currentPath = currentPath.split(".").slice(0, -1).join("."); // truncate .js/.ts file extension of path
- currentPath = currentPath.replaceAll("#", ":").replaceAll("\\", "/"); // replace # with : for path parameters and windows paths with slashes
- if (currentPath.endsWith("/index")) currentPath = currentPath.slice(0, "/index".length * -1); // delete index from path
+ currentPath = file.replace(root.slice(0, -1), "");
+ currentPath = currentPath.split(".").slice(0, -1).join("."); // truncate .js/.ts file extension of path
+ currentPath = currentPath.replaceAll("#", ":").replaceAll("\\", "/"); // replace # with : for path parameters and windows paths with slashes
+ if (currentPath.endsWith("/index")) currentPath = currentPath.slice(0, "/index".length * -1); // delete index from path
- try {
- require(file);
- } catch (e) {
- console.error(e);
- }
- });
+ try {
+ require(file);
+ } catch (e) {
+ console.error(e);
+ }
+ });
- return routes;
+ return routes;
};
diff --git a/scripts/util/walk.js b/scripts/util/walk.js
index be59023..0654331 100644
--- a/scripts/util/walk.js
+++ b/scripts/util/walk.js
@@ -20,18 +20,18 @@
/** dir: string. types: string[] ( file types ) */
module.exports = function walk(dir, types = ["ts"]) {
- var results = [];
- var list = fs.readdirSync(dir);
- list.forEach(function (file) {
- file = dir + "/" + file;
- var stat = fs.statSync(file);
- if (stat && stat.isDirectory()) {
- /* Recurse into a subdirectory */
- results = results.concat(walk(file, types));
- } else {
- if (!types.find((x) => file.endsWith(x))) return;
- results.push(file);
- }
- });
- return results;
+ var results = [];
+ var list = fs.readdirSync(dir);
+ list.forEach(function (file) {
+ file = dir + "/" + file;
+ var stat = fs.statSync(file);
+ if (stat && stat.isDirectory()) {
+ /* Recurse into a subdirectory */
+ results = results.concat(walk(file, types));
+ } else {
+ if (!types.find((x) => file.endsWith(x))) return;
+ results.push(file);
+ }
+ });
+ return results;
};
diff --git a/server.code-workspace b/server.code-workspace
index c3ffcff..d73553d 100644
--- a/server.code-workspace
+++ b/server.code-workspace
@@ -1,23 +1,23 @@
{
- "folders": [
- {
- "path": "src",
- },
- {
- "path": "assets",
- },
- {
- "path": "scripts",
- },
- {
- "path": ".",
- },
- ],
- "settings": {
- "typescript.tsdk": "util\\node_modules\\typescript\\lib",
- },
- "launch": {
- "version": "0.2.0",
- "configurations": [],
- },
+ "folders": [
+ {
+ "path": "src",
+ },
+ {
+ "path": "assets",
+ },
+ {
+ "path": "scripts",
+ },
+ {
+ "path": ".",
+ },
+ ],
+ "settings": {
+ "typescript.tsdk": "util\\node_modules\\typescript\\lib",
+ },
+ "launch": {
+ "version": "0.2.0",
+ "configurations": [],
+ },
}
diff --git a/src/api/Server.ts b/src/api/Server.ts
index 0969e5e..f81898e 100644
--- a/src/api/Server.ts
+++ b/src/api/Server.ts
@@ -31,149 +31,149 @@
export type SpacebarServerOptions = ServerOptions;
declare global {
- // eslint-disable-next-line @typescript-eslint/no-namespace
- namespace Express {
- interface Request {
- server: SpacebarServer;
- }
- }
+ // eslint-disable-next-line @typescript-eslint/no-namespace
+ namespace Express {
+ interface Request {
+ server: SpacebarServer;
+ }
+ }
}
export class SpacebarServer extends Server {
- declare public options: SpacebarServerOptions;
+ declare public options: SpacebarServerOptions;
- constructor(opts?: Partial) {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- super({ ...opts, errorHandler: false, jsonBody: false });
- }
+ constructor(opts?: Partial) {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ super({ ...opts, errorHandler: false, jsonBody: false });
+ }
- async start() {
- await initDatabase();
- await Config.init();
- await initEvent();
- await Email.init();
- await ConnectionConfig.init();
- await initInstance();
- WebAuthn.init();
+ async start() {
+ await initDatabase();
+ await Config.init();
+ await initEvent();
+ await Email.init();
+ await ConnectionConfig.init();
+ await initInstance();
+ WebAuthn.init();
- const logRequests = process.env["LOG_REQUESTS"] != undefined;
- if (logRequests) {
- this.app.use(
- morgan("combined", {
- skip: (req, res) => {
- let skip = !(process.env["LOG_REQUESTS"]?.includes(res.statusCode.toString()) ?? false);
- if (process.env["LOG_REQUESTS"]?.charAt(0) == "-") skip = !skip;
- return skip;
- },
- }),
- );
- }
+ const logRequests = process.env["LOG_REQUESTS"] != undefined;
+ if (logRequests) {
+ this.app.use(
+ morgan("combined", {
+ skip: (req, res) => {
+ let skip = !(process.env["LOG_REQUESTS"]?.includes(res.statusCode.toString()) ?? false);
+ if (process.env["LOG_REQUESTS"]?.charAt(0) == "-") skip = !skip;
+ return skip;
+ },
+ }),
+ );
+ }
- this.app.set("json replacer", JSONReplacer);
- this.app.disable("x-powered-by");
+ this.app.set("json replacer", JSONReplacer);
+ this.app.disable("x-powered-by");
- const trustedProxies = Config.get().security.trustedProxies;
- if (trustedProxies) this.app.set("trust proxy", trustedProxies);
+ const trustedProxies = Config.get().security.trustedProxies;
+ if (trustedProxies) this.app.set("trust proxy", trustedProxies);
- this.app.use(CORS);
- this.app.use(BodyParser({ inflate: true, limit: "10mb" }));
+ this.app.use(CORS);
+ this.app.use(BodyParser({ inflate: true, limit: "10mb" }));
- const app = this.app;
- const api = Router({ mergeParams: true });
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- this.app = api;
+ const app = this.app;
+ const api = Router({ mergeParams: true });
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ this.app = api;
- api.use(Authentication);
- await initRateLimits(api);
- await initTranslation(api);
+ api.use(Authentication);
+ await initRateLimits(api);
+ await initTranslation(api);
- this.routes = (await registerRoutes(this, path.join(__dirname, "routes", "/"))).filter((r) => !!r);
+ this.routes = (await registerRoutes(this, path.join(__dirname, "routes", "/"))).filter((r) => !!r);
- // 404 is not an error in express, so this should not be an error middleware
- // this is a fine place to put the 404 handler because its after we register the routes
- // and since its not an error middleware, our error handler below still works.
- // Emma [it/its] @ Rory& - the _ is required now, as pillarjs throw an error if you don't pass a param name now
- api.use("*_", (req: Request, res: Response) => {
- res.status(404).json({
- message: "404 endpoint not found",
- code: 0,
- });
- });
+ // 404 is not an error in express, so this should not be an error middleware
+ // this is a fine place to put the 404 handler because its after we register the routes
+ // and since its not an error middleware, our error handler below still works.
+ // Emma [it/its] @ Rory& - the _ is required now, as pillarjs throw an error if you don't pass a param name now
+ api.use("*_", (req: Request, res: Response) => {
+ res.status(404).json({
+ message: "404 endpoint not found",
+ code: 0,
+ });
+ });
- this.app = app;
+ this.app = app;
- //app.use("/__development", )
- //app.use("/__internals", )
- app.use("/api/v6", api);
- app.use("/api/v7", api);
- app.use("/api/v8", api);
- app.use("/api/v9", api);
- app.use("/api", api); // allow unversioned requests
+ //app.use("/__development", )
+ //app.use("/__internals", )
+ app.use("/api/v6", api);
+ app.use("/api/v7", api);
+ app.use("/api/v8", api);
+ app.use("/api/v9", api);
+ app.use("/api", api); // allow unversioned requests
- app.use("/imageproxy/:hash/:size/:url", ImageProxy);
+ app.use("/imageproxy/:hash/:size/:url", ImageProxy);
- app.get("/", (req, res) => res.sendFile(path.join(PUBLIC_ASSETS_FOLDER, "index.html")));
+ app.get("/", (req, res) => res.sendFile(path.join(PUBLIC_ASSETS_FOLDER, "index.html")));
- app.get("/verify-email", (req, res) => res.sendFile(path.join(PUBLIC_ASSETS_FOLDER, "verify.html")));
+ app.get("/verify-email", (req, res) => res.sendFile(path.join(PUBLIC_ASSETS_FOLDER, "verify.html")));
- app.get("/_spacebar/api/schemas.json", (req, res) => {
- res.sendFile(path.join(ASSETS_FOLDER, "schemas.json"));
- });
+ app.get("/_spacebar/api/schemas.json", (req, res) => {
+ res.sendFile(path.join(ASSETS_FOLDER, "schemas.json"));
+ });
- app.get("/_spacebar/api/openapi.json", (req, res) => {
- res.sendFile(path.join(ASSETS_FOLDER, "openapi.json"));
- });
+ app.get("/_spacebar/api/openapi.json", (req, res) => {
+ res.sendFile(path.join(ASSETS_FOLDER, "openapi.json"));
+ });
- // current well-known location
- app.get("/.well-known/spacebar", (req, res) => {
- res.json({
- api: Config.get().api.endpointPublic,
- });
- });
+ // current well-known location
+ app.get("/.well-known/spacebar", (req, res) => {
+ res.json({
+ api: Config.get().api.endpointPublic,
+ });
+ });
- // new well-known location
- app.get("/.well-known/spacebar/client", (req, res) => {
- let erlpackSupported = false;
- try {
- require("@yukikaze-bot/erlpack");
- erlpackSupported = true;
- } catch (e) {
- // empty
- }
+ // new well-known location
+ app.get("/.well-known/spacebar/client", (req, res) => {
+ let erlpackSupported = false;
+ try {
+ require("@yukikaze-bot/erlpack");
+ erlpackSupported = true;
+ } catch (e) {
+ // empty
+ }
- res.json({
- api: {
- baseUrl: Config.get().api.endpointPublic?.split("/api")[0] || "", // TODO: migrate database values to not include /api/v9
- apiVersions: {
- default: Config.get().api.defaultVersion,
- active: Config.get().api.activeVersions,
- },
- },
- cdn: {
- baseUrl: Config.get().cdn.endpointPublic,
- },
- gateway: {
- baseUrl: Config.get().gateway.endpointPublic,
- encoding: [...(erlpackSupported ? ["etf"] : []), "json"],
- compression: ["zstd-stream", "zlib-stream", null],
- },
- admin:
- Config.get().admin.endpointPublic === null
- ? undefined
- : {
- baseUrl: Config.get().admin.endpointPublic,
- },
- });
- });
+ res.json({
+ api: {
+ baseUrl: Config.get().api.endpointPublic?.split("/api")[0] || "", // TODO: migrate database values to not include /api/v9
+ apiVersions: {
+ default: Config.get().api.defaultVersion,
+ active: Config.get().api.activeVersions,
+ },
+ },
+ cdn: {
+ baseUrl: Config.get().cdn.endpointPublic,
+ },
+ gateway: {
+ baseUrl: Config.get().gateway.endpointPublic,
+ encoding: [...(erlpackSupported ? ["etf"] : []), "json"],
+ compression: ["zstd-stream", "zlib-stream", null],
+ },
+ admin:
+ Config.get().admin.endpointPublic === null
+ ? undefined
+ : {
+ baseUrl: Config.get().admin.endpointPublic,
+ },
+ });
+ });
- this.app.use(ErrorHandler);
+ this.app.use(ErrorHandler);
- ConnectionLoader.loadConnections();
+ ConnectionLoader.loadConnections();
- if (logRequests) console.log(red(`Warning: Request logging is enabled! This will spam your console!\nTo disable this, unset the 'LOG_REQUESTS' environment variable!`));
+ if (logRequests) console.log(red(`Warning: Request logging is enabled! This will spam your console!\nTo disable this, unset the 'LOG_REQUESTS' environment variable!`));
- return super.start();
- }
+ return super.start();
+ }
}
diff --git a/src/api/middlewares/Authentication.ts b/src/api/middlewares/Authentication.ts
index 47f6ab3..078a566 100644
--- a/src/api/middlewares/Authentication.ts
+++ b/src/api/middlewares/Authentication.ts
@@ -21,112 +21,112 @@
import { HTTPError } from "lambert-server";
export const NO_AUTHORIZATION_ROUTES = [
- // Authentication routes
- "POST /auth/login",
- "POST /auth/register",
- "GET /auth/location-metadata",
- "POST /auth/mfa/",
- "POST /auth/verify",
- "POST /auth/forgot",
- "POST /auth/reset",
- "POST /auth/fingerprint",
- "GET /invites/",
- // Routes with a seperate auth system
- /^(POST|HEAD|GET|PATCH|DELETE) \/webhooks\/\d+\/\w+\/?/, // no token requires auth
- /^POST \/interactions\/\d+\/[A-Za-z0-9_-]+\/callback/,
- // Public information endpoints
- "GET /ping",
- "GET /gateway",
- "GET /experiments",
- "GET /updates",
- "GET /download",
- "GET /scheduled-maintenances/upcoming.json",
- // Public kubernetes integration
- "GET /-/readyz",
- "GET /-/healthz",
- // Client analytics
- "POST /science",
- "POST /track",
- // Public policy pages
- "GET /policies/instance/",
- // Oauth callback
- "/oauth2/callback",
- // Asset delivery
- /^(GET|HEAD) \/guilds\/\d+\/widget\.(json|png)/,
- // Connections
- /^(POST|HEAD) \/connections\/\w+\/callback/,
- // Image proxy
- /^(GET|HEAD) \/imageproxy\/[A-Za-z0-9+/]\/\d+x\d+\/.+/,
+ // Authentication routes
+ "POST /auth/login",
+ "POST /auth/register",
+ "GET /auth/location-metadata",
+ "POST /auth/mfa/",
+ "POST /auth/verify",
+ "POST /auth/forgot",
+ "POST /auth/reset",
+ "POST /auth/fingerprint",
+ "GET /invites/",
+ // Routes with a seperate auth system
+ /^(POST|HEAD|GET|PATCH|DELETE) \/webhooks\/\d+\/\w+\/?/, // no token requires auth
+ /^POST \/interactions\/\d+\/[A-Za-z0-9_-]+\/callback/,
+ // Public information endpoints
+ "GET /ping",
+ "GET /gateway",
+ "GET /experiments",
+ "GET /updates",
+ "GET /download",
+ "GET /scheduled-maintenances/upcoming.json",
+ // Public kubernetes integration
+ "GET /-/readyz",
+ "GET /-/healthz",
+ // Client analytics
+ "POST /science",
+ "POST /track",
+ // Public policy pages
+ "GET /policies/instance/",
+ // Oauth callback
+ "/oauth2/callback",
+ // Asset delivery
+ /^(GET|HEAD) \/guilds\/\d+\/widget\.(json|png)/,
+ // Connections
+ /^(POST|HEAD) \/connections\/\w+\/callback/,
+ // Image proxy
+ /^(GET|HEAD) \/imageproxy\/[A-Za-z0-9+/]\/\d+x\d+\/.+/,
];
export const API_PREFIX = /^\/api(\/v\d+)?/;
export const API_PREFIX_TRAILING_SLASH = /^\/api(\/v\d+)?\//;
declare global {
- // eslint-disable-next-line @typescript-eslint/no-namespace
- namespace Express {
- interface Request {
- user_id: string;
- user_bot: boolean;
- token: { id: string; iat: number; ver?: number; did?: string };
- rights: Rights;
- fingerprint?: string;
- }
- }
+ // eslint-disable-next-line @typescript-eslint/no-namespace
+ namespace Express {
+ interface Request {
+ user_id: string;
+ user_bot: boolean;
+ token: { id: string; iat: number; ver?: number; did?: string };
+ rights: Rights;
+ fingerprint?: string;
+ }
+ }
}
export async function Authentication(req: Request, res: Response, next: NextFunction) {
- if (req.method === "OPTIONS") return res.sendStatus(204);
- const url = req.url.replace(API_PREFIX, "");
+ if (req.method === "OPTIONS") return res.sendStatus(204);
+ const url = req.url.replace(API_PREFIX, "");
- if (req.headers.cookie?.split("; ").find((x) => x.startsWith("__sb_sessid=")))
- req.fingerprint = req.headers.cookie
- .split("; ")
- .find((x) => x.startsWith("__sb_sessid="))!
- .split("=")[1];
- // for some reason we need to require here, else the openapi generator fails with "route is not a function"
- else res.setHeader("Set-Cookie", `__sb_sessid=${(req.fingerprint = (await require("../util")).randomString(32))}; Secure; HttpOnly; SameSite=None; Path=/`);
+ if (req.headers.cookie?.split("; ").find((x) => x.startsWith("__sb_sessid=")))
+ req.fingerprint = req.headers.cookie
+ .split("; ")
+ .find((x) => x.startsWith("__sb_sessid="))!
+ .split("=")[1];
+ // for some reason we need to require here, else the openapi generator fails with "route is not a function"
+ else res.setHeader("Set-Cookie", `__sb_sessid=${(req.fingerprint = (await require("../util")).randomString(32))}; Secure; HttpOnly; SameSite=None; Path=/`);
- if (
- NO_AUTHORIZATION_ROUTES.some((x) => {
- if (typeof x !== "string") {
- return x.test(req.method + " " + url);
- }
+ if (
+ NO_AUTHORIZATION_ROUTES.some((x) => {
+ if (typeof x !== "string") {
+ return x.test(req.method + " " + url);
+ }
- const fullRoute = req.method + " " + url;
+ const fullRoute = req.method + " " + url;
- if (req.method === "HEAD") {
- const urlPart = x.split(" ").slice(1).join(" ");
- if (urlPart.endsWith("/")) {
- return url.startsWith(urlPart);
- } else {
- return url === urlPart;
- }
- }
+ if (req.method === "HEAD") {
+ const urlPart = x.split(" ").slice(1).join(" ");
+ if (urlPart.endsWith("/")) {
+ return url.startsWith(urlPart);
+ } else {
+ return url === urlPart;
+ }
+ }
- if (x.endsWith("/")) {
- return fullRoute.startsWith(x);
- } else {
- return fullRoute === x;
- }
- })
- )
- return next();
+ if (x.endsWith("/")) {
+ return fullRoute.startsWith(x);
+ } else {
+ return fullRoute === x;
+ }
+ })
+ )
+ return next();
- if (!req.headers.authorization) return next(new HTTPError("Missing Authorization Header", 401));
+ if (!req.headers.authorization) return next(new HTTPError("Missing Authorization Header", 401));
- try {
- const { decoded, user, session, tokenVersion } = await checkToken(req.headers.authorization, {
- ipAddress: req.ip,
- fingerprint: req.fingerprint,
- });
+ try {
+ const { decoded, user, session, tokenVersion } = await checkToken(req.headers.authorization, {
+ ipAddress: req.ip,
+ fingerprint: req.fingerprint,
+ });
- req.token = decoded;
- req.user_id = decoded.id;
- req.user_bot = user.bot;
- req.rights = new Rights(Number(user.rights));
- return next();
- } catch (error) {
- return next(new HTTPError(error!.toString(), 400));
- }
+ req.token = decoded;
+ req.user_id = decoded.id;
+ req.user_bot = user.bot;
+ req.rights = new Rights(Number(user.rights));
+ return next();
+ } catch (error) {
+ return next(new HTTPError(error!.toString(), 400));
+ }
}
diff --git a/src/api/middlewares/BodyParser.ts b/src/api/middlewares/BodyParser.ts
index e08aad4..a579abb 100644
--- a/src/api/middlewares/BodyParser.ts
+++ b/src/api/middlewares/BodyParser.ts
@@ -21,31 +21,31 @@
import { HTTPError } from "lambert-server";
const errorMessages: { [key: string]: [string, number] } = {
- "entity.too.large": ["Request body too large", 413],
- "entity.parse.failed": ["Invalid JSON body", 400],
- "entity.verify.failed": ["Entity verification failed", 403],
- "request.aborted": ["Request aborted", 400],
- "request.size.invalid": ["Request size did not match content length", 400],
- "stream.encoding.set": ["Stream encoding should not be set", 500],
- "stream.not.readable": ["Stream is not readable", 500],
- "parameters.too.many": ["Too many parameters", 413],
- "charset.unsupported": ["Unsupported charset", 415],
- "encoding.unsupported": ["Unsupported content encoding", 415],
+ "entity.too.large": ["Request body too large", 413],
+ "entity.parse.failed": ["Invalid JSON body", 400],
+ "entity.verify.failed": ["Entity verification failed", 403],
+ "request.aborted": ["Request aborted", 400],
+ "request.size.invalid": ["Request size did not match content length", 400],
+ "stream.encoding.set": ["Stream encoding should not be set", 500],
+ "stream.not.readable": ["Stream is not readable", 500],
+ "parameters.too.many": ["Too many parameters", 413],
+ "charset.unsupported": ["Unsupported charset", 415],
+ "encoding.unsupported": ["Unsupported content encoding", 415],
};
export function BodyParser(opts?: OptionsJson) {
- const jsonParser = bodyParser.json(opts);
+ const jsonParser = bodyParser.json(opts);
- return (req: Request, res: Response, next: NextFunction) => {
- if (!req.headers["content-type"]) req.headers["content-type"] = "application/json";
+ return (req: Request, res: Response, next: NextFunction) => {
+ if (!req.headers["content-type"]) req.headers["content-type"] = "application/json";
- jsonParser(req, res, (err) => {
- if (err) {
- const [message, status] = errorMessages[err.type] || ["Invalid Body", 400];
- const errorMessage = message.includes("charset") || message.includes("encoding") ? `${message} "${err.charset || err.encoding}"` : message;
- return next(new HTTPError(errorMessage, status));
- }
- next();
- });
- };
+ jsonParser(req, res, (err) => {
+ if (err) {
+ const [message, status] = errorMessages[err.type] || ["Invalid Body", 400];
+ const errorMessage = message.includes("charset") || message.includes("encoding") ? `${message} "${err.charset || err.encoding}"` : message;
+ return next(new HTTPError(errorMessage, status));
+ }
+ next();
+ });
+ };
}
diff --git a/src/api/middlewares/CORS.ts b/src/api/middlewares/CORS.ts
index 34532d3..2318625 100644
--- a/src/api/middlewares/CORS.ts
+++ b/src/api/middlewares/CORS.ts
@@ -21,20 +21,20 @@
// TODO: config settings
export function CORS(req: Request, res: Response, next: NextFunction) {
- res.set("Access-Control-Allow-Credentials", "true");
- res.set("Access-Control-Allow-Headers", req.header("Access-Control-Request-Headers") || "*");
- res.set("Access-Control-Allow-Methods", req.header("Access-Control-Request-Method") || "*");
- res.set("Access-Control-Allow-Origin", req.header("Origin") ?? "*");
- res.set("Access-Control-Max-Age", "5"); // dont make it too long so we can change it dynamically
- // TODO: use better CSP
- res.set(
- "Content-security-policy",
- "default-src * data: blob: filesystem: about: ws: wss: 'unsafe-inline' 'unsafe-eval'; script-src * data: blob: 'unsafe-inline' 'unsafe-eval'; connect-src * data: blob: 'unsafe-inline'; img-src * data: blob: 'unsafe-inline'; frame-src * data: blob: ; style-src * data: blob: 'unsafe-inline'; font-src * data: blob: 'unsafe-inline';",
- );
+ res.set("Access-Control-Allow-Credentials", "true");
+ res.set("Access-Control-Allow-Headers", req.header("Access-Control-Request-Headers") || "*");
+ res.set("Access-Control-Allow-Methods", req.header("Access-Control-Request-Method") || "*");
+ res.set("Access-Control-Allow-Origin", req.header("Origin") ?? "*");
+ res.set("Access-Control-Max-Age", "5"); // dont make it too long so we can change it dynamically
+ // TODO: use better CSP
+ res.set(
+ "Content-security-policy",
+ "default-src * data: blob: filesystem: about: ws: wss: 'unsafe-inline' 'unsafe-eval'; script-src * data: blob: 'unsafe-inline' 'unsafe-eval'; connect-src * data: blob: 'unsafe-inline'; img-src * data: blob: 'unsafe-inline'; frame-src * data: blob: ; style-src * data: blob: 'unsafe-inline'; font-src * data: blob: 'unsafe-inline';",
+ );
- if (req.method === "OPTIONS") {
- res.status(204).end();
- return;
- }
- next();
+ if (req.method === "OPTIONS") {
+ res.status(204).end();
+ return;
+ }
+ next();
}
diff --git a/src/api/middlewares/ErrorHandler.ts b/src/api/middlewares/ErrorHandler.ts
index cd306c9..1a9a18a 100644
--- a/src/api/middlewares/ErrorHandler.ts
+++ b/src/api/middlewares/ErrorHandler.ts
@@ -22,48 +22,48 @@
const EntityNotFoundErrorRegex = /"(\w+)"/;
export function ErrorHandler(error: Error & { type?: string }, req: Request, res: Response, next: NextFunction) {
- if (!error) return next();
+ if (!error) return next();
- try {
- let code = 400;
- let httpcode = code;
- let message = error?.toString();
- let errors = undefined;
- let _ajvErrors = undefined;
+ try {
+ let code = 400;
+ let httpcode = code;
+ let message = error?.toString();
+ let errors = undefined;
+ let _ajvErrors = undefined;
- if (error instanceof HTTPError && error.code) code = httpcode = error.code;
- else if (error instanceof ApiError) {
- code = error.code;
- message = error.message;
- httpcode = error.httpStatus;
- } else if (error.name === "EntityNotFoundError") {
- message = `${error.message.match(EntityNotFoundErrorRegex)?.[1] || "Item"} could not be found`;
- code = httpcode = 404;
- } else if (error instanceof FieldError) {
- code = Number(error.code);
- message = error.message;
- errors = error.errors;
- _ajvErrors = error._ajvErrors;
- } else if (error?.type == "entity.parse.failed") {
- // body-parser failed
- httpcode = 400;
- code = 50109;
- message = "The request body contains invalid JSON.";
- } else {
- console.error(`[Error] ${code} ${req.url}\n`, errors || error, "\nbody:", req.body);
+ if (error instanceof HTTPError && error.code) code = httpcode = error.code;
+ else if (error instanceof ApiError) {
+ code = error.code;
+ message = error.message;
+ httpcode = error.httpStatus;
+ } else if (error.name === "EntityNotFoundError") {
+ message = `${error.message.match(EntityNotFoundErrorRegex)?.[1] || "Item"} could not be found`;
+ code = httpcode = 404;
+ } else if (error instanceof FieldError) {
+ code = Number(error.code);
+ message = error.message;
+ errors = error.errors;
+ _ajvErrors = error._ajvErrors;
+ } else if (error?.type == "entity.parse.failed") {
+ // body-parser failed
+ httpcode = 400;
+ code = 50109;
+ message = "The request body contains invalid JSON.";
+ } else {
+ console.error(`[Error] ${code} ${req.url}\n`, errors || error, "\nbody:", req.body);
- if (req.server?.options?.production) {
- // don't expose internal errors to the user, instead human errors should be thrown as HTTPError
- message = "Internal Server Error";
- }
- code = httpcode = 500;
- }
+ if (req.server?.options?.production) {
+ // don't expose internal errors to the user, instead human errors should be thrown as HTTPError
+ message = "Internal Server Error";
+ }
+ code = httpcode = 500;
+ }
- if (httpcode > 511) httpcode = 400;
+ if (httpcode > 511) httpcode = 400;
- res.status(httpcode).json({ code: code, message, errors, _ajvErrors });
- } catch (error) {
- console.error(`[Internal Server Error] 500`, error);
- return res.status(500).json({ code: 500, message: "Internal Server Error" });
- }
+ res.status(httpcode).json({ code: code, message, errors, _ajvErrors });
+ } catch (error) {
+ console.error(`[Internal Server Error] 500`, error);
+ return res.status(500).json({ code: 500, message: "Internal Server Error" });
+ }
}
diff --git a/src/api/middlewares/ImageProxy.ts b/src/api/middlewares/ImageProxy.ts
index 7869012..e950ea8 100644
--- a/src/api/middlewares/ImageProxy.ts
+++ b/src/api/middlewares/ImageProxy.ts
@@ -25,9 +25,9 @@
let Jimp: JimpType | undefined = undefined;
try {
- Jimp = require("jimp") as JimpType;
+ Jimp = require("jimp") as JimpType;
} catch {
- // empty
+ // empty
}
let sentImageProxyWarning = false;
@@ -37,101 +37,101 @@
const resizeSupported = new Set([...sharpSupported, ...jimpSupported]);
export async function ImageProxy(req: Request, res: Response) {
- const path = req.originalUrl.split("/").slice(2);
+ const path = req.originalUrl.split("/").slice(2);
- // src/api/util/utility/EmbedHandlers.ts getProxyUrl
- const hash = crypto.createHmac("sha1", Config.get().security.requestSignature).update(path.slice(1).join("/")).digest("base64").replace(/\+/g, "-").replace(/\//g, "_");
+ // src/api/util/utility/EmbedHandlers.ts getProxyUrl
+ const hash = crypto.createHmac("sha1", Config.get().security.requestSignature).update(path.slice(1).join("/")).digest("base64").replace(/\+/g, "-").replace(/\//g, "_");
- try {
- if (!crypto.timingSafeEqual(Buffer.from(hash), Buffer.from(path[0]))) throw new Error("Invalid signature");
- } catch {
- console.log("[ImageProxy] Invalid signature, expected " + hash + " but got " + path[0]);
- res.status(403).send("Invalid signature");
- return;
- }
+ try {
+ if (!crypto.timingSafeEqual(Buffer.from(hash), Buffer.from(path[0]))) throw new Error("Invalid signature");
+ } catch {
+ console.log("[ImageProxy] Invalid signature, expected " + hash + " but got " + path[0]);
+ res.status(403).send("Invalid signature");
+ return;
+ }
- const abort = new AbortController();
- setTimeout(() => abort.abort(), 5000);
+ const abort = new AbortController();
+ setTimeout(() => abort.abort(), 5000);
- const request = await fetch("https://" + path.slice(2).join("/"), {
- headers: {
- "User-Agent": "SpacebarImageProxy/1.0.0 (https://spacebar.chat)",
- },
- signal: abort.signal,
- }).catch((e) => {
- if (e.name === "AbortError") res.status(504).send("Request timed out");
- else res.status(500).send("Unable to proxy origin: " + e.message);
- });
- if (!request) return;
+ const request = await fetch("https://" + path.slice(2).join("/"), {
+ headers: {
+ "User-Agent": "SpacebarImageProxy/1.0.0 (https://spacebar.chat)",
+ },
+ signal: abort.signal,
+ }).catch((e) => {
+ if (e.name === "AbortError") res.status(504).send("Request timed out");
+ else res.status(500).send("Unable to proxy origin: " + e.message);
+ });
+ if (!request) return;
- if (request.status !== 200) {
- res.status(request.status).send("Origin failed to respond: " + request.status + " " + request.statusText);
- return;
- }
+ if (request.status !== 200) {
+ res.status(request.status).send("Origin failed to respond: " + request.status + " " + request.statusText);
+ return;
+ }
- if (!request.headers.get("Content-Type") || !request.headers.get("Content-Length")) {
- res.status(500).send("Origin did not provide a Content-Type or Content-Length header");
- return;
- }
+ if (!request.headers.get("Content-Type") || !request.headers.get("Content-Length")) {
+ res.status(500).send("Origin did not provide a Content-Type or Content-Length header");
+ return;
+ }
- // @ts-expect-error TS doesn't believe that the header cannot be null (it's checked for falsiness above)
- if (parseInt(request.headers.get("Content-Length")) > 1024 * 1024 * 10) {
- res.status(500).send("Origin provided a Content-Length header that is too large");
- return;
- }
+ // @ts-expect-error TS doesn't believe that the header cannot be null (it's checked for falsiness above)
+ if (parseInt(request.headers.get("Content-Length")) > 1024 * 1024 * 10) {
+ res.status(500).send("Origin provided a Content-Length header that is too large");
+ return;
+ }
- // @ts-expect-error TS doesn't believe that the header cannot be null (it's checked for falsiness above)
- let contentType: string = request.headers.get("Content-Type");
+ // @ts-expect-error TS doesn't believe that the header cannot be null (it's checked for falsiness above)
+ let contentType: string = request.headers.get("Content-Type");
- const arrayBuffer = await request.arrayBuffer();
- let resultBuffer = Buffer.from(arrayBuffer);
+ const arrayBuffer = await request.arrayBuffer();
+ let resultBuffer = Buffer.from(arrayBuffer);
- if (!sentImageProxyWarning && resizeSupported.has(contentType) && /^\d+x\d+$/.test(path[1])) {
- if (sharp !== false) {
- try {
- sharp = await import("sharp");
- } catch {
- sharp = false;
- }
- }
+ if (!sentImageProxyWarning && resizeSupported.has(contentType) && /^\d+x\d+$/.test(path[1])) {
+ if (sharp !== false) {
+ try {
+ sharp = await import("sharp");
+ } catch {
+ sharp = false;
+ }
+ }
- if (sharp === false && !Jimp) {
- try {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore Typings don't fit
- Jimp = await import("jimp");
- } catch {
- sentImageProxyWarning = true;
- console.log(`[ImageProxy] ${yellow('Neither "sharp" or "jimp" NPM packages are installed, image resizing will be disabled')}`);
- }
- }
+ if (sharp === false && !Jimp) {
+ try {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore Typings don't fit
+ Jimp = await import("jimp");
+ } catch {
+ sentImageProxyWarning = true;
+ console.log(`[ImageProxy] ${yellow('Neither "sharp" or "jimp" NPM packages are installed, image resizing will be disabled')}`);
+ }
+ }
- const [width, height] = path[1].split("x").map((x) => parseInt(x));
+ const [width, height] = path[1].split("x").map((x) => parseInt(x));
- const buffer = Buffer.from(arrayBuffer);
- if (sharp && sharpSupported.has(contentType)) {
- resultBuffer = Buffer.from(
- await sharp
- .default(buffer)
- // Sharp doesn't support "scaleToFit"
- .resize(width)
- .toBuffer(),
- );
- } else if (Jimp && jimpSupported.has(contentType)) {
- resultBuffer = await Jimp.read(buffer).then((image) => {
- contentType = image.getMIME();
- return (
- image
- .scaleToFit(width, height)
- // @ts-expect-error Jimp is defined at this point
- .getBufferAsync(Jimp.AUTO)
- );
- });
- }
- }
+ const buffer = Buffer.from(arrayBuffer);
+ if (sharp && sharpSupported.has(contentType)) {
+ resultBuffer = Buffer.from(
+ await sharp
+ .default(buffer)
+ // Sharp doesn't support "scaleToFit"
+ .resize(width)
+ .toBuffer(),
+ );
+ } else if (Jimp && jimpSupported.has(contentType)) {
+ resultBuffer = await Jimp.read(buffer).then((image) => {
+ contentType = image.getMIME();
+ return (
+ image
+ .scaleToFit(width, height)
+ // @ts-expect-error Jimp is defined at this point
+ .getBufferAsync(Jimp.AUTO)
+ );
+ });
+ }
+ }
- res.header("Content-Type", contentType);
- res.setHeader("Cache-Control", "public, max-age=" + Config.get().cdn.proxyCacheHeaderSeconds);
+ res.header("Content-Type", contentType);
+ res.setHeader("Cache-Control", "public, max-age=" + Config.get().cdn.proxyCacheHeaderSeconds);
- res.send(resultBuffer);
+ res.send(resultBuffer);
}
diff --git a/src/api/middlewares/RateLimit.ts b/src/api/middlewares/RateLimit.ts
index 1a41ad4..c749df6 100644
--- a/src/api/middlewares/RateLimit.ts
+++ b/src/api/middlewares/RateLimit.ts
@@ -34,188 +34,188 @@
*/
type RateLimit = {
- id: "global" | "error" | string;
- executor_id: string;
- hits: number;
- blocked: boolean;
- expires_at: Date;
+ id: "global" | "error" | string;
+ executor_id: string;
+ hits: number;
+ blocked: boolean;
+ expires_at: Date;
};
const Cache = new Map();
const EventRateLimit = "RATELIMIT";
export default function rateLimit(opts: {
- bucket?: string;
- window: number;
- count: number;
- bot?: number;
- webhook?: number;
- oauth?: number;
- GET?: number;
- MODIFY?: number;
- error?: boolean;
- success?: boolean;
- onlyIp?: boolean;
+ bucket?: string;
+ window: number;
+ count: number;
+ bot?: number;
+ webhook?: number;
+ oauth?: number;
+ GET?: number;
+ MODIFY?: number;
+ error?: boolean;
+ success?: boolean;
+ onlyIp?: boolean;
}) {
- return async (req: Request, res: Response, next: NextFunction) => {
- // exempt user? if so, immediately short circuit
- if (req.user_id) {
- const rights = await getRights(req.user_id);
- if (rights.has("BYPASS_RATE_LIMITS")) return next();
- }
+ return async (req: Request, res: Response, next: NextFunction) => {
+ // exempt user? if so, immediately short circuit
+ if (req.user_id) {
+ const rights = await getRights(req.user_id);
+ if (rights.has("BYPASS_RATE_LIMITS")) return next();
+ }
- const bucket_id = opts.bucket || req.originalUrl.replace(API_PREFIX_TRAILING_SLASH, "");
- let executor_id = req.ip || "127.0.0.1";
- if (!opts.onlyIp && req.user_id) executor_id = req.user_id;
+ const bucket_id = opts.bucket || req.originalUrl.replace(API_PREFIX_TRAILING_SLASH, "");
+ let executor_id = req.ip || "127.0.0.1";
+ if (!opts.onlyIp && req.user_id) executor_id = req.user_id;
- let max_hits = opts.count;
- if (opts.bot && req.user_bot) max_hits = opts.bot;
- if (opts.GET && ["GET", "OPTIONS", "HEAD"].includes(req.method)) max_hits = opts.GET;
- else if (opts.MODIFY && ["POST", "DELETE", "PATCH", "PUT"].includes(req.method)) max_hits = opts.MODIFY;
+ let max_hits = opts.count;
+ if (opts.bot && req.user_bot) max_hits = opts.bot;
+ if (opts.GET && ["GET", "OPTIONS", "HEAD"].includes(req.method)) max_hits = opts.GET;
+ else if (opts.MODIFY && ["POST", "DELETE", "PATCH", "PUT"].includes(req.method)) max_hits = opts.MODIFY;
- const offender = Cache.get(executor_id + bucket_id);
+ const offender = Cache.get(executor_id + bucket_id);
- res.set("X-RateLimit-Limit", `${max_hits}`)
- .set("X-RateLimit-Remaining", `${max_hits - (offender?.hits || 0)}`)
- .set("X-RateLimit-Bucket", `${bucket_id}`)
- // assuming we aren't blocked, a new window will start after this request
- .set("X-RateLimit-Reset", `${Date.now() + opts.window}`)
- .set("X-RateLimit-Reset-After", `${opts.window}`);
+ res.set("X-RateLimit-Limit", `${max_hits}`)
+ .set("X-RateLimit-Remaining", `${max_hits - (offender?.hits || 0)}`)
+ .set("X-RateLimit-Bucket", `${bucket_id}`)
+ // assuming we aren't blocked, a new window will start after this request
+ .set("X-RateLimit-Reset", `${Date.now() + opts.window}`)
+ .set("X-RateLimit-Reset-After", `${opts.window}`);
- if (offender) {
- let reset = offender.expires_at.getTime();
- let resetAfterMs = reset - Date.now();
- let resetAfterSec = Math.ceil(resetAfterMs / 1000);
+ if (offender) {
+ let reset = offender.expires_at.getTime();
+ let resetAfterMs = reset - Date.now();
+ let resetAfterSec = Math.ceil(resetAfterMs / 1000);
- if (resetAfterMs <= 0) {
- offender.hits = 0;
- offender.expires_at = new Date(Date.now() + opts.window * 1000);
- offender.blocked = false;
+ if (resetAfterMs <= 0) {
+ offender.hits = 0;
+ offender.expires_at = new Date(Date.now() + opts.window * 1000);
+ offender.blocked = false;
- Cache.delete(executor_id + bucket_id);
- }
+ Cache.delete(executor_id + bucket_id);
+ }
- res.set("X-RateLimit-Reset", `${reset}`);
- res.set("X-RateLimit-Reset-After", `${Math.max(0, Math.ceil(resetAfterSec))}`);
+ res.set("X-RateLimit-Reset", `${reset}`);
+ res.set("X-RateLimit-Reset-After", `${Math.max(0, Math.ceil(resetAfterSec))}`);
- if (offender.blocked) {
- const global = bucket_id === "global";
- // each block violation pushes the expiry one full window further
- reset += opts.window * 1000;
- offender.expires_at = new Date(offender.expires_at.getTime() + opts.window * 1000);
- resetAfterMs = reset - Date.now();
- resetAfterSec = Math.ceil(resetAfterMs / 1000);
+ if (offender.blocked) {
+ const global = bucket_id === "global";
+ // each block violation pushes the expiry one full window further
+ reset += opts.window * 1000;
+ offender.expires_at = new Date(offender.expires_at.getTime() + opts.window * 1000);
+ resetAfterMs = reset - Date.now();
+ resetAfterSec = Math.ceil(resetAfterMs / 1000);
- console.log(`blocked bucket: ${bucket_id} ${executor_id}`, {
- resetAfterMs,
- });
+ console.log(`blocked bucket: ${bucket_id} ${executor_id}`, {
+ resetAfterMs,
+ });
- if (global) res.set("X-RateLimit-Global", "true");
+ if (global) res.set("X-RateLimit-Global", "true");
- return (
- res
- .status(429)
- .set("X-RateLimit-Remaining", "0")
- .set("Retry-After", `${Math.max(0, Math.ceil(resetAfterSec))}`)
- // TODO: error rate limit message translation
- .send({
- message: "You are being rate limited.",
- retry_after: resetAfterSec,
- global,
- })
- );
- }
- }
+ return (
+ res
+ .status(429)
+ .set("X-RateLimit-Remaining", "0")
+ .set("Retry-After", `${Math.max(0, Math.ceil(resetAfterSec))}`)
+ // TODO: error rate limit message translation
+ .send({
+ message: "You are being rate limited.",
+ retry_after: resetAfterSec,
+ global,
+ })
+ );
+ }
+ }
- next();
- const hitRouteOpts = {
- bucket_id,
- executor_id,
- max_hits,
- window: opts.window,
- };
+ next();
+ const hitRouteOpts = {
+ bucket_id,
+ executor_id,
+ max_hits,
+ window: opts.window,
+ };
- if (opts.error || opts.success) {
- res.once("finish", () => {
- // check if error and increment error rate limit
- if (res.statusCode >= 400 && opts.error) {
- return hitRoute(hitRouteOpts);
- } else if (res.statusCode >= 200 && res.statusCode < 300 && opts.success) {
- return hitRoute(hitRouteOpts);
- }
- });
- } else {
- return hitRoute(hitRouteOpts);
- }
- };
+ if (opts.error || opts.success) {
+ res.once("finish", () => {
+ // check if error and increment error rate limit
+ if (res.statusCode >= 400 && opts.error) {
+ return hitRoute(hitRouteOpts);
+ } else if (res.statusCode >= 200 && res.statusCode < 300 && opts.success) {
+ return hitRoute(hitRouteOpts);
+ }
+ });
+ } else {
+ return hitRoute(hitRouteOpts);
+ }
+ };
}
export async function initRateLimits(app: Router) {
- const { routes, global, ip, error, enabled } = Config.get().limits.rate;
- if (!enabled) return;
- console.log("Enabling rate limits...");
- await listenEvent(EventRateLimit, (event) => {
- Cache.set(event.channel_id as string, event.data);
- event.acknowledge?.();
- });
- // await RateLimit.delete({ expires_at: LessThan(new Date().toISOString()) }); // cleans up if not already deleted, morethan -> older date
- // const limits = await RateLimit.find({ blocked: true });
- // limits.forEach((limit) => {
- // Cache.set(limit.executor_id, limit);
- // });
+ const { routes, global, ip, error, enabled } = Config.get().limits.rate;
+ if (!enabled) return;
+ console.log("Enabling rate limits...");
+ await listenEvent(EventRateLimit, (event) => {
+ Cache.set(event.channel_id as string, event.data);
+ event.acknowledge?.();
+ });
+ // await RateLimit.delete({ expires_at: LessThan(new Date().toISOString()) }); // cleans up if not already deleted, morethan -> older date
+ // const limits = await RateLimit.find({ blocked: true });
+ // limits.forEach((limit) => {
+ // Cache.set(limit.executor_id, limit);
+ // });
- setInterval(() => {
- Cache.forEach((x, key) => {
- if (new Date() > x.expires_at) {
- Cache.delete(key);
- // RateLimit.delete({ executor_id: key });
- }
- });
- }, 1000 * 60);
+ setInterval(() => {
+ Cache.forEach((x, key) => {
+ if (new Date() > x.expires_at) {
+ Cache.delete(key);
+ // RateLimit.delete({ executor_id: key });
+ }
+ });
+ }, 1000 * 60);
- app.use(
- rateLimit({
- bucket: "global",
- onlyIp: true,
- ...ip,
- }),
- );
- app.use(rateLimit({ bucket: "global", ...global }));
- app.use(
- rateLimit({
- bucket: "error",
- error: true,
- onlyIp: true,
- ...error,
- }),
- );
- app.use("/guilds/:guild_id", rateLimit(routes.guild));
- app.use("/webhooks/:webhook_id", rateLimit(routes.webhook));
- app.use("/channels/:channel_id", rateLimit(routes.channel));
- app.use("/auth/login", rateLimit(routes.auth.login));
- app.use("/auth/register", rateLimit({ onlyIp: true, success: true, ...routes.auth.register }));
+ app.use(
+ rateLimit({
+ bucket: "global",
+ onlyIp: true,
+ ...ip,
+ }),
+ );
+ app.use(rateLimit({ bucket: "global", ...global }));
+ app.use(
+ rateLimit({
+ bucket: "error",
+ error: true,
+ onlyIp: true,
+ ...error,
+ }),
+ );
+ app.use("/guilds/:guild_id", rateLimit(routes.guild));
+ app.use("/webhooks/:webhook_id", rateLimit(routes.webhook));
+ app.use("/channels/:channel_id", rateLimit(routes.channel));
+ app.use("/auth/login", rateLimit(routes.auth.login));
+ app.use("/auth/register", rateLimit({ onlyIp: true, success: true, ...routes.auth.register }));
}
async function hitRoute(opts: { executor_id: string; bucket_id: string; max_hits: number; window: number }) {
- const id = opts.executor_id + opts.bucket_id;
- let limit = Cache.get(id);
- if (!limit) {
- limit = {
- id: opts.bucket_id,
- executor_id: opts.executor_id,
- expires_at: new Date(Date.now() + opts.window * 1000),
- hits: 0,
- blocked: false,
- };
- Cache.set(id, limit);
- }
+ const id = opts.executor_id + opts.bucket_id;
+ let limit = Cache.get(id);
+ if (!limit) {
+ limit = {
+ id: opts.bucket_id,
+ executor_id: opts.executor_id,
+ expires_at: new Date(Date.now() + opts.window * 1000),
+ hits: 0,
+ blocked: false,
+ };
+ Cache.set(id, limit);
+ }
- limit.hits++;
- if (limit.hits >= opts.max_hits) {
- limit.blocked = true;
- }
+ limit.hits++;
+ if (limit.hits >= opts.max_hits) {
+ limit.blocked = true;
+ }
- /*
+ /*
let ratelimit = await RateLimit.findOne({ where: { id: opts.bucket_id, executor_id: opts.executor_id } });
if (!ratelimit) {
ratelimit = new RateLimit({
diff --git a/src/api/middlewares/Translation.ts b/src/api/middlewares/Translation.ts
index e089407..3ca204b 100644
--- a/src/api/middlewares/Translation.ts
+++ b/src/api/middlewares/Translation.ts
@@ -26,23 +26,23 @@
const ASSET_FOLDER_PATH = path.join(__dirname, "..", "..", "..", "assets");
export async function initTranslation(router: Router) {
- const languages = fs.readdirSync(path.join(ASSET_FOLDER_PATH, "locales"));
- const namespaces = fs.readdirSync(path.join(ASSET_FOLDER_PATH, "locales", "en"));
- const ns = namespaces.filter((x) => x.endsWith(".json")).map((x) => x.slice(0, x.length - 5));
+ const languages = fs.readdirSync(path.join(ASSET_FOLDER_PATH, "locales"));
+ const namespaces = fs.readdirSync(path.join(ASSET_FOLDER_PATH, "locales", "en"));
+ const ns = namespaces.filter((x) => x.endsWith(".json")).map((x) => x.slice(0, x.length - 5));
- await i18next
- .use(i18nextBackend)
- .use(i18nextMiddleware.LanguageDetector)
- .init({
- preload: languages,
- // debug: true,
- fallbackLng: "en",
- ns,
- backend: {
- loadPath: path.join(ASSET_FOLDER_PATH, "locales") + "/{{lng}}/{{ns}}.json",
- },
- load: "all",
- });
+ await i18next
+ .use(i18nextBackend)
+ .use(i18nextMiddleware.LanguageDetector)
+ .init({
+ preload: languages,
+ // debug: true,
+ fallbackLng: "en",
+ ns,
+ backend: {
+ loadPath: path.join(ASSET_FOLDER_PATH, "locales") + "/{{lng}}/{{ns}}.json",
+ },
+ load: "all",
+ });
- router.use(i18nextMiddleware.handle(i18next, {}));
+ router.use(i18nextMiddleware.handle(i18next, {}));
}
diff --git a/src/api/routes/-/healthz.ts b/src/api/routes/-/healthz.ts
index 5acd8c8..886473c 100644
--- a/src/api/routes/-/healthz.ts
+++ b/src/api/routes/-/healthz.ts
@@ -23,9 +23,9 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), (req: Request, res: Response) => {
- if (!getDatabase()) return res.sendStatus(503);
+ if (!getDatabase()) return res.sendStatus(503);
- return res.sendStatus(200);
+ return res.sendStatus(200);
});
export default router;
diff --git a/src/api/routes/-/readyz.ts b/src/api/routes/-/readyz.ts
index 5acd8c8..886473c 100644
--- a/src/api/routes/-/readyz.ts
+++ b/src/api/routes/-/readyz.ts
@@ -23,9 +23,9 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), (req: Request, res: Response) => {
- if (!getDatabase()) return res.sendStatus(503);
+ if (!getDatabase()) return res.sendStatus(503);
- return res.sendStatus(200);
+ return res.sendStatus(200);
});
export default router;
diff --git "a/src/api/routes/applications/\043application_id/bot/index.ts" "b/src/api/routes/applications/\043application_id/bot/index.ts"
index ad49184..83b4fc6 100644
--- "a/src/api/routes/applications/\043application_id/bot/index.ts"
+++ "b/src/api/routes/applications/\043application_id/bot/index.ts"
@@ -26,98 +26,98 @@
const router: Router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- responses: {
- 204: {
- body: "TokenOnlyResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const app = await Application.findOneOrFail({
- where: { id: req.params.application_id },
- relations: ["owner"],
- });
+ "/",
+ route({
+ responses: {
+ 204: {
+ body: "TokenOnlyResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const app = await Application.findOneOrFail({
+ where: { id: req.params.application_id },
+ relations: ["owner"],
+ });
- if (app.owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
+ if (app.owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
- const user = await createAppBotUser(app, req);
+ const user = await createAppBotUser(app, req);
- res.send({
- token: await generateToken(user.id),
- });
- },
+ res.send({
+ token: await generateToken(user.id),
+ });
+ },
);
router.post(
- "/reset",
- route({
- responses: {
- 200: {
- body: "TokenResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const bot = await User.findOneOrFail({ where: { id: req.params.application_id } });
- const owner = await User.findOneOrFail({ where: { id: req.user_id } });
+ "/reset",
+ route({
+ responses: {
+ 200: {
+ body: "TokenResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const bot = await User.findOneOrFail({ where: { id: req.params.application_id } });
+ const owner = await User.findOneOrFail({ where: { id: req.user_id } });
- if (owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
+ if (owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
- if (owner.totp_secret && (!req.body.code || verifyToken(owner.totp_secret, req.body.code))) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
+ if (owner.totp_secret && (!req.body.code || verifyToken(owner.totp_secret, req.body.code))) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
- bot.data = { hash: undefined, valid_tokens_since: new Date() };
+ bot.data = { hash: undefined, valid_tokens_since: new Date() };
- await bot.save();
+ await bot.save();
- const token = await generateToken(bot.id);
+ const token = await generateToken(bot.id);
- res.json({ token }).status(200);
- },
+ res.json({ token }).status(200);
+ },
);
router.patch(
- "/",
- route({
- requestBody: "BotModifySchema",
- responses: {
- 200: {
- body: "Application",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as BotModifySchema;
- if (!body.avatar?.trim()) delete body.avatar;
+ "/",
+ route({
+ requestBody: "BotModifySchema",
+ responses: {
+ 200: {
+ body: "Application",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as BotModifySchema;
+ if (!body.avatar?.trim()) delete body.avatar;
- const app = await Application.findOneOrFail({
- where: { id: req.params.application_id },
- relations: ["bot", "owner"],
- });
+ const app = await Application.findOneOrFail({
+ where: { id: req.params.application_id },
+ relations: ["bot", "owner"],
+ });
- if (!app.bot) throw DiscordApiErrors.BOT_ONLY_ENDPOINT;
+ if (!app.bot) throw DiscordApiErrors.BOT_ONLY_ENDPOINT;
- if (app.owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
+ if (app.owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
- if (body.avatar) body.avatar = await handleFile(`/avatars/${app.id}`, body.avatar as string);
+ if (body.avatar) body.avatar = await handleFile(`/avatars/${app.id}`, body.avatar as string);
- app.bot.assign(body);
+ app.bot.assign(body);
- app.bot.save();
+ app.bot.save();
- await app.save();
- res.json(app).status(200);
- },
+ await app.save();
+ res.json(app).status(200);
+ },
);
export default router;
diff --git "a/src/api/routes/applications/\043application_id/commands/\043command_id/index.ts" "b/src/api/routes/applications/\043application_id/commands/\043command_id/index.ts"
index 7907c1b..8e4c3ce 100644
--- "a/src/api/routes/applications/\043application_id/commands/\043command_id/index.ts"
+++ "b/src/api/routes/applications/\043application_id/commands/\043command_id/index.ts"
@@ -24,99 +24,99 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
+ const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
- if (!applicationExists) {
- res.status(404).send({ code: 404, message: "Unknown application" });
- return;
- }
+ if (!applicationExists) {
+ res.status(404).send({ code: 404, message: "Unknown application" });
+ return;
+ }
- const command = await ApplicationCommand.findOne({ where: { application_id: req.params.application_id, id: req.params.command_id } });
+ const command = await ApplicationCommand.findOne({ where: { application_id: req.params.application_id, id: req.params.command_id } });
- if (!command) {
- res.status(404).send({ code: 404, message: "Unknown application command" });
- return;
- }
+ if (!command) {
+ res.status(404).send({ code: 404, message: "Unknown application command" });
+ return;
+ }
- res.send(command);
+ res.send(command);
});
router.patch(
- "/",
- route({
- requestBody: "ApplicationCommandCreateSchema",
- }),
- async (req: Request, res: Response) => {
- const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
+ "/",
+ route({
+ requestBody: "ApplicationCommandCreateSchema",
+ }),
+ async (req: Request, res: Response) => {
+ const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
- if (!applicationExists) {
- res.status(404).send({ code: 404, message: "Unknown application" });
- return;
- }
+ if (!applicationExists) {
+ res.status(404).send({ code: 404, message: "Unknown application" });
+ return;
+ }
- const commandExists = await ApplicationCommand.exists({ where: { application_id: req.params.application_id, id: req.params.command_id } });
+ const commandExists = await ApplicationCommand.exists({ where: { application_id: req.params.application_id, id: req.params.command_id } });
- if (!commandExists) {
- res.status(404).send({ code: 404, message: "Unknown application command" });
- return;
- }
+ if (!commandExists) {
+ res.status(404).send({ code: 404, message: "Unknown application command" });
+ return;
+ }
- const body = req.body as ApplicationCommandCreateSchema;
+ const body = req.body as ApplicationCommandCreateSchema;
- if (!body.type) {
- body.type = 1;
- }
+ if (!body.type) {
+ body.type = 1;
+ }
- if (body.name.trim().length < 1 || body.name.trim().length > 32) {
- // TODO: configurable?
- throw FieldErrors({
- name: {
- code: "BASE_TYPE_BAD_LENGTH",
- message: `Must be between 1 and 32 in length.`,
- },
- });
- }
+ if (body.name.trim().length < 1 || body.name.trim().length > 32) {
+ // TODO: configurable?
+ throw FieldErrors({
+ name: {
+ code: "BASE_TYPE_BAD_LENGTH",
+ message: `Must be between 1 and 32 in length.`,
+ },
+ });
+ }
- const commandForDb: ApplicationCommandSchema = {
- application_id: req.params.application_id,
- name: body.name.trim(),
- name_localizations: body.name_localizations,
- description: body.description?.trim() || "",
- description_localizations: body.description_localizations,
- default_member_permissions: body.default_member_permissions || null,
- contexts: body.contexts,
- dm_permission: body.dm_permission || true,
- global_popularity_rank: 1,
- handler: body.handler,
- integration_types: body.integration_types,
- nsfw: body.nsfw,
- options: body.options,
- type: body.type,
- version: Snowflake.generate(),
- };
+ const commandForDb: ApplicationCommandSchema = {
+ application_id: req.params.application_id,
+ name: body.name.trim(),
+ name_localizations: body.name_localizations,
+ description: body.description?.trim() || "",
+ description_localizations: body.description_localizations,
+ default_member_permissions: body.default_member_permissions || null,
+ contexts: body.contexts,
+ dm_permission: body.dm_permission || true,
+ global_popularity_rank: 1,
+ handler: body.handler,
+ integration_types: body.integration_types,
+ nsfw: body.nsfw,
+ options: body.options,
+ type: body.type,
+ version: Snowflake.generate(),
+ };
- await ApplicationCommand.update({ name: body.name.trim() }, commandForDb);
- res.send(commandForDb);
- },
+ await ApplicationCommand.update({ name: body.name.trim() }, commandForDb);
+ res.send(commandForDb);
+ },
);
router.delete("/", async (req: Request, res: Response) => {
- const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
+ const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
- if (!applicationExists) {
- res.status(404).send({ code: 404, message: "Unknown application" });
- return;
- }
+ if (!applicationExists) {
+ res.status(404).send({ code: 404, message: "Unknown application" });
+ return;
+ }
- const commandExists = await ApplicationCommand.exists({ where: { application_id: req.params.application_id, id: req.params.command_id } });
+ const commandExists = await ApplicationCommand.exists({ where: { application_id: req.params.application_id, id: req.params.command_id } });
- if (!commandExists) {
- res.status(404).send({ code: 404, message: "Unknown application command" });
- return;
- }
+ if (!commandExists) {
+ res.status(404).send({ code: 404, message: "Unknown application command" });
+ return;
+ }
- await ApplicationCommand.delete({ application_id: req.params.application_id, id: req.params.command_id });
- res.sendStatus(204);
+ await ApplicationCommand.delete({ application_id: req.params.application_id, id: req.params.command_id });
+ res.sendStatus(204);
});
export default router;
diff --git "a/src/api/routes/applications/\043application_id/commands/index.ts" "b/src/api/routes/applications/\043application_id/commands/index.ts"
index 97753f0..91824be 100644
--- "a/src/api/routes/applications/\043application_id/commands/index.ts"
+++ "b/src/api/routes/applications/\043application_id/commands/index.ts"
@@ -25,147 +25,147 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
+ const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
- if (!applicationExists) {
- res.status(404).send({ code: 404, message: "Unknown application" });
- return;
- }
+ if (!applicationExists) {
+ res.status(404).send({ code: 404, message: "Unknown application" });
+ return;
+ }
- const command = await ApplicationCommand.find({ where: { application_id: req.params.application_id } });
- res.send(command);
+ const command = await ApplicationCommand.find({ where: { application_id: req.params.application_id } });
+ res.send(command);
});
router.post(
- "/",
- route({
- requestBody: "ApplicationCommandCreateSchema",
- }),
- async (req: Request, res: Response) => {
- const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
+ "/",
+ route({
+ requestBody: "ApplicationCommandCreateSchema",
+ }),
+ async (req: Request, res: Response) => {
+ const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
- if (!applicationExists) {
- res.status(404).send({ code: 404, message: "Unknown application" });
- return;
- }
+ if (!applicationExists) {
+ res.status(404).send({ code: 404, message: "Unknown application" });
+ return;
+ }
- const body = req.body as ApplicationCommandCreateSchema;
+ const body = req.body as ApplicationCommandCreateSchema;
- if (!body.type) {
- body.type = 1;
- }
+ if (!body.type) {
+ body.type = 1;
+ }
- if (body.name.trim().length < 1 || body.name.trim().length > 32) {
- // TODO: configurable?
- throw FieldErrors({
- name: {
- code: "BASE_TYPE_BAD_LENGTH",
- message: `Must be between 1 and 32 in length.`,
- },
- });
- }
+ if (body.name.trim().length < 1 || body.name.trim().length > 32) {
+ // TODO: configurable?
+ throw FieldErrors({
+ name: {
+ code: "BASE_TYPE_BAD_LENGTH",
+ message: `Must be between 1 and 32 in length.`,
+ },
+ });
+ }
- const commandForDb: ApplicationCommandSchema = {
- application_id: req.params.application_id,
- name: body.name.trim(),
- name_localizations: body.name_localizations,
- description: body.description?.trim() || "",
- description_localizations: body.description_localizations,
- default_member_permissions: body.default_member_permissions || null,
- contexts: body.contexts,
- dm_permission: body.dm_permission || true,
- global_popularity_rank: 1,
- handler: body.handler,
- integration_types: body.integration_types,
- nsfw: body.nsfw,
- options: body.options,
- type: body.type,
- version: Snowflake.generate(),
- };
+ const commandForDb: ApplicationCommandSchema = {
+ application_id: req.params.application_id,
+ name: body.name.trim(),
+ name_localizations: body.name_localizations,
+ description: body.description?.trim() || "",
+ description_localizations: body.description_localizations,
+ default_member_permissions: body.default_member_permissions || null,
+ contexts: body.contexts,
+ dm_permission: body.dm_permission || true,
+ global_popularity_rank: 1,
+ handler: body.handler,
+ integration_types: body.integration_types,
+ nsfw: body.nsfw,
+ options: body.options,
+ type: body.type,
+ version: Snowflake.generate(),
+ };
- const commandExists = await ApplicationCommand.exists({ where: { application_id: req.params.application_id, name: body.name.trim() } });
+ const commandExists = await ApplicationCommand.exists({ where: { application_id: req.params.application_id, name: body.name.trim() } });
- if (commandExists) {
- await ApplicationCommand.update({ application_id: req.params.application_id, name: body.name.trim() }, commandForDb);
- } else {
- commandForDb.id = Snowflake.generate(); // Have to be done that way so the id doesn't change
- await ApplicationCommand.save(commandForDb);
- }
+ if (commandExists) {
+ await ApplicationCommand.update({ application_id: req.params.application_id, name: body.name.trim() }, commandForDb);
+ } else {
+ commandForDb.id = Snowflake.generate(); // Have to be done that way so the id doesn't change
+ await ApplicationCommand.save(commandForDb);
+ }
- res.send(body);
- },
+ res.send(body);
+ },
);
router.put(
- "/",
- route({
- requestBody: "BulkApplicationCommandCreateSchema",
- }),
- async (req: Request, res: Response) => {
- const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
+ "/",
+ route({
+ requestBody: "BulkApplicationCommandCreateSchema",
+ }),
+ async (req: Request, res: Response) => {
+ const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
- if (!applicationExists) {
- res.status(404).send({ code: 404, message: "Unknown application" });
- return;
- }
+ if (!applicationExists) {
+ res.status(404).send({ code: 404, message: "Unknown application" });
+ return;
+ }
- const body = req.body as ApplicationCommandCreateSchema[];
+ const body = req.body as ApplicationCommandCreateSchema[];
- // Remove commands not present in array
- const applicationCommands = await ApplicationCommand.find({ where: { application_id: req.params.application_id, guild_id: IsNull() } });
+ // Remove commands not present in array
+ const applicationCommands = await ApplicationCommand.find({ where: { application_id: req.params.application_id, guild_id: IsNull() } });
- const commandNamesInArray = body.map((c) => c.name);
- const commandsNotInArray = applicationCommands.filter((c) => !commandNamesInArray.includes(c.name));
+ const commandNamesInArray = body.map((c) => c.name);
+ const commandsNotInArray = applicationCommands.filter((c) => !commandNamesInArray.includes(c.name));
- for (const command of commandsNotInArray) {
- await ApplicationCommand.delete({ application_id: req.params.application_id, guild_id: IsNull(), id: command.id });
- }
+ for (const command of commandsNotInArray) {
+ await ApplicationCommand.delete({ application_id: req.params.application_id, guild_id: IsNull(), id: command.id });
+ }
- for (const command of body) {
- if (!command.type) {
- command.type = 1;
- }
+ for (const command of body) {
+ if (!command.type) {
+ command.type = 1;
+ }
- if (command.name.trim().length < 1 || command.name.trim().length > 32) {
- // TODO: configurable?
- throw FieldErrors({
- name: {
- code: "BASE_TYPE_BAD_LENGTH",
- message: `Must be between 1 and 32 in length.`,
- },
- });
- }
+ if (command.name.trim().length < 1 || command.name.trim().length > 32) {
+ // TODO: configurable?
+ throw FieldErrors({
+ name: {
+ code: "BASE_TYPE_BAD_LENGTH",
+ message: `Must be between 1 and 32 in length.`,
+ },
+ });
+ }
- const commandForDb: ApplicationCommandSchema = {
- application_id: req.params.application_id,
- name: command.name.trim(),
- name_localizations: command.name_localizations,
- description: command.description?.trim() || "",
- description_localizations: command.description_localizations,
- default_member_permissions: command.default_member_permissions || null,
- contexts: command.contexts,
- dm_permission: command.dm_permission || true,
- global_popularity_rank: 1,
- handler: command.handler,
- integration_types: command.integration_types,
- nsfw: command.nsfw,
- options: command.options,
- type: command.type,
- version: Snowflake.generate(),
- };
+ const commandForDb: ApplicationCommandSchema = {
+ application_id: req.params.application_id,
+ name: command.name.trim(),
+ name_localizations: command.name_localizations,
+ description: command.description?.trim() || "",
+ description_localizations: command.description_localizations,
+ default_member_permissions: command.default_member_permissions || null,
+ contexts: command.contexts,
+ dm_permission: command.dm_permission || true,
+ global_popularity_rank: 1,
+ handler: command.handler,
+ integration_types: command.integration_types,
+ nsfw: command.nsfw,
+ options: command.options,
+ type: command.type,
+ version: Snowflake.generate(),
+ };
- const commandExists = await ApplicationCommand.exists({ where: { application_id: req.params.application_id, name: command.name.trim() } });
+ const commandExists = await ApplicationCommand.exists({ where: { application_id: req.params.application_id, name: command.name.trim() } });
- if (commandExists) {
- await ApplicationCommand.update({ application_id: req.params.application_id, name: command.name.trim() }, commandForDb);
- } else {
- commandForDb.id = Snowflake.generate(); // Have to be done that way so the id doesn't change
- await ApplicationCommand.save(commandForDb);
- }
- }
+ if (commandExists) {
+ await ApplicationCommand.update({ application_id: req.params.application_id, name: command.name.trim() }, commandForDb);
+ } else {
+ commandForDb.id = Snowflake.generate(); // Have to be done that way so the id doesn't change
+ await ApplicationCommand.save(commandForDb);
+ }
+ }
- res.send(body);
- },
+ res.send(body);
+ },
);
export default router;
diff --git "a/src/api/routes/applications/\043application_id/entitlements.ts" "b/src/api/routes/applications/\043application_id/entitlements.ts"
index 63a7e7b..4cd13b9 100644
--- "a/src/api/routes/applications/\043application_id/entitlements.ts"
+++ "b/src/api/routes/applications/\043application_id/entitlements.ts"
@@ -22,19 +22,19 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "ApplicationEntitlementsResponse",
- },
- },
- }),
- (req: Request, res: Response) => {
- // TODO:
- //const { exclude_consumed } = req.query;
- res.status(200).send([]);
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "ApplicationEntitlementsResponse",
+ },
+ },
+ }),
+ (req: Request, res: Response) => {
+ // TODO:
+ //const { exclude_consumed } = req.query;
+ res.status(200).send([]);
+ },
);
export default router;
diff --git "a/src/api/routes/applications/\043application_id/guilds/\043guild_id/commands/\043command_id/index.ts" "b/src/api/routes/applications/\043application_id/guilds/\043guild_id/commands/\043command_id/index.ts"
index 2570358..be2d62e 100644
--- "a/src/api/routes/applications/\043application_id/guilds/\043guild_id/commands/\043command_id/index.ts"
+++ "b/src/api/routes/applications/\043application_id/guilds/\043guild_id/commands/\043command_id/index.ts"
@@ -24,140 +24,140 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
+ const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
- if (!applicationExists) {
- res.status(404).send({ code: 404, message: "Unknown application" });
- return;
- }
+ if (!applicationExists) {
+ res.status(404).send({ code: 404, message: "Unknown application" });
+ return;
+ }
- const guildExists = await Guild.exists({ where: { id: req.params.guild_id } });
+ const guildExists = await Guild.exists({ where: { id: req.params.guild_id } });
- if (!guildExists) {
- res.status(404).send({ code: 404, message: "Unknown Server" });
- return;
- }
+ if (!guildExists) {
+ res.status(404).send({ code: 404, message: "Unknown Server" });
+ return;
+ }
- if (!(await Member.exists({ where: { id: req.params.application_id, guild_id: req.params.guild_id } }))) {
- res.status(401).send({ code: 401, message: "Missing Access" });
- return;
- }
+ if (!(await Member.exists({ where: { id: req.params.application_id, guild_id: req.params.guild_id } }))) {
+ res.status(401).send({ code: 401, message: "Missing Access" });
+ return;
+ }
- const command = await ApplicationCommand.findOne({ where: { application_id: req.params.application_id, id: req.params.command_id, guild_id: req.params.guild_id } });
+ const command = await ApplicationCommand.findOne({ where: { application_id: req.params.application_id, id: req.params.command_id, guild_id: req.params.guild_id } });
- if (!command) {
- res.status(404).send({ code: 404, message: "Unknown application command" });
- return;
- }
+ if (!command) {
+ res.status(404).send({ code: 404, message: "Unknown application command" });
+ return;
+ }
- res.send(command);
+ res.send(command);
});
router.patch(
- "/",
- route({
- requestBody: "ApplicationCommandCreateSchema",
- }),
- async (req: Request, res: Response) => {
- const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
+ "/",
+ route({
+ requestBody: "ApplicationCommandCreateSchema",
+ }),
+ async (req: Request, res: Response) => {
+ const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
- if (!applicationExists) {
- res.status(404).send({ code: 404, message: "Unknown application" });
- return;
- }
+ if (!applicationExists) {
+ res.status(404).send({ code: 404, message: "Unknown application" });
+ return;
+ }
- const guildExists = await Guild.exists({ where: { id: req.params.guild_id } });
+ const guildExists = await Guild.exists({ where: { id: req.params.guild_id } });
- if (!guildExists) {
- res.status(404).send({ code: 404, message: "Unknown Server" });
- return;
- }
+ if (!guildExists) {
+ res.status(404).send({ code: 404, message: "Unknown Server" });
+ return;
+ }
- if (!(await Member.exists({ where: { id: req.params.application_id, guild_id: req.params.guild_id } }))) {
- res.status(401).send({ code: 401, message: "Missing Access" });
- return;
- }
+ if (!(await Member.exists({ where: { id: req.params.application_id, guild_id: req.params.guild_id } }))) {
+ res.status(401).send({ code: 401, message: "Missing Access" });
+ return;
+ }
- const body = req.body as ApplicationCommandCreateSchema;
+ const body = req.body as ApplicationCommandCreateSchema;
- if (!body.type) {
- body.type = 1;
- }
+ if (!body.type) {
+ body.type = 1;
+ }
- if (body.name.trim().length < 1 || body.name.trim().length > 32) {
- // TODO: configurable?
- throw FieldErrors({
- name: {
- code: "BASE_TYPE_BAD_LENGTH",
- message: `Must be between 1 and 32 in length.`,
- },
- });
- }
+ if (body.name.trim().length < 1 || body.name.trim().length > 32) {
+ // TODO: configurable?
+ throw FieldErrors({
+ name: {
+ code: "BASE_TYPE_BAD_LENGTH",
+ message: `Must be between 1 and 32 in length.`,
+ },
+ });
+ }
- const commandForDb: ApplicationCommandSchema = {
- application_id: req.params.application_id,
- name: body.name.trim(),
- name_localizations: body.name_localizations,
- description: body.description?.trim() || "",
- description_localizations: body.description_localizations,
- default_member_permissions: body.default_member_permissions || null,
- contexts: body.contexts,
- dm_permission: body.dm_permission || true,
- global_popularity_rank: 1,
- handler: body.handler,
- integration_types: body.integration_types,
- nsfw: body.nsfw,
- options: body.options,
- type: body.type,
- version: Snowflake.generate(),
- };
+ const commandForDb: ApplicationCommandSchema = {
+ application_id: req.params.application_id,
+ name: body.name.trim(),
+ name_localizations: body.name_localizations,
+ description: body.description?.trim() || "",
+ description_localizations: body.description_localizations,
+ default_member_permissions: body.default_member_permissions || null,
+ contexts: body.contexts,
+ dm_permission: body.dm_permission || true,
+ global_popularity_rank: 1,
+ handler: body.handler,
+ integration_types: body.integration_types,
+ nsfw: body.nsfw,
+ options: body.options,
+ type: body.type,
+ version: Snowflake.generate(),
+ };
- const commandExists = await ApplicationCommand.exists({
- where: { application_id: req.params.application_id, guild_id: req.params.guild_id, id: req.params.command_id, name: body.name.trim() },
- });
+ const commandExists = await ApplicationCommand.exists({
+ where: { application_id: req.params.application_id, guild_id: req.params.guild_id, id: req.params.command_id, name: body.name.trim() },
+ });
- if (!commandExists) {
- res.status(404).send({ code: 404, message: "Unknown application command" });
- return;
- }
+ if (!commandExists) {
+ res.status(404).send({ code: 404, message: "Unknown application command" });
+ return;
+ }
- await ApplicationCommand.update(
- { application_id: req.params.application_id, guild_id: req.params.guild_id, id: req.params.command_id, name: body.name.trim() },
- commandForDb,
- );
- res.send(commandForDb);
- },
+ await ApplicationCommand.update(
+ { application_id: req.params.application_id, guild_id: req.params.guild_id, id: req.params.command_id, name: body.name.trim() },
+ commandForDb,
+ );
+ res.send(commandForDb);
+ },
);
router.delete("/", async (req: Request, res: Response) => {
- const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
+ const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
- if (!applicationExists) {
- res.status(404).send({ code: 404, message: "Unknown application" });
- return;
- }
+ if (!applicationExists) {
+ res.status(404).send({ code: 404, message: "Unknown application" });
+ return;
+ }
- const guildExists = await Guild.exists({ where: { id: req.params.guild_id } });
+ const guildExists = await Guild.exists({ where: { id: req.params.guild_id } });
- if (!guildExists) {
- res.status(404).send({ code: 404, message: "Unknown Server" });
- return;
- }
+ if (!guildExists) {
+ res.status(404).send({ code: 404, message: "Unknown Server" });
+ return;
+ }
- if (!(await Member.exists({ where: { id: req.params.application_id, guild_id: req.params.guild_id } }))) {
- res.status(401).send({ code: 401, message: "Missing Access" });
- return;
- }
+ if (!(await Member.exists({ where: { id: req.params.application_id, guild_id: req.params.guild_id } }))) {
+ res.status(401).send({ code: 401, message: "Missing Access" });
+ return;
+ }
- const commandExists = await ApplicationCommand.exists({ where: { application_id: req.params.application_id, guild_id: req.params.guild_id, id: req.params.command_id } });
+ const commandExists = await ApplicationCommand.exists({ where: { application_id: req.params.application_id, guild_id: req.params.guild_id, id: req.params.command_id } });
- if (!commandExists) {
- res.status(404).send({ code: 404, message: "Unknown application command" });
- return;
- }
+ if (!commandExists) {
+ res.status(404).send({ code: 404, message: "Unknown application command" });
+ return;
+ }
- await ApplicationCommand.delete({ application_id: req.params.application_id, guild_id: req.params.guild_id, id: req.params.command_id });
- res.sendStatus(204);
+ await ApplicationCommand.delete({ application_id: req.params.application_id, guild_id: req.params.guild_id, id: req.params.command_id });
+ res.sendStatus(204);
});
export default router;
diff --git "a/src/api/routes/applications/\043application_id/guilds/\043guild_id/commands/index.ts" "b/src/api/routes/applications/\043application_id/guilds/\043guild_id/commands/index.ts"
index 1639e7b..607c846 100644
--- "a/src/api/routes/applications/\043application_id/guilds/\043guild_id/commands/index.ts"
+++ "b/src/api/routes/applications/\043application_id/guilds/\043guild_id/commands/index.ts"
@@ -24,185 +24,185 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
+ const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
- if (!applicationExists) {
- res.status(404).send({ code: 404, message: "Unknown application" });
- return;
- }
+ if (!applicationExists) {
+ res.status(404).send({ code: 404, message: "Unknown application" });
+ return;
+ }
- const guildExists = await Guild.exists({ where: { id: req.params.guild_id } });
+ const guildExists = await Guild.exists({ where: { id: req.params.guild_id } });
- if (!guildExists) {
- res.status(404).send({ code: 404, message: "Unknown Server" });
- return;
- }
+ if (!guildExists) {
+ res.status(404).send({ code: 404, message: "Unknown Server" });
+ return;
+ }
- if (!(await Member.exists({ where: { id: req.params.application_id, guild_id: req.params.guild_id } }))) {
- res.status(401).send({ code: 401, message: "Missing Access" });
- return;
- }
+ if (!(await Member.exists({ where: { id: req.params.application_id, guild_id: req.params.guild_id } }))) {
+ res.status(401).send({ code: 401, message: "Missing Access" });
+ return;
+ }
- const command = await ApplicationCommand.find({ where: { application_id: req.params.application_id, guild_id: req.params.guild_id } });
- res.send(command);
+ const command = await ApplicationCommand.find({ where: { application_id: req.params.application_id, guild_id: req.params.guild_id } });
+ res.send(command);
});
router.post(
- "/",
- route({
- requestBody: "ApplicationCommandCreateSchema",
- }),
- async (req: Request, res: Response) => {
- const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
+ "/",
+ route({
+ requestBody: "ApplicationCommandCreateSchema",
+ }),
+ async (req: Request, res: Response) => {
+ const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
- if (!applicationExists) {
- res.status(404).send({ code: 404, message: "Unknown application" });
- return;
- }
+ if (!applicationExists) {
+ res.status(404).send({ code: 404, message: "Unknown application" });
+ return;
+ }
- const guildExists = await Guild.exists({ where: { id: req.params.guild_id } });
+ const guildExists = await Guild.exists({ where: { id: req.params.guild_id } });
- if (!guildExists) {
- res.status(404).send({ code: 404, message: "Unknown Server" });
- return;
- }
+ if (!guildExists) {
+ res.status(404).send({ code: 404, message: "Unknown Server" });
+ return;
+ }
- if (!(await Member.exists({ where: { id: req.params.application_id, guild_id: req.params.guild_id } }))) {
- res.status(401).send({ code: 401, message: "Missing Access" });
- return;
- }
+ if (!(await Member.exists({ where: { id: req.params.application_id, guild_id: req.params.guild_id } }))) {
+ res.status(401).send({ code: 401, message: "Missing Access" });
+ return;
+ }
- const body = req.body as ApplicationCommandCreateSchema;
+ const body = req.body as ApplicationCommandCreateSchema;
- if (!body.type) {
- body.type = 1;
- }
+ if (!body.type) {
+ body.type = 1;
+ }
- if (body.name.trim().length < 1 || body.name.trim().length > 32) {
- // TODO: configurable?
- throw FieldErrors({
- name: {
- code: "BASE_TYPE_BAD_LENGTH",
- message: `Must be between 1 and 32 in length.`,
- },
- });
- }
+ if (body.name.trim().length < 1 || body.name.trim().length > 32) {
+ // TODO: configurable?
+ throw FieldErrors({
+ name: {
+ code: "BASE_TYPE_BAD_LENGTH",
+ message: `Must be between 1 and 32 in length.`,
+ },
+ });
+ }
- const commandForDb: ApplicationCommandSchema = {
- application_id: req.params.application_id,
- guild_id: req.params.guild_id,
- name: body.name.trim(),
- name_localizations: body.name_localizations,
- description: body.description?.trim() || "",
- description_localizations: body.description_localizations,
- default_member_permissions: body.default_member_permissions || null,
- contexts: body.contexts,
- dm_permission: body.dm_permission || true,
- global_popularity_rank: 1,
- handler: body.handler,
- integration_types: body.integration_types,
- nsfw: body.nsfw,
- options: body.options,
- type: body.type,
- version: Snowflake.generate(),
- };
+ const commandForDb: ApplicationCommandSchema = {
+ application_id: req.params.application_id,
+ guild_id: req.params.guild_id,
+ name: body.name.trim(),
+ name_localizations: body.name_localizations,
+ description: body.description?.trim() || "",
+ description_localizations: body.description_localizations,
+ default_member_permissions: body.default_member_permissions || null,
+ contexts: body.contexts,
+ dm_permission: body.dm_permission || true,
+ global_popularity_rank: 1,
+ handler: body.handler,
+ integration_types: body.integration_types,
+ nsfw: body.nsfw,
+ options: body.options,
+ type: body.type,
+ version: Snowflake.generate(),
+ };
- const commandExists = await ApplicationCommand.exists({ where: { application_id: req.params.application_id, guild_id: req.params.guild_id, name: body.name.trim() } });
+ const commandExists = await ApplicationCommand.exists({ where: { application_id: req.params.application_id, guild_id: req.params.guild_id, name: body.name.trim() } });
- if (commandExists) {
- await ApplicationCommand.update({ application_id: req.params.application_id, guild_id: req.params.guild_id, name: body.name.trim() }, commandForDb);
- } else {
- commandForDb.id = Snowflake.generate(); // Have to be done that way so the id doesn't change
- await ApplicationCommand.save(commandForDb);
- }
+ if (commandExists) {
+ await ApplicationCommand.update({ application_id: req.params.application_id, guild_id: req.params.guild_id, name: body.name.trim() }, commandForDb);
+ } else {
+ commandForDb.id = Snowflake.generate(); // Have to be done that way so the id doesn't change
+ await ApplicationCommand.save(commandForDb);
+ }
- res.send(body);
- },
+ res.send(body);
+ },
);
router.put(
- "/",
- route({
- requestBody: "BulkApplicationCommandCreateSchema",
- }),
- async (req: Request, res: Response) => {
- const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
+ "/",
+ route({
+ requestBody: "BulkApplicationCommandCreateSchema",
+ }),
+ async (req: Request, res: Response) => {
+ const applicationExists = await Application.exists({ where: { id: req.params.application_id } });
- if (!applicationExists) {
- res.status(404).send({ code: 404, message: "Unknown application" });
- return;
- }
+ if (!applicationExists) {
+ res.status(404).send({ code: 404, message: "Unknown application" });
+ return;
+ }
- const guildExists = await Guild.exists({ where: { id: req.params.guild_id } });
+ const guildExists = await Guild.exists({ where: { id: req.params.guild_id } });
- if (!guildExists) {
- res.status(404).send({ code: 404, message: "Unknown Server" });
- return;
- }
+ if (!guildExists) {
+ res.status(404).send({ code: 404, message: "Unknown Server" });
+ return;
+ }
- if (!(await Member.exists({ where: { id: req.params.application_id, guild_id: req.params.guild_id } }))) {
- res.status(401).send({ code: 401, message: "Missing Access" });
- return;
- }
+ if (!(await Member.exists({ where: { id: req.params.application_id, guild_id: req.params.guild_id } }))) {
+ res.status(401).send({ code: 401, message: "Missing Access" });
+ return;
+ }
- const body = req.body as ApplicationCommandCreateSchema[];
+ const body = req.body as ApplicationCommandCreateSchema[];
- // Remove commands not present in array
- const applicationCommands = await ApplicationCommand.find({ where: { application_id: req.params.application_id, guild_id: req.params.guild_id } });
+ // Remove commands not present in array
+ const applicationCommands = await ApplicationCommand.find({ where: { application_id: req.params.application_id, guild_id: req.params.guild_id } });
- const commandNamesInArray = body.map((c) => c.name);
- const commandsNotInArray = applicationCommands.filter((c) => !commandNamesInArray.includes(c.name));
+ const commandNamesInArray = body.map((c) => c.name);
+ const commandsNotInArray = applicationCommands.filter((c) => !commandNamesInArray.includes(c.name));
- for (const command of commandsNotInArray) {
- await ApplicationCommand.delete({ application_id: req.params.application_id, guild_id: req.params.guild_id, id: command.id });
- }
+ for (const command of commandsNotInArray) {
+ await ApplicationCommand.delete({ application_id: req.params.application_id, guild_id: req.params.guild_id, id: command.id });
+ }
- for (const command of body) {
- if (!command.type) {
- command.type = 1;
- }
+ for (const command of body) {
+ if (!command.type) {
+ command.type = 1;
+ }
- if (command.name.trim().length < 1 || command.name.trim().length > 32) {
- // TODO: configurable?
- throw FieldErrors({
- name: {
- code: "BASE_TYPE_BAD_LENGTH",
- message: `Must be between 1 and 32 in length.`,
- },
- });
- }
+ if (command.name.trim().length < 1 || command.name.trim().length > 32) {
+ // TODO: configurable?
+ throw FieldErrors({
+ name: {
+ code: "BASE_TYPE_BAD_LENGTH",
+ message: `Must be between 1 and 32 in length.`,
+ },
+ });
+ }
- const commandForDb: ApplicationCommandSchema = {
- application_id: req.params.application_id,
- guild_id: req.params.guild_id,
- name: command.name.trim(),
- name_localizations: command.name_localizations,
- description: command.description?.trim() || "",
- description_localizations: command.description_localizations,
- default_member_permissions: command.default_member_permissions || null,
- contexts: command.contexts,
- dm_permission: command.dm_permission || true,
- global_popularity_rank: 1,
- handler: command.handler,
- integration_types: command.integration_types,
- nsfw: command.nsfw,
- options: command.options,
- type: command.type,
- version: Snowflake.generate(),
- };
+ const commandForDb: ApplicationCommandSchema = {
+ application_id: req.params.application_id,
+ guild_id: req.params.guild_id,
+ name: command.name.trim(),
+ name_localizations: command.name_localizations,
+ description: command.description?.trim() || "",
+ description_localizations: command.description_localizations,
+ default_member_permissions: command.default_member_permissions || null,
+ contexts: command.contexts,
+ dm_permission: command.dm_permission || true,
+ global_popularity_rank: 1,
+ handler: command.handler,
+ integration_types: command.integration_types,
+ nsfw: command.nsfw,
+ options: command.options,
+ type: command.type,
+ version: Snowflake.generate(),
+ };
- const commandExists = await ApplicationCommand.exists({ where: { application_id: req.params.application_id, guild_id: req.params.guild_id, name: command.name } });
+ const commandExists = await ApplicationCommand.exists({ where: { application_id: req.params.application_id, guild_id: req.params.guild_id, name: command.name } });
- if (commandExists) {
- await ApplicationCommand.update({ application_id: req.params.application_id, guild_id: req.params.guild_id, name: command.name }, commandForDb);
- } else {
- commandForDb.id = Snowflake.generate(); // Have to be done that way so the id doesn't change
- await ApplicationCommand.save(commandForDb);
- }
- }
+ if (commandExists) {
+ await ApplicationCommand.update({ application_id: req.params.application_id, guild_id: req.params.guild_id, name: command.name }, commandForDb);
+ } else {
+ commandForDb.id = Snowflake.generate(); // Have to be done that way so the id doesn't change
+ await ApplicationCommand.save(commandForDb);
+ }
+ }
- res.send(body);
- },
+ res.send(body);
+ },
);
export default router;
diff --git "a/src/api/routes/applications/\043application_id/index.ts" "b/src/api/routes/applications/\043application_id/index.ts"
index c38895d..bf29f40 100644
--- "a/src/api/routes/applications/\043application_id/index.ts"
+++ "b/src/api/routes/applications/\043application_id/index.ts"
@@ -26,106 +26,106 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "Application",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const app = await Application.findOneOrFail({
- where: { id: req.params.application_id },
- relations: ["owner", "bot"],
- });
- if (app.owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "Application",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const app = await Application.findOneOrFail({
+ where: { id: req.params.application_id },
+ relations: ["owner", "bot"],
+ });
+ if (app.owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
- return res.json(app);
- },
+ return res.json(app);
+ },
);
router.patch(
- "/",
- route({
- requestBody: "ApplicationModifySchema",
- responses: {
- 200: {
- body: "Application",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as ApplicationModifySchema;
+ "/",
+ route({
+ requestBody: "ApplicationModifySchema",
+ responses: {
+ 200: {
+ body: "Application",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as ApplicationModifySchema;
- const app = await Application.findOneOrFail({
- where: { id: req.params.application_id },
- relations: ["owner", "bot"],
- });
+ const app = await Application.findOneOrFail({
+ where: { id: req.params.application_id },
+ relations: ["owner", "bot"],
+ });
- if (app.owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
+ if (app.owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
- if (app.owner.totp_secret && (!req.body.code || verifyToken(app.owner.totp_secret, req.body.code))) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
+ if (app.owner.totp_secret && (!req.body.code || verifyToken(app.owner.totp_secret, req.body.code))) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
- if (body.icon) {
- body.icon = await handleFile(`/app-icons/${app.id}`, body.icon as string);
- }
- if (body.cover_image) {
- body.cover_image = await handleFile(`/app-icons/${app.id}`, body.cover_image as string);
- }
+ if (body.icon) {
+ body.icon = await handleFile(`/app-icons/${app.id}`, body.icon as string);
+ }
+ if (body.cover_image) {
+ body.cover_image = await handleFile(`/app-icons/${app.id}`, body.cover_image as string);
+ }
- if (body.guild_id) {
- const guild = await Guild.findOneOrFail({
- where: { id: body.guild_id },
- select: ["owner_id"],
- });
- if (guild.owner_id != req.user_id) throw new HTTPError("You must be the owner of the guild to link it to an application", 400);
- }
+ if (body.guild_id) {
+ const guild = await Guild.findOneOrFail({
+ where: { id: body.guild_id },
+ select: ["owner_id"],
+ });
+ if (guild.owner_id != req.user_id) throw new HTTPError("You must be the owner of the guild to link it to an application", 400);
+ }
- if (app.bot) {
- app.bot.assign({ bio: body.description });
- await app.bot.save();
- }
+ if (app.bot) {
+ app.bot.assign({ bio: body.description });
+ await app.bot.save();
+ }
- app.assign(body);
+ app.assign(body);
- await app.save();
+ await app.save();
- return res.json(app);
- },
+ return res.json(app);
+ },
);
router.post(
- "/delete",
- route({
- responses: {
- 200: {},
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const app = await Application.findOneOrFail({
- where: { id: req.params.application_id },
- relations: ["bot", "owner"],
- });
- if (app.owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
+ "/delete",
+ route({
+ responses: {
+ 200: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const app = await Application.findOneOrFail({
+ where: { id: req.params.application_id },
+ relations: ["bot", "owner"],
+ });
+ if (app.owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION;
- if (app.owner.totp_secret && (!req.body.code || verifyToken(app.owner.totp_secret, req.body.code))) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
- if (app.bot) {
- await User.delete({ id: app.id });
- }
- await Application.delete({ id: app.id });
+ if (app.owner.totp_secret && (!req.body.code || verifyToken(app.owner.totp_secret, req.body.code))) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
+ if (app.bot) {
+ await User.delete({ id: app.id });
+ }
+ await Application.delete({ id: app.id });
- res.send().status(200);
- },
+ res.send().status(200);
+ },
);
export default router;
diff --git "a/src/api/routes/applications/\043application_id/skus.ts" "b/src/api/routes/applications/\043application_id/skus.ts"
index 0877f4f..9b9e338 100644
--- "a/src/api/routes/applications/\043application_id/skus.ts"
+++ "b/src/api/routes/applications/\043application_id/skus.ts"
@@ -22,17 +22,17 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "ApplicationSkusResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- res.json([]).status(200);
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "ApplicationSkusResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ res.json([]).status(200);
+ },
);
export default router;
diff --git a/src/api/routes/applications/@me.ts b/src/api/routes/applications/@me.ts
index f4a9097..c1cf0db 100644
--- a/src/api/routes/applications/@me.ts
+++ b/src/api/routes/applications/@me.ts
@@ -27,74 +27,74 @@
// TODO: actually make this be correct - this is just a copy paste of /applications/:id/index.ts minus delete
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "Application",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const app = await Application.findOneOrFail({
- where: { id: req.user_id },
- relations: ["owner", "bot"],
- });
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "Application",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const app = await Application.findOneOrFail({
+ where: { id: req.user_id },
+ relations: ["owner", "bot"],
+ });
- return res.json(app);
- },
+ return res.json(app);
+ },
);
router.patch(
- "/",
- route({
- requestBody: "ApplicationModifySchema",
- responses: {
- 200: {
- body: "Application",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as ApplicationModifySchema;
+ "/",
+ route({
+ requestBody: "ApplicationModifySchema",
+ responses: {
+ 200: {
+ body: "Application",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as ApplicationModifySchema;
- const app = await Application.findOneOrFail({
- where: { id: req.user_id },
- relations: ["owner", "bot"],
- });
+ const app = await Application.findOneOrFail({
+ where: { id: req.user_id },
+ relations: ["owner", "bot"],
+ });
- if (body.icon) {
- body.icon = await handleFile(`/app-icons/${app.id}`, body.icon as string);
- }
- if (body.cover_image) {
- body.cover_image = await handleFile(`/app-icons/${app.id}`, body.cover_image as string);
- }
+ if (body.icon) {
+ body.icon = await handleFile(`/app-icons/${app.id}`, body.icon as string);
+ }
+ if (body.cover_image) {
+ body.cover_image = await handleFile(`/app-icons/${app.id}`, body.cover_image as string);
+ }
- if (body.guild_id) {
- const guild = await Guild.findOneOrFail({
- where: { id: body.guild_id },
- select: ["owner_id"],
- });
- if (guild.owner_id != req.user_id) throw new HTTPError("You must be the owner of the guild to link it to an application", 400);
- }
+ if (body.guild_id) {
+ const guild = await Guild.findOneOrFail({
+ where: { id: body.guild_id },
+ select: ["owner_id"],
+ });
+ if (guild.owner_id != req.user_id) throw new HTTPError("You must be the owner of the guild to link it to an application", 400);
+ }
- if (app.bot) {
- app.bot.assign({ bio: body.description });
- await app.bot.save();
- }
+ if (app.bot) {
+ app.bot.assign({ bio: body.description });
+ await app.bot.save();
+ }
- app.assign(body);
+ app.assign(body);
- await app.save();
+ await app.save();
- return res.json(app);
- },
+ return res.json(app);
+ },
);
export default router;
diff --git a/src/api/routes/applications/detectable.ts b/src/api/routes/applications/detectable.ts
index 4de8a78..83122e7 100644
--- a/src/api/routes/applications/detectable.ts
+++ b/src/api/routes/applications/detectable.ts
@@ -22,32 +22,32 @@
const router: Router = Router({ mergeParams: true });
const cache = {
- data: {},
- expires: 0,
+ data: {},
+ expires: 0,
};
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "ApplicationDetectableResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- // cache for 6 hours
- if (Date.now() > cache.expires) {
- const response = await fetch("https://discord.com/api/v10/games/detectable"); // because, well, it's unauthenticated anyways
- const data = await response.json();
- cache.data = data as ApplicationDetectableResponse;
- cache.expires = Date.now() + 6 * 60 * 60 * 1000;
- }
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "ApplicationDetectableResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ // cache for 6 hours
+ if (Date.now() > cache.expires) {
+ const response = await fetch("https://discord.com/api/v10/games/detectable"); // because, well, it's unauthenticated anyways
+ const data = await response.json();
+ cache.data = data as ApplicationDetectableResponse;
+ cache.expires = Date.now() + 6 * 60 * 60 * 1000;
+ }
- res.set("Cache-Control", `public, max-age=${Math.floor((cache.expires - Date.now()) / 1000)}, s-maxage=${Math.floor((cache.expires - Date.now()) / 1000)}, immutable`)
- .status(200)
- .json(cache.data);
- },
+ res.set("Cache-Control", `public, max-age=${Math.floor((cache.expires - Date.now()) / 1000)}, s-maxage=${Math.floor((cache.expires - Date.now()) / 1000)}, immutable`)
+ .status(200)
+ .json(cache.data);
+ },
);
export default router;
diff --git a/src/api/routes/applications/index.ts b/src/api/routes/applications/index.ts
index e3b270c..ff89f03 100644
--- a/src/api/routes/applications/index.ts
+++ b/src/api/routes/applications/index.ts
@@ -24,54 +24,54 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APIApplicationArray",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const results = await Application.find({
- where: { owner: { id: req.user_id } },
- relations: ["owner", "bot"],
- });
- res.json(results).status(200);
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APIApplicationArray",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const results = await Application.find({
+ where: { owner: { id: req.user_id } },
+ relations: ["owner", "bot"],
+ });
+ res.json(results).status(200);
+ },
);
router.post(
- "/",
- route({
- requestBody: "ApplicationCreateSchema",
- responses: {
- 200: {
- body: "Application",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as ApplicationCreateSchema;
- const user = await User.findOneOrFail({ where: { id: req.user_id } });
+ "/",
+ route({
+ requestBody: "ApplicationCreateSchema",
+ responses: {
+ 200: {
+ body: "Application",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as ApplicationCreateSchema;
+ const user = await User.findOneOrFail({ where: { id: req.user_id } });
- const app = Application.create({
- name: trimSpecial(body.name),
- description: "",
- bot_public: true,
- owner: user,
- verify_key: "IMPLEMENTME",
- flags: 0,
- });
+ const app = Application.create({
+ name: trimSpecial(body.name),
+ description: "",
+ bot_public: true,
+ owner: user,
+ verify_key: "IMPLEMENTME",
+ flags: 0,
+ });
- // april 14, 2023: discord made bot users be automatically added to all new apps
- const { autoCreateBotUsers } = Config.get().general;
- if (autoCreateBotUsers) {
- await createAppBotUser(app, req);
- } else await app.save();
+ // april 14, 2023: discord made bot users be automatically added to all new apps
+ const { autoCreateBotUsers } = Config.get().general;
+ if (autoCreateBotUsers) {
+ await createAppBotUser(app, req);
+ } else await app.save();
- res.json(app);
- },
+ res.json(app);
+ },
);
export default router;
diff --git a/src/api/routes/attachments/refresh-urls.ts b/src/api/routes/attachments/refresh-urls.ts
index 92a7dd1..f153091 100644
--- a/src/api/routes/attachments/refresh-urls.ts
+++ b/src/api/routes/attachments/refresh-urls.ts
@@ -23,37 +23,37 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "RefreshUrlsRequestSchema",
- responses: {
- 200: {
- body: "RefreshUrlsResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { attachment_urls } = req.body as RefreshUrlsRequestSchema;
+ "/",
+ route({
+ requestBody: "RefreshUrlsRequestSchema",
+ responses: {
+ 200: {
+ body: "RefreshUrlsResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { attachment_urls } = req.body as RefreshUrlsRequestSchema;
- const refreshed_urls = attachment_urls.map((url) => {
- return getUrlSignature(
- new NewUrlSignatureData({
- url: url,
- ip: req.ip,
- userAgent: req.headers["user-agent"] as string,
- }),
- )
- .applyToUrl(url)
- .toString();
- });
+ const refreshed_urls = attachment_urls.map((url) => {
+ return getUrlSignature(
+ new NewUrlSignatureData({
+ url: url,
+ ip: req.ip,
+ userAgent: req.headers["user-agent"] as string,
+ }),
+ )
+ .applyToUrl(url)
+ .toString();
+ });
- return res.status(200).json({
- refreshed_urls,
- });
- },
+ return res.status(200).json({
+ refreshed_urls,
+ });
+ },
);
export default router;
diff --git a/src/api/routes/auth/fingerprint.ts b/src/api/routes/auth/fingerprint.ts
index d7ef34b..a4a49d0 100644
--- a/src/api/routes/auth/fingerprint.ts
+++ b/src/api/routes/auth/fingerprint.ts
@@ -21,9 +21,9 @@
import { Request, Response, Router } from "express";
const router = Router({ mergeParams: true });
router.post("/", route({ responses: { 200: { body: "CreateFingerprintResponse" } } }), (req: Request, res: Response) => {
- const snowflake = Snowflake.generate();
- return res.json({
- fingerprint: `${snowflake}.${createHash("sha512").update(snowflake).digest("base64")}`,
- });
+ const snowflake = Snowflake.generate();
+ return res.json({
+ fingerprint: `${snowflake}.${createHash("sha512").update(snowflake).digest("base64")}`,
+ });
});
export default router;
diff --git a/src/api/routes/auth/forgot.ts b/src/api/routes/auth/forgot.ts
index 6e61382..db16c3b 100644
--- a/src/api/routes/auth/forgot.ts
+++ b/src/api/routes/auth/forgot.ts
@@ -23,55 +23,55 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "ForgotPasswordSchema",
- responses: {
- 204: {},
- 400: {
- body: "APIErrorOrCaptchaResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { login, captcha_key } = req.body as ForgotPasswordSchema;
+ "/",
+ route({
+ requestBody: "ForgotPasswordSchema",
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorOrCaptchaResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { login, captcha_key } = req.body as ForgotPasswordSchema;
- const config = Config.get();
+ const config = Config.get();
- if (config.passwordReset.requireCaptcha && config.security.captcha.enabled) {
- const { sitekey, service } = config.security.captcha;
- if (!captcha_key) {
- return res.status(400).json({
- captcha_key: ["captcha-required"],
- captcha_sitekey: sitekey,
- captcha_service: service,
- });
- }
+ if (config.passwordReset.requireCaptcha && config.security.captcha.enabled) {
+ const { sitekey, service } = config.security.captcha;
+ if (!captcha_key) {
+ return res.status(400).json({
+ captcha_key: ["captcha-required"],
+ captcha_sitekey: sitekey,
+ captcha_service: service,
+ });
+ }
- const ip = req.ip;
- const verify = await verifyCaptcha(captcha_key, ip);
- if (!verify.success) {
- return res.status(400).json({
- captcha_key: verify["error-codes"],
- captcha_sitekey: sitekey,
- captcha_service: service,
- });
- }
- }
+ const ip = req.ip;
+ const verify = await verifyCaptcha(captcha_key, ip);
+ if (!verify.success) {
+ return res.status(400).json({
+ captcha_key: verify["error-codes"],
+ captcha_sitekey: sitekey,
+ captcha_service: service,
+ });
+ }
+ }
- res.sendStatus(204);
+ res.sendStatus(204);
- const user = await User.findOne({
- where: [{ phone: login }, { email: login }],
- select: ["username", "id", "email"],
- }).catch(() => {});
+ const user = await User.findOne({
+ where: [{ phone: login }, { email: login }],
+ select: ["username", "id", "email"],
+ }).catch(() => {});
- if (user && user.email) {
- Email.sendResetPassword(user, user.email).catch((e) => {
- console.error(`Failed to send password reset email to ${user.username}#${user.discriminator} (${user.id}): ${e}`);
- });
- }
- },
+ if (user && user.email) {
+ Email.sendResetPassword(user, user.email).catch((e) => {
+ console.error(`Failed to send password reset email to ${user.username}#${user.discriminator} (${user.id}): ${e}`);
+ });
+ }
+ },
);
export default router;
diff --git a/src/api/routes/auth/generate-registration-tokens.ts b/src/api/routes/auth/generate-registration-tokens.ts
index be93295..a6b70c6 100644
--- a/src/api/routes/auth/generate-registration-tokens.ts
+++ b/src/api/routes/auth/generate-registration-tokens.ts
@@ -24,46 +24,46 @@
export default router;
router.get(
- "/",
- route({
- query: {
- count: {
- type: "number",
- description: "The number of registration tokens to generate. Defaults to 1.",
- },
- length: {
- type: "number",
- description: "The length of each registration token. Defaults to 255.",
- },
- },
- right: "CREATE_REGISTRATION_TOKENS",
- responses: { 200: { body: "GenerateRegistrationTokensResponse" } },
- }),
- async (req: Request, res: Response) => {
- const count = req.query.count ? parseInt(req.query.count as string) : 1;
- const length = req.query.length ? parseInt(req.query.length as string) : 255;
+ "/",
+ route({
+ query: {
+ count: {
+ type: "number",
+ description: "The number of registration tokens to generate. Defaults to 1.",
+ },
+ length: {
+ type: "number",
+ description: "The length of each registration token. Defaults to 255.",
+ },
+ },
+ right: "CREATE_REGISTRATION_TOKENS",
+ responses: { 200: { body: "GenerateRegistrationTokensResponse" } },
+ }),
+ async (req: Request, res: Response) => {
+ const count = req.query.count ? parseInt(req.query.count as string) : 1;
+ const length = req.query.length ? parseInt(req.query.length as string) : 255;
- const tokens: ValidRegistrationToken[] = [];
+ const tokens: ValidRegistrationToken[] = [];
- for (let i = 0; i < count; i++) {
- const token = ValidRegistrationToken.create({
- token: randomString(length),
- expires_at: new Date(Date.now() + Config.get().security.defaultRegistrationTokenExpiration),
- });
- tokens.push(token);
- }
+ for (let i = 0; i < count; i++) {
+ const token = ValidRegistrationToken.create({
+ token: randomString(length),
+ expires_at: new Date(Date.now() + Config.get().security.defaultRegistrationTokenExpiration),
+ });
+ tokens.push(token);
+ }
- // Why are these options used, exactly?
- await ValidRegistrationToken.save(tokens, {
- chunk: 1000,
- reload: false,
- transaction: false,
- });
+ // Why are these options used, exactly?
+ await ValidRegistrationToken.save(tokens, {
+ chunk: 1000,
+ reload: false,
+ transaction: false,
+ });
- const ret = req.query.include_url ? tokens.map((x) => `${Config.get().general.frontPage}/register?token=${x.token}`) : tokens.map((x) => x.token);
+ const ret = req.query.include_url ? tokens.map((x) => `${Config.get().general.frontPage}/register?token=${x.token}`) : tokens.map((x) => x.token);
- if (req.query.plain) return res.send(ret.join("\n"));
+ if (req.query.plain) return res.send(ret.join("\n"));
- return res.json({ tokens: ret });
- },
+ return res.json({ tokens: ret });
+ },
);
diff --git a/src/api/routes/auth/location-metadata.ts b/src/api/routes/auth/location-metadata.ts
index 92f4790..6f2f26a 100644
--- a/src/api/routes/auth/location-metadata.ts
+++ b/src/api/routes/auth/location-metadata.ts
@@ -22,24 +22,24 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "LocationMetadataResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- //TODO
- //Note: It's most likely related to legal. At the moment Discord hasn't finished this too
- const country_code = (await IpDataClient.getIpInfo(req.ip!))?.country_code;
- res.json({
- consent_required: false,
- country_code: country_code,
- promotional_email_opt_in: { required: true, pre_checked: false },
- });
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "LocationMetadataResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ //TODO
+ //Note: It's most likely related to legal. At the moment Discord hasn't finished this too
+ const country_code = (await IpDataClient.getIpInfo(req.ip!))?.country_code;
+ res.json({
+ consent_required: false,
+ country_code: country_code,
+ promotional_email_opt_in: { required: true, pre_checked: false },
+ });
+ },
);
export default router;
diff --git a/src/api/routes/auth/login.ts b/src/api/routes/auth/login.ts
index c8ef627..911ad4a 100644
--- a/src/api/routes/auth/login.ts
+++ b/src/api/routes/auth/login.ts
@@ -27,157 +27,157 @@
export default router;
router.post(
- "/",
- route({
- requestBody: "LoginSchema",
- responses: {
- 200: {
- body: "LoginResponse",
- },
- 400: {
- body: "APIErrorOrCaptchaResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { login, password, captcha_key, undelete } = req.body as LoginSchema;
+ "/",
+ route({
+ requestBody: "LoginSchema",
+ responses: {
+ 200: {
+ body: "LoginResponse",
+ },
+ 400: {
+ body: "APIErrorOrCaptchaResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { login, password, captcha_key, undelete } = req.body as LoginSchema;
- const config = Config.get();
+ const config = Config.get();
- if (config.login.requireCaptcha && config.security.captcha.enabled) {
- const { sitekey, service } = config.security.captcha;
- if (!captcha_key) {
- return res.status(400).json({
- captcha_key: ["captcha-required"],
- captcha_sitekey: sitekey,
- captcha_service: service,
- });
- }
+ if (config.login.requireCaptcha && config.security.captcha.enabled) {
+ const { sitekey, service } = config.security.captcha;
+ if (!captcha_key) {
+ return res.status(400).json({
+ captcha_key: ["captcha-required"],
+ captcha_sitekey: sitekey,
+ captcha_service: service,
+ });
+ }
- const ip = req.ip;
- const verify = await verifyCaptcha(captcha_key, ip);
- if (!verify.success) {
- return res.status(400).json({
- captcha_key: verify["error-codes"],
- captcha_sitekey: sitekey,
- captcha_service: service,
- });
- }
- }
+ const ip = req.ip;
+ const verify = await verifyCaptcha(captcha_key, ip);
+ if (!verify.success) {
+ return res.status(400).json({
+ captcha_key: verify["error-codes"],
+ captcha_sitekey: sitekey,
+ captcha_service: service,
+ });
+ }
+ }
- const user = await User.findOneOrFail({
- where: [{ phone: login }, { email: login }],
- select: ["data", "id", "disabled", "deleted", "totp_secret", "mfa_enabled", "webauthn_enabled", "security_keys", "verified"],
- relations: ["security_keys", "settings"],
- }).catch(() => {
- throw FieldErrors({
- login: {
- message: req.t("auth:login.INVALID_LOGIN"),
- code: "INVALID_LOGIN",
- },
- password: {
- message: req.t("auth:login.INVALID_LOGIN"),
- code: "INVALID_LOGIN",
- },
- });
- });
+ const user = await User.findOneOrFail({
+ where: [{ phone: login }, { email: login }],
+ select: ["data", "id", "disabled", "deleted", "totp_secret", "mfa_enabled", "webauthn_enabled", "security_keys", "verified"],
+ relations: ["security_keys", "settings"],
+ }).catch(() => {
+ throw FieldErrors({
+ login: {
+ message: req.t("auth:login.INVALID_LOGIN"),
+ code: "INVALID_LOGIN",
+ },
+ password: {
+ message: req.t("auth:login.INVALID_LOGIN"),
+ code: "INVALID_LOGIN",
+ },
+ });
+ });
- // the salt is saved in the password refer to bcrypt docs
- const same_password = await bcrypt.compare(password, user.data.hash || "");
- if (!same_password) {
- throw FieldErrors({
- login: {
- message: req.t("auth:login.INVALID_LOGIN"),
- code: "INVALID_LOGIN",
- },
- password: {
- message: req.t("auth:login.INVALID_LOGIN"),
- code: "INVALID_LOGIN",
- },
- });
- }
+ // the salt is saved in the password refer to bcrypt docs
+ const same_password = await bcrypt.compare(password, user.data.hash || "");
+ if (!same_password) {
+ throw FieldErrors({
+ login: {
+ message: req.t("auth:login.INVALID_LOGIN"),
+ code: "INVALID_LOGIN",
+ },
+ password: {
+ message: req.t("auth:login.INVALID_LOGIN"),
+ code: "INVALID_LOGIN",
+ },
+ });
+ }
- // return an error for unverified accounts if verification is required
- if (config.login.requireVerification && !user.verified) {
- throw FieldErrors({
- login: {
- code: "ACCOUNT_LOGIN_VERIFICATION_EMAIL",
- message: "Email verification is required, please check your email.",
- },
- });
- }
+ // return an error for unverified accounts if verification is required
+ if (config.login.requireVerification && !user.verified) {
+ throw FieldErrors({
+ login: {
+ code: "ACCOUNT_LOGIN_VERIFICATION_EMAIL",
+ message: "Email verification is required, please check your email.",
+ },
+ });
+ }
- if (user.mfa_enabled && !user.webauthn_enabled) {
- // TODO: This is not a discord.com ticket. I'm not sure what it is but I'm lazy
- const ticket = crypto.randomBytes(40).toString("hex");
+ if (user.mfa_enabled && !user.webauthn_enabled) {
+ // TODO: This is not a discord.com ticket. I'm not sure what it is but I'm lazy
+ const ticket = crypto.randomBytes(40).toString("hex");
- await User.update({ id: user.id }, { totp_last_ticket: ticket });
+ await User.update({ id: user.id }, { totp_last_ticket: ticket });
- return res.json({
- ticket: ticket,
- mfa: true,
- sms: false, // TODO
- token: null,
- });
- }
+ return res.json({
+ ticket: ticket,
+ mfa: true,
+ sms: false, // TODO
+ token: null,
+ });
+ }
- if (user.mfa_enabled && user.webauthn_enabled) {
- if (!WebAuthn.fido2) {
- // TODO: I did this for typescript and I can't use !
- throw new Error("WebAuthn not enabled");
- }
+ if (user.mfa_enabled && user.webauthn_enabled) {
+ if (!WebAuthn.fido2) {
+ // TODO: I did this for typescript and I can't use !
+ throw new Error("WebAuthn not enabled");
+ }
- const options = await WebAuthn.fido2.assertionOptions();
- const challenge = JSON.stringify({
- publicKey: {
- ...options,
- challenge: Buffer.from(options.challenge).toString("base64"),
- allowCredentials: user.security_keys.map((x) => ({
- id: x.key_id,
- type: "public-key",
- })),
- transports: ["usb", "ble", "nfc"],
- timeout: 60000,
- },
- });
+ const options = await WebAuthn.fido2.assertionOptions();
+ const challenge = JSON.stringify({
+ publicKey: {
+ ...options,
+ challenge: Buffer.from(options.challenge).toString("base64"),
+ allowCredentials: user.security_keys.map((x) => ({
+ id: x.key_id,
+ type: "public-key",
+ })),
+ transports: ["usb", "ble", "nfc"],
+ timeout: 60000,
+ },
+ });
- const ticket = await generateWebAuthnTicket(challenge);
- await User.update({ id: user.id }, { totp_last_ticket: ticket });
+ const ticket = await generateWebAuthnTicket(challenge);
+ await User.update({ id: user.id }, { totp_last_ticket: ticket });
- return res.json({
- ticket: ticket,
- mfa: true,
- sms: false, // TODO
- token: null,
- webauthn: challenge,
- });
- }
+ return res.json({
+ ticket: ticket,
+ mfa: true,
+ sms: false, // TODO
+ token: null,
+ webauthn: challenge,
+ });
+ }
- if (undelete) {
- // undelete refers to un'disable' here
- if (user.disabled) await User.update({ id: user.id }, { disabled: false });
- if (user.deleted) await User.update({ id: user.id }, { deleted: false });
- } else {
- if (user.deleted)
- return res.status(400).json({
- message: "This account is scheduled for deletion.",
- code: 20011,
- });
- if (user.disabled)
- return res.status(400).json({
- message: req.t("auth:login.ACCOUNT_DISABLED"),
- code: 20013,
- });
- }
+ if (undelete) {
+ // undelete refers to un'disable' here
+ if (user.disabled) await User.update({ id: user.id }, { disabled: false });
+ if (user.deleted) await User.update({ id: user.id }, { deleted: false });
+ } else {
+ if (user.deleted)
+ return res.status(400).json({
+ message: "This account is scheduled for deletion.",
+ code: 20011,
+ });
+ if (user.disabled)
+ return res.status(400).json({
+ message: req.t("auth:login.ACCOUNT_DISABLED"),
+ code: 20013,
+ });
+ }
- const token = await generateToken(user.id);
+ const token = await generateToken(user.id);
- // Notice this will have a different token structure, than discord
- // Discord header is just the user id as string, which is not possible with npm-jsonwebtoken package
- // https://user-images.githubusercontent.com/6506416/81051916-dd8c9900-8ec2-11ea-8794-daf12d6f31f0.png
+ // Notice this will have a different token structure, than discord
+ // Discord header is just the user id as string, which is not possible with npm-jsonwebtoken package
+ // https://user-images.githubusercontent.com/6506416/81051916-dd8c9900-8ec2-11ea-8794-daf12d6f31f0.png
- res.json({ token, settings: { ...user.settings, index: undefined } });
- },
+ res.json({ token, settings: { ...user.settings, index: undefined } });
+ },
);
/**
diff --git a/src/api/routes/auth/logout.ts b/src/api/routes/auth/logout.ts
index f20a199..b460e31 100644
--- a/src/api/routes/auth/logout.ts
+++ b/src/api/routes/auth/logout.ts
@@ -24,25 +24,25 @@
export default router;
router.post(
- "/",
- route({
- responses: {
- 204: {},
- },
- }),
- async (req: Request, res: Response) => {
- if (req.body.provider != null || req.body.voip_provider != null) {
- console.log(`[LOGOUT]: provider or voip provider not null!`, req.body);
- } else {
- delete req.body.provider;
- delete req.body.voip_provider;
- if (Object.keys(req.body).length != 0) console.log(`[LOGOUT]: Extra fields sent in logout!`, req.body);
- }
+ "/",
+ route({
+ responses: {
+ 204: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ if (req.body.provider != null || req.body.voip_provider != null) {
+ console.log(`[LOGOUT]: provider or voip provider not null!`, req.body);
+ } else {
+ delete req.body.provider;
+ delete req.body.voip_provider;
+ if (Object.keys(req.body).length != 0) console.log(`[LOGOUT]: Extra fields sent in logout!`, req.body);
+ }
- if (req.token.did) {
- await Session.delete({ user_id: req.user_id, session_id: req.token.did });
- }
+ if (req.token.did) {
+ await Session.delete({ user_id: req.user_id, session_id: req.token.did });
+ }
- res.status(204).send();
- },
+ res.status(204).send();
+ },
);
diff --git a/src/api/routes/auth/mfa/totp.ts b/src/api/routes/auth/mfa/totp.ts
index edf307c..b9f2fa8 100644
--- a/src/api/routes/auth/mfa/totp.ts
+++ b/src/api/routes/auth/mfa/totp.ts
@@ -25,54 +25,54 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "TotpSchema",
- responses: {
- 200: {
- body: "TokenResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- // const { code, ticket, gift_code_sku_id, login_source } =
- const { code, ticket } = req.body as TotpSchema;
+ "/",
+ route({
+ requestBody: "TotpSchema",
+ responses: {
+ 200: {
+ body: "TokenResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ // const { code, ticket, gift_code_sku_id, login_source } =
+ const { code, ticket } = req.body as TotpSchema;
- const user = await User.findOneOrFail({
- where: {
- totp_last_ticket: ticket,
- },
- select: ["id", "totp_secret"],
- relations: ["settings"],
- });
+ const user = await User.findOneOrFail({
+ where: {
+ totp_last_ticket: ticket,
+ },
+ select: ["id", "totp_secret"],
+ relations: ["settings"],
+ });
- const backup = await BackupCode.findOne({
- where: {
- code: code,
- expired: false,
- consumed: false,
- user: { id: user.id },
- },
- });
+ const backup = await BackupCode.findOne({
+ where: {
+ code: code,
+ expired: false,
+ consumed: false,
+ user: { id: user.id },
+ },
+ });
- if (!backup) {
- const ret = verifyToken(user.totp_secret || "", code);
- if (!ret || ret.delta != 0) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
- } else {
- backup.consumed = true;
- await backup.save();
- }
+ if (!backup) {
+ const ret = verifyToken(user.totp_secret || "", code);
+ if (!ret || ret.delta != 0) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
+ } else {
+ backup.consumed = true;
+ await backup.save();
+ }
- await User.update({ id: user.id }, { totp_last_ticket: "" });
+ await User.update({ id: user.id }, { totp_last_ticket: "" });
- return res.json({
- token: await generateToken(user.id),
- settings: { ...user.settings, index: undefined },
- });
- },
+ return res.json({
+ token: await generateToken(user.id),
+ settings: { ...user.settings, index: undefined },
+ });
+ },
);
export default router;
diff --git a/src/api/routes/auth/mfa/webauthn.ts b/src/api/routes/auth/mfa/webauthn.ts
index 63b1335..da476ab 100644
--- a/src/api/routes/auth/mfa/webauthn.ts
+++ b/src/api/routes/auth/mfa/webauthn.ts
@@ -25,77 +25,77 @@
const router = Router({ mergeParams: true });
function toArrayBuffer(buf: Buffer) {
- const ab = new ArrayBuffer(buf.length);
- const view = new Uint8Array(ab);
- for (let i = 0; i < buf.length; ++i) {
- view[i] = buf[i];
- }
- return ab;
+ const ab = new ArrayBuffer(buf.length);
+ const view = new Uint8Array(ab);
+ for (let i = 0; i < buf.length; ++i) {
+ view[i] = buf[i];
+ }
+ return ab;
}
router.post(
- "/",
- route({
- requestBody: "WebAuthnTotpSchema",
- responses: {
- 200: { body: "TokenResponse" },
- 400: { body: "APIErrorResponse" },
- },
- }),
- async (req: Request, res: Response) => {
- if (!WebAuthn.fido2) {
- // TODO: I did this for typescript and I can't use !
- throw new Error("WebAuthn not enabled");
- }
+ "/",
+ route({
+ requestBody: "WebAuthnTotpSchema",
+ responses: {
+ 200: { body: "TokenResponse" },
+ 400: { body: "APIErrorResponse" },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ if (!WebAuthn.fido2) {
+ // TODO: I did this for typescript and I can't use !
+ throw new Error("WebAuthn not enabled");
+ }
- const { code, ticket } = req.body as WebAuthnTotpSchema;
+ const { code, ticket } = req.body as WebAuthnTotpSchema;
- const user = await User.findOneOrFail({
- where: {
- totp_last_ticket: ticket,
- },
- select: ["id"],
- relations: ["settings"],
- });
+ const user = await User.findOneOrFail({
+ where: {
+ totp_last_ticket: ticket,
+ },
+ select: ["id"],
+ relations: ["settings"],
+ });
- const ret = await verifyWebAuthnToken(ticket);
- if (!ret) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
+ const ret = await verifyWebAuthnToken(ticket);
+ if (!ret) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
- await User.update({ id: user.id }, { totp_last_ticket: "" });
+ await User.update({ id: user.id }, { totp_last_ticket: "" });
- const clientAttestationResponse = JSON.parse(code);
+ const clientAttestationResponse = JSON.parse(code);
- if (!clientAttestationResponse.rawId) throw new HTTPError("Missing rawId", 400);
+ if (!clientAttestationResponse.rawId) throw new HTTPError("Missing rawId", 400);
- clientAttestationResponse.rawId = toArrayBuffer(Buffer.from(clientAttestationResponse.rawId, "base64url"));
+ clientAttestationResponse.rawId = toArrayBuffer(Buffer.from(clientAttestationResponse.rawId, "base64url"));
- const securityKey = await SecurityKey.findOneOrFail({
- where: {
- key_id: Buffer.from(clientAttestationResponse.rawId, "base64url").toString("base64"),
- },
- });
+ const securityKey = await SecurityKey.findOneOrFail({
+ where: {
+ key_id: Buffer.from(clientAttestationResponse.rawId, "base64url").toString("base64"),
+ },
+ });
- const assertionExpectations: ExpectedAssertionResult = JSON.parse(Buffer.from(clientAttestationResponse.response.clientDataJSON, "base64").toString());
+ const assertionExpectations: ExpectedAssertionResult = JSON.parse(Buffer.from(clientAttestationResponse.response.clientDataJSON, "base64").toString());
- const authnResult = await WebAuthn.fido2.assertionResult(clientAttestationResponse, {
- ...assertionExpectations,
- factor: "second",
- publicKey: securityKey.public_key,
- prevCounter: securityKey.counter,
- userHandle: securityKey.key_id,
- });
+ const authnResult = await WebAuthn.fido2.assertionResult(clientAttestationResponse, {
+ ...assertionExpectations,
+ factor: "second",
+ publicKey: securityKey.public_key,
+ prevCounter: securityKey.counter,
+ userHandle: securityKey.key_id,
+ });
- const counter = authnResult.authnrData.get("counter");
+ const counter = authnResult.authnrData.get("counter");
- securityKey.counter = counter;
+ securityKey.counter = counter;
- await securityKey.save();
+ await securityKey.save();
- return res.json({
- token: await generateToken(user.id),
- user_settings: user.settings,
- });
- },
+ return res.json({
+ token: await generateToken(user.id),
+ user_settings: user.settings,
+ });
+ },
);
export default router;
diff --git a/src/api/routes/auth/register.ts b/src/api/routes/auth/register.ts
index d4b061b..6aa52bf 100644
--- a/src/api/routes/auth/register.ts
+++ b/src/api/routes/auth/register.ts
@@ -27,294 +27,294 @@
const router: Router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "RegisterSchema",
- responses: {
- 200: { body: "TokenOnlyResponse" },
- 400: { body: "APIErrorOrCaptchaResponse" },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as RegisterSchema;
- const { register, security, limits } = Config.get();
- const ip = req.ip!;
+ "/",
+ route({
+ requestBody: "RegisterSchema",
+ responses: {
+ 200: { body: "TokenOnlyResponse" },
+ 400: { body: "APIErrorOrCaptchaResponse" },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as RegisterSchema;
+ const { register, security, limits } = Config.get();
+ const ip = req.ip!;
- // Reg tokens
- // They're a one time use token that bypasses registration limits ( rates, disabled reg, etc )
- let regTokenUsed = false;
- if (req.get("Referrer") && req.get("Referrer")?.includes("token=")) {
- // eg theyre on https://staging.spacebar.chat/register?token=whatever
- const token = req.get("Referrer")?.split("token=")[1].split("&")[0];
- if (token) {
- const regToken = await ValidRegistrationToken.findOneOrFail({
- where: { token, expires_at: MoreThan(new Date()) },
- });
- await regToken.remove();
- regTokenUsed = true;
- console.log(`[REGISTER] Registration token ${token} used for registration!`);
- } else {
- console.log(`[REGISTER] Invalid registration token ${token} used for registration by ${ip}!`);
- }
- }
+ // Reg tokens
+ // They're a one time use token that bypasses registration limits ( rates, disabled reg, etc )
+ let regTokenUsed = false;
+ if (req.get("Referrer") && req.get("Referrer")?.includes("token=")) {
+ // eg theyre on https://staging.spacebar.chat/register?token=whatever
+ const token = req.get("Referrer")?.split("token=")[1].split("&")[0];
+ if (token) {
+ const regToken = await ValidRegistrationToken.findOneOrFail({
+ where: { token, expires_at: MoreThan(new Date()) },
+ });
+ await regToken.remove();
+ regTokenUsed = true;
+ console.log(`[REGISTER] Registration token ${token} used for registration!`);
+ } else {
+ console.log(`[REGISTER] Invalid registration token ${token} used for registration by ${ip}!`);
+ }
+ }
- // check if registration is allowed
- if (!regTokenUsed && !register.allowNewRegistration) {
- throw FieldErrors({
- email: {
- code: "REGISTRATION_DISABLED",
- message: req.t("auth:register.REGISTRATION_DISABLED"),
- },
- });
- }
+ // check if registration is allowed
+ if (!regTokenUsed && !register.allowNewRegistration) {
+ throw FieldErrors({
+ email: {
+ code: "REGISTRATION_DISABLED",
+ message: req.t("auth:register.REGISTRATION_DISABLED"),
+ },
+ });
+ }
- // check if the user agreed to the Terms of Service
- if (!body.consent) {
- throw FieldErrors({
- consent: {
- code: "CONSENT_REQUIRED",
- message: req.t("auth:register.CONSENT_REQUIRED"),
- },
- });
- }
+ // check if the user agreed to the Terms of Service
+ if (!body.consent) {
+ throw FieldErrors({
+ consent: {
+ code: "CONSENT_REQUIRED",
+ message: req.t("auth:register.CONSENT_REQUIRED"),
+ },
+ });
+ }
- if (!regTokenUsed && register.disabled) {
- throw FieldErrors({
- email: {
- code: "DISABLED",
- message: "registration is disabled on this instance",
- },
- });
- }
+ if (!regTokenUsed && register.disabled) {
+ throw FieldErrors({
+ email: {
+ code: "DISABLED",
+ message: "registration is disabled on this instance",
+ },
+ });
+ }
- if (!regTokenUsed && register.requireCaptcha && security.captcha.enabled) {
- const { sitekey, service } = security.captcha;
- if (!body.captcha_key) {
- return res?.status(400).json({
- captcha_key: ["captcha-required"],
- captcha_sitekey: sitekey,
- captcha_service: service,
- });
- }
+ if (!regTokenUsed && register.requireCaptcha && security.captcha.enabled) {
+ const { sitekey, service } = security.captcha;
+ if (!body.captcha_key) {
+ return res?.status(400).json({
+ captcha_key: ["captcha-required"],
+ captcha_sitekey: sitekey,
+ captcha_service: service,
+ });
+ }
- const verify = await verifyCaptcha(body.captcha_key, ip);
- if (!verify.success) {
- return res.status(400).json({
- captcha_key: verify["error-codes"],
- captcha_sitekey: sitekey,
- captcha_service: service,
- });
- }
- }
+ const verify = await verifyCaptcha(body.captcha_key, ip);
+ if (!verify.success) {
+ return res.status(400).json({
+ captcha_key: verify["error-codes"],
+ captcha_sitekey: sitekey,
+ captcha_service: service,
+ });
+ }
+ }
- if (!regTokenUsed && !register.allowMultipleAccounts) {
- // TODO: check if fingerprint was eligible generated
- const exists = await User.findOne({
- where: { fingerprints: body.fingerprint },
- select: ["id"],
- });
+ if (!regTokenUsed && !register.allowMultipleAccounts) {
+ // TODO: check if fingerprint was eligible generated
+ const exists = await User.findOne({
+ where: { fingerprints: body.fingerprint },
+ select: ["id"],
+ });
- if (exists) {
- throw FieldErrors({
- email: {
- code: "EMAIL_ALREADY_REGISTERED",
- message: req.t("auth:register.EMAIL_ALREADY_REGISTERED"),
- },
- });
- }
- }
+ if (exists) {
+ throw FieldErrors({
+ email: {
+ code: "EMAIL_ALREADY_REGISTERED",
+ message: req.t("auth:register.EMAIL_ALREADY_REGISTERED"),
+ },
+ });
+ }
+ }
- if (!regTokenUsed && register.checkIp) {
- const blacklist = await AbuseIpDbClient.getBlacklist();
- if (blacklist) {
- const entry = blacklist.data.find((e) => e.ipAddress === ip);
+ if (!regTokenUsed && register.checkIp) {
+ const blacklist = await AbuseIpDbClient.getBlacklist();
+ if (blacklist) {
+ const entry = blacklist.data.find((e) => e.ipAddress === ip);
- if (entry && entry.abuseConfidenceScore >= register.blockAbuseIpDbAboveScore) {
- console.log(`[Register] ${ip} blocked from registration: AbuseIPDB score ${entry.abuseConfidenceScore} >= ${register.blockAbuseIpDbAboveScore} (BLACKLIST)`);
- throw new HTTPError("Your IP is blocked from registration");
- }
- }
+ if (entry && entry.abuseConfidenceScore >= register.blockAbuseIpDbAboveScore) {
+ console.log(`[Register] ${ip} blocked from registration: AbuseIPDB score ${entry.abuseConfidenceScore} >= ${register.blockAbuseIpDbAboveScore} (BLACKLIST)`);
+ throw new HTTPError("Your IP is blocked from registration");
+ }
+ }
- const checkIp = await AbuseIpDbClient.checkIpAddress(ip);
- if (checkIp?.data && checkIp.data.abuseConfidenceScore >= register.blockAbuseIpDbAboveScore) {
- console.log(`[Register] ${ip} blocked from registration: AbuseIPDB score ${checkIp.data.abuseConfidenceScore} >= ${register.blockAbuseIpDbAboveScore} (CHECK)`);
- throw new HTTPError("Your IP is blocked from registration");
- }
+ const checkIp = await AbuseIpDbClient.checkIpAddress(ip);
+ if (checkIp?.data && checkIp.data.abuseConfidenceScore >= register.blockAbuseIpDbAboveScore) {
+ console.log(`[Register] ${ip} blocked from registration: AbuseIPDB score ${checkIp.data.abuseConfidenceScore} >= ${register.blockAbuseIpDbAboveScore} (CHECK)`);
+ throw new HTTPError("Your IP is blocked from registration");
+ }
- const ipData = await IpDataClient.getIpInfo(ip);
- if (ipData) {
- if (!ipData.threat) {
- console.log("Invalid IPData.co response, missing threat field", ipData);
- }
- const categories = Object.entries(ipData.threat)
- .filter(([key, value]) => key.startsWith("is_") && value === true)
- .map(([key]) => key.replace("is_", ""));
- const blockedCategories = new Set(categories).intersection(new Set(register.blockIpDataCoThreatTypes));
- if (blockedCategories.size > 0) {
- console.log(`[Register] ${ip} blocked from registration: IPData.co threat types ${Array.from(blockedCategories).join(", ")}`);
- throw new HTTPError("Your IP is blocked from registration");
- }
+ const ipData = await IpDataClient.getIpInfo(ip);
+ if (ipData) {
+ if (!ipData.threat) {
+ console.log("Invalid IPData.co response, missing threat field", ipData);
+ }
+ const categories = Object.entries(ipData.threat)
+ .filter(([key, value]) => key.startsWith("is_") && value === true)
+ .map(([key]) => key.replace("is_", ""));
+ const blockedCategories = new Set(categories).intersection(new Set(register.blockIpDataCoThreatTypes));
+ if (blockedCategories.size > 0) {
+ console.log(`[Register] ${ip} blocked from registration: IPData.co threat types ${Array.from(blockedCategories).join(", ")}`);
+ throw new HTTPError("Your IP is blocked from registration");
+ }
- if (register.blockAsnTypes.includes(ipData.asn.type)) {
- console.log(`[Register] ${ip} blocked from registration: IPData.co ASN type ${ipData.asn.type} is blocked`);
- throw new HTTPError("Your IP is blocked from registration");
- }
+ if (register.blockAsnTypes.includes(ipData.asn.type)) {
+ console.log(`[Register] ${ip} blocked from registration: IPData.co ASN type ${ipData.asn.type} is blocked`);
+ throw new HTTPError("Your IP is blocked from registration");
+ }
- if (register.blockAsns.includes(ipData.asn.asn)) {
- console.log(`[Register] ${ip} blocked from registration: IPData.co ASN ${ipData.asn.name} is blocked`);
- throw new HTTPError("Your IP is blocked from registration");
- }
+ if (register.blockAsns.includes(ipData.asn.asn)) {
+ console.log(`[Register] ${ip} blocked from registration: IPData.co ASN ${ipData.asn.name} is blocked`);
+ throw new HTTPError("Your IP is blocked from registration");
+ }
- if (register.blockProxies && IpDataClient.isProxy(ipData)) {
- console.log(`[Register] ${ip} blocked from registration: IPData.co response matched IpDataClient.isProxy() check`);
- throw new HTTPError("Your IP is blocked from registration");
- }
- }
- }
+ if (register.blockProxies && IpDataClient.isProxy(ipData)) {
+ console.log(`[Register] ${ip} blocked from registration: IPData.co response matched IpDataClient.isProxy() check`);
+ throw new HTTPError("Your IP is blocked from registration");
+ }
+ }
+ }
- // TODO: gift_code_sku_id?
- // TODO: check password strength
+ // TODO: gift_code_sku_id?
+ // TODO: check password strength
- const email = body.email;
- if (email) {
- // replace all dots and chars after +, if its a gmail.com email
- if (!email) {
- throw FieldErrors({
- email: {
- code: "INVALID_EMAIL",
- message: req?.t("auth:register.INVALID_EMAIL"),
- },
- });
- }
+ const email = body.email;
+ if (email) {
+ // replace all dots and chars after +, if its a gmail.com email
+ if (!email) {
+ throw FieldErrors({
+ email: {
+ code: "INVALID_EMAIL",
+ message: req?.t("auth:register.INVALID_EMAIL"),
+ },
+ });
+ }
- // check if there is already an account with this email
- const exists = await User.findOne({ where: { email: email } });
+ // check if there is already an account with this email
+ const exists = await User.findOne({ where: { email: email } });
- if (exists) {
- throw FieldErrors({
- email: {
- code: "EMAIL_ALREADY_REGISTERED",
- message: req.t("auth:register.EMAIL_ALREADY_REGISTERED"),
- },
- });
- }
- } else if (register.email.required) {
- throw FieldErrors({
- email: {
- code: "BASE_TYPE_REQUIRED",
- message: req.t("common:field.BASE_TYPE_REQUIRED"),
- },
- });
- }
+ if (exists) {
+ throw FieldErrors({
+ email: {
+ code: "EMAIL_ALREADY_REGISTERED",
+ message: req.t("auth:register.EMAIL_ALREADY_REGISTERED"),
+ },
+ });
+ }
+ } else if (register.email.required) {
+ throw FieldErrors({
+ email: {
+ code: "BASE_TYPE_REQUIRED",
+ message: req.t("common:field.BASE_TYPE_REQUIRED"),
+ },
+ });
+ }
- if (register.dateOfBirth.required && !body.date_of_birth) {
- throw FieldErrors({
- date_of_birth: {
- code: "BASE_TYPE_REQUIRED",
- message: req.t("common:field.BASE_TYPE_REQUIRED"),
- },
- });
- } else if (register.dateOfBirth.required && register.dateOfBirth.minimum) {
- const minimum = new Date();
- minimum.setFullYear(minimum.getFullYear() - register.dateOfBirth.minimum);
+ if (register.dateOfBirth.required && !body.date_of_birth) {
+ throw FieldErrors({
+ date_of_birth: {
+ code: "BASE_TYPE_REQUIRED",
+ message: req.t("common:field.BASE_TYPE_REQUIRED"),
+ },
+ });
+ } else if (register.dateOfBirth.required && register.dateOfBirth.minimum) {
+ const minimum = new Date();
+ minimum.setFullYear(minimum.getFullYear() - register.dateOfBirth.minimum);
- let parsedDob;
- try {
- parsedDob = new Date(body.date_of_birth as Date);
- if (isNaN(parsedDob.getTime())) {
- throw new Error("Invalid date");
- }
- } catch (e) {
- throw FieldErrors({
- date_of_birth: {
- code: "DATE_OF_BIRTH_INVALID",
- message: req.t("auth:register.DATE_OF_BIRTH_INVALID"),
- },
- });
- }
+ let parsedDob;
+ try {
+ parsedDob = new Date(body.date_of_birth as Date);
+ if (isNaN(parsedDob.getTime())) {
+ throw new Error("Invalid date");
+ }
+ } catch (e) {
+ throw FieldErrors({
+ date_of_birth: {
+ code: "DATE_OF_BIRTH_INVALID",
+ message: req.t("auth:register.DATE_OF_BIRTH_INVALID"),
+ },
+ });
+ }
- // higher is younger
- if (parsedDob > minimum) {
- throw FieldErrors({
- date_of_birth: {
- code: "DATE_OF_BIRTH_UNDERAGE",
- message: req.t("auth:register.DATE_OF_BIRTH_UNDERAGE", {
- years: register.dateOfBirth.minimum,
- }),
- },
- });
- }
- }
+ // higher is younger
+ if (parsedDob > minimum) {
+ throw FieldErrors({
+ date_of_birth: {
+ code: "DATE_OF_BIRTH_UNDERAGE",
+ message: req.t("auth:register.DATE_OF_BIRTH_UNDERAGE", {
+ years: register.dateOfBirth.minimum,
+ }),
+ },
+ });
+ }
+ }
- if (body.password) {
- const min = register.password.minLength ?? 8;
+ if (body.password) {
+ const min = register.password.minLength ?? 8;
- if (body.password.length < min) {
- throw FieldErrors({
- password: {
- code: "PASSWORD_REQUIREMENTS_MIN_LENGTH",
- message: req.t("auth:register.PASSWORD_REQUIREMENTS_MIN_LENGTH", { min: min }),
- },
- });
- }
- // the salt is saved in the password refer to bcrypt docs
- body.password = await bcrypt.hash(body.password, 12);
- } else if (register.password.required) {
- throw FieldErrors({
- password: {
- code: "BASE_TYPE_REQUIRED",
- message: req.t("common:field.BASE_TYPE_REQUIRED"),
- },
- });
- }
+ if (body.password.length < min) {
+ throw FieldErrors({
+ password: {
+ code: "PASSWORD_REQUIREMENTS_MIN_LENGTH",
+ message: req.t("auth:register.PASSWORD_REQUIREMENTS_MIN_LENGTH", { min: min }),
+ },
+ });
+ }
+ // the salt is saved in the password refer to bcrypt docs
+ body.password = await bcrypt.hash(body.password, 12);
+ } else if (register.password.required) {
+ throw FieldErrors({
+ password: {
+ code: "BASE_TYPE_REQUIRED",
+ message: req.t("common:field.BASE_TYPE_REQUIRED"),
+ },
+ });
+ }
- if (!regTokenUsed && !body.invite && (register.requireInvite || (register.guestsRequireInvite && !register.email))) {
- // require invite to register -> e.g. for organizations to send invites to their employees
- throw FieldErrors({
- email: {
- code: "INVITE_ONLY",
- message: req.t("auth:register.INVITE_ONLY"),
- },
- });
- }
+ if (!regTokenUsed && !body.invite && (register.requireInvite || (register.guestsRequireInvite && !register.email))) {
+ // require invite to register -> e.g. for organizations to send invites to their employees
+ throw FieldErrors({
+ email: {
+ code: "INVITE_ONLY",
+ message: req.t("auth:register.INVITE_ONLY"),
+ },
+ });
+ }
- if (
- !regTokenUsed &&
- limits.absoluteRate.register.enabled &&
- (await User.count({
- where: {
- created_at: MoreThan(new Date(Date.now() - limits.absoluteRate.register.window)),
- },
- })) >= limits.absoluteRate.register.limit
- ) {
- console.log(`Global register ratelimit exceeded for ${req.ip}, ${req.body.username}, ${req.body.invite || "No invite given"}`);
- throw FieldErrors({
- email: {
- code: "TOO_MANY_REGISTRATIONS",
- message: req.t("auth:register.TOO_MANY_REGISTRATIONS"),
- },
- });
- }
+ if (
+ !regTokenUsed &&
+ limits.absoluteRate.register.enabled &&
+ (await User.count({
+ where: {
+ created_at: MoreThan(new Date(Date.now() - limits.absoluteRate.register.window)),
+ },
+ })) >= limits.absoluteRate.register.limit
+ ) {
+ console.log(`Global register ratelimit exceeded for ${req.ip}, ${req.body.username}, ${req.body.invite || "No invite given"}`);
+ throw FieldErrors({
+ email: {
+ code: "TOO_MANY_REGISTRATIONS",
+ message: req.t("auth:register.TOO_MANY_REGISTRATIONS"),
+ },
+ });
+ }
- const { maxUsername } = Config.get().limits.user;
- if (body.username.length > maxUsername) {
- throw FieldErrors({
- username: {
- code: "BASE_TYPE_BAD_LENGTH",
- message: `Must be between 2 and ${maxUsername} in length.`,
- },
- });
- }
+ const { maxUsername } = Config.get().limits.user;
+ if (body.username.length > maxUsername) {
+ throw FieldErrors({
+ username: {
+ code: "BASE_TYPE_BAD_LENGTH",
+ message: `Must be between 2 and ${maxUsername} in length.`,
+ },
+ });
+ }
- const user = await User.register({ ...body, req });
+ const user = await User.register({ ...body, req });
- if (body.invite) {
- // await to fail if the invite doesn't exist (necessary for requireInvite to work properly) (username only signups are possible)
- await Invite.joinGuild(user.id, body.invite);
- }
+ if (body.invite) {
+ // await to fail if the invite doesn't exist (necessary for requireInvite to work properly) (username only signups are possible)
+ await Invite.joinGuild(user.id, body.invite);
+ }
- return res.json({ token: await generateToken(user.id) });
- },
+ return res.json({ token: await generateToken(user.id) });
+ },
);
export default router;
diff --git a/src/api/routes/auth/reset.ts b/src/api/routes/auth/reset.ts
index 69f97d2..77e93e8 100644
--- a/src/api/routes/auth/reset.ts
+++ b/src/api/routes/auth/reset.ts
@@ -26,54 +26,54 @@
// TODO: the response interface also returns settings, but this route doesn't actually return that.
router.post(
- "/",
- route({
- requestBody: "PasswordResetSchema",
- responses: {
- 200: {
- body: "TokenOnlyResponse",
- },
- 400: {
- body: "APIErrorOrCaptchaResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { password, token } = req.body as PasswordResetSchema;
+ "/",
+ route({
+ requestBody: "PasswordResetSchema",
+ responses: {
+ 200: {
+ body: "TokenOnlyResponse",
+ },
+ 400: {
+ body: "APIErrorOrCaptchaResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { password, token } = req.body as PasswordResetSchema;
- let user;
- try {
- const userTokenData = await checkToken(token, {
- select: ["email"],
- fingerprint: req.fingerprint,
- ipAddress: req.ip,
- });
- user = userTokenData.user;
- } catch {
- throw FieldErrors({
- password: {
- message: req.t("auth:password_reset.INVALID_TOKEN"),
- code: "INVALID_TOKEN",
- },
- });
- }
+ let user;
+ try {
+ const userTokenData = await checkToken(token, {
+ select: ["email"],
+ fingerprint: req.fingerprint,
+ ipAddress: req.ip,
+ });
+ user = userTokenData.user;
+ } catch {
+ throw FieldErrors({
+ password: {
+ message: req.t("auth:password_reset.INVALID_TOKEN"),
+ code: "INVALID_TOKEN",
+ },
+ });
+ }
- // the salt is saved in the password refer to bcrypt docs
- const hash = await bcrypt.hash(password, 12);
+ // the salt is saved in the password refer to bcrypt docs
+ const hash = await bcrypt.hash(password, 12);
- const data = {
- data: {
- hash,
- valid_tokens_since: new Date(),
- },
- };
- await User.update({ id: user.id }, data);
+ const data = {
+ data: {
+ hash,
+ valid_tokens_since: new Date(),
+ },
+ };
+ await User.update({ id: user.id }, data);
- // come on, the user has to have an email to reset their password in the first place
- await Email.sendPasswordChanged(user, user.email!);
+ // come on, the user has to have an email to reset their password in the first place
+ await Email.sendPasswordChanged(user, user.email!);
- res.json({ token: await generateToken(user.id) });
- },
+ res.json({ token: await generateToken(user.id) });
+ },
);
export default router;
diff --git a/src/api/routes/auth/sessions.ts b/src/api/routes/auth/sessions.ts
index 6c721f2..3a9095f 100644
--- a/src/api/routes/auth/sessions.ts
+++ b/src/api/routes/auth/sessions.ts
@@ -23,54 +23,54 @@
import { In } from "typeorm";
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "GetSessionsResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { extended = false } = req.query;
- const sessions = (await Session.find({ where: { user_id: req.user_id, is_admin_session: false } })) as Session[];
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "GetSessionsResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { extended = false } = req.query;
+ const sessions = (await Session.find({ where: { user_id: req.user_id, is_admin_session: false } })) as Session[];
- res.json({
- user_sessions: sessions.map((session) => (extended ? session.getExtendedDeviceInfo() : session.getDiscordDeviceInfo())),
- });
- },
+ res.json({
+ user_sessions: sessions.map((session) => (extended ? session.getExtendedDeviceInfo() : session.getDiscordDeviceInfo())),
+ });
+ },
);
router.post(
- "/logout",
- route({
- requestBody: "SessionsLogoutSchema",
- responses: {
- 204: {},
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as SessionsLogoutSchema;
+ "/logout",
+ route({
+ requestBody: "SessionsLogoutSchema",
+ responses: {
+ 204: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as SessionsLogoutSchema;
- let sessions: Session[] = [];
- if ("session_ids" in body) {
- sessions = (await Session.find({ where: { user_id: req.user_id, session_id: In(body.session_ids!) } })) as Session[];
- }
+ let sessions: Session[] = [];
+ if ("session_ids" in body) {
+ sessions = (await Session.find({ where: { user_id: req.user_id, session_id: In(body.session_ids!) } })) as Session[];
+ }
- if ("session_id_hashes" in body) {
- const allSessions = (await Session.find({ where: { user_id: req.user_id } })) as Session[];
- const hashSet = new Set(body.session_id_hashes);
- const matchingSessions = allSessions.filter((session) => {
- const hash = createHash("sha256").update(session.session_id).digest("hex");
- return hashSet.has(hash);
- });
- sessions.push(...matchingSessions);
- }
+ if ("session_id_hashes" in body) {
+ const allSessions = (await Session.find({ where: { user_id: req.user_id } })) as Session[];
+ const hashSet = new Set(body.session_id_hashes);
+ const matchingSessions = allSessions.filter((session) => {
+ const hash = createHash("sha256").update(session.session_id).digest("hex");
+ return hashSet.has(hash);
+ });
+ sessions.push(...matchingSessions);
+ }
- for (const session of sessions) {
- await session.remove();
- }
- res.status(204).send();
- },
+ for (const session of sessions) {
+ await session.remove();
+ }
+ res.status(204).send();
+ },
);
export default router;
diff --git a/src/api/routes/auth/verify/index.ts b/src/api/routes/auth/verify/index.ts
index 43fb23a..7c8ca18 100644
--- a/src/api/routes/auth/verify/index.ts
+++ b/src/api/routes/auth/verify/index.ts
@@ -22,79 +22,79 @@
const router = Router({ mergeParams: true });
async function getToken(user: User) {
- const token = await generateToken(user.id);
+ const token = await generateToken(user.id);
- // Notice this will have a different token structure, than discord
- // Discord header is just the user id as string, which is not possible with npm-jsonwebtoken package
- // https://user-images.githubusercontent.com/6506416/81051916-dd8c9900-8ec2-11ea-8794-daf12d6f31f0.png
+ // Notice this will have a different token structure, than discord
+ // Discord header is just the user id as string, which is not possible with npm-jsonwebtoken package
+ // https://user-images.githubusercontent.com/6506416/81051916-dd8c9900-8ec2-11ea-8794-daf12d6f31f0.png
- return { token };
+ return { token };
}
// TODO: the response interface also returns settings, but this route doesn't actually return that.
router.post(
- "/",
- route({
- requestBody: "VerifyEmailSchema",
- responses: {
- 200: {
- body: "TokenResponse",
- },
- 400: {
- body: "APIErrorOrCaptchaResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { captcha_key, token } = req.body;
+ "/",
+ route({
+ requestBody: "VerifyEmailSchema",
+ responses: {
+ 200: {
+ body: "TokenResponse",
+ },
+ 400: {
+ body: "APIErrorOrCaptchaResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { captcha_key, token } = req.body;
- const config = Config.get();
+ const config = Config.get();
- if (config.register.requireCaptcha && config.security.captcha.enabled) {
- const { sitekey, service } = config.security.captcha;
+ if (config.register.requireCaptcha && config.security.captcha.enabled) {
+ const { sitekey, service } = config.security.captcha;
- if (!captcha_key) {
- return res.status(400).json({
- captcha_key: ["captcha-required"],
- captcha_sitekey: sitekey,
- captcha_service: service,
- });
- }
+ if (!captcha_key) {
+ return res.status(400).json({
+ captcha_key: ["captcha-required"],
+ captcha_sitekey: sitekey,
+ captcha_service: service,
+ });
+ }
- const ip = req.ip;
- const verify = await verifyCaptcha(captcha_key, ip);
- if (!verify.success) {
- return res.status(400).json({
- captcha_key: verify["error-codes"],
- captcha_sitekey: sitekey,
- captcha_service: service,
- });
- }
- }
+ const ip = req.ip;
+ const verify = await verifyCaptcha(captcha_key, ip);
+ if (!verify.success) {
+ return res.status(400).json({
+ captcha_key: verify["error-codes"],
+ captcha_sitekey: sitekey,
+ captcha_service: service,
+ });
+ }
+ }
- let user;
+ let user;
- try {
- const userTokenData = await checkToken(token, {
- fingerprint: req.fingerprint,
- ipAddress: req.ip,
- });
- user = userTokenData.user;
- } catch {
- throw FieldErrors({
- token: {
- message: req.t("auth:password_reset.INVALID_TOKEN"),
- code: "INVALID_TOKEN",
- },
- });
- }
+ try {
+ const userTokenData = await checkToken(token, {
+ fingerprint: req.fingerprint,
+ ipAddress: req.ip,
+ });
+ user = userTokenData.user;
+ } catch {
+ throw FieldErrors({
+ token: {
+ message: req.t("auth:password_reset.INVALID_TOKEN"),
+ code: "INVALID_TOKEN",
+ },
+ });
+ }
- if (user.verified) return res.json(await getToken(user));
+ if (user.verified) return res.json(await getToken(user));
- await User.update({ id: user.id }, { verified: true });
+ await User.update({ id: user.id }, { verified: true });
- return res.json(await getToken(user));
- },
+ return res.json(await getToken(user));
+ },
);
export default router;
diff --git a/src/api/routes/auth/verify/resend.ts b/src/api/routes/auth/verify/resend.ts
index 4ef1d51..ce6672a 100644
--- a/src/api/routes/auth/verify/resend.ts
+++ b/src/api/routes/auth/verify/resend.ts
@@ -23,43 +23,43 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- right: "RESEND_VERIFICATION_EMAIL",
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 500: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- select: ["username", "email", "verified"],
- });
+ "/",
+ route({
+ right: "RESEND_VERIFICATION_EMAIL",
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 500: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ select: ["username", "email", "verified"],
+ });
- if (!user.email) {
- // TODO: whats the proper error response for this?
- throw new HTTPError("User does not have an email address", 400);
- }
+ if (!user.email) {
+ // TODO: whats the proper error response for this?
+ throw new HTTPError("User does not have an email address", 400);
+ }
- if (user.verified) {
- throw new HTTPError("Email is already verified", 400);
- }
+ if (user.verified) {
+ throw new HTTPError("Email is already verified", 400);
+ }
- await Email.sendVerifyEmail(user, user.email)
- .then(() => {
- return res.sendStatus(204);
- })
- .catch((e) => {
- console.error(`Failed to send verification email to ${user.username}#${user.discriminator}: ${e}`);
- throw new HTTPError("Failed to send verification email", 500);
- });
- },
+ await Email.sendVerifyEmail(user, user.email)
+ .then(() => {
+ return res.sendStatus(204);
+ })
+ .catch((e) => {
+ console.error(`Failed to send verification email to ${user.username}#${user.discriminator}: ${e}`);
+ throw new HTTPError("Failed to send verification email", 500);
+ });
+ },
);
export default router;
diff --git a/src/api/routes/auth/verify/view-backup-codes-challenge.ts b/src/api/routes/auth/verify/view-backup-codes-challenge.ts
index 7c15795..d3d40d3 100644
--- a/src/api/routes/auth/verify/view-backup-codes-challenge.ts
+++ b/src/api/routes/auth/verify/view-backup-codes-challenge.ts
@@ -24,36 +24,36 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "BackupCodesChallengeSchema",
- responses: {
- 200: { body: "BackupCodesChallengeResponse" },
- 400: { body: "APIErrorResponse" },
- },
- }),
- async (req: Request, res: Response) => {
- const { password } = req.body as BackupCodesChallengeSchema;
+ "/",
+ route({
+ requestBody: "BackupCodesChallengeSchema",
+ responses: {
+ 200: { body: "BackupCodesChallengeResponse" },
+ 400: { body: "APIErrorResponse" },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { password } = req.body as BackupCodesChallengeSchema;
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- select: ["data"],
- });
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ select: ["data"],
+ });
- if (!(await bcrypt.compare(password, user.data.hash || ""))) {
- throw FieldErrors({
- password: {
- message: req.t("auth:login.INVALID_PASSWORD"),
- code: "INVALID_PASSWORD",
- },
- });
- }
+ if (!(await bcrypt.compare(password, user.data.hash || ""))) {
+ throw FieldErrors({
+ password: {
+ message: req.t("auth:login.INVALID_PASSWORD"),
+ code: "INVALID_PASSWORD",
+ },
+ });
+ }
- return res.json({
- nonce: "NoncePlaceholder",
- regenerate_nonce: "RegenNoncePlaceholder",
- });
- },
+ return res.json({
+ nonce: "NoncePlaceholder",
+ regenerate_nonce: "RegenNoncePlaceholder",
+ });
+ },
);
export default router;
diff --git a/src/api/routes/beaker.ts b/src/api/routes/beaker.ts
index 62df41e..4eb2941 100644
--- a/src/api/routes/beaker.ts
+++ b/src/api/routes/beaker.ts
@@ -23,16 +23,16 @@
// screw off, telemetry requests
router.post(
- "/",
- route({
- responses: {
- 204: {},
- },
- }),
- (req: Request, res: Response) => {
- // TODO:
- res.sendStatus(204);
- },
+ "/",
+ route({
+ responses: {
+ 204: {},
+ },
+ }),
+ (req: Request, res: Response) => {
+ // TODO:
+ res.sendStatus(204);
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/attachments.ts" "b/src/api/routes/channels/\043channel_id/attachments.ts"
index 039bfa2..30fd2c6 100644
--- "a/src/api/routes/channels/\043channel_id/attachments.ts"
+++ "b/src/api/routes/channels/\043channel_id/attachments.ts"
@@ -25,109 +25,109 @@
const router: Router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "UploadAttachmentRequestSchema",
- responses: {
- 200: {
- body: "UploadAttachmentResponseSchema",
- },
- 404: {},
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const payload = req.body as UploadAttachmentRequestSchema;
- const { channel_id } = req.params;
+ "/",
+ route({
+ requestBody: "UploadAttachmentRequestSchema",
+ responses: {
+ 200: {
+ body: "UploadAttachmentResponseSchema",
+ },
+ 404: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const payload = req.body as UploadAttachmentRequestSchema;
+ const { channel_id } = req.params;
- const user = await User.findOneOrFail({ where: { id: req.user_id } });
- const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
+ const user = await User.findOneOrFail({ where: { id: req.user_id } });
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
- if (!(await channel.getUserPermissions({ user_id: req.user_id })).has(Permissions.FLAGS.ATTACH_FILES)) {
- return res.status(403).json({
- code: 403,
- message: "Missing Permissions: ATTACH_FILES",
- });
- }
+ if (!(await channel.getUserPermissions({ user_id: req.user_id })).has(Permissions.FLAGS.ATTACH_FILES)) {
+ return res.status(403).json({
+ code: 403,
+ message: "Missing Permissions: ATTACH_FILES",
+ });
+ }
- const cdnUrl = Config.get().cdn.endpointPublic;
- const batchId = `CLOUD_${user.id}_${randomString(128)}`;
+ const cdnUrl = Config.get().cdn.endpointPublic;
+ const batchId = `CLOUD_${user.id}_${randomString(128)}`;
- // validate IDs
- const seenIds: (string | undefined)[] = [];
- for (const file of payload.files) {
- if (seenIds.includes(file.id)) {
- return res.status(400).json({
- code: 400,
- message: `Duplicate attachment ID: ${file.id}`,
- });
- }
- seenIds.push(file.id);
- }
+ // validate IDs
+ const seenIds: (string | undefined)[] = [];
+ for (const file of payload.files) {
+ if (seenIds.includes(file.id)) {
+ return res.status(400).json({
+ code: 400,
+ message: `Duplicate attachment ID: ${file.id}`,
+ });
+ }
+ seenIds.push(file.id);
+ }
- const attachments = await Promise.all(
- payload.files.map(async (attachment) => {
- attachment.filename = attachment.filename.replaceAll(" ", "_").replace(/[^a-zA-Z0-9._]+/g, "");
- const uploadFilename = `${channel_id}/${batchId}/${attachment.id ?? "0"}/${attachment.filename}`;
- const newAttachment = CloudAttachment.create({
- user: user,
- channel: channel,
- uploadFilename: uploadFilename,
- userAttachmentId: attachment.id ?? "0",
- userFilename: attachment.filename,
- userFileSize: attachment.file_size,
- userIsClip: attachment.is_clip,
- userOriginalContentType: attachment.original_content_type,
- });
- await newAttachment.save();
- return newAttachment;
- }),
- );
+ const attachments = await Promise.all(
+ payload.files.map(async (attachment) => {
+ attachment.filename = attachment.filename.replaceAll(" ", "_").replace(/[^a-zA-Z0-9._]+/g, "");
+ const uploadFilename = `${channel_id}/${batchId}/${attachment.id ?? "0"}/${attachment.filename}`;
+ const newAttachment = CloudAttachment.create({
+ user: user,
+ channel: channel,
+ uploadFilename: uploadFilename,
+ userAttachmentId: attachment.id ?? "0",
+ userFilename: attachment.filename,
+ userFileSize: attachment.file_size,
+ userIsClip: attachment.is_clip,
+ userOriginalContentType: attachment.original_content_type,
+ });
+ await newAttachment.save();
+ return newAttachment;
+ }),
+ );
- res.send({
- attachments: attachments.map((a) => {
- return {
- id: a.userAttachmentId,
- upload_filename: a.uploadFilename,
- upload_url: `${cdnUrl}/attachments/${a.uploadFilename}`,
- original_content_type: a.userOriginalContentType,
- };
- }),
- } as UploadAttachmentResponseSchema);
- },
+ res.send({
+ attachments: attachments.map((a) => {
+ return {
+ id: a.userAttachmentId,
+ upload_filename: a.uploadFilename,
+ upload_url: `${cdnUrl}/attachments/${a.uploadFilename}`,
+ original_content_type: a.userOriginalContentType,
+ };
+ }),
+ } as UploadAttachmentResponseSchema);
+ },
);
router.delete("/:cloud_attachment_url", async (req: Request, res: Response) => {
- const { channel_id, cloud_attachment_url } = req.params;
+ const { channel_id, cloud_attachment_url } = req.params;
- const user = await User.findOneOrFail({ where: { id: req.user_id } });
- const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
- const att = await CloudAttachment.findOneOrFail({ where: { uploadFilename: decodeURI(cloud_attachment_url) } });
- if (att.userId !== user.id) {
- return res.status(403).json({
- code: 403,
- message: "You do not own this attachment.",
- });
- }
+ const user = await User.findOneOrFail({ where: { id: req.user_id } });
+ const channel = await Channel.findOneOrFail({ where: { id: channel_id } });
+ const att = await CloudAttachment.findOneOrFail({ where: { uploadFilename: decodeURI(cloud_attachment_url) } });
+ if (att.userId !== user.id) {
+ return res.status(403).json({
+ code: 403,
+ message: "You do not own this attachment.",
+ });
+ }
- if (att.channelId !== channel.id) {
- return res.status(400).json({
- code: 400,
- message: "Attachment does not belong to this channel.",
- });
- }
+ if (att.channelId !== channel.id) {
+ return res.status(400).json({
+ code: 400,
+ message: "Attachment does not belong to this channel.",
+ });
+ }
- const response = await fetch(`${Config.get().cdn.endpointPrivate}/attachments/${att.uploadFilename}`, {
- headers: {
- signature: Config.get().security.requestSignature,
- },
- method: "DELETE",
- });
+ const response = await fetch(`${Config.get().cdn.endpointPrivate}/attachments/${att.uploadFilename}`, {
+ headers: {
+ signature: Config.get().security.requestSignature,
+ },
+ method: "DELETE",
+ });
- await att.remove();
- return res.status(response.status).send(response.body);
+ await att.remove();
+ return res.status(response.status).send(response.body);
});
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/directory-entries.ts" "b/src/api/routes/channels/\043channel_id/directory-entries.ts"
index c07b1f7..da95050 100644
--- "a/src/api/routes/channels/\043channel_id/directory-entries.ts"
+++ "b/src/api/routes/channels/\043channel_id/directory-entries.ts"
@@ -22,20 +22,20 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "HubDirectoryEntriesResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- res.json([] as HubDirectoryEntriesResponse);
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "HubDirectoryEntriesResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ res.json([] as HubDirectoryEntriesResponse);
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/greet.ts" "b/src/api/routes/channels/\043channel_id/greet.ts"
index b6ce1ee..f78f26a 100644
--- "a/src/api/routes/channels/\043channel_id/greet.ts"
+++ "b/src/api/routes/channels/\043channel_id/greet.ts"
@@ -25,83 +25,83 @@
const router: Router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "GreetRequestSchema",
- permission: "MANAGE_CHANNELS",
- responses: {
- 200: {
- body: "Message",
- },
- 404: {},
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const payload = req.body as GreetRequestSchema;
- const { channel_id } = req.params;
+ "/",
+ route({
+ requestBody: "GreetRequestSchema",
+ permission: "MANAGE_CHANNELS",
+ responses: {
+ 200: {
+ body: "Message",
+ },
+ 404: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const payload = req.body as GreetRequestSchema;
+ const { channel_id } = req.params;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
- const targetMessage = await Message.findOneOrFail({
- where: {
- id: payload.message_reference?.message_id,
- channel_id: payload.message_reference?.channel_id,
- guild_id: payload.message_reference?.guild_id,
- },
- });
+ const targetMessage = await Message.findOneOrFail({
+ where: {
+ id: payload.message_reference?.message_id,
+ channel_id: payload.message_reference?.channel_id,
+ guild_id: payload.message_reference?.guild_id,
+ },
+ });
- if (!channel.isDm() && targetMessage.type != MessageType.GUILD_MEMBER_JOIN)
- return res.status(400).json({
- code: 400, // TODO: what's the actual error code?
- message: "Cannot send greet message referencing this message.",
- });
+ if (!channel.isDm() && targetMessage.type != MessageType.GUILD_MEMBER_JOIN)
+ return res.status(400).json({
+ code: 400, // TODO: what's the actual error code?
+ message: "Cannot send greet message referencing this message.",
+ });
- if (!(await channel.getUserPermissions({ user_id: req.user_id })).has(Permissions.FLAGS.SEND_MESSAGES)) {
- return res.status(403).json({
- code: 403,
- message: "Missing Permissions: SEND_MESSAGES",
- });
- }
+ if (!(await channel.getUserPermissions({ user_id: req.user_id })).has(Permissions.FLAGS.SEND_MESSAGES)) {
+ return res.status(403).json({
+ code: 403,
+ message: "Missing Permissions: SEND_MESSAGES",
+ });
+ }
- const specCompliant = true; // incase we want to allow clients to add more than one sticker to pick
- if (specCompliant && payload.sticker_ids.length != 1)
- return res.status(400).json({
- code: 400,
- message: "Must include exactly one sticker.",
- });
+ const specCompliant = true; // incase we want to allow clients to add more than one sticker to pick
+ if (specCompliant && payload.sticker_ids.length != 1)
+ return res.status(400).json({
+ code: 400,
+ message: "Must include exactly one sticker.",
+ });
- const stickers = await Sticker.find({ where: { id: In(payload.sticker_ids) } });
+ const stickers = await Sticker.find({ where: { id: In(payload.sticker_ids) } });
- const randomSticker = stickers[Math.floor(Math.random() * stickers.length)];
+ const randomSticker = stickers[Math.floor(Math.random() * stickers.length)];
- const message = Message.create({
- channel_id: channel_id,
- author_id: req.user_id,
- type: MessageType.REPLY,
- message_reference: { ...payload.message_reference, type: 0 },
- referenced_message: targetMessage,
- sticker_items: randomSticker ? [{ id: randomSticker.id, name: randomSticker.name, format_type: randomSticker.format_type }] : [],
- });
+ const message = Message.create({
+ channel_id: channel_id,
+ author_id: req.user_id,
+ type: MessageType.REPLY,
+ message_reference: { ...payload.message_reference, type: 0 },
+ referenced_message: targetMessage,
+ sticker_items: randomSticker ? [{ id: randomSticker.id, name: randomSticker.name, format_type: randomSticker.format_type }] : [],
+ });
- channel.last_message_id = message.id;
+ channel.last_message_id = message.id;
- await Promise.all([
- message.save(),
- emitEvent({
- event: "MESSAGE_CREATE",
- data: message,
- channel_id,
- } as MessageCreateEvent),
- channel.save(),
- ]);
+ await Promise.all([
+ message.save(),
+ emitEvent({
+ event: "MESSAGE_CREATE",
+ data: message,
+ channel_id,
+ } as MessageCreateEvent),
+ channel.save(),
+ ]);
- res.send(channel);
- },
+ res.send(channel);
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/index.ts" "b/src/api/routes/channels/\043channel_id/index.ts"
index 97857da..37909a9 100644
--- "a/src/api/routes/channels/\043channel_id/index.ts"
+++ "b/src/api/routes/channels/\043channel_id/index.ts"
@@ -26,132 +26,132 @@
// TODO: Get channel
router.get(
- "/",
- route({
- permission: "VIEW_CHANNEL",
- responses: {
- 200: {
- body: "Channel",
- },
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id } = req.params;
+ "/",
+ route({
+ permission: "VIEW_CHANNEL",
+ responses: {
+ 200: {
+ body: "Channel",
+ },
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id } = req.params;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
- if (!channel.guild_id) return res.send(channel);
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
+ if (!channel.guild_id) return res.send(channel);
- channel.position = await Channel.calculatePosition(channel_id, channel.guild_id, channel.guild);
- return res.send(channel);
- },
+ channel.position = await Channel.calculatePosition(channel_id, channel.guild_id, channel.guild);
+ return res.send(channel);
+ },
);
router.delete(
- "/",
- route({
- permission: "MANAGE_CHANNELS",
- responses: {
- 200: {
- body: "Channel",
- },
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id } = req.params;
+ "/",
+ route({
+ permission: "MANAGE_CHANNELS",
+ responses: {
+ 200: {
+ body: "Channel",
+ },
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id } = req.params;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- relations: ["recipients"],
- });
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ relations: ["recipients"],
+ });
- if (channel.type === ChannelType.DM) {
- const recipient = await Recipient.findOneOrFail({
- where: { channel_id: channel_id, user_id: req.user_id },
- });
- recipient.closed = true;
- await Promise.all([
- recipient.save(),
- emitEvent({
- event: "CHANNEL_DELETE",
- data: channel,
- user_id: req.user_id,
- } as ChannelDeleteEvent),
- ]);
- } else if (channel.type === ChannelType.GROUP_DM) {
- await Channel.removeRecipientFromChannel(channel, req.user_id);
- } else {
- if (channel.type == ChannelType.GUILD_CATEGORY) {
- const channels = await Channel.find({
- where: { parent_id: channel_id },
- });
- for await (const c of channels) {
- c.parent_id = null;
+ if (channel.type === ChannelType.DM) {
+ const recipient = await Recipient.findOneOrFail({
+ where: { channel_id: channel_id, user_id: req.user_id },
+ });
+ recipient.closed = true;
+ await Promise.all([
+ recipient.save(),
+ emitEvent({
+ event: "CHANNEL_DELETE",
+ data: channel,
+ user_id: req.user_id,
+ } as ChannelDeleteEvent),
+ ]);
+ } else if (channel.type === ChannelType.GROUP_DM) {
+ await Channel.removeRecipientFromChannel(channel, req.user_id);
+ } else {
+ if (channel.type == ChannelType.GUILD_CATEGORY) {
+ const channels = await Channel.find({
+ where: { parent_id: channel_id },
+ });
+ for await (const c of channels) {
+ c.parent_id = null;
- await Promise.all([
- c.save(),
- emitEvent({
- event: "CHANNEL_UPDATE",
- data: c,
- channel_id: c.id,
- } as ChannelUpdateEvent),
- ]);
- }
- }
+ await Promise.all([
+ c.save(),
+ emitEvent({
+ event: "CHANNEL_UPDATE",
+ data: c,
+ channel_id: c.id,
+ } as ChannelUpdateEvent),
+ ]);
+ }
+ }
- await Promise.all([
- Channel.deleteChannel(channel),
- emitEvent({
- event: "CHANNEL_DELETE",
- data: channel,
- channel_id,
- } as ChannelDeleteEvent),
- ]);
- }
+ await Promise.all([
+ Channel.deleteChannel(channel),
+ emitEvent({
+ event: "CHANNEL_DELETE",
+ data: channel,
+ channel_id,
+ } as ChannelDeleteEvent),
+ ]);
+ }
- res.send(channel);
- },
+ res.send(channel);
+ },
);
router.patch(
- "/",
- route({
- requestBody: "ChannelModifySchema",
- permission: "MANAGE_CHANNELS",
- responses: {
- 200: {
- body: "Channel",
- },
- 404: {},
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const payload = req.body as ChannelModifySchema;
- const { channel_id } = req.params;
- if (payload.icon) payload.icon = await handleFile(`/channel-icons/${channel_id}`, payload.icon);
+ "/",
+ route({
+ requestBody: "ChannelModifySchema",
+ permission: "MANAGE_CHANNELS",
+ responses: {
+ 200: {
+ body: "Channel",
+ },
+ 404: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const payload = req.body as ChannelModifySchema;
+ const { channel_id } = req.params;
+ if (payload.icon) payload.icon = await handleFile(`/channel-icons/${channel_id}`, payload.icon);
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
- channel.assign(payload);
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
+ channel.assign(payload);
- await Promise.all([
- channel.save(),
- emitEvent({
- event: "CHANNEL_UPDATE",
- data: channel,
- channel_id,
- } as ChannelUpdateEvent),
- ]);
+ await Promise.all([
+ channel.save(),
+ emitEvent({
+ event: "CHANNEL_UPDATE",
+ data: channel,
+ channel_id,
+ } as ChannelUpdateEvent),
+ ]);
- res.send(channel);
- },
+ res.send(channel);
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/invites.ts" "b/src/api/routes/channels/\043channel_id/invites.ts"
index 298f42e..808f0f8 100644
--- "a/src/api/routes/channels/\043channel_id/invites.ts"
+++ "b/src/api/routes/channels/\043channel_id/invites.ts"
@@ -25,96 +25,96 @@
const router: Router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "InviteCreateSchema",
- permission: "CREATE_INSTANT_INVITE",
- right: "CREATE_INVITES",
- responses: {
- 201: {
- body: "Invite",
- },
- 404: {},
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { user_id } = req;
- const body = req.body as InviteCreateSchema;
- const { channel_id } = req.params;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- select: ["id", "name", "type", "guild_id"],
- });
- isTextChannel(channel.type);
+ "/",
+ route({
+ requestBody: "InviteCreateSchema",
+ permission: "CREATE_INSTANT_INVITE",
+ right: "CREATE_INVITES",
+ responses: {
+ 201: {
+ body: "Invite",
+ },
+ 404: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { user_id } = req;
+ const body = req.body as InviteCreateSchema;
+ const { channel_id } = req.params;
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ select: ["id", "name", "type", "guild_id"],
+ });
+ isTextChannel(channel.type);
- if (!channel.guild_id) {
- throw new HTTPError("This channel doesn't exist", 404);
- }
- const { guild_id } = channel;
+ if (!channel.guild_id) {
+ throw new HTTPError("This channel doesn't exist", 404);
+ }
+ const { guild_id } = channel;
- const expires_at = body.max_age == 0 || body.max_age == undefined ? undefined : new Date(body.max_age * 1000 + Date.now());
+ const expires_at = body.max_age == 0 || body.max_age == undefined ? undefined : new Date(body.max_age * 1000 + Date.now());
- const invite = await Invite.create({
- code: randomString(),
- temporary: body.temporary || true,
- uses: 0,
- max_uses: body.max_uses ? Math.max(0, body.max_uses) : 0,
- max_age: body.max_age ? Math.max(0, body.max_age) : 0,
- expires_at,
- created_at: new Date(),
- guild_id,
- channel_id: channel_id,
- inviter_id: user_id,
- flags: body.flags ?? 0,
- }).save();
+ const invite = await Invite.create({
+ code: randomString(),
+ temporary: body.temporary || true,
+ uses: 0,
+ max_uses: body.max_uses ? Math.max(0, body.max_uses) : 0,
+ max_age: body.max_age ? Math.max(0, body.max_age) : 0,
+ expires_at,
+ created_at: new Date(),
+ guild_id,
+ channel_id: channel_id,
+ inviter_id: user_id,
+ flags: body.flags ?? 0,
+ }).save();
- const data = invite.toJSON();
- data.inviter = (await User.getPublicUser(req.user_id)).toPublicUser();
- data.guild = await Guild.findOne({ where: { id: guild_id } });
- data.channel = channel;
+ const data = invite.toJSON();
+ data.inviter = (await User.getPublicUser(req.user_id)).toPublicUser();
+ data.guild = await Guild.findOne({ where: { id: guild_id } });
+ data.channel = channel;
- await emitEvent({
- event: "INVITE_CREATE",
- data,
- guild_id,
- } as InviteCreateEvent);
+ await emitEvent({
+ event: "INVITE_CREATE",
+ data,
+ guild_id,
+ } as InviteCreateEvent);
- res.status(201).send(data);
- },
+ res.status(201).send(data);
+ },
);
router.get(
- "/",
- route({
- permission: "MANAGE_CHANNELS",
- responses: {
- 200: {
- body: "APIInviteArray",
- },
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id } = req.params;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
+ "/",
+ route({
+ permission: "MANAGE_CHANNELS",
+ responses: {
+ 200: {
+ body: "APIInviteArray",
+ },
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id } = req.params;
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
- if (!channel.guild_id) {
- throw new HTTPError("This channel doesn't exist", 404);
- }
- const { guild_id } = channel;
+ if (!channel.guild_id) {
+ throw new HTTPError("This channel doesn't exist", 404);
+ }
+ const { guild_id } = channel;
- const invites = await Invite.find({
- where: { guild_id, channel_id },
- relations: PublicInviteRelation,
- });
+ const invites = await Invite.find({
+ where: { guild_id, channel_id },
+ relations: PublicInviteRelation,
+ });
- res.status(200).send(invites);
- },
+ res.status(200).send(invites);
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/messages/\043message_id/ack.ts" "b/src/api/routes/channels/\043channel_id/messages/\043message_id/ack.ts"
index c7c96fe..7b9f039 100644
--- "a/src/api/routes/channels/\043channel_id/messages/\043message_id/ack.ts"
+++ "b/src/api/routes/channels/\043channel_id/messages/\043message_id/ack.ts"
@@ -27,42 +27,42 @@
// TODO: advance-only notification cursor
router.post(
- "/",
- route({
- requestBody: "MessageAcknowledgeSchema",
- responses: {
- 200: {},
- 403: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id, message_id } = req.params;
+ "/",
+ route({
+ requestBody: "MessageAcknowledgeSchema",
+ responses: {
+ 200: {},
+ 403: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id, message_id } = req.params;
- const permission = await getPermission(req.user_id, undefined, channel_id);
- permission.hasThrow("VIEW_CHANNEL");
+ const permission = await getPermission(req.user_id, undefined, channel_id);
+ permission.hasThrow("VIEW_CHANNEL");
- let read_state = await ReadState.findOne({
- where: { user_id: req.user_id, channel_id },
- });
- if (!read_state) read_state = ReadState.create({ user_id: req.user_id, channel_id });
- read_state.last_message_id = message_id;
- //It's a little more complicated but this'll do :P
- read_state.mention_count = 0;
+ let read_state = await ReadState.findOne({
+ where: { user_id: req.user_id, channel_id },
+ });
+ if (!read_state) read_state = ReadState.create({ user_id: req.user_id, channel_id });
+ read_state.last_message_id = message_id;
+ //It's a little more complicated but this'll do :P
+ read_state.mention_count = 0;
- await read_state.save();
+ await read_state.save();
- await emitEvent({
- event: "MESSAGE_ACK",
- user_id: req.user_id,
- data: {
- channel_id,
- message_id,
- version: 3763,
- },
- } as MessageAckEvent);
+ await emitEvent({
+ event: "MESSAGE_ACK",
+ user_id: req.user_id,
+ data: {
+ channel_id,
+ message_id,
+ version: 3763,
+ },
+ } as MessageAckEvent);
- res.json({ token: null });
- },
+ res.json({ token: null });
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/messages/\043message_id/crosspost.ts" "b/src/api/routes/channels/\043channel_id/messages/\043message_id/crosspost.ts"
index 6d89c50..2aad157 100644
--- "a/src/api/routes/channels/\043channel_id/messages/\043message_id/crosspost.ts"
+++ "b/src/api/routes/channels/\043channel_id/messages/\043message_id/crosspost.ts"
@@ -22,43 +22,43 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- permission: "MANAGE_MESSAGES",
- responses: {
- 200: {
- body: "Message",
- },
- },
- }),
- (req: Request, res: Response) => {
- // TODO:
- res.json({
- id: "",
- type: 0,
- content: "",
- channel_id: "",
- author: {
- id: "",
- username: "",
- avatar: "",
- discriminator: "",
- public_flags: 64,
- },
- attachments: [],
- embeds: [],
- mentions: [],
- mention_roles: [],
- pinned: false,
- mention_everyone: false,
- tts: false,
- timestamp: "",
- edited_timestamp: null,
- flags: 1,
- components: [],
- poll: {},
- }).status(200);
- },
+ "/",
+ route({
+ permission: "MANAGE_MESSAGES",
+ responses: {
+ 200: {
+ body: "Message",
+ },
+ },
+ }),
+ (req: Request, res: Response) => {
+ // TODO:
+ res.json({
+ id: "",
+ type: 0,
+ content: "",
+ channel_id: "",
+ author: {
+ id: "",
+ username: "",
+ avatar: "",
+ discriminator: "",
+ public_flags: 64,
+ },
+ attachments: [],
+ embeds: [],
+ mentions: [],
+ mention_roles: [],
+ pinned: false,
+ mention_everyone: false,
+ tts: false,
+ timestamp: "",
+ edited_timestamp: null,
+ flags: 1,
+ components: [],
+ poll: {},
+ }).status(200);
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/messages/\043message_id/index.ts" "b/src/api/routes/channels/\043channel_id/messages/\043message_id/index.ts"
index cdba9b1..64f29c9 100644
--- "a/src/api/routes/channels/\043channel_id/messages/\043message_id/index.ts"
+++ "b/src/api/routes/channels/\043channel_id/messages/\043message_id/index.ts"
@@ -17,19 +17,19 @@
*/
import {
- Attachment,
- Channel,
- Message,
- MessageCreateEvent,
- MessageDeleteEvent,
- MessageUpdateEvent,
- Snowflake,
- SpacebarApiErrors,
- emitEvent,
- getPermission,
- getRights,
- uploadFile,
- NewUrlUserSignatureData,
+ Attachment,
+ Channel,
+ Message,
+ MessageCreateEvent,
+ MessageDeleteEvent,
+ MessageUpdateEvent,
+ Snowflake,
+ SpacebarApiErrors,
+ emitEvent,
+ getPermission,
+ getRights,
+ uploadFile,
+ NewUrlUserSignatureData,
} from "@spacebar/util";
import { Request, Response, Router } from "express";
import { HTTPError } from "lambert-server";
@@ -41,285 +41,285 @@
// TODO: message content/embed string length limit
const messageUpload = multer({
- limits: {
- fileSize: 1024 * 1024 * 100,
- fields: 10,
- files: 1,
- },
- storage: multer.memoryStorage(),
+ limits: {
+ fileSize: 1024 * 1024 * 100,
+ fields: 10,
+ files: 1,
+ },
+ storage: multer.memoryStorage(),
}); // max upload 50 mb
router.patch(
- "/",
- route({
- requestBody: "MessageEditSchema",
- permission: "SEND_MESSAGES",
- right: "SEND_MESSAGES",
- responses: {
- 200: {
- body: "Message",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {},
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { message_id, channel_id } = req.params;
- let body = req.body as MessageEditSchema;
+ "/",
+ route({
+ requestBody: "MessageEditSchema",
+ permission: "SEND_MESSAGES",
+ right: "SEND_MESSAGES",
+ responses: {
+ 200: {
+ body: "Message",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {},
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { message_id, channel_id } = req.params;
+ let body = req.body as MessageEditSchema;
- const message = await Message.findOneOrFail({
- where: { id: message_id, channel_id },
- relations: ["attachments"],
- });
+ const message = await Message.findOneOrFail({
+ where: { id: message_id, channel_id },
+ relations: ["attachments"],
+ });
- const permissions = await getPermission(req.user_id, undefined, channel_id);
+ const permissions = await getPermission(req.user_id, undefined, channel_id);
- const rights = await getRights(req.user_id);
+ const rights = await getRights(req.user_id);
- if (req.user_id !== message.author_id) {
- if (!rights.has("MANAGE_MESSAGES")) {
- permissions.hasThrow("MANAGE_MESSAGES");
- body = { flags: body.flags };
- // guild admins can only suppress embeds of other messages, no such restriction imposed to instance-wide admins
- }
- } else rights.hasThrow("SELF_EDIT_MESSAGES");
+ if (req.user_id !== message.author_id) {
+ if (!rights.has("MANAGE_MESSAGES")) {
+ permissions.hasThrow("MANAGE_MESSAGES");
+ body = { flags: body.flags };
+ // guild admins can only suppress embeds of other messages, no such restriction imposed to instance-wide admins
+ }
+ } else rights.hasThrow("SELF_EDIT_MESSAGES");
- // no longer necessary, somehow resolved by updating the type of `attachments`...?
- // //@ts-expect-error Something is wrong with message_reference here, TS complains since "channel_id" is optional in MessageCreateSchema
- const new_message = await handleMessage({
- ...message,
- // TODO: should message_reference be overridable?
- message_reference: message.message_reference,
- ...body,
- author_id: message.author_id,
- channel_id,
- id: message_id,
- edited_timestamp: new Date(),
- });
+ // no longer necessary, somehow resolved by updating the type of `attachments`...?
+ // //@ts-expect-error Something is wrong with message_reference here, TS complains since "channel_id" is optional in MessageCreateSchema
+ const new_message = await handleMessage({
+ ...message,
+ // TODO: should message_reference be overridable?
+ message_reference: message.message_reference,
+ ...body,
+ author_id: message.author_id,
+ channel_id,
+ id: message_id,
+ edited_timestamp: new Date(),
+ });
- await Promise.all([
- new_message.save(),
- await emitEvent({
- event: "MESSAGE_UPDATE",
- channel_id,
- data: {
- ...new_message.toJSON(),
- nonce: undefined,
- member: new_message.member?.toPublicMember(),
- },
- } as MessageUpdateEvent),
- ]);
+ await Promise.all([
+ new_message.save(),
+ await emitEvent({
+ event: "MESSAGE_UPDATE",
+ channel_id,
+ data: {
+ ...new_message.toJSON(),
+ nonce: undefined,
+ member: new_message.member?.toPublicMember(),
+ },
+ } as MessageUpdateEvent),
+ ]);
- postHandleMessage(new_message);
+ postHandleMessage(new_message);
- // TODO: a DTO?
- return res.json({
- ...new_message.toJSON(),
- id: new_message.id,
- type: new_message.type,
- channel_id: new_message.channel_id,
- member: new_message.member?.toPublicMember(),
- author: new_message.author?.toPublicUser(),
- attachments: new_message.attachments,
- embeds: new_message.embeds,
- mentions: new_message.embeds,
- mention_roles: new_message.mention_roles,
- mention_everyone: new_message.mention_everyone,
- pinned: new_message.pinned,
- timestamp: new_message.timestamp,
- edited_timestamp: new_message.edited_timestamp,
+ // TODO: a DTO?
+ return res.json({
+ ...new_message.toJSON(),
+ id: new_message.id,
+ type: new_message.type,
+ channel_id: new_message.channel_id,
+ member: new_message.member?.toPublicMember(),
+ author: new_message.author?.toPublicUser(),
+ attachments: new_message.attachments,
+ embeds: new_message.embeds,
+ mentions: new_message.embeds,
+ mention_roles: new_message.mention_roles,
+ mention_everyone: new_message.mention_everyone,
+ pinned: new_message.pinned,
+ timestamp: new_message.timestamp,
+ edited_timestamp: new_message.edited_timestamp,
- // these are not in the Discord.com response
- mention_channels: new_message.mention_channels,
- });
- },
+ // these are not in the Discord.com response
+ mention_channels: new_message.mention_channels,
+ });
+ },
);
// Backfill message with specific timestamp
router.put(
- "/",
- messageUpload.single("file"),
- async (req, res, next) => {
- if (req.body.payload_json) {
- req.body = JSON.parse(req.body.payload_json);
- }
+ "/",
+ messageUpload.single("file"),
+ async (req, res, next) => {
+ if (req.body.payload_json) {
+ req.body = JSON.parse(req.body.payload_json);
+ }
- next();
- },
- route({
- requestBody: "MessageCreateSchema",
- permission: "SEND_MESSAGES",
- right: "SEND_BACKDATED_EVENTS",
- responses: {
- 200: {
- body: "Message",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {},
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id, message_id } = req.params;
- const body = req.body as MessageCreateSchema;
- const attachments: (MessageCreateAttachment | MessageCreateCloudAttachment)[] = body.attachments ?? [];
+ next();
+ },
+ route({
+ requestBody: "MessageCreateSchema",
+ permission: "SEND_MESSAGES",
+ right: "SEND_BACKDATED_EVENTS",
+ responses: {
+ 200: {
+ body: "Message",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {},
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id, message_id } = req.params;
+ const body = req.body as MessageCreateSchema;
+ const attachments: (MessageCreateAttachment | MessageCreateCloudAttachment)[] = body.attachments ?? [];
- const rights = await getRights(req.user_id);
- rights.hasThrow("SEND_MESSAGES");
+ const rights = await getRights(req.user_id);
+ rights.hasThrow("SEND_MESSAGES");
- // regex to check if message contains anything other than numerals ( also no decimals )
- if (!message_id.match(/^\+?\d+$/)) {
- throw new HTTPError("Message IDs must be positive integers", 400);
- }
+ // regex to check if message contains anything other than numerals ( also no decimals )
+ if (!message_id.match(/^\+?\d+$/)) {
+ throw new HTTPError("Message IDs must be positive integers", 400);
+ }
- const snowflake = Snowflake.deconstruct(message_id);
- if (Date.now() < snowflake.timestamp) {
- // message is in the future
- throw SpacebarApiErrors.CANNOT_BACKFILL_TO_THE_FUTURE;
- }
+ const snowflake = Snowflake.deconstruct(message_id);
+ if (Date.now() < snowflake.timestamp) {
+ // message is in the future
+ throw SpacebarApiErrors.CANNOT_BACKFILL_TO_THE_FUTURE;
+ }
- const exists = await Message.findOne({
- where: { id: message_id, channel_id: channel_id },
- });
- if (exists) {
- throw SpacebarApiErrors.CANNOT_REPLACE_BY_BACKFILL;
- }
+ const exists = await Message.findOne({
+ where: { id: message_id, channel_id: channel_id },
+ });
+ if (exists) {
+ throw SpacebarApiErrors.CANNOT_REPLACE_BY_BACKFILL;
+ }
- if (req.file) {
- try {
- const file = await uploadFile(`/attachments/${req.params.channel_id}`, req.file);
- attachments.push(Attachment.create({ ...file, proxy_url: file.url }));
- } catch (error) {
- return res.status(400).json(error);
- }
- }
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- relations: ["recipients", "recipients.user"],
- });
+ if (req.file) {
+ try {
+ const file = await uploadFile(`/attachments/${req.params.channel_id}`, req.file);
+ attachments.push(Attachment.create({ ...file, proxy_url: file.url }));
+ } catch (error) {
+ return res.status(400).json(error);
+ }
+ }
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ relations: ["recipients", "recipients.user"],
+ });
- const embeds = body.embeds || [];
- if (body.embed) embeds.push(body.embed);
- const message = await handleMessage({
- ...body,
- type: 0,
- pinned: false,
- author_id: req.user_id,
- id: message_id,
- embeds,
- channel_id,
- attachments,
- edited_timestamp: undefined,
- timestamp: new Date(snowflake.timestamp),
- });
+ const embeds = body.embeds || [];
+ if (body.embed) embeds.push(body.embed);
+ const message = await handleMessage({
+ ...body,
+ type: 0,
+ pinned: false,
+ author_id: req.user_id,
+ id: message_id,
+ embeds,
+ channel_id,
+ attachments,
+ edited_timestamp: undefined,
+ timestamp: new Date(snowflake.timestamp),
+ });
- //Fix for the client bug
- delete message.member;
+ //Fix for the client bug
+ delete message.member;
- await Promise.all([
- message.save(),
- emitEvent({
- event: "MESSAGE_CREATE",
- channel_id: channel_id,
- data: message,
- } as MessageCreateEvent),
- channel.save(),
- ]);
+ await Promise.all([
+ message.save(),
+ emitEvent({
+ event: "MESSAGE_CREATE",
+ channel_id: channel_id,
+ data: message,
+ } as MessageCreateEvent),
+ channel.save(),
+ ]);
- // no await as it shouldnt block the message send function and silently catch error
- postHandleMessage(message).catch((e) => console.error("[Message] post-message handler failed", e));
+ // no await as it shouldnt block the message send function and silently catch error
+ postHandleMessage(message).catch((e) => console.error("[Message] post-message handler failed", e));
- return res.json(
- message.withSignedAttachments(
- new NewUrlUserSignatureData({
- ip: req.ip,
- userAgent: req.headers["user-agent"] as string,
- }),
- ),
- );
- },
+ return res.json(
+ message.withSignedAttachments(
+ new NewUrlUserSignatureData({
+ ip: req.ip,
+ userAgent: req.headers["user-agent"] as string,
+ }),
+ ),
+ );
+ },
);
router.get(
- "/",
- route({
- permission: "VIEW_CHANNEL",
- responses: {
- 200: {
- body: "Message",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {},
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { message_id, channel_id } = req.params;
+ "/",
+ route({
+ permission: "VIEW_CHANNEL",
+ responses: {
+ 200: {
+ body: "Message",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {},
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { message_id, channel_id } = req.params;
- const message = await Message.findOneOrFail({
- where: { id: message_id, channel_id },
- relations: ["attachments"],
- });
+ const message = await Message.findOneOrFail({
+ where: { id: message_id, channel_id },
+ relations: ["attachments"],
+ });
- const permissions = await getPermission(req.user_id, undefined, channel_id);
+ const permissions = await getPermission(req.user_id, undefined, channel_id);
- if (message.author_id !== req.user_id) permissions.hasThrow("READ_MESSAGE_HISTORY");
+ if (message.author_id !== req.user_id) permissions.hasThrow("READ_MESSAGE_HISTORY");
- return res.json(message);
- },
+ return res.json(message);
+ },
);
router.delete(
- "/",
- route({
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { message_id, channel_id } = req.params;
+ "/",
+ route({
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { message_id, channel_id } = req.params;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
- const message = await Message.findOneOrFail({
- where: { id: message_id },
- });
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
+ const message = await Message.findOneOrFail({
+ where: { id: message_id },
+ });
- const rights = await getRights(req.user_id);
+ const rights = await getRights(req.user_id);
- if (message.author_id !== req.user_id) {
- if (!rights.has("MANAGE_MESSAGES")) {
- const permission = await getPermission(req.user_id, channel.guild_id, channel_id);
- permission.hasThrow("MANAGE_MESSAGES");
- }
- } else rights.hasThrow("SELF_DELETE_MESSAGES");
+ if (message.author_id !== req.user_id) {
+ if (!rights.has("MANAGE_MESSAGES")) {
+ const permission = await getPermission(req.user_id, channel.guild_id, channel_id);
+ permission.hasThrow("MANAGE_MESSAGES");
+ }
+ } else rights.hasThrow("SELF_DELETE_MESSAGES");
- await Message.delete({ id: message_id });
+ await Message.delete({ id: message_id });
- await emitEvent({
- event: "MESSAGE_DELETE",
- channel_id,
- data: {
- id: message_id,
- channel_id,
- guild_id: channel.guild_id,
- },
- } as MessageDeleteEvent);
+ await emitEvent({
+ event: "MESSAGE_DELETE",
+ channel_id,
+ data: {
+ id: message_id,
+ channel_id,
+ guild_id: channel.guild_id,
+ },
+ } as MessageDeleteEvent);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/messages/\043message_id/reactions.ts" "b/src/api/routes/channels/\043channel_id/messages/\043message_id/reactions.ts"
index 63c41cd..b21dbd3 100644
--- "a/src/api/routes/channels/\043channel_id/messages/\043message_id/reactions.ts"
+++ "b/src/api/routes/channels/\043channel_id/messages/\043message_id/reactions.ts"
@@ -18,18 +18,18 @@
import { route } from "@spacebar/api";
import {
- Channel,
- emitEvent,
- Emoji,
- getPermission,
- Member,
- Message,
- MessageReactionAddEvent,
- MessageReactionRemoveAllEvent,
- MessageReactionRemoveEmojiEvent,
- MessageReactionRemoveEvent,
- User,
- arrayRemove,
+ Channel,
+ emitEvent,
+ Emoji,
+ getPermission,
+ Member,
+ Message,
+ MessageReactionAddEvent,
+ MessageReactionRemoveAllEvent,
+ MessageReactionRemoveEmojiEvent,
+ MessageReactionRemoveEvent,
+ User,
+ arrayRemove,
} from "@spacebar/util";
import { Request, Response, Router } from "express";
import { HTTPError } from "lambert-server";
@@ -40,326 +40,326 @@
// TODO: check if emoji is really an unicode emoji or a properly encoded external emoji
function getEmoji(emoji: string): PartialEmoji {
- emoji = decodeURIComponent(emoji);
- const parts = emoji.includes(":") && emoji.split(":");
- if (parts)
- return {
- name: parts[0],
- id: parts[1],
- };
+ emoji = decodeURIComponent(emoji);
+ const parts = emoji.includes(":") && emoji.split(":");
+ if (parts)
+ return {
+ name: parts[0],
+ id: parts[1],
+ };
- return {
- id: undefined,
- name: emoji,
- };
+ return {
+ id: undefined,
+ name: emoji,
+ };
}
router.delete(
- "/",
- route({
- permission: "MANAGE_MESSAGES",
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {},
- 403: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { message_id, channel_id } = req.params;
+ "/",
+ route({
+ permission: "MANAGE_MESSAGES",
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {},
+ 403: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { message_id, channel_id } = req.params;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
- await Message.update({ id: message_id, channel_id }, { reactions: [] });
+ await Message.update({ id: message_id, channel_id }, { reactions: [] });
- await emitEvent({
- event: "MESSAGE_REACTION_REMOVE_ALL",
- channel_id,
- data: {
- channel_id,
- message_id,
- guild_id: channel.guild_id,
- },
- } as MessageReactionRemoveAllEvent);
+ await emitEvent({
+ event: "MESSAGE_REACTION_REMOVE_ALL",
+ channel_id,
+ data: {
+ channel_id,
+ message_id,
+ guild_id: channel.guild_id,
+ },
+ } as MessageReactionRemoveAllEvent);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
router.delete(
- "/:emoji",
- route({
- permission: "MANAGE_MESSAGES",
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {},
- 403: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { message_id, channel_id } = req.params;
- const emoji = getEmoji(req.params.emoji);
+ "/:emoji",
+ route({
+ permission: "MANAGE_MESSAGES",
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {},
+ 403: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { message_id, channel_id } = req.params;
+ const emoji = getEmoji(req.params.emoji);
- const message = await Message.findOneOrFail({
- where: { id: message_id, channel_id },
- });
+ const message = await Message.findOneOrFail({
+ where: { id: message_id, channel_id },
+ });
- const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
- if (!already_added) throw new HTTPError("Reaction not found", 404);
- arrayRemove(message.reactions, already_added);
+ const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
+ if (!already_added) throw new HTTPError("Reaction not found", 404);
+ arrayRemove(message.reactions, already_added);
- await Promise.all([
- message.save(),
- emitEvent({
- event: "MESSAGE_REACTION_REMOVE_EMOJI",
- channel_id,
- data: {
- channel_id,
- message_id,
- guild_id: message.guild_id,
- emoji,
- },
- } as MessageReactionRemoveEmojiEvent),
- ]);
+ await Promise.all([
+ message.save(),
+ emitEvent({
+ event: "MESSAGE_REACTION_REMOVE_EMOJI",
+ channel_id,
+ data: {
+ channel_id,
+ message_id,
+ guild_id: message.guild_id,
+ emoji,
+ },
+ } as MessageReactionRemoveEmojiEvent),
+ ]);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
router.get(
- "/:emoji",
- route({
- permission: "VIEW_CHANNEL",
- responses: {
- 200: {
- body: "PublicUser",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 404: {},
- 403: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { message_id, channel_id } = req.params;
- const emoji = getEmoji(req.params.emoji);
+ "/:emoji",
+ route({
+ permission: "VIEW_CHANNEL",
+ responses: {
+ 200: {
+ body: "PublicUser",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {},
+ 403: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { message_id, channel_id } = req.params;
+ const emoji = getEmoji(req.params.emoji);
- const message = await Message.findOneOrFail({
- where: { id: message_id, channel_id },
- });
- const reaction = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
- if (!reaction) throw new HTTPError("Reaction not found", 404);
+ const message = await Message.findOneOrFail({
+ where: { id: message_id, channel_id },
+ });
+ const reaction = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
+ if (!reaction) throw new HTTPError("Reaction not found", 404);
- const users = (
- await User.find({
- where: {
- id: In(reaction.user_ids),
- },
- select: PublicUserProjection,
- })
- ).map((user) => user.toPublicUser());
+ const users = (
+ await User.find({
+ where: {
+ id: In(reaction.user_ids),
+ },
+ select: PublicUserProjection,
+ })
+ ).map((user) => user.toPublicUser());
- res.json(users);
- },
+ res.json(users);
+ },
);
router.put(
- "/:emoji/:user_id",
- route({
- permission: "READ_MESSAGE_HISTORY",
- right: "SELF_ADD_REACTIONS",
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {},
- 403: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { message_id, channel_id, user_id } = req.params;
- if (user_id !== "@me") throw new HTTPError("Invalid user");
- const emoji = getEmoji(req.params.emoji);
+ "/:emoji/:user_id",
+ route({
+ permission: "READ_MESSAGE_HISTORY",
+ right: "SELF_ADD_REACTIONS",
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {},
+ 403: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { message_id, channel_id, user_id } = req.params;
+ if (user_id !== "@me") throw new HTTPError("Invalid user");
+ const emoji = getEmoji(req.params.emoji);
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
- const message = await Message.findOneOrFail({
- where: { id: message_id, channel_id },
- });
- const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
+ const message = await Message.findOneOrFail({
+ where: { id: message_id, channel_id },
+ });
+ const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
- if (!already_added) req.permission?.hasThrow("ADD_REACTIONS");
+ if (!already_added) req.permission?.hasThrow("ADD_REACTIONS");
- if (emoji.id) {
- const external_emoji = await Emoji.findOneOrFail({
- where: { id: emoji.id },
- });
- if (!already_added && channel.guild_id != external_emoji.guild_id) req.permission?.hasThrow("USE_EXTERNAL_EMOJIS");
- emoji.animated = external_emoji.animated;
- emoji.name = external_emoji.name;
- }
+ if (emoji.id) {
+ const external_emoji = await Emoji.findOneOrFail({
+ where: { id: emoji.id },
+ });
+ if (!already_added && channel.guild_id != external_emoji.guild_id) req.permission?.hasThrow("USE_EXTERNAL_EMOJIS");
+ emoji.animated = external_emoji.animated;
+ emoji.name = external_emoji.name;
+ }
- if (already_added) {
- if (already_added.user_ids.includes(req.user_id)) return res.sendStatus(204); // Do not throw an error ¯\_(ツ)_/¯ as discord also doesn't throw any error
- already_added.count++;
- already_added.user_ids.push(req.user_id);
- } else
- message.reactions.push({
- count: 1,
- emoji,
- user_ids: [req.user_id],
- });
+ if (already_added) {
+ if (already_added.user_ids.includes(req.user_id)) return res.sendStatus(204); // Do not throw an error ¯\_(ツ)_/¯ as discord also doesn't throw any error
+ already_added.count++;
+ already_added.user_ids.push(req.user_id);
+ } else
+ message.reactions.push({
+ count: 1,
+ emoji,
+ user_ids: [req.user_id],
+ });
- await message.save();
+ await message.save();
- const member =
- channel.guild_id &&
- (
- await Member.findOneOrFail({
- where: { id: req.user_id },
- select: PublicMemberProjection,
- })
- ).toPublicMember();
+ const member =
+ channel.guild_id &&
+ (
+ await Member.findOneOrFail({
+ where: { id: req.user_id },
+ select: PublicMemberProjection,
+ })
+ ).toPublicMember();
- await emitEvent({
- event: "MESSAGE_REACTION_ADD",
- channel_id,
- data: {
- user_id: req.user_id,
- channel_id,
- message_id,
- guild_id: channel.guild_id,
- emoji,
- member,
- },
- } as MessageReactionAddEvent);
+ await emitEvent({
+ event: "MESSAGE_REACTION_ADD",
+ channel_id,
+ data: {
+ user_id: req.user_id,
+ channel_id,
+ message_id,
+ guild_id: channel.guild_id,
+ emoji,
+ member,
+ },
+ } as MessageReactionAddEvent);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
router.delete(
- "/:emoji/:user_id",
- route({
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {},
- 403: {},
- },
- }),
- async (req: Request, res: Response) => {
- let { user_id } = req.params;
- const { message_id, channel_id } = req.params;
+ "/:emoji/:user_id",
+ route({
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {},
+ 403: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ let { user_id } = req.params;
+ const { message_id, channel_id } = req.params;
- const emoji = getEmoji(req.params.emoji);
+ const emoji = getEmoji(req.params.emoji);
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
- const message = await Message.findOneOrFail({
- where: { id: message_id, channel_id },
- });
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
+ const message = await Message.findOneOrFail({
+ where: { id: message_id, channel_id },
+ });
- if (user_id === "@me") user_id = req.user_id;
- else {
- const permissions = await getPermission(req.user_id, undefined, channel_id);
- permissions.hasThrow("MANAGE_MESSAGES");
- }
+ if (user_id === "@me") user_id = req.user_id;
+ else {
+ const permissions = await getPermission(req.user_id, undefined, channel_id);
+ permissions.hasThrow("MANAGE_MESSAGES");
+ }
- const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
- if (!already_added || !already_added.user_ids.includes(user_id)) throw new HTTPError("Reaction not found", 404);
+ const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
+ if (!already_added || !already_added.user_ids.includes(user_id)) throw new HTTPError("Reaction not found", 404);
- already_added.count--;
+ already_added.count--;
- if (already_added.count <= 0) arrayRemove(message.reactions, already_added);
- else already_added.user_ids.splice(already_added.user_ids.indexOf(user_id), 1);
+ if (already_added.count <= 0) arrayRemove(message.reactions, already_added);
+ else already_added.user_ids.splice(already_added.user_ids.indexOf(user_id), 1);
- await message.save();
+ await message.save();
- await emitEvent({
- event: "MESSAGE_REACTION_REMOVE",
- channel_id,
- data: {
- user_id: req.user_id,
- channel_id,
- message_id,
- guild_id: channel.guild_id,
- emoji,
- },
- } as MessageReactionRemoveEvent);
+ await emitEvent({
+ event: "MESSAGE_REACTION_REMOVE",
+ channel_id,
+ data: {
+ user_id: req.user_id,
+ channel_id,
+ message_id,
+ guild_id: channel.guild_id,
+ emoji,
+ },
+ } as MessageReactionRemoveEvent);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
router.delete(
- "/:emoji/:burst/:user_id",
- route({
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {},
- 403: {},
- },
- }),
- async (req: Request, res: Response) => {
- let { user_id } = req.params;
- const { message_id, channel_id } = req.params;
+ "/:emoji/:burst/:user_id",
+ route({
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {},
+ 403: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ let { user_id } = req.params;
+ const { message_id, channel_id } = req.params;
- const emoji = getEmoji(req.params.emoji);
+ const emoji = getEmoji(req.params.emoji);
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
- const message = await Message.findOneOrFail({
- where: { id: message_id, channel_id },
- });
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
+ const message = await Message.findOneOrFail({
+ where: { id: message_id, channel_id },
+ });
- if (user_id === "@me") user_id = req.user_id;
- else {
- const permissions = await getPermission(req.user_id, undefined, channel_id);
- permissions.hasThrow("MANAGE_MESSAGES");
- }
+ if (user_id === "@me") user_id = req.user_id;
+ else {
+ const permissions = await getPermission(req.user_id, undefined, channel_id);
+ permissions.hasThrow("MANAGE_MESSAGES");
+ }
- const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
- if (!already_added || !already_added.user_ids.includes(user_id)) throw new HTTPError("Reaction not found", 404);
+ const already_added = message.reactions.find((x) => (x.emoji.id === emoji.id && emoji.id) || x.emoji.name === emoji.name);
+ if (!already_added || !already_added.user_ids.includes(user_id)) throw new HTTPError("Reaction not found", 404);
- already_added.count--;
+ already_added.count--;
- if (already_added.count <= 0) arrayRemove(message.reactions, already_added);
- else already_added.user_ids.splice(already_added.user_ids.indexOf(user_id), 1);
+ if (already_added.count <= 0) arrayRemove(message.reactions, already_added);
+ else already_added.user_ids.splice(already_added.user_ids.indexOf(user_id), 1);
- await message.save();
+ await message.save();
- await emitEvent({
- event: "MESSAGE_REACTION_REMOVE",
- channel_id,
- data: {
- user_id: req.user_id,
- channel_id,
- message_id,
- guild_id: channel.guild_id,
- emoji,
- },
- } as MessageReactionRemoveEvent);
+ await emitEvent({
+ event: "MESSAGE_REACTION_REMOVE",
+ channel_id,
+ data: {
+ user_id: req.user_id,
+ channel_id,
+ message_id,
+ guild_id: channel.guild_id,
+ emoji,
+ },
+ } as MessageReactionRemoveEvent);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/messages/bulk-delete.ts" "b/src/api/routes/channels/\043channel_id/messages/bulk-delete.ts"
index 54801a4..f4645ab 100644
--- "a/src/api/routes/channels/\043channel_id/messages/bulk-delete.ts"
+++ "b/src/api/routes/channels/\043channel_id/messages/bulk-delete.ts"
@@ -29,48 +29,48 @@
// should this request fail, if you provide messages older than 14 days/invalid ids? ANSWER: NO
// https://discord.com/developers/docs/resources/channel#bulk-delete-messages
router.post(
- "/",
- route({
- requestBody: "BulkDeleteSchema",
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 403: {},
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id } = req.params;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
- if (!channel.guild_id) throw new HTTPError("Can't bulk delete dm channel messages", 400);
+ "/",
+ route({
+ requestBody: "BulkDeleteSchema",
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {},
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id } = req.params;
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
+ if (!channel.guild_id) throw new HTTPError("Can't bulk delete dm channel messages", 400);
- const rights = await getRights(req.user_id);
- rights.hasThrow("SELF_DELETE_MESSAGES");
+ const rights = await getRights(req.user_id);
+ rights.hasThrow("SELF_DELETE_MESSAGES");
- const superuser = rights.has("MANAGE_MESSAGES");
- const permission = await getPermission(req.user_id, channel?.guild_id, channel_id);
+ const superuser = rights.has("MANAGE_MESSAGES");
+ const permission = await getPermission(req.user_id, channel?.guild_id, channel_id);
- const { maxBulkDelete } = Config.get().limits.message;
+ const { maxBulkDelete } = Config.get().limits.message;
- const { messages } = req.body as { messages: string[] };
- if (messages.length === 0) throw new HTTPError("You must specify messages to bulk delete");
- if (!superuser) {
- permission.hasThrow("MANAGE_MESSAGES");
- if (messages.length > maxBulkDelete) throw new HTTPError(`You cannot delete more than ${maxBulkDelete} messages`);
- }
+ const { messages } = req.body as { messages: string[] };
+ if (messages.length === 0) throw new HTTPError("You must specify messages to bulk delete");
+ if (!superuser) {
+ permission.hasThrow("MANAGE_MESSAGES");
+ if (messages.length > maxBulkDelete) throw new HTTPError(`You cannot delete more than ${maxBulkDelete} messages`);
+ }
- await Message.delete(messages);
+ await Message.delete(messages);
- await emitEvent({
- event: "MESSAGE_DELETE_BULK",
- channel_id,
- data: { ids: messages, channel_id, guild_id: channel.guild_id },
- } as MessageDeleteBulkEvent);
+ await emitEvent({
+ event: "MESSAGE_DELETE_BULK",
+ channel_id,
+ data: { ids: messages, channel_id, guild_id: channel.guild_id },
+ } as MessageDeleteBulkEvent);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
diff --git "a/src/api/routes/channels/\043channel_id/messages/index.ts" "b/src/api/routes/channels/\043channel_id/messages/index.ts"
index 2ce3774..272fa8a 100644
--- "a/src/api/routes/channels/\043channel_id/messages/index.ts"
+++ "b/src/api/routes/channels/\043channel_id/messages/index.ts"
@@ -18,29 +18,29 @@
import { handleMessage, postHandleMessage, route } from "@spacebar/api";
import {
- Attachment,
- AutomodRule,
- AutomodTriggerTypes,
- Channel,
- Config,
- DiscordApiErrors,
- DmChannelDTO,
- emitEvent,
- FieldErrors,
- getPermission,
- getUrlSignature,
- Member,
- Message,
- MessageCreateEvent,
- NewUrlSignatureData,
- NewUrlUserSignatureData,
- ReadState,
- Relationship,
- Rights,
- Snowflake,
- stringGlobToRegexp,
- uploadFile,
- User,
+ Attachment,
+ AutomodRule,
+ AutomodTriggerTypes,
+ Channel,
+ Config,
+ DiscordApiErrors,
+ DmChannelDTO,
+ emitEvent,
+ FieldErrors,
+ getPermission,
+ getUrlSignature,
+ Member,
+ Message,
+ MessageCreateEvent,
+ NewUrlSignatureData,
+ NewUrlUserSignatureData,
+ ReadState,
+ Relationship,
+ Rights,
+ Snowflake,
+ stringGlobToRegexp,
+ uploadFile,
+ User,
} from "@spacebar/util";
import { Request, Response, Router } from "express";
import { HTTPError } from "lambert-server";
@@ -48,17 +48,17 @@
import { FindManyOptions, FindOperator, LessThan, MoreThan, MoreThanOrEqual } from "typeorm";
import { URL } from "url";
import {
- AcknowledgeDeleteSchema,
- AutomodCustomWordsRule,
- AutomodRuleActionType,
- AutomodRuleEventType,
- isTextChannel,
- MessageCreateAttachment,
- MessageCreateCloudAttachment,
- MessageCreateSchema,
- Reaction,
- ReadStateType,
- RelationshipType,
+ AcknowledgeDeleteSchema,
+ AutomodCustomWordsRule,
+ AutomodRuleActionType,
+ AutomodRuleEventType,
+ isTextChannel,
+ MessageCreateAttachment,
+ MessageCreateCloudAttachment,
+ MessageCreateSchema,
+ Reaction,
+ ReadStateType,
+ RelationshipType,
} from "@spacebar/schemas";
const router: Router = Router({ mergeParams: true });
@@ -66,221 +66,221 @@
// https://discord.com/developers/docs/resources/channel#create-message
// get messages
router.get(
- "/",
- route({
- query: {
- around: {
- type: "string",
- },
- before: {
- type: "string",
- },
- after: {
- type: "string",
- },
- limit: {
- type: "number",
- description: "max number of messages to return (1-100). defaults to 50",
- },
- },
- responses: {
- 200: {
- body: "APIMessageArray",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {},
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const channel_id = req.params.channel_id;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
- if (!channel) throw new HTTPError("Channel not found", 404);
+ "/",
+ route({
+ query: {
+ around: {
+ type: "string",
+ },
+ before: {
+ type: "string",
+ },
+ after: {
+ type: "string",
+ },
+ limit: {
+ type: "number",
+ description: "max number of messages to return (1-100). defaults to 50",
+ },
+ },
+ responses: {
+ 200: {
+ body: "APIMessageArray",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {},
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const channel_id = req.params.channel_id;
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
+ if (!channel) throw new HTTPError("Channel not found", 404);
- isTextChannel(channel.type);
- const around = req.query.around ? `${req.query.around}` : undefined;
- const before = req.query.before ? `${req.query.before}` : undefined;
- const after = req.query.after ? `${req.query.after}` : undefined;
- const limit = Number(req.query.limit) || 50;
- if (limit < 1 || limit > 100) throw new HTTPError("limit must be between 1 and 100", 422);
+ isTextChannel(channel.type);
+ const around = req.query.around ? `${req.query.around}` : undefined;
+ const before = req.query.before ? `${req.query.before}` : undefined;
+ const after = req.query.after ? `${req.query.after}` : undefined;
+ const limit = Number(req.query.limit) || 50;
+ if (limit < 1 || limit > 100) throw new HTTPError("limit must be between 1 and 100", 422);
- const permissions = await getPermission(req.user_id, channel.guild_id, channel_id);
- permissions.hasThrow("VIEW_CHANNEL");
- if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json([]);
+ const permissions = await getPermission(req.user_id, channel.guild_id, channel_id);
+ permissions.hasThrow("VIEW_CHANNEL");
+ if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json([]);
- const query: FindManyOptions & {
- where: { id?: FindOperator | FindOperator[] };
- } = {
- order: { timestamp: "DESC" },
- take: limit,
- where: { channel_id },
- relations: [
- "author",
- "webhook",
- "application",
- "mentions",
- "mention_roles",
- "mention_channels",
- "sticker_items",
- "attachments",
- "referenced_message",
- "referenced_message.author",
- "referenced_message.webhook",
- "referenced_message.application",
- "referenced_message.mentions",
- "referenced_message.mention_roles",
- "referenced_message.mention_channels",
- "referenced_message.sticker_items",
- "referenced_message.attachments",
- ],
- };
+ const query: FindManyOptions & {
+ where: { id?: FindOperator | FindOperator[] };
+ } = {
+ order: { timestamp: "DESC" },
+ take: limit,
+ where: { channel_id },
+ relations: [
+ "author",
+ "webhook",
+ "application",
+ "mentions",
+ "mention_roles",
+ "mention_channels",
+ "sticker_items",
+ "attachments",
+ "referenced_message",
+ "referenced_message.author",
+ "referenced_message.webhook",
+ "referenced_message.application",
+ "referenced_message.mentions",
+ "referenced_message.mention_roles",
+ "referenced_message.mention_channels",
+ "referenced_message.sticker_items",
+ "referenced_message.attachments",
+ ],
+ };
- let messages: Message[];
+ let messages: Message[];
- if (around) {
- query.take = Math.floor(limit / 2);
- if (query.take != 0) {
- const [right, left] = await Promise.all([
- Message.find({
- ...query,
- where: { channel_id, id: LessThan(around) },
- }),
- Message.find({
- ...query,
- where: { channel_id, id: MoreThanOrEqual(around) },
- order: { timestamp: "ASC" },
- }),
- ]);
- left.push(...right);
- messages = left.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
- } else {
- query.take = 1;
- const message = await Message.findOne({
- ...query,
- where: { channel_id, id: around },
- });
- messages = message ? [message] : [];
- }
- } else {
- if (after) {
- if (BigInt(after) > BigInt(Snowflake.generate())) throw new HTTPError("after parameter must not be greater than current time", 422);
+ if (around) {
+ query.take = Math.floor(limit / 2);
+ if (query.take != 0) {
+ const [right, left] = await Promise.all([
+ Message.find({
+ ...query,
+ where: { channel_id, id: LessThan(around) },
+ }),
+ Message.find({
+ ...query,
+ where: { channel_id, id: MoreThanOrEqual(around) },
+ order: { timestamp: "ASC" },
+ }),
+ ]);
+ left.push(...right);
+ messages = left.sort((a, b) => a.timestamp.getTime() - b.timestamp.getTime());
+ } else {
+ query.take = 1;
+ const message = await Message.findOne({
+ ...query,
+ where: { channel_id, id: around },
+ });
+ messages = message ? [message] : [];
+ }
+ } else {
+ if (after) {
+ if (BigInt(after) > BigInt(Snowflake.generate())) throw new HTTPError("after parameter must not be greater than current time", 422);
- query.where.id = MoreThan(after);
- query.order = { timestamp: "ASC" };
- } else if (before) {
- if (BigInt(before) > BigInt(Snowflake.generate())) throw new HTTPError("before parameter must not be greater than current time", 422);
+ query.where.id = MoreThan(after);
+ query.order = { timestamp: "ASC" };
+ } else if (before) {
+ if (BigInt(before) > BigInt(Snowflake.generate())) throw new HTTPError("before parameter must not be greater than current time", 422);
- query.where.id = LessThan(before);
- }
+ query.where.id = LessThan(before);
+ }
- messages = await Message.find(query);
- }
+ messages = await Message.find(query);
+ }
- const endpoint = Config.get().cdn.endpointPublic;
+ const endpoint = Config.get().cdn.endpointPublic;
- const ret = messages.map((x: Message) => {
- x = x.toJSON();
+ const ret = messages.map((x: Message) => {
+ x = x.toJSON();
- (x.reactions || []).forEach((y: Partial) => {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- //@ts-ignore
- if ((y.user_ids || []).includes(req.user_id)) y.me = true;
- delete y.user_ids;
- });
- if (!x.author)
- x.author = User.create({
- id: "4",
- discriminator: "0000",
- username: "Spacebar Ghost",
- public_flags: 0,
- });
- x.attachments?.forEach((y: Attachment) => {
- // dynamically set attachment proxy_url in case the endpoint changed
- const uri = y.proxy_url.startsWith("http") ? y.proxy_url : `https://example.org${y.proxy_url}`;
+ (x.reactions || []).forEach((y: Partial) => {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ //@ts-ignore
+ if ((y.user_ids || []).includes(req.user_id)) y.me = true;
+ delete y.user_ids;
+ });
+ if (!x.author)
+ x.author = User.create({
+ id: "4",
+ discriminator: "0000",
+ username: "Spacebar Ghost",
+ public_flags: 0,
+ });
+ x.attachments?.forEach((y: Attachment) => {
+ // dynamically set attachment proxy_url in case the endpoint changed
+ const uri = y.proxy_url.startsWith("http") ? y.proxy_url : `https://example.org${y.proxy_url}`;
- const url = new URL(uri);
- if (endpoint) {
- const newBase = new URL(endpoint);
- url.protocol = newBase.protocol;
- url.hostname = newBase.hostname;
- url.port = newBase.port;
- }
+ const url = new URL(uri);
+ if (endpoint) {
+ const newBase = new URL(endpoint);
+ url.protocol = newBase.protocol;
+ url.hostname = newBase.hostname;
+ url.port = newBase.port;
+ }
- y.proxy_url = url.toString();
+ y.proxy_url = url.toString();
- y.proxy_url = getUrlSignature(
- new NewUrlSignatureData({
- url: y.proxy_url,
- userAgent: req.headers["user-agent"],
- ip: req.ip,
- }),
- )
- .applyToUrl(y.proxy_url)
- .toString();
+ y.proxy_url = getUrlSignature(
+ new NewUrlSignatureData({
+ url: y.proxy_url,
+ userAgent: req.headers["user-agent"],
+ ip: req.ip,
+ }),
+ )
+ .applyToUrl(y.proxy_url)
+ .toString();
- y.url = getUrlSignature(
- new NewUrlSignatureData({
- url: y.url,
- userAgent: req.headers["user-agent"],
- ip: req.ip,
- }),
- )
- .applyToUrl(y.url)
- .toString();
- });
+ y.url = getUrlSignature(
+ new NewUrlSignatureData({
+ url: y.url,
+ userAgent: req.headers["user-agent"],
+ ip: req.ip,
+ }),
+ )
+ .applyToUrl(y.url)
+ .toString();
+ });
- /**
+ /**
Some clients ( discord.js ) only check if a property exists within the response,
which causes errors when, say, the `application` property is `null`.
**/
- // for (var curr in x) {
- // if (x[curr] === null)
- // delete x[curr];
- // }
+ // for (var curr in x) {
+ // if (x[curr] === null)
+ // delete x[curr];
+ // }
- return x;
- });
+ return x;
+ });
- await Promise.all(
- ret
- .filter((x: MessageCreateSchema) => x.interaction_metadata && !x.interaction_metadata.user)
- .map(async (x: MessageCreateSchema) => {
- x.interaction_metadata!.user = x.interaction!.user = await User.findOneOrFail({ where: { id: (x as Message).interaction_metadata!.user_id } });
- }),
- );
+ await Promise.all(
+ ret
+ .filter((x: MessageCreateSchema) => x.interaction_metadata && !x.interaction_metadata.user)
+ .map(async (x: MessageCreateSchema) => {
+ x.interaction_metadata!.user = x.interaction!.user = await User.findOneOrFail({ where: { id: (x as Message).interaction_metadata!.user_id } });
+ }),
+ );
- // polyfill message references for old messages
- await Promise.all(
- ret
- .filter((msg) => msg.message_reference && !msg.referenced_message?.id)
- .map(async (msg) => {
- const whereOptions: { id: string; guild_id?: string; channel_id?: string } = {
- id: msg.message_reference!.message_id,
- };
- if (msg.message_reference!.guild_id) whereOptions.guild_id = msg.message_reference!.guild_id;
- if (msg.message_reference!.channel_id) whereOptions.channel_id = msg.message_reference!.channel_id;
+ // polyfill message references for old messages
+ await Promise.all(
+ ret
+ .filter((msg) => msg.message_reference && !msg.referenced_message?.id)
+ .map(async (msg) => {
+ const whereOptions: { id: string; guild_id?: string; channel_id?: string } = {
+ id: msg.message_reference!.message_id,
+ };
+ if (msg.message_reference!.guild_id) whereOptions.guild_id = msg.message_reference!.guild_id;
+ if (msg.message_reference!.channel_id) whereOptions.channel_id = msg.message_reference!.channel_id;
- msg.referenced_message = await Message.findOne({ where: whereOptions, relations: ["author", "mentions", "mention_roles", "mention_channels"] });
- }),
- );
+ msg.referenced_message = await Message.findOne({ where: whereOptions, relations: ["author", "mentions", "mention_roles", "mention_channels"] });
+ }),
+ );
- return res.json(ret);
- },
+ return res.json(ret);
+ },
);
// TODO: config max upload size
const messageUpload = multer({
- limits: {
- fileSize: Config.get().limits.message.maxAttachmentSize,
- fields: 10,
- // files: 1
- },
- storage: multer.memoryStorage(),
+ limits: {
+ fileSize: Config.get().limits.message.maxAttachmentSize,
+ fields: 10,
+ // files: 1
+ },
+ storage: multer.memoryStorage(),
}); // max upload 50 mb
/**
TODO: dynamically change limit of MessageCreateSchema with config
@@ -292,213 +292,213 @@
**/
// Send message
router.post(
- "/",
- messageUpload.any(),
- (req, res, next) => {
- if (req.body.payload_json) {
- req.body = JSON.parse(req.body.payload_json);
- }
+ "/",
+ messageUpload.any(),
+ (req, res, next) => {
+ if (req.body.payload_json) {
+ req.body = JSON.parse(req.body.payload_json);
+ }
- next();
- },
- route({
- requestBody: "MessageCreateSchema",
- permission: "SEND_MESSAGES",
- right: "SEND_MESSAGES",
- responses: {
- 200: {
- body: "Message",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {},
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id } = req.params;
- const body = req.body as MessageCreateSchema;
- const attachments: (Attachment | MessageCreateAttachment | MessageCreateCloudAttachment)[] = body.attachments ?? [];
+ next();
+ },
+ route({
+ requestBody: "MessageCreateSchema",
+ permission: "SEND_MESSAGES",
+ right: "SEND_MESSAGES",
+ responses: {
+ 200: {
+ body: "Message",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {},
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id } = req.params;
+ const body = req.body as MessageCreateSchema;
+ const attachments: (Attachment | MessageCreateAttachment | MessageCreateCloudAttachment)[] = body.attachments ?? [];
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- relations: ["recipients", "recipients.user"],
- });
- if (!channel.isWritable()) {
- throw new HTTPError(`Cannot send messages to channel of type ${channel.type}`, 400);
- }
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ relations: ["recipients", "recipients.user"],
+ });
+ if (!channel.isWritable()) {
+ throw new HTTPError(`Cannot send messages to channel of type ${channel.type}`, 400);
+ }
- // handle blocked users in dms
- if (channel.recipients?.length == 2) {
- const otherUser = channel.recipients.find((r) => r.user_id != req.user_id)?.user;
- if (otherUser) {
- const relationship = await Relationship.findOne({
- where: [
- { from_id: req.user_id, to_id: otherUser.id },
- { from_id: otherUser.id, to_id: req.user_id },
- ],
- });
+ // handle blocked users in dms
+ if (channel.recipients?.length == 2) {
+ const otherUser = channel.recipients.find((r) => r.user_id != req.user_id)?.user;
+ if (otherUser) {
+ const relationship = await Relationship.findOne({
+ where: [
+ { from_id: req.user_id, to_id: otherUser.id },
+ { from_id: otherUser.id, to_id: req.user_id },
+ ],
+ });
- if (relationship?.type === RelationshipType.blocked) {
- throw DiscordApiErrors.CANNOT_MESSAGE_USER;
- }
- }
- }
+ if (relationship?.type === RelationshipType.blocked) {
+ throw DiscordApiErrors.CANNOT_MESSAGE_USER;
+ }
+ }
+ }
- if (body.nonce) {
- const existing = await Message.findOne({
- where: {
- nonce: body.nonce,
- channel_id: channel.id,
- author_id: req.user_id,
- },
- });
- if (existing) {
- return res.json(existing);
- }
- }
+ if (body.nonce) {
+ const existing = await Message.findOne({
+ where: {
+ nonce: body.nonce,
+ channel_id: channel.id,
+ author_id: req.user_id,
+ },
+ });
+ if (existing) {
+ return res.json(existing);
+ }
+ }
- if (!req.rights.has(Rights.FLAGS.BYPASS_RATE_LIMITS)) {
- const limits = Config.get().limits;
- if (limits.absoluteRate.sendMessage.enabled) {
- const count = await Message.count({
- where: {
- channel_id,
- timestamp: MoreThan(new Date(Date.now() - limits.absoluteRate.sendMessage.window)),
- },
- });
+ if (!req.rights.has(Rights.FLAGS.BYPASS_RATE_LIMITS)) {
+ const limits = Config.get().limits;
+ if (limits.absoluteRate.sendMessage.enabled) {
+ const count = await Message.count({
+ where: {
+ channel_id,
+ timestamp: MoreThan(new Date(Date.now() - limits.absoluteRate.sendMessage.window)),
+ },
+ });
- if (count >= limits.absoluteRate.sendMessage.limit)
- throw FieldErrors({
- channel_id: {
- code: "TOO_MANY_MESSAGES",
- message: req.t("common:toomany.MESSAGE"),
- },
- });
- }
- }
+ if (count >= limits.absoluteRate.sendMessage.limit)
+ throw FieldErrors({
+ channel_id: {
+ code: "TOO_MANY_MESSAGES",
+ message: req.t("common:toomany.MESSAGE"),
+ },
+ });
+ }
+ }
- const files = (req.files as Express.Multer.File[]) ?? [];
- for (const currFile of files) {
- try {
- const file = await uploadFile(`/attachments/${channel.id}`, currFile);
- attachments.push(Attachment.create({ ...file, proxy_url: file.url }));
- } catch (error) {
- return res.status(400).json({ message: error?.toString() });
- }
- }
+ const files = (req.files as Express.Multer.File[]) ?? [];
+ for (const currFile of files) {
+ try {
+ const file = await uploadFile(`/attachments/${channel.id}`, currFile);
+ attachments.push(Attachment.create({ ...file, proxy_url: file.url }));
+ } catch (error) {
+ return res.status(400).json({ message: error?.toString() });
+ }
+ }
- const embeds = body.embeds || [];
- if (body.embed) embeds.push(body.embed);
- const message = await handleMessage({
- ...body,
- type: 0,
- pinned: false,
- author_id: req.user_id,
- embeds,
- channel_id,
- attachments,
- timestamp: new Date(),
- });
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- //@ts-ignore dont care2
- message.edited_timestamp = null;
+ const embeds = body.embeds || [];
+ if (body.embed) embeds.push(body.embed);
+ const message = await handleMessage({
+ ...body,
+ type: 0,
+ pinned: false,
+ author_id: req.user_id,
+ embeds,
+ channel_id,
+ attachments,
+ timestamp: new Date(),
+ });
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ //@ts-ignore dont care2
+ message.edited_timestamp = null;
- channel.last_message_id = message.id;
+ channel.last_message_id = message.id;
- if (channel.isDm()) {
- const channel_dto = await DmChannelDTO.from(channel);
+ if (channel.isDm()) {
+ const channel_dto = await DmChannelDTO.from(channel);
- // Only one recipients should be closed here, since in group DMs the recipient is deleted not closed
- await Promise.all(
- channel.recipients?.map((recipient) => {
- if (recipient.closed) {
- recipient.closed = false;
- return Promise.all([
- recipient.save(),
- emitEvent({
- event: "CHANNEL_CREATE",
- data: channel_dto.excludedRecipients([recipient.user_id]),
- user_id: recipient.user_id,
- }),
- ]);
- }
- }) || [],
- );
- }
+ // Only one recipients should be closed here, since in group DMs the recipient is deleted not closed
+ await Promise.all(
+ channel.recipients?.map((recipient) => {
+ if (recipient.closed) {
+ recipient.closed = false;
+ return Promise.all([
+ recipient.save(),
+ emitEvent({
+ event: "CHANNEL_CREATE",
+ data: channel_dto.excludedRecipients([recipient.user_id]),
+ user_id: recipient.user_id,
+ }),
+ ]);
+ }
+ }) || [],
+ );
+ }
- if (message.guild_id) {
- // handleMessage will fetch the Member, but only if they are not guild owner.
- // have to fetch ourselves otherwise.
- if (!message.member) {
- message.member = await Member.findOneOrFail({
- where: { id: req.user_id, guild_id: message.guild_id },
- relations: ["roles"],
- });
- }
+ if (message.guild_id) {
+ // handleMessage will fetch the Member, but only if they are not guild owner.
+ // have to fetch ourselves otherwise.
+ if (!message.member) {
+ message.member = await Member.findOneOrFail({
+ where: { id: req.user_id, guild_id: message.guild_id },
+ relations: ["roles"],
+ });
+ }
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- message.member.roles = message.member.roles.filter((x) => x.id != x.guild_id).map((x) => x.id);
- }
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ message.member.roles = message.member.roles.filter((x) => x.id != x.guild_id).map((x) => x.id);
+ }
- let read_state = await ReadState.findOne({
- where: { user_id: req.user_id, channel_id },
- });
- if (!read_state) read_state = ReadState.create({ user_id: req.user_id, channel_id });
- read_state.last_message_id = message.id;
- //It's a little more complicated than this but this'll do
- read_state.mention_count = 0;
+ let read_state = await ReadState.findOne({
+ where: { user_id: req.user_id, channel_id },
+ });
+ if (!read_state) read_state = ReadState.create({ user_id: req.user_id, channel_id });
+ read_state.last_message_id = message.id;
+ //It's a little more complicated than this but this'll do
+ read_state.mention_count = 0;
- await Promise.all([
- read_state.save(),
- message.save(),
- emitEvent({
- event: "MESSAGE_CREATE",
- channel_id: channel_id,
- data: message,
- } as MessageCreateEvent),
- message.guild_id ? Member.update({ id: req.user_id, guild_id: message.guild_id }, { last_message_id: message.id }) : null,
- channel.save(),
- ]);
+ await Promise.all([
+ read_state.save(),
+ message.save(),
+ emitEvent({
+ event: "MESSAGE_CREATE",
+ channel_id: channel_id,
+ data: message,
+ } as MessageCreateEvent),
+ message.guild_id ? Member.update({ id: req.user_id, guild_id: message.guild_id }, { last_message_id: message.id }) : null,
+ channel.save(),
+ ]);
- // no await as it shouldnt block the message send function and silently catch error
- postHandleMessage(message).catch((e) => console.error("[Message] post-message handler failed", e));
+ // no await as it shouldnt block the message send function and silently catch error
+ postHandleMessage(message).catch((e) => console.error("[Message] post-message handler failed", e));
- return res.json(
- message.withSignedAttachments(
- new NewUrlUserSignatureData({
- ip: req.ip,
- userAgent: req.headers["user-agent"] as string,
- }),
- ),
- );
- },
+ return res.json(
+ message.withSignedAttachments(
+ new NewUrlUserSignatureData({
+ ip: req.ip,
+ userAgent: req.headers["user-agent"] as string,
+ }),
+ ),
+ );
+ },
);
router.delete(
- "/ack",
- route({
- requestBody: "AcknowledgeDeleteSchema",
- responses: {
- 204: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id } = req.params; // not really a channel id if read_state_type != CHANNEL
- const body = req.body as AcknowledgeDeleteSchema;
- if (body.version != 2) return res.status(204).send();
- // TODO: handle other read state types
- if (body.read_state_type != ReadStateType.CHANNEL) return res.status(204).send();
+ "/ack",
+ route({
+ requestBody: "AcknowledgeDeleteSchema",
+ responses: {
+ 204: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id } = req.params; // not really a channel id if read_state_type != CHANNEL
+ const body = req.body as AcknowledgeDeleteSchema;
+ if (body.version != 2) return res.status(204).send();
+ // TODO: handle other read state types
+ if (body.read_state_type != ReadStateType.CHANNEL) return res.status(204).send();
- const readState = await ReadState.findOne({ where: { channel_id, user_id: req.user_id } });
- if (readState) {
- await readState.remove();
- }
+ const readState = await ReadState.findOne({ where: { channel_id, user_id: req.user_id } });
+ if (readState) {
+ await readState.remove();
+ }
- res.status(204).send();
- },
+ res.status(204).send();
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/messages/pins/index.ts" "b/src/api/routes/channels/\043channel_id/messages/pins/index.ts"
index 1d770bd..2355c8b 100644
--- "a/src/api/routes/channels/\043channel_id/messages/pins/index.ts"
+++ "b/src/api/routes/channels/\043channel_id/messages/pins/index.ts"
@@ -24,169 +24,169 @@
const router: Router = Router({ mergeParams: true });
router.put(
- "/:message_id",
- route({
- permission: "VIEW_CHANNEL",
- responses: {
- 204: {},
- 403: {},
- 404: {},
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id, message_id } = req.params;
+ "/:message_id",
+ route({
+ permission: "VIEW_CHANNEL",
+ responses: {
+ 204: {},
+ 403: {},
+ 404: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id, message_id } = req.params;
- const message = await Message.findOneOrFail({
- where: { id: message_id },
- relations: ["author"],
- });
+ const message = await Message.findOneOrFail({
+ where: { id: message_id },
+ relations: ["author"],
+ });
- // * in dm channels anyone can pin messages -> only check for guilds
- if (message.guild_id) req.permission?.hasThrow("MANAGE_MESSAGES");
+ // * in dm channels anyone can pin messages -> only check for guilds
+ if (message.guild_id) req.permission?.hasThrow("MANAGE_MESSAGES");
- const pinned_count = await Message.count({
- where: { channel: { id: channel_id }, pinned_at: Not(IsNull()) },
- });
+ const pinned_count = await Message.count({
+ where: { channel: { id: channel_id }, pinned_at: Not(IsNull()) },
+ });
- const { maxPins } = Config.get().limits.channel;
- if (pinned_count >= maxPins) throw DiscordApiErrors.MAXIMUM_PINS.withParams(maxPins);
+ const { maxPins } = Config.get().limits.channel;
+ if (pinned_count >= maxPins) throw DiscordApiErrors.MAXIMUM_PINS.withParams(maxPins);
- message.pinned_at = new Date();
+ message.pinned_at = new Date();
- const author = await User.getPublicUser(req.user_id);
+ const author = await User.getPublicUser(req.user_id);
- const systemPinMessage = Message.create({
- timestamp: new Date(),
- type: 6,
- guild_id: message.guild_id,
- channel_id: message.channel_id,
- author,
- message_reference: {
- message_id: message.id,
- channel_id: message.channel_id,
- guild_id: message.guild_id,
- },
- reactions: [],
- attachments: [],
- embeds: [],
- sticker_items: [],
- edited_timestamp: undefined,
- mentions: [],
- mention_channels: [],
- mention_roles: [],
- mention_everyone: false,
- });
+ const systemPinMessage = Message.create({
+ timestamp: new Date(),
+ type: 6,
+ guild_id: message.guild_id,
+ channel_id: message.channel_id,
+ author,
+ message_reference: {
+ message_id: message.id,
+ channel_id: message.channel_id,
+ guild_id: message.guild_id,
+ },
+ reactions: [],
+ attachments: [],
+ embeds: [],
+ sticker_items: [],
+ edited_timestamp: undefined,
+ mentions: [],
+ mention_channels: [],
+ mention_roles: [],
+ mention_everyone: false,
+ });
- await Promise.all([
- message.save(),
- emitEvent({
- event: "MESSAGE_UPDATE",
- channel_id,
- data: message,
- } as MessageUpdateEvent),
- emitEvent({
- event: "CHANNEL_PINS_UPDATE",
- channel_id,
- data: {
- channel_id,
- guild_id: message.guild_id,
- last_pin_timestamp: undefined,
- },
- } as ChannelPinsUpdateEvent),
- systemPinMessage.save(),
- emitEvent({
- event: "MESSAGE_CREATE",
- channel_id: message.channel_id,
- data: systemPinMessage,
- } as MessageCreateEvent),
- ]);
+ await Promise.all([
+ message.save(),
+ emitEvent({
+ event: "MESSAGE_UPDATE",
+ channel_id,
+ data: message,
+ } as MessageUpdateEvent),
+ emitEvent({
+ event: "CHANNEL_PINS_UPDATE",
+ channel_id,
+ data: {
+ channel_id,
+ guild_id: message.guild_id,
+ last_pin_timestamp: undefined,
+ },
+ } as ChannelPinsUpdateEvent),
+ systemPinMessage.save(),
+ emitEvent({
+ event: "MESSAGE_CREATE",
+ channel_id: message.channel_id,
+ data: systemPinMessage,
+ } as MessageCreateEvent),
+ ]);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
router.delete(
- "/:message_id",
- route({
- permission: "VIEW_CHANNEL",
- responses: {
- 204: {},
- 403: {},
- 404: {},
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id, message_id } = req.params;
+ "/:message_id",
+ route({
+ permission: "VIEW_CHANNEL",
+ responses: {
+ 204: {},
+ 403: {},
+ 404: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id, message_id } = req.params;
- const message = await Message.findOneOrFail({
- where: { id: message_id },
- relations: ["author"],
- });
+ const message = await Message.findOneOrFail({
+ where: { id: message_id },
+ relations: ["author"],
+ });
- if (message.guild_id) req.permission?.hasThrow("MANAGE_MESSAGES");
+ if (message.guild_id) req.permission?.hasThrow("MANAGE_MESSAGES");
- message.pinned_at = null;
+ message.pinned_at = null;
- await Promise.all([
- message.save(),
- emitEvent({
- event: "MESSAGE_UPDATE",
- channel_id,
- data: message,
- } as MessageUpdateEvent),
- emitEvent({
- event: "CHANNEL_PINS_UPDATE",
- channel_id,
- data: {
- channel_id,
- guild_id: message.guild_id,
- last_pin_timestamp: undefined,
- },
- } as ChannelPinsUpdateEvent),
- ]);
+ await Promise.all([
+ message.save(),
+ emitEvent({
+ event: "MESSAGE_UPDATE",
+ channel_id,
+ data: message,
+ } as MessageUpdateEvent),
+ emitEvent({
+ event: "CHANNEL_PINS_UPDATE",
+ channel_id,
+ data: {
+ channel_id,
+ guild_id: message.guild_id,
+ last_pin_timestamp: undefined,
+ },
+ } as ChannelPinsUpdateEvent),
+ ]);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
router.get(
- "/",
- route({
- permission: ["READ_MESSAGE_HISTORY"],
- responses: {
- 200: {
- body: "APIMessageArray",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id } = req.params;
+ "/",
+ route({
+ permission: ["READ_MESSAGE_HISTORY"],
+ responses: {
+ 200: {
+ body: "APIMessageArray",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id } = req.params;
- const pins = await Message.find({
- where: { channel_id: channel_id, pinned_at: Not(IsNull()) },
- relations: ["author"],
- order: { pinned_at: "DESC" },
- });
+ const pins = await Message.find({
+ where: { channel_id: channel_id, pinned_at: Not(IsNull()) },
+ relations: ["author"],
+ order: { pinned_at: "DESC" },
+ });
- const items = pins.map((message: Message) => ({
- message,
- pinned_at: message.pinned_at,
- }));
+ const items = pins.map((message: Message) => ({
+ message,
+ pinned_at: message.pinned_at,
+ }));
- res.send({
- items,
- has_more: false,
- });
- },
+ res.send({
+ items,
+ has_more: false,
+ });
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/messages/search.ts" "b/src/api/routes/channels/\043channel_id/messages/search.ts"
index 7331945..bec9a44 100644
--- "a/src/api/routes/channels/\043channel_id/messages/search.ts"
+++ "b/src/api/routes/channels/\043channel_id/messages/search.ts"
@@ -27,116 +27,116 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "GuildMessagesSearchResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 422: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id } = req.params;
- const channel = await Channel.findOneOrFail({
- where: { guild_id: req.params.guild_id },
- select: ["id"],
- });
- const {
- content,
- // include_nsfw, // TODO
- offset,
- sort_order,
- // sort_by, // TODO: Handle 'relevance'
- limit,
- author_id,
- } = req.query;
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "GuildMessagesSearchResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 422: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id } = req.params;
+ const channel = await Channel.findOneOrFail({
+ where: { guild_id: req.params.guild_id },
+ select: ["id"],
+ });
+ const {
+ content,
+ // include_nsfw, // TODO
+ offset,
+ sort_order,
+ // sort_by, // TODO: Handle 'relevance'
+ limit,
+ author_id,
+ } = req.query;
- const parsedLimit = Number(limit) || 50;
- if (parsedLimit < 1 || parsedLimit > 100) throw new HTTPError("limit must be between 1 and 100", 422);
+ const parsedLimit = Number(limit) || 50;
+ if (parsedLimit < 1 || parsedLimit > 100) throw new HTTPError("limit must be between 1 and 100", 422);
- if (sort_order) {
- if (typeof sort_order != "string" || ["desc", "asc"].indexOf(sort_order) == -1)
- throw FieldErrors({
- sort_order: {
- message: "Value must be one of ('desc', 'asc').",
- code: "BASE_TYPE_CHOICES",
- },
- }); // todo this is wrong
- }
+ if (sort_order) {
+ if (typeof sort_order != "string" || ["desc", "asc"].indexOf(sort_order) == -1)
+ throw FieldErrors({
+ sort_order: {
+ message: "Value must be one of ('desc', 'asc').",
+ code: "BASE_TYPE_CHOICES",
+ },
+ }); // todo this is wrong
+ }
- const permissions = await getPermission(req.user_id, channel.guild_id, channel_id as string | undefined);
- permissions.hasThrow("VIEW_CHANNEL");
- if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json({ messages: [], total_results: 0 });
+ const permissions = await getPermission(req.user_id, channel.guild_id, channel_id as string | undefined);
+ permissions.hasThrow("VIEW_CHANNEL");
+ if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json({ messages: [], total_results: 0 });
- const query: FindManyOptions = {
- order: {
- timestamp: sort_order ? (sort_order.toUpperCase() as "ASC" | "DESC") : "DESC",
- },
- take: parsedLimit || 0,
- where: {
- guild: {
- id: channel.guild_id,
- },
- channel: {
- id: channel_id,
- },
- },
- relations: ["author", "webhook", "application", "mentions", "mention_roles", "mention_channels", "sticker_items", "attachments"],
- skip: offset ? Number(offset) : 0,
- };
- //@ts-ignore
- query.where.channel = { id: channel_id };
+ const query: FindManyOptions = {
+ order: {
+ timestamp: sort_order ? (sort_order.toUpperCase() as "ASC" | "DESC") : "DESC",
+ },
+ take: parsedLimit || 0,
+ where: {
+ guild: {
+ id: channel.guild_id,
+ },
+ channel: {
+ id: channel_id,
+ },
+ },
+ relations: ["author", "webhook", "application", "mentions", "mention_roles", "mention_channels", "sticker_items", "attachments"],
+ skip: offset ? Number(offset) : 0,
+ };
+ //@ts-ignore
+ query.where.channel = { id: channel_id };
- //@ts-ignore
- if (author_id) query.where.author = { id: author_id };
- //@ts-ignore
- if (content) query.where.content = Like(`%${content}%`);
+ //@ts-ignore
+ if (author_id) query.where.author = { id: author_id };
+ //@ts-ignore
+ if (content) query.where.content = Like(`%${content}%`);
- const messages: Message[] = await Message.find(query);
- delete query.take;
- const total_results = await Message.count(query);
+ const messages: Message[] = await Message.find(query);
+ delete query.take;
+ const total_results = await Message.count(query);
- const messagesDto = messages.map((x) => [
- {
- id: x.id,
- type: x.type,
- content: x.content,
- channel_id: x.channel_id,
- author: {
- id: x.author?.id,
- username: x.author?.username,
- avatar: x.author?.avatar,
- avatar_decoration: null,
- discriminator: x.author?.discriminator,
- public_flags: x.author?.public_flags,
- },
- attachments: x.attachments,
- embeds: x.embeds,
- mentions: x.mentions,
- mention_roles: x.mention_roles,
- pinned: x.pinned,
- mention_everyone: x.mention_everyone,
- tts: x.tts,
- timestamp: x.timestamp,
- edited_timestamp: x.edited_timestamp,
- flags: x.flags,
- components: x.components,
- poll: x.poll,
- hit: true,
- },
- ]);
+ const messagesDto = messages.map((x) => [
+ {
+ id: x.id,
+ type: x.type,
+ content: x.content,
+ channel_id: x.channel_id,
+ author: {
+ id: x.author?.id,
+ username: x.author?.username,
+ avatar: x.author?.avatar,
+ avatar_decoration: null,
+ discriminator: x.author?.discriminator,
+ public_flags: x.author?.public_flags,
+ },
+ attachments: x.attachments,
+ embeds: x.embeds,
+ mentions: x.mentions,
+ mention_roles: x.mention_roles,
+ pinned: x.pinned,
+ mention_everyone: x.mention_everyone,
+ tts: x.tts,
+ timestamp: x.timestamp,
+ edited_timestamp: x.edited_timestamp,
+ flags: x.flags,
+ components: x.components,
+ poll: x.poll,
+ hit: true,
+ },
+ ]);
- return res.json({
- messages: messagesDto,
- total_results,
- });
- },
+ return res.json({
+ messages: messagesDto,
+ total_results,
+ });
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/permissions.ts" "b/src/api/routes/channels/\043channel_id/permissions.ts"
index b45ff14..c03ca03 100644
--- "a/src/api/routes/channels/\043channel_id/permissions.ts"
+++ "b/src/api/routes/channels/\043channel_id/permissions.ts"
@@ -27,80 +27,80 @@
// TODO: Only permissions your bot has in the guild or channel can be allowed/denied (unless your bot has a MANAGE_ROLES overwrite in the channel)
router.put(
- "/:overwrite_id",
- route({
- requestBody: "ChannelPermissionOverwriteSchema",
- permission: "MANAGE_ROLES",
- responses: {
- 204: {},
- 404: {},
- 501: {},
- 400: { body: "APIErrorResponse" },
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id, overwrite_id } = req.params;
- const body = req.body as ChannelPermissionOverwriteSchema;
+ "/:overwrite_id",
+ route({
+ requestBody: "ChannelPermissionOverwriteSchema",
+ permission: "MANAGE_ROLES",
+ responses: {
+ 204: {},
+ 404: {},
+ 501: {},
+ 400: { body: "APIErrorResponse" },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id, overwrite_id } = req.params;
+ const body = req.body as ChannelPermissionOverwriteSchema;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
- if (!channel.guild_id) throw new HTTPError("Channel not found", 404);
- channel.position = await Channel.calculatePosition(channel_id, channel.guild_id, channel.guild);
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
+ if (!channel.guild_id) throw new HTTPError("Channel not found", 404);
+ channel.position = await Channel.calculatePosition(channel_id, channel.guild_id, channel.guild);
- if (body.type === ChannelPermissionOverwriteType.role) {
- if (!(await Role.count({ where: { id: overwrite_id } }))) throw new HTTPError("role not found", 404);
- } else if (body.type === ChannelPermissionOverwriteType.member) {
- if (!(await Member.count({ where: { id: overwrite_id } }))) throw new HTTPError("user not found", 404);
- } else throw new HTTPError("type not supported", 501);
+ if (body.type === ChannelPermissionOverwriteType.role) {
+ if (!(await Role.count({ where: { id: overwrite_id } }))) throw new HTTPError("role not found", 404);
+ } else if (body.type === ChannelPermissionOverwriteType.member) {
+ if (!(await Member.count({ where: { id: overwrite_id } }))) throw new HTTPError("user not found", 404);
+ } else throw new HTTPError("type not supported", 501);
- let overwrite: ChannelPermissionOverwrite | undefined = channel.permission_overwrites?.find((x) => x.id === overwrite_id);
- if (!overwrite) {
- overwrite = {
- id: overwrite_id,
- type: body.type,
- allow: "0",
- deny: "0",
- };
- channel.permission_overwrites?.push(overwrite);
- }
- overwrite.allow = String((req.permission?.bitfield || 0n) & (BigInt(body.allow) || BigInt("0")));
- overwrite.deny = String((req.permission?.bitfield || 0n) & (BigInt(body.deny) || BigInt("0")));
+ let overwrite: ChannelPermissionOverwrite | undefined = channel.permission_overwrites?.find((x) => x.id === overwrite_id);
+ if (!overwrite) {
+ overwrite = {
+ id: overwrite_id,
+ type: body.type,
+ allow: "0",
+ deny: "0",
+ };
+ channel.permission_overwrites?.push(overwrite);
+ }
+ overwrite.allow = String((req.permission?.bitfield || 0n) & (BigInt(body.allow) || BigInt("0")));
+ overwrite.deny = String((req.permission?.bitfield || 0n) & (BigInt(body.deny) || BigInt("0")));
- await Promise.all([
- channel.save(),
- emitEvent({
- event: "CHANNEL_UPDATE",
- channel_id,
- data: channel,
- } as ChannelUpdateEvent),
- ]);
+ await Promise.all([
+ channel.save(),
+ emitEvent({
+ event: "CHANNEL_UPDATE",
+ channel_id,
+ data: channel,
+ } as ChannelUpdateEvent),
+ ]);
- return res.sendStatus(204);
- },
+ return res.sendStatus(204);
+ },
);
// TODO: check permission hierarchy
router.delete("/:overwrite_id", route({ permission: "MANAGE_ROLES", responses: { 204: {}, 404: {} } }), async (req: Request, res: Response) => {
- const { channel_id, overwrite_id } = req.params;
+ const { channel_id, overwrite_id } = req.params;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
- if (!channel.guild_id) throw new HTTPError("Channel not found", 404);
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
+ if (!channel.guild_id) throw new HTTPError("Channel not found", 404);
- channel.permission_overwrites = channel.permission_overwrites?.filter((x) => x.id !== overwrite_id);
+ channel.permission_overwrites = channel.permission_overwrites?.filter((x) => x.id !== overwrite_id);
- await Promise.all([
- channel.save(),
- emitEvent({
- event: "CHANNEL_UPDATE",
- channel_id,
- data: channel,
- } as ChannelUpdateEvent),
- ]);
+ await Promise.all([
+ channel.save(),
+ emitEvent({
+ event: "CHANNEL_UPDATE",
+ channel_id,
+ data: channel,
+ } as ChannelUpdateEvent),
+ ]);
- return res.sendStatus(204);
+ return res.sendStatus(204);
});
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/pins.ts" "b/src/api/routes/channels/\043channel_id/pins.ts"
index 4b62115..8e56a54 100644
--- "a/src/api/routes/channels/\043channel_id/pins.ts"
+++ "b/src/api/routes/channels/\043channel_id/pins.ts"
@@ -25,161 +25,161 @@
// This is the old endpoint
router.put(
- "/:message_id",
- route({
- permission: "VIEW_CHANNEL",
- responses: {
- 204: {},
- 403: {},
- 404: {},
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id, message_id } = req.params;
+ "/:message_id",
+ route({
+ permission: "VIEW_CHANNEL",
+ responses: {
+ 204: {},
+ 403: {},
+ 404: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id, message_id } = req.params;
- const message = await Message.findOneOrFail({
- where: { id: message_id },
- relations: ["author"],
- });
+ const message = await Message.findOneOrFail({
+ where: { id: message_id },
+ relations: ["author"],
+ });
- // * in dm channels anyone can pin messages -> only check for guilds
- if (message.guild_id) req.permission?.hasThrow("MANAGE_MESSAGES");
+ // * in dm channels anyone can pin messages -> only check for guilds
+ if (message.guild_id) req.permission?.hasThrow("MANAGE_MESSAGES");
- const pinned_count = await Message.count({
- where: { channel: { id: channel_id }, pinned_at: Not(IsNull()) },
- });
+ const pinned_count = await Message.count({
+ where: { channel: { id: channel_id }, pinned_at: Not(IsNull()) },
+ });
- const { maxPins } = Config.get().limits.channel;
- if (pinned_count >= maxPins) throw DiscordApiErrors.MAXIMUM_PINS.withParams(maxPins);
+ const { maxPins } = Config.get().limits.channel;
+ if (pinned_count >= maxPins) throw DiscordApiErrors.MAXIMUM_PINS.withParams(maxPins);
- message.pinned_at = new Date();
+ message.pinned_at = new Date();
- const author = await User.getPublicUser(req.user_id);
+ const author = await User.getPublicUser(req.user_id);
- const systemPinMessage = Message.create({
- timestamp: new Date(),
- type: 6,
- guild_id: message.guild_id,
- channel_id: message.channel_id,
- author,
- message_reference: {
- message_id: message.id,
- channel_id: message.channel_id,
- guild_id: message.guild_id,
- },
- reactions: [],
- attachments: [],
- embeds: [],
- sticker_items: [],
- edited_timestamp: undefined,
- mentions: [],
- mention_channels: [],
- mention_roles: [],
- mention_everyone: false,
- });
+ const systemPinMessage = Message.create({
+ timestamp: new Date(),
+ type: 6,
+ guild_id: message.guild_id,
+ channel_id: message.channel_id,
+ author,
+ message_reference: {
+ message_id: message.id,
+ channel_id: message.channel_id,
+ guild_id: message.guild_id,
+ },
+ reactions: [],
+ attachments: [],
+ embeds: [],
+ sticker_items: [],
+ edited_timestamp: undefined,
+ mentions: [],
+ mention_channels: [],
+ mention_roles: [],
+ mention_everyone: false,
+ });
- await Promise.all([
- message.save(),
- emitEvent({
- event: "MESSAGE_UPDATE",
- channel_id,
- data: message,
- } as MessageUpdateEvent),
- emitEvent({
- event: "CHANNEL_PINS_UPDATE",
- channel_id,
- data: {
- channel_id,
- guild_id: message.guild_id,
- last_pin_timestamp: undefined,
- },
- } as ChannelPinsUpdateEvent),
- systemPinMessage.save(),
- emitEvent({
- event: "MESSAGE_CREATE",
- channel_id: message.channel_id,
- data: systemPinMessage,
- } as MessageCreateEvent),
- ]);
+ await Promise.all([
+ message.save(),
+ emitEvent({
+ event: "MESSAGE_UPDATE",
+ channel_id,
+ data: message,
+ } as MessageUpdateEvent),
+ emitEvent({
+ event: "CHANNEL_PINS_UPDATE",
+ channel_id,
+ data: {
+ channel_id,
+ guild_id: message.guild_id,
+ last_pin_timestamp: undefined,
+ },
+ } as ChannelPinsUpdateEvent),
+ systemPinMessage.save(),
+ emitEvent({
+ event: "MESSAGE_CREATE",
+ channel_id: message.channel_id,
+ data: systemPinMessage,
+ } as MessageCreateEvent),
+ ]);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
router.delete(
- "/:message_id",
- route({
- permission: "VIEW_CHANNEL",
- responses: {
- 204: {},
- 403: {},
- 404: {},
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id, message_id } = req.params;
+ "/:message_id",
+ route({
+ permission: "VIEW_CHANNEL",
+ responses: {
+ 204: {},
+ 403: {},
+ 404: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id, message_id } = req.params;
- const message = await Message.findOneOrFail({
- where: { id: message_id },
- relations: ["author"],
- });
+ const message = await Message.findOneOrFail({
+ where: { id: message_id },
+ relations: ["author"],
+ });
- if (message.guild_id) req.permission?.hasThrow("MANAGE_MESSAGES");
+ if (message.guild_id) req.permission?.hasThrow("MANAGE_MESSAGES");
- message.pinned_at = null;
+ message.pinned_at = null;
- await Promise.all([
- message.save(),
- emitEvent({
- event: "MESSAGE_UPDATE",
- channel_id,
- data: message,
- } as MessageUpdateEvent),
- emitEvent({
- event: "CHANNEL_PINS_UPDATE",
- channel_id,
- data: {
- channel_id,
- guild_id: message.guild_id,
- last_pin_timestamp: undefined,
- },
- } as ChannelPinsUpdateEvent),
- ]);
+ await Promise.all([
+ message.save(),
+ emitEvent({
+ event: "MESSAGE_UPDATE",
+ channel_id,
+ data: message,
+ } as MessageUpdateEvent),
+ emitEvent({
+ event: "CHANNEL_PINS_UPDATE",
+ channel_id,
+ data: {
+ channel_id,
+ guild_id: message.guild_id,
+ last_pin_timestamp: undefined,
+ },
+ } as ChannelPinsUpdateEvent),
+ ]);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
router.get(
- "/",
- route({
- permission: ["READ_MESSAGE_HISTORY"],
- responses: {
- 200: {
- body: "APIMessageArray",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id } = req.params;
+ "/",
+ route({
+ permission: ["READ_MESSAGE_HISTORY"],
+ responses: {
+ 200: {
+ body: "APIMessageArray",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id } = req.params;
- const pins = await Message.find({
- where: { channel_id: channel_id, pinned_at: Not(IsNull()) },
- relations: ["author"],
- order: { pinned_at: "DESC" },
- });
+ const pins = await Message.find({
+ where: { channel_id: channel_id, pinned_at: Not(IsNull()) },
+ relations: ["author"],
+ order: { pinned_at: "DESC" },
+ });
- res.send(pins);
- },
+ res.send(pins);
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/purge.ts" "b/src/api/routes/channels/\043channel_id/purge.ts"
index 9686bc2..3a46beb 100644
--- "a/src/api/routes/channels/\043channel_id/purge.ts"
+++ "b/src/api/routes/channels/\043channel_id/purge.ts"
@@ -31,71 +31,71 @@
TODO: apply the delete bit by bit to prevent client and database stress
**/
router.post(
- "/",
- route({
- /*body: "PurgeSchema",*/
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {},
- 403: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id } = req.params;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
+ "/",
+ route({
+ /*body: "PurgeSchema",*/
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {},
+ 403: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id } = req.params;
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
- if (!channel.guild_id) throw new HTTPError("Can't purge dm channels", 400);
- isTextChannel(channel.type);
+ if (!channel.guild_id) throw new HTTPError("Can't purge dm channels", 400);
+ isTextChannel(channel.type);
- const rights = await getRights(req.user_id);
- if (!rights.has("MANAGE_MESSAGES")) {
- const permissions = await getPermission(req.user_id, channel.guild_id, channel_id);
- permissions.hasThrow("MANAGE_MESSAGES");
- permissions.hasThrow("MANAGE_CHANNELS");
- }
+ const rights = await getRights(req.user_id);
+ if (!rights.has("MANAGE_MESSAGES")) {
+ const permissions = await getPermission(req.user_id, channel.guild_id, channel_id);
+ permissions.hasThrow("MANAGE_MESSAGES");
+ permissions.hasThrow("MANAGE_CHANNELS");
+ }
- const { before, after } = req.body as PurgeSchema;
+ const { before, after } = req.body as PurgeSchema;
- // TODO: send the deletion event bite-by-bite to prevent client stress
+ // TODO: send the deletion event bite-by-bite to prevent client stress
- const query: FindManyOptions & {
- where: { id?: FindOperator };
- } = {
- order: { id: "ASC" },
- // take: limit,
- where: {
- channel_id,
- id: Between(after, before), // the right way around
- author_id: rights.has("SELF_DELETE_MESSAGES") ? undefined : Not(req.user_id),
- // if you lack the right of self-deletion, you can't delete your own messages, even in purges
- },
- relations: ["author", "webhook", "application", "mentions", "mention_roles", "mention_channels", "sticker_items", "attachments"],
- };
+ const query: FindManyOptions & {
+ where: { id?: FindOperator };
+ } = {
+ order: { id: "ASC" },
+ // take: limit,
+ where: {
+ channel_id,
+ id: Between(after, before), // the right way around
+ author_id: rights.has("SELF_DELETE_MESSAGES") ? undefined : Not(req.user_id),
+ // if you lack the right of self-deletion, you can't delete your own messages, even in purges
+ },
+ relations: ["author", "webhook", "application", "mentions", "mention_roles", "mention_channels", "sticker_items", "attachments"],
+ };
- const messages = await Message.find(query);
+ const messages = await Message.find(query);
- if (messages.length == 0) {
- res.sendStatus(304);
- return;
- }
+ if (messages.length == 0) {
+ res.sendStatus(304);
+ return;
+ }
- await Message.delete(messages.map((x) => x.id));
+ await Message.delete(messages.map((x) => x.id));
- await emitEvent({
- event: "MESSAGE_DELETE_BULK",
- channel_id,
- data: {
- ids: messages.map((x) => x.id),
- channel_id,
- guild_id: channel.guild_id,
- },
- } as MessageDeleteBulkEvent);
+ await emitEvent({
+ event: "MESSAGE_DELETE_BULK",
+ channel_id,
+ data: {
+ ids: messages.map((x) => x.id),
+ channel_id,
+ guild_id: channel.guild_id,
+ },
+ } as MessageDeleteBulkEvent);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
diff --git "a/src/api/routes/channels/\043channel_id/recipients.ts" "b/src/api/routes/channels/\043channel_id/recipients.ts"
index 6388cfe..d0af3b4 100644
--- "a/src/api/routes/channels/\043channel_id/recipients.ts"
+++ "b/src/api/routes/channels/\043channel_id/recipients.ts"
@@ -24,79 +24,79 @@
const router: Router = Router({ mergeParams: true });
router.put(
- "/:user_id",
- route({
- responses: {
- 201: {},
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id, user_id } = req.params;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- relations: ["recipients"],
- });
+ "/:user_id",
+ route({
+ responses: {
+ 201: {},
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id, user_id } = req.params;
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ relations: ["recipients"],
+ });
- if (channel.type !== ChannelType.GROUP_DM) {
- const recipients = [...new Set([...(channel.recipients?.map((r) => r.user_id) || []), user_id])];
+ if (channel.type !== ChannelType.GROUP_DM) {
+ const recipients = [...new Set([...(channel.recipients?.map((r) => r.user_id) || []), user_id])];
- const new_channel = await Channel.createDMChannel(recipients, req.user_id);
- return res.status(201).json(new_channel);
- } else {
- if (channel.recipients?.map((r) => r.user_id).includes(user_id)) {
- throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
- }
+ const new_channel = await Channel.createDMChannel(recipients, req.user_id);
+ return res.status(201).json(new_channel);
+ } else {
+ if (channel.recipients?.map((r) => r.user_id).includes(user_id)) {
+ throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
+ }
- channel.recipients?.push(Recipient.create({ channel_id: channel_id, user_id: user_id }));
- await channel.save();
+ channel.recipients?.push(Recipient.create({ channel_id: channel_id, user_id: user_id }));
+ await channel.save();
- await emitEvent({
- event: "CHANNEL_CREATE",
- data: await DmChannelDTO.from(channel, [user_id]),
- user_id: user_id,
- });
+ await emitEvent({
+ event: "CHANNEL_CREATE",
+ data: await DmChannelDTO.from(channel, [user_id]),
+ user_id: user_id,
+ });
- await emitEvent({
- event: "CHANNEL_RECIPIENT_ADD",
- data: {
- channel_id: channel_id,
- user: await User.findOneOrFail({
- where: { id: user_id },
- select: PublicUserProjection,
- }),
- },
- channel_id: channel_id,
- } as ChannelRecipientAddEvent);
- return res.sendStatus(204);
- }
- },
+ await emitEvent({
+ event: "CHANNEL_RECIPIENT_ADD",
+ data: {
+ channel_id: channel_id,
+ user: await User.findOneOrFail({
+ where: { id: user_id },
+ select: PublicUserProjection,
+ }),
+ },
+ channel_id: channel_id,
+ } as ChannelRecipientAddEvent);
+ return res.sendStatus(204);
+ }
+ },
);
router.delete(
- "/:user_id",
- route({
- responses: {
- 204: {},
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id, user_id } = req.params;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- relations: ["recipients"],
- });
- if (!(channel.type === ChannelType.GROUP_DM && (channel.owner_id === req.user_id || user_id === req.user_id))) throw DiscordApiErrors.MISSING_PERMISSIONS;
+ "/:user_id",
+ route({
+ responses: {
+ 204: {},
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id, user_id } = req.params;
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ relations: ["recipients"],
+ });
+ if (!(channel.type === ChannelType.GROUP_DM && (channel.owner_id === req.user_id || user_id === req.user_id))) throw DiscordApiErrors.MISSING_PERMISSIONS;
- if (!channel.recipients?.map((r) => r.user_id).includes(user_id)) {
- throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
- }
+ if (!channel.recipients?.map((r) => r.user_id).includes(user_id)) {
+ throw DiscordApiErrors.INVALID_RECIPIENT; //TODO is this the right error?
+ }
- await Channel.removeRecipientFromChannel(channel, user_id);
+ await Channel.removeRecipientFromChannel(channel, user_id);
- return res.sendStatus(204);
- },
+ return res.sendStatus(204);
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/typing.ts" "b/src/api/routes/channels/\043channel_id/typing.ts"
index 8c36add..a41ab7f 100644
--- "a/src/api/routes/channels/\043channel_id/typing.ts"
+++ "b/src/api/routes/channels/\043channel_id/typing.ts"
@@ -23,47 +23,47 @@
const router: Router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- permission: "SEND_MESSAGES",
- responses: {
- 204: {},
- 404: {},
- 403: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id } = req.params;
- const user_id = req.user_id;
- const timestamp = Math.floor(Date.now() / 1000);
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
- const member = await Member.findOne({
- where: { id: user_id, guild_id: channel.guild_id },
- relations: ["roles", "user"],
- });
- await emitEvent({
- event: "TYPING_START",
- channel_id: channel_id,
- data: {
- ...(member
- ? {
- member: {
- ...member.toPublicMember(),
- roles: member?.roles?.map((x) => x.id),
- },
- }
- : null),
- channel_id,
- timestamp,
- user_id,
- guild_id: channel.guild_id,
- },
- } as TypingStartEvent);
+ "/",
+ route({
+ permission: "SEND_MESSAGES",
+ responses: {
+ 204: {},
+ 404: {},
+ 403: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id } = req.params;
+ const user_id = req.user_id;
+ const timestamp = Math.floor(Date.now() / 1000);
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
+ const member = await Member.findOne({
+ where: { id: user_id, guild_id: channel.guild_id },
+ relations: ["roles", "user"],
+ });
+ await emitEvent({
+ event: "TYPING_START",
+ channel_id: channel_id,
+ data: {
+ ...(member
+ ? {
+ member: {
+ ...member.toPublicMember(),
+ roles: member?.roles?.map((x) => x.id),
+ },
+ }
+ : null),
+ channel_id,
+ timestamp,
+ user_id,
+ guild_id: channel.guild_id,
+ },
+ } as TypingStartEvent);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
export default router;
diff --git "a/src/api/routes/channels/\043channel_id/webhooks.ts" "b/src/api/routes/channels/\043channel_id/webhooks.ts"
index 9d226b1..1c3c980 100644
--- "a/src/api/routes/channels/\043channel_id/webhooks.ts"
+++ "b/src/api/routes/channels/\043channel_id/webhooks.ts"
@@ -26,88 +26,88 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- description: "Returns a list of channel webhook objects. Requires the MANAGE_WEBHOOKS permission.",
- permission: "MANAGE_WEBHOOKS",
- responses: {
- 200: {
- body: "APIWebhookArray",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { channel_id } = req.params;
- const webhooks = await Webhook.find({
- where: { channel_id },
- relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
- });
+ "/",
+ route({
+ description: "Returns a list of channel webhook objects. Requires the MANAGE_WEBHOOKS permission.",
+ permission: "MANAGE_WEBHOOKS",
+ responses: {
+ 200: {
+ body: "APIWebhookArray",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { channel_id } = req.params;
+ const webhooks = await Webhook.find({
+ where: { channel_id },
+ relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
+ });
- return res.json(
- webhooks.map((webhook) => ({
- ...webhook,
- url: Config.get().api.endpointPublic + "/webhooks/" + webhook.id + "/" + webhook.token,
- })),
- );
- },
+ return res.json(
+ webhooks.map((webhook) => ({
+ ...webhook,
+ url: Config.get().api.endpointPublic + "/webhooks/" + webhook.id + "/" + webhook.token,
+ })),
+ );
+ },
);
// TODO: use Image Data Type for avatar instead of String
router.post(
- "/",
- route({
- requestBody: "WebhookCreateSchema",
- permission: "MANAGE_WEBHOOKS",
- responses: {
- 200: {
- body: "WebhookCreateResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {},
- },
- }),
- async (req: Request, res: Response) => {
- const channel_id = req.params.channel_id;
- const channel = await Channel.findOneOrFail({
- where: { id: channel_id },
- });
+ "/",
+ route({
+ requestBody: "WebhookCreateSchema",
+ permission: "MANAGE_WEBHOOKS",
+ responses: {
+ 200: {
+ body: "WebhookCreateResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const channel_id = req.params.channel_id;
+ const channel = await Channel.findOneOrFail({
+ where: { id: channel_id },
+ });
- isTextChannel(channel.type);
- if (!channel.guild_id) throw new HTTPError("Not a guild channel", 400);
+ isTextChannel(channel.type);
+ if (!channel.guild_id) throw new HTTPError("Not a guild channel", 400);
- const webhook_count = await Webhook.count({ where: { channel_id } });
- const { maxWebhooks } = Config.get().limits.channel;
- if (maxWebhooks && webhook_count > maxWebhooks) throw DiscordApiErrors.MAXIMUM_WEBHOOKS.withParams(maxWebhooks);
+ const webhook_count = await Webhook.count({ where: { channel_id } });
+ const { maxWebhooks } = Config.get().limits.channel;
+ if (maxWebhooks && webhook_count > maxWebhooks) throw DiscordApiErrors.MAXIMUM_WEBHOOKS.withParams(maxWebhooks);
- let { avatar, name } = req.body as WebhookCreateSchema;
- name = trimSpecial(name);
+ let { avatar, name } = req.body as WebhookCreateSchema;
+ name = trimSpecial(name);
- // TODO: move this
- if (name) {
- ValidateName(name);
- }
+ // TODO: move this
+ if (name) {
+ ValidateName(name);
+ }
- if (avatar) avatar = await handleFile(`/avatars/${channel_id}`, avatar);
+ if (avatar) avatar = await handleFile(`/avatars/${channel_id}`, avatar);
- const hook = await Webhook.create({
- type: WebhookType.Incoming,
- name,
- avatar,
- guild_id: channel.guild_id,
- channel_id: channel.id,
- user_id: req.user_id,
- token: crypto.randomBytes(24).toString("base64url"),
- }).save();
+ const hook = await Webhook.create({
+ type: WebhookType.Incoming,
+ name,
+ avatar,
+ guild_id: channel.guild_id,
+ channel_id: channel.id,
+ user_id: req.user_id,
+ token: crypto.randomBytes(24).toString("base64url"),
+ }).save();
- const user = await User.getPublicUser(req.user_id);
+ const user = await User.getPublicUser(req.user_id);
- return res.json({
- ...hook,
- user: user,
- });
- },
+ return res.json({
+ ...hook,
+ user: user,
+ });
+ },
);
export default router;
diff --git a/src/api/routes/channels/preload-messages.ts b/src/api/routes/channels/preload-messages.ts
index cdfc58f..6a19052 100644
--- a/src/api/routes/channels/preload-messages.ts
+++ b/src/api/routes/channels/preload-messages.ts
@@ -23,49 +23,49 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "PreloadMessagesRequestSchema",
- responses: {
- 200: {
- body: "PreloadMessagesResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as PreloadMessagesRequestSchema;
- if (body.channels.length > Config.get().limits.message.maxPreloadCount)
- return res.status(400).send({
- code: 400,
- message: `Cannot preload more than ${Config.get().limits.message.maxPreloadCount} channels at once.`,
- });
+ "/",
+ route({
+ requestBody: "PreloadMessagesRequestSchema",
+ responses: {
+ 200: {
+ body: "PreloadMessagesResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as PreloadMessagesRequestSchema;
+ if (body.channels.length > Config.get().limits.message.maxPreloadCount)
+ return res.status(400).send({
+ code: 400,
+ message: `Cannot preload more than ${Config.get().limits.message.maxPreloadCount} channels at once.`,
+ });
- const messages = (
- await Promise.all(
- body.channels.map(
- async (channelId) =>
- await Message.findOne({
- where: { channel_id: channelId },
- order: { timestamp: "DESC" },
- }),
- ),
- )
- ).filter((x) => x !== null) as Message[];
+ const messages = (
+ await Promise.all(
+ body.channels.map(
+ async (channelId) =>
+ await Message.findOne({
+ where: { channel_id: channelId },
+ order: { timestamp: "DESC" },
+ }),
+ ),
+ )
+ ).filter((x) => x !== null) as Message[];
- const filteredMessages = messages.map((message) => {
- const x = message.toJSON();
- // https://docs.discord.food/resources/message#preload-messages - reactions are not included in the response
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-expect-error
- x.reactions = undefined;
- return x;
- }) as PreloadMessagesResponseSchema;
+ const filteredMessages = messages.map((message) => {
+ const x = message.toJSON();
+ // https://docs.discord.food/resources/message#preload-messages - reactions are not included in the response
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-expect-error
+ x.reactions = undefined;
+ return x;
+ }) as PreloadMessagesResponseSchema;
- return res.status(200).send(filteredMessages);
- },
+ return res.status(200).send(filteredMessages);
+ },
);
export default router;
diff --git a/src/api/routes/collectibles-categories.ts b/src/api/routes/collectibles-categories.ts
index d2cac39..ffeff09 100644
--- a/src/api/routes/collectibles-categories.ts
+++ b/src/api/routes/collectibles-categories.ts
@@ -23,18 +23,18 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "CollectiblesCategoriesResponse",
- },
- 204: {},
- },
- }),
- (req: Request, res: Response) => {
- res.send([] as CollectiblesCategoriesResponse);
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "CollectiblesCategoriesResponse",
+ },
+ 204: {},
+ },
+ }),
+ (req: Request, res: Response) => {
+ res.send([] as CollectiblesCategoriesResponse);
+ },
);
export default router;
diff --git a/src/api/routes/collectibles-shop.ts b/src/api/routes/collectibles-shop.ts
index b4c82f5..756c80c 100644
--- a/src/api/routes/collectibles-shop.ts
+++ b/src/api/routes/collectibles-shop.ts
@@ -23,21 +23,21 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "CollectiblesShopResponse",
- },
- 204: {},
- },
- }),
- (req: Request, res: Response) => {
- res.send({
- shop_blocks: [],
- categories: [],
- } as CollectiblesShopResponse);
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "CollectiblesShopResponse",
+ },
+ 204: {},
+ },
+ }),
+ (req: Request, res: Response) => {
+ res.send({
+ shop_blocks: [],
+ categories: [],
+ } as CollectiblesShopResponse);
+ },
);
export default router;
diff --git "a/src/api/routes/connections/\043connection_name/\043connection_id/refresh.ts" "b/src/api/routes/connections/\043connection_name/\043connection_id/refresh.ts"
index 46f20ae..4a1a1cb 100644
--- "a/src/api/routes/connections/\043connection_name/\043connection_id/refresh.ts"
+++ "b/src/api/routes/connections/\043connection_name/\043connection_id/refresh.ts"
@@ -21,9 +21,9 @@
const router = Router({ mergeParams: true });
router.post("/", route({}), async (req: Request, res: Response) => {
- // TODO:
- // const { connection_name, connection_id } = req.params;
- res.sendStatus(204);
+ // TODO:
+ // const { connection_name, connection_id } = req.params;
+ res.sendStatus(204);
});
export default router;
diff --git "a/src/api/routes/connections/\043connection_name/authorize.ts" "b/src/api/routes/connections/\043connection_name/authorize.ts"
index b8e50db..1efb656 100644
--- "a/src/api/routes/connections/\043connection_name/authorize.ts"
+++ "b/src/api/routes/connections/\043connection_name/authorize.ts"
@@ -23,28 +23,28 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- const { connection_name } = req.params;
- const connection = ConnectionStore.connections.get(connection_name);
- if (!connection)
- throw FieldErrors({
- provider_id: {
- code: "BASE_TYPE_CHOICES",
- message: req.t("common:field.BASE_TYPE_CHOICES", {
- types: Array.from(ConnectionStore.connections.keys()).join(", "),
- }),
- },
- });
+ const { connection_name } = req.params;
+ const connection = ConnectionStore.connections.get(connection_name);
+ if (!connection)
+ throw FieldErrors({
+ provider_id: {
+ code: "BASE_TYPE_CHOICES",
+ message: req.t("common:field.BASE_TYPE_CHOICES", {
+ types: Array.from(ConnectionStore.connections.keys()).join(", "),
+ }),
+ },
+ });
- if (!connection.settings.enabled)
- throw FieldErrors({
- provider_id: {
- message: "This connection has been disabled server-side.",
- },
- });
+ if (!connection.settings.enabled)
+ throw FieldErrors({
+ provider_id: {
+ message: "This connection has been disabled server-side.",
+ },
+ });
- res.json({
- url: await connection.getAuthorizationUrl(req.user_id),
- });
+ res.json({
+ url: await connection.getAuthorizationUrl(req.user_id),
+ });
});
export default router;
diff --git "a/src/api/routes/connections/\043connection_name/callback.ts" "b/src/api/routes/connections/\043connection_name/callback.ts"
index 5732a8e..a83882c 100644
--- "a/src/api/routes/connections/\043connection_name/callback.ts"
+++ "b/src/api/routes/connections/\043connection_name/callback.ts"
@@ -24,38 +24,38 @@
const router = Router({ mergeParams: true });
router.post("/", route({ requestBody: "ConnectionCallbackSchema" }), async (req: Request, res: Response) => {
- const { connection_name } = req.params;
- const connection = ConnectionStore.connections.get(connection_name);
- if (!connection)
- throw FieldErrors({
- provider_id: {
- code: "BASE_TYPE_CHOICES",
- message: req.t("common:field.BASE_TYPE_CHOICES", {
- types: Array.from(ConnectionStore.connections.keys()).join(", "),
- }),
- },
- });
+ const { connection_name } = req.params;
+ const connection = ConnectionStore.connections.get(connection_name);
+ if (!connection)
+ throw FieldErrors({
+ provider_id: {
+ code: "BASE_TYPE_CHOICES",
+ message: req.t("common:field.BASE_TYPE_CHOICES", {
+ types: Array.from(ConnectionStore.connections.keys()).join(", "),
+ }),
+ },
+ });
- if (!connection.settings.enabled)
- throw FieldErrors({
- provider_id: {
- message: "This connection has been disabled server-side.",
- },
- });
+ if (!connection.settings.enabled)
+ throw FieldErrors({
+ provider_id: {
+ message: "This connection has been disabled server-side.",
+ },
+ });
- const body = req.body as ConnectionCallbackSchema;
- const userId = connection.getUserId(body.state);
- const connectedAccnt = await connection.handleCallback(body);
+ const body = req.body as ConnectionCallbackSchema;
+ const userId = connection.getUserId(body.state);
+ const connectedAccnt = await connection.handleCallback(body);
- // whether we should emit a connections update event, only used when a connection doesnt already exist
- if (connectedAccnt)
- emitEvent({
- event: "USER_CONNECTIONS_UPDATE",
- data: { ...connectedAccnt, token_data: undefined },
- user_id: userId,
- });
+ // whether we should emit a connections update event, only used when a connection doesnt already exist
+ if (connectedAccnt)
+ emitEvent({
+ event: "USER_CONNECTIONS_UPDATE",
+ data: { ...connectedAccnt, token_data: undefined },
+ user_id: userId,
+ });
- res.sendStatus(204);
+ res.sendStatus(204);
});
export default router;
diff --git a/src/api/routes/connections/index.ts b/src/api/routes/connections/index.ts
index b30d402..017ebbb 100644
--- a/src/api/routes/connections/index.ts
+++ b/src/api/routes/connections/index.ts
@@ -22,24 +22,24 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APIConnectionsConfiguration",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const config = ConnectionConfig.get();
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APIConnectionsConfiguration",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const config = ConnectionConfig.get();
- Object.keys(config).forEach((key) => {
- delete config[key].clientId;
- delete config[key].clientSecret;
- });
+ Object.keys(config).forEach((key) => {
+ delete config[key].clientId;
+ delete config[key].clientSecret;
+ });
- res.json(config);
- },
+ res.json(config);
+ },
);
export default router;
diff --git a/src/api/routes/discoverable-guilds.ts b/src/api/routes/discoverable-guilds.ts
index ce34aa0..dcecec3 100644
--- a/src/api/routes/discoverable-guilds.ts
+++ b/src/api/routes/discoverable-guilds.ts
@@ -25,52 +25,52 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "DiscoverableGuildsResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { offset, limit, categories } = req.query;
- const showAllGuilds = Config.get().guild.discovery.showAllGuilds;
- const configLimit = Config.get().guild.discovery.limit;
- let guilds;
- if (categories == undefined) {
- guilds = showAllGuilds
- ? await Guild.find({
- take: Math.abs(Number(limit || configLimit)),
- })
- : await Guild.find({
- where: { features: Like(`%DISCOVERABLE%`) },
- take: Math.abs(Number(limit || configLimit)),
- });
- } else {
- guilds = showAllGuilds
- ? await Guild.find({
- where: { primary_category_id: categories.toString() },
- take: Math.abs(Number(limit || configLimit)),
- })
- : await Guild.find({
- where: {
- primary_category_id: categories.toString(),
- features: Like("%DISCOVERABLE%"),
- },
- take: Math.abs(Number(limit || configLimit)),
- });
- }
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "DiscoverableGuildsResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { offset, limit, categories } = req.query;
+ const showAllGuilds = Config.get().guild.discovery.showAllGuilds;
+ const configLimit = Config.get().guild.discovery.limit;
+ let guilds;
+ if (categories == undefined) {
+ guilds = showAllGuilds
+ ? await Guild.find({
+ take: Math.abs(Number(limit || configLimit)),
+ })
+ : await Guild.find({
+ where: { features: Like(`%DISCOVERABLE%`) },
+ take: Math.abs(Number(limit || configLimit)),
+ });
+ } else {
+ guilds = showAllGuilds
+ ? await Guild.find({
+ where: { primary_category_id: categories.toString() },
+ take: Math.abs(Number(limit || configLimit)),
+ })
+ : await Guild.find({
+ where: {
+ primary_category_id: categories.toString(),
+ features: Like("%DISCOVERABLE%"),
+ },
+ take: Math.abs(Number(limit || configLimit)),
+ });
+ }
- const total = guilds ? guilds.length : undefined;
+ const total = guilds ? guilds.length : undefined;
- res.send({
- total: total,
- guilds: guilds,
- offset: Number(offset || Config.get().guild.discovery.offset),
- limit: Number(limit || configLimit),
- });
- },
+ res.send({
+ total: total,
+ guilds: guilds,
+ offset: Number(offset || Config.get().guild.discovery.offset),
+ limit: Number(limit || configLimit),
+ });
+ },
);
export default router;
diff --git a/src/api/routes/discovery.ts b/src/api/routes/discovery.ts
index cb1e3a9..d865dfe 100644
--- a/src/api/routes/discovery.ts
+++ b/src/api/routes/discovery.ts
@@ -23,25 +23,25 @@
const router = Router({ mergeParams: true });
router.get(
- "/categories",
- route({
- responses: {
- 200: {
- body: "APIDiscoveryCategoryArray",
- },
- },
- }),
- async (req: Request, res: Response) => {
- // TODO:
- // Get locale instead
+ "/categories",
+ route({
+ responses: {
+ 200: {
+ body: "APIDiscoveryCategoryArray",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ // TODO:
+ // Get locale instead
- // const { locale, primary_only } = req.query;
- const { primary_only } = req.query;
+ // const { locale, primary_only } = req.query;
+ const { primary_only } = req.query;
- const out = primary_only ? await Categories.find({ where: { is_primary: true } }) : await Categories.find();
+ const out = primary_only ? await Categories.find({ where: { is_primary: true } }) : await Categories.find();
- res.send(out);
- },
+ res.send(out);
+ },
);
export default router;
diff --git a/src/api/routes/download.ts b/src/api/routes/download.ts
index 0658832..f54a3bb 100644
--- a/src/api/routes/download.ts
+++ b/src/api/routes/download.ts
@@ -23,36 +23,36 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 302: {},
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { platform } = req.query;
+ "/",
+ route({
+ responses: {
+ 302: {},
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { platform } = req.query;
- if (!platform)
- throw FieldErrors({
- platform: {
- code: "BASE_TYPE_REQUIRED",
- message: req.t("common:field.BASE_TYPE_REQUIRED"),
- },
- });
+ if (!platform)
+ throw FieldErrors({
+ platform: {
+ code: "BASE_TYPE_REQUIRED",
+ message: req.t("common:field.BASE_TYPE_REQUIRED"),
+ },
+ });
- const release = await ClientRelease.findOneOrFail({
- where: {
- enabled: true,
- platform: platform as string,
- },
- order: { pub_date: "DESC" },
- });
+ const release = await ClientRelease.findOneOrFail({
+ where: {
+ enabled: true,
+ platform: platform as string,
+ },
+ order: { pub_date: "DESC" },
+ });
- res.redirect(release.url);
- },
+ res.redirect(release.url);
+ },
);
export default router;
diff --git "a/src/api/routes/emojis/\043emoji_id/source.ts" "b/src/api/routes/emojis/\043emoji_id/source.ts"
index 7a5e1c7..f5c4a83 100644
--- "a/src/api/routes/emojis/\043emoji_id/source.ts"
+++ "b/src/api/routes/emojis/\043emoji_id/source.ts"
@@ -24,63 +24,63 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "EmojiSourceResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { emoji_id } = req.params;
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "EmojiSourceResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { emoji_id } = req.params;
- const emoji = await Emoji.findOne({ where: { id: emoji_id } });
- if (!emoji) {
- res.status(404).json({
- code: DiscordApiErrors.UNKNOWN_EMOJI.code,
- message: `No emoji with ID ${emoji_id} appear to exist. Are you sure you didn't mistype it?`,
- errors: {},
- } as APIErrorResponse);
- return;
- }
+ const emoji = await Emoji.findOne({ where: { id: emoji_id } });
+ if (!emoji) {
+ res.status(404).json({
+ code: DiscordApiErrors.UNKNOWN_EMOJI.code,
+ message: `No emoji with ID ${emoji_id} appear to exist. Are you sure you didn't mistype it?`,
+ errors: {},
+ } as APIErrorResponse);
+ return;
+ }
- // TODO: emojis can be owned by applications these days, account for this when we get there?
- res.json({
- type: "GUILD",
- guild: {
- ...(await Guild.findOne({
- where: {
- id: emoji.guild_id,
- },
- select: {
- id: true,
- name: true,
- icon: true,
- description: true,
- features: true,
- emojis: true,
- premium_tier: true,
- premium_subscription_count: true,
- },
- })),
- approximate_member_count: await Member.countBy({
- guild_id: emoji.guild_id,
- }),
- approximate_presence_count: await Member.countBy({
- guild_id: emoji.guild_id,
- user: {
- sessions: {
- status: "online",
- },
- },
- }),
- } as EmojiGuild,
- } as EmojiSourceResponse);
- },
+ // TODO: emojis can be owned by applications these days, account for this when we get there?
+ res.json({
+ type: "GUILD",
+ guild: {
+ ...(await Guild.findOne({
+ where: {
+ id: emoji.guild_id,
+ },
+ select: {
+ id: true,
+ name: true,
+ icon: true,
+ description: true,
+ features: true,
+ emojis: true,
+ premium_tier: true,
+ premium_subscription_count: true,
+ },
+ })),
+ approximate_member_count: await Member.countBy({
+ guild_id: emoji.guild_id,
+ }),
+ approximate_presence_count: await Member.countBy({
+ guild_id: emoji.guild_id,
+ user: {
+ sessions: {
+ status: "online",
+ },
+ },
+ }),
+ } as EmojiGuild,
+ } as EmojiSourceResponse);
+ },
);
export default router;
diff --git a/src/api/routes/experiments.ts b/src/api/routes/experiments.ts
index bf12063..9dd54cc 100644
--- a/src/api/routes/experiments.ts
+++ b/src/api/routes/experiments.ts
@@ -22,8 +22,8 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), (req: Request, res: Response) => {
- // TODO:
- res.send({ fingerprint: "", assignments: [], guild_experiments: [] });
+ // TODO:
+ res.send({ fingerprint: "", assignments: [], guild_experiments: [] });
});
export default router;
diff --git a/src/api/routes/games/detectable.ts b/src/api/routes/games/detectable.ts
index 9e10bd5..e1415ea 100644
--- a/src/api/routes/games/detectable.ts
+++ b/src/api/routes/games/detectable.ts
@@ -22,33 +22,33 @@
const router: Router = Router({ mergeParams: true });
const cache = {
- data: {},
- expires: 0,
+ data: {},
+ expires: 0,
};
// modern dclients call this, is /applications/detectable deprecated?
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "ApplicationDetectableResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- // cache for 6 hours
- if (Date.now() > cache.expires) {
- const response = await fetch("https://discord.com/api/v10/games/detectable"); // because, well, it's unauthenticated anyways
- const data = await response.json();
- cache.data = data as ApplicationDetectableResponse;
- cache.expires = Date.now() + 6 * 60 * 60 * 1000;
- }
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "ApplicationDetectableResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ // cache for 6 hours
+ if (Date.now() > cache.expires) {
+ const response = await fetch("https://discord.com/api/v10/games/detectable"); // because, well, it's unauthenticated anyways
+ const data = await response.json();
+ cache.data = data as ApplicationDetectableResponse;
+ cache.expires = Date.now() + 6 * 60 * 60 * 1000;
+ }
- res.set("Cache-Control", `public, max-age=${Math.floor((cache.expires - Date.now()) / 1000)}, s-maxage=${Math.floor((cache.expires - Date.now()) / 1000)}, immutable`)
- .status(200)
- .json(cache.data);
- },
+ res.set("Cache-Control", `public, max-age=${Math.floor((cache.expires - Date.now()) / 1000)}, s-maxage=${Math.floor((cache.expires - Date.now()) / 1000)}, immutable`)
+ .status(200)
+ .json(cache.data);
+ },
);
export default router;
diff --git a/src/api/routes/gateway/bot.ts b/src/api/routes/gateway/bot.ts
index 80fa951..34a648c 100644
--- a/src/api/routes/gateway/bot.ts
+++ b/src/api/routes/gateway/bot.ts
@@ -23,27 +23,27 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "GatewayBotResponse",
- },
- },
- }),
- (req: Request, res: Response) => {
- const { endpointPublic } = Config.get().gateway;
- res.json({
- url: endpointPublic,
- shards: 1,
- session_start_limit: {
- total: 1000,
- remaining: 999,
- reset_after: 14400000,
- max_concurrency: 1,
- },
- });
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "GatewayBotResponse",
+ },
+ },
+ }),
+ (req: Request, res: Response) => {
+ const { endpointPublic } = Config.get().gateway;
+ res.json({
+ url: endpointPublic,
+ shards: 1,
+ session_start_limit: {
+ total: 1000,
+ remaining: 999,
+ reset_after: 14400000,
+ max_concurrency: 1,
+ },
+ });
+ },
);
export default router;
diff --git a/src/api/routes/gateway/index.ts b/src/api/routes/gateway/index.ts
index 1fafbf5..b85fcd9 100644
--- a/src/api/routes/gateway/index.ts
+++ b/src/api/routes/gateway/index.ts
@@ -23,20 +23,20 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "GatewayResponse",
- },
- },
- }),
- (req: Request, res: Response) => {
- const { endpointPublic } = Config.get().gateway;
- res.json({
- url: endpointPublic,
- });
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "GatewayResponse",
+ },
+ },
+ }),
+ (req: Request, res: Response) => {
+ const { endpointPublic } = Config.get().gateway;
+ res.json({
+ url: endpointPublic,
+ });
+ },
);
export default router;
diff --git a/src/api/routes/gifs/search.ts b/src/api/routes/gifs/search.ts
index e81c2c3..ca07956 100644
--- a/src/api/routes/gifs/search.ts
+++ b/src/api/routes/gifs/search.ts
@@ -25,45 +25,45 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- query: {
- q: {
- type: "string",
- required: true,
- description: "Search query",
- },
- media_format: {
- type: "string",
- description: "Media format",
- values: Object.keys(TenorMediaTypes).filter((key) => isNaN(Number(key))),
- },
- locale: {
- type: "string",
- description: "Locale",
- },
- },
- responses: {
- 200: {
- body: "TenorGifsResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- // TODO: Custom providers
- const { q, media_format, locale } = req.query;
+ "/",
+ route({
+ query: {
+ q: {
+ type: "string",
+ required: true,
+ description: "Search query",
+ },
+ media_format: {
+ type: "string",
+ description: "Media format",
+ values: Object.keys(TenorMediaTypes).filter((key) => isNaN(Number(key))),
+ },
+ locale: {
+ type: "string",
+ description: "Locale",
+ },
+ },
+ responses: {
+ 200: {
+ body: "TenorGifsResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ // TODO: Custom providers
+ const { q, media_format, locale } = req.query;
- const apiKey = getGifApiKey();
+ const apiKey = getGifApiKey();
- const response = await fetch(`https://g.tenor.com/v1/search?q=${q}&media_format=${media_format}&locale=${locale}&key=${apiKey}`, {
- method: "get",
- headers: { "Content-Type": "application/json" },
- });
+ const response = await fetch(`https://g.tenor.com/v1/search?q=${q}&media_format=${media_format}&locale=${locale}&key=${apiKey}`, {
+ method: "get",
+ headers: { "Content-Type": "application/json" },
+ });
- const { results } = (await response.json()) as { results: TenorGif[] };
+ const { results } = (await response.json()) as { results: TenorGif[] };
- res.json(results.map(parseGifResult)).status(200);
- },
+ res.json(results.map(parseGifResult)).status(200);
+ },
);
export default router;
diff --git a/src/api/routes/gifs/trending-gifs.ts b/src/api/routes/gifs/trending-gifs.ts
index d5907b4..99aa528 100644
--- a/src/api/routes/gifs/trending-gifs.ts
+++ b/src/api/routes/gifs/trending-gifs.ts
@@ -24,40 +24,40 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- query: {
- media_format: {
- type: "string",
- description: "Media format",
- values: Object.keys(TenorMediaTypes).filter((key) => isNaN(Number(key))),
- },
- locale: {
- type: "string",
- description: "Locale",
- },
- },
- responses: {
- 200: {
- body: "TenorGifsResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- // TODO: Custom providers
- const { media_format, locale } = req.query;
+ "/",
+ route({
+ query: {
+ media_format: {
+ type: "string",
+ description: "Media format",
+ values: Object.keys(TenorMediaTypes).filter((key) => isNaN(Number(key))),
+ },
+ locale: {
+ type: "string",
+ description: "Locale",
+ },
+ },
+ responses: {
+ 200: {
+ body: "TenorGifsResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ // TODO: Custom providers
+ const { media_format, locale } = req.query;
- const apiKey = getGifApiKey();
+ const apiKey = getGifApiKey();
- const response = await fetch(`https://g.tenor.com/v1/trending?media_format=${media_format}&locale=${locale}&key=${apiKey}`, {
- method: "get",
- headers: { "Content-Type": "application/json" },
- });
+ const response = await fetch(`https://g.tenor.com/v1/trending?media_format=${media_format}&locale=${locale}&key=${apiKey}`, {
+ method: "get",
+ headers: { "Content-Type": "application/json" },
+ });
- const { results } = (await response.json()) as { results: TenorGif[] };
+ const { results } = (await response.json()) as { results: TenorGif[] };
- res.json(results.map(parseGifResult)).status(200);
- },
+ res.json(results.map(parseGifResult)).status(200);
+ },
);
export default router;
diff --git a/src/api/routes/gifs/trending.ts b/src/api/routes/gifs/trending.ts
index d86c06b..4a7a3f3 100644
--- a/src/api/routes/gifs/trending.ts
+++ b/src/api/routes/gifs/trending.ts
@@ -24,50 +24,50 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- query: {
- locale: {
- type: "string",
- description: "Locale",
- },
- },
- responses: {
- 200: {
- body: "TenorTrendingResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- // TODO: Custom providers
- // TODO: return gifs as mp4
- // const { media_format, locale } = req.query;
- const { locale } = req.query;
+ "/",
+ route({
+ query: {
+ locale: {
+ type: "string",
+ description: "Locale",
+ },
+ },
+ responses: {
+ 200: {
+ body: "TenorTrendingResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ // TODO: Custom providers
+ // TODO: return gifs as mp4
+ // const { media_format, locale } = req.query;
+ const { locale } = req.query;
- const apiKey = getGifApiKey();
+ const apiKey = getGifApiKey();
- const [responseSource, trendGifSource] = await Promise.all([
- fetch(`https://g.tenor.com/v1/categories?locale=${locale}&key=${apiKey}`, {
- method: "get",
- headers: { "Content-Type": "application/json" },
- }),
- fetch(`https://g.tenor.com/v1/trending?locale=${locale}&key=${apiKey}`, {
- method: "get",
- headers: { "Content-Type": "application/json" },
- }),
- ]);
+ const [responseSource, trendGifSource] = await Promise.all([
+ fetch(`https://g.tenor.com/v1/categories?locale=${locale}&key=${apiKey}`, {
+ method: "get",
+ headers: { "Content-Type": "application/json" },
+ }),
+ fetch(`https://g.tenor.com/v1/trending?locale=${locale}&key=${apiKey}`, {
+ method: "get",
+ headers: { "Content-Type": "application/json" },
+ }),
+ ]);
- const { tags } = (await responseSource.json()) as TenorCategoriesResults;
- const { results } = (await trendGifSource.json()) as TenorTrendingResults;
+ const { tags } = (await responseSource.json()) as TenorCategoriesResults;
+ const { results } = (await trendGifSource.json()) as TenorTrendingResults;
- res.json({
- categories: tags.map((x) => ({
- name: x.searchterm,
- src: x.image,
- })),
- gifs: [parseGifResult(results[0])],
- }).status(200);
- },
+ res.json({
+ categories: tags.map((x) => ({
+ name: x.searchterm,
+ src: x.image,
+ })),
+ gifs: [parseGifResult(results[0])],
+ }).status(200);
+ },
);
export default router;
diff --git a/src/api/routes/guild-recommendations.ts b/src/api/routes/guild-recommendations.ts
index fa642ea..38ba102 100644
--- a/src/api/routes/guild-recommendations.ts
+++ b/src/api/routes/guild-recommendations.ts
@@ -25,32 +25,32 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "GuildRecommendationsResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- // const { limit, personalization_disabled } = req.query;
- const { limit } = req.query;
- const showAllGuilds = Config.get().guild.discovery.showAllGuilds;
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "GuildRecommendationsResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ // const { limit, personalization_disabled } = req.query;
+ const { limit } = req.query;
+ const showAllGuilds = Config.get().guild.discovery.showAllGuilds;
- const genLoadId = (size: number) => [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join("");
+ const genLoadId = (size: number) => [...Array(size)].map(() => Math.floor(Math.random() * 16).toString(16)).join("");
- const guilds = showAllGuilds
- ? await Guild.find({ take: Math.abs(Number(limit || 24)) })
- : await Guild.find({
- where: { features: Like("%DISCOVERABLE%") },
- take: Math.abs(Number(limit || 24)),
- });
- res.send({
- recommended_guilds: guilds,
- load_id: `server_recs/${genLoadId(32)}`,
- }).status(200);
- },
+ const guilds = showAllGuilds
+ ? await Guild.find({ take: Math.abs(Number(limit || 24)) })
+ : await Guild.find({
+ where: { features: Like("%DISCOVERABLE%") },
+ take: Math.abs(Number(limit || 24)),
+ });
+ res.send({
+ recommended_guilds: guilds,
+ load_id: `server_recs/${genLoadId(32)}`,
+ }).status(200);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/application-command-index.ts" "b/src/api/routes/guilds/\043guild_id/application-command-index.ts"
index bb1d800..244029d 100644
--- "a/src/api/routes/guilds/\043guild_id/application-command-index.ts"
+++ "b/src/api/routes/guilds/\043guild_id/application-command-index.ts"
@@ -25,66 +25,66 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- const members = await Member.find({ where: { guild_id: req.params.guild_id, user: { bot: true } } });
- const applications: Application[] = [];
+ const members = await Member.find({ where: { guild_id: req.params.guild_id, user: { bot: true } } });
+ const applications: Application[] = [];
- for (const member of members) {
- const app = await Application.findOne({ where: { id: member.id } });
- if (app) applications.push(app);
- }
+ for (const member of members) {
+ const app = await Application.findOne({ where: { id: member.id } });
+ if (app) applications.push(app);
+ }
- const applicationsSendable = [];
+ const applicationsSendable = [];
- for (const application of applications) {
- applicationsSendable.push({
- bot_id: application.bot?.id,
- description: application.description,
- flags: application.flags,
- icon: application.icon,
- id: application.id,
- name: application.name,
- });
- }
+ for (const application of applications) {
+ applicationsSendable.push({
+ bot_id: application.bot?.id,
+ description: application.description,
+ flags: application.flags,
+ icon: application.icon,
+ id: application.id,
+ name: application.name,
+ });
+ }
- const applicationCommands: ApplicationCommand[][] = [];
+ const applicationCommands: ApplicationCommand[][] = [];
- for (const application of applications) {
- applicationCommands.push(await ApplicationCommand.find({ where: { application_id: application.id, guild_id: IsNull() } }));
- applicationCommands.push(await ApplicationCommand.find({ where: { application_id: application.id, guild_id: req.params.guild_id } }));
- }
+ for (const application of applications) {
+ applicationCommands.push(await ApplicationCommand.find({ where: { application_id: application.id, guild_id: IsNull() } }));
+ applicationCommands.push(await ApplicationCommand.find({ where: { application_id: application.id, guild_id: req.params.guild_id } }));
+ }
- const applicationCommandsSendable: ApplicationCommandSchema[] = [];
+ const applicationCommandsSendable: ApplicationCommandSchema[] = [];
- for (const command of applicationCommands.flat()) {
- applicationCommandsSendable.push({
- id: command.id,
- type: command.type,
- application_id: command.application_id,
- guild_id: command.guild_id,
- name: command.name,
- name_localizations: command.name_localizations,
- // name_localized: // TODO: make this work
- description: command.description,
- description_localizations: command.description_localizations,
- // description_localized: // TODO: make this work
- options: command.type === ApplicationCommandType.CHAT_INPUT ? command.options : undefined,
- default_member_permissions: command.default_member_permissions,
- dm_permission: command.dm_permission,
- permissions: command.permissions,
- nsfw: command.nsfw,
- integration_types: command.integration_types,
- global_popularity_rank: command.global_popularity_rank,
- contexts: command.contexts,
- version: command.version,
- handler: command.handler,
- });
- }
+ for (const command of applicationCommands.flat()) {
+ applicationCommandsSendable.push({
+ id: command.id,
+ type: command.type,
+ application_id: command.application_id,
+ guild_id: command.guild_id,
+ name: command.name,
+ name_localizations: command.name_localizations,
+ // name_localized: // TODO: make this work
+ description: command.description,
+ description_localizations: command.description_localizations,
+ // description_localized: // TODO: make this work
+ options: command.type === ApplicationCommandType.CHAT_INPUT ? command.options : undefined,
+ default_member_permissions: command.default_member_permissions,
+ dm_permission: command.dm_permission,
+ permissions: command.permissions,
+ nsfw: command.nsfw,
+ integration_types: command.integration_types,
+ global_popularity_rank: command.global_popularity_rank,
+ contexts: command.contexts,
+ version: command.version,
+ handler: command.handler,
+ });
+ }
- res.send({
- applications: applicationsSendable,
- application_commands: applicationCommandsSendable,
- version: Snowflake.generate(),
- });
+ res.send({
+ applications: applicationsSendable,
+ application_commands: applicationCommandsSendable,
+ version: Snowflake.generate(),
+ });
});
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/audit-logs.ts" "b/src/api/routes/guilds/\043guild_id/audit-logs.ts"
index 620f882..4acc8e5 100644
--- "a/src/api/routes/guilds/\043guild_id/audit-logs.ts"
+++ "b/src/api/routes/guilds/\043guild_id/audit-logs.ts"
@@ -22,14 +22,14 @@
//TODO: implement audit logs
router.get("/", route({}), async (req: Request, res: Response) => {
- res.json({
- audit_log_entries: [],
- users: [],
- integrations: [],
- webhooks: [],
- guild_scheduled_events: [],
- threads: [],
- application_commands: [],
- });
+ res.json({
+ audit_log_entries: [],
+ users: [],
+ integrations: [],
+ webhooks: [],
+ guild_scheduled_events: [],
+ threads: [],
+ application_commands: [],
+ });
});
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/auto-moderation/rules.ts" "b/src/api/routes/guilds/\043guild_id/auto-moderation/rules.ts"
index e2b3732..8c24651 100644
--- "a/src/api/routes/guilds/\043guild_id/auto-moderation/rules.ts"
+++ "b/src/api/routes/guilds/\043guild_id/auto-moderation/rules.ts"
@@ -25,116 +25,116 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- permission: ["MANAGE_GUILD"],
- responses: {
- 200: {
- body: "AutomodRuleSchemaWithId[]",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- const rules = await AutomodRule.find({ where: { guild_id } });
- return res.json(rules);
- },
+ "/",
+ route({
+ permission: ["MANAGE_GUILD"],
+ responses: {
+ 200: {
+ body: "AutomodRuleSchemaWithId[]",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ const rules = await AutomodRule.find({ where: { guild_id } });
+ return res.json(rules);
+ },
);
router.post(
- "/",
- route({
- // requestBody: "AutomodRuleSchema",
- permission: ["MANAGE_GUILD"],
- responses: {
- 200: {
- body: "AutomodRuleSchemaWithId",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- if (req.user_id !== req.body.creator_id) throw new HTTPError("You can't create a rule for someone else", 403);
+ "/",
+ route({
+ // requestBody: "AutomodRuleSchema",
+ permission: ["MANAGE_GUILD"],
+ responses: {
+ 200: {
+ body: "AutomodRuleSchemaWithId",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ if (req.user_id !== req.body.creator_id) throw new HTTPError("You can't create a rule for someone else", 403);
- if (guild_id !== req.body.guild_id) throw new HTTPError("You can't create a rule for another guild", 403);
+ if (guild_id !== req.body.guild_id) throw new HTTPError("You can't create a rule for another guild", 403);
- if (req.body.id) {
- throw new HTTPError("You can't specify an ID for a new rule", 400);
- }
+ if (req.body.id) {
+ throw new HTTPError("You can't specify an ID for a new rule", 400);
+ }
- const data = req.body as AutomodRuleSchema;
+ const data = req.body as AutomodRuleSchema;
- const created = AutomodRule.create({
- creator: await User.findOneOrFail({
- where: { id: data.creator_id },
- }),
- ...data,
- });
+ const created = AutomodRule.create({
+ creator: await User.findOneOrFail({
+ where: { id: data.creator_id },
+ }),
+ ...data,
+ });
- const savedRule = await AutomodRule.save(created);
- return res.json(savedRule);
- },
+ const savedRule = await AutomodRule.save(created);
+ return res.json(savedRule);
+ },
);
router.patch(
- "/:rule_id",
- route({
- // requestBody: "AutomodRuleSchema
- permission: ["MANAGE_GUILD"],
- responses: {
- 200: {
- body: "AutomodRuleSchemaWithId",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { rule_id } = req.params;
- const rule = await AutomodRule.findOneOrFail({
- where: { id: rule_id },
- });
+ "/:rule_id",
+ route({
+ // requestBody: "AutomodRuleSchema
+ permission: ["MANAGE_GUILD"],
+ responses: {
+ 200: {
+ body: "AutomodRuleSchemaWithId",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { rule_id } = req.params;
+ const rule = await AutomodRule.findOneOrFail({
+ where: { id: rule_id },
+ });
- const data = req.body as AutomodRuleSchema;
+ const data = req.body as AutomodRuleSchema;
- AutomodRule.merge(rule, data);
- const savedRule = await AutomodRule.save(rule);
- return res.json(savedRule);
- },
+ AutomodRule.merge(rule, data);
+ const savedRule = await AutomodRule.save(rule);
+ return res.json(savedRule);
+ },
);
router.delete(
- "/:rule_id",
- route({
- permission: ["MANAGE_GUILD"],
- responses: {
- 204: {},
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { rule_id } = req.params;
- await AutomodRule.delete({ id: rule_id });
- return res.status(204).send();
- },
+ "/:rule_id",
+ route({
+ permission: ["MANAGE_GUILD"],
+ responses: {
+ 204: {},
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { rule_id } = req.params;
+ await AutomodRule.delete({ id: rule_id });
+ return res.status(204).send();
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/bans.ts" "b/src/api/routes/guilds/\043guild_id/bans.ts"
index 03b4ede..cf043b7 100644
--- "a/src/api/routes/guilds/\043guild_id/bans.ts"
+++ "b/src/api/routes/guilds/\043guild_id/bans.ts"
@@ -27,267 +27,267 @@
/* TODO: Deleting the secrets is just a temporary go-around. Views should be implemented for both safety and better handling. */
router.get(
- "/",
- route({
- permission: "BAN_MEMBERS",
- responses: {
- 200: {
- body: "APIBansArray",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
+ "/",
+ route({
+ permission: "BAN_MEMBERS",
+ responses: {
+ 200: {
+ body: "APIBansArray",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
- let bans = await Ban.find({ where: { guild_id: guild_id } });
- const promisesToAwait: Promise[] = [];
- const bansObj: APIBansArray = [];
+ let bans = await Ban.find({ where: { guild_id: guild_id } });
+ const promisesToAwait: Promise[] = [];
+ const bansObj: APIBansArray = [];
- bans = bans.filter((ban) => ban.user_id !== ban.executor_id); // pretend self-bans don't exist to prevent victim chasing
+ bans = bans.filter((ban) => ban.user_id !== ban.executor_id); // pretend self-bans don't exist to prevent victim chasing
- bans.forEach((ban) => {
- promisesToAwait.push(User.getPublicUser(ban.user_id));
- });
+ bans.forEach((ban) => {
+ promisesToAwait.push(User.getPublicUser(ban.user_id));
+ });
- const bannedUsers = await Promise.all(promisesToAwait);
+ const bannedUsers = await Promise.all(promisesToAwait);
- bans.forEach((ban, index) => {
- const user = bannedUsers[index];
- bansObj.push({
- reason: ban.reason ?? null,
- user: {
- username: user.username,
- discriminator: user.discriminator,
- id: user.id,
- avatar: user.avatar ?? null,
- public_flags: user.public_flags,
- },
- });
- });
+ bans.forEach((ban, index) => {
+ const user = bannedUsers[index];
+ bansObj.push({
+ reason: ban.reason ?? null,
+ user: {
+ username: user.username,
+ discriminator: user.discriminator,
+ id: user.id,
+ avatar: user.avatar ?? null,
+ public_flags: user.public_flags,
+ },
+ });
+ });
- return res.json(bansObj);
- },
+ return res.json(bansObj);
+ },
);
router.get(
- "/search",
- route({
- permission: "BAN_MEMBERS",
- query: {
- query: {
- type: "string",
- description: "Query to match username(s) and display name(s) against (1-32 characters)",
- required: true,
- },
- limit: {
- type: "number",
- description: "Max number of members to return (1-10, default 10)",
- required: false,
- },
- },
- responses: {
- 200: {
- body: "APIBansArray",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
+ "/search",
+ route({
+ permission: "BAN_MEMBERS",
+ query: {
+ query: {
+ type: "string",
+ description: "Query to match username(s) and display name(s) against (1-32 characters)",
+ required: true,
+ },
+ limit: {
+ type: "number",
+ description: "Max number of members to return (1-10, default 10)",
+ required: false,
+ },
+ },
+ responses: {
+ 200: {
+ body: "APIBansArray",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
- const limit = Number(req.query.limit) || 10;
- if (limit > 10 || limit < 1) throw new HTTPError("Limit must be between 1 and 10");
+ const limit = Number(req.query.limit) || 10;
+ if (limit > 10 || limit < 1) throw new HTTPError("Limit must be between 1 and 10");
- const query = String(req.query.query);
- if (!query || query.trim().length === 0 || query.length > 32) {
- throw new HTTPError("The query must be between 1 and 32 characters in length");
- }
+ const query = String(req.query.query);
+ if (!query || query.trim().length === 0 || query.length > 32) {
+ throw new HTTPError("The query must be between 1 and 32 characters in length");
+ }
- let bans = await Ban.createQueryBuilder("ban")
- .leftJoinAndSelect("ban.user", "user")
- .where("ban.guild_id = :guildId", { guildId: guild_id })
- .andWhere("user.username LIKE :userName", {
- userName: `%${query}%`,
- })
- .limit(limit)
- .getMany();
+ let bans = await Ban.createQueryBuilder("ban")
+ .leftJoinAndSelect("ban.user", "user")
+ .where("ban.guild_id = :guildId", { guildId: guild_id })
+ .andWhere("user.username LIKE :userName", {
+ userName: `%${query}%`,
+ })
+ .limit(limit)
+ .getMany();
- bans = bans.filter((ban) => ban.user_id !== ban.executor_id); // pretend self-bans don't exist to prevent victim chasing
+ bans = bans.filter((ban) => ban.user_id !== ban.executor_id); // pretend self-bans don't exist to prevent victim chasing
- const bansObj: APIBansArray = bans.map((ban) => {
- const user = ban.user;
- return {
- reason: ban.reason ?? null,
- user: {
- username: user.username,
- discriminator: user.discriminator,
- id: user.id,
- avatar: user.avatar ?? null,
- public_flags: user.public_flags,
- },
- };
- });
+ const bansObj: APIBansArray = bans.map((ban) => {
+ const user = ban.user;
+ return {
+ reason: ban.reason ?? null,
+ user: {
+ username: user.username,
+ discriminator: user.discriminator,
+ id: user.id,
+ avatar: user.avatar ?? null,
+ public_flags: user.public_flags,
+ },
+ };
+ });
- return res.json(bansObj);
- },
+ return res.json(bansObj);
+ },
);
router.get(
- "/:user_id",
- route({
- permission: "BAN_MEMBERS",
- responses: {
- 200: {
- body: "GuildBansResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id, user_id } = req.params;
+ "/:user_id",
+ route({
+ permission: "BAN_MEMBERS",
+ responses: {
+ 200: {
+ body: "GuildBansResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id, user_id } = req.params;
- const ban = (await Ban.findOneOrFail({
- where: { guild_id: guild_id, user_id: user_id },
- })) as BanRegistrySchema;
+ const ban = (await Ban.findOneOrFail({
+ where: { guild_id: guild_id, user_id: user_id },
+ })) as BanRegistrySchema;
- if (ban.user_id === ban.executor_id) throw DiscordApiErrors.UNKNOWN_BAN;
- // pretend self-bans don't exist to prevent victim chasing
+ if (ban.user_id === ban.executor_id) throw DiscordApiErrors.UNKNOWN_BAN;
+ // pretend self-bans don't exist to prevent victim chasing
- const user = await User.getPublicUser(ban.user_id);
+ const user = await User.getPublicUser(ban.user_id);
- const banInfo: GuildBansResponse = {
- user: {
- username: user.username,
- discriminator: user.discriminator,
- id: user.id,
- avatar: user.avatar ?? null,
- public_flags: user.public_flags,
- },
- reason: ban.reason ?? null,
- };
+ const banInfo: GuildBansResponse = {
+ user: {
+ username: user.username,
+ discriminator: user.discriminator,
+ id: user.id,
+ avatar: user.avatar ?? null,
+ public_flags: user.public_flags,
+ },
+ reason: ban.reason ?? null,
+ };
- return res.json(banInfo);
- },
+ return res.json(banInfo);
+ },
);
router.put(
- "/:user_id",
- route({
- requestBody: "BanCreateSchema",
- permission: "BAN_MEMBERS",
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- const banned_user_id = req.params.user_id;
- const opts = req.body as BanCreateSchema;
+ "/:user_id",
+ route({
+ requestBody: "BanCreateSchema",
+ permission: "BAN_MEMBERS",
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ const banned_user_id = req.params.user_id;
+ const opts = req.body as BanCreateSchema;
- let deleteMessagesMs = opts.delete_message_days
- ? (opts.delete_message_days as number) * 86400000
- : opts.delete_message_seconds
- ? (opts.delete_message_seconds as number) * 1000
- : 0;
+ let deleteMessagesMs = opts.delete_message_days
+ ? (opts.delete_message_days as number) * 86400000
+ : opts.delete_message_seconds
+ ? (opts.delete_message_seconds as number) * 1000
+ : 0;
- if (deleteMessagesMs < 0) deleteMessagesMs = 0;
+ if (deleteMessagesMs < 0) deleteMessagesMs = 0;
- if (req.user_id === banned_user_id && banned_user_id === req.permission?.cache.guild?.owner_id)
- throw new HTTPError("You are the guild owner, hence can't ban yourself", 403);
+ if (req.user_id === banned_user_id && banned_user_id === req.permission?.cache.guild?.owner_id)
+ throw new HTTPError("You are the guild owner, hence can't ban yourself", 403);
- if (req.permission?.cache.guild?.owner_id === banned_user_id) throw new HTTPError("You can't ban the owner", 400);
+ if (req.permission?.cache.guild?.owner_id === banned_user_id) throw new HTTPError("You can't ban the owner", 400);
- const existingBan = await Ban.findOne({
- where: { guild_id: guild_id, user_id: banned_user_id },
- });
+ const existingBan = await Ban.findOne({
+ where: { guild_id: guild_id, user_id: banned_user_id },
+ });
- // Bans on already banned users are silently ignored
- if (existingBan) return res.status(204).send();
+ // Bans on already banned users are silently ignored
+ if (existingBan) return res.status(204).send();
- const banned_user = await User.getPublicUser(banned_user_id);
+ const banned_user = await User.getPublicUser(banned_user_id);
- const ban = Ban.create({
- user_id: banned_user_id,
- guild_id: guild_id,
- executor_id: req.user_id,
- reason: req.body.reason, // || otherwise empty
- });
+ const ban = Ban.create({
+ user_id: banned_user_id,
+ guild_id: guild_id,
+ executor_id: req.user_id,
+ reason: req.body.reason, // || otherwise empty
+ });
- await Promise.all([
- Member.removeFromGuild(banned_user_id, guild_id),
- ban.save(),
- emitEvent({
- event: "GUILD_BAN_ADD",
- data: {
- guild_id: guild_id,
- user: banned_user.toPublicUser(),
- delete_message_secs: Math.floor(deleteMessagesMs / 1000),
- },
- guild_id: guild_id,
- } as GuildBanAddEvent),
- ]);
+ await Promise.all([
+ Member.removeFromGuild(banned_user_id, guild_id),
+ ban.save(),
+ emitEvent({
+ event: "GUILD_BAN_ADD",
+ data: {
+ guild_id: guild_id,
+ user: banned_user.toPublicUser(),
+ delete_message_secs: Math.floor(deleteMessagesMs / 1000),
+ },
+ guild_id: guild_id,
+ } as GuildBanAddEvent),
+ ]);
- return res.status(204).send();
- },
+ return res.status(204).send();
+ },
);
router.delete(
- "/:user_id",
- route({
- permission: "BAN_MEMBERS",
- responses: {
- 204: {},
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id, user_id } = req.params;
+ "/:user_id",
+ route({
+ permission: "BAN_MEMBERS",
+ responses: {
+ 204: {},
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id, user_id } = req.params;
- await Ban.findOneOrFail({
- where: { guild_id: guild_id, user_id: user_id },
- });
+ await Ban.findOneOrFail({
+ where: { guild_id: guild_id, user_id: user_id },
+ });
- const banned_user = await User.getPublicUser(user_id);
+ const banned_user = await User.getPublicUser(user_id);
- await Promise.all([
- Ban.delete({
- user_id: user_id,
- guild_id,
- }),
+ await Promise.all([
+ Ban.delete({
+ user_id: user_id,
+ guild_id,
+ }),
- emitEvent({
- event: "GUILD_BAN_REMOVE",
- data: {
- guild_id,
- user: banned_user,
- },
- guild_id,
- } as GuildBanRemoveEvent),
- ]);
+ emitEvent({
+ event: "GUILD_BAN_REMOVE",
+ data: {
+ guild_id,
+ user: banned_user,
+ },
+ guild_id,
+ } as GuildBanRemoveEvent),
+ ]);
- return res.status(204).send();
- },
+ return res.status(204).send();
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/bulk-ban.ts" "b/src/api/routes/guilds/\043guild_id/bulk-ban.ts"
index a564e2d..004c2ab 100644
--- "a/src/api/routes/guilds/\043guild_id/bulk-ban.ts"
+++ "b/src/api/routes/guilds/\043guild_id/bulk-ban.ts"
@@ -25,93 +25,93 @@
const router: Router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "BulkBanSchema",
- permission: ["BAN_MEMBERS", "MANAGE_GUILD"],
- responses: {
- 200: {
- body: "Ban",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
+ "/",
+ route({
+ requestBody: "BulkBanSchema",
+ permission: ["BAN_MEMBERS", "MANAGE_GUILD"],
+ responses: {
+ 200: {
+ body: "Ban",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
- const userIds: Array = req.body.user_ids;
- if (!userIds) throw new HTTPError("The user_ids array is missing", 400);
+ const userIds: Array = req.body.user_ids;
+ if (!userIds) throw new HTTPError("The user_ids array is missing", 400);
- if (userIds.length > Config.get().limits.guild.maxBulkBanUsers) throw new HTTPError("The user_ids array must be between 1 and 200 in length", 400);
+ if (userIds.length > Config.get().limits.guild.maxBulkBanUsers) throw new HTTPError("The user_ids array must be between 1 and 200 in length", 400);
- const banned_users = [];
- const failed_users = [];
- for await (const banned_user_id of userIds) {
- if (req.user_id === banned_user_id && banned_user_id === req.permission?.cache.guild?.owner_id) {
- failed_users.push(banned_user_id);
- continue;
- }
+ const banned_users = [];
+ const failed_users = [];
+ for await (const banned_user_id of userIds) {
+ if (req.user_id === banned_user_id && banned_user_id === req.permission?.cache.guild?.owner_id) {
+ failed_users.push(banned_user_id);
+ continue;
+ }
- if (req.permission?.cache.guild?.owner_id === banned_user_id) {
- failed_users.push(banned_user_id);
- continue;
- }
+ if (req.permission?.cache.guild?.owner_id === banned_user_id) {
+ failed_users.push(banned_user_id);
+ continue;
+ }
- const existingBan = await Ban.findOne({
- where: { guild_id: guild_id, user_id: banned_user_id },
- });
- if (existingBan) {
- failed_users.push(banned_user_id);
- continue;
- }
+ const existingBan = await Ban.findOne({
+ where: { guild_id: guild_id, user_id: banned_user_id },
+ });
+ if (existingBan) {
+ failed_users.push(banned_user_id);
+ continue;
+ }
- let banned_user;
- try {
- banned_user = await User.getPublicUser(banned_user_id);
- } catch {
- failed_users.push(banned_user_id);
- continue;
- }
+ let banned_user;
+ try {
+ banned_user = await User.getPublicUser(banned_user_id);
+ } catch {
+ failed_users.push(banned_user_id);
+ continue;
+ }
- const ban = Ban.create({
- user_id: banned_user_id,
- guild_id: guild_id,
- ip: req.ip,
- executor_id: req.user_id,
- reason: req.body.reason, // || otherwise empty
- });
+ const ban = Ban.create({
+ user_id: banned_user_id,
+ guild_id: guild_id,
+ ip: req.ip,
+ executor_id: req.user_id,
+ reason: req.body.reason, // || otherwise empty
+ });
- try {
- await Promise.all([
- Member.removeFromGuild(banned_user_id, guild_id),
- ban.save(),
- emitEvent({
- event: "GUILD_BAN_ADD",
- data: {
- guild_id: guild_id,
- user: banned_user.toPublicUser(),
- },
- guild_id: guild_id,
- } as GuildBanAddEvent),
- ]);
- banned_users.push(banned_user_id);
- } catch {
- failed_users.push(banned_user_id);
- continue;
- }
- }
+ try {
+ await Promise.all([
+ Member.removeFromGuild(banned_user_id, guild_id),
+ ban.save(),
+ emitEvent({
+ event: "GUILD_BAN_ADD",
+ data: {
+ guild_id: guild_id,
+ user: banned_user.toPublicUser(),
+ },
+ guild_id: guild_id,
+ } as GuildBanAddEvent),
+ ]);
+ banned_users.push(banned_user_id);
+ } catch {
+ failed_users.push(banned_user_id);
+ continue;
+ }
+ }
- if (banned_users.length === 0 && failed_users.length > 0) throw DiscordApiErrors.BULK_BAN_FAILED;
- return res.json({
- banned_users: banned_users,
- failed_users: failed_users,
- });
- },
+ if (banned_users.length === 0 && failed_users.length > 0) throw DiscordApiErrors.BULK_BAN_FAILED;
+ return res.json({
+ banned_users: banned_users,
+ failed_users: failed_users,
+ });
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/channels.ts" "b/src/api/routes/guilds/\043guild_id/channels.ts"
index ecb25be..fc374ac 100644
--- "a/src/api/routes/guilds/\043guild_id/channels.ts"
+++ "b/src/api/routes/guilds/\043guild_id/channels.ts"
@@ -23,148 +23,148 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 201: {
- body: "APIChannelArray",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- const channels = await Channel.find({ where: { guild_id } });
+ "/",
+ route({
+ responses: {
+ 201: {
+ body: "APIChannelArray",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ const channels = await Channel.find({ where: { guild_id } });
- for await (const channel of channels) {
- channel.position = await Channel.calculatePosition(channel.id, guild_id, channel.guild);
- }
- channels.sort((a, b) => a.position - b.position);
+ for await (const channel of channels) {
+ channel.position = await Channel.calculatePosition(channel.id, guild_id, channel.guild);
+ }
+ channels.sort((a, b) => a.position - b.position);
- res.json(channels);
- },
+ res.json(channels);
+ },
);
router.post(
- "/",
- route({
- requestBody: "ChannelModifySchema",
- permission: "MANAGE_CHANNELS",
- responses: {
- 201: {
- body: "Channel",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- // creates a new guild channel https://discord.com/developers/docs/resources/guild#create-guild-channel
- const { guild_id } = req.params;
- const body = req.body as ChannelModifySchema;
+ "/",
+ route({
+ requestBody: "ChannelModifySchema",
+ permission: "MANAGE_CHANNELS",
+ responses: {
+ 201: {
+ body: "Channel",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ // creates a new guild channel https://discord.com/developers/docs/resources/guild#create-guild-channel
+ const { guild_id } = req.params;
+ const body = req.body as ChannelModifySchema;
- const channel = await Channel.createChannel({ ...body, guild_id }, req.user_id);
- channel.position = await Channel.calculatePosition(channel.id, guild_id, channel.guild);
+ const channel = await Channel.createChannel({ ...body, guild_id }, req.user_id);
+ channel.position = await Channel.calculatePosition(channel.id, guild_id, channel.guild);
- res.status(201).json(channel);
- },
+ res.status(201).json(channel);
+ },
);
router.patch(
- "/",
- route({
- requestBody: "ChannelReorderSchema",
- permission: "MANAGE_CHANNELS",
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- // changes guild channel position
- const { guild_id } = req.params;
- let body = req.body as ChannelReorderSchema;
+ "/",
+ route({
+ requestBody: "ChannelReorderSchema",
+ permission: "MANAGE_CHANNELS",
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ // changes guild channel position
+ const { guild_id } = req.params;
+ let body = req.body as ChannelReorderSchema;
- const guild = await Guild.findOneOrFail({
- where: { id: guild_id },
- select: { channel_ordering: true },
- });
+ const guild = await Guild.findOneOrFail({
+ where: { id: guild_id },
+ select: { channel_ordering: true },
+ });
- body = body.sort((a, b) => {
- const apos = a.position || (a.parent_id ? guild.channel_ordering.findIndex((_) => _ === a.parent_id) + 1 : 0);
- const bpos = b.position || (b.parent_id ? guild.channel_ordering.findIndex((_) => _ === b.parent_id) + 1 : 0);
- return apos - bpos;
- });
+ body = body.sort((a, b) => {
+ const apos = a.position || (a.parent_id ? guild.channel_ordering.findIndex((_) => _ === a.parent_id) + 1 : 0);
+ const bpos = b.position || (b.parent_id ? guild.channel_ordering.findIndex((_) => _ === b.parent_id) + 1 : 0);
+ return apos - bpos;
+ });
- // The channels not listed for this query
- const notMentioned = guild.channel_ordering.filter((x) => !body.find((c) => c.id == x));
+ // The channels not listed for this query
+ const notMentioned = guild.channel_ordering.filter((x) => !body.find((c) => c.id == x));
- const withParents = body.filter((x) => x.parent_id !== undefined);
- const withPositions = body.filter((x) => x.position !== undefined);
- // You can't do it with Promise.all or the way this is being done is super incorrect
- for await (const opt of withPositions) {
- const channel = await Channel.findOneOrFail({
- where: { id: opt.id },
- });
+ const withParents = body.filter((x) => x.parent_id !== undefined);
+ const withPositions = body.filter((x) => x.position !== undefined);
+ // You can't do it with Promise.all or the way this is being done is super incorrect
+ for await (const opt of withPositions) {
+ const channel = await Channel.findOneOrFail({
+ where: { id: opt.id },
+ });
- notMentioned.splice(opt.position as number, 0, channel.id);
- channel.position = notMentioned.findIndex((_) => _ === channel.id);
+ notMentioned.splice(opt.position as number, 0, channel.id);
+ channel.position = notMentioned.findIndex((_) => _ === channel.id);
- await emitEvent({
- event: "CHANNEL_UPDATE",
- data: channel,
- channel_id: channel.id,
- guild_id,
- } as ChannelUpdateEvent);
- }
- // Due to this also being able to change the order, this needs to be done in order
- // have to do the parents after the positions
- for await (const opt of withParents) {
- const [channel, parent] = await Promise.all([
- Channel.findOneOrFail({
- where: { id: opt.id },
- }),
- opt.parent_id
- ? Channel.findOneOrFail({
- where: { id: opt.parent_id },
- select: {
- permission_overwrites: true,
- id: true,
- },
- })
- : null,
- ]);
+ await emitEvent({
+ event: "CHANNEL_UPDATE",
+ data: channel,
+ channel_id: channel.id,
+ guild_id,
+ } as ChannelUpdateEvent);
+ }
+ // Due to this also being able to change the order, this needs to be done in order
+ // have to do the parents after the positions
+ for await (const opt of withParents) {
+ const [channel, parent] = await Promise.all([
+ Channel.findOneOrFail({
+ where: { id: opt.id },
+ }),
+ opt.parent_id
+ ? Channel.findOneOrFail({
+ where: { id: opt.parent_id },
+ select: {
+ permission_overwrites: true,
+ id: true,
+ },
+ })
+ : null,
+ ]);
- if (opt.lock_permissions && parent) await Channel.update({ id: channel.id }, { permission_overwrites: parent.permission_overwrites });
- if (parent && opt.position === undefined) {
- const parentPos = notMentioned.indexOf(parent.id);
- notMentioned.splice(parentPos + 1, 0, channel.id);
- channel.position = (parentPos + 1) as number;
- }
- channel.parent = parent || undefined;
- channel.parent_id = parent?.id || null;
- await channel.save();
+ if (opt.lock_permissions && parent) await Channel.update({ id: channel.id }, { permission_overwrites: parent.permission_overwrites });
+ if (parent && opt.position === undefined) {
+ const parentPos = notMentioned.indexOf(parent.id);
+ notMentioned.splice(parentPos + 1, 0, channel.id);
+ channel.position = (parentPos + 1) as number;
+ }
+ channel.parent = parent || undefined;
+ channel.parent_id = parent?.id || null;
+ await channel.save();
- await emitEvent({
- event: "CHANNEL_UPDATE",
- data: channel,
- channel_id: channel.id,
- guild_id,
- } as ChannelUpdateEvent);
- }
+ await emitEvent({
+ event: "CHANNEL_UPDATE",
+ data: channel,
+ channel_id: channel.id,
+ guild_id,
+ } as ChannelUpdateEvent);
+ }
- await Guild.update({ id: guild_id }, { channel_ordering: notMentioned });
+ await Guild.update({ id: guild_id }, { channel_ordering: notMentioned });
- return res.sendStatus(204);
- },
+ return res.sendStatus(204);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/delete.ts" "b/src/api/routes/guilds/\043guild_id/delete.ts"
index 509445c..4edd2c3 100644
--- "a/src/api/routes/guilds/\043guild_id/delete.ts"
+++ "b/src/api/routes/guilds/\043guild_id/delete.ts"
@@ -26,40 +26,40 @@
// discord prefixes this route with /delete instead of using the delete method
// docs are wrong https://discord.com/developers/docs/resources/guild#delete-guild
router.post(
- "/",
- route({
- responses: {
- 204: {},
- 401: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
+ "/",
+ route({
+ responses: {
+ 204: {},
+ 401: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({
- where: { id: guild_id },
- select: ["owner_id"],
- });
- if (guild.owner_id !== req.user_id) throw new HTTPError("You are not the owner of this guild", 401);
+ const guild = await Guild.findOneOrFail({
+ where: { id: guild_id },
+ select: ["owner_id"],
+ });
+ if (guild.owner_id !== req.user_id) throw new HTTPError("You are not the owner of this guild", 401);
- await Promise.all([
- Guild.delete({ id: guild_id }), // this will also delete all guild related data
- emitEvent({
- event: "GUILD_DELETE",
- data: {
- id: guild_id,
- },
- guild_id: guild_id,
- } as GuildDeleteEvent),
- ]);
+ await Promise.all([
+ Guild.delete({ id: guild_id }), // this will also delete all guild related data
+ emitEvent({
+ event: "GUILD_DELETE",
+ data: {
+ id: guild_id,
+ },
+ guild_id: guild_id,
+ } as GuildDeleteEvent),
+ ]);
- return res.sendStatus(204);
- },
+ return res.sendStatus(204);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/discovery-requirements.ts" "b/src/api/routes/guilds/\043guild_id/discovery-requirements.ts"
index 8972733..150c920 100644
--- "a/src/api/routes/guilds/\043guild_id/discovery-requirements.ts"
+++ "b/src/api/routes/guilds/\043guild_id/discovery-requirements.ts"
@@ -22,44 +22,44 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "GuildDiscoveryRequirementsResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- // TODO:
- // Load from database
- // Admin control, but for now it allows anyone to be discoverable
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "GuildDiscoveryRequirementsResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ // TODO:
+ // Load from database
+ // Admin control, but for now it allows anyone to be discoverable
- res.send({
- guild_id: guild_id,
- safe_environment: true,
- healthy: true,
- health_score_pending: false,
- size: true,
- nsfw_properties: {},
- protected: true,
- sufficient: true,
- sufficient_without_grace_period: true,
- valid_rules_channel: true,
- retention_healthy: true,
- engagement_healthy: true,
- age: true,
- minimum_age: 0,
- health_score: {
- avg_nonnew_participators: 0,
- avg_nonnew_communicators: 0,
- num_intentful_joiners: 0,
- perc_ret_w1_intentful: 0,
- },
- minimum_size: 0,
- });
- },
+ res.send({
+ guild_id: guild_id,
+ safe_environment: true,
+ healthy: true,
+ health_score_pending: false,
+ size: true,
+ nsfw_properties: {},
+ protected: true,
+ sufficient: true,
+ sufficient_without_grace_period: true,
+ valid_rules_channel: true,
+ retention_healthy: true,
+ engagement_healthy: true,
+ age: true,
+ minimum_age: 0,
+ health_score: {
+ avg_nonnew_participators: 0,
+ avg_nonnew_communicators: 0,
+ num_intentful_joiners: 0,
+ perc_ret_w1_intentful: 0,
+ },
+ minimum_size: 0,
+ });
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/emojis.ts" "b/src/api/routes/guilds/\043guild_id/emojis.ts"
index c74f939..5b07380 100644
--- "a/src/api/routes/guilds/\043guild_id/emojis.ts"
+++ "b/src/api/routes/guilds/\043guild_id/emojis.ts"
@@ -24,186 +24,186 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APIEmojiArray",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APIEmojiArray",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
- await Member.IsInGuildOrFail(req.user_id, guild_id);
+ await Member.IsInGuildOrFail(req.user_id, guild_id);
- const emojis = await Emoji.find({
- where: { guild_id: guild_id },
- relations: ["user"],
- });
+ const emojis = await Emoji.find({
+ where: { guild_id: guild_id },
+ relations: ["user"],
+ });
- return res.json(emojis);
- },
+ return res.json(emojis);
+ },
);
router.get(
- "/:emoji_id",
- route({
- responses: {
- 200: {
- body: "Emoji",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id, emoji_id } = req.params;
+ "/:emoji_id",
+ route({
+ responses: {
+ 200: {
+ body: "Emoji",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id, emoji_id } = req.params;
- await Member.IsInGuildOrFail(req.user_id, guild_id);
+ await Member.IsInGuildOrFail(req.user_id, guild_id);
- const emoji = await Emoji.findOneOrFail({
- where: { guild_id: guild_id, id: emoji_id },
- relations: ["user"],
- });
+ const emoji = await Emoji.findOneOrFail({
+ where: { guild_id: guild_id, id: emoji_id },
+ relations: ["user"],
+ });
- return res.json(emoji);
- },
+ return res.json(emoji);
+ },
);
router.post(
- "/",
- route({
- requestBody: "EmojiCreateSchema",
- permission: "MANAGE_EMOJIS_AND_STICKERS",
- responses: {
- 201: {
- body: "Emoji",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- const body = req.body as EmojiCreateSchema;
+ "/",
+ route({
+ requestBody: "EmojiCreateSchema",
+ permission: "MANAGE_EMOJIS_AND_STICKERS",
+ responses: {
+ 201: {
+ body: "Emoji",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ const body = req.body as EmojiCreateSchema;
- const id = Snowflake.generate();
- const emoji_count = await Emoji.count({
- where: { guild_id: guild_id },
- });
- const { maxEmojis } = Config.get().limits.guild;
+ const id = Snowflake.generate();
+ const emoji_count = await Emoji.count({
+ where: { guild_id: guild_id },
+ });
+ const { maxEmojis } = Config.get().limits.guild;
- if (emoji_count >= maxEmojis) throw DiscordApiErrors.MAXIMUM_NUMBER_OF_EMOJIS_REACHED.withParams(maxEmojis);
- if (body.require_colons == null) body.require_colons = true;
+ if (emoji_count >= maxEmojis) throw DiscordApiErrors.MAXIMUM_NUMBER_OF_EMOJIS_REACHED.withParams(maxEmojis);
+ if (body.require_colons == null) body.require_colons = true;
- const user = await User.findOneOrFail({ where: { id: req.user_id } });
- await handleFile(`/emojis/${id}`, body.image);
+ const user = await User.findOneOrFail({ where: { id: req.user_id } });
+ await handleFile(`/emojis/${id}`, body.image);
- const mimeType = body.image.split(":")[1].split(";")[0];
- const emoji = await Emoji.create({
- id: id,
- guild_id: guild_id,
- name: body.name,
- require_colons: body.require_colons ?? undefined, // schema allows nulls, db does not
- user: user,
- managed: false,
- animated: mimeType == "image/gif" || mimeType == "image/apng" || mimeType == "video/webm",
- available: true,
- roles: [],
- }).save();
+ const mimeType = body.image.split(":")[1].split(";")[0];
+ const emoji = await Emoji.create({
+ id: id,
+ guild_id: guild_id,
+ name: body.name,
+ require_colons: body.require_colons ?? undefined, // schema allows nulls, db does not
+ user: user,
+ managed: false,
+ animated: mimeType == "image/gif" || mimeType == "image/apng" || mimeType == "video/webm",
+ available: true,
+ roles: [],
+ }).save();
- await emitEvent({
- event: "GUILD_EMOJIS_UPDATE",
- guild_id: guild_id,
- data: {
- guild_id: guild_id,
- emojis: await Emoji.find({ where: { guild_id: guild_id } }),
- },
- } as GuildEmojisUpdateEvent);
+ await emitEvent({
+ event: "GUILD_EMOJIS_UPDATE",
+ guild_id: guild_id,
+ data: {
+ guild_id: guild_id,
+ emojis: await Emoji.find({ where: { guild_id: guild_id } }),
+ },
+ } as GuildEmojisUpdateEvent);
- return res.status(201).json(emoji);
- },
+ return res.status(201).json(emoji);
+ },
);
router.patch(
- "/:emoji_id",
- route({
- requestBody: "EmojiModifySchema",
- permission: "MANAGE_EMOJIS_AND_STICKERS",
- responses: {
- 200: {
- body: "Emoji",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { emoji_id, guild_id } = req.params;
- const body = req.body as EmojiModifySchema;
+ "/:emoji_id",
+ route({
+ requestBody: "EmojiModifySchema",
+ permission: "MANAGE_EMOJIS_AND_STICKERS",
+ responses: {
+ 200: {
+ body: "Emoji",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { emoji_id, guild_id } = req.params;
+ const body = req.body as EmojiModifySchema;
- const emoji = await Emoji.create({
- ...body,
- id: emoji_id,
- guild_id: guild_id,
- }).save();
+ const emoji = await Emoji.create({
+ ...body,
+ id: emoji_id,
+ guild_id: guild_id,
+ }).save();
- await emitEvent({
- event: "GUILD_EMOJIS_UPDATE",
- guild_id: guild_id,
- data: {
- guild_id: guild_id,
- emojis: await Emoji.find({ where: { guild_id: guild_id } }),
- },
- } as GuildEmojisUpdateEvent);
+ await emitEvent({
+ event: "GUILD_EMOJIS_UPDATE",
+ guild_id: guild_id,
+ data: {
+ guild_id: guild_id,
+ emojis: await Emoji.find({ where: { guild_id: guild_id } }),
+ },
+ } as GuildEmojisUpdateEvent);
- return res.json(emoji);
- },
+ return res.json(emoji);
+ },
);
router.delete(
- "/:emoji_id",
- route({
- permission: "MANAGE_EMOJIS_AND_STICKERS",
- responses: {
- 204: {},
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { emoji_id, guild_id } = req.params;
+ "/:emoji_id",
+ route({
+ permission: "MANAGE_EMOJIS_AND_STICKERS",
+ responses: {
+ 204: {},
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { emoji_id, guild_id } = req.params;
- await Emoji.delete({
- id: emoji_id,
- guild_id: guild_id,
- });
+ await Emoji.delete({
+ id: emoji_id,
+ guild_id: guild_id,
+ });
- await emitEvent({
- event: "GUILD_EMOJIS_UPDATE",
- guild_id: guild_id,
- data: {
- guild_id: guild_id,
- emojis: await Emoji.find({ where: { guild_id: guild_id } }),
- },
- } as GuildEmojisUpdateEvent);
+ await emitEvent({
+ event: "GUILD_EMOJIS_UPDATE",
+ guild_id: guild_id,
+ data: {
+ guild_id: guild_id,
+ emojis: await Emoji.find({ where: { guild_id: guild_id } }),
+ },
+ } as GuildEmojisUpdateEvent);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/index.ts" "b/src/api/routes/guilds/\043guild_id/index.ts"
index d6593bd..38cc913 100644
--- "a/src/api/routes/guilds/\043guild_id/index.ts"
+++ "b/src/api/routes/guilds/\043guild_id/index.ts"
@@ -25,188 +25,188 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- "200": {
- body: "APIGuildWithJoinedAt",
- },
- 401: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
+ "/",
+ route({
+ responses: {
+ "200": {
+ body: "APIGuildWithJoinedAt",
+ },
+ 401: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
- const [guild, member] = await Promise.all([Guild.findOneOrFail({ where: { id: guild_id } }), Member.findOne({ where: { guild_id: guild_id, id: req.user_id } })]);
- if (!member) throw new HTTPError("You are not a member of the guild you are trying to access", 401);
+ const [guild, member] = await Promise.all([Guild.findOneOrFail({ where: { id: guild_id } }), Member.findOne({ where: { guild_id: guild_id, id: req.user_id } })]);
+ if (!member) throw new HTTPError("You are not a member of the guild you are trying to access", 401);
- return res.send({
- ...guild,
- joined_at: member?.joined_at,
- });
- },
+ return res.send({
+ ...guild,
+ joined_at: member?.joined_at,
+ });
+ },
);
router.patch(
- "/",
- route({
- requestBody: "GuildUpdateSchema",
- permission: "MANAGE_GUILD",
- responses: {
- 200: {
- body: "GuildCreateResponse",
- },
- 401: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as GuildUpdateSchema;
- const { guild_id } = req.params;
+ "/",
+ route({
+ requestBody: "GuildUpdateSchema",
+ permission: "MANAGE_GUILD",
+ responses: {
+ 200: {
+ body: "GuildCreateResponse",
+ },
+ 401: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as GuildUpdateSchema;
+ const { guild_id } = req.params;
- const rights = await getRights(req.user_id);
- const permission = await getPermission(req.user_id, guild_id);
+ const rights = await getRights(req.user_id);
+ const permission = await getPermission(req.user_id, guild_id);
- if (!rights.has("MANAGE_GUILDS") && !permission.has("MANAGE_GUILD")) throw DiscordApiErrors.MISSING_PERMISSIONS.withParams("MANAGE_GUILDS");
+ if (!rights.has("MANAGE_GUILDS") && !permission.has("MANAGE_GUILD")) throw DiscordApiErrors.MISSING_PERMISSIONS.withParams("MANAGE_GUILDS");
- const guild = await Guild.findOneOrFail({
- where: { id: guild_id },
- relations: ["emojis", "roles", "stickers"],
- });
+ const guild = await Guild.findOneOrFail({
+ where: { id: guild_id },
+ relations: ["emojis", "roles", "stickers"],
+ });
- // trying to `select` this fails
- guild.channel_ordering = (
- await Guild.findOneOrFail({
- where: { id: guild_id },
- select: { channel_ordering: true },
- })
- ).channel_ordering;
+ // trying to `select` this fails
+ guild.channel_ordering = (
+ await Guild.findOneOrFail({
+ where: { id: guild_id },
+ select: { channel_ordering: true },
+ })
+ ).channel_ordering;
- // TODO: guild update check image
+ // TODO: guild update check image
- if (body.icon && body.icon != guild.icon) body.icon = await handleFile(`/icons/${guild_id}`, body.icon);
+ if (body.icon && body.icon != guild.icon) body.icon = await handleFile(`/icons/${guild_id}`, body.icon);
- if (body.banner && body.banner !== guild.banner) body.banner = await handleFile(`/banners/${guild_id}`, body.banner);
+ if (body.banner && body.banner !== guild.banner) body.banner = await handleFile(`/banners/${guild_id}`, body.banner);
- if (body.splash && body.splash !== guild.splash) body.splash = await handleFile(`/splashes/${guild_id}`, body.splash);
+ if (body.splash && body.splash !== guild.splash) body.splash = await handleFile(`/splashes/${guild_id}`, body.splash);
- if (body.discovery_splash && body.discovery_splash !== guild.discovery_splash)
- body.discovery_splash = await handleFile(`/discovery-splashes/${guild_id}`, body.discovery_splash);
+ if (body.discovery_splash && body.discovery_splash !== guild.discovery_splash)
+ body.discovery_splash = await handleFile(`/discovery-splashes/${guild_id}`, body.discovery_splash);
- if (body.features) {
- const diff = guild.features.filter((x) => !body.features?.includes(x)).concat(body.features.filter((x) => !guild.features.includes(x)));
+ if (body.features) {
+ const diff = guild.features.filter((x) => !body.features?.includes(x)).concat(body.features.filter((x) => !guild.features.includes(x)));
- // TODO move these
- const MUTABLE_FEATURES = ["COMMUNITY", "INVITES_DISABLED", "DISCOVERABLE"];
+ // TODO move these
+ const MUTABLE_FEATURES = ["COMMUNITY", "INVITES_DISABLED", "DISCOVERABLE"];
- for (const feature of diff) {
- if (MUTABLE_FEATURES.includes(feature)) continue;
+ for (const feature of diff) {
+ if (MUTABLE_FEATURES.includes(feature)) continue;
- throw SpacebarApiErrors.FEATURE_IS_IMMUTABLE.withParams(feature);
- }
+ throw SpacebarApiErrors.FEATURE_IS_IMMUTABLE.withParams(feature);
+ }
- // for some reason, they don't update in the assign.
- guild.features = body.features;
- }
+ // for some reason, they don't update in the assign.
+ guild.features = body.features;
+ }
- // TODO: check if body ids are valid
- guild.assign(body);
+ // TODO: check if body ids are valid
+ guild.assign(body);
- if (body.public_updates_channel_id == "1") {
- // create an updates channel for them
- const channel = await Channel.createChannel(
- {
- name: "moderator-only",
- guild_id: guild.id,
- position: 0,
- type: 0,
- permission_overwrites: [
- // remove SEND_MESSAGES from @everyone
- {
- id: guild.id,
- allow: "0",
- deny: Permissions.FLAGS.VIEW_CHANNEL.toString(),
- type: 0,
- },
- ],
- },
- undefined,
- { skipPermissionCheck: true },
- );
+ if (body.public_updates_channel_id == "1") {
+ // create an updates channel for them
+ const channel = await Channel.createChannel(
+ {
+ name: "moderator-only",
+ guild_id: guild.id,
+ position: 0,
+ type: 0,
+ permission_overwrites: [
+ // remove SEND_MESSAGES from @everyone
+ {
+ id: guild.id,
+ allow: "0",
+ deny: Permissions.FLAGS.VIEW_CHANNEL.toString(),
+ type: 0,
+ },
+ ],
+ },
+ undefined,
+ { skipPermissionCheck: true },
+ );
- await Guild.insertChannelInOrder(guild.id, channel.id, 0, guild);
+ await Guild.insertChannelInOrder(guild.id, channel.id, 0, guild);
- guild.public_updates_channel_id = channel.id;
- } else if (body.public_updates_channel_id != undefined) {
- // ensure channel exists in this guild
- await Channel.findOneOrFail({
- where: { guild_id, id: body.public_updates_channel_id },
- select: { id: true },
- });
- }
+ guild.public_updates_channel_id = channel.id;
+ } else if (body.public_updates_channel_id != undefined) {
+ // ensure channel exists in this guild
+ await Channel.findOneOrFail({
+ where: { guild_id, id: body.public_updates_channel_id },
+ select: { id: true },
+ });
+ }
- if (body.rules_channel_id == "1") {
- // create a rules for them
- const channel = await Channel.createChannel(
- {
- name: "rules",
- guild_id: guild.id,
- position: 0,
- type: 0,
- permission_overwrites: [
- // remove SEND_MESSAGES from @everyone
- {
- id: guild.id,
- allow: "0",
- deny: Permissions.FLAGS.SEND_MESSAGES.toString(),
- type: 0,
- },
- ],
- },
- undefined,
- { skipPermissionCheck: true },
- );
+ if (body.rules_channel_id == "1") {
+ // create a rules for them
+ const channel = await Channel.createChannel(
+ {
+ name: "rules",
+ guild_id: guild.id,
+ position: 0,
+ type: 0,
+ permission_overwrites: [
+ // remove SEND_MESSAGES from @everyone
+ {
+ id: guild.id,
+ allow: "0",
+ deny: Permissions.FLAGS.SEND_MESSAGES.toString(),
+ type: 0,
+ },
+ ],
+ },
+ undefined,
+ { skipPermissionCheck: true },
+ );
- await Guild.insertChannelInOrder(guild.id, channel.id, 0, guild);
+ await Guild.insertChannelInOrder(guild.id, channel.id, 0, guild);
- guild.rules_channel_id = channel.id;
- } else if (body.rules_channel_id != undefined) {
- // ensure channel exists in this guild
- await Channel.findOneOrFail({
- where: { guild_id, id: body.rules_channel_id },
- select: { id: true },
- });
- }
+ guild.rules_channel_id = channel.id;
+ } else if (body.rules_channel_id != undefined) {
+ // ensure channel exists in this guild
+ await Channel.findOneOrFail({
+ where: { guild_id, id: body.rules_channel_id },
+ select: { id: true },
+ });
+ }
- const data = guild.toJSON();
- // TODO: guild hashes
- // TODO: fix vanity_url_code, template_id
- // delete data.vanity_url_code;
- delete data.template_id;
+ const data = guild.toJSON();
+ // TODO: guild hashes
+ // TODO: fix vanity_url_code, template_id
+ // delete data.vanity_url_code;
+ delete data.template_id;
- await Promise.all([
- guild.save(),
- emitEvent({
- event: "GUILD_UPDATE",
- data,
- guild_id,
- } as GuildUpdateEvent),
- ]);
+ await Promise.all([
+ guild.save(),
+ emitEvent({
+ event: "GUILD_UPDATE",
+ data,
+ guild_id,
+ } as GuildUpdateEvent),
+ ]);
- return res.json(data);
- },
+ return res.json(data);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/integrations.ts" "b/src/api/routes/guilds/\043guild_id/integrations.ts"
index e396e23..704b5a5 100644
--- "a/src/api/routes/guilds/\043guild_id/integrations.ts"
+++ "b/src/api/routes/guilds/\043guild_id/integrations.ts"
@@ -22,6 +22,6 @@
//TODO: implement integrations list
router.get("/", route({}), async (req: Request, res: Response) => {
- res.json([]);
+ res.json([]);
});
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/invites.ts" "b/src/api/routes/guilds/\043guild_id/invites.ts"
index 9372651..32d86a4 100644
--- "a/src/api/routes/guilds/\043guild_id/invites.ts"
+++ "b/src/api/routes/guilds/\043guild_id/invites.ts"
@@ -23,33 +23,33 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- permission: "MANAGE_GUILD",
- responses: {
- 200: {
- body: "APIInviteArray",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
+ "/",
+ route({
+ permission: "MANAGE_GUILD",
+ responses: {
+ 200: {
+ body: "APIInviteArray",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
- const invites = await Invite.find({
- where: { guild_id },
- relations: PublicInviteRelation,
- });
+ const invites = await Invite.find({
+ where: { guild_id },
+ relations: PublicInviteRelation,
+ });
- await Promise.all(
- invites
- .filter((i) => i.isExpired())
- .map(async (i) => {
- await Invite.delete({ code: i.code });
- }),
- );
+ await Promise.all(
+ invites
+ .filter((i) => i.isExpired())
+ .map(async (i) => {
+ await Invite.delete({ code: i.code });
+ }),
+ );
- return res.json(invites.filter((i) => !i.isExpired()));
- },
+ return res.json(invites.filter((i) => !i.isExpired()));
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/member-verification.ts" "b/src/api/routes/guilds/\043guild_id/member-verification.ts"
index 20225e2..11b36a3 100644
--- "a/src/api/routes/guilds/\043guild_id/member-verification.ts"
+++ "b/src/api/routes/guilds/\043guild_id/member-verification.ts"
@@ -21,22 +21,22 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- // TODO: member verification
+ "/",
+ route({
+ responses: {
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ // TODO: member verification
- res.status(404).json({
- message: "Unknown Guild Member Verification Form",
- code: 10068,
- });
- },
+ res.status(404).json({
+ message: "Unknown Guild Member Verification Form",
+ code: 10068,
+ });
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/members/\043member_id/index.ts" "b/src/api/routes/guilds/\043guild_id/members/\043member_id/index.ts"
index 9696cb6..81cda18 100644
--- "a/src/api/routes/guilds/\043guild_id/members/\043member_id/index.ts"
+++ "b/src/api/routes/guilds/\043guild_id/members/\043member_id/index.ts"
@@ -24,212 +24,212 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APIPublicMember",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id, member_id } = req.params;
- await Member.IsInGuildOrFail(req.user_id, guild_id);
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APIPublicMember",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id, member_id } = req.params;
+ await Member.IsInGuildOrFail(req.user_id, guild_id);
- const member = await Member.findOneOrFail({
- where: { id: member_id, guild_id },
- relations: ["roles", "user"],
- select: {
- index: true,
- // only grab public member props
- ...Object.fromEntries(PublicMemberProjection.map((x) => [x, true])),
- // and public user props
- user: Object.fromEntries(PublicUserProjection.map((x) => [x, true])),
- roles: {
- id: true,
- },
- },
- });
+ const member = await Member.findOneOrFail({
+ where: { id: member_id, guild_id },
+ relations: ["roles", "user"],
+ select: {
+ index: true,
+ // only grab public member props
+ ...Object.fromEntries(PublicMemberProjection.map((x) => [x, true])),
+ // and public user props
+ user: Object.fromEntries(PublicUserProjection.map((x) => [x, true])),
+ roles: {
+ id: true,
+ },
+ },
+ });
- return res.json({
- ...member.toPublicMember(),
- user: member.user.toPublicUser(),
- roles: member.roles.map((x) => x.id),
- });
- },
+ return res.json({
+ ...member.toPublicMember(),
+ user: member.user.toPublicUser(),
+ roles: member.roles.map((x) => x.id),
+ });
+ },
);
router.patch(
- "/",
- route({
- requestBody: "MemberChangeSchema",
- responses: {
- 200: {
- body: "Member",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- const member_id = req.params.member_id === "@me" ? req.user_id : req.params.member_id;
- const body = req.body as MemberChangeSchema;
+ "/",
+ route({
+ requestBody: "MemberChangeSchema",
+ responses: {
+ 200: {
+ body: "Member",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ const member_id = req.params.member_id === "@me" ? req.user_id : req.params.member_id;
+ const body = req.body as MemberChangeSchema;
- const member = await Member.findOneOrFail({
- where: { id: member_id, guild_id },
- relations: ["roles", "user"],
- });
- const permission = await getPermission(req.user_id, guild_id);
+ const member = await Member.findOneOrFail({
+ where: { id: member_id, guild_id },
+ relations: ["roles", "user"],
+ });
+ const permission = await getPermission(req.user_id, guild_id);
- if ("nick" in body) {
- permission.hasThrow("MANAGE_NICKNAMES");
+ if ("nick" in body) {
+ permission.hasThrow("MANAGE_NICKNAMES");
- if (!body.nick) {
- delete body.nick;
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- //@ts-ignore shut up
- member.nick = null; // remove the nickname
- }
- }
+ if (!body.nick) {
+ delete body.nick;
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ //@ts-ignore shut up
+ member.nick = null; // remove the nickname
+ }
+ }
- if (("bio" in body || "avatar" in body) && req.params.member_id != "@me") {
- const rights = await getRights(req.user_id);
- rights.hasThrow("MANAGE_USERS");
- }
+ if (("bio" in body || "avatar" in body) && req.params.member_id != "@me") {
+ const rights = await getRights(req.user_id);
+ rights.hasThrow("MANAGE_USERS");
+ }
- if (body.avatar) body.avatar = await handleFile(`/guilds/${guild_id}/users/${member_id}/avatars`, body.avatar as string);
+ if (body.avatar) body.avatar = await handleFile(`/guilds/${guild_id}/users/${member_id}/avatars`, body.avatar as string);
- member.assign(body);
+ member.assign(body);
- // must do this after the assign because the body roles array
- // is string[] not Role[]
- if ("roles" in body) {
- permission.hasThrow("MANAGE_ROLES");
+ // must do this after the assign because the body roles array
+ // is string[] not Role[]
+ if ("roles" in body) {
+ permission.hasThrow("MANAGE_ROLES");
- body.roles = body.roles || [];
- body.roles.filter((x) => !!x);
+ body.roles = body.roles || [];
+ body.roles.filter((x) => !!x);
- if (body.roles.indexOf(guild_id) === -1) body.roles.push(guild_id);
- // foreign key constraint will fail if role doesn't exist
- member.roles = body.roles.map((x) => Role.create({ id: x }));
- }
+ if (body.roles.indexOf(guild_id) === -1) body.roles.push(guild_id);
+ // foreign key constraint will fail if role doesn't exist
+ member.roles = body.roles.map((x) => Role.create({ id: x }));
+ }
- if ("communication_disabled_until" in body) {
- permission.hasThrow("MODERATE_MEMBERS");
- member.communication_disabled_until = body.communication_disabled_until == null ? null : new Date(body.communication_disabled_until);
- }
+ if ("communication_disabled_until" in body) {
+ permission.hasThrow("MODERATE_MEMBERS");
+ member.communication_disabled_until = body.communication_disabled_until == null ? null : new Date(body.communication_disabled_until);
+ }
- await member.save();
+ await member.save();
- member.roles = member.roles.filter((x) => x.id !== guild_id);
+ member.roles = member.roles.filter((x) => x.id !== guild_id);
- // do not use promise.all as we have to first write to db before emitting the event to catch errors
- await emitEvent({
- event: "GUILD_MEMBER_UPDATE",
- guild_id,
- data: { ...member, roles: member.roles.map((x) => x.id) },
- } as GuildMemberUpdateEvent);
+ // do not use promise.all as we have to first write to db before emitting the event to catch errors
+ await emitEvent({
+ event: "GUILD_MEMBER_UPDATE",
+ guild_id,
+ data: { ...member, roles: member.roles.map((x) => x.id) },
+ } as GuildMemberUpdateEvent);
- res.json(member);
- },
+ res.json(member);
+ },
);
router.put(
- "/",
- route({
- responses: {
- 200: {
- body: "MemberJoinGuildResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- // TODO: Lurker mode
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "MemberJoinGuildResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ // TODO: Lurker mode
- const rights = await getRights(req.user_id);
+ const rights = await getRights(req.user_id);
- const { guild_id } = req.params;
- let { member_id } = req.params;
- if (member_id === "@me") {
- member_id = req.user_id;
- rights.hasThrow("JOIN_GUILDS");
- if (req.user_bot) throw DiscordApiErrors.BOT_PROHIBITED_ENDPOINT;
- } else {
- // TODO: check oauth2 scope
+ const { guild_id } = req.params;
+ let { member_id } = req.params;
+ if (member_id === "@me") {
+ member_id = req.user_id;
+ rights.hasThrow("JOIN_GUILDS");
+ if (req.user_bot) throw DiscordApiErrors.BOT_PROHIBITED_ENDPOINT;
+ } else {
+ // TODO: check oauth2 scope
- throw DiscordApiErrors.MISSING_REQUIRED_OAUTH2_SCOPE;
- }
+ throw DiscordApiErrors.MISSING_REQUIRED_OAUTH2_SCOPE;
+ }
- const guild = await Guild.findOneOrFail({
- where: { id: guild_id },
- });
+ const guild = await Guild.findOneOrFail({
+ where: { id: guild_id },
+ });
- if (!guild.features.includes("DISCOVERABLE")) {
- throw DiscordApiErrors.UNKNOWN_GUILD;
- }
+ if (!guild.features.includes("DISCOVERABLE")) {
+ throw DiscordApiErrors.UNKNOWN_GUILD;
+ }
- const emoji = await Emoji.find({
- where: { guild_id: guild_id },
- });
+ const emoji = await Emoji.find({
+ where: { guild_id: guild_id },
+ });
- const roles = await Role.find({
- where: { guild_id: guild_id },
- });
+ const roles = await Role.find({
+ where: { guild_id: guild_id },
+ });
- const stickers = await Sticker.find({
- where: { guild_id: guild_id },
- });
+ const stickers = await Sticker.find({
+ where: { guild_id: guild_id },
+ });
- await Member.addToGuild(member_id, guild_id);
- res.send({ ...guild, emojis: emoji, roles: roles, stickers: stickers });
- },
+ await Member.addToGuild(member_id, guild_id);
+ res.send({ ...guild, emojis: emoji, roles: roles, stickers: stickers });
+ },
);
router.delete(
- "/",
- route({
- responses: {
- 204: {},
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id, member_id } = req.params;
- const permission = await getPermission(req.user_id, guild_id);
- const rights = await getRights(req.user_id);
- if (member_id === "@me" || member_id === req.user_id) {
- // TODO: unless force-joined
- rights.hasThrow("SELF_LEAVE_GROUPS");
- } else {
- rights.hasThrow("KICK_BAN_MEMBERS");
- permission.hasThrow("KICK_MEMBERS");
- }
+ "/",
+ route({
+ responses: {
+ 204: {},
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id, member_id } = req.params;
+ const permission = await getPermission(req.user_id, guild_id);
+ const rights = await getRights(req.user_id);
+ if (member_id === "@me" || member_id === req.user_id) {
+ // TODO: unless force-joined
+ rights.hasThrow("SELF_LEAVE_GROUPS");
+ } else {
+ rights.hasThrow("KICK_BAN_MEMBERS");
+ permission.hasThrow("KICK_MEMBERS");
+ }
- await Member.removeFromGuild(member_id, guild_id);
- res.sendStatus(204);
- },
+ await Member.removeFromGuild(member_id, guild_id);
+ res.sendStatus(204);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/members/\043member_id/nick.ts" "b/src/api/routes/guilds/\043guild_id/members/\043member_id/nick.ts"
index 2a70777..33f8915 100644
--- "a/src/api/routes/guilds/\043guild_id/members/\043member_id/nick.ts"
+++ "b/src/api/routes/guilds/\043guild_id/members/\043member_id/nick.ts"
@@ -23,38 +23,38 @@
const router = Router({ mergeParams: true });
router.patch(
- "/",
- route({
- requestBody: "MemberNickChangeSchema",
- responses: {
- 200: {
- body: "APIPublicMember",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- let permissionString: PermissionResolvable = "MANAGE_NICKNAMES";
- const member_id = req.params.member_id === "@me" ? ((permissionString = "CHANGE_NICKNAME"), req.user_id) : req.params.member_id;
+ "/",
+ route({
+ requestBody: "MemberNickChangeSchema",
+ responses: {
+ 200: {
+ body: "APIPublicMember",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ let permissionString: PermissionResolvable = "MANAGE_NICKNAMES";
+ const member_id = req.params.member_id === "@me" ? ((permissionString = "CHANGE_NICKNAME"), req.user_id) : req.params.member_id;
- const perms = await getPermission(req.user_id, guild_id);
- perms.hasThrow(permissionString);
+ const perms = await getPermission(req.user_id, guild_id);
+ perms.hasThrow(permissionString);
- await Member.changeNickname(member_id, guild_id, req.body.nick);
+ await Member.changeNickname(member_id, guild_id, req.body.nick);
- const member = await Member.findOne({
- where: { id: member_id, guild_id },
- relations: ["roles"],
- });
+ const member = await Member.findOne({
+ where: { id: member_id, guild_id },
+ relations: ["roles"],
+ });
- res.send(member?.toPublicMember());
- },
+ res.send(member?.toPublicMember());
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/members/\043member_id/roles/\043role_id/index.ts" "b/src/api/routes/guilds/\043guild_id/members/\043member_id/roles/\043role_id/index.ts"
index 5a5bfdf..d482c06 100644
--- "a/src/api/routes/guilds/\043guild_id/members/\043member_id/roles/\043role_id/index.ts"
+++ "b/src/api/routes/guilds/\043guild_id/members/\043member_id/roles/\043role_id/index.ts"
@@ -23,39 +23,39 @@
const router = Router({ mergeParams: true });
router.delete(
- "/",
- route({
- permission: "MANAGE_ROLES",
- responses: {
- 204: {},
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id, role_id, member_id } = req.params;
+ "/",
+ route({
+ permission: "MANAGE_ROLES",
+ responses: {
+ 204: {},
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id, role_id, member_id } = req.params;
- await Member.removeRole(member_id, guild_id, role_id);
- res.sendStatus(204);
- },
+ await Member.removeRole(member_id, guild_id, role_id);
+ res.sendStatus(204);
+ },
);
router.put(
- "/",
- route({
- permission: "MANAGE_ROLES",
- responses: {
- 204: {},
- 403: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id, role_id, member_id } = req.params;
+ "/",
+ route({
+ permission: "MANAGE_ROLES",
+ responses: {
+ 204: {},
+ 403: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id, role_id, member_id } = req.params;
- await Member.addRole(member_id, guild_id, role_id);
- res.sendStatus(204);
- },
+ await Member.addRole(member_id, guild_id, role_id);
+ res.sendStatus(204);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/members/index.ts" "b/src/api/routes/guilds/\043guild_id/members/index.ts"
index a047472..08b7707 100644
--- "a/src/api/routes/guilds/\043guild_id/members/index.ts"
+++ "b/src/api/routes/guilds/\043guild_id/members/index.ts"
@@ -29,44 +29,44 @@
// TODO: check for GUILD_MEMBERS intent
router.get(
- "/",
- route({
- query: {
- limit: {
- type: "number",
- description: "max number of members to return (1-1000). default 1",
- },
- after: {
- type: "string",
- },
- },
- responses: {
- 200: {
- body: "APIMemberArray",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- const limit = Number(req.query.limit) || 1;
- if (limit > 1000 || limit < 1) throw new HTTPError("Limit must be between 1 and 1000");
- const after = `${req.query.after}`;
- const query = after ? { id: MoreThan(after) } : {};
+ "/",
+ route({
+ query: {
+ limit: {
+ type: "number",
+ description: "max number of members to return (1-1000). default 1",
+ },
+ after: {
+ type: "string",
+ },
+ },
+ responses: {
+ 200: {
+ body: "APIMemberArray",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ const limit = Number(req.query.limit) || 1;
+ if (limit > 1000 || limit < 1) throw new HTTPError("Limit must be between 1 and 1000");
+ const after = `${req.query.after}`;
+ const query = after ? { id: MoreThan(after) } : {};
- await Member.IsInGuildOrFail(req.user_id, guild_id);
+ await Member.IsInGuildOrFail(req.user_id, guild_id);
- const members = await Member.find({
- where: { guild_id, ...query },
- select: PublicMemberProjection,
- take: limit,
- order: { id: "ASC" },
- });
+ const members = await Member.find({
+ where: { guild_id, ...query },
+ select: PublicMemberProjection,
+ take: limit,
+ order: { id: "ASC" },
+ });
- return res.json(members);
- },
+ return res.json(members);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/messages/search.ts" "b/src/api/routes/guilds/\043guild_id/messages/search.ts"
index 6532b53..be00d5d 100644
--- "a/src/api/routes/guilds/\043guild_id/messages/search.ts"
+++ "b/src/api/routes/guilds/\043guild_id/messages/search.ts"
@@ -27,125 +27,125 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "GuildMessagesSearchResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 422: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const {
- channel_id,
- content,
- // include_nsfw, // TODO
- offset,
- sort_order,
- // sort_by, // TODO: Handle 'relevance'
- limit,
- author_id,
- } = req.query;
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "GuildMessagesSearchResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 422: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const {
+ channel_id,
+ content,
+ // include_nsfw, // TODO
+ offset,
+ sort_order,
+ // sort_by, // TODO: Handle 'relevance'
+ limit,
+ author_id,
+ } = req.query;
- const parsedLimit = Number(limit) || 50;
- if (parsedLimit < 1 || parsedLimit > 100) throw new HTTPError("limit must be between 1 and 100", 422);
+ const parsedLimit = Number(limit) || 50;
+ if (parsedLimit < 1 || parsedLimit > 100) throw new HTTPError("limit must be between 1 and 100", 422);
- if (sort_order) {
- if (typeof sort_order != "string" || ["desc", "asc"].indexOf(sort_order) == -1)
- throw FieldErrors({
- sort_order: {
- message: "Value must be one of ('desc', 'asc').",
- code: "BASE_TYPE_CHOICES",
- },
- }); // todo this is wrong
- }
+ if (sort_order) {
+ if (typeof sort_order != "string" || ["desc", "asc"].indexOf(sort_order) == -1)
+ throw FieldErrors({
+ sort_order: {
+ message: "Value must be one of ('desc', 'asc').",
+ code: "BASE_TYPE_CHOICES",
+ },
+ }); // todo this is wrong
+ }
- const permissions = await getPermission(req.user_id, req.params.guild_id, channel_id as string | undefined);
- permissions.hasThrow("VIEW_CHANNEL");
- if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json({ messages: [], total_results: 0 });
+ const permissions = await getPermission(req.user_id, req.params.guild_id, channel_id as string | undefined);
+ permissions.hasThrow("VIEW_CHANNEL");
+ if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json({ messages: [], total_results: 0 });
- const query: FindManyOptions = {
- order: {
- timestamp: sort_order ? (sort_order.toUpperCase() as "ASC" | "DESC") : "DESC",
- },
- take: parsedLimit || 0,
- where: {
- guild: {
- id: req.params.guild_id,
- },
- },
- relations: ["author", "webhook", "application", "mentions", "mention_roles", "mention_channels", "sticker_items", "attachments"],
- skip: offset ? Number(offset) : 0,
- };
- //@ts-ignore
- if (channel_id) query.where.channel = { id: channel_id };
- else {
- // get all channel IDs that this user can access
- const channels = await Channel.find({
- where: { guild_id: req.params.guild_id },
- select: ["id"],
- });
- const ids = [];
+ const query: FindManyOptions = {
+ order: {
+ timestamp: sort_order ? (sort_order.toUpperCase() as "ASC" | "DESC") : "DESC",
+ },
+ take: parsedLimit || 0,
+ where: {
+ guild: {
+ id: req.params.guild_id,
+ },
+ },
+ relations: ["author", "webhook", "application", "mentions", "mention_roles", "mention_channels", "sticker_items", "attachments"],
+ skip: offset ? Number(offset) : 0,
+ };
+ //@ts-ignore
+ if (channel_id) query.where.channel = { id: channel_id };
+ else {
+ // get all channel IDs that this user can access
+ const channels = await Channel.find({
+ where: { guild_id: req.params.guild_id },
+ select: ["id"],
+ });
+ const ids = [];
- for (const channel of channels) {
- const perm = await getPermission(req.user_id, req.params.guild_id, channel.id);
- if (!perm.has("VIEW_CHANNEL") || !perm.has("READ_MESSAGE_HISTORY")) continue;
- ids.push(channel.id);
- }
+ for (const channel of channels) {
+ const perm = await getPermission(req.user_id, req.params.guild_id, channel.id);
+ if (!perm.has("VIEW_CHANNEL") || !perm.has("READ_MESSAGE_HISTORY")) continue;
+ ids.push(channel.id);
+ }
- //@ts-ignore
- query.where.channel = { id: In(ids) };
- }
- //@ts-ignore
- if (author_id) query.where.author = { id: author_id };
- //@ts-ignore
- if (content) query.where.content = Like(`%${content}%`);
+ //@ts-ignore
+ query.where.channel = { id: In(ids) };
+ }
+ //@ts-ignore
+ if (author_id) query.where.author = { id: author_id };
+ //@ts-ignore
+ if (content) query.where.content = Like(`%${content}%`);
- const messages: Message[] = await Message.find(query);
- delete query.take;
- const total_results = await Message.count(query);
+ const messages: Message[] = await Message.find(query);
+ delete query.take;
+ const total_results = await Message.count(query);
- const messagesDto = messages.map((x) => [
- {
- id: x.id,
- type: x.type,
- content: x.content,
- channel_id: x.channel_id,
- author: {
- id: x.author?.id,
- username: x.author?.username,
- avatar: x.author?.avatar,
- avatar_decoration: null,
- discriminator: x.author?.discriminator,
- public_flags: x.author?.public_flags,
- },
- attachments: x.attachments,
- embeds: x.embeds,
- mentions: x.mentions,
- mention_roles: x.mention_roles,
- pinned: x.pinned,
- mention_everyone: x.mention_everyone,
- tts: x.tts,
- timestamp: x.timestamp,
- edited_timestamp: x.edited_timestamp,
- flags: x.flags,
- components: x.components,
- poll: x.poll,
- hit: true,
- },
- ]);
+ const messagesDto = messages.map((x) => [
+ {
+ id: x.id,
+ type: x.type,
+ content: x.content,
+ channel_id: x.channel_id,
+ author: {
+ id: x.author?.id,
+ username: x.author?.username,
+ avatar: x.author?.avatar,
+ avatar_decoration: null,
+ discriminator: x.author?.discriminator,
+ public_flags: x.author?.public_flags,
+ },
+ attachments: x.attachments,
+ embeds: x.embeds,
+ mentions: x.mentions,
+ mention_roles: x.mention_roles,
+ pinned: x.pinned,
+ mention_everyone: x.mention_everyone,
+ tts: x.tts,
+ timestamp: x.timestamp,
+ edited_timestamp: x.edited_timestamp,
+ flags: x.flags,
+ components: x.components,
+ poll: x.poll,
+ hit: true,
+ },
+ ]);
- return res.json({
- messages: messagesDto,
- total_results,
- });
- },
+ return res.json({
+ messages: messagesDto,
+ total_results,
+ });
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/premium.ts" "b/src/api/routes/guilds/\043guild_id/premium.ts"
index b72ded2..fc0d34b 100644
--- "a/src/api/routes/guilds/\043guild_id/premium.ts"
+++ "b/src/api/routes/guilds/\043guild_id/premium.ts"
@@ -21,8 +21,8 @@
const router = Router({ mergeParams: true });
router.get("/subscriptions", route({}), async (req: Request, res: Response) => {
- // TODO:
- res.json([]);
+ // TODO:
+ res.json([]);
});
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/profile.ts" "b/src/api/routes/guilds/\043guild_id/profile.ts"
index 4b263fb..176c612 100644
--- "a/src/api/routes/guilds/\043guild_id/profile.ts"
+++ "b/src/api/routes/guilds/\043guild_id/profile.ts"
@@ -24,43 +24,43 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- "200": {
- body: "GuildProfileResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
- const profileResponse: GuildProfileResponse = {
- id: guild_id,
- name: guild.name,
- icon_hash: guild.icon ?? null,
- member_count: guild.member_count!,
- online_count: guild.member_count!,
- description: guild.description ?? "A Spacebar guild",
- brand_color_primary: "#FF00FF",
- banner_hash: null,
- game_application_ids: [], // We don't track this
- game_activity: {}, // We don't track this
- tag: guild.name.substring(0, 4).toUpperCase(), // TODO: allow custom tags
- badge: 0,
- badge_color_primary: "#FF00FF",
- badge_color_secondary: "#00FFFF",
- badge_hash: "",
- traits: [],
- features: guild.features ?? [],
- visibility: GuildVisibilityLevel.PUBLIC,
- custom_banner_hash: guild.banner ?? null,
- premium_subscription_count: guild.premium_subscription_count ?? 0,
- premium_tier: guild.premium_tier ?? 0,
- };
+ "/",
+ route({
+ responses: {
+ "200": {
+ body: "GuildProfileResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
+ const profileResponse: GuildProfileResponse = {
+ id: guild_id,
+ name: guild.name,
+ icon_hash: guild.icon ?? null,
+ member_count: guild.member_count!,
+ online_count: guild.member_count!,
+ description: guild.description ?? "A Spacebar guild",
+ brand_color_primary: "#FF00FF",
+ banner_hash: null,
+ game_application_ids: [], // We don't track this
+ game_activity: {}, // We don't track this
+ tag: guild.name.substring(0, 4).toUpperCase(), // TODO: allow custom tags
+ badge: 0,
+ badge_color_primary: "#FF00FF",
+ badge_color_secondary: "#00FFFF",
+ badge_hash: "",
+ traits: [],
+ features: guild.features ?? [],
+ visibility: GuildVisibilityLevel.PUBLIC,
+ custom_banner_hash: guild.banner ?? null,
+ premium_subscription_count: guild.premium_subscription_count ?? 0,
+ premium_tier: guild.premium_tier ?? 0,
+ };
- res.send(profileResponse);
- },
+ res.send(profileResponse);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/profile/index.ts" "b/src/api/routes/guilds/\043guild_id/profile/index.ts"
index 8f0e385..7a944b1 100644
--- "a/src/api/routes/guilds/\043guild_id/profile/index.ts"
+++ "b/src/api/routes/guilds/\043guild_id/profile/index.ts"
@@ -24,47 +24,47 @@
const router = Router({ mergeParams: true });
router.patch(
- "/:member_id",
- route({
- requestBody: "MemberChangeProfileSchema",
- responses: {
- 200: {
- body: "Member",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- // const member_id =
- // req.params.member_id === "@me" ? req.user_id : req.params.member_id;
- const body = req.body as MemberChangeProfileSchema;
+ "/:member_id",
+ route({
+ requestBody: "MemberChangeProfileSchema",
+ responses: {
+ 200: {
+ body: "Member",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ // const member_id =
+ // req.params.member_id === "@me" ? req.user_id : req.params.member_id;
+ const body = req.body as MemberChangeProfileSchema;
- let member = await Member.findOneOrFail({
- where: { id: req.user_id, guild_id },
- relations: ["roles", "user"],
- });
+ let member = await Member.findOneOrFail({
+ where: { id: req.user_id, guild_id },
+ relations: ["roles", "user"],
+ });
- if (body.banner) body.banner = await handleFile(`/guilds/${guild_id}/users/${req.user_id}/avatars`, body.banner as string);
+ if (body.banner) body.banner = await handleFile(`/guilds/${guild_id}/users/${req.user_id}/avatars`, body.banner as string);
- member = await OrmUtils.mergeDeep(member, body);
+ member = await OrmUtils.mergeDeep(member, body);
- await member.save();
+ await member.save();
- // do not use promise.all as we have to first write to db before emitting the event to catch errors
- await emitEvent({
- event: "GUILD_MEMBER_UPDATE",
- guild_id,
- data: { ...member, roles: member.roles.map((x) => x.id) },
- } as GuildMemberUpdateEvent);
+ // do not use promise.all as we have to first write to db before emitting the event to catch errors
+ await emitEvent({
+ event: "GUILD_MEMBER_UPDATE",
+ guild_id,
+ data: { ...member, roles: member.roles.map((x) => x.id) },
+ } as GuildMemberUpdateEvent);
- res.json(member);
- },
+ res.json(member);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/prune.ts" "b/src/api/routes/guilds/\043guild_id/prune.ts"
index 47984e0..c8a42b8 100644
--- "a/src/api/routes/guilds/\043guild_id/prune.ts"
+++ "b/src/api/routes/guilds/\043guild_id/prune.ts"
@@ -24,102 +24,102 @@
//Returns all inactive members, respecting role hierarchy
const inactiveMembers = async (guild_id: string, user_id: string, days: number, roles: string[] = []) => {
- const date = new Date();
- date.setDate(date.getDate() - days);
- //Snowflake should have `generateFromTime` method? Or similar?
- const minId = BigInt(date.valueOf() - Snowflake.EPOCH) << BigInt(22);
+ const date = new Date();
+ date.setDate(date.getDate() - days);
+ //Snowflake should have `generateFromTime` method? Or similar?
+ const minId = BigInt(date.valueOf() - Snowflake.EPOCH) << BigInt(22);
- /**
+ /**
idea: ability to customise the cutoff variable
possible candidates: public read receipt, last presence, last VC leave
**/
- let members = await Member.find({
- where: [
- {
- guild_id,
- last_message_id: LessThan(minId.toString()),
- },
- {
- guild_id,
- last_message_id: IsNull(),
- },
- ],
- relations: ["roles"],
- });
- if (!members.length) return [];
+ let members = await Member.find({
+ where: [
+ {
+ guild_id,
+ last_message_id: LessThan(minId.toString()),
+ },
+ {
+ guild_id,
+ last_message_id: IsNull(),
+ },
+ ],
+ relations: ["roles"],
+ });
+ if (!members.length) return [];
- //I'm sure I can do this in the above db query ( and it would probably be better to do so ), but oh well.
- if (roles.length && members.length) members = members.filter((user) => user.roles?.some((role) => roles.includes(role.id)));
+ //I'm sure I can do this in the above db query ( and it would probably be better to do so ), but oh well.
+ if (roles.length && members.length) members = members.filter((user) => user.roles?.some((role) => roles.includes(role.id)));
- const me = await Member.findOneOrFail({
- where: { id: user_id, guild_id },
- relations: ["roles"],
- });
- const myHighestRole = Math.max(...(me.roles?.map((x) => x.position) || []));
+ const me = await Member.findOneOrFail({
+ where: { id: user_id, guild_id },
+ relations: ["roles"],
+ });
+ const myHighestRole = Math.max(...(me.roles?.map((x) => x.position) || []));
- const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
- members = members.filter(
- (member) =>
- member.id !== guild.owner_id && //can't kick owner
- member.roles?.some(
- (role) =>
- role.position < myHighestRole || //roles higher than me can't be kicked
- me.id === guild.owner_id, //owner can kick anyone
- ),
- );
+ members = members.filter(
+ (member) =>
+ member.id !== guild.owner_id && //can't kick owner
+ member.roles?.some(
+ (role) =>
+ role.position < myHighestRole || //roles higher than me can't be kicked
+ me.id === guild.owner_id, //owner can kick anyone
+ ),
+ );
- return members;
+ return members;
};
router.get(
- "/",
- route({
- responses: {
- "200": {
- body: "GuildPruneResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const days = parseInt(req.query.days as string);
+ "/",
+ route({
+ responses: {
+ "200": {
+ body: "GuildPruneResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const days = parseInt(req.query.days as string);
- let roles = req.query.include_roles;
- if (typeof roles === "string") roles = [roles]; //express will return array otherwise
+ let roles = req.query.include_roles;
+ if (typeof roles === "string") roles = [roles]; //express will return array otherwise
- const members = await inactiveMembers(req.params.guild_id, req.user_id, days, roles as string[]);
+ const members = await inactiveMembers(req.params.guild_id, req.user_id, days, roles as string[]);
- res.send({ pruned: members.length });
- },
+ res.send({ pruned: members.length });
+ },
);
router.post(
- "/",
- route({
- permission: "KICK_MEMBERS",
- right: "KICK_BAN_MEMBERS",
- responses: {
- 200: {
- body: "GuildPurgeResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const days = parseInt(req.body.days);
+ "/",
+ route({
+ permission: "KICK_MEMBERS",
+ right: "KICK_BAN_MEMBERS",
+ responses: {
+ 200: {
+ body: "GuildPurgeResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const days = parseInt(req.body.days);
- let roles = req.query.include_roles;
- if (typeof roles === "string") roles = [roles];
+ let roles = req.query.include_roles;
+ if (typeof roles === "string") roles = [roles];
- const { guild_id } = req.params;
- const members = await inactiveMembers(guild_id, req.user_id, days, roles as string[]);
+ const { guild_id } = req.params;
+ const members = await inactiveMembers(guild_id, req.user_id, days, roles as string[]);
- await Promise.all(members.map((x) => Member.removeFromGuild(x.id, guild_id)));
+ await Promise.all(members.map((x) => Member.removeFromGuild(x.id, guild_id)));
- res.send({ purged: members.length });
- },
+ res.send({ purged: members.length });
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/regions.ts" "b/src/api/routes/guilds/\043guild_id/regions.ts"
index a3c5a81..b2a311d 100644
--- "a/src/api/routes/guilds/\043guild_id/regions.ts"
+++ "b/src/api/routes/guilds/\043guild_id/regions.ts"
@@ -23,23 +23,23 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APIGuildVoiceRegion",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
- //TODO we should use an enum for guild's features and not hardcoded strings
- return res.json(await getVoiceRegions(req.ip!, guild.features.includes("VIP_REGIONS")));
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APIGuildVoiceRegion",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
+ //TODO we should use an enum for guild's features and not hardcoded strings
+ return res.json(await getVoiceRegions(req.ip!, guild.features.includes("VIP_REGIONS")));
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/roles/\043role_id/index.ts" "b/src/api/routes/guilds/\043guild_id/roles/\043role_id/index.ts"
index b8349eb..1811284 100644
--- "a/src/api/routes/guilds/\043guild_id/roles/\043role_id/index.ts"
+++ "b/src/api/routes/guilds/\043guild_id/roles/\043role_id/index.ts"
@@ -25,121 +25,121 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "Role",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id, role_id } = req.params;
- await Member.IsInGuildOrFail(req.user_id, guild_id);
- const role = await Role.findOneOrFail({
- where: { guild_id, id: role_id },
- });
- return res.json(role);
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "Role",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id, role_id } = req.params;
+ await Member.IsInGuildOrFail(req.user_id, guild_id);
+ const role = await Role.findOneOrFail({
+ where: { guild_id, id: role_id },
+ });
+ return res.json(role);
+ },
);
router.delete(
- "/",
- route({
- permission: "MANAGE_ROLES",
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id, role_id } = req.params;
- if (role_id === guild_id) throw new HTTPError("You can't delete the @everyone role");
+ "/",
+ route({
+ permission: "MANAGE_ROLES",
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id, role_id } = req.params;
+ if (role_id === guild_id) throw new HTTPError("You can't delete the @everyone role");
- await Promise.all([
- Role.delete({
- id: role_id,
- guild_id: guild_id,
- }),
- emitEvent({
- event: "GUILD_ROLE_DELETE",
- guild_id,
- data: {
- guild_id,
- role_id,
- },
- } as GuildRoleDeleteEvent),
- ]);
+ await Promise.all([
+ Role.delete({
+ id: role_id,
+ guild_id: guild_id,
+ }),
+ emitEvent({
+ event: "GUILD_ROLE_DELETE",
+ guild_id,
+ data: {
+ guild_id,
+ role_id,
+ },
+ } as GuildRoleDeleteEvent),
+ ]);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
// TODO: check role hierarchy
router.patch(
- "/",
- route({
- requestBody: "RoleModifySchema",
- permission: "MANAGE_ROLES",
- responses: {
- 200: {
- body: "Role",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { role_id, guild_id } = req.params;
- const body = req.body as RoleModifySchema;
+ "/",
+ route({
+ requestBody: "RoleModifySchema",
+ permission: "MANAGE_ROLES",
+ responses: {
+ 200: {
+ body: "Role",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { role_id, guild_id } = req.params;
+ const body = req.body as RoleModifySchema;
- if (body.icon && body.icon.length) body.icon = await handleFile(`/role-icons/${role_id}`, body.icon as string);
- else body.icon = undefined;
+ if (body.icon && body.icon.length) body.icon = await handleFile(`/role-icons/${role_id}`, body.icon as string);
+ else body.icon = undefined;
- const role = await Role.findOneOrFail({
- where: { id: role_id, guild: { id: guild_id } },
- });
- role.assign({
- ...body,
- permissions: String((req.permission?.bitfield || 0n) & BigInt(body.permissions || "0")),
- });
+ const role = await Role.findOneOrFail({
+ where: { id: role_id, guild: { id: guild_id } },
+ });
+ role.assign({
+ ...body,
+ permissions: String((req.permission?.bitfield || 0n) & BigInt(body.permissions || "0")),
+ });
- await Promise.all([
- role.save(),
- emitEvent({
- event: "GUILD_ROLE_UPDATE",
- guild_id,
- data: {
- guild_id,
- role,
- },
- } as GuildRoleUpdateEvent),
- ]);
+ await Promise.all([
+ role.save(),
+ emitEvent({
+ event: "GUILD_ROLE_UPDATE",
+ guild_id,
+ data: {
+ guild_id,
+ role,
+ },
+ } as GuildRoleUpdateEvent),
+ ]);
- res.json(role);
- },
+ res.json(role);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/roles/\043role_id/member-ids.ts" "b/src/api/routes/guilds/\043guild_id/roles/\043role_id/member-ids.ts"
index 6558da5..ab61325 100644
--- "a/src/api/routes/guilds/\043guild_id/roles/\043role_id/member-ids.ts"
+++ "b/src/api/routes/guilds/\043guild_id/roles/\043role_id/member-ids.ts"
@@ -23,20 +23,20 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- const { guild_id, role_id } = req.params;
+ const { guild_id, role_id } = req.params;
- // TODO: Is this route really not paginated?
- const members = await Member.find({
- select: ["id"],
- where: {
- roles: {
- id: role_id,
- },
- guild_id,
- },
- });
+ // TODO: Is this route really not paginated?
+ const members = await Member.find({
+ select: ["id"],
+ where: {
+ roles: {
+ id: role_id,
+ },
+ guild_id,
+ },
+ });
- return res.json(members.map((x) => x.id));
+ return res.json(members.map((x) => x.id));
});
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/roles/\043role_id/members.ts" "b/src/api/routes/guilds/\043guild_id/roles/\043role_id/members.ts"
index d22d143..f89d593 100644
--- "a/src/api/routes/guilds/\043guild_id/roles/\043role_id/members.ts"
+++ "b/src/api/routes/guilds/\043guild_id/roles/\043role_id/members.ts"
@@ -23,24 +23,24 @@
const router = Router({ mergeParams: true });
router.patch("/", route({ permission: "MANAGE_ROLES" }), async (req: Request, res: Response) => {
- // Payload is JSON containing a list of member_ids, the new list of members to have the role
- const { guild_id, role_id } = req.params;
- const { member_ids } = req.body;
+ // Payload is JSON containing a list of member_ids, the new list of members to have the role
+ const { guild_id, role_id } = req.params;
+ const { member_ids } = req.body;
- // don't mess with @everyone
- if (role_id == guild_id) throw DiscordApiErrors.INVALID_ROLE;
+ // don't mess with @everyone
+ if (role_id == guild_id) throw DiscordApiErrors.INVALID_ROLE;
- const members = await Member.find({
- where: { guild_id },
- relations: ["roles"],
- });
+ const members = await Member.find({
+ where: { guild_id },
+ relations: ["roles"],
+ });
- const [add, remove] = arrayPartition(members, (member) => member_ids.includes(member.id) && !member.roles.map((role) => role.id).includes(role_id));
+ const [add, remove] = arrayPartition(members, (member) => member_ids.includes(member.id) && !member.roles.map((role) => role.id).includes(role_id));
- // TODO (erkin): have a bulk add/remove function that adds the roles in a single txn
- await Promise.all([...add.map((member) => Member.addRole(member.id, guild_id, role_id)), ...remove.map((member) => Member.removeRole(member.id, guild_id, role_id))]);
+ // TODO (erkin): have a bulk add/remove function that adds the roles in a single txn
+ await Promise.all([...add.map((member) => Member.addRole(member.id, guild_id, role_id)), ...remove.map((member) => Member.removeRole(member.id, guild_id, role_id))]);
- res.sendStatus(204);
+ res.sendStatus(204);
});
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/roles/index.ts" "b/src/api/routes/guilds/\043guild_id/roles/index.ts"
index 26584e9..8caea56 100644
--- "a/src/api/routes/guilds/\043guild_id/roles/index.ts"
+++ "b/src/api/routes/guilds/\043guild_id/roles/index.ts"
@@ -25,129 +25,129 @@
const router: Router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- const guild_id = req.params.guild_id;
+ const guild_id = req.params.guild_id;
- await Member.IsInGuildOrFail(req.user_id, guild_id);
+ await Member.IsInGuildOrFail(req.user_id, guild_id);
- const roles = await Role.find({ where: { guild_id: guild_id } });
+ const roles = await Role.find({ where: { guild_id: guild_id } });
- return res.json(roles);
+ return res.json(roles);
});
router.post(
- "/",
- route({
- requestBody: "RoleModifySchema",
- permission: "MANAGE_ROLES",
- responses: {
- 200: {
- body: "Role",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const guild_id = req.params.guild_id;
- const body = req.body as RoleModifySchema;
+ "/",
+ route({
+ requestBody: "RoleModifySchema",
+ permission: "MANAGE_ROLES",
+ responses: {
+ 200: {
+ body: "Role",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const guild_id = req.params.guild_id;
+ const body = req.body as RoleModifySchema;
- const role_count = await Role.count({ where: { guild_id } });
- const { maxRoles } = Config.get().limits.guild;
+ const role_count = await Role.count({ where: { guild_id } });
+ const { maxRoles } = Config.get().limits.guild;
- if (role_count > maxRoles) throw DiscordApiErrors.MAXIMUM_ROLES.withParams(maxRoles);
+ if (role_count > maxRoles) throw DiscordApiErrors.MAXIMUM_ROLES.withParams(maxRoles);
- const role = Role.create({
- // values before ...body are default and can be overridden
- position: 1,
- hoist: false,
- color: 0,
- mentionable: false,
- ...body,
- guild_id: guild_id,
- managed: false,
- permissions: String((req.permission?.bitfield || 0n) & BigInt(body.permissions || "0")),
- tags: undefined,
- icon: undefined,
- unicode_emoji: undefined,
- id: Snowflake.generate(),
- colors: {
- primary_color: body.colors?.primary_color || body.color || 0,
- secondary_color: body.colors?.secondary_color || undefined, // gradient
- tertiary_color: body.colors?.tertiary_color || undefined, // "holographic"
- },
- });
+ const role = Role.create({
+ // values before ...body are default and can be overridden
+ position: 1,
+ hoist: false,
+ color: 0,
+ mentionable: false,
+ ...body,
+ guild_id: guild_id,
+ managed: false,
+ permissions: String((req.permission?.bitfield || 0n) & BigInt(body.permissions || "0")),
+ tags: undefined,
+ icon: undefined,
+ unicode_emoji: undefined,
+ id: Snowflake.generate(),
+ colors: {
+ primary_color: body.colors?.primary_color || body.color || 0,
+ secondary_color: body.colors?.secondary_color || undefined, // gradient
+ tertiary_color: body.colors?.tertiary_color || undefined, // "holographic"
+ },
+ });
- await Promise.all([
- role.save(),
- // Move all existing roles up one position, to accommodate the new role
- Role.createQueryBuilder("roles")
- .where({
- guild: { id: guild_id },
- name: Not("@everyone"),
- id: Not(role.id),
- })
- .update({ position: () => "position + 1" })
- .execute(),
- emitEvent({
- event: "GUILD_ROLE_CREATE",
- guild_id,
- data: {
- guild_id,
- role: role,
- },
- } as GuildRoleCreateEvent),
- ]);
+ await Promise.all([
+ role.save(),
+ // Move all existing roles up one position, to accommodate the new role
+ Role.createQueryBuilder("roles")
+ .where({
+ guild: { id: guild_id },
+ name: Not("@everyone"),
+ id: Not(role.id),
+ })
+ .update({ position: () => "position + 1" })
+ .execute(),
+ emitEvent({
+ event: "GUILD_ROLE_CREATE",
+ guild_id,
+ data: {
+ guild_id,
+ role: role,
+ },
+ } as GuildRoleCreateEvent),
+ ]);
- res.json(role);
- },
+ res.json(role);
+ },
);
router.patch(
- "/",
- route({
- requestBody: "RolePositionUpdateSchema",
- permission: "MANAGE_ROLES",
- responses: {
- 200: {
- body: "APIRoleArray",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- const body = req.body as RolePositionUpdateSchema;
+ "/",
+ route({
+ requestBody: "RolePositionUpdateSchema",
+ permission: "MANAGE_ROLES",
+ responses: {
+ 200: {
+ body: "APIRoleArray",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ const body = req.body as RolePositionUpdateSchema;
- await Promise.all(body.map(async (x) => Role.update({ guild_id, id: x.id }, { position: x.position })));
+ await Promise.all(body.map(async (x) => Role.update({ guild_id, id: x.id }, { position: x.position })));
- const roles = await Role.find({
- where: body.map((x) => ({ id: x.id, guild_id })),
- });
+ const roles = await Role.find({
+ where: body.map((x) => ({ id: x.id, guild_id })),
+ });
- await Promise.all(
- roles.map((x) =>
- emitEvent({
- event: "GUILD_ROLE_UPDATE",
- guild_id,
- data: {
- guild_id,
- role: x,
- },
- } as GuildRoleUpdateEvent),
- ),
- );
+ await Promise.all(
+ roles.map((x) =>
+ emitEvent({
+ event: "GUILD_ROLE_UPDATE",
+ guild_id,
+ data: {
+ guild_id,
+ role: x,
+ },
+ } as GuildRoleUpdateEvent),
+ ),
+ );
- res.json(roles);
- },
+ res.json(roles);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/roles/member-counts.ts" "b/src/api/routes/guilds/\043guild_id/roles/member-counts.ts"
index 5574e59..d77149d 100644
--- "a/src/api/routes/guilds/\043guild_id/roles/member-counts.ts"
+++ "b/src/api/routes/guilds/\043guild_id/roles/member-counts.ts"
@@ -23,16 +23,16 @@
const router: Router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- await Member.IsInGuildOrFail(req.user_id, guild_id);
+ const { guild_id } = req.params;
+ await Member.IsInGuildOrFail(req.user_id, guild_id);
- const role_ids = await Role.find({ where: { guild_id }, select: ["id"] });
- const counts: { [id: string]: number } = {};
- for (const { id } of role_ids) {
- counts[id] = await Member.count({ where: { roles: { id }, guild_id } });
- }
+ const role_ids = await Role.find({ where: { guild_id }, select: ["id"] });
+ const counts: { [id: string]: number } = {};
+ for (const { id } of role_ids) {
+ counts[id] = await Member.count({ where: { roles: { id }, guild_id } });
+ }
- return res.json(counts);
+ return res.json(counts);
});
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/stickers.ts" "b/src/api/routes/guilds/\043guild_id/stickers.ts"
index 231c3b5..f3a9f52 100644
--- "a/src/api/routes/guilds/\043guild_id/stickers.ts"
+++ "b/src/api/routes/guilds/\043guild_id/stickers.ts"
@@ -25,185 +25,185 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APIStickerArray",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- await Member.IsInGuildOrFail(req.user_id, guild_id);
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APIStickerArray",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ await Member.IsInGuildOrFail(req.user_id, guild_id);
- res.json(await Sticker.find({ where: { guild_id } }));
- },
+ res.json(await Sticker.find({ where: { guild_id } }));
+ },
);
const bodyParser = multer({
- limits: {
- fileSize: 1024 * 1024 * 100,
- fields: 10,
- files: 1,
- },
- storage: multer.memoryStorage(),
+ limits: {
+ fileSize: 1024 * 1024 * 100,
+ fields: 10,
+ files: 1,
+ },
+ storage: multer.memoryStorage(),
}).single("file");
router.post(
- "/",
- bodyParser,
- route({
- permission: "MANAGE_EMOJIS_AND_STICKERS",
- requestBody: "ModifyGuildStickerSchema",
- responses: {
- 200: {
- body: "Sticker",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- if (!req.file) throw new HTTPError("missing file");
+ "/",
+ bodyParser,
+ route({
+ permission: "MANAGE_EMOJIS_AND_STICKERS",
+ requestBody: "ModifyGuildStickerSchema",
+ responses: {
+ 200: {
+ body: "Sticker",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ if (!req.file) throw new HTTPError("missing file");
- const { guild_id } = req.params;
- const body = req.body as ModifyGuildStickerSchema;
- const id = Snowflake.generate();
+ const { guild_id } = req.params;
+ const body = req.body as ModifyGuildStickerSchema;
+ const id = Snowflake.generate();
- const sticker_count = await Sticker.count({
- where: { guild_id: guild_id },
- });
- const { maxStickers } = Config.get().limits.guild;
+ const sticker_count = await Sticker.count({
+ where: { guild_id: guild_id },
+ });
+ const { maxStickers } = Config.get().limits.guild;
- if (sticker_count >= maxStickers) throw DiscordApiErrors.MAXIMUM_STICKERS.withParams(maxStickers);
+ if (sticker_count >= maxStickers) throw DiscordApiErrors.MAXIMUM_STICKERS.withParams(maxStickers);
- const [sticker] = await Promise.all([
- Sticker.create({
- ...body,
- guild_id,
- id,
- type: StickerType.GUILD,
- format_type: getStickerFormat(req.file.mimetype),
- available: true,
- }).save(),
- uploadFile(`/stickers/${id}`, req.file),
- ]);
+ const [sticker] = await Promise.all([
+ Sticker.create({
+ ...body,
+ guild_id,
+ id,
+ type: StickerType.GUILD,
+ format_type: getStickerFormat(req.file.mimetype),
+ available: true,
+ }).save(),
+ uploadFile(`/stickers/${id}`, req.file),
+ ]);
- await sendStickerUpdateEvent(guild_id);
+ await sendStickerUpdateEvent(guild_id);
- res.json(sticker);
- },
+ res.json(sticker);
+ },
);
function getStickerFormat(mime_type: string) {
- switch (mime_type) {
- case "image/apng":
- return StickerFormatType.APNG;
- case "application/json":
- return StickerFormatType.LOTTIE;
- case "image/png":
- return StickerFormatType.PNG;
- case "image/gif":
- return StickerFormatType.GIF;
- default:
- throw new HTTPError("invalid sticker format: must be png, apng or lottie");
- }
+ switch (mime_type) {
+ case "image/apng":
+ return StickerFormatType.APNG;
+ case "application/json":
+ return StickerFormatType.LOTTIE;
+ case "image/png":
+ return StickerFormatType.PNG;
+ case "image/gif":
+ return StickerFormatType.GIF;
+ default:
+ throw new HTTPError("invalid sticker format: must be png, apng or lottie");
+ }
}
router.get(
- "/:sticker_id",
- route({
- responses: {
- 200: {
- body: "Sticker",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id, sticker_id } = req.params;
- await Member.IsInGuildOrFail(req.user_id, guild_id);
+ "/:sticker_id",
+ route({
+ responses: {
+ 200: {
+ body: "Sticker",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id, sticker_id } = req.params;
+ await Member.IsInGuildOrFail(req.user_id, guild_id);
- res.json(
- await Sticker.findOneOrFail({
- where: { guild_id, id: sticker_id },
- }),
- );
- },
+ res.json(
+ await Sticker.findOneOrFail({
+ where: { guild_id, id: sticker_id },
+ }),
+ );
+ },
);
router.patch(
- "/:sticker_id",
- route({
- requestBody: "ModifyGuildStickerSchema",
- permission: "MANAGE_EMOJIS_AND_STICKERS",
- responses: {
- 200: {
- body: "Sticker",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id, sticker_id } = req.params;
- const body = req.body as ModifyGuildStickerSchema;
+ "/:sticker_id",
+ route({
+ requestBody: "ModifyGuildStickerSchema",
+ permission: "MANAGE_EMOJIS_AND_STICKERS",
+ responses: {
+ 200: {
+ body: "Sticker",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id, sticker_id } = req.params;
+ const body = req.body as ModifyGuildStickerSchema;
- const sticker = await Sticker.create({
- ...body,
- guild_id,
- id: sticker_id,
- }).save();
- await sendStickerUpdateEvent(guild_id);
+ const sticker = await Sticker.create({
+ ...body,
+ guild_id,
+ id: sticker_id,
+ }).save();
+ await sendStickerUpdateEvent(guild_id);
- return res.json(sticker);
- },
+ return res.json(sticker);
+ },
);
async function sendStickerUpdateEvent(guild_id: string) {
- return emitEvent({
- event: "GUILD_STICKERS_UPDATE",
- guild_id: guild_id,
- data: {
- guild_id: guild_id,
- stickers: await Sticker.find({ where: { guild_id: guild_id } }),
- },
- } as GuildStickersUpdateEvent);
+ return emitEvent({
+ event: "GUILD_STICKERS_UPDATE",
+ guild_id: guild_id,
+ data: {
+ guild_id: guild_id,
+ stickers: await Sticker.find({ where: { guild_id: guild_id } }),
+ },
+ } as GuildStickersUpdateEvent);
}
router.delete(
- "/:sticker_id",
- route({
- permission: "MANAGE_EMOJIS_AND_STICKERS",
- responses: {
- 204: {},
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id, sticker_id } = req.params;
+ "/:sticker_id",
+ route({
+ permission: "MANAGE_EMOJIS_AND_STICKERS",
+ responses: {
+ 204: {},
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id, sticker_id } = req.params;
- await Sticker.delete({ guild_id, id: sticker_id });
- await sendStickerUpdateEvent(guild_id);
+ await Sticker.delete({ guild_id, id: sticker_id });
+ await sendStickerUpdateEvent(guild_id);
- return res.sendStatus(204);
- },
+ return res.sendStatus(204);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/templates.ts" "b/src/api/routes/guilds/\043guild_id/templates.ts"
index ef9d12c..2cc9604 100644
--- "a/src/api/routes/guilds/\043guild_id/templates.ts"
+++ "b/src/api/routes/guilds/\043guild_id/templates.ts"
@@ -24,160 +24,160 @@
const router: Router = Router({ mergeParams: true });
const TemplateGuildProjection: (keyof Guild)[] = [
- "id",
- "name",
- "description",
- "region",
- "verification_level",
- "default_message_notifications",
- "explicit_content_filter",
- "preferred_locale",
- "afk_timeout",
- // "roles",
- // "channels",
- "afk_channel_id",
- "system_channel_id",
- "system_channel_flags",
- "icon",
+ "id",
+ "name",
+ "description",
+ "region",
+ "verification_level",
+ "default_message_notifications",
+ "explicit_content_filter",
+ "preferred_locale",
+ "afk_timeout",
+ // "roles",
+ // "channels",
+ "afk_channel_id",
+ "system_channel_id",
+ "system_channel_flags",
+ "icon",
];
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APITemplateArray",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APITemplateArray",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
- const templates = await Template.find({
- where: { source_guild_id: guild_id },
- });
+ const templates = await Template.find({
+ where: { source_guild_id: guild_id },
+ });
- return res.json(templates);
- },
+ return res.json(templates);
+ },
);
router.post(
- "/",
- route({
- requestBody: "TemplateCreateSchema",
- permission: "MANAGE_GUILD",
- responses: {
- 200: {
- body: "Template",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({
- where: { id: guild_id },
- select: TemplateGuildProjection,
- relations: ["roles", "channels"],
- });
- const exists = await Template.findOne({
- where: { id: guild_id },
- });
- if (exists) throw new HTTPError("Template already exists", 400);
+ "/",
+ route({
+ requestBody: "TemplateCreateSchema",
+ permission: "MANAGE_GUILD",
+ responses: {
+ 200: {
+ body: "Template",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ const guild = await Guild.findOneOrFail({
+ where: { id: guild_id },
+ select: TemplateGuildProjection,
+ relations: ["roles", "channels"],
+ });
+ const exists = await Template.findOne({
+ where: { id: guild_id },
+ });
+ if (exists) throw new HTTPError("Template already exists", 400);
- const template = await Template.create({
- ...req.body,
- code: generateCode(),
- creator_id: req.user_id,
- created_at: new Date(),
- updated_at: new Date(),
- source_guild_id: guild_id,
- serialized_source_guild: guild,
- }).save();
+ const template = await Template.create({
+ ...req.body,
+ code: generateCode(),
+ creator_id: req.user_id,
+ created_at: new Date(),
+ updated_at: new Date(),
+ source_guild_id: guild_id,
+ serialized_source_guild: guild,
+ }).save();
- res.json(template);
- },
+ res.json(template);
+ },
);
router.delete(
- "/:code",
- route({
- permission: "MANAGE_GUILD",
- responses: {
- 200: { body: "Template" },
- 403: { body: "APIErrorResponse" },
- },
- }),
- async (req: Request, res: Response) => {
- const { code, guild_id } = req.params;
+ "/:code",
+ route({
+ permission: "MANAGE_GUILD",
+ responses: {
+ 200: { body: "Template" },
+ 403: { body: "APIErrorResponse" },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { code, guild_id } = req.params;
- const template = await Template.delete({
- code,
- source_guild_id: guild_id,
- });
+ const template = await Template.delete({
+ code,
+ source_guild_id: guild_id,
+ });
- res.json(template);
- },
+ res.json(template);
+ },
);
router.put(
- "/:code",
- route({
- permission: "MANAGE_GUILD",
- responses: {
- 200: { body: "Template" },
- 403: { body: "APIErrorResponse" },
- },
- }),
- async (req: Request, res: Response) => {
- const { code, guild_id } = req.params;
- const guild = await Guild.findOneOrFail({
- where: { id: guild_id },
- select: TemplateGuildProjection,
- });
+ "/:code",
+ route({
+ permission: "MANAGE_GUILD",
+ responses: {
+ 200: { body: "Template" },
+ 403: { body: "APIErrorResponse" },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { code, guild_id } = req.params;
+ const guild = await Guild.findOneOrFail({
+ where: { id: guild_id },
+ select: TemplateGuildProjection,
+ });
- const template = await Template.create({
- code,
- serialized_source_guild: guild,
- }).save();
+ const template = await Template.create({
+ code,
+ serialized_source_guild: guild,
+ }).save();
- res.json(template);
- },
+ res.json(template);
+ },
);
router.patch(
- "/:code",
- route({
- requestBody: "TemplateModifySchema",
- permission: "MANAGE_GUILD",
- responses: {
- 200: { body: "Template" },
- 403: { body: "APIErrorResponse" },
- },
- }),
- async (req: Request, res: Response) => {
- const { code, guild_id } = req.params;
- const { name, description } = req.body;
+ "/:code",
+ route({
+ requestBody: "TemplateModifySchema",
+ permission: "MANAGE_GUILD",
+ responses: {
+ 200: { body: "Template" },
+ 403: { body: "APIErrorResponse" },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { code, guild_id } = req.params;
+ const { name, description } = req.body;
- const template = await Template.findOneOrFail({
- where: { code, source_guild_id: guild_id },
- });
+ const template = await Template.findOneOrFail({
+ where: { code, source_guild_id: guild_id },
+ });
- template.name = name;
- template.description = description;
+ template.name = name;
+ template.description = description;
- await template.save();
+ await template.save();
- res.json(template);
- },
+ res.json(template);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/vanity-url.ts" "b/src/api/routes/guilds/\043guild_id/vanity-url.ts"
index 77d72ed..e622c25 100644
--- "a/src/api/routes/guilds/\043guild_id/vanity-url.ts"
+++ "b/src/api/routes/guilds/\043guild_id/vanity-url.ts"
@@ -27,96 +27,96 @@
const InviteRegex = /\W/g;
router.get(
- "/",
- route({
- permission: "MANAGE_GUILD",
- responses: {
- 200: {
- body: "GuildVanityUrlResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
+ "/",
+ route({
+ permission: "MANAGE_GUILD",
+ responses: {
+ 200: {
+ body: "GuildVanityUrlResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
- if (!guild.features.includes("ALIASABLE_NAMES")) {
- const invite = await Invite.findOne({
- where: { guild_id: guild_id, vanity_url: true },
- });
- if (!invite) return res.json({ code: null });
+ if (!guild.features.includes("ALIASABLE_NAMES")) {
+ const invite = await Invite.findOne({
+ where: { guild_id: guild_id, vanity_url: true },
+ });
+ if (!invite) return res.json({ code: null });
- return res.json({ code: invite.code, uses: invite.uses });
- } else {
- const invite = await Invite.find({
- where: { guild_id: guild_id, vanity_url: true },
- });
- if (!invite || invite.length == 0) return res.json({ code: null });
+ return res.json({ code: invite.code, uses: invite.uses });
+ } else {
+ const invite = await Invite.find({
+ where: { guild_id: guild_id, vanity_url: true },
+ });
+ if (!invite || invite.length == 0) return res.json({ code: null });
- return res.json(invite.map((x) => ({ code: x.code, uses: x.uses })));
- }
- },
+ return res.json(invite.map((x) => ({ code: x.code, uses: x.uses })));
+ }
+ },
);
router.patch(
- "/",
- route({
- requestBody: "VanityUrlSchema",
- permission: "MANAGE_GUILD",
- responses: {
- 200: {
- body: "GuildVanityUrlCreateResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- const body = req.body as VanityUrlSchema;
- const code = body.code?.replace(InviteRegex, "");
+ "/",
+ route({
+ requestBody: "VanityUrlSchema",
+ permission: "MANAGE_GUILD",
+ responses: {
+ 200: {
+ body: "GuildVanityUrlCreateResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ const body = req.body as VanityUrlSchema;
+ const code = body.code?.replace(InviteRegex, "");
- const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
- if (!guild.features.includes("VANITY_URL")) throw new HTTPError("Your guild doesn't support vanity urls");
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
+ if (!guild.features.includes("VANITY_URL")) throw new HTTPError("Your guild doesn't support vanity urls");
- if (!code || code.length === 0) throw new HTTPError("Code cannot be null or empty");
+ if (!code || code.length === 0) throw new HTTPError("Code cannot be null or empty");
- const invite = await Invite.findOne({ where: { code } });
- if (invite) throw new HTTPError("Invite already exists");
+ const invite = await Invite.findOne({ where: { code } });
+ if (invite) throw new HTTPError("Invite already exists");
- const { id } = await Channel.findOneOrFail({
- where: { guild_id, type: ChannelType.GUILD_TEXT },
- });
+ const { id } = await Channel.findOneOrFail({
+ where: { guild_id, type: ChannelType.GUILD_TEXT },
+ });
- if (!guild.features.includes("ALIASABLE_NAMES")) {
- await Invite.delete({ guild_id, vanity_url: true });
- }
+ if (!guild.features.includes("ALIASABLE_NAMES")) {
+ await Invite.delete({ guild_id, vanity_url: true });
+ }
- await Invite.create({
- vanity_url: true,
- code,
- temporary: false,
- uses: 0,
- max_uses: 0,
- max_age: 0,
- created_at: new Date(),
- guild_id: guild_id,
- channel_id: id,
- flags: 0,
- }).save();
+ await Invite.create({
+ vanity_url: true,
+ code,
+ temporary: false,
+ uses: 0,
+ max_uses: 0,
+ max_age: 0,
+ created_at: new Date(),
+ guild_id: guild_id,
+ channel_id: id,
+ flags: 0,
+ }).save();
- return res.json({ code });
- },
+ return res.json({ code });
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/voice-states/\043user_id/index.ts" "b/src/api/routes/guilds/\043guild_id/voice-states/\043user_id/index.ts"
index 38be139..5283ae0 100644
--- "a/src/api/routes/guilds/\043guild_id/voice-states/\043user_id/index.ts"
+++ "b/src/api/routes/guilds/\043guild_id/voice-states/\043user_id/index.ts"
@@ -25,67 +25,67 @@
//TODO need more testing when community guild and voice stage channel are working
router.patch(
- "/",
- route({
- requestBody: "VoiceStateUpdateSchema",
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as VoiceStateUpdateSchema;
- const { guild_id } = req.params;
- const user_id = req.params.user_id === "@me" ? req.user_id : req.params.user_id;
+ "/",
+ route({
+ requestBody: "VoiceStateUpdateSchema",
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as VoiceStateUpdateSchema;
+ const { guild_id } = req.params;
+ const user_id = req.params.user_id === "@me" ? req.user_id : req.params.user_id;
- const perms = await getPermission(req.user_id, guild_id, body.channel_id);
+ const perms = await getPermission(req.user_id, guild_id, body.channel_id);
- /*
+ /*
From https://discord.com/developers/docs/resources/guild#modify-current-user-voice-state
You must have the MUTE_MEMBERS permission to unsuppress others. You can always suppress yourself.
You must have the REQUEST_TO_SPEAK permission to request to speak. You can always clear your own request to speak.
*/
- if (body.suppress && user_id !== req.user_id) {
- perms.hasThrow("MUTE_MEMBERS");
- }
- if (!body.suppress) body.request_to_speak_timestamp = new Date();
- if (body.request_to_speak_timestamp) perms.hasThrow("REQUEST_TO_SPEAK");
+ if (body.suppress && user_id !== req.user_id) {
+ perms.hasThrow("MUTE_MEMBERS");
+ }
+ if (!body.suppress) body.request_to_speak_timestamp = new Date();
+ if (body.request_to_speak_timestamp) perms.hasThrow("REQUEST_TO_SPEAK");
- const voice_state = await VoiceState.findOne({
- where: {
- guild_id,
- channel_id: body.channel_id,
- user_id,
- },
- });
- if (!voice_state) throw DiscordApiErrors.UNKNOWN_VOICE_STATE;
+ const voice_state = await VoiceState.findOne({
+ where: {
+ guild_id,
+ channel_id: body.channel_id,
+ user_id,
+ },
+ });
+ if (!voice_state) throw DiscordApiErrors.UNKNOWN_VOICE_STATE;
- voice_state.assign(body);
- const channel = await Channel.findOneOrFail({
- where: { guild_id, id: body.channel_id },
- });
- if (channel.type !== ChannelType.GUILD_STAGE_VOICE) {
- throw DiscordApiErrors.CANNOT_EXECUTE_ON_THIS_CHANNEL_TYPE;
- }
+ voice_state.assign(body);
+ const channel = await Channel.findOneOrFail({
+ where: { guild_id, id: body.channel_id },
+ });
+ if (channel.type !== ChannelType.GUILD_STAGE_VOICE) {
+ throw DiscordApiErrors.CANNOT_EXECUTE_ON_THIS_CHANNEL_TYPE;
+ }
- await Promise.all([
- voice_state.save(),
- emitEvent({
- event: "VOICE_STATE_UPDATE",
- data: voice_state.toPublicVoiceState(),
- guild_id,
- } as VoiceStateUpdateEvent),
- ]);
- return res.sendStatus(204);
- },
+ await Promise.all([
+ voice_state.save(),
+ emitEvent({
+ event: "VOICE_STATE_UPDATE",
+ data: voice_state.toPublicVoiceState(),
+ guild_id,
+ } as VoiceStateUpdateEvent),
+ ]);
+ return res.sendStatus(204);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/webhooks.ts" "b/src/api/routes/guilds/\043guild_id/webhooks.ts"
index 49f34b6..81837d3 100644
--- "a/src/api/routes/guilds/\043guild_id/webhooks.ts"
+++ "b/src/api/routes/guilds/\043guild_id/webhooks.ts"
@@ -22,31 +22,31 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- description: "Returns a list of guild webhook objects. Requires the MANAGE_WEBHOOKS permission.",
- permission: "MANAGE_WEBHOOKS",
- responses: {
- 200: {
- body: "APIWebhookArray",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- const webhooks = await Webhook.find({
- where: { guild_id },
- relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
- });
+ "/",
+ route({
+ description: "Returns a list of guild webhook objects. Requires the MANAGE_WEBHOOKS permission.",
+ permission: "MANAGE_WEBHOOKS",
+ responses: {
+ 200: {
+ body: "APIWebhookArray",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
+ const webhooks = await Webhook.find({
+ where: { guild_id },
+ relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
+ });
- const instanceUrl = Config.get().api.endpointPublic;
- return res.json(
- webhooks.map((webhook) => ({
- ...webhook,
- url: instanceUrl + "/webhooks/" + webhook.id + "/" + webhook.token,
- })),
- );
- },
+ const instanceUrl = Config.get().api.endpointPublic;
+ return res.json(
+ webhooks.map((webhook) => ({
+ ...webhook,
+ url: instanceUrl + "/webhooks/" + webhook.id + "/" + webhook.token,
+ })),
+ );
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/welcome-screen.ts" "b/src/api/routes/guilds/\043guild_id/welcome-screen.ts"
index a8956ee..474d597 100644
--- "a/src/api/routes/guilds/\043guild_id/welcome-screen.ts"
+++ "b/src/api/routes/guilds/\043guild_id/welcome-screen.ts"
@@ -24,69 +24,69 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "GuildWelcomeScreen",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const guild_id = req.params.guild_id;
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "GuildWelcomeScreen",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const guild_id = req.params.guild_id;
- const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
- await Member.IsInGuildOrFail(req.user_id, guild_id);
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
+ await Member.IsInGuildOrFail(req.user_id, guild_id);
- res.json(guild.welcome_screen);
- },
+ res.json(guild.welcome_screen);
+ },
);
router.patch(
- "/",
- route({
- requestBody: "GuildUpdateWelcomeScreenSchema",
- permission: "MANAGE_GUILD",
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const guild_id = req.params.guild_id;
- const body = req.body as GuildUpdateWelcomeScreenSchema;
+ "/",
+ route({
+ requestBody: "GuildUpdateWelcomeScreenSchema",
+ permission: "MANAGE_GUILD",
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const guild_id = req.params.guild_id;
+ const body = req.body as GuildUpdateWelcomeScreenSchema;
- const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
- if (body.enabled != undefined) guild.welcome_screen.enabled = body.enabled;
+ if (body.enabled != undefined) guild.welcome_screen.enabled = body.enabled;
- if (body.description != undefined) guild.welcome_screen.description = body.description;
+ if (body.description != undefined) guild.welcome_screen.description = body.description;
- if (body.welcome_channels != undefined) {
- // Ensure channels exist within the guild
- await Promise.all(
- body.welcome_channels?.map(({ channel_id }) =>
- Channel.findOneOrFail({
- where: { id: channel_id, guild_id },
- select: { id: true },
- }),
- ) || [],
- );
- guild.welcome_screen.welcome_channels = body.welcome_channels;
- }
+ if (body.welcome_channels != undefined) {
+ // Ensure channels exist within the guild
+ await Promise.all(
+ body.welcome_channels?.map(({ channel_id }) =>
+ Channel.findOneOrFail({
+ where: { id: channel_id, guild_id },
+ select: { id: true },
+ }),
+ ) || [],
+ );
+ guild.welcome_screen.welcome_channels = body.welcome_channels;
+ }
- await guild.save();
+ await guild.save();
- res.status(200).json(guild.welcome_screen);
- },
+ res.status(200).json(guild.welcome_screen);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/widget.json.ts" "b/src/api/routes/guilds/\043guild_id/widget.json.ts"
index d6f958f..8f41417 100644
--- "a/src/api/routes/guilds/\043guild_id/widget.json.ts"
+++ "b/src/api/routes/guilds/\043guild_id/widget.json.ts"
@@ -32,88 +32,88 @@
// https://discord.com/developers/docs/resources/guild#get-guild-widget
// TODO: Cache the response for a guild for 5 minutes regardless of response
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "GuildWidgetJsonResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "GuildWidgetJsonResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({
- where: { id: guild_id },
- select: {
- channel_ordering: true,
- widget_channel_id: true,
- widget_enabled: true,
- presence_count: true,
- name: true,
- },
- });
- if (!guild.widget_enabled) throw DiscordApiErrors.EMBED_DISABLED;
+ const guild = await Guild.findOneOrFail({
+ where: { id: guild_id },
+ select: {
+ channel_ordering: true,
+ widget_channel_id: true,
+ widget_enabled: true,
+ presence_count: true,
+ name: true,
+ },
+ });
+ if (!guild.widget_enabled) throw DiscordApiErrors.EMBED_DISABLED;
- // Fetch existing widget invite for widget channel
- let invite = await Invite.findOne({
- where: { channel_id: guild.widget_channel_id },
- });
+ // Fetch existing widget invite for widget channel
+ let invite = await Invite.findOne({
+ where: { channel_id: guild.widget_channel_id },
+ });
- if (guild.widget_channel_id && !invite) {
- // Create invite for channel if none exists
- // TODO: Refactor invite create code to a shared function
- const max_age = 86400; // 24 hours
- const expires_at = new Date(max_age * 1000 + Date.now());
+ if (guild.widget_channel_id && !invite) {
+ // Create invite for channel if none exists
+ // TODO: Refactor invite create code to a shared function
+ const max_age = 86400; // 24 hours
+ const expires_at = new Date(max_age * 1000 + Date.now());
- invite = await Invite.create({
- code: randomString(),
- temporary: false,
- uses: 0,
- max_uses: 0,
- max_age: max_age,
- expires_at,
- created_at: new Date(),
- guild_id,
- channel_id: guild.widget_channel_id,
- flags: 0,
- }).save();
- }
+ invite = await Invite.create({
+ code: randomString(),
+ temporary: false,
+ uses: 0,
+ max_uses: 0,
+ max_age: max_age,
+ expires_at,
+ created_at: new Date(),
+ guild_id,
+ channel_id: guild.widget_channel_id,
+ flags: 0,
+ }).save();
+ }
- // Fetch voice channels, and the @everyone permissions object
- const channels: { id: string; name: string; position: number }[] = [];
+ // Fetch voice channels, and the @everyone permissions object
+ const channels: { id: string; name: string; position: number }[] = [];
- (await Channel.getOrderedChannels(guild.id, guild)).filter((doc) => {
- // Only return channels where @everyone has the CONNECT permission
- if (doc.permission_overwrites === undefined || Permissions.channelPermission(doc.permission_overwrites, Permissions.FLAGS.CONNECT) === Permissions.FLAGS.CONNECT) {
- channels.push({
- id: doc.id,
- name: doc.name ?? "Unknown channel",
- position: doc.position ?? 0,
- });
- }
- });
+ (await Channel.getOrderedChannels(guild.id, guild)).filter((doc) => {
+ // Only return channels where @everyone has the CONNECT permission
+ if (doc.permission_overwrites === undefined || Permissions.channelPermission(doc.permission_overwrites, Permissions.FLAGS.CONNECT) === Permissions.FLAGS.CONNECT) {
+ channels.push({
+ id: doc.id,
+ name: doc.name ?? "Unknown channel",
+ position: doc.position ?? 0,
+ });
+ }
+ });
- // Fetch members
- // TODO: Understand how Discord's max 100 random member sample works, and apply to here (see top of this file)
- const members = await Member.find({ where: { guild_id: guild_id } });
+ // Fetch members
+ // TODO: Understand how Discord's max 100 random member sample works, and apply to here (see top of this file)
+ const members = await Member.find({ where: { guild_id: guild_id } });
- // Construct object to respond with
- const data = {
- id: guild_id,
- name: guild.name,
- instant_invite: invite?.code,
- channels: channels,
- members: members,
- presence_count: guild.presence_count,
- };
+ // Construct object to respond with
+ const data = {
+ id: guild_id,
+ name: guild.name,
+ instant_invite: invite?.code,
+ channels: channels,
+ members: members,
+ presence_count: guild.presence_count,
+ };
- res.set("Cache-Control", "public, max-age=300");
- return res.json(data);
- },
+ res.set("Cache-Control", "public, max-age=300");
+ return res.json(data);
+ },
);
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/widget.png.ts" "b/src/api/routes/guilds/\043guild_id/widget.png.ts"
index a7a9b60..b0abc95 100644
--- "a/src/api/routes/guilds/\043guild_id/widget.png.ts"
+++ "b/src/api/routes/guilds/\043guild_id/widget.png.ts"
@@ -33,112 +33,112 @@
// https://discord.com/developers/docs/resources/guild#get-guild-widget-image
// TODO: Cache the response
router.get(
- "/",
- route({
- responses: {
- 200: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
+ "/",
+ route({
+ responses: {
+ 200: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
- if (!guild.widget_enabled) throw DiscordApiErrors.EMBED_DISABLED;
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
+ if (!guild.widget_enabled) throw DiscordApiErrors.EMBED_DISABLED;
- // Fetch guild information
- const icon = "avatars/" + guild_id + "/" + guild.icon;
- const name = guild.name;
- const presence = guild.presence_count + " ONLINE";
+ // Fetch guild information
+ const icon = "avatars/" + guild_id + "/" + guild.icon;
+ const name = guild.name;
+ const presence = guild.presence_count + " ONLINE";
- // Fetch parameter
- const style = req.query.style?.toString() || "shield";
- if (!["shield", "banner1", "banner2", "banner3", "banner4"].includes(style)) {
- throw new HTTPError("Value must be one of ('shield', 'banner1', 'banner2', 'banner3', 'banner4').", 400);
- }
+ // Fetch parameter
+ const style = req.query.style?.toString() || "shield";
+ if (!["shield", "banner1", "banner2", "banner3", "banner4"].includes(style)) {
+ throw new HTTPError("Value must be one of ('shield', 'banner1', 'banner2', 'banner3', 'banner4').", 400);
+ }
- // Setup canvas
- const { createCanvas, loadImage } = require("canvas");
- const sizeOf = require("image-size");
+ // Setup canvas
+ const { createCanvas, loadImage } = require("canvas");
+ const sizeOf = require("image-size");
- // TODO: Widget style templates need Spacebar branding
- const source = path.join(__dirname, "..", "..", "..", "..", "..", "assets", "widget", `${style}.png`);
- if (!fs.existsSync(source)) {
- throw new HTTPError("Widget template does not exist.", 400);
- }
+ // TODO: Widget style templates need Spacebar branding
+ const source = path.join(__dirname, "..", "..", "..", "..", "..", "assets", "widget", `${style}.png`);
+ if (!fs.existsSync(source)) {
+ throw new HTTPError("Widget template does not exist.", 400);
+ }
- // Create base template image for parameter
- const { width, height } = await sizeOf(source);
- const canvas = createCanvas(width, height);
- const ctx = canvas.getContext("2d");
- const template = await loadImage(source);
- ctx.drawImage(template, 0, 0);
+ // Create base template image for parameter
+ const { width, height } = await sizeOf(source);
+ const canvas = createCanvas(width, height);
+ const ctx = canvas.getContext("2d");
+ const template = await loadImage(source);
+ ctx.drawImage(template, 0, 0);
- // Add the guild specific information to the template asset image
- switch (style) {
- case "shield":
- ctx.textAlign = "center";
- await drawText(ctx, 73, 13, "#FFFFFF", "thin 10px Verdana", presence);
- break;
- case "banner1":
- if (icon) await drawIcon(ctx, 20, 27, 50, icon);
- await drawText(ctx, 83, 51, "#FFFFFF", "12px Verdana", name, 22);
- await drawText(ctx, 83, 66, "#C9D2F0FF", "thin 11px Verdana", presence);
- break;
- case "banner2":
- if (icon) await drawIcon(ctx, 13, 19, 36, icon);
- await drawText(ctx, 62, 34, "#FFFFFF", "12px Verdana", name, 15);
- await drawText(ctx, 62, 49, "#C9D2F0FF", "thin 11px Verdana", presence);
- break;
- case "banner3":
- if (icon) await drawIcon(ctx, 20, 20, 50, icon);
- await drawText(ctx, 83, 44, "#FFFFFF", "12px Verdana", name, 27);
- await drawText(ctx, 83, 58, "#C9D2F0FF", "thin 11px Verdana", presence);
- break;
- case "banner4":
- if (icon) await drawIcon(ctx, 21, 136, 50, icon);
- await drawText(ctx, 84, 156, "#FFFFFF", "13px Verdana", name, 27);
- await drawText(ctx, 84, 171, "#C9D2F0FF", "thin 12px Verdana", presence);
- break;
- default:
- throw new HTTPError("Value must be one of ('shield', 'banner1', 'banner2', 'banner3', 'banner4').", 400);
- }
+ // Add the guild specific information to the template asset image
+ switch (style) {
+ case "shield":
+ ctx.textAlign = "center";
+ await drawText(ctx, 73, 13, "#FFFFFF", "thin 10px Verdana", presence);
+ break;
+ case "banner1":
+ if (icon) await drawIcon(ctx, 20, 27, 50, icon);
+ await drawText(ctx, 83, 51, "#FFFFFF", "12px Verdana", name, 22);
+ await drawText(ctx, 83, 66, "#C9D2F0FF", "thin 11px Verdana", presence);
+ break;
+ case "banner2":
+ if (icon) await drawIcon(ctx, 13, 19, 36, icon);
+ await drawText(ctx, 62, 34, "#FFFFFF", "12px Verdana", name, 15);
+ await drawText(ctx, 62, 49, "#C9D2F0FF", "thin 11px Verdana", presence);
+ break;
+ case "banner3":
+ if (icon) await drawIcon(ctx, 20, 20, 50, icon);
+ await drawText(ctx, 83, 44, "#FFFFFF", "12px Verdana", name, 27);
+ await drawText(ctx, 83, 58, "#C9D2F0FF", "thin 11px Verdana", presence);
+ break;
+ case "banner4":
+ if (icon) await drawIcon(ctx, 21, 136, 50, icon);
+ await drawText(ctx, 84, 156, "#FFFFFF", "13px Verdana", name, 27);
+ await drawText(ctx, 84, 171, "#C9D2F0FF", "thin 12px Verdana", presence);
+ break;
+ default:
+ throw new HTTPError("Value must be one of ('shield', 'banner1', 'banner2', 'banner3', 'banner4').", 400);
+ }
- // Return final image
- const buffer = canvas.toBuffer("image/png");
- res.set("Content-Type", "image/png");
- res.set("Cache-Control", "public, max-age=3600");
- return res.send(buffer);
- },
+ // Return final image
+ const buffer = canvas.toBuffer("image/png");
+ res.set("Content-Type", "image/png");
+ res.set("Cache-Control", "public, max-age=3600");
+ return res.send(buffer);
+ },
);
async function drawIcon(canvas: any, x: number, y: number, scale: number, icon: string) {
- const { loadImage } = require("canvas");
- const img = await loadImage(await storage.get(icon));
+ const { loadImage } = require("canvas");
+ const img = await loadImage(await storage.get(icon));
- // Do some canvas clipping magic!
- canvas.save();
- canvas.beginPath();
+ // Do some canvas clipping magic!
+ canvas.save();
+ canvas.beginPath();
- const r = scale / 2; // use scale to determine radius
- canvas.arc(x + r, y + r, r, 0, 2 * Math.PI, false); // start circle at x, and y coords + radius to find center
+ const r = scale / 2; // use scale to determine radius
+ canvas.arc(x + r, y + r, r, 0, 2 * Math.PI, false); // start circle at x, and y coords + radius to find center
- canvas.clip();
- canvas.drawImage(img, x, y, scale, scale);
+ canvas.clip();
+ canvas.drawImage(img, x, y, scale, scale);
- canvas.restore();
+ canvas.restore();
}
async function drawText(canvas: any, x: number, y: number, color: string, font: string, text: string, maxcharacters?: number) {
- canvas.fillStyle = color;
- canvas.font = font;
- if (text.length > (maxcharacters || 0) && maxcharacters) text = text.slice(0, maxcharacters) + "...";
- canvas.fillText(text, x, y);
+ canvas.fillStyle = color;
+ canvas.font = font;
+ if (text.length > (maxcharacters || 0) && maxcharacters) text = text.slice(0, maxcharacters) + "...";
+ canvas.fillText(text, x, y);
}
export default router;
diff --git "a/src/api/routes/guilds/\043guild_id/widget.ts" "b/src/api/routes/guilds/\043guild_id/widget.ts"
index cad26f3..5a2fdb9 100644
--- "a/src/api/routes/guilds/\043guild_id/widget.ts"
+++ "b/src/api/routes/guilds/\043guild_id/widget.ts"
@@ -25,62 +25,62 @@
// https://discord.com/developers/docs/resources/guild#get-guild-widget-settings
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "GuildWidgetSettingsResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { guild_id } = req.params;
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "GuildWidgetSettingsResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
+ const guild = await Guild.findOneOrFail({ where: { id: guild_id } });
- return res.json({
- enabled: guild.widget_enabled || false,
- channel_id: guild.widget_channel_id || null,
- });
- },
+ return res.json({
+ enabled: guild.widget_enabled || false,
+ channel_id: guild.widget_channel_id || null,
+ });
+ },
);
// https://discord.com/developers/docs/resources/guild#modify-guild-widget
router.patch(
- "/",
- route({
- requestBody: "WidgetModifySchema",
- permission: "MANAGE_GUILD",
- responses: {
- 200: {
- body: "WidgetModifySchema",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as WidgetModifySchema;
- const { guild_id } = req.params;
+ "/",
+ route({
+ requestBody: "WidgetModifySchema",
+ permission: "MANAGE_GUILD",
+ responses: {
+ 200: {
+ body: "WidgetModifySchema",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as WidgetModifySchema;
+ const { guild_id } = req.params;
- await Guild.update(
- { id: guild_id },
- {
- widget_enabled: body.enabled,
- widget_channel_id: body.channel_id,
- },
- );
- // Widget invite for the widget_channel_id gets created as part of the /guilds/{guild.id}/widget.json request
+ await Guild.update(
+ { id: guild_id },
+ {
+ widget_enabled: body.enabled,
+ widget_channel_id: body.channel_id,
+ },
+ );
+ // Widget invite for the widget_channel_id gets created as part of the /guilds/{guild.id}/widget.json request
- return res.json(body);
- },
+ return res.json(body);
+ },
);
export default router;
diff --git a/src/api/routes/guilds/automations/email-domain-lookup.ts b/src/api/routes/guilds/automations/email-domain-lookup.ts
index 93ae231..605026b 100644
--- a/src/api/routes/guilds/automations/email-domain-lookup.ts
+++ b/src/api/routes/guilds/automations/email-domain-lookup.ts
@@ -26,74 +26,74 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "EmailDomainLookupSchema",
- responses: {
- 200: {
- body: "EmailDomainLookupResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { email } = req.body as EmailDomainLookupSchema;
+ "/",
+ route({
+ requestBody: "EmailDomainLookupSchema",
+ responses: {
+ 200: {
+ body: "EmailDomainLookupResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { email } = req.body as EmailDomainLookupSchema;
- const [_, tld] = email.split("@");
+ const [_, tld] = email.split("@");
- if (emailProviders.includes(tld.toLowerCase())) {
- throw FieldErrors({
- name: {
- message: "That looks like a personal email address. Please use your official student email.",
- code: "EMAIL_IS_UNOFFICIAL",
- },
- });
- }
+ if (emailProviders.includes(tld.toLowerCase())) {
+ throw FieldErrors({
+ name: {
+ message: "That looks like a personal email address. Please use your official student email.",
+ code: "EMAIL_IS_UNOFFICIAL",
+ },
+ });
+ }
- return res.json({
- guilds_info: [],
- has_matching_guild: false,
- } as EmailDomainLookupResponse);
- },
+ return res.json({
+ guilds_info: [],
+ has_matching_guild: false,
+ } as EmailDomainLookupResponse);
+ },
);
router.post(
- "/verify-code",
- route({
- requestBody: "EmailDomainLookupVerifyCodeSchema",
- responses: {
- // 200: {
- // body: "EmailDomainLookupVerifyCodeResponse",
- // },
- 400: {
- body: "APIErrorResponse",
- },
- 501: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { email } = req.body as EmailDomainLookupVerifyCodeSchema;
+ "/verify-code",
+ route({
+ requestBody: "EmailDomainLookupVerifyCodeSchema",
+ responses: {
+ // 200: {
+ // body: "EmailDomainLookupVerifyCodeResponse",
+ // },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 501: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { email } = req.body as EmailDomainLookupVerifyCodeSchema;
- const [_, tld] = email.split("@");
+ const [_, tld] = email.split("@");
- if (emailProviders.includes(tld.toLowerCase())) {
- throw FieldErrors({
- name: {
- message: "That looks like a personal email address. Please use your official student email.",
- code: "EMAIL_IS_UNOFFICIAL",
- },
- });
- }
+ if (emailProviders.includes(tld.toLowerCase())) {
+ throw FieldErrors({
+ name: {
+ message: "That looks like a personal email address. Please use your official student email.",
+ code: "EMAIL_IS_UNOFFICIAL",
+ },
+ });
+ }
- throw new HTTPError("Not implemented", 501);
+ throw new HTTPError("Not implemented", 501);
- // return res.json({
- // guild: null,
- // joined: false,
- // } as EmailDomainLookupVerifyCodeResponse);
- },
+ // return res.json({
+ // guild: null,
+ // joined: false,
+ // } as EmailDomainLookupVerifyCodeResponse);
+ },
);
export default router;
diff --git a/src/api/routes/guilds/index.ts b/src/api/routes/guilds/index.ts
index 6f60fa6..78ba93a 100644
--- a/src/api/routes/guilds/index.ts
+++ b/src/api/routes/guilds/index.ts
@@ -26,49 +26,49 @@
//TODO: create default channel
router.post(
- "/",
- route({
- requestBody: "GuildCreateSchema",
- right: "CREATE_GUILDS",
- responses: {
- 201: {
- body: "GuildCreateResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as GuildCreateSchema;
+ "/",
+ route({
+ requestBody: "GuildCreateSchema",
+ right: "CREATE_GUILDS",
+ responses: {
+ 201: {
+ body: "GuildCreateResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as GuildCreateSchema;
- const { maxGuilds } = Config.get().limits.user;
- const guild_count = await Member.count({ where: { id: req.user_id } });
- const rights = await getRights(req.user_id);
- if (guild_count >= maxGuilds && !rights.has("MANAGE_GUILDS")) {
- throw DiscordApiErrors.MAXIMUM_GUILDS.withParams(maxGuilds);
- }
+ const { maxGuilds } = Config.get().limits.user;
+ const guild_count = await Member.count({ where: { id: req.user_id } });
+ const rights = await getRights(req.user_id);
+ if (guild_count >= maxGuilds && !rights.has("MANAGE_GUILDS")) {
+ throw DiscordApiErrors.MAXIMUM_GUILDS.withParams(maxGuilds);
+ }
- const guild = await Guild.createGuild({
- ...body,
- owner_id: req.user_id,
- template_guild_id: null,
- });
+ const guild = await Guild.createGuild({
+ ...body,
+ owner_id: req.user_id,
+ template_guild_id: null,
+ });
- const { autoJoin } = Config.get().guild;
- if (autoJoin.enabled && !autoJoin.guilds?.length) {
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- await Config.set({ guild: { autoJoin: { guilds: [guild.id] } } });
- }
+ const { autoJoin } = Config.get().guild;
+ if (autoJoin.enabled && !autoJoin.guilds?.length) {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ await Config.set({ guild: { autoJoin: { guilds: [guild.id] } } });
+ }
- await Member.addToGuild(req.user_id, guild.id);
+ await Member.addToGuild(req.user_id, guild.id);
- res.status(201).json(guild);
- },
+ res.status(201).json(guild);
+ },
);
export default router;
diff --git a/src/api/routes/guilds/templates/index.ts b/src/api/routes/guilds/templates/index.ts
index 50ba017..e5dfd68 100644
--- a/src/api/routes/guilds/templates/index.ts
+++ b/src/api/routes/guilds/templates/index.ts
@@ -25,80 +25,80 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/:template_code",
- route({
- responses: {
- 200: {
- body: "Template",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { template_code } = req.params;
+ "/:template_code",
+ route({
+ responses: {
+ 200: {
+ body: "Template",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { template_code } = req.params;
- const template = await getTemplate(template_code);
+ const template = await getTemplate(template_code);
- res.json(template);
- },
+ res.json(template);
+ },
);
router.post("/:template_code", route({ requestBody: "GuildTemplateCreateSchema" }), async (req: Request, res: Response) => {
- const { template_code } = req.params;
- const body = req.body as GuildTemplateCreateSchema;
+ const { template_code } = req.params;
+ const body = req.body as GuildTemplateCreateSchema;
- const { maxGuilds } = Config.get().limits.user;
+ const { maxGuilds } = Config.get().limits.user;
- const guild_count = await Member.count({ where: { id: req.user_id } });
- if (guild_count >= maxGuilds) throw DiscordApiErrors.MAXIMUM_GUILDS.withParams(maxGuilds);
+ const guild_count = await Member.count({ where: { id: req.user_id } });
+ if (guild_count >= maxGuilds) throw DiscordApiErrors.MAXIMUM_GUILDS.withParams(maxGuilds);
- const template = (await getTemplate(template_code)) as Template;
+ const template = (await getTemplate(template_code)) as Template;
- const guild = await Guild.createGuild({
- ...template.serialized_source_guild,
- // body comes after the template
- ...body,
- owner_id: req.user_id,
- template_guild_id: template.source_guild_id,
- });
+ const guild = await Guild.createGuild({
+ ...template.serialized_source_guild,
+ // body comes after the template
+ ...body,
+ owner_id: req.user_id,
+ template_guild_id: template.source_guild_id,
+ });
- await Member.addToGuild(req.user_id, guild.id);
+ await Member.addToGuild(req.user_id, guild.id);
- res.status(201).json({ id: guild.id });
+ res.status(201).json({ id: guild.id });
});
async function getTemplate(code: string) {
- const { allowDiscordTemplates, allowRaws, enabled } = Config.get().templates;
+ const { allowDiscordTemplates, allowRaws, enabled } = Config.get().templates;
- if (!enabled) throw new HTTPError("Template creation & usage is disabled on this instance.", 403);
+ if (!enabled) throw new HTTPError("Template creation & usage is disabled on this instance.", 403);
- if (code.startsWith("discord:")) {
- if (!allowDiscordTemplates) throw new HTTPError("Discord templates cannot be used on this instance.", 403);
+ if (code.startsWith("discord:")) {
+ if (!allowDiscordTemplates) throw new HTTPError("Discord templates cannot be used on this instance.", 403);
- const discordTemplateID = code.split("discord:", 2)[1];
+ const discordTemplateID = code.split("discord:", 2)[1];
- const discordTemplateData = await fetch(`https://discord.com/api/v9/guilds/templates/${discordTemplateID}`, {
- method: "get",
- headers: { "Content-Type": "application/json" },
- });
+ const discordTemplateData = await fetch(`https://discord.com/api/v9/guilds/templates/${discordTemplateID}`, {
+ method: "get",
+ headers: { "Content-Type": "application/json" },
+ });
- return await discordTemplateData.json();
- }
+ return await discordTemplateData.json();
+ }
- if (code.startsWith("external:")) {
- if (!allowRaws) throw new HTTPError("Importing raws is disabled on this instance.", 403);
+ if (code.startsWith("external:")) {
+ if (!allowRaws) throw new HTTPError("Importing raws is disabled on this instance.", 403);
- return code.split("external:", 2)[1];
- }
+ return code.split("external:", 2)[1];
+ }
- return await Template.findOneOrFail({
- where: { code: code },
- });
+ return await Template.findOneOrFail({
+ where: { code: code },
+ });
}
export default router;
diff --git a/src/api/routes/hub-waitlist.ts b/src/api/routes/hub-waitlist.ts
index bdf0931..43c2662 100644
--- a/src/api/routes/hub-waitlist.ts
+++ b/src/api/routes/hub-waitlist.ts
@@ -22,28 +22,28 @@
const router = Router({ mergeParams: true });
router.post(
- "/signup",
- route({
- requestBody: "HubWaitlistSignupSchema",
- responses: {
- 200: {
- body: "HubWaitlistSignupResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { email, school } = req.body as HubWaitlistSignupSchema;
+ "/signup",
+ route({
+ requestBody: "HubWaitlistSignupSchema",
+ responses: {
+ 200: {
+ body: "HubWaitlistSignupResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { email, school } = req.body as HubWaitlistSignupSchema;
- res.json({
- email,
- email_domain: email.split("@")[1],
- school,
- user_id: req.user_id,
- } as HubWaitlistSignupResponse);
- },
+ res.json({
+ email,
+ email_domain: email.split("@")[1],
+ school,
+ user_id: req.user_id,
+ } as HubWaitlistSignupResponse);
+ },
);
export default router;
diff --git "a/src/api/routes/interactions/\043interaction_id/\043interaction_token/callback.ts" "b/src/api/routes/interactions/\043interaction_id/\043interaction_token/callback.ts"
index 442ce0e..e94d455 100644
--- "a/src/api/routes/interactions/\043interaction_id/\043interaction_token/callback.ts"
+++ "b/src/api/routes/interactions/\043interaction_id/\043interaction_token/callback.ts"
@@ -26,79 +26,79 @@
const router = Router({ mergeParams: true });
router.post("/", route({}), async (req: Request, res: Response) => {
- const body = req.body as InteractionCallbackSchema;
+ const body = req.body as InteractionCallbackSchema;
- const errors: Record = {};
- const knownComponentIds: string[] = [];
+ const errors: Record = {};
+ const knownComponentIds: string[] = [];
- for (const row of body.data.components || []) {
- if (!row.components) {
- continue;
- }
+ for (const row of body.data.components || []) {
+ if (!row.components) {
+ continue;
+ }
- if (row.components.length < 1 || row.components.length > 5) {
- errors[`data.components[${body.data.components!.indexOf(row)}].components`] = {
- code: "BASE_TYPE_BAD_LENGTH",
- message: `Must be between 1 and 5 in length.`,
- };
- }
+ if (row.components.length < 1 || row.components.length > 5) {
+ errors[`data.components[${body.data.components!.indexOf(row)}].components`] = {
+ code: "BASE_TYPE_BAD_LENGTH",
+ message: `Must be between 1 and 5 in length.`,
+ };
+ }
- for (const component of row.components) {
- if (component.type == MessageComponentType.Button && component.style != ButtonStyle.Link) {
- if (component.custom_id?.trim() === "") {
- errors[`data.components[${body.data.components!.indexOf(row)}].components[${row.components.indexOf(component)}].custom_id`] = {
- code: "BUTTON_COMPONENT_CUSTOM_ID_REQUIRED",
- message: "A custom id required",
- };
- }
+ for (const component of row.components) {
+ if (component.type == MessageComponentType.Button && component.style != ButtonStyle.Link) {
+ if (component.custom_id?.trim() === "") {
+ errors[`data.components[${body.data.components!.indexOf(row)}].components[${row.components.indexOf(component)}].custom_id`] = {
+ code: "BUTTON_COMPONENT_CUSTOM_ID_REQUIRED",
+ message: "A custom id required",
+ };
+ }
- if (knownComponentIds.includes(component.custom_id!)) {
- errors[`data.components[${body.data.components!.indexOf(row)}].components[${row.components.indexOf(component)}].custom_id`] = {
- code: "COMPONENT_CUSTOM_ID_DUPLICATED",
- message: "Component custom id cannot be duplicated",
- };
- } else {
- knownComponentIds.push(component.custom_id!);
- }
- }
- }
- }
+ if (knownComponentIds.includes(component.custom_id!)) {
+ errors[`data.components[${body.data.components!.indexOf(row)}].components[${row.components.indexOf(component)}].custom_id`] = {
+ code: "COMPONENT_CUSTOM_ID_DUPLICATED",
+ message: "Component custom id cannot be duplicated",
+ };
+ } else {
+ knownComponentIds.push(component.custom_id!);
+ }
+ }
+ }
+ }
- if (Object.keys(errors).length > 0) {
- throw FieldErrors(errors);
- }
+ if (Object.keys(errors).length > 0) {
+ throw FieldErrors(errors);
+ }
- const interactionId = req.params.interaction_id;
- const interaction = pendingInteractions.get(req.params.interaction_id);
+ const interactionId = req.params.interaction_id;
+ const interaction = pendingInteractions.get(req.params.interaction_id);
- if (!interaction) {
- return;
- }
+ if (!interaction) {
+ return;
+ }
- clearTimeout(interaction.timeout);
+ clearTimeout(interaction.timeout);
- emitEvent({
- event: "INTERACTION_SUCCESS",
- user_id: interaction?.userId,
- data: {
- id: interactionId,
- nonce: interaction?.nonce,
- },
- } as InteractionSuccessEvent);
+ emitEvent({
+ event: "INTERACTION_SUCCESS",
+ user_id: interaction?.userId,
+ data: {
+ id: interactionId,
+ nonce: interaction?.nonce,
+ },
+ } as InteractionSuccessEvent);
- switch (body.type) {
- case InteractionCallbackType.PONG:
- // TODO
- break;
- case InteractionCallbackType.ACKNOWLEDGE:
- // Deprected
- break;
- case InteractionCallbackType.CHANNEL_MESSAGE:
- // TODO
- break;
- case InteractionCallbackType.CHANNEL_MESSAGE_WITH_SOURCE: {
- const user = await User.findOneOrFail({ where: { id: interaction.userId } });
- /*
+ switch (body.type) {
+ case InteractionCallbackType.PONG:
+ // TODO
+ break;
+ case InteractionCallbackType.ACKNOWLEDGE:
+ // Deprected
+ break;
+ case InteractionCallbackType.CHANNEL_MESSAGE:
+ // TODO
+ break;
+ case InteractionCallbackType.CHANNEL_MESSAGE_WITH_SOURCE: {
+ const user = await User.findOneOrFail({ where: { id: interaction.userId } });
+ /*
const files = (req.files as Express.Multer.File[]) ?? [];
//I don't think traditional attachments are allowed anyways
const attachments: (Attachment | MessageCreateAttachment | MessageCreateCloudAttachment)[] = [];
@@ -111,71 +111,71 @@
}
}
*/
- await sendMessage({
- type: MessageType.APPLICATION_COMMAND,
- timestamp: new Date(),
- application_id: interaction.applicationId,
- channel_id: interaction.channelId,
- author_id: interaction.applicationId,
- nonce: interaction.nonce,
- content: body.data.content,
- components: body.data.components || [],
- tts: body.data.tts,
- embeds: body.data.embeds || [],
- attachments: body.data.attachments,
- poll: body.data.poll,
- flags: body.data.flags,
- reactions: [],
- // webhook_id: interaction.applicationId, // This one requires a webhook to be created first
- interaction: {
- id: interactionId,
- name: interaction.commandName,
- type: 2,
- user,
- },
- interaction_metadata: {
- id: interactionId,
- type: 2,
- user_id: interaction.userId,
- user,
- authorizing_integration_owners: {
- "1": interaction.userId,
- },
- name: interaction.commandName,
- command_type: interaction.commandType,
- },
- });
+ await sendMessage({
+ type: MessageType.APPLICATION_COMMAND,
+ timestamp: new Date(),
+ application_id: interaction.applicationId,
+ channel_id: interaction.channelId,
+ author_id: interaction.applicationId,
+ nonce: interaction.nonce,
+ content: body.data.content,
+ components: body.data.components || [],
+ tts: body.data.tts,
+ embeds: body.data.embeds || [],
+ attachments: body.data.attachments,
+ poll: body.data.poll,
+ flags: body.data.flags,
+ reactions: [],
+ // webhook_id: interaction.applicationId, // This one requires a webhook to be created first
+ interaction: {
+ id: interactionId,
+ name: interaction.commandName,
+ type: 2,
+ user,
+ },
+ interaction_metadata: {
+ id: interactionId,
+ type: 2,
+ user_id: interaction.userId,
+ user,
+ authorizing_integration_owners: {
+ "1": interaction.userId,
+ },
+ name: interaction.commandName,
+ command_type: interaction.commandType,
+ },
+ });
- break;
- }
- case InteractionCallbackType.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE:
- // TODO
- break;
- case InteractionCallbackType.DEFERRED_UPDATE_MESSAGE:
- // TODO
- break;
- case InteractionCallbackType.UPDATE_MESSAGE:
- // TODO
- break;
- case InteractionCallbackType.APPLICATION_COMMAND_AUTOCOMPLETE_RESULT:
- // TODO
- break;
- case InteractionCallbackType.MODAL:
- // TODO
- break;
- case InteractionCallbackType.PREMIUM_REQUIRED:
- // Deprecated
- break;
- case InteractionCallbackType.IFRAME_MODAL:
- // TODO
- break;
- case InteractionCallbackType.LAUNCH_ACTIVITY:
- // TODO
- break;
- }
+ break;
+ }
+ case InteractionCallbackType.DEFERRED_CHANNEL_MESSAGE_WITH_SOURCE:
+ // TODO
+ break;
+ case InteractionCallbackType.DEFERRED_UPDATE_MESSAGE:
+ // TODO
+ break;
+ case InteractionCallbackType.UPDATE_MESSAGE:
+ // TODO
+ break;
+ case InteractionCallbackType.APPLICATION_COMMAND_AUTOCOMPLETE_RESULT:
+ // TODO
+ break;
+ case InteractionCallbackType.MODAL:
+ // TODO
+ break;
+ case InteractionCallbackType.PREMIUM_REQUIRED:
+ // Deprecated
+ break;
+ case InteractionCallbackType.IFRAME_MODAL:
+ // TODO
+ break;
+ case InteractionCallbackType.LAUNCH_ACTIVITY:
+ // TODO
+ break;
+ }
- pendingInteractions.delete(interactionId);
- res.sendStatus(204);
+ pendingInteractions.delete(interactionId);
+ res.sendStatus(204);
});
export default router;
diff --git a/src/api/routes/interactions/index.ts b/src/api/routes/interactions/index.ts
index 9f15439..eb516ce 100644
--- a/src/api/routes/interactions/index.ts
+++ b/src/api/routes/interactions/index.ts
@@ -27,104 +27,104 @@
const router = Router({ mergeParams: true });
router.post("/", route({}), async (req: Request, res: Response) => {
- const body = req.body as InteractionSchema;
+ const body = req.body as InteractionSchema;
- const interactionId = Snowflake.generate();
- const interactionToken = randomBytes(24).toString("base64url");
+ const interactionId = Snowflake.generate();
+ const interactionToken = randomBytes(24).toString("base64url");
- emitEvent({
- event: "INTERACTION_CREATE",
- user_id: req.user_id,
- data: {
- id: interactionId,
- nonce: body.nonce,
- },
- } as InteractionCreateEvent);
+ emitEvent({
+ event: "INTERACTION_CREATE",
+ user_id: req.user_id,
+ data: {
+ id: interactionId,
+ nonce: body.nonce,
+ },
+ } as InteractionCreateEvent);
- const user = await User.findOneOrFail({ where: { id: req.user_id } });
+ const user = await User.findOneOrFail({ where: { id: req.user_id } });
- const interactionData: Partial = {
- id: interactionId,
- application_id: body.application_id,
- channel_id: body.channel_id,
- type: body.type,
- token: interactionToken,
- version: 1,
- entitlements: [],
- authorizing_integration_owners: { "0": req.user_id },
- attachment_size_limit: Config.get().cdn.maxAttachmentSize,
- };
+ const interactionData: Partial = {
+ id: interactionId,
+ application_id: body.application_id,
+ channel_id: body.channel_id,
+ type: body.type,
+ token: interactionToken,
+ version: 1,
+ entitlements: [],
+ authorizing_integration_owners: { "0": req.user_id },
+ attachment_size_limit: Config.get().cdn.maxAttachmentSize,
+ };
- if (body.type === InteractionType.ApplicationCommand || body.type === InteractionType.MessageComponent || body.type === InteractionType.ModalSubmit) {
- interactionData.data = body.data;
- }
+ if (body.type === InteractionType.ApplicationCommand || body.type === InteractionType.MessageComponent || body.type === InteractionType.ModalSubmit) {
+ interactionData.data = body.data;
+ }
- if (body.type != InteractionType.Ping) {
- interactionData.locale = user?.settings?.locale;
- }
+ if (body.type != InteractionType.Ping) {
+ interactionData.locale = user?.settings?.locale;
+ }
- if (body.guild_id) {
- interactionData.context = 0;
- interactionData.guild_id = body.guild_id;
- interactionData.app_permissions = (await getPermission(body.application_id, body.guild_id, body.channel_id)).bitfield.toString();
+ if (body.guild_id) {
+ interactionData.context = 0;
+ interactionData.guild_id = body.guild_id;
+ interactionData.app_permissions = (await getPermission(body.application_id, body.guild_id, body.channel_id)).bitfield.toString();
- const guild = await Guild.findOneOrFail({ where: { id: body.guild_id } });
- const member = await Member.findOneOrFail({ where: { guild_id: body.guild_id, id: req.user_id }, relations: ["user"] });
+ const guild = await Guild.findOneOrFail({ where: { id: body.guild_id } });
+ const member = await Member.findOneOrFail({ where: { guild_id: body.guild_id, id: req.user_id }, relations: ["user"] });
- interactionData.guild = {
- id: guild.id,
- features: guild.features,
- locale: guild.preferred_locale!,
- };
+ interactionData.guild = {
+ id: guild.id,
+ features: guild.features,
+ locale: guild.preferred_locale!,
+ };
- interactionData.guild_locale = guild.preferred_locale;
- interactionData.member = member.toPublicMember();
- } else {
- interactionData.user = user.toPublicUser();
- interactionData.app_permissions = (await getPermission(body.application_id, "", body.channel_id)).bitfield.toString();
+ interactionData.guild_locale = guild.preferred_locale;
+ interactionData.member = member.toPublicMember();
+ } else {
+ interactionData.user = user.toPublicUser();
+ interactionData.app_permissions = (await getPermission(body.application_id, "", body.channel_id)).bitfield.toString();
- if (body.channel_id === body.application_id) {
- interactionData.context = 1;
- } else {
- interactionData.context = 2;
- }
- }
+ if (body.channel_id === body.application_id) {
+ interactionData.context = 1;
+ } else {
+ interactionData.context = 2;
+ }
+ }
- if (body.type === InteractionType.MessageComponent || body.data.type === InteractionType.ModalSubmit) {
- interactionData.message = await Message.findOneOrFail({ where: { id: body.message_id, flags: undefined }, relations: ["author"] });
- }
+ if (body.type === InteractionType.MessageComponent || body.data.type === InteractionType.ModalSubmit) {
+ interactionData.message = await Message.findOneOrFail({ where: { id: body.message_id, flags: undefined }, relations: ["author"] });
+ }
- emitEvent({
- event: "INTERACTION_CREATE",
- user_id: body.application_id,
- data: interactionData,
- } as InteractionCreateEvent);
+ emitEvent({
+ event: "INTERACTION_CREATE",
+ user_id: body.application_id,
+ data: interactionData,
+ } as InteractionCreateEvent);
- const interactionTimeout = setTimeout(() => {
- emitEvent({
- event: "INTERACTION_FAILURE",
- user_id: req.user_id,
- data: {
- id: interactionId,
- nonce: body.nonce,
- reason_code: 2, // when types are done: InteractionFailureReason.TIMEOUT,
- },
- } as InteractionFailureEvent);
- }, 3000);
+ const interactionTimeout = setTimeout(() => {
+ emitEvent({
+ event: "INTERACTION_FAILURE",
+ user_id: req.user_id,
+ data: {
+ id: interactionId,
+ nonce: body.nonce,
+ reason_code: 2, // when types are done: InteractionFailureReason.TIMEOUT,
+ },
+ } as InteractionFailureEvent);
+ }, 3000);
- pendingInteractions.set(interactionId, {
- timeout: interactionTimeout,
- nonce: body.nonce,
- applicationId: body.application_id,
- userId: req.user_id,
- guildId: body.guild_id,
- channelId: body.channel_id,
- type: body.type,
- commandType: body.data.type,
- commandName: body.data.name,
- });
+ pendingInteractions.set(interactionId, {
+ timeout: interactionTimeout,
+ nonce: body.nonce,
+ applicationId: body.application_id,
+ userId: req.user_id,
+ guildId: body.guild_id,
+ channelId: body.channel_id,
+ type: body.type,
+ commandType: body.data.type,
+ commandName: body.data.name,
+ });
- res.sendStatus(204);
+ res.sendStatus(204);
});
export default router;
diff --git a/src/api/routes/invites/index.ts b/src/api/routes/invites/index.ts
index 87715f3..26b0ad9 100644
--- a/src/api/routes/invites/index.ts
+++ b/src/api/routes/invites/index.ts
@@ -25,134 +25,134 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/:invite_code",
- route({
- responses: {
- "200": {
- body: "Invite",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { invite_code } = req.params;
+ "/:invite_code",
+ route({
+ responses: {
+ "200": {
+ body: "Invite",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { invite_code } = req.params;
- const invite = await Invite.findOneOrFail({
- where: { code: invite_code },
- relations: PublicInviteRelation,
- });
+ const invite = await Invite.findOneOrFail({
+ where: { code: invite_code },
+ relations: PublicInviteRelation,
+ });
- res.status(200).send(invite);
- },
+ res.status(200).send(invite);
+ },
);
router.post(
- "/:invite_code",
- route({
- right: "USE_MASS_INVITES",
- responses: {
- "200": {
- body: "Invite",
- },
- 401: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- if (req.user_bot) throw DiscordApiErrors.BOT_PROHIBITED_ENDPOINT;
+ "/:invite_code",
+ route({
+ right: "USE_MASS_INVITES",
+ responses: {
+ "200": {
+ body: "Invite",
+ },
+ 401: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ if (req.user_bot) throw DiscordApiErrors.BOT_PROHIBITED_ENDPOINT;
- const { invite_code } = req.params;
- const { guild_id } = await Invite.findOneOrFail({
- where: { code: invite_code },
- });
- const { features } = await Guild.findOneOrFail({
- where: { id: guild_id },
- });
- const { public_flags } = await User.findOneOrFail({
- where: { id: req.user_id },
- });
- const ban = await Ban.findOne({
- where: [
- { guild_id: guild_id, user_id: req.user_id },
- { guild_id: guild_id, ip: req.ip },
- ],
- });
+ const { invite_code } = req.params;
+ const { guild_id } = await Invite.findOneOrFail({
+ where: { code: invite_code },
+ });
+ const { features } = await Guild.findOneOrFail({
+ where: { id: guild_id },
+ });
+ const { public_flags } = await User.findOneOrFail({
+ where: { id: req.user_id },
+ });
+ const ban = await Ban.findOne({
+ where: [
+ { guild_id: guild_id, user_id: req.user_id },
+ { guild_id: guild_id, ip: req.ip },
+ ],
+ });
- if (ban) {
- console.log(`[Invite] User ${req.user_id} tried to join guild ${guild_id} but is banned by ${ban.user_id === req.user_id ? "User ID" : "IP address"}.`);
- throw DiscordApiErrors.USER_BANNED;
- }
+ if (ban) {
+ console.log(`[Invite] User ${req.user_id} tried to join guild ${guild_id} but is banned by ${ban.user_id === req.user_id ? "User ID" : "IP address"}.`);
+ throw DiscordApiErrors.USER_BANNED;
+ }
- if ((BigInt(public_flags) & UserFlags.FLAGS.QUARANTINED) === UserFlags.FLAGS.QUARANTINED) {
- console.log(`[Invite] User ${req.user_id} tried to join guild ${guild_id} but is quarantined.`);
- throw DiscordApiErrors.UNKNOWN_INVITE;
- }
+ if ((BigInt(public_flags) & UserFlags.FLAGS.QUARANTINED) === UserFlags.FLAGS.QUARANTINED) {
+ console.log(`[Invite] User ${req.user_id} tried to join guild ${guild_id} but is quarantined.`);
+ throw DiscordApiErrors.UNKNOWN_INVITE;
+ }
- if (features.includes("INTERNAL_EMPLOYEE_ONLY") && (public_flags & 1) !== 1) {
- console.log(`[Invite] User ${req.user_id} tried to join guild ${guild_id} but is not staff.`);
- throw new HTTPError("Only intended for the staff of this instance.", 401);
- }
+ if (features.includes("INTERNAL_EMPLOYEE_ONLY") && (public_flags & 1) !== 1) {
+ console.log(`[Invite] User ${req.user_id} tried to join guild ${guild_id} but is not staff.`);
+ throw new HTTPError("Only intended for the staff of this instance.", 401);
+ }
- if (features.includes("INVITES_DISABLED")) {
- console.log(`[Invite] User ${req.user_id} tried to join guild ${guild_id} but joins are closed.`);
- throw new HTTPError("Sorry, this guild has joins closed.", 403);
- }
+ if (features.includes("INVITES_DISABLED")) {
+ console.log(`[Invite] User ${req.user_id} tried to join guild ${guild_id} but joins are closed.`);
+ throw new HTTPError("Sorry, this guild has joins closed.", 403);
+ }
- const invite = await Invite.joinGuild(req.user_id, invite_code);
+ const invite = await Invite.joinGuild(req.user_id, invite_code);
- res.json(invite);
- },
+ res.json(invite);
+ },
);
// * cant use permission of route() function because path doesn't have guild_id/channel_id
router.delete(
- "/:invite_code",
- route({
- responses: {
- "200": {
- body: "Invite",
- },
- 401: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { invite_code } = req.params;
- const invite = await Invite.findOneOrFail({ where: { code: invite_code } });
- const { guild_id, channel_id } = invite;
+ "/:invite_code",
+ route({
+ responses: {
+ "200": {
+ body: "Invite",
+ },
+ 401: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { invite_code } = req.params;
+ const invite = await Invite.findOneOrFail({ where: { code: invite_code } });
+ const { guild_id, channel_id } = invite;
- const permission = await getPermission(req.user_id, guild_id, channel_id);
+ const permission = await getPermission(req.user_id, guild_id, channel_id);
- if (!permission.has("MANAGE_GUILD") && !permission.has("MANAGE_CHANNELS")) throw new HTTPError("You missing the MANAGE_GUILD or MANAGE_CHANNELS permission", 401);
+ if (!permission.has("MANAGE_GUILD") && !permission.has("MANAGE_CHANNELS")) throw new HTTPError("You missing the MANAGE_GUILD or MANAGE_CHANNELS permission", 401);
- await Promise.all([
- Invite.delete({ code: invite_code }),
- emitEvent({
- event: "INVITE_DELETE",
- guild_id: guild_id,
- data: {
- channel_id: channel_id,
- guild_id: guild_id,
- code: invite_code,
- },
- } as InviteDeleteEvent),
- ]);
+ await Promise.all([
+ Invite.delete({ code: invite_code }),
+ emitEvent({
+ event: "INVITE_DELETE",
+ guild_id: guild_id,
+ data: {
+ channel_id: channel_id,
+ guild_id: guild_id,
+ code: invite_code,
+ },
+ } as InviteDeleteEvent),
+ ]);
- res.json({ invite: invite });
- },
+ res.json({ invite: invite });
+ },
);
export default router;
diff --git a/src/api/routes/oauth2/applications/@me.ts b/src/api/routes/oauth2/applications/@me.ts
index 6daad79..9cdd47c 100644
--- a/src/api/routes/oauth2/applications/@me.ts
+++ b/src/api/routes/oauth2/applications/@me.ts
@@ -24,30 +24,30 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "Application",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const app = await Application.findOneOrFail({
- where: { id: req.params.id }, // ...huh? there's no ID in the path...
- relations: ["bot", "owner"],
- select: {
- owner: Object.fromEntries(PublicUserProjection.map((x) => [x, true])),
- },
- });
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "Application",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const app = await Application.findOneOrFail({
+ where: { id: req.params.id }, // ...huh? there's no ID in the path...
+ relations: ["bot", "owner"],
+ select: {
+ owner: Object.fromEntries(PublicUserProjection.map((x) => [x, true])),
+ },
+ });
- if (!app.bot) throw DiscordApiErrors.BOT_ONLY_ENDPOINT;
+ if (!app.bot) throw DiscordApiErrors.BOT_ONLY_ENDPOINT;
- res.json({
- ...app,
- owner: app.owner.toPublicUser(),
- install_params: app.install_params !== null ? app.install_params : undefined,
- });
- },
+ res.json({
+ ...app,
+ owner: app.owner.toPublicUser(),
+ install_params: app.install_params !== null ? app.install_params : undefined,
+ });
+ },
);
export default router;
diff --git a/src/api/routes/oauth2/authorize.ts b/src/api/routes/oauth2/authorize.ts
index 4084a05..4dea75c 100644
--- a/src/api/routes/oauth2/authorize.ts
+++ b/src/api/routes/oauth2/authorize.ts
@@ -25,198 +25,198 @@
// TODO: scopes, other oauth types
router.get(
- "/",
- route({
- query: {
- client_id: {
- type: "string",
- },
- },
- responses: {
- // TODO: I really didn't feel like typing all of it out
- 200: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- // const { client_id, scope, response_type, redirect_url } = req.query;
- const { client_id } = req.query;
- if (!client_id) {
- throw FieldErrors({
- client_id: {
- code: "BASE_TYPE_REQUIRED",
- message: req.t("common:field.BASE_TYPE_REQUIRED"),
- },
- });
- }
+ "/",
+ route({
+ query: {
+ client_id: {
+ type: "string",
+ },
+ },
+ responses: {
+ // TODO: I really didn't feel like typing all of it out
+ 200: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ // const { client_id, scope, response_type, redirect_url } = req.query;
+ const { client_id } = req.query;
+ if (!client_id) {
+ throw FieldErrors({
+ client_id: {
+ code: "BASE_TYPE_REQUIRED",
+ message: req.t("common:field.BASE_TYPE_REQUIRED"),
+ },
+ });
+ }
- const app = await Application.findOne({
- where: {
- id: client_id as string,
- },
- relations: ["bot"],
- });
+ const app = await Application.findOne({
+ where: {
+ id: client_id as string,
+ },
+ relations: ["bot"],
+ });
- // TODO: use DiscordApiErrors
- // findOneOrFail throws code 404
- if (!app) throw DiscordApiErrors.UNKNOWN_APPLICATION;
- if (!app.bot) throw DiscordApiErrors.OAUTH2_APPLICATION_BOT_ABSENT;
+ // TODO: use DiscordApiErrors
+ // findOneOrFail throws code 404
+ if (!app) throw DiscordApiErrors.UNKNOWN_APPLICATION;
+ if (!app.bot) throw DiscordApiErrors.OAUTH2_APPLICATION_BOT_ABSENT;
- const bot = app.bot;
- delete app.bot;
+ const bot = app.bot;
+ delete app.bot;
- const user = await User.findOneOrFail({
- where: {
- id: req.user_id,
- bot: false,
- },
- select: ["id", "username", "avatar", "discriminator", "public_flags"],
- });
+ const user = await User.findOneOrFail({
+ where: {
+ id: req.user_id,
+ bot: false,
+ },
+ select: ["id", "username", "avatar", "discriminator", "public_flags"],
+ });
- const guilds = await Member.find({
- where: {
- id: req.user_id,
- },
- relations: ["guild", "roles", "user"],
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- //@ts-ignore
- // prettier-ignore
- select: ["guild.id", "guild.name", "guild.icon", "guild.mfa_level", "guild.owner_id", "roles.id", "user.flags"],
- });
+ const guilds = await Member.find({
+ where: {
+ id: req.user_id,
+ },
+ relations: ["guild", "roles", "user"],
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ //@ts-ignore
+ // prettier-ignore
+ select: ["guild.id", "guild.name", "guild.icon", "guild.mfa_level", "guild.owner_id", "roles.id", "user.flags"],
+ });
- const guildsWithPermissions = guilds.map((x) => {
- const perms = Permissions.finalPermission({
- user: {
- id: user.id,
- roles: x.roles?.map((x) => x.id) || [],
- communication_disabled_until: x.communication_disabled_until,
- flags: x.user.flags,
- },
- guild: {
- roles: x?.roles || [],
- id: x.guild.id,
- owner_id: x.guild.owner_id!, // ownerless guilds...?
- },
- });
+ const guildsWithPermissions = guilds.map((x) => {
+ const perms = Permissions.finalPermission({
+ user: {
+ id: user.id,
+ roles: x.roles?.map((x) => x.id) || [],
+ communication_disabled_until: x.communication_disabled_until,
+ flags: x.user.flags,
+ },
+ guild: {
+ roles: x?.roles || [],
+ id: x.guild.id,
+ owner_id: x.guild.owner_id!, // ownerless guilds...?
+ },
+ });
- return {
- id: x.guild.id,
- name: x.guild.name,
- icon: x.guild.icon,
- mfa_level: x.guild.mfa_level,
- permissions: perms.bitfield.toString(),
- };
- });
+ return {
+ id: x.guild.id,
+ name: x.guild.name,
+ icon: x.guild.icon,
+ mfa_level: x.guild.mfa_level,
+ permissions: perms.bitfield.toString(),
+ };
+ });
- return res.json({
- guilds: guildsWithPermissions,
- user: {
- id: user.id,
- username: user.username,
- avatar: user.avatar,
- avatar_decoration: null, // TODO
- discriminator: user.discriminator,
- public_flags: user.public_flags,
- },
- application: {
- id: app.id,
- name: app.name,
- icon: app.icon,
- description: app.description,
- summary: app.summary,
- type: app.type,
- hook: app.hook,
- guild_id: null, // TODO support guilds
- bot_public: app.bot_public,
- bot_require_code_grant: app.bot_require_code_grant,
- verify_key: app.verify_key,
- flags: app.flags,
- },
- bot: {
- id: bot.id,
- username: bot.username,
- avatar: bot.avatar,
- avatar_decoration: null, // TODO
- discriminator: bot.discriminator,
- public_flags: bot.public_flags,
- bot: true,
- approximated_guild_count: 0, // TODO
- },
- authorized: false,
- });
- },
+ return res.json({
+ guilds: guildsWithPermissions,
+ user: {
+ id: user.id,
+ username: user.username,
+ avatar: user.avatar,
+ avatar_decoration: null, // TODO
+ discriminator: user.discriminator,
+ public_flags: user.public_flags,
+ },
+ application: {
+ id: app.id,
+ name: app.name,
+ icon: app.icon,
+ description: app.description,
+ summary: app.summary,
+ type: app.type,
+ hook: app.hook,
+ guild_id: null, // TODO support guilds
+ bot_public: app.bot_public,
+ bot_require_code_grant: app.bot_require_code_grant,
+ verify_key: app.verify_key,
+ flags: app.flags,
+ },
+ bot: {
+ id: bot.id,
+ username: bot.username,
+ avatar: bot.avatar,
+ avatar_decoration: null, // TODO
+ discriminator: bot.discriminator,
+ public_flags: bot.public_flags,
+ bot: true,
+ approximated_guild_count: 0, // TODO
+ },
+ authorized: false,
+ });
+ },
);
router.post(
- "/",
- route({
- requestBody: "ApplicationAuthorizeSchema",
- query: {
- client_id: {
- type: "string",
- },
- },
- responses: {
- 200: {
- body: "OAuthAuthorizeResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as ApplicationAuthorizeSchema;
- // const { client_id, scope, response_type, redirect_url } = req.query;
- const { client_id } = req.query;
+ "/",
+ route({
+ requestBody: "ApplicationAuthorizeSchema",
+ query: {
+ client_id: {
+ type: "string",
+ },
+ },
+ responses: {
+ 200: {
+ body: "OAuthAuthorizeResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as ApplicationAuthorizeSchema;
+ // const { client_id, scope, response_type, redirect_url } = req.query;
+ const { client_id } = req.query;
- if (!client_id) {
- throw FieldErrors({
- client_id: {
- code: "BASE_TYPE_REQUIRED",
- message: req.t("common:field.BASE_TYPE_REQUIRED"),
- },
- });
- }
+ if (!client_id) {
+ throw FieldErrors({
+ client_id: {
+ code: "BASE_TYPE_REQUIRED",
+ message: req.t("common:field.BASE_TYPE_REQUIRED"),
+ },
+ });
+ }
- // TODO: ensure guild_id is not an empty string
- // TODO: captcha verification
- // TODO: MFA verification
+ // TODO: ensure guild_id is not an empty string
+ // TODO: captcha verification
+ // TODO: MFA verification
- const perms = await getPermission(req.user_id, body.guild_id, undefined, { member_relations: ["user"] });
- // getPermission cache won't exist if we're owner
- if (Object.keys(perms.cache || {}).length > 0 && perms.cache.member?.user.bot) throw DiscordApiErrors.UNAUTHORIZED;
- perms.hasThrow("MANAGE_GUILD");
+ const perms = await getPermission(req.user_id, body.guild_id, undefined, { member_relations: ["user"] });
+ // getPermission cache won't exist if we're owner
+ if (Object.keys(perms.cache || {}).length > 0 && perms.cache.member?.user.bot) throw DiscordApiErrors.UNAUTHORIZED;
+ perms.hasThrow("MANAGE_GUILD");
- const app = await Application.findOne({
- where: {
- id: client_id as string,
- },
- relations: ["bot"],
- });
+ const app = await Application.findOne({
+ where: {
+ id: client_id as string,
+ },
+ relations: ["bot"],
+ });
- // TODO: use DiscordApiErrors
- // findOneOrFail throws code 404
- if (!app) throw new ApiError("Unknown Application", 10002, 404);
- if (!app.bot) throw new ApiError("OAuth2 application does not have a bot", 50010, 400);
+ // TODO: use DiscordApiErrors
+ // findOneOrFail throws code 404
+ if (!app) throw new ApiError("Unknown Application", 10002, 404);
+ if (!app.bot) throw new ApiError("OAuth2 application does not have a bot", 50010, 400);
- await Member.addToGuild(app.id, body.guild_id);
+ await Member.addToGuild(app.id, body.guild_id);
- return res.json({
- location: "/oauth2/authorized", // redirect URL
- });
- },
+ return res.json({
+ location: "/oauth2/authorized", // redirect URL
+ });
+ },
);
export default router;
diff --git a/src/api/routes/oauth2/tokens.ts b/src/api/routes/oauth2/tokens.ts
index 6b85bab..4af1061 100644
--- a/src/api/routes/oauth2/tokens.ts
+++ b/src/api/routes/oauth2/tokens.ts
@@ -21,8 +21,8 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- //TODO
- res.json([]);
+ //TODO
+ res.json([]);
});
export default router;
diff --git a/src/api/routes/outbound-promotions.ts b/src/api/routes/outbound-promotions.ts
index f1f9a29..e8e6f65 100644
--- a/src/api/routes/outbound-promotions.ts
+++ b/src/api/routes/outbound-promotions.ts
@@ -22,8 +22,8 @@
const router: Router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- //TODO
- res.json([]).status(200);
+ //TODO
+ res.json([]).status(200);
});
export default router;
diff --git "a/src/api/routes/partners/\043guild_id/requirements.ts" "b/src/api/routes/partners/\043guild_id/requirements.ts"
index 30ec8b3..9a08bc6 100644
--- "a/src/api/routes/partners/\043guild_id/requirements.ts"
+++ "b/src/api/routes/partners/\043guild_id/requirements.ts"
@@ -22,34 +22,34 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- const { guild_id } = req.params;
- // TODO:
- // Load from database
- // Admin control, but for now it allows anyone to be discoverable
+ const { guild_id } = req.params;
+ // TODO:
+ // Load from database
+ // Admin control, but for now it allows anyone to be discoverable
- res.send({
- guild_id: guild_id,
- safe_environment: true,
- healthy: true,
- health_score_pending: false,
- size: true,
- nsfw_properties: {},
- protected: true,
- sufficient: true,
- sufficient_without_grace_period: true,
- valid_rules_channel: true,
- retention_healthy: true,
- engagement_healthy: true,
- age: true,
- minimum_age: 0,
- health_score: {
- avg_nonnew_participators: 0,
- avg_nonnew_communicators: 0,
- num_intentful_joiners: 0,
- perc_ret_w1_intentful: 0,
- },
- minimum_size: 0,
- });
+ res.send({
+ guild_id: guild_id,
+ safe_environment: true,
+ healthy: true,
+ health_score_pending: false,
+ size: true,
+ nsfw_properties: {},
+ protected: true,
+ sufficient: true,
+ sufficient_without_grace_period: true,
+ valid_rules_channel: true,
+ retention_healthy: true,
+ engagement_healthy: true,
+ age: true,
+ minimum_age: 0,
+ health_score: {
+ avg_nonnew_participators: 0,
+ avg_nonnew_communicators: 0,
+ num_intentful_joiners: 0,
+ perc_ret_w1_intentful: 0,
+ },
+ minimum_size: 0,
+ });
});
export default router;
diff --git a/src/api/routes/ping.ts b/src/api/routes/ping.ts
index 55e4b7d..be737f8 100644
--- a/src/api/routes/ping.ts
+++ b/src/api/routes/ping.ts
@@ -23,32 +23,32 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "InstancePingResponse",
- },
- },
- }),
- (req: Request, res: Response) => {
- const { general } = Config.get();
- res.send({
- ping: "pong!",
- instance: {
- id: general.instanceId,
- name: general.instanceName,
- description: general.instanceDescription,
- image: general.image,
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "InstancePingResponse",
+ },
+ },
+ }),
+ (req: Request, res: Response) => {
+ const { general } = Config.get();
+ res.send({
+ ping: "pong!",
+ instance: {
+ id: general.instanceId,
+ name: general.instanceName,
+ description: general.instanceDescription,
+ image: general.image,
- correspondenceEmail: general.correspondenceEmail,
- correspondenceUserID: general.correspondenceUserID,
+ correspondenceEmail: general.correspondenceEmail,
+ correspondenceUserID: general.correspondenceUserID,
- frontPage: general.frontPage,
- tosPage: general.tosPage,
- },
- });
- },
+ frontPage: general.frontPage,
+ tosPage: general.tosPage,
+ },
+ });
+ },
);
export default router;
diff --git a/src/api/routes/policies/instance/config.ts b/src/api/routes/policies/instance/config.ts
index 97fb509..946ac8a 100755
--- a/src/api/routes/policies/instance/config.ts
+++ b/src/api/routes/policies/instance/config.ts
@@ -23,44 +23,44 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "Object",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const general = Config.get();
- let outputtedConfig;
- if (req.user_id) {
- const rights = await getRights(req.user_id);
- if (rights.has("OPERATOR")) outputtedConfig = general;
- } else {
- outputtedConfig = {
- limits_user_maxGuilds: general.limits.user.maxGuilds,
- limits_user_maxBio: general.limits.user.maxBio,
- limits_guild_maxEmojis: general.limits.guild.maxEmojis,
- limits_guild_maxRoles: general.limits.guild.maxRoles,
- limits_message_maxCharacters: general.limits.message.maxCharacters,
- limits_message_maxAttachmentSize: general.limits.message.maxAttachmentSize,
- limits_message_maxEmbedDownloadSize: general.limits.message.maxEmbedDownloadSize,
- limits_channel_maxWebhooks: general.limits.channel.maxWebhooks,
- register_dateOfBirth_requiredc: general.register.dateOfBirth.required,
- register_password_required: general.register.password.required,
- register_disabled: general.register.disabled,
- register_requireInvite: general.register.requireInvite,
- register_allowNewRegistration: general.register.allowNewRegistration,
- register_allowMultipleAccounts: general.register.allowMultipleAccounts,
- guild_autoJoin_canLeave: general.guild.autoJoin.canLeave,
- guild_autoJoin_guilds_x: general.guild.autoJoin.guilds,
- register_email_required: general.register.email.required,
- can_recover_account: general.email.provider != null && general.general.frontPage != null,
- };
- }
- res.send(outputtedConfig);
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "Object",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const general = Config.get();
+ let outputtedConfig;
+ if (req.user_id) {
+ const rights = await getRights(req.user_id);
+ if (rights.has("OPERATOR")) outputtedConfig = general;
+ } else {
+ outputtedConfig = {
+ limits_user_maxGuilds: general.limits.user.maxGuilds,
+ limits_user_maxBio: general.limits.user.maxBio,
+ limits_guild_maxEmojis: general.limits.guild.maxEmojis,
+ limits_guild_maxRoles: general.limits.guild.maxRoles,
+ limits_message_maxCharacters: general.limits.message.maxCharacters,
+ limits_message_maxAttachmentSize: general.limits.message.maxAttachmentSize,
+ limits_message_maxEmbedDownloadSize: general.limits.message.maxEmbedDownloadSize,
+ limits_channel_maxWebhooks: general.limits.channel.maxWebhooks,
+ register_dateOfBirth_requiredc: general.register.dateOfBirth.required,
+ register_password_required: general.register.password.required,
+ register_disabled: general.register.disabled,
+ register_requireInvite: general.register.requireInvite,
+ register_allowNewRegistration: general.register.allowNewRegistration,
+ register_allowMultipleAccounts: general.register.allowMultipleAccounts,
+ guild_autoJoin_canLeave: general.guild.autoJoin.canLeave,
+ guild_autoJoin_guilds_x: general.guild.autoJoin.guilds,
+ register_email_required: general.register.email.required,
+ can_recover_account: general.email.provider != null && general.general.frontPage != null,
+ };
+ }
+ res.send(outputtedConfig);
+ },
);
export default router;
diff --git a/src/api/routes/policies/instance/domains.ts b/src/api/routes/policies/instance/domains.ts
index 967ac2f..7aaaeb5 100644
--- a/src/api/routes/policies/instance/domains.ts
+++ b/src/api/routes/policies/instance/domains.ts
@@ -22,26 +22,26 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "InstanceDomainsResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { cdn, gateway, api } = Config.get();
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "InstanceDomainsResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { cdn, gateway, api } = Config.get();
- res.json({
- admin: Config.get().admin.endpointPublic,
- api: Config.get().api.endpointPublic?.split("/api")[0] || "", // Transitional, see /.well-known/spacebar/client
- apiEndpoint: api.endpointPublic,
- cdn: cdn.endpointPublic,
- defaultApiVersion: api.defaultVersion,
- gateway: gateway.endpointPublic,
- });
- },
+ res.json({
+ admin: Config.get().admin.endpointPublic,
+ api: Config.get().api.endpointPublic?.split("/api")[0] || "", // Transitional, see /.well-known/spacebar/client
+ apiEndpoint: api.endpointPublic,
+ cdn: cdn.endpointPublic,
+ defaultApiVersion: api.defaultVersion,
+ gateway: gateway.endpointPublic,
+ });
+ },
);
export default router;
diff --git a/src/api/routes/policies/instance/index.ts b/src/api/routes/policies/instance/index.ts
index 8fc214f..a54570f 100644
--- a/src/api/routes/policies/instance/index.ts
+++ b/src/api/routes/policies/instance/index.ts
@@ -22,18 +22,18 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APIGeneralConfiguration",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { general } = Config.get();
- res.json(general);
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APIGeneralConfiguration",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { general } = Config.get();
+ res.json(general);
+ },
);
export default router;
diff --git a/src/api/routes/policies/instance/limits.ts b/src/api/routes/policies/instance/limits.ts
index 0d0ed32..7ade151 100644
--- a/src/api/routes/policies/instance/limits.ts
+++ b/src/api/routes/policies/instance/limits.ts
@@ -22,18 +22,18 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APILimitsConfiguration",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { limits } = Config.get();
- res.json(limits);
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APILimitsConfiguration",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { limits } = Config.get();
+ res.json(limits);
+ },
);
export default router;
diff --git a/src/api/routes/policies/stats.ts b/src/api/routes/policies/stats.ts
index 0828c37..0edcfd6 100644
--- a/src/api/routes/policies/stats.ts
+++ b/src/api/routes/policies/stats.ts
@@ -22,32 +22,32 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "InstanceStatsResponse",
- },
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- if (!Config.get().security.statsWorldReadable) {
- const rights = await getRights(req.user_id);
- rights.hasThrow("VIEW_SERVER_STATS");
- }
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "InstanceStatsResponse",
+ },
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ if (!Config.get().security.statsWorldReadable) {
+ const rights = await getRights(req.user_id);
+ rights.hasThrow("VIEW_SERVER_STATS");
+ }
- res.json({
- counts: {
- user: await User.count(),
- guild: await Guild.count(),
- message: await Message.count(),
- members: await Member.count(),
- },
- });
- },
+ res.json({
+ counts: {
+ user: await User.count(),
+ guild: await Guild.count(),
+ message: await Message.count(),
+ members: await Member.count(),
+ },
+ });
+ },
);
export default router;
diff --git a/src/api/routes/read-states/ack-bulk.ts b/src/api/routes/read-states/ack-bulk.ts
index a597e4b..d0212c0 100644
--- a/src/api/routes/read-states/ack-bulk.ts
+++ b/src/api/routes/read-states/ack-bulk.ts
@@ -23,48 +23,48 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "AckBulkSchema",
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as AckBulkSchema;
+ "/",
+ route({
+ requestBody: "AckBulkSchema",
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as AckBulkSchema;
- // TODO: what is read_state_type ?
+ // TODO: what is read_state_type ?
- await Promise.all([
- // for every new state
- ...body.read_states.map(async (x) => {
- // find an existing one
- const ret =
- (await ReadState.findOne({
- where: {
- user_id: req.user_id,
- channel_id: x.channel_id,
- },
- })) ??
- // if it doesn't exist, create it (not a promise)
- ReadState.create({
- user_id: req.user_id,
- channel_id: x.channel_id,
- });
+ await Promise.all([
+ // for every new state
+ ...body.read_states.map(async (x) => {
+ // find an existing one
+ const ret =
+ (await ReadState.findOne({
+ where: {
+ user_id: req.user_id,
+ channel_id: x.channel_id,
+ },
+ })) ??
+ // if it doesn't exist, create it (not a promise)
+ ReadState.create({
+ user_id: req.user_id,
+ channel_id: x.channel_id,
+ });
- ret.last_message_id = x.message_id;
- //It's a little more complicated than this but this'll do
- ret.mention_count = 0;
+ ret.last_message_id = x.message_id;
+ //It's a little more complicated than this but this'll do
+ ret.mention_count = 0;
- return ret.save();
- }),
- ]);
+ return ret.save();
+ }),
+ ]);
- return res.sendStatus(204);
- },
+ return res.sendStatus(204);
+ },
);
export default router;
diff --git a/src/api/routes/reporting/menu/message.ts b/src/api/routes/reporting/menu/message.ts
index c72bc84..de57c79 100644
--- a/src/api/routes/reporting/menu/message.ts
+++ b/src/api/routes/reporting/menu/message.ts
@@ -22,19 +22,19 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "ReportingMenuResponse",
- },
- 204: {},
- },
- }),
- (req: Request, res: Response) => {
- // TODO: implement
- //res.send([] as ReportingMenuResponseSchema);
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "ReportingMenuResponse",
+ },
+ 204: {},
+ },
+ }),
+ (req: Request, res: Response) => {
+ // TODO: implement
+ //res.send([] as ReportingMenuResponseSchema);
+ },
);
export default router;
diff --git a/src/api/routes/safety-hub/@me/index.ts b/src/api/routes/safety-hub/@me/index.ts
index 06a1e28..7d0e7ff 100644
--- a/src/api/routes/safety-hub/@me/index.ts
+++ b/src/api/routes/safety-hub/@me/index.ts
@@ -24,36 +24,36 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "AccountStandingResponse",
- },
- 401: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- select: ["data"],
- });
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "AccountStandingResponse",
+ },
+ 401: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ select: ["data"],
+ });
- res.send({
- classifications: [],
- guild_classifications: [],
- account_standing: {
- state: AccountStandingState.ALL_GOOD,
- },
- is_dsa_eligible: true,
- username: user.username,
- discriminator: user.discriminator,
- is_appeal_eligible: true,
- appeal_eligibility: [AppealEligibility.DSA_ELIGIBLE, AppealEligibility.IN_APP_ELIGIBLE, AppealEligibility.AGE_VERIFY_ELIGIBLE],
- } as AccountStandingResponse);
- },
+ res.send({
+ classifications: [],
+ guild_classifications: [],
+ account_standing: {
+ state: AccountStandingState.ALL_GOOD,
+ },
+ is_dsa_eligible: true,
+ username: user.username,
+ discriminator: user.discriminator,
+ is_appeal_eligible: true,
+ appeal_eligibility: [AppealEligibility.DSA_ELIGIBLE, AppealEligibility.IN_APP_ELIGIBLE, AppealEligibility.AGE_VERIFY_ELIGIBLE],
+ } as AccountStandingResponse);
+ },
);
export default router;
diff --git a/src/api/routes/safety-hub/suspended/@me.ts b/src/api/routes/safety-hub/suspended/@me.ts
index 06a1e28..7d0e7ff 100644
--- a/src/api/routes/safety-hub/suspended/@me.ts
+++ b/src/api/routes/safety-hub/suspended/@me.ts
@@ -24,36 +24,36 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "AccountStandingResponse",
- },
- 401: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- select: ["data"],
- });
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "AccountStandingResponse",
+ },
+ 401: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ select: ["data"],
+ });
- res.send({
- classifications: [],
- guild_classifications: [],
- account_standing: {
- state: AccountStandingState.ALL_GOOD,
- },
- is_dsa_eligible: true,
- username: user.username,
- discriminator: user.discriminator,
- is_appeal_eligible: true,
- appeal_eligibility: [AppealEligibility.DSA_ELIGIBLE, AppealEligibility.IN_APP_ELIGIBLE, AppealEligibility.AGE_VERIFY_ELIGIBLE],
- } as AccountStandingResponse);
- },
+ res.send({
+ classifications: [],
+ guild_classifications: [],
+ account_standing: {
+ state: AccountStandingState.ALL_GOOD,
+ },
+ is_dsa_eligible: true,
+ username: user.username,
+ discriminator: user.discriminator,
+ is_appeal_eligible: true,
+ appeal_eligibility: [AppealEligibility.DSA_ELIGIBLE, AppealEligibility.IN_APP_ELIGIBLE, AppealEligibility.AGE_VERIFY_ELIGIBLE],
+ } as AccountStandingResponse);
+ },
);
export default router;
diff --git a/src/api/routes/scheduled-maintenances/upcoming.json.ts b/src/api/routes/scheduled-maintenances/upcoming.json.ts
index de4dcbf..5958d58 100644
--- a/src/api/routes/scheduled-maintenances/upcoming.json.ts
+++ b/src/api/routes/scheduled-maintenances/upcoming.json.ts
@@ -21,10 +21,10 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- res.json({
- page: {},
- scheduled_maintenances: {},
- });
+ res.json({
+ page: {},
+ scheduled_maintenances: {},
+ });
});
export default router;
diff --git a/src/api/routes/science.ts b/src/api/routes/science.ts
index 2d2d519..4a6ddea 100644
--- a/src/api/routes/science.ts
+++ b/src/api/routes/science.ts
@@ -22,16 +22,16 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- responses: {
- 204: {},
- },
- }),
- (req: Request, res: Response) => {
- // TODO:
- res.sendStatus(204);
- },
+ "/",
+ route({
+ responses: {
+ 204: {},
+ },
+ }),
+ (req: Request, res: Response) => {
+ // TODO:
+ res.sendStatus(204);
+ },
);
export default router;
diff --git a/src/api/routes/stage-instances.ts b/src/api/routes/stage-instances.ts
index f1f9a29..e8e6f65 100644
--- a/src/api/routes/stage-instances.ts
+++ b/src/api/routes/stage-instances.ts
@@ -22,8 +22,8 @@
const router: Router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- //TODO
- res.json([]).status(200);
+ //TODO
+ res.json([]).status(200);
});
export default router;
diff --git a/src/api/routes/sticker-packs/index.ts b/src/api/routes/sticker-packs/index.ts
index 7d2fe17..749ce02 100644
--- a/src/api/routes/sticker-packs/index.ts
+++ b/src/api/routes/sticker-packs/index.ts
@@ -23,21 +23,21 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APIStickerPackArray",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const sticker_packs = await StickerPack.find({
- relations: ["stickers"],
- });
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APIStickerPackArray",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const sticker_packs = await StickerPack.find({
+ relations: ["stickers"],
+ });
- res.json({ sticker_packs });
- },
+ res.json({ sticker_packs });
+ },
);
export default router;
diff --git "a/src/api/routes/stickers/\043sticker_id/index.ts" "b/src/api/routes/stickers/\043sticker_id/index.ts"
index ddbc397..0f850ef 100644
--- "a/src/api/routes/stickers/\043sticker_id/index.ts"
+++ "b/src/api/routes/stickers/\043sticker_id/index.ts"
@@ -22,19 +22,19 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "Sticker",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { sticker_id } = req.params;
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "Sticker",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { sticker_id } = req.params;
- res.json(await Sticker.find({ where: { id: sticker_id } }));
- },
+ res.json(await Sticker.find({ where: { id: sticker_id } }));
+ },
);
export default router;
diff --git a/src/api/routes/stop.ts b/src/api/routes/stop.ts
index bf4af56..be29e0a 100644
--- a/src/api/routes/stop.ts
+++ b/src/api/routes/stop.ts
@@ -22,21 +22,21 @@
const router: Router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- right: "OPERATOR",
- responses: {
- 200: {},
- 403: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- console.log(`/stop was called by ${req.user_id} at ${new Date()}`);
- res.sendStatus(200);
- process.kill(process.pid, "SIGTERM");
- },
+ "/",
+ route({
+ right: "OPERATOR",
+ responses: {
+ 200: {},
+ 403: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ console.log(`/stop was called by ${req.user_id} at ${new Date()}`);
+ res.sendStatus(200);
+ process.kill(process.pid, "SIGTERM");
+ },
);
export default router;
diff --git "a/src/api/routes/store/published-listings/applications/\043application_id/index.ts" "b/src/api/routes/store/published-listings/applications/\043application_id/index.ts"
index eb2df64..39fa9db 100644
--- "a/src/api/routes/store/published-listings/applications/\043application_id/index.ts"
+++ "b/src/api/routes/store/published-listings/applications/\043application_id/index.ts"
@@ -22,76 +22,76 @@
const router: Router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- //TODO
- // const id = req.params.id;
- res.json({
- id: "",
- summary: "",
- sku: {
- id: "",
- type: 1,
- dependent_sku_id: null,
- application_id: "",
- manifest_labels: [],
- access_type: 2,
- name: "",
- features: [],
- release_date: "",
- premium: false,
- slug: "",
- flags: 4,
- genres: [],
- legal_notice: "",
- application: {
- id: "",
- name: "",
- icon: "",
- description: "",
- summary: "",
- cover_image: "",
- primary_sku_id: "",
- hook: true,
- slug: "",
- guild_id: "",
- bot_public: "",
- bot_require_code_grant: false,
- verify_key: "",
- publishers: [
- {
- id: "",
- name: "",
- },
- ],
- developers: [
- {
- id: "",
- name: "",
- },
- ],
- system_requirements: {},
- show_age_gate: false,
- price: {
- amount: 0,
- currency: "EUR",
- },
- locales: [],
- },
- tagline: "",
- description: "",
- carousel_items: [
- {
- asset_id: "",
- },
- ],
- header_logo_dark_theme: {}, //{id: "", size: 4665, mime_type: "image/gif", width 160, height: 160}
- header_logo_light_theme: {},
- box_art: {},
- thumbnail: {},
- header_background: {},
- hero_background: {},
- assets: [],
- },
- }).status(200);
+ //TODO
+ // const id = req.params.id;
+ res.json({
+ id: "",
+ summary: "",
+ sku: {
+ id: "",
+ type: 1,
+ dependent_sku_id: null,
+ application_id: "",
+ manifest_labels: [],
+ access_type: 2,
+ name: "",
+ features: [],
+ release_date: "",
+ premium: false,
+ slug: "",
+ flags: 4,
+ genres: [],
+ legal_notice: "",
+ application: {
+ id: "",
+ name: "",
+ icon: "",
+ description: "",
+ summary: "",
+ cover_image: "",
+ primary_sku_id: "",
+ hook: true,
+ slug: "",
+ guild_id: "",
+ bot_public: "",
+ bot_require_code_grant: false,
+ verify_key: "",
+ publishers: [
+ {
+ id: "",
+ name: "",
+ },
+ ],
+ developers: [
+ {
+ id: "",
+ name: "",
+ },
+ ],
+ system_requirements: {},
+ show_age_gate: false,
+ price: {
+ amount: 0,
+ currency: "EUR",
+ },
+ locales: [],
+ },
+ tagline: "",
+ description: "",
+ carousel_items: [
+ {
+ asset_id: "",
+ },
+ ],
+ header_logo_dark_theme: {}, //{id: "", size: 4665, mime_type: "image/gif", width 160, height: 160}
+ header_logo_light_theme: {},
+ box_art: {},
+ thumbnail: {},
+ header_background: {},
+ hero_background: {},
+ assets: [],
+ },
+ }).status(200);
});
export default router;
diff --git "a/src/api/routes/store/published-listings/applications/\043application_id/subscription-plans.ts" "b/src/api/routes/store/published-listings/applications/\043application_id/subscription-plans.ts"
index b8f5963..953e391 100644
--- "a/src/api/routes/store/published-listings/applications/\043application_id/subscription-plans.ts"
+++ "b/src/api/routes/store/published-listings/applications/\043application_id/subscription-plans.ts"
@@ -22,22 +22,22 @@
const router: Router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- //TODO
- res.json([
- {
- id: "",
- name: "",
- interval: 1,
- interval_count: 1,
- tax_inclusive: true,
- sku_id: "",
- fallback_price: 499,
- fallback_currency: "eur",
- currency: "eur",
- price: 4199,
- price_tier: null,
- },
- ]).status(200);
+ //TODO
+ res.json([
+ {
+ id: "",
+ name: "",
+ interval: 1,
+ interval_count: 1,
+ tax_inclusive: true,
+ sku_id: "",
+ fallback_price: 499,
+ fallback_currency: "eur",
+ currency: "eur",
+ price: 4199,
+ price_tier: null,
+ },
+ ]).status(200);
});
export default router;
diff --git a/src/api/routes/store/published-listings/skus.ts b/src/api/routes/store/published-listings/skus.ts
index a463b4e..03cbab4 100644
--- a/src/api/routes/store/published-listings/skus.ts
+++ b/src/api/routes/store/published-listings/skus.ts
@@ -22,76 +22,76 @@
const router: Router = Router({ mergeParams: true });
router.get("/:sku_id", route({}), async (req: Request, res: Response) => {
- //TODO
- // const id = req.params.id;
- res.json({
- id: "",
- summary: "",
- sku: {
- id: "",
- type: 1,
- dependent_sku_id: null,
- application_id: "",
- manifets_labels: [],
- access_type: 2,
- name: "",
- features: [],
- release_date: "",
- premium: false,
- slug: "",
- flags: 4,
- genres: [],
- legal_notice: "",
- application: {
- id: "",
- name: "",
- icon: "",
- description: "",
- summary: "",
- cover_image: "",
- primary_sku_id: "",
- hook: true,
- slug: "",
- guild_id: "",
- bot_public: "",
- bot_require_code_grant: false,
- verify_key: "",
- publishers: [
- {
- id: "",
- name: "",
- },
- ],
- developers: [
- {
- id: "",
- name: "",
- },
- ],
- system_requirements: {},
- show_age_gate: false,
- price: {
- amount: 0,
- currency: "EUR",
- },
- locales: [],
- },
- tagline: "",
- description: "",
- carousel_items: [
- {
- asset_id: "",
- },
- ],
- header_logo_dark_theme: {}, //{id: "", size: 4665, mime_type: "image/gif", width 160, height: 160}
- header_logo_light_theme: {},
- box_art: {},
- thumbnail: {},
- header_background: {},
- hero_background: {},
- assets: [],
- },
- }).status(200);
+ //TODO
+ // const id = req.params.id;
+ res.json({
+ id: "",
+ summary: "",
+ sku: {
+ id: "",
+ type: 1,
+ dependent_sku_id: null,
+ application_id: "",
+ manifets_labels: [],
+ access_type: 2,
+ name: "",
+ features: [],
+ release_date: "",
+ premium: false,
+ slug: "",
+ flags: 4,
+ genres: [],
+ legal_notice: "",
+ application: {
+ id: "",
+ name: "",
+ icon: "",
+ description: "",
+ summary: "",
+ cover_image: "",
+ primary_sku_id: "",
+ hook: true,
+ slug: "",
+ guild_id: "",
+ bot_public: "",
+ bot_require_code_grant: false,
+ verify_key: "",
+ publishers: [
+ {
+ id: "",
+ name: "",
+ },
+ ],
+ developers: [
+ {
+ id: "",
+ name: "",
+ },
+ ],
+ system_requirements: {},
+ show_age_gate: false,
+ price: {
+ amount: 0,
+ currency: "EUR",
+ },
+ locales: [],
+ },
+ tagline: "",
+ description: "",
+ carousel_items: [
+ {
+ asset_id: "",
+ },
+ ],
+ header_logo_dark_theme: {}, //{id: "", size: 4665, mime_type: "image/gif", width 160, height: 160}
+ header_logo_light_theme: {},
+ box_art: {},
+ thumbnail: {},
+ header_background: {},
+ hero_background: {},
+ assets: [],
+ },
+ }).status(200);
});
export default router;
diff --git "a/src/api/routes/store/published-listings/skus/\043sku_id/subscription-plans.ts" "b/src/api/routes/store/published-listings/skus/\043sku_id/subscription-plans.ts"
index f2ea23c..0aae149 100644
--- "a/src/api/routes/store/published-listings/skus/\043sku_id/subscription-plans.ts"
+++ "b/src/api/routes/store/published-listings/skus/\043sku_id/subscription-plans.ts"
@@ -22,310 +22,310 @@
const router: Router = Router({ mergeParams: true });
const skus = new Map([
- [
- "521842865731534868",
- [
- {
- id: "511651856145973248",
- name: "Individual Premium Tier 3 Monthly (Legacy)",
- interval: 1,
- interval_count: 1,
- tax_inclusive: true,
- sku_id: "521842865731534868",
- currency: "eur",
- price: 0,
- price_tier: null,
- },
- {
- id: "511651860671627264",
- name: "Individiual Premium Tier 3 Yearly (Legacy)",
- interval: 2,
- interval_count: 1,
- tax_inclusive: true,
- sku_id: "521842865731534868",
- currency: "eur",
- price: 0,
- price_tier: null,
- },
- ],
- ],
- [
- "521846918637420545",
- [
- {
- id: "511651871736201216",
- name: "Individual Premium Tier 2 Monthly",
- interval: 1,
- interval_count: 1,
- tax_inclusive: true,
- sku_id: "521846918637420545",
- currency: "eur",
- price: 0,
- price_tier: null,
- },
- {
- id: "511651876987469824",
- name: "Individual Premum Tier 2 Yearly",
- interval: 2,
- interval_count: 1,
- tax_inclusive: true,
- sku_id: "521846918637420545",
- currency: "eur",
- price: 0,
- price_tier: null,
- },
- {
- id: "978380684370378761",
- name: "Individual Premum Tier 1",
- interval: 2,
- interval_count: 1,
- tax_inclusive: true,
- sku_id: "521846918637420545",
- currency: "eur",
- price: 0,
- price_tier: null,
- },
- ],
- ],
- [
- "521847234246082599",
- [
- {
- id: "642251038925127690",
- name: "Individual Premium Tier 3 Quarterly",
- interval: 1,
- interval_count: 3,
- tax_inclusive: true,
- sku_id: "521847234246082599",
- currency: "eur",
- price: 0,
- price_tier: null,
- },
- {
- id: "511651880837840896",
- name: "Individual Premium Tier 3 Monthly",
- interval: 1,
- interval_count: 1,
- tax_inclusive: true,
- sku_id: "521847234246082599",
- currency: "eur",
- price: 0,
- price_tier: null,
- },
- {
- id: "511651885459963904",
- name: "Individual Premium Tier 3 Yearly",
- interval: 2,
- interval_count: 1,
- tax_inclusive: true,
- sku_id: "521847234246082599",
- currency: "eur",
- price: 0,
- price_tier: null,
- },
- ],
- ],
- [
- "590663762298667008",
- [
- {
- id: "590665532894740483",
- name: "Crowd Premium Monthly",
- interval: 1,
- interval_count: 1,
- tax_inclusive: true,
- sku_id: "590663762298667008",
- discount_price: 0,
- currency: "eur",
- price: 0,
- price_tier: null,
- },
- {
- id: "590665538238152709",
- name: "Crowd Premium Yearly",
- interval: 2,
- interval_count: 1,
- tax_inclusive: true,
- sku_id: "590663762298667008",
- discount_price: 0,
- currency: "eur",
- price: 0,
- price_tier: null,
- },
- ],
- ],
- [
- "978380684370378762",
- [
- [
- {
- id: "978380692553465866",
- name: "Premium Tier 0 Monthly",
- interval: 1,
- interval_count: 1,
- tax_inclusive: true,
- sku_id: "978380684370378762",
- currency: "usd",
- price: 299,
- price_tier: null,
- prices: {
- "0": {
- country_prices: {
- country_code: "US",
- prices: [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- },
- payment_source_prices: {
- "775487223059316758": [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- "736345864146255982": [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- "683074999590060249": [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- },
- },
- "3": {
- country_prices: {
- country_code: "US",
- prices: [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- },
- payment_source_prices: {
- "775487223059316758": [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- "736345864146255982": [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- "683074999590060249": [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- },
- },
- "4": {
- country_prices: {
- country_code: "US",
- prices: [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- },
- payment_source_prices: {
- "775487223059316758": [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- "736345864146255982": [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- "683074999590060249": [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- },
- },
- "1": {
- country_prices: {
- country_code: "US",
- prices: [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- },
- payment_source_prices: {
- "775487223059316758": [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- "736345864146255982": [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- "683074999590060249": [
- {
- currency: "usd",
- amount: 0,
- exponent: 2,
- },
- ],
- },
- },
- },
- },
- ],
- ],
- ],
+ [
+ "521842865731534868",
+ [
+ {
+ id: "511651856145973248",
+ name: "Individual Premium Tier 3 Monthly (Legacy)",
+ interval: 1,
+ interval_count: 1,
+ tax_inclusive: true,
+ sku_id: "521842865731534868",
+ currency: "eur",
+ price: 0,
+ price_tier: null,
+ },
+ {
+ id: "511651860671627264",
+ name: "Individiual Premium Tier 3 Yearly (Legacy)",
+ interval: 2,
+ interval_count: 1,
+ tax_inclusive: true,
+ sku_id: "521842865731534868",
+ currency: "eur",
+ price: 0,
+ price_tier: null,
+ },
+ ],
+ ],
+ [
+ "521846918637420545",
+ [
+ {
+ id: "511651871736201216",
+ name: "Individual Premium Tier 2 Monthly",
+ interval: 1,
+ interval_count: 1,
+ tax_inclusive: true,
+ sku_id: "521846918637420545",
+ currency: "eur",
+ price: 0,
+ price_tier: null,
+ },
+ {
+ id: "511651876987469824",
+ name: "Individual Premum Tier 2 Yearly",
+ interval: 2,
+ interval_count: 1,
+ tax_inclusive: true,
+ sku_id: "521846918637420545",
+ currency: "eur",
+ price: 0,
+ price_tier: null,
+ },
+ {
+ id: "978380684370378761",
+ name: "Individual Premum Tier 1",
+ interval: 2,
+ interval_count: 1,
+ tax_inclusive: true,
+ sku_id: "521846918637420545",
+ currency: "eur",
+ price: 0,
+ price_tier: null,
+ },
+ ],
+ ],
+ [
+ "521847234246082599",
+ [
+ {
+ id: "642251038925127690",
+ name: "Individual Premium Tier 3 Quarterly",
+ interval: 1,
+ interval_count: 3,
+ tax_inclusive: true,
+ sku_id: "521847234246082599",
+ currency: "eur",
+ price: 0,
+ price_tier: null,
+ },
+ {
+ id: "511651880837840896",
+ name: "Individual Premium Tier 3 Monthly",
+ interval: 1,
+ interval_count: 1,
+ tax_inclusive: true,
+ sku_id: "521847234246082599",
+ currency: "eur",
+ price: 0,
+ price_tier: null,
+ },
+ {
+ id: "511651885459963904",
+ name: "Individual Premium Tier 3 Yearly",
+ interval: 2,
+ interval_count: 1,
+ tax_inclusive: true,
+ sku_id: "521847234246082599",
+ currency: "eur",
+ price: 0,
+ price_tier: null,
+ },
+ ],
+ ],
+ [
+ "590663762298667008",
+ [
+ {
+ id: "590665532894740483",
+ name: "Crowd Premium Monthly",
+ interval: 1,
+ interval_count: 1,
+ tax_inclusive: true,
+ sku_id: "590663762298667008",
+ discount_price: 0,
+ currency: "eur",
+ price: 0,
+ price_tier: null,
+ },
+ {
+ id: "590665538238152709",
+ name: "Crowd Premium Yearly",
+ interval: 2,
+ interval_count: 1,
+ tax_inclusive: true,
+ sku_id: "590663762298667008",
+ discount_price: 0,
+ currency: "eur",
+ price: 0,
+ price_tier: null,
+ },
+ ],
+ ],
+ [
+ "978380684370378762",
+ [
+ [
+ {
+ id: "978380692553465866",
+ name: "Premium Tier 0 Monthly",
+ interval: 1,
+ interval_count: 1,
+ tax_inclusive: true,
+ sku_id: "978380684370378762",
+ currency: "usd",
+ price: 299,
+ price_tier: null,
+ prices: {
+ "0": {
+ country_prices: {
+ country_code: "US",
+ prices: [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ },
+ payment_source_prices: {
+ "775487223059316758": [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ "736345864146255982": [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ "683074999590060249": [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ },
+ },
+ "3": {
+ country_prices: {
+ country_code: "US",
+ prices: [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ },
+ payment_source_prices: {
+ "775487223059316758": [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ "736345864146255982": [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ "683074999590060249": [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ },
+ },
+ "4": {
+ country_prices: {
+ country_code: "US",
+ prices: [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ },
+ payment_source_prices: {
+ "775487223059316758": [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ "736345864146255982": [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ "683074999590060249": [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ },
+ },
+ "1": {
+ country_prices: {
+ country_code: "US",
+ prices: [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ },
+ payment_source_prices: {
+ "775487223059316758": [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ "736345864146255982": [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ "683074999590060249": [
+ {
+ currency: "usd",
+ amount: 0,
+ exponent: 2,
+ },
+ ],
+ },
+ },
+ },
+ },
+ ],
+ ],
+ ],
]);
router.get("/", route({}), async (req: Request, res: Response) => {
- // TODO: add the ability to add custom
- const { sku_id } = req.params;
+ // TODO: add the ability to add custom
+ const { sku_id } = req.params;
- if (!skus.has(sku_id)) {
- console.log(`Request for invalid SKU ${sku_id}! Please report this!`);
- res.sendStatus(404);
- } else {
- res.json(skus.get(sku_id)).status(200);
- }
+ if (!skus.has(sku_id)) {
+ console.log(`Request for invalid SKU ${sku_id}! Please report this!`);
+ res.sendStatus(404);
+ } else {
+ res.json(skus.get(sku_id)).status(200);
+ }
});
export default router;
diff --git a/src/api/routes/teams.ts b/src/api/routes/teams.ts
index 21ec3a5..27ccabf 100644
--- a/src/api/routes/teams.ts
+++ b/src/api/routes/teams.ts
@@ -25,67 +25,67 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- query: {
- include_payout_account_status: {
- type: "boolean",
- description: "Whether to include team payout account status in the response (default false)",
- },
- },
- responses: {
- 200: {
- body: "TeamListResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const teams = await Team.find({
- where: {
- owner_user_id: req.user_id,
- },
- relations: ["members"],
- });
+ "/",
+ route({
+ query: {
+ include_payout_account_status: {
+ type: "boolean",
+ description: "Whether to include team payout account status in the response (default false)",
+ },
+ },
+ responses: {
+ 200: {
+ body: "TeamListResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const teams = await Team.find({
+ where: {
+ owner_user_id: req.user_id,
+ },
+ relations: ["members"],
+ });
- res.send(teams);
- },
+ res.send(teams);
+ },
);
router.post(
- "/",
- route({
- requestBody: "TeamCreateSchema",
- responses: {
- 200: {
- body: "Team",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const user = await User.findOneOrFail({
- where: [{ id: req.user_id }],
- select: ["mfa_enabled"],
- });
- if (!user.mfa_enabled) throw new HTTPError("You must enable MFA to create a team");
+ "/",
+ route({
+ requestBody: "TeamCreateSchema",
+ responses: {
+ 200: {
+ body: "Team",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const user = await User.findOneOrFail({
+ where: [{ id: req.user_id }],
+ select: ["mfa_enabled"],
+ });
+ if (!user.mfa_enabled) throw new HTTPError("You must enable MFA to create a team");
- const body = req.body as TeamCreateSchema;
+ const body = req.body as TeamCreateSchema;
- const team = Team.create({
- name: body.name,
- owner_user_id: req.user_id,
- });
- await team.save();
+ const team = Team.create({
+ name: body.name,
+ owner_user_id: req.user_id,
+ });
+ await team.save();
- await TeamMember.create({
- user_id: req.user_id,
- team_id: team.id,
- membership_state: TeamMemberState.ACCEPTED,
- permissions: ["*"],
- role: TeamMemberRole.ADMIN,
- }).save();
+ await TeamMember.create({
+ user_id: req.user_id,
+ team_id: team.id,
+ membership_state: TeamMemberState.ACCEPTED,
+ permissions: ["*"],
+ role: TeamMemberRole.ADMIN,
+ }).save();
- res.json(team);
- },
+ res.json(team);
+ },
);
export default router;
diff --git a/src/api/routes/track.ts b/src/api/routes/track.ts
index 644302c..d320613 100644
--- a/src/api/routes/track.ts
+++ b/src/api/routes/track.ts
@@ -22,8 +22,8 @@
const router = Router({ mergeParams: true });
router.post("/", route({}), (req: Request, res: Response) => {
- // TODO:
- res.sendStatus(204);
+ // TODO:
+ res.sendStatus(204);
});
export default router;
diff --git a/src/api/routes/updates.ts b/src/api/routes/updates.ts
index 5262dc2..7228a76 100644
--- a/src/api/routes/updates.ts
+++ b/src/api/routes/updates.ts
@@ -23,46 +23,46 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "UpdatesResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const platform = req.query.platform;
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "UpdatesResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const platform = req.query.platform;
- if (!platform)
- throw FieldErrors({
- platform: {
- code: "BASE_TYPE_REQUIRED",
- message: req.t("common:field.BASE_TYPE_REQUIRED"),
- },
- });
+ if (!platform)
+ throw FieldErrors({
+ platform: {
+ code: "BASE_TYPE_REQUIRED",
+ message: req.t("common:field.BASE_TYPE_REQUIRED"),
+ },
+ });
- const release = await ClientRelease.findOneOrFail({
- where: {
- enabled: true,
- platform: platform as string,
- },
- order: { pub_date: "DESC" },
- });
+ const release = await ClientRelease.findOneOrFail({
+ where: {
+ enabled: true,
+ platform: platform as string,
+ },
+ order: { pub_date: "DESC" },
+ });
- res.json({
- name: release.name,
- pub_date: release.pub_date,
- url: release.url,
- notes: release.notes,
- });
- },
+ res.json({
+ name: release.name,
+ pub_date: release.pub_date,
+ url: release.url,
+ notes: release.notes,
+ });
+ },
);
export default router;
diff --git "a/src/api/routes/users/\043user_id/delete.ts" "b/src/api/routes/users/\043user_id/delete.ts"
index be361f1..c2286ce 100644
--- "a/src/api/routes/users/\043user_id/delete.ts"
+++ "b/src/api/routes/users/\043user_id/delete.ts"
@@ -18,20 +18,20 @@
import { route } from "@spacebar/api";
import {
- Channel,
- ChannelDeleteEvent,
- ChannelRecipientRemoveEvent,
- emitEvent,
- Emoji,
- Guild,
- InstanceBan,
- Member,
- Recipient,
- Sticker,
- Stopwatch,
- User,
- UserDeleteEvent,
- UserSettingsProtos,
+ Channel,
+ ChannelDeleteEvent,
+ ChannelRecipientRemoveEvent,
+ emitEvent,
+ Emoji,
+ Guild,
+ InstanceBan,
+ Member,
+ Recipient,
+ Sticker,
+ Stopwatch,
+ User,
+ UserDeleteEvent,
+ UserSettingsProtos,
} from "@spacebar/util";
import { Request, Response, Router } from "express";
import { ChannelType, InstanceUserDeleteSchema, PrivateUserProjection } from "@spacebar/schemas";
@@ -40,158 +40,158 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- right: "MANAGE_USERS",
- requestBody: "InstanceUserDeleteSchema",
- responses: {
- 204: {},
- 403: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const sw = Stopwatch.startNew();
- const body = req.body as InstanceUserDeleteSchema | undefined;
- const user = await User.findOneOrFail({
- where: { id: req.params.user_id },
- select: [...PrivateUserProjection, "data"],
- });
+ "/",
+ route({
+ right: "MANAGE_USERS",
+ requestBody: "InstanceUserDeleteSchema",
+ responses: {
+ 204: {},
+ 403: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const sw = Stopwatch.startNew();
+ const body = req.body as InstanceUserDeleteSchema | undefined;
+ const user = await User.findOneOrFail({
+ where: { id: req.params.user_id },
+ select: [...PrivateUserProjection, "data"],
+ });
- if ((body?.persistInstanceBan ?? true) && !(await InstanceBan.findOne({ where: { user_id: user.id } })))
- await InstanceBan.create({ user_id: user.id, reason: body?.reason ?? "" }).save();
+ if ((body?.persistInstanceBan ?? true) && !(await InstanceBan.findOne({ where: { user_id: user.id } })))
+ await InstanceBan.create({ user_id: user.id, reason: body?.reason ?? "" }).save();
- // prevent bugginess with clients - delete all DMs, only having half of the conversation is quite useless anyhow
- const dmChannels = await user.getDmChannels();
- for (const channel of dmChannels) {
- console.log(`[Instance ban] Deleting DM channel ${channel.id} for user ${user.id}`);
- await emitEvent({
- event: "CHANNEL_DELETE",
- data: channel.toJSON(),
- channel_id: channel.id,
- } as ChannelDeleteEvent);
- await Recipient.delete({ channel_id: channel.id });
- await Channel.deleteChannel(channel);
- }
+ // prevent bugginess with clients - delete all DMs, only having half of the conversation is quite useless anyhow
+ const dmChannels = await user.getDmChannels();
+ for (const channel of dmChannels) {
+ console.log(`[Instance ban] Deleting DM channel ${channel.id} for user ${user.id}`);
+ await emitEvent({
+ event: "CHANNEL_DELETE",
+ data: channel.toJSON(),
+ channel_id: channel.id,
+ } as ChannelDeleteEvent);
+ await Recipient.delete({ channel_id: channel.id });
+ await Channel.deleteChannel(channel);
+ }
- //leave all group channels
- const groupChannels = await Channel.find({
- where: { type: ChannelType.GROUP_DM },
- relations: ["recipients"],
- select: {
- id: true,
- owner_id: true,
- recipients: {
- id: true,
- user_id: true,
- },
- },
- });
+ //leave all group channels
+ const groupChannels = await Channel.find({
+ where: { type: ChannelType.GROUP_DM },
+ relations: ["recipients"],
+ select: {
+ id: true,
+ owner_id: true,
+ recipients: {
+ id: true,
+ user_id: true,
+ },
+ },
+ });
- await Promise.all(
- groupChannels.map(async (channel) => {
- const recipient = channel.recipients!.find((r) => r.user_id === user.id);
- if (recipient) {
- await Recipient.delete({ id: recipient.id });
- await emitEvent({
- event: "CHANNEL_RECIPIENT_REMOVE",
- data: {
- user: user.toPublicUser(),
- channel_id: channel.id,
- },
- channel_id: channel.id,
- } as ChannelRecipientRemoveEvent);
- console.log(`[Instance ban] Removed user ${user.id} from group channel ${channel.id}`);
- }
+ await Promise.all(
+ groupChannels.map(async (channel) => {
+ const recipient = channel.recipients!.find((r) => r.user_id === user.id);
+ if (recipient) {
+ await Recipient.delete({ id: recipient.id });
+ await emitEvent({
+ event: "CHANNEL_RECIPIENT_REMOVE",
+ data: {
+ user: user.toPublicUser(),
+ channel_id: channel.id,
+ },
+ channel_id: channel.id,
+ } as ChannelRecipientRemoveEvent);
+ console.log(`[Instance ban] Removed user ${user.id} from group channel ${channel.id}`);
+ }
- // if no recipients remain, delete the channel
- const remainingRecipients = await Recipient.find({ where: { channel_id: channel.id } });
- if (remainingRecipients.length === 0) {
- await emitEvent({
- event: "CHANNEL_DELETE",
- data: channel.toJSON(),
- channel_id: channel.id,
- } as ChannelDeleteEvent);
- await Channel.deleteChannel(channel);
- console.log(`[Instance ban] Deleted empty group channel ${channel.id}`);
- } else {
- // otherwise, if the banned user was the owner, reassign ownership
- if (channel.owner_id === user.id) {
- channel.owner_id = remainingRecipients[0].user_id;
- await channel.save();
- console.log(`[Instance ban] Reassigned ownership of group channel ${channel.id} to user ${channel.owner_id}`);
- }
- }
- }),
- );
+ // if no recipients remain, delete the channel
+ const remainingRecipients = await Recipient.find({ where: { channel_id: channel.id } });
+ if (remainingRecipients.length === 0) {
+ await emitEvent({
+ event: "CHANNEL_DELETE",
+ data: channel.toJSON(),
+ channel_id: channel.id,
+ } as ChannelDeleteEvent);
+ await Channel.deleteChannel(channel);
+ console.log(`[Instance ban] Deleted empty group channel ${channel.id}`);
+ } else {
+ // otherwise, if the banned user was the owner, reassign ownership
+ if (channel.owner_id === user.id) {
+ channel.owner_id = remainingRecipients[0].user_id;
+ await channel.save();
+ console.log(`[Instance ban] Reassigned ownership of group channel ${channel.id} to user ${channel.owner_id}`);
+ }
+ }
+ }),
+ );
- // change ownership on guilds
- const guilds = await Guild.find({ where: { owner_id: req.params.user_id } });
- await Promise.all(
- guilds.map(async (guild) => {
- const members = await Member.find({
- where: { guild_id: guild.id, id: Not(req.params.user_id) },
- relations: { roles: true },
- select: { id: true, roles: { id: true, position: true } },
- });
- const sortedMembers = members
- .filter((m) => m.id !== req.params.user_id)
- .sort((a, b) => {
- const aHighestRole = a.roles.reduce((prev, curr) => (curr.position > prev.position ? curr : prev), { position: -1 } as { position: number });
- const bHighestRole = b.roles.reduce((prev, curr) => (curr.position > prev.position ? curr : prev), { position: -1 } as { position: number });
- return bHighestRole.position - aHighestRole.position;
- });
- if (sortedMembers.length === 0) {
- // no members left, delete guild
- await guild.remove();
- console.log(`[Instance ban] Deleted guild ${guild.id} as user ${user.id} was the last member`);
- } else {
- // assign new owner
- guild.owner_id = sortedMembers[0].id;
- await guild.save();
- console.log(`[Instance ban] Transferred ownership of guild ${guild.id} to user ${guild.owner_id}`);
+ // change ownership on guilds
+ const guilds = await Guild.find({ where: { owner_id: req.params.user_id } });
+ await Promise.all(
+ guilds.map(async (guild) => {
+ const members = await Member.find({
+ where: { guild_id: guild.id, id: Not(req.params.user_id) },
+ relations: { roles: true },
+ select: { id: true, roles: { id: true, position: true } },
+ });
+ const sortedMembers = members
+ .filter((m) => m.id !== req.params.user_id)
+ .sort((a, b) => {
+ const aHighestRole = a.roles.reduce((prev, curr) => (curr.position > prev.position ? curr : prev), { position: -1 } as { position: number });
+ const bHighestRole = b.roles.reduce((prev, curr) => (curr.position > prev.position ? curr : prev), { position: -1 } as { position: number });
+ return bHighestRole.position - aHighestRole.position;
+ });
+ if (sortedMembers.length === 0) {
+ // no members left, delete guild
+ await guild.remove();
+ console.log(`[Instance ban] Deleted guild ${guild.id} as user ${user.id} was the last member`);
+ } else {
+ // assign new owner
+ guild.owner_id = sortedMembers[0].id;
+ await guild.save();
+ console.log(`[Instance ban] Transferred ownership of guild ${guild.id} to user ${guild.owner_id}`);
- // safety - reassign emojis/stickers owned by the old owner
- const stickers = await Sticker.find({ where: { guild_id: guild.id, user_id: req.params.user_id } });
- await Promise.all(
- stickers.map(async (sticker) => {
- sticker.user_id = guild.owner_id;
- await sticker.save();
- console.log(`[Instance ban] Reassigned sticker ${sticker.id} ownership to user ${guild.owner_id}`);
- }),
- );
+ // safety - reassign emojis/stickers owned by the old owner
+ const stickers = await Sticker.find({ where: { guild_id: guild.id, user_id: req.params.user_id } });
+ await Promise.all(
+ stickers.map(async (sticker) => {
+ sticker.user_id = guild.owner_id;
+ await sticker.save();
+ console.log(`[Instance ban] Reassigned sticker ${sticker.id} ownership to user ${guild.owner_id}`);
+ }),
+ );
- const emojis = await Emoji.find({ where: { guild_id: guild.id, user_id: req.params.user_id } });
- await Promise.all(
- emojis.map(async (emoji) => {
- emoji.user_id = guild.owner_id!;
- await emoji.save();
- console.log(`[Instance ban] Reassigned emoji ${emoji.id} ownership to user ${guild.owner_id}`);
- }),
- );
- }
- }),
- );
+ const emojis = await Emoji.find({ where: { guild_id: guild.id, user_id: req.params.user_id } });
+ await Promise.all(
+ emojis.map(async (emoji) => {
+ emoji.user_id = guild.owner_id!;
+ await emoji.save();
+ console.log(`[Instance ban] Reassigned emoji ${emoji.id} ownership to user ${guild.owner_id}`);
+ }),
+ );
+ }
+ }),
+ );
- const members = await Member.find({ where: { id: req.params.user_id } });
- await Promise.all([...members.map((member) => Member.removeFromGuild(member.id, member.guild_id))]);
- await UserSettingsProtos.delete({ user_id: req.params.user_id });
- await User.delete({ id: req.params.user_id });
+ const members = await Member.find({ where: { id: req.params.user_id } });
+ await Promise.all([...members.map((member) => Member.removeFromGuild(member.id, member.guild_id))]);
+ await UserSettingsProtos.delete({ user_id: req.params.user_id });
+ await User.delete({ id: req.params.user_id });
- // TODO: respect intents as USER_DELETE has potential to cause privacy issues
- await emitEvent({
- event: "USER_DELETE",
- user_id: req.user_id,
- data: { user_id: req.params.user_id },
- } as UserDeleteEvent);
+ // TODO: respect intents as USER_DELETE has potential to cause privacy issues
+ await emitEvent({
+ event: "USER_DELETE",
+ user_id: req.user_id,
+ data: { user_id: req.params.user_id },
+ } as UserDeleteEvent);
- console.log(`[Instance ban] Deleted user ${user.id} from instance in ${sw.elapsed().toString()}`);
- res.sendStatus(204);
- },
+ console.log(`[Instance ban] Deleted user ${user.id} from instance in ${sw.elapsed().toString()}`);
+ res.sendStatus(204);
+ },
);
export default router;
diff --git "a/src/api/routes/users/\043user_id/index.ts" "b/src/api/routes/users/\043user_id/index.ts"
index 417f961..7fca1e0 100644
--- "a/src/api/routes/users/\043user_id/index.ts"
+++ "b/src/api/routes/users/\043user_id/index.ts"
@@ -23,19 +23,19 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APIPublicUser",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { user_id } = req.params;
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APIPublicUser",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { user_id } = req.params;
- res.json(await User.getPublicUser(user_id));
- },
+ res.json(await User.getPublicUser(user_id));
+ },
);
export default router;
diff --git "a/src/api/routes/users/\043user_id/messages.ts" "b/src/api/routes/users/\043user_id/messages.ts"
index 717bca9..95c7cfc 100644
--- "a/src/api/routes/users/\043user_id/messages.ts"
+++ "b/src/api/routes/users/\043user_id/messages.ts"
@@ -23,33 +23,33 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "DmMessagesResponseSchema",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const user = await User.findOneOrFail({ where: { id: req.params.user_id } });
- const channel = await user.getDmChannelWith(req.user_id);
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "DmMessagesResponseSchema",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const user = await User.findOneOrFail({ where: { id: req.params.user_id } });
+ const channel = await user.getDmChannelWith(req.user_id);
- const messages = (
- await Message.find({
- where: { channel_id: channel?.id },
- order: { timestamp: "DESC" },
- take: Math.min(Math.max(req.query.limit ? Number(req.query.limit) : 50, 1), Config.get().limits.message.maxPreloadCount),
- })
- ).filter((x) => x !== null) as Message[];
+ const messages = (
+ await Message.find({
+ where: { channel_id: channel?.id },
+ order: { timestamp: "DESC" },
+ take: Math.min(Math.max(req.query.limit ? Number(req.query.limit) : 50, 1), Config.get().limits.message.maxPreloadCount),
+ })
+ ).filter((x) => x !== null) as Message[];
- const filteredMessages = messages.map((message) => message.toPartialMessage()) as DmMessagesResponseSchema;
+ const filteredMessages = messages.map((message) => message.toPartialMessage()) as DmMessagesResponseSchema;
- return res.status(200).send(filteredMessages);
- },
+ return res.status(200).send(filteredMessages);
+ },
);
// TODO: POST to send a message to the user
diff --git "a/src/api/routes/users/\043user_id/profile.ts" "b/src/api/routes/users/\043user_id/profile.ts"
index a5ea3e9..bcd59cd 100644
--- "a/src/api/routes/users/\043user_id/profile.ts"
+++ "b/src/api/routes/users/\043user_id/profile.ts"
@@ -25,146 +25,146 @@
const router: Router = Router({ mergeParams: true });
router.get("/", route({ responses: { 200: { body: "UserProfileResponse" } } }), async (req: Request, res: Response) => {
- if (req.params.user_id === "@me") req.params.user_id = req.user_id;
+ if (req.params.user_id === "@me") req.params.user_id = req.user_id;
- const { guild_id, with_mutual_guilds, with_mutual_friends, with_mutual_friends_count } = req.query;
+ const { guild_id, with_mutual_guilds, with_mutual_friends, with_mutual_friends_count } = req.query;
- const user = await User.getPublicUser(req.params.user_id, {
- relations: ["connected_accounts"],
- });
+ const user = await User.getPublicUser(req.params.user_id, {
+ relations: ["connected_accounts"],
+ });
- const mutual_guilds: object[] = [];
- let premium_guild_since;
+ const mutual_guilds: object[] = [];
+ let premium_guild_since;
- if (with_mutual_guilds == "true") {
- const requested_member = await Member.find({
- where: { id: req.params.user_id },
- });
- const self_member = await Member.find({
- where: { id: req.user_id },
- });
+ if (with_mutual_guilds == "true") {
+ const requested_member = await Member.find({
+ where: { id: req.params.user_id },
+ });
+ const self_member = await Member.find({
+ where: { id: req.user_id },
+ });
- for (const rmem of requested_member) {
- if (rmem.premium_since) {
- if (premium_guild_since) {
- if (premium_guild_since > rmem.premium_since) {
- premium_guild_since = rmem.premium_since;
- }
- } else {
- premium_guild_since = rmem.premium_since;
- }
- }
- for (const smem of self_member) {
- if (smem.guild_id === rmem.guild_id) {
- mutual_guilds.push({
- id: rmem.guild_id,
- nick: rmem.nick,
- });
- }
- }
- }
- }
+ for (const rmem of requested_member) {
+ if (rmem.premium_since) {
+ if (premium_guild_since) {
+ if (premium_guild_since > rmem.premium_since) {
+ premium_guild_since = rmem.premium_since;
+ }
+ } else {
+ premium_guild_since = rmem.premium_since;
+ }
+ }
+ for (const smem of self_member) {
+ if (smem.guild_id === rmem.guild_id) {
+ mutual_guilds.push({
+ id: rmem.guild_id,
+ nick: rmem.nick,
+ });
+ }
+ }
+ }
+ }
- const guild_member =
- guild_id && typeof guild_id == "string"
- ? await Member.findOneOrFail({
- where: { id: req.params.user_id, guild_id: guild_id },
- relations: ["roles"],
- })
- : undefined;
+ const guild_member =
+ guild_id && typeof guild_id == "string"
+ ? await Member.findOneOrFail({
+ where: { id: req.params.user_id, guild_id: guild_id },
+ relations: ["roles"],
+ })
+ : undefined;
- // TODO: make proper DTO's in util?
+ // TODO: make proper DTO's in util?
- const userProfile = {
- bio: req.user_bot ? null : user.bio,
- accent_color: user.accent_color,
- banner: user.banner,
- pronouns: user.pronouns,
- theme_colors: user.theme_colors?.map((t) => Number(t)), // these are strings for some reason, they should be numbers
- };
+ const userProfile = {
+ bio: req.user_bot ? null : user.bio,
+ accent_color: user.accent_color,
+ banner: user.banner,
+ pronouns: user.pronouns,
+ theme_colors: user.theme_colors?.map((t) => Number(t)), // these are strings for some reason, they should be numbers
+ };
- const guildMemberProfile = {
- accent_color: null,
- banner: guild_member?.banner || null,
- bio: guild_member?.bio || "",
- guild_id,
- };
+ const guildMemberProfile = {
+ accent_color: null,
+ banner: guild_member?.banner || null,
+ bio: guild_member?.bio || "",
+ guild_id,
+ };
- const badges = await Badge.find();
+ const badges = await Badge.find();
- let mutual_friends: PublicUser[] = [];
- let mutual_friends_count = 0;
+ let mutual_friends: PublicUser[] = [];
+ let mutual_friends_count = 0;
- if (with_mutual_friends == "true" || with_mutual_friends_count == "true") {
- const relationshipsSelf = await Relationship.find({ where: { from_id: req.user_id, type: RelationshipType.friends } });
- const relationshipsUser = await Relationship.find({ where: { from_id: req.params.user_id, type: RelationshipType.friends } });
- const relationshipsIntersection = relationshipsSelf.filter((r1) => relationshipsUser.some((r2) => r2.to_id === r1.to_id));
- if (with_mutual_friends_count) mutual_friends_count = relationshipsIntersection.length;
- if (with_mutual_friends) {
- const users = await User.find({ where: { id: In(relationshipsIntersection.map((r) => r.to_id)) }, select: PublicUserProjection });
- mutual_friends = users.map((u) => u.toPublicUser());
- }
- }
+ if (with_mutual_friends == "true" || with_mutual_friends_count == "true") {
+ const relationshipsSelf = await Relationship.find({ where: { from_id: req.user_id, type: RelationshipType.friends } });
+ const relationshipsUser = await Relationship.find({ where: { from_id: req.params.user_id, type: RelationshipType.friends } });
+ const relationshipsIntersection = relationshipsSelf.filter((r1) => relationshipsUser.some((r2) => r2.to_id === r1.to_id));
+ if (with_mutual_friends_count) mutual_friends_count = relationshipsIntersection.length;
+ if (with_mutual_friends) {
+ const users = await User.find({ where: { id: In(relationshipsIntersection.map((r) => r.to_id)) }, select: PublicUserProjection });
+ mutual_friends = users.map((u) => u.toPublicUser());
+ }
+ }
- res.json({
- connected_accounts: user.connected_accounts.filter((x) => x.visibility != 0),
- premium_guild_since: premium_guild_since, // TODO
- premium_since: user.premium_since, // TODO
- mutual_guilds: with_mutual_guilds ? mutual_guilds : undefined, // TODO {id: "", nick: null} when ?with_mutual_guilds=true
- mutual_friends: with_mutual_friends ? mutual_friends : undefined,
- mutual_friends_count: with_mutual_friends_count ? mutual_friends_count : undefined,
- user: user.toPublicUser(),
- premium_type: user.premium_type,
- profile_themes_experiment_bucket: 4, // TODO: This doesn't make it available, for some reason?
- user_profile: userProfile,
- guild_member: { ...guild_member?.toPublicMember(), user: user.toPublicUser() },
- guild_member_profile: guild_id && guildMemberProfile,
- badges: badges.filter((x) => user.badge_ids?.includes(x.id)),
- });
+ res.json({
+ connected_accounts: user.connected_accounts.filter((x) => x.visibility != 0),
+ premium_guild_since: premium_guild_since, // TODO
+ premium_since: user.premium_since, // TODO
+ mutual_guilds: with_mutual_guilds ? mutual_guilds : undefined, // TODO {id: "", nick: null} when ?with_mutual_guilds=true
+ mutual_friends: with_mutual_friends ? mutual_friends : undefined,
+ mutual_friends_count: with_mutual_friends_count ? mutual_friends_count : undefined,
+ user: user.toPublicUser(),
+ premium_type: user.premium_type,
+ profile_themes_experiment_bucket: 4, // TODO: This doesn't make it available, for some reason?
+ user_profile: userProfile,
+ guild_member: { ...guild_member?.toPublicMember(), user: user.toPublicUser() },
+ guild_member_profile: guild_id && guildMemberProfile,
+ badges: badges.filter((x) => user.badge_ids?.includes(x.id)),
+ });
});
router.patch("/", route({ requestBody: "UserProfileModifySchema" }), async (req: Request, res: Response) => {
- const body = req.body as UserProfileModifySchema;
+ const body = req.body as UserProfileModifySchema;
- if (body.banner) body.banner = await handleFile(`/banners/${req.user_id}`, body.banner as string);
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- select: [...PrivateUserProjection, "data"],
- });
+ if (body.banner) body.banner = await handleFile(`/banners/${req.user_id}`, body.banner as string);
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ select: [...PrivateUserProjection, "data"],
+ });
- if (body.bio) {
- const { maxBio } = Config.get().limits.user;
- if (body.bio.length > maxBio) {
- throw FieldErrors({
- bio: {
- code: "BIO_INVALID",
- message: `Bio must be less than ${maxBio} in length`,
- },
- });
- }
- }
+ if (body.bio) {
+ const { maxBio } = Config.get().limits.user;
+ if (body.bio.length > maxBio) {
+ throw FieldErrors({
+ bio: {
+ code: "BIO_INVALID",
+ message: `Bio must be less than ${maxBio} in length`,
+ },
+ });
+ }
+ }
- user.assign(body);
- await user.save();
+ user.assign(body);
+ await user.save();
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- delete user.data;
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ delete user.data;
- // TODO: send update member list event in gateway
- await emitEvent({
- event: "USER_UPDATE",
- user_id: req.user_id,
- data: user,
- } as UserUpdateEvent);
+ // TODO: send update member list event in gateway
+ await emitEvent({
+ event: "USER_UPDATE",
+ user_id: req.user_id,
+ data: user,
+ } as UserUpdateEvent);
- res.json({
- accent_color: user.accent_color,
- bio: user.bio,
- banner: user.banner,
- theme_colors: user.theme_colors,
- pronouns: user.pronouns,
- });
+ res.json({
+ accent_color: user.accent_color,
+ bio: user.bio,
+ banner: user.banner,
+ theme_colors: user.theme_colors,
+ pronouns: user.pronouns,
+ });
});
export default router;
diff --git "a/src/api/routes/users/\043user_id/relationships.ts" "b/src/api/routes/users/\043user_id/relationships.ts"
index 7e33291..3272ef7 100644
--- "a/src/api/routes/users/\043user_id/relationships.ts"
+++ "b/src/api/routes/users/\043user_id/relationships.ts"
@@ -24,44 +24,44 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: { body: "UserRelationsResponse" },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const mutual_relations: UserRelationsResponse = [];
+ "/",
+ route({
+ responses: {
+ 200: { body: "UserRelationsResponse" },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const mutual_relations: UserRelationsResponse = [];
- const requested_relations = await User.findOneOrFail({
- where: { id: req.params.user_id },
- relations: ["relationships"],
- });
- const self_relations = await User.findOneOrFail({
- where: { id: req.user_id },
- relations: ["relationships"],
- });
+ const requested_relations = await User.findOneOrFail({
+ where: { id: req.params.user_id },
+ relations: ["relationships"],
+ });
+ const self_relations = await User.findOneOrFail({
+ where: { id: req.user_id },
+ relations: ["relationships"],
+ });
- for (const rmem of requested_relations.relationships) {
- for (const smem of self_relations.relationships)
- if (rmem.to_id === smem.to_id && rmem.type === 1 && rmem.to_id !== req.user_id) {
- const relation_user = await User.getPublicUser(rmem.to_id);
+ for (const rmem of requested_relations.relationships) {
+ for (const smem of self_relations.relationships)
+ if (rmem.to_id === smem.to_id && rmem.type === 1 && rmem.to_id !== req.user_id) {
+ const relation_user = await User.getPublicUser(rmem.to_id);
- mutual_relations.push({
- id: relation_user.id,
- username: relation_user.username,
- avatar: relation_user.avatar,
- discriminator: relation_user.discriminator,
- public_flags: relation_user.public_flags,
- });
- }
- }
+ mutual_relations.push({
+ id: relation_user.id,
+ username: relation_user.username,
+ avatar: relation_user.avatar,
+ discriminator: relation_user.discriminator,
+ public_flags: relation_user.public_flags,
+ });
+ }
+ }
- res.json(mutual_relations);
- },
+ res.json(mutual_relations);
+ },
);
export default router;
diff --git a/src/api/routes/users/@me/activities/statistics/applications.ts b/src/api/routes/users/@me/activities/statistics/applications.ts
index a9bc596..b011916 100644
--- a/src/api/routes/users/@me/activities/statistics/applications.ts
+++ b/src/api/routes/users/@me/activities/statistics/applications.ts
@@ -22,8 +22,8 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), (req: Request, res: Response) => {
- // TODO:
- res.json([]).status(200);
+ // TODO:
+ res.json([]).status(200);
});
export default router;
diff --git a/src/api/routes/users/@me/affinities/guilds.ts b/src/api/routes/users/@me/affinities/guilds.ts
index 30fe887..8de9aa5 100644
--- a/src/api/routes/users/@me/affinities/guilds.ts
+++ b/src/api/routes/users/@me/affinities/guilds.ts
@@ -22,8 +22,8 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), (req: Request, res: Response) => {
- // TODO:
- res.status(200).send({ guild_affinities: [] });
+ // TODO:
+ res.status(200).send({ guild_affinities: [] });
});
export default router;
diff --git a/src/api/routes/users/@me/affinities/users.ts b/src/api/routes/users/@me/affinities/users.ts
index 038f410..2f66625 100644
--- a/src/api/routes/users/@me/affinities/users.ts
+++ b/src/api/routes/users/@me/affinities/users.ts
@@ -22,8 +22,8 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), (req: Request, res: Response) => {
- // TODO:
- res.status(200).send({ user_affinities: [], inverse_user_affinities: [] });
+ // TODO:
+ res.status(200).send({ user_affinities: [], inverse_user_affinities: [] });
});
export default router;
diff --git "a/src/api/routes/users/@me/applications/\043application_id/entitlements.ts" "b/src/api/routes/users/@me/applications/\043application_id/entitlements.ts"
index f1f9a29..e8e6f65 100644
--- "a/src/api/routes/users/@me/applications/\043application_id/entitlements.ts"
+++ "b/src/api/routes/users/@me/applications/\043application_id/entitlements.ts"
@@ -22,8 +22,8 @@
const router: Router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- //TODO
- res.json([]).status(200);
+ //TODO
+ res.json([]).status(200);
});
export default router;
diff --git a/src/api/routes/users/@me/billing/country-code.ts b/src/api/routes/users/@me/billing/country-code.ts
index 1907536..8bddafc 100644
--- a/src/api/routes/users/@me/billing/country-code.ts
+++ b/src/api/routes/users/@me/billing/country-code.ts
@@ -22,8 +22,8 @@
const router: Router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- //TODO
- res.json({ country_code: "US" }).status(200);
+ //TODO
+ res.json({ country_code: "US" }).status(200);
});
export default router;
diff --git a/src/api/routes/users/@me/billing/location-info.ts b/src/api/routes/users/@me/billing/location-info.ts
index 3fe7f67..918ea91 100644
--- a/src/api/routes/users/@me/billing/location-info.ts
+++ b/src/api/routes/users/@me/billing/location-info.ts
@@ -22,9 +22,9 @@
const router: Router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- //TODO
- // TODO: subdivision_code (optional)
- res.json({ country_code: "US" }).status(200);
+ //TODO
+ // TODO: subdivision_code (optional)
+ res.json({ country_code: "US" }).status(200);
});
export default router;
diff --git a/src/api/routes/users/@me/billing/payment-sources.ts b/src/api/routes/users/@me/billing/payment-sources.ts
index c2ebd3f..1380ed5 100644
--- a/src/api/routes/users/@me/billing/payment-sources.ts
+++ b/src/api/routes/users/@me/billing/payment-sources.ts
@@ -23,59 +23,59 @@
// https://docs.discord.food/resources/billing#example-payment-source
const example = {
- id: "1422548914485198869",
- type: 1,
- invalid: false,
- flags: 2,
- deleted_at: null,
- brand: "visa",
- last_4: "4242",
- expires_month: 9,
- expires_year: 2077,
- billing_address: {
- name: "John Doe",
- line_1: "123 Main Street",
- line_2: "Apt 4B",
- city: "San Francisco",
- state: "CA",
- country: "US",
- postal_code: "94105",
- },
- country: "US",
- payment_gateway: 1,
- payment_gateway_source_id: "pm_DwiVlGlYwe1qxLzy4QWChQeo",
- default: false,
+ id: "1422548914485198869",
+ type: 1,
+ invalid: false,
+ flags: 2,
+ deleted_at: null,
+ brand: "visa",
+ last_4: "4242",
+ expires_month: 9,
+ expires_year: 2077,
+ billing_address: {
+ name: "John Doe",
+ line_1: "123 Main Street",
+ line_2: "Apt 4B",
+ city: "San Francisco",
+ state: "CA",
+ country: "US",
+ postal_code: "94105",
+ },
+ country: "US",
+ payment_gateway: 1,
+ payment_gateway_source_id: "pm_DwiVlGlYwe1qxLzy4QWChQeo",
+ default: false,
};
router.get("/", route({}), (req: Request, res: Response) => {
- // TODO: schema
- res.json([example]).status(200);
+ // TODO: schema
+ res.json([example]).status(200);
});
router.post("/", route({}), (req: Request, res: Response) => {
- // TODO: schema
- res.json([example]).status(200);
+ // TODO: schema
+ res.json([example]).status(200);
});
router.get("/:payment_source_id", route({}), (req: Request, res: Response) => {
- // TODO: schema
- res.json({
- ...example,
- id: req.route.payment_source_id,
- }).status(200);
+ // TODO: schema
+ res.json({
+ ...example,
+ id: req.route.payment_source_id,
+ }).status(200);
});
router.patch("/:payment_source_id", route({}), (req: Request, res: Response) => {
- // TODO: schema
- res.json({
- ...example,
- id: req.route.payment_source_id,
- }).status(200);
+ // TODO: schema
+ res.json({
+ ...example,
+ id: req.route.payment_source_id,
+ }).status(200);
});
router.delete("/:payment_source_id", route({}), (req: Request, res: Response) => {
- // TODO: schema
- res.status(204);
+ // TODO: schema
+ res.status(204);
});
export default router;
diff --git a/src/api/routes/users/@me/billing/subscriptions.ts b/src/api/routes/users/@me/billing/subscriptions.ts
index f1f9a29..e8e6f65 100644
--- a/src/api/routes/users/@me/billing/subscriptions.ts
+++ b/src/api/routes/users/@me/billing/subscriptions.ts
@@ -22,8 +22,8 @@
const router: Router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- //TODO
- res.json([]).status(200);
+ //TODO
+ res.json([]).status(200);
});
export default router;
diff --git a/src/api/routes/users/@me/channels.ts b/src/api/routes/users/@me/channels.ts
index 9411e72..e13b874 100644
--- a/src/api/routes/users/@me/channels.ts
+++ b/src/api/routes/users/@me/channels.ts
@@ -24,37 +24,37 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APIDMChannelArray",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const recipients = await Recipient.find({
- where: { user_id: req.user_id, closed: false },
- relations: ["channel", "channel.recipients"],
- });
- res.json(await Promise.all(recipients.map((r) => DmChannelDTO.from(r.channel, [req.user_id]))));
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APIDMChannelArray",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const recipients = await Recipient.find({
+ where: { user_id: req.user_id, closed: false },
+ relations: ["channel", "channel.recipients"],
+ });
+ res.json(await Promise.all(recipients.map((r) => DmChannelDTO.from(r.channel, [req.user_id]))));
+ },
);
router.post(
- "/",
- route({
- requestBody: "DmChannelCreateSchema",
- responses: {
- 200: {
- body: "DmChannelDTO",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as DmChannelCreateSchema;
- res.json(await Channel.createDMChannel(body.recipients, req.user_id, body.name));
- },
+ "/",
+ route({
+ requestBody: "DmChannelCreateSchema",
+ responses: {
+ 200: {
+ body: "DmChannelDTO",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as DmChannelCreateSchema;
+ res.json(await Channel.createDMChannel(body.recipients, req.user_id, body.name));
+ },
);
export default router;
diff --git a/src/api/routes/users/@me/collectibles-marketing.ts b/src/api/routes/users/@me/collectibles-marketing.ts
index c9f1a1d..a043a14 100644
--- a/src/api/routes/users/@me/collectibles-marketing.ts
+++ b/src/api/routes/users/@me/collectibles-marketing.ts
@@ -24,26 +24,26 @@
// Unsure what this endpoint does, it seems to only affect the visual style of the shop tab in home
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "CollectiblesMarketingResponse",
- },
- 204: {},
- 401: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- res.send({
- marketings: {},
- } as CollectiblesMarketingResponse);
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "CollectiblesMarketingResponse",
+ },
+ 204: {},
+ 401: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ res.send({
+ marketings: {},
+ } as CollectiblesMarketingResponse);
+ },
);
export default router;
diff --git a/src/api/routes/users/@me/collectibles-purchases.ts b/src/api/routes/users/@me/collectibles-purchases.ts
index 9491e30..1e6a08d 100644
--- a/src/api/routes/users/@me/collectibles-purchases.ts
+++ b/src/api/routes/users/@me/collectibles-purchases.ts
@@ -23,24 +23,24 @@
// Unsure what this endpoint does, it seems to only affect the visual style of the shop tab in home
router.get(
- "/",
- route({
- responses: {
- 200: {
- // body: "CollectiblesPurchasesResponse",
- },
- 204: {},
- 401: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- res.send([]);
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ // body: "CollectiblesPurchasesResponse",
+ },
+ 204: {},
+ 401: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ res.send([]);
+ },
);
export default router;
diff --git "a/src/api/routes/users/@me/connections/\043connection_name/\043connection_id/access-token.ts" "b/src/api/routes/users/@me/connections/\043connection_name/\043connection_id/access-token.ts"
index fcab432..8846efe 100644
--- "a/src/api/routes/users/@me/connections/\043connection_name/\043connection_id/access-token.ts"
+++ "b/src/api/routes/users/@me/connections/\043connection_name/\043connection_id/access-token.ts"
@@ -28,49 +28,49 @@
// NOTE: this route has not been extensively tested, as the required connections are not implemented as of writing
router.get("/", route({}), async (req: Request, res: Response) => {
- const { connection_name, connection_id } = req.params;
+ const { connection_name, connection_id } = req.params;
- const connection = ConnectionStore.connections.get(connection_name);
+ const connection = ConnectionStore.connections.get(connection_name);
- if (!ALLOWED_CONNECTIONS.includes(connection_name) || !connection)
- throw FieldErrors({
- provider_id: {
- code: "BASE_TYPE_CHOICES",
- message: req.t("common:field.BASE_TYPE_CHOICES", {
- types: ALLOWED_CONNECTIONS.join(", "),
- }),
- },
- });
+ if (!ALLOWED_CONNECTIONS.includes(connection_name) || !connection)
+ throw FieldErrors({
+ provider_id: {
+ code: "BASE_TYPE_CHOICES",
+ message: req.t("common:field.BASE_TYPE_CHOICES", {
+ types: ALLOWED_CONNECTIONS.join(", "),
+ }),
+ },
+ });
- if (!connection.settings.enabled)
- throw FieldErrors({
- provider_id: {
- message: "This connection has been disabled server-side.",
- },
- });
+ if (!connection.settings.enabled)
+ throw FieldErrors({
+ provider_id: {
+ message: "This connection has been disabled server-side.",
+ },
+ });
- const connectedAccount = await ConnectedAccount.findOne({
- where: {
- type: connection_name,
- external_id: connection_id,
- user_id: req.user_id,
- },
- select: ["external_id", "type", "name", "verified", "visibility", "show_activity", "revoked", "token_data", "friend_sync", "integrations"],
- });
- if (!connectedAccount) throw DiscordApiErrors.UNKNOWN_CONNECTION;
- if (connectedAccount.revoked) throw DiscordApiErrors.CONNECTION_REVOKED;
- if (!connectedAccount.token_data) throw new ApiError("No token data", 0, 400);
+ const connectedAccount = await ConnectedAccount.findOne({
+ where: {
+ type: connection_name,
+ external_id: connection_id,
+ user_id: req.user_id,
+ },
+ select: ["external_id", "type", "name", "verified", "visibility", "show_activity", "revoked", "token_data", "friend_sync", "integrations"],
+ });
+ if (!connectedAccount) throw DiscordApiErrors.UNKNOWN_CONNECTION;
+ if (connectedAccount.revoked) throw DiscordApiErrors.CONNECTION_REVOKED;
+ if (!connectedAccount.token_data) throw new ApiError("No token data", 0, 400);
- let access_token = connectedAccount.token_data.access_token;
- const { expires_at, expires_in, fetched_at } = connectedAccount.token_data;
+ let access_token = connectedAccount.token_data.access_token;
+ const { expires_at, expires_in, fetched_at } = connectedAccount.token_data;
- if ((expires_at && expires_at < Date.now()) || (expires_in && fetched_at + expires_in * 1000 < Date.now())) {
- if (!(connection instanceof RefreshableConnection)) throw new ApiError("Access token expired", 0, 400);
- const tokenData = await connection.refresh(connectedAccount);
- access_token = tokenData.access_token;
- }
+ if ((expires_at && expires_at < Date.now()) || (expires_in && fetched_at + expires_in * 1000 < Date.now())) {
+ if (!(connection instanceof RefreshableConnection)) throw new ApiError("Access token expired", 0, 400);
+ const tokenData = await connection.refresh(connectedAccount);
+ access_token = tokenData.access_token;
+ }
- res.json({ access_token });
+ res.json({ access_token });
});
export default router;
diff --git "a/src/api/routes/users/@me/connections/\043connection_name/\043connection_id/index.ts" "b/src/api/routes/users/@me/connections/\043connection_name/\043connection_id/index.ts"
index 37deee3..111312a 100644
--- "a/src/api/routes/users/@me/connections/\043connection_name/\043connection_id/index.ts"
+++ "b/src/api/routes/users/@me/connections/\043connection_name/\043connection_id/index.ts"
@@ -24,65 +24,65 @@
// TODO: connection update schema
router.patch("/", route({ requestBody: "ConnectionUpdateSchema" }), async (req: Request, res: Response) => {
- const { connection_name, connection_id } = req.params;
- const body = req.body as ConnectionUpdateSchema;
+ const { connection_name, connection_id } = req.params;
+ const body = req.body as ConnectionUpdateSchema;
- const connection = await ConnectedAccount.findOne({
- where: {
- user_id: req.user_id,
- external_id: connection_id,
- type: connection_name,
- },
- select: ["external_id", "type", "name", "verified", "visibility", "show_activity", "revoked", "friend_sync", "integrations"],
- });
+ const connection = await ConnectedAccount.findOne({
+ where: {
+ user_id: req.user_id,
+ external_id: connection_id,
+ type: connection_name,
+ },
+ select: ["external_id", "type", "name", "verified", "visibility", "show_activity", "revoked", "friend_sync", "integrations"],
+ });
- if (!connection) return DiscordApiErrors.UNKNOWN_CONNECTION;
- // TODO: do we need to do anything if the connection is revoked?
+ if (!connection) return DiscordApiErrors.UNKNOWN_CONNECTION;
+ // TODO: do we need to do anything if the connection is revoked?
- if (typeof body.visibility === "boolean")
- //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number?
- body.visibility = body.visibility ? 1 : 0;
- if (typeof body.show_activity === "boolean")
- //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number?
- body.show_activity = body.show_activity ? 1 : 0;
- if (typeof body.metadata_visibility === "boolean")
- //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number?
- body.metadata_visibility = body.metadata_visibility ? 1 : 0;
+ if (typeof body.visibility === "boolean")
+ //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number?
+ body.visibility = body.visibility ? 1 : 0;
+ if (typeof body.show_activity === "boolean")
+ //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number?
+ body.show_activity = body.show_activity ? 1 : 0;
+ if (typeof body.metadata_visibility === "boolean")
+ //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number?
+ body.metadata_visibility = body.metadata_visibility ? 1 : 0;
- connection.assign(req.body);
+ connection.assign(req.body);
- await ConnectedAccount.update(
- {
- user_id: req.user_id,
- external_id: connection_id,
- type: connection_name,
- },
- connection,
- );
- res.json(connection.toJSON());
+ await ConnectedAccount.update(
+ {
+ user_id: req.user_id,
+ external_id: connection_id,
+ type: connection_name,
+ },
+ connection,
+ );
+ res.json(connection.toJSON());
});
router.delete("/", route({}), async (req: Request, res: Response) => {
- const { connection_name, connection_id } = req.params;
+ const { connection_name, connection_id } = req.params;
- const account = await ConnectedAccount.findOneOrFail({
- where: {
- user_id: req.user_id,
- external_id: connection_id,
- type: connection_name,
- },
- });
+ const account = await ConnectedAccount.findOneOrFail({
+ where: {
+ user_id: req.user_id,
+ external_id: connection_id,
+ type: connection_name,
+ },
+ });
- await Promise.all([
- ConnectedAccount.remove(account),
- emitEvent({
- event: "USER_CONNECTIONS_UPDATE",
- data: account,
- user_id: req.user_id,
- }),
- ]);
+ await Promise.all([
+ ConnectedAccount.remove(account),
+ emitEvent({
+ event: "USER_CONNECTIONS_UPDATE",
+ data: account,
+ user_id: req.user_id,
+ }),
+ ]);
- return res.sendStatus(200);
+ return res.sendStatus(200);
});
export default router;
diff --git a/src/api/routes/users/@me/connections/index.ts b/src/api/routes/users/@me/connections/index.ts
index 00625ee..a2d8b82 100644
--- a/src/api/routes/users/@me/connections/index.ts
+++ b/src/api/routes/users/@me/connections/index.ts
@@ -23,14 +23,14 @@
const router: Router = Router({ mergeParams: true });
router.get("/", route({}), async (req: Request, res: Response) => {
- const connections = await ConnectedAccount.find({
- where: {
- user_id: req.user_id,
- },
- select: ["external_id", "type", "name", "verified", "visibility", "show_activity", "revoked", "token_data", "friend_sync", "integrations"],
- });
+ const connections = await ConnectedAccount.find({
+ where: {
+ user_id: req.user_id,
+ },
+ select: ["external_id", "type", "name", "verified", "visibility", "show_activity", "revoked", "token_data", "friend_sync", "integrations"],
+ });
- res.json(connections.map((x) => new ConnectedAccountDTO(x, true)));
+ res.json(connections.map((x) => new ConnectedAccountDTO(x, true)));
});
export default router;
diff --git a/src/api/routes/users/@me/delete.ts b/src/api/routes/users/@me/delete.ts
index 4386118..668f7c1 100644
--- a/src/api/routes/users/@me/delete.ts
+++ b/src/api/routes/users/@me/delete.ts
@@ -25,44 +25,44 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- responses: {
- 204: {},
- 401: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- select: ["data"],
- }); //User object
- let correctpass = true;
+ "/",
+ route({
+ responses: {
+ 204: {},
+ 401: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ select: ["data"],
+ }); //User object
+ let correctpass = true;
- if (user.data.hash) {
- // guest accounts can delete accounts without password
- correctpass = await bcrypt.compare(req.body.password, user.data.hash);
- if (!correctpass) {
- throw new HTTPError(req.t("auth:login.INVALID_PASSWORD"));
- }
- }
+ if (user.data.hash) {
+ // guest accounts can delete accounts without password
+ correctpass = await bcrypt.compare(req.body.password, user.data.hash);
+ if (!correctpass) {
+ throw new HTTPError(req.t("auth:login.INVALID_PASSWORD"));
+ }
+ }
- // TODO: decrement guild member count
+ // TODO: decrement guild member count
- if (correctpass) {
- const members = await Member.find({ where: { id: req.user_id } });
- await Promise.all([User.delete({ id: req.user_id }), ...members.map((member) => Member.removeFromGuild(member.id, member.guild_id))]);
+ if (correctpass) {
+ const members = await Member.find({ where: { id: req.user_id } });
+ await Promise.all([User.delete({ id: req.user_id }), ...members.map((member) => Member.removeFromGuild(member.id, member.guild_id))]);
- res.sendStatus(204);
- } else {
- res.sendStatus(401);
- }
- },
+ res.sendStatus(204);
+ } else {
+ res.sendStatus(401);
+ }
+ },
);
export default router;
diff --git a/src/api/routes/users/@me/devices.ts b/src/api/routes/users/@me/devices.ts
index 644302c..d320613 100644
--- a/src/api/routes/users/@me/devices.ts
+++ b/src/api/routes/users/@me/devices.ts
@@ -22,8 +22,8 @@
const router = Router({ mergeParams: true });
router.post("/", route({}), (req: Request, res: Response) => {
- // TODO:
- res.sendStatus(204);
+ // TODO:
+ res.sendStatus(204);
});
export default router;
diff --git a/src/api/routes/users/@me/disable.ts b/src/api/routes/users/@me/disable.ts
index 73de839..95995e4 100644
--- a/src/api/routes/users/@me/disable.ts
+++ b/src/api/routes/users/@me/disable.ts
@@ -24,41 +24,41 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- select: ["data"],
- }); //User object
- let correctpass = true;
+ "/",
+ route({
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ select: ["data"],
+ }); //User object
+ let correctpass = true;
- if (user.data.hash) {
- // guest accounts can delete accounts without password
- correctpass = await bcrypt.compare(req.body.password, user.data.hash); //Not sure if user typed right password :/
- }
+ if (user.data.hash) {
+ // guest accounts can delete accounts without password
+ correctpass = await bcrypt.compare(req.body.password, user.data.hash); //Not sure if user typed right password :/
+ }
- if (correctpass) {
- await User.update({ id: req.user_id }, { disabled: true });
+ if (correctpass) {
+ await User.update({ id: req.user_id }, { disabled: true });
- res.sendStatus(204);
- } else {
- res.status(400).json({
- message: "Password does not match",
- code: 50018,
- });
- }
- },
+ res.sendStatus(204);
+ } else {
+ res.status(400).json({
+ message: "Password does not match",
+ code: 50018,
+ });
+ }
+ },
);
export default router;
diff --git a/src/api/routes/users/@me/email-settings.ts b/src/api/routes/users/@me/email-settings.ts
index c557500..ede7353 100644
--- a/src/api/routes/users/@me/email-settings.ts
+++ b/src/api/routes/users/@me/email-settings.ts
@@ -22,17 +22,17 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), (req: Request, res: Response) => {
- // TODO:
- res.json({
- categories: {
- social: true,
- communication: true,
- tips: false,
- updates_and_announcements: false,
- recommendations_and_events: false,
- },
- initialized: false,
- }).status(200);
+ // TODO:
+ res.json({
+ categories: {
+ social: true,
+ communication: true,
+ tips: false,
+ updates_and_announcements: false,
+ recommendations_and_events: false,
+ },
+ initialized: false,
+ }).status(200);
});
export default router;
diff --git a/src/api/routes/users/@me/entitlements.ts b/src/api/routes/users/@me/entitlements.ts
index fd953ee..ac73a12 100644
--- a/src/api/routes/users/@me/entitlements.ts
+++ b/src/api/routes/users/@me/entitlements.ts
@@ -22,8 +22,8 @@
const router = Router({ mergeParams: true });
router.get("/gifts", route({}), (req: Request, res: Response) => {
- // TODO:
- res.json([]).status(200);
+ // TODO:
+ res.json([]).status(200);
});
export default router;
diff --git a/src/api/routes/users/@me/guilds.ts b/src/api/routes/users/@me/guilds.ts
index df71f46..c06c39c 100644
--- a/src/api/routes/users/@me/guilds.ts
+++ b/src/api/routes/users/@me/guilds.ts
@@ -24,62 +24,62 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APIGuildArray",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const members = await Member.find({
- relations: ["guild"],
- where: { id: req.user_id },
- });
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APIGuildArray",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const members = await Member.find({
+ relations: ["guild"],
+ where: { id: req.user_id },
+ });
- let guild = members.map((x) => x.guild);
+ let guild = members.map((x) => x.guild);
- if ("with_counts" in req.query && req.query.with_counts == "true") {
- guild = []; // TODO: Load guilds with user role permissions number
- }
+ if ("with_counts" in req.query && req.query.with_counts == "true") {
+ guild = []; // TODO: Load guilds with user role permissions number
+ }
- res.json(guild);
- },
+ res.json(guild);
+ },
);
// user send to leave a certain guild
router.delete(
- "/:guild_id",
- route({
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { autoJoin } = Config.get().guild;
- const { guild_id } = req.params;
- const guild = await Guild.findOneOrFail({
- where: { id: guild_id },
- select: ["owner_id"],
- });
+ "/:guild_id",
+ route({
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { autoJoin } = Config.get().guild;
+ const { guild_id } = req.params;
+ const guild = await Guild.findOneOrFail({
+ where: { id: guild_id },
+ select: ["owner_id"],
+ });
- if (!guild) throw new HTTPError("Guild doesn't exist", 404);
- if (guild.owner_id === req.user_id) throw new HTTPError("You can't leave your own guild", 400);
- if (autoJoin.enabled && autoJoin.guilds.includes(guild_id) && !autoJoin.canLeave) {
- throw new HTTPError("You can't leave instance auto join guilds", 400);
- }
+ if (!guild) throw new HTTPError("Guild doesn't exist", 404);
+ if (guild.owner_id === req.user_id) throw new HTTPError("You can't leave your own guild", 400);
+ if (autoJoin.enabled && autoJoin.guilds.includes(guild_id) && !autoJoin.canLeave) {
+ throw new HTTPError("You can't leave instance auto join guilds", 400);
+ }
- await Member.removeFromGuild(req.user_id, guild_id);
+ await Member.removeFromGuild(req.user_id, guild_id);
- return res.sendStatus(204);
- },
+ return res.sendStatus(204);
+ },
);
export default router;
diff --git "a/src/api/routes/users/@me/guilds/\043guild_id/settings.ts" "b/src/api/routes/users/@me/guilds/\043guild_id/settings.ts"
index 7fda9a9..16b64ec 100644
--- "a/src/api/routes/users/@me/guilds/\043guild_id/settings.ts"
+++ "b/src/api/routes/users/@me/guilds/\043guild_id/settings.ts"
@@ -25,54 +25,54 @@
// GET doesn't exist on discord.com
router.get(
- "/",
- route({
- responses: {
- 200: {},
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const user = await Member.findOneOrFail({
- where: { id: req.user_id, guild_id: req.params.guild_id },
- select: ["settings"],
- });
- return res.json(user.settings);
- },
+ "/",
+ route({
+ responses: {
+ 200: {},
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const user = await Member.findOneOrFail({
+ where: { id: req.user_id, guild_id: req.params.guild_id },
+ select: ["settings"],
+ });
+ return res.json(user.settings);
+ },
);
router.patch(
- "/",
- route({
- requestBody: "UserGuildSettingsSchema",
- responses: {
- 200: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as UserGuildSettingsSchema;
+ "/",
+ route({
+ requestBody: "UserGuildSettingsSchema",
+ responses: {
+ 200: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as UserGuildSettingsSchema;
- if (body.channel_overrides) {
- for (const channel in body.channel_overrides) {
- Channel.findOneOrFail({ where: { id: channel } });
- }
- }
+ if (body.channel_overrides) {
+ for (const channel in body.channel_overrides) {
+ Channel.findOneOrFail({ where: { id: channel } });
+ }
+ }
- const user = await Member.findOneOrFail({
- where: { id: req.user_id, guild_id: req.params.guild_id },
- select: ["settings"],
- });
- OrmUtils.mergeDeep(user.settings || {}, body);
- Member.update({ id: req.user_id, guild_id: req.params.guild_id }, user);
+ const user = await Member.findOneOrFail({
+ where: { id: req.user_id, guild_id: req.params.guild_id },
+ select: ["settings"],
+ });
+ OrmUtils.mergeDeep(user.settings || {}, body);
+ Member.update({ id: req.user_id, guild_id: req.params.guild_id }, user);
- res.json(user.settings);
- },
+ res.json(user.settings);
+ },
);
export default router;
diff --git a/src/api/routes/users/@me/guilds/premium/subscription-slots.ts b/src/api/routes/users/@me/guilds/premium/subscription-slots.ts
index a9bc596..b011916 100644
--- a/src/api/routes/users/@me/guilds/premium/subscription-slots.ts
+++ b/src/api/routes/users/@me/guilds/premium/subscription-slots.ts
@@ -22,8 +22,8 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), (req: Request, res: Response) => {
- // TODO:
- res.json([]).status(200);
+ // TODO:
+ res.json([]).status(200);
});
export default router;
diff --git a/src/api/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts
index aba9f92..bd1fa07 100644
--- a/src/api/routes/users/@me/index.ts
+++ b/src/api/routes/users/@me/index.ts
@@ -25,182 +25,182 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APIPrivateUser",
- },
- },
- }),
- async (req: Request, res: Response) => {
- res.json(
- await User.findOne({
- select: PrivateUserProjection,
- where: { id: req.user_id },
- }),
- );
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APIPrivateUser",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ res.json(
+ await User.findOne({
+ select: PrivateUserProjection,
+ where: { id: req.user_id },
+ }),
+ );
+ },
);
router.patch(
- "/",
- route({
- requestBody: "UserModifySchema",
- responses: {
- 200: {
- body: "UserUpdateResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as UserModifySchema;
+ "/",
+ route({
+ requestBody: "UserModifySchema",
+ responses: {
+ 200: {
+ body: "UserUpdateResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as UserModifySchema;
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- select: [...PrivateUserProjection, "data"],
- });
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ select: [...PrivateUserProjection, "data"],
+ });
- // Populated on password change
- let newToken: string | undefined;
+ // Populated on password change
+ let newToken: string | undefined;
- if (body.avatar) body.avatar = await handleFile(`/avatars/${req.user_id}`, body.avatar as string);
- if (body.banner) body.banner = await handleFile(`/banners/${req.user_id}`, body.banner as string);
+ if (body.avatar) body.avatar = await handleFile(`/avatars/${req.user_id}`, body.avatar as string);
+ if (body.banner) body.banner = await handleFile(`/banners/${req.user_id}`, body.banner as string);
- if (body.password) {
- if (user.data?.hash) {
- const same_password = await bcrypt.compare(body.password, user.data.hash || "");
- if (!same_password) {
- throw FieldErrors({
- password: {
- message: req.t("auth:login.INVALID_PASSWORD"),
- code: "INVALID_PASSWORD",
- },
- });
- }
- } else {
- user.data.hash = await bcrypt.hash(body.password, 12);
- }
- }
+ if (body.password) {
+ if (user.data?.hash) {
+ const same_password = await bcrypt.compare(body.password, user.data.hash || "");
+ if (!same_password) {
+ throw FieldErrors({
+ password: {
+ message: req.t("auth:login.INVALID_PASSWORD"),
+ code: "INVALID_PASSWORD",
+ },
+ });
+ }
+ } else {
+ user.data.hash = await bcrypt.hash(body.password, 12);
+ }
+ }
- if (body.email) {
- if (!body.email && Config.get().register.email.required)
- throw FieldErrors({
- email: {
- message: req.t("auth:register.EMAIL_INVALID"),
- code: "EMAIL_INVALID",
- },
- });
- if (!body.password)
- throw FieldErrors({
- password: {
- message: req.t("auth:login.INVALID_PASSWORD"),
- code: "INVALID_PASSWORD",
- },
- });
- }
+ if (body.email) {
+ if (!body.email && Config.get().register.email.required)
+ throw FieldErrors({
+ email: {
+ message: req.t("auth:register.EMAIL_INVALID"),
+ code: "EMAIL_INVALID",
+ },
+ });
+ if (!body.password)
+ throw FieldErrors({
+ password: {
+ message: req.t("auth:login.INVALID_PASSWORD"),
+ code: "INVALID_PASSWORD",
+ },
+ });
+ }
- if (body.new_password) {
- if (!body.password && user.email) {
- throw FieldErrors({
- password: {
- code: "BASE_TYPE_REQUIRED",
- message: req.t("common:field.BASE_TYPE_REQUIRED"),
- },
- });
- }
- user.data.hash = await bcrypt.hash(body.new_password, 12);
- user.data.valid_tokens_since = new Date();
- newToken = (await generateToken(user.id)) as string;
- }
+ if (body.new_password) {
+ if (!body.password && user.email) {
+ throw FieldErrors({
+ password: {
+ code: "BASE_TYPE_REQUIRED",
+ message: req.t("common:field.BASE_TYPE_REQUIRED"),
+ },
+ });
+ }
+ user.data.hash = await bcrypt.hash(body.new_password, 12);
+ user.data.valid_tokens_since = new Date();
+ newToken = (await generateToken(user.id)) as string;
+ }
- if (body.username) {
- const check_username = body?.username?.replace(/\s/g, "").trim();
- if (!check_username) {
- throw FieldErrors({
- username: {
- code: "BASE_TYPE_REQUIRED",
- message: req.t("common:field.BASE_TYPE_REQUIRED"),
- },
- });
- }
+ if (body.username) {
+ const check_username = body?.username?.replace(/\s/g, "").trim();
+ if (!check_username) {
+ throw FieldErrors({
+ username: {
+ code: "BASE_TYPE_REQUIRED",
+ message: req.t("common:field.BASE_TYPE_REQUIRED"),
+ },
+ });
+ }
- const { maxUsername } = Config.get().limits.user;
- if (check_username.length > maxUsername || check_username.length < 2) {
- throw FieldErrors({
- username: {
- code: "BASE_TYPE_BAD_LENGTH",
- message: `Must be between 2 and ${maxUsername} in length.`,
- },
- });
- }
+ const { maxUsername } = Config.get().limits.user;
+ if (check_username.length > maxUsername || check_username.length < 2) {
+ throw FieldErrors({
+ username: {
+ code: "BASE_TYPE_BAD_LENGTH",
+ message: `Must be between 2 and ${maxUsername} in length.`,
+ },
+ });
+ }
- if (!body.password) {
- throw FieldErrors({
- password: {
- message: req.t("auth:login.INVALID_PASSWORD"),
- code: "INVALID_PASSWORD",
- },
- });
- }
- }
+ if (!body.password) {
+ throw FieldErrors({
+ password: {
+ message: req.t("auth:login.INVALID_PASSWORD"),
+ code: "INVALID_PASSWORD",
+ },
+ });
+ }
+ }
- if (body.discriminator) {
- if (
- await User.findOne({
- where: {
- discriminator: body.discriminator,
- username: body.username || user.username,
- },
- })
- ) {
- throw FieldErrors({
- discriminator: {
- code: "INVALID_DISCRIMINATOR",
- message: "This discriminator is already in use.",
- },
- });
- }
- }
+ if (body.discriminator) {
+ if (
+ await User.findOne({
+ where: {
+ discriminator: body.discriminator,
+ username: body.username || user.username,
+ },
+ })
+ ) {
+ throw FieldErrors({
+ discriminator: {
+ code: "INVALID_DISCRIMINATOR",
+ message: "This discriminator is already in use.",
+ },
+ });
+ }
+ }
- if (body.bio) {
- const { maxBio } = Config.get().limits.user;
- if (body.bio.length > maxBio) {
- throw FieldErrors({
- bio: {
- code: "BIO_INVALID",
- message: `Bio must be less than ${maxBio} in length`,
- },
- });
- }
- }
+ if (body.bio) {
+ const { maxBio } = Config.get().limits.user;
+ if (body.bio.length > maxBio) {
+ throw FieldErrors({
+ bio: {
+ code: "BIO_INVALID",
+ message: `Bio must be less than ${maxBio} in length`,
+ },
+ });
+ }
+ }
- user.assign(body);
- user.validate();
- await user.save();
+ user.assign(body);
+ user.validate();
+ await user.save();
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- //@ts-ignore
- delete user.data;
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ //@ts-ignore
+ delete user.data;
- // TODO: send update member list event in gateway
- await emitEvent({
- event: "USER_UPDATE",
- user_id: req.user_id,
- data: user,
- } as UserUpdateEvent);
+ // TODO: send update member list event in gateway
+ await emitEvent({
+ event: "USER_UPDATE",
+ user_id: req.user_id,
+ data: user,
+ } as UserUpdateEvent);
- res.json({
- ...user,
- newToken,
- });
- },
+ res.json({
+ ...user,
+ newToken,
+ });
+ },
);
export default router;
diff --git a/src/api/routes/users/@me/library.ts b/src/api/routes/users/@me/library.ts
index 845cd17..8d09b38 100644
--- a/src/api/routes/users/@me/library.ts
+++ b/src/api/routes/users/@me/library.ts
@@ -22,8 +22,8 @@
const router = Router({ mergeParams: true });
router.get("/", route({}), (req: Request, res: Response) => {
- // TODO:
- res.status(200).send([]);
+ // TODO:
+ res.status(200).send([]);
});
export default router;
diff --git a/src/api/routes/users/@me/mentions.ts b/src/api/routes/users/@me/mentions.ts
index 37a7abe..2d631e9 100644
--- a/src/api/routes/users/@me/mentions.ts
+++ b/src/api/routes/users/@me/mentions.ts
@@ -24,139 +24,139 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "",
- route({
- responses: {
- 200: {
- body: "MessageListResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- // AFAICT this endpoint doesn't list DMs
- async (req: Request, res: Response) => {
- const limit = req.query.limit && !isNaN(Number(req.query.limit)) ? Number(req.query.limit) : 25;
- const everyone = req.query.everyone !== undefined ? Boolean(req.query.everyone) : true;
- const roles = req.query.roles !== undefined ? Boolean(req.query.roles) : true;
- const before = req.query.before !== undefined ? String(req.query.before as string) : undefined;
- const guild_id = req.query.guild_id !== undefined ? req.query.guild_id : undefined;
+ "",
+ route({
+ responses: {
+ 200: {
+ body: "MessageListResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ // AFAICT this endpoint doesn't list DMs
+ async (req: Request, res: Response) => {
+ const limit = req.query.limit && !isNaN(Number(req.query.limit)) ? Number(req.query.limit) : 25;
+ const everyone = req.query.everyone !== undefined ? Boolean(req.query.everyone) : true;
+ const roles = req.query.roles !== undefined ? Boolean(req.query.roles) : true;
+ const before = req.query.before !== undefined ? String(req.query.before as string) : undefined;
+ const guild_id = req.query.guild_id !== undefined ? req.query.guild_id : undefined;
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- });
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ });
- const memberships = await Member.find({
- where: { id: req.user_id, ...(guild_id === undefined ? {} : { guild_id: String(guild_id) }) },
- select: {
- guild_id: true,
- id: true,
- communication_disabled_until: true,
- roles: {
- // We don't want to include all guild roles, as this could cause a lot more explosive behavior
- id: true,
- position: true,
- permissions: true,
- mentionable: true, // cause we can skip querying for unmentionable roles
- },
- guild: {
- id: true,
- owner_id: true,
- },
- },
- relations: ["guild", "roles"],
- });
+ const memberships = await Member.find({
+ where: { id: req.user_id, ...(guild_id === undefined ? {} : { guild_id: String(guild_id) }) },
+ select: {
+ guild_id: true,
+ id: true,
+ communication_disabled_until: true,
+ roles: {
+ // We don't want to include all guild roles, as this could cause a lot more explosive behavior
+ id: true,
+ position: true,
+ permissions: true,
+ mentionable: true, // cause we can skip querying for unmentionable roles
+ },
+ guild: {
+ id: true,
+ owner_id: true,
+ },
+ },
+ relations: ["guild", "roles"],
+ });
- const channels = await Channel.find({
- where: {
- guild_id: In(memberships.map((m) => m.guild_id)),
- },
- select: { id: true, guild_id: true, permission_overwrites: true },
- });
+ const channels = await Channel.find({
+ where: {
+ guild_id: In(memberships.map((m) => m.guild_id)),
+ },
+ select: { id: true, guild_id: true, permission_overwrites: true },
+ });
- const visibleChannels = channels.filter((c) => {
- const member = memberships.find((m) => m.guild_id === c.guild_id)!;
- return Permissions.finalPermission({
- user: { id: member.id, roles: member.roles.map((r) => r.id), communication_disabled_until: member.communication_disabled_until, flags: 0 },
- guild: { id: member.guild.id, owner_id: member.guild.owner_id!, roles: member.roles },
- channel: c,
- }).has("VIEW_CHANNEL");
- });
+ const visibleChannels = channels.filter((c) => {
+ const member = memberships.find((m) => m.guild_id === c.guild_id)!;
+ return Permissions.finalPermission({
+ user: { id: member.id, roles: member.roles.map((r) => r.id), communication_disabled_until: member.communication_disabled_until, flags: 0 },
+ guild: { id: member.guild.id, owner_id: member.guild.owner_id!, roles: member.roles },
+ channel: c,
+ }).has("VIEW_CHANNEL");
+ });
- const visibleChannelIds = visibleChannels.map((c) => c.id);
- const ownedMentionableRoleIds = memberships.reduce((acc, m) => {
- acc.push(...m.roles.filter((r) => r.mentionable).map((r) => r.id));
- return acc;
- }, [] as Snowflake[]);
+ const visibleChannelIds = visibleChannels.map((c) => c.id);
+ const ownedMentionableRoleIds = memberships.reduce((acc, m) => {
+ acc.push(...m.roles.filter((r) => r.mentionable).map((r) => r.id));
+ return acc;
+ }, [] as Snowflake[]);
- const whereQuery: FindOptionsWhere[] = [
- {
- channel_id: In(visibleChannelIds),
- mentions: { id: user.id },
- id: before ? LessThan(before) : undefined,
- },
- ];
- if (everyone) {
- whereQuery.push({
- channel_id: In(visibleChannelIds),
- mention_everyone: true,
- id: before ? LessThan(before) : undefined,
- });
- }
- if (roles) {
- whereQuery.push({
- channel_id: In(visibleChannelIds),
- mention_roles: { id: In(ownedMentionableRoleIds) },
- id: before ? LessThan(before) : undefined,
- });
- }
+ const whereQuery: FindOptionsWhere[] = [
+ {
+ channel_id: In(visibleChannelIds),
+ mentions: { id: user.id },
+ id: before ? LessThan(before) : undefined,
+ },
+ ];
+ if (everyone) {
+ whereQuery.push({
+ channel_id: In(visibleChannelIds),
+ mention_everyone: true,
+ id: before ? LessThan(before) : undefined,
+ });
+ }
+ if (roles) {
+ whereQuery.push({
+ channel_id: In(visibleChannelIds),
+ mention_roles: { id: In(ownedMentionableRoleIds) },
+ id: before ? LessThan(before) : undefined,
+ });
+ }
- const sw = Stopwatch.startNew();
- const finalMessages = (
- await Message.find({
- where: whereQuery,
- order: { timestamp: "DESC" },
- relations: [
- "author",
- "webhook",
- "application",
- "mentions",
- "mention_roles",
- "mention_channels",
- "sticker_items",
- "attachments",
- "referenced_message",
- "referenced_message.author",
- "referenced_message.webhook",
- "referenced_message.application",
- "referenced_message.mentions",
- "referenced_message.mention_roles",
- "referenced_message.mention_channels",
- "referenced_message.sticker_items",
- "referenced_message.attachments",
- ],
- take: limit,
- })
- ).map((m) => {
- return {
- ...m.toJSON(),
- attachments: m.attachments?.map((attachment: Attachment) =>
- Attachment.prototype.signUrls.call(
- attachment,
- new NewUrlUserSignatureData({
- ip: req.ip,
- userAgent: req.headers["user-agent"] as string,
- }),
- ),
- ),
- };
- });
+ const sw = Stopwatch.startNew();
+ const finalMessages = (
+ await Message.find({
+ where: whereQuery,
+ order: { timestamp: "DESC" },
+ relations: [
+ "author",
+ "webhook",
+ "application",
+ "mentions",
+ "mention_roles",
+ "mention_channels",
+ "sticker_items",
+ "attachments",
+ "referenced_message",
+ "referenced_message.author",
+ "referenced_message.webhook",
+ "referenced_message.application",
+ "referenced_message.mentions",
+ "referenced_message.mention_roles",
+ "referenced_message.mention_channels",
+ "referenced_message.sticker_items",
+ "referenced_message.attachments",
+ ],
+ take: limit,
+ })
+ ).map((m) => {
+ return {
+ ...m.toJSON(),
+ attachments: m.attachments?.map((attachment: Attachment) =>
+ Attachment.prototype.signUrls.call(
+ attachment,
+ new NewUrlUserSignatureData({
+ ip: req.ip,
+ userAgent: req.headers["user-agent"] as string,
+ }),
+ ),
+ ),
+ };
+ });
- console.log(`[Inbox/mentions] User ${user.id} fetched full message data for ${finalMessages.length} messages in ${sw.elapsed().totalMilliseconds}ms`);
+ console.log(`[Inbox/mentions] User ${user.id} fetched full message data for ${finalMessages.length} messages in ${sw.elapsed().totalMilliseconds}ms`);
- return res.json(finalMessages);
- },
+ return res.json(finalMessages);
+ },
);
export default router;
diff --git a/src/api/routes/users/@me/mfa/codes-verification.ts b/src/api/routes/users/@me/mfa/codes-verification.ts
index c8995d8..4cc4c07 100644
--- a/src/api/routes/users/@me/mfa/codes-verification.ts
+++ b/src/api/routes/users/@me/mfa/codes-verification.ts
@@ -24,52 +24,52 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "CodesVerificationSchema",
- responses: {
- 200: {
- body: "APIBackupCodeArray",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- // const { key, nonce, regenerate } = req.body as CodesVerificationSchema;
- const { regenerate } = req.body as CodesVerificationSchema;
+ "/",
+ route({
+ requestBody: "CodesVerificationSchema",
+ responses: {
+ 200: {
+ body: "APIBackupCodeArray",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ // const { key, nonce, regenerate } = req.body as CodesVerificationSchema;
+ const { regenerate } = req.body as CodesVerificationSchema;
- // TODO: We don't have email/etc etc, so can't send a verification code.
- // Once that's done, this route can verify `key`
+ // TODO: We don't have email/etc etc, so can't send a verification code.
+ // Once that's done, this route can verify `key`
- // const user = await User.findOneOrFail({ where: { id: req.user_id } });
- if ((await User.count({ where: { id: req.user_id } })) === 0) throw DiscordApiErrors.UNKNOWN_USER;
+ // const user = await User.findOneOrFail({ where: { id: req.user_id } });
+ if ((await User.count({ where: { id: req.user_id } })) === 0) throw DiscordApiErrors.UNKNOWN_USER;
- let codes: BackupCode[];
- if (regenerate) {
- await BackupCode.update({ user: { id: req.user_id } }, { expired: true });
+ let codes: BackupCode[];
+ if (regenerate) {
+ await BackupCode.update({ user: { id: req.user_id } }, { expired: true });
- codes = generateMfaBackupCodes(req.user_id);
- await Promise.all(codes.map((x) => x.save()));
- } else {
- codes = await BackupCode.find({
- where: {
- user: {
- id: req.user_id,
- },
- expired: false,
- },
- });
- }
+ codes = generateMfaBackupCodes(req.user_id);
+ await Promise.all(codes.map((x) => x.save()));
+ } else {
+ codes = await BackupCode.find({
+ where: {
+ user: {
+ id: req.user_id,
+ },
+ expired: false,
+ },
+ });
+ }
- return res.json({
- backup_codes: codes.map((x) => ({ ...x, expired: undefined })),
- });
- },
+ return res.json({
+ backup_codes: codes.map((x) => ({ ...x, expired: undefined })),
+ });
+ },
);
export default router;
diff --git a/src/api/routes/users/@me/mfa/codes.ts b/src/api/routes/users/@me/mfa/codes.ts
index 579a106..2eb1a3e 100644
--- a/src/api/routes/users/@me/mfa/codes.ts
+++ b/src/api/routes/users/@me/mfa/codes.ts
@@ -27,61 +27,61 @@
// TODO: This route is replaced with users/@me/mfa/codes-verification in newer clients
router.post(
- "/",
- route({
- requestBody: "MfaCodesSchema",
- deprecated: true,
- description: "This route is replaced with users/@me/mfa/codes-verification in newer clients",
- responses: {
- 200: {
- body: "APIBackupCodeArray",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { password, regenerate } = req.body as MfaCodesSchema;
+ "/",
+ route({
+ requestBody: "MfaCodesSchema",
+ deprecated: true,
+ description: "This route is replaced with users/@me/mfa/codes-verification in newer clients",
+ responses: {
+ 200: {
+ body: "APIBackupCodeArray",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { password, regenerate } = req.body as MfaCodesSchema;
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- select: ["data"],
- });
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ select: ["data"],
+ });
- if (!(await bcrypt.compare(password, user.data.hash || ""))) {
- throw FieldErrors({
- password: {
- message: req.t("auth:login.INVALID_PASSWORD"),
- code: "INVALID_PASSWORD",
- },
- });
- }
+ if (!(await bcrypt.compare(password, user.data.hash || ""))) {
+ throw FieldErrors({
+ password: {
+ message: req.t("auth:login.INVALID_PASSWORD"),
+ code: "INVALID_PASSWORD",
+ },
+ });
+ }
- let codes: BackupCode[];
- if (regenerate) {
- await BackupCode.update({ user: { id: req.user_id } }, { expired: true });
+ let codes: BackupCode[];
+ if (regenerate) {
+ await BackupCode.update({ user: { id: req.user_id } }, { expired: true });
- codes = generateMfaBackupCodes(req.user_id);
- await Promise.all(codes.map((x) => x.save()));
- } else {
- codes = await BackupCode.find({
- where: {
- user: {
- id: req.user_id,
- },
- expired: false,
- },
- });
- }
+ codes = generateMfaBackupCodes(req.user_id);
+ await Promise.all(codes.map((x) => x.save()));
+ } else {
+ codes = await BackupCode.find({
+ where: {
+ user: {
+ id: req.user_id,
+ },
+ expired: false,
+ },
+ });
+ }
- return res.json({
- backup_codes: codes.map((x) => ({ ...x, expired: undefined })),
- });
- },
+ return res.json({
+ backup_codes: codes.map((x) => ({ ...x, expired: undefined })),
+ });
+ },
);
export default router;
diff --git a/src/api/routes/users/@me/mfa/totp/disable.ts b/src/api/routes/users/@me/mfa/totp/disable.ts
index 003dcb7..11c927e 100644
--- a/src/api/routes/users/@me/mfa/totp/disable.ts
+++ b/src/api/routes/users/@me/mfa/totp/disable.ts
@@ -26,51 +26,51 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "TotpDisableSchema",
- responses: {
- 200: {
- body: "TokenOnlyResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as TotpDisableSchema;
+ "/",
+ route({
+ requestBody: "TotpDisableSchema",
+ responses: {
+ 200: {
+ body: "TokenOnlyResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as TotpDisableSchema;
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- select: ["totp_secret"],
- });
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ select: ["totp_secret"],
+ });
- const backup = await BackupCode.findOne({ where: { code: body.code } });
- if (!backup) {
- const ret = verifyToken(user.totp_secret || "", body.code);
- if (!ret || ret.delta != 0) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
- }
+ const backup = await BackupCode.findOne({ where: { code: body.code } });
+ if (!backup) {
+ const ret = verifyToken(user.totp_secret || "", body.code);
+ if (!ret || ret.delta != 0) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
+ }
- await User.update(
- { id: req.user_id },
- {
- mfa_enabled: false,
- totp_secret: "",
- },
- );
+ await User.update(
+ { id: req.user_id },
+ {
+ mfa_enabled: false,
+ totp_secret: "",
+ },
+ );
- await BackupCode.update(
- { user: { id: req.user_id } },
- {
- expired: true,
- },
- );
+ await BackupCode.update(
+ { user: { id: req.user_id } },
+ {
+ expired: true,
+ },
+ );
- return res.json({
- token: await generateToken(user.id),
- });
- },
+ return res.json({
+ token: await generateToken(user.id),
+ });
+ },
);
export default router;
diff --git a/src/api/routes/users/@me/mfa/totp/enable.ts b/src/api/routes/users/@me/mfa/totp/enable.ts
index f0563e3..a400c62 100644
--- a/src/api/routes/users/@me/mfa/totp/enable.ts
+++ b/src/api/routes/users/@me/mfa/totp/enable.ts
@@ -27,54 +27,54 @@
const router = Router({ mergeParams: true });
router.post(
- "/",
- route({
- requestBody: "TotpEnableSchema",
- responses: {
- 200: {
- body: "TokenWithBackupCodesResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as TotpEnableSchema;
+ "/",
+ route({
+ requestBody: "TotpEnableSchema",
+ responses: {
+ 200: {
+ body: "TokenWithBackupCodesResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as TotpEnableSchema;
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- select: ["data", "email"],
- });
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ select: ["data", "email"],
+ });
- // TODO: Are guests allowed to enable 2fa?
- if (user.data.hash) {
- if (!(await bcrypt.compare(body.password, user.data.hash))) {
- throw new HTTPError(req.t("auth:login.INVALID_PASSWORD"));
- }
- }
+ // TODO: Are guests allowed to enable 2fa?
+ if (user.data.hash) {
+ if (!(await bcrypt.compare(body.password, user.data.hash))) {
+ throw new HTTPError(req.t("auth:login.INVALID_PASSWORD"));
+ }
+ }
- if (!body.secret) throw new HTTPError(req.t("auth:login.INVALID_TOTP_SECRET"), 60005);
+ if (!body.secret) throw new HTTPError(req.t("auth:login.INVALID_TOTP_SECRET"), 60005);
- if (!body.code) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
+ if (!body.code) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
- if (verifyToken(body.secret, body.code)?.delta != 0) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
+ if (verifyToken(body.secret, body.code)?.delta != 0) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008);
- const backup_codes = generateMfaBackupCodes(req.user_id);
- await Promise.all(backup_codes.map((x) => x.save()));
- await User.update({ id: req.user_id }, { mfa_enabled: true, totp_secret: body.secret });
+ const backup_codes = generateMfaBackupCodes(req.user_id);
+ await Promise.all(backup_codes.map((x) => x.save()));
+ await User.update({ id: req.user_id }, { mfa_enabled: true, totp_secret: body.secret });
- res.send({
- token: await generateToken(user.id),
- backup_codes: backup_codes.map((x) => ({
- ...x,
- expired: undefined,
- })),
- });
- },
+ res.send({
+ token: await generateToken(user.id),
+ backup_codes: backup_codes.map((x) => ({
+ ...x,
+ expired: undefined,
+ })),
+ });
+ },
);
export default router;
diff --git "a/src/api/routes/users/@me/mfa/webauthn/credentials/\043key_id/index.ts" "b/src/api/routes/users/@me/mfa/webauthn/credentials/\043key_id/index.ts"
index 6dc0656..77180ca 100644
--- "a/src/api/routes/users/@me/mfa/webauthn/credentials/\043key_id/index.ts"
+++ "b/src/api/routes/users/@me/mfa/webauthn/credentials/\043key_id/index.ts"
@@ -22,29 +22,29 @@
const router = Router({ mergeParams: true });
router.delete(
- "/",
- route({
- responses: {
- 204: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { key_id } = req.params;
+ "/",
+ route({
+ responses: {
+ 204: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { key_id } = req.params;
- await SecurityKey.delete({
- id: key_id,
- user_id: req.user_id,
- });
+ await SecurityKey.delete({
+ id: key_id,
+ user_id: req.user_id,
+ });
- const keys = await SecurityKey.count({
- where: { user_id: req.user_id },
- });
+ const keys = await SecurityKey.count({
+ where: { user_id: req.user_id },
+ });
- // disable webauthn if there are no keys left
- if (keys === 0) await User.update({ id: req.user_id }, { webauthn_enabled: false });
+ // disable webauthn if there are no keys left
+ if (keys === 0) await User.update({ id: req.user_id }, { webauthn_enabled: false });
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
export default router;
diff --git a/src/api/routes/users/@me/mfa/webauthn/credentials/index.ts b/src/api/routes/users/@me/mfa/webauthn/credentials/index.ts
index 0c4b733..7bd29a5 100644
--- a/src/api/routes/users/@me/mfa/webauthn/credentials/index.ts
+++ b/src/api/routes/users/@me/mfa/webauthn/credentials/index.ts
@@ -26,138 +26,138 @@
const router = Router({ mergeParams: true });
const isGenerateSchema = (body: WebAuthnPostSchema): body is GenerateWebAuthnCredentialsSchema => {
- return "password" in body;
+ return "password" in body;
};
const isCreateSchema = (body: WebAuthnPostSchema): body is CreateWebAuthnCredentialSchema => {
- return "credential" in body;
+ return "credential" in body;
};
function toArrayBuffer(buf: Buffer) {
- const ab = new ArrayBuffer(buf.length);
- const view = new Uint8Array(ab);
- for (let i = 0; i < buf.length; ++i) {
- view[i] = buf[i];
- }
- return ab;
+ const ab = new ArrayBuffer(buf.length);
+ const view = new Uint8Array(ab);
+ for (let i = 0; i < buf.length; ++i) {
+ view[i] = buf[i];
+ }
+ return ab;
}
router.get("/", route({}), async (req: Request, res: Response) => {
- const securityKeys = await SecurityKey.find({
- where: {
- user_id: req.user_id,
- },
- });
+ const securityKeys = await SecurityKey.find({
+ where: {
+ user_id: req.user_id,
+ },
+ });
- return res.json(
- securityKeys.map((key) => ({
- id: key.id,
- name: key.name,
- })),
- );
+ return res.json(
+ securityKeys.map((key) => ({
+ id: key.id,
+ name: key.name,
+ })),
+ );
});
router.post(
- "/",
- route({
- requestBody: "WebAuthnPostSchema",
- responses: {
- 200: {
- body: "WebAuthnCreateResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- if (!WebAuthn.fido2) {
- // TODO: I did this for typescript and I can't use !
- throw new Error("WebAuthn not enabled");
- }
+ "/",
+ route({
+ requestBody: "WebAuthnPostSchema",
+ responses: {
+ 200: {
+ body: "WebAuthnCreateResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ if (!WebAuthn.fido2) {
+ // TODO: I did this for typescript and I can't use !
+ throw new Error("WebAuthn not enabled");
+ }
- const user = await User.findOneOrFail({
- where: {
- id: req.user_id,
- },
- select: ["data", "id", "disabled", "deleted", "totp_secret", "mfa_enabled", "username"],
- relations: ["settings"],
- });
+ const user = await User.findOneOrFail({
+ where: {
+ id: req.user_id,
+ },
+ select: ["data", "id", "disabled", "deleted", "totp_secret", "mfa_enabled", "username"],
+ relations: ["settings"],
+ });
- if (isGenerateSchema(req.body)) {
- const { password } = req.body;
- const same_password = await bcrypt.compare(password, user.data.hash || "");
- if (!same_password) {
- throw FieldErrors({
- password: {
- message: req.t("auth:login.INVALID_PASSWORD"),
- code: "INVALID_PASSWORD",
- },
- });
- }
+ if (isGenerateSchema(req.body)) {
+ const { password } = req.body;
+ const same_password = await bcrypt.compare(password, user.data.hash || "");
+ if (!same_password) {
+ throw FieldErrors({
+ password: {
+ message: req.t("auth:login.INVALID_PASSWORD"),
+ code: "INVALID_PASSWORD",
+ },
+ });
+ }
- const registrationOptions = await WebAuthn.fido2.attestationOptions();
- const challenge = JSON.stringify({
- publicKey: {
- ...registrationOptions,
- challenge: Buffer.from(registrationOptions.challenge).toString("base64"),
- user: {
- id: user.id,
- name: user.username,
- displayName: user.username,
- },
- },
- });
+ const registrationOptions = await WebAuthn.fido2.attestationOptions();
+ const challenge = JSON.stringify({
+ publicKey: {
+ ...registrationOptions,
+ challenge: Buffer.from(registrationOptions.challenge).toString("base64"),
+ user: {
+ id: user.id,
+ name: user.username,
+ displayName: user.username,
+ },
+ },
+ });
- const ticket = await generateWebAuthnTicket(challenge);
+ const ticket = await generateWebAuthnTicket(challenge);
- return res.json({
- ticket: ticket,
- challenge,
- });
- } else if (isCreateSchema(req.body)) {
- const { credential, name, ticket } = req.body;
+ return res.json({
+ ticket: ticket,
+ challenge,
+ });
+ } else if (isCreateSchema(req.body)) {
+ const { credential, name, ticket } = req.body;
- const verified = await verifyWebAuthnToken(ticket);
- if (!verified) throw new HTTPError("Invalid ticket", 400);
+ const verified = await verifyWebAuthnToken(ticket);
+ if (!verified) throw new HTTPError("Invalid ticket", 400);
- const clientAttestationResponse = JSON.parse(credential);
+ const clientAttestationResponse = JSON.parse(credential);
- if (!clientAttestationResponse.rawId) throw new HTTPError("Missing rawId", 400);
+ if (!clientAttestationResponse.rawId) throw new HTTPError("Missing rawId", 400);
- const rawIdBuffer = Buffer.from(clientAttestationResponse.rawId, "base64");
- clientAttestationResponse.rawId = toArrayBuffer(rawIdBuffer);
+ const rawIdBuffer = Buffer.from(clientAttestationResponse.rawId, "base64");
+ clientAttestationResponse.rawId = toArrayBuffer(rawIdBuffer);
- const attestationExpectations: ExpectedAttestationResult = JSON.parse(Buffer.from(clientAttestationResponse.response.clientDataJSON, "base64").toString());
+ const attestationExpectations: ExpectedAttestationResult = JSON.parse(Buffer.from(clientAttestationResponse.response.clientDataJSON, "base64").toString());
- const regResult = await WebAuthn.fido2.attestationResult(clientAttestationResponse, {
- ...attestationExpectations,
- factor: "second",
- });
+ const regResult = await WebAuthn.fido2.attestationResult(clientAttestationResponse, {
+ ...attestationExpectations,
+ factor: "second",
+ });
- const authnrData = regResult.authnrData;
- const keyId = Buffer.from(authnrData.get("credId")).toString("base64");
- const counter = authnrData.get("counter");
- const publicKey = authnrData.get("credentialPublicKeyPem");
+ const authnrData = regResult.authnrData;
+ const keyId = Buffer.from(authnrData.get("credId")).toString("base64");
+ const counter = authnrData.get("counter");
+ const publicKey = authnrData.get("credentialPublicKeyPem");
- const securityKey = SecurityKey.create({
- name,
- counter,
- public_key: publicKey,
- user_id: req.user_id,
- key_id: keyId,
- });
+ const securityKey = SecurityKey.create({
+ name,
+ counter,
+ public_key: publicKey,
+ user_id: req.user_id,
+ key_id: keyId,
+ });
- await Promise.all([securityKey.save(), User.update({ id: req.user_id }, { webauthn_enabled: true })]);
+ await Promise.all([securityKey.save(), User.update({ id: req.user_id }, { webauthn_enabled: true })]);
- return res.json({
- name,
- id: securityKey.id,
- });
- } else {
- throw DiscordApiErrors.INVALID_AUTHENTICATION_TOKEN;
- }
- },
+ return res.json({
+ name,
+ id: securityKey.id,
+ });
+ } else {
+ throw DiscordApiErrors.INVALID_AUTHENTICATION_TOKEN;
+ }
+ },
);
export default router;
diff --git a/src/api/routes/users/@me/notes.ts b/src/api/routes/users/@me/notes.ts
index 4969fa7..8cd3330 100644
--- a/src/api/routes/users/@me/notes.ts
+++ b/src/api/routes/users/@me/notes.ts
@@ -23,89 +23,89 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/:user_id",
- route({
- responses: {
- 200: {
- body: "UserNoteResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { user_id } = req.params;
+ "/:user_id",
+ route({
+ responses: {
+ 200: {
+ body: "UserNoteResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { user_id } = req.params;
- const note = await Note.findOneOrFail({
- where: {
- owner: { id: req.user_id },
- target: { id: user_id },
- },
- });
+ const note = await Note.findOneOrFail({
+ where: {
+ owner: { id: req.user_id },
+ target: { id: user_id },
+ },
+ });
- return res.json({
- note: note?.content,
- note_user_id: user_id,
- user_id: req.user_id,
- });
- },
+ return res.json({
+ note: note?.content,
+ note_user_id: user_id,
+ user_id: req.user_id,
+ });
+ },
);
router.put(
- "/:user_id",
- route({
- requestBody: "UserNoteUpdateSchema",
- responses: {
- 204: {},
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { user_id } = req.params;
- const owner = await User.findOneOrFail({ where: { id: req.user_id } });
- const target = await User.findOneOrFail({ where: { id: user_id } }); //if noted user does not exist throw
- const { note } = req.body;
+ "/:user_id",
+ route({
+ requestBody: "UserNoteUpdateSchema",
+ responses: {
+ 204: {},
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { user_id } = req.params;
+ const owner = await User.findOneOrFail({ where: { id: req.user_id } });
+ const target = await User.findOneOrFail({ where: { id: user_id } }); //if noted user does not exist throw
+ const { note } = req.body;
- if (note && note.length) {
- // upsert a note
- if (
- await Note.findOne({
- where: {
- owner: { id: owner.id },
- target: { id: target.id },
- },
- })
- ) {
- Note.update({ owner: { id: owner.id }, target: { id: target.id } }, { owner, target, content: note });
- } else {
- Note.insert({
- id: Snowflake.generate(),
- owner,
- target,
- content: note,
- });
- }
- } else {
- await Note.delete({
- owner: { id: owner.id },
- target: { id: target.id },
- });
- }
+ if (note && note.length) {
+ // upsert a note
+ if (
+ await Note.findOne({
+ where: {
+ owner: { id: owner.id },
+ target: { id: target.id },
+ },
+ })
+ ) {
+ Note.update({ owner: { id: owner.id }, target: { id: target.id } }, { owner, target, content: note });
+ } else {
+ Note.insert({
+ id: Snowflake.generate(),
+ owner,
+ target,
+ content: note,
+ });
+ }
+ } else {
+ await Note.delete({
+ owner: { id: owner.id },
+ target: { id: target.id },
+ });
+ }
- await emitEvent({
- event: "USER_NOTE_UPDATE",
- data: {
- note: note,
- id: target.id,
- },
- user_id: owner.id,
- });
+ await emitEvent({
+ event: "USER_NOTE_UPDATE",
+ data: {
+ note: note,
+ id: target.id,
+ },
+ user_id: owner.id,
+ });
- return res.sendStatus(204);
- },
+ return res.sendStatus(204);
+ },
);
export default router;
diff --git a/src/api/routes/users/@me/relationships.ts b/src/api/routes/users/@me/relationships.ts
index d3df9eb..ef6c779 100644
--- a/src/api/routes/users/@me/relationships.ts
+++ b/src/api/routes/users/@me/relationships.ts
@@ -27,255 +27,255 @@
const userProjection: (keyof User)[] = ["relationships", ...PublicUserProjection];
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "UserRelationshipsResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- relations: ["relationships", "relationships.to"],
- select: ["id", "relationships"],
- });
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "UserRelationshipsResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ relations: ["relationships", "relationships.to"],
+ select: ["id", "relationships"],
+ });
- const related_users = user.relationships.map((r) => r.toPublicRelationship());
- return res.json(related_users);
- },
+ const related_users = user.relationships.map((r) => r.toPublicRelationship());
+ return res.json(related_users);
+ },
);
router.put(
- "/:user_id",
- route({
- requestBody: "RelationshipPutSchema",
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- return await updateRelationship(
- req,
- res,
- await User.findOneOrFail({
- where: { id: req.params.user_id },
- relations: ["relationships", "relationships.to"],
- select: userProjection,
- }),
- req.body.type ?? RelationshipType.friends,
- );
- },
+ "/:user_id",
+ route({
+ requestBody: "RelationshipPutSchema",
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ return await updateRelationship(
+ req,
+ res,
+ await User.findOneOrFail({
+ where: { id: req.params.user_id },
+ relations: ["relationships", "relationships.to"],
+ select: userProjection,
+ }),
+ req.body.type ?? RelationshipType.friends,
+ );
+ },
);
router.post(
- "/",
- route({
- requestBody: "RelationshipPostSchema",
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- return await updateRelationship(
- req,
- res,
- await User.findOneOrFail({
- relations: ["relationships", "relationships.to"],
- select: userProjection,
- where: {
- discriminator: String(req.body.discriminator).padStart(4, "0"), //Discord send the discriminator as integer, we need to add leading zeroes
- username: req.body.username,
- },
- }),
- req.body.type,
- );
- },
+ "/",
+ route({
+ requestBody: "RelationshipPostSchema",
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ return await updateRelationship(
+ req,
+ res,
+ await User.findOneOrFail({
+ relations: ["relationships", "relationships.to"],
+ select: userProjection,
+ where: {
+ discriminator: String(req.body.discriminator).padStart(4, "0"), //Discord send the discriminator as integer, we need to add leading zeroes
+ username: req.body.username,
+ },
+ }),
+ req.body.type,
+ );
+ },
);
router.delete(
- "/:user_id",
- route({
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { user_id } = req.params;
- if (user_id === req.user_id) throw new HTTPError("You can't remove yourself as a friend");
+ "/:user_id",
+ route({
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { user_id } = req.params;
+ if (user_id === req.user_id) throw new HTTPError("You can't remove yourself as a friend");
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- select: userProjection,
- relations: ["relationships"],
- });
- const friend = await User.findOneOrFail({
- where: { id: user_id },
- select: userProjection,
- relations: ["relationships"],
- });
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ select: userProjection,
+ relations: ["relationships"],
+ });
+ const friend = await User.findOneOrFail({
+ where: { id: user_id },
+ select: userProjection,
+ relations: ["relationships"],
+ });
- const relationship = user.relationships.find((x) => x.to_id === user_id);
- const friendRequest = friend.relationships.find((x) => x.to_id === req.user_id);
+ const relationship = user.relationships.find((x) => x.to_id === user_id);
+ const friendRequest = friend.relationships.find((x) => x.to_id === req.user_id);
- if (!relationship) throw new HTTPError("You are not friends with the user", 404);
+ if (!relationship) throw new HTTPError("You are not friends with the user", 404);
- if (relationship?.type === RelationshipType.blocked) {
- // unblock user
- await Promise.all([
- Relationship.delete({ id: relationship.id }),
- emitEvent({
- event: "RELATIONSHIP_REMOVE",
- user_id: req.user_id,
- data: relationship.toPublicRelationship(),
- } as RelationshipRemoveEvent),
- ]);
- return res.sendStatus(204);
- }
- if (friendRequest && friendRequest.type !== RelationshipType.blocked) {
- await Promise.all([
- Relationship.delete({ id: friendRequest.id }),
- await emitEvent({
- event: "RELATIONSHIP_REMOVE",
- data: friendRequest.toPublicRelationship(),
- user_id: user_id,
- } as RelationshipRemoveEvent),
- ]);
- }
+ if (relationship?.type === RelationshipType.blocked) {
+ // unblock user
+ await Promise.all([
+ Relationship.delete({ id: relationship.id }),
+ emitEvent({
+ event: "RELATIONSHIP_REMOVE",
+ user_id: req.user_id,
+ data: relationship.toPublicRelationship(),
+ } as RelationshipRemoveEvent),
+ ]);
+ return res.sendStatus(204);
+ }
+ if (friendRequest && friendRequest.type !== RelationshipType.blocked) {
+ await Promise.all([
+ Relationship.delete({ id: friendRequest.id }),
+ await emitEvent({
+ event: "RELATIONSHIP_REMOVE",
+ data: friendRequest.toPublicRelationship(),
+ user_id: user_id,
+ } as RelationshipRemoveEvent),
+ ]);
+ }
- await Promise.all([
- Relationship.delete({ id: relationship.id }),
- emitEvent({
- event: "RELATIONSHIP_REMOVE",
- data: relationship.toPublicRelationship(),
- user_id: req.user_id,
- } as RelationshipRemoveEvent),
- ]);
+ await Promise.all([
+ Relationship.delete({ id: relationship.id }),
+ emitEvent({
+ event: "RELATIONSHIP_REMOVE",
+ data: relationship.toPublicRelationship(),
+ user_id: req.user_id,
+ } as RelationshipRemoveEvent),
+ ]);
- return res.sendStatus(204);
- },
+ return res.sendStatus(204);
+ },
);
export default router;
async function updateRelationship(req: Request, res: Response, friend: User, type: RelationshipType) {
- const id = friend.id;
- if (id === req.user_id) throw new HTTPError("You can't add yourself as a friend");
+ const id = friend.id;
+ if (id === req.user_id) throw new HTTPError("You can't add yourself as a friend");
- const user = await User.findOneOrFail({
- where: { id: req.user_id },
- relations: ["relationships", "relationships.to"],
- select: userProjection,
- });
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id },
+ relations: ["relationships", "relationships.to"],
+ select: userProjection,
+ });
- let relationship = user.relationships.find((x) => x.to_id === id);
- const friendRequest = friend.relationships.find((x) => x.to_id === req.user_id);
+ let relationship = user.relationships.find((x) => x.to_id === id);
+ const friendRequest = friend.relationships.find((x) => x.to_id === req.user_id);
- // TODO: you can add infinitely many blocked users (should this be prevented?)
- if (type === RelationshipType.blocked) {
- if (relationship) {
- if (relationship.type === RelationshipType.blocked) throw new HTTPError("You already blocked the user");
- relationship.type = RelationshipType.blocked;
- await relationship.save();
- } else {
- relationship = await Relationship.create({
- to_id: id,
- type: RelationshipType.blocked,
- from_id: req.user_id,
- }).save();
- }
+ // TODO: you can add infinitely many blocked users (should this be prevented?)
+ if (type === RelationshipType.blocked) {
+ if (relationship) {
+ if (relationship.type === RelationshipType.blocked) throw new HTTPError("You already blocked the user");
+ relationship.type = RelationshipType.blocked;
+ await relationship.save();
+ } else {
+ relationship = await Relationship.create({
+ to_id: id,
+ type: RelationshipType.blocked,
+ from_id: req.user_id,
+ }).save();
+ }
- if (friendRequest && friendRequest.type !== RelationshipType.blocked) {
- await Promise.all([
- Relationship.delete({ id: friendRequest.id }),
- emitEvent({
- event: "RELATIONSHIP_REMOVE",
- data: friendRequest.toPublicRelationship(),
- user_id: id,
- } as RelationshipRemoveEvent),
- ]);
- }
+ if (friendRequest && friendRequest.type !== RelationshipType.blocked) {
+ await Promise.all([
+ Relationship.delete({ id: friendRequest.id }),
+ emitEvent({
+ event: "RELATIONSHIP_REMOVE",
+ data: friendRequest.toPublicRelationship(),
+ user_id: id,
+ } as RelationshipRemoveEvent),
+ ]);
+ }
- await emitEvent({
- event: "RELATIONSHIP_ADD",
- data: relationship.toPublicRelationship(),
- user_id: req.user_id,
- } as RelationshipAddEvent);
+ await emitEvent({
+ event: "RELATIONSHIP_ADD",
+ data: relationship.toPublicRelationship(),
+ user_id: req.user_id,
+ } as RelationshipAddEvent);
- return res.sendStatus(204);
- }
+ return res.sendStatus(204);
+ }
- const { maxFriends } = Config.get().limits.user;
- if (user.relationships.length >= maxFriends) throw DiscordApiErrors.MAXIMUM_FRIENDS.withParams(maxFriends);
+ const { maxFriends } = Config.get().limits.user;
+ if (user.relationships.length >= maxFriends) throw DiscordApiErrors.MAXIMUM_FRIENDS.withParams(maxFriends);
- let incoming_relationship = Relationship.create({
- nickname: undefined,
- type: RelationshipType.incoming,
- to: user,
- from: friend,
- });
- let outgoing_relationship = Relationship.create({
- nickname: undefined,
- type: RelationshipType.outgoing,
- to: friend,
- from: user,
- });
+ let incoming_relationship = Relationship.create({
+ nickname: undefined,
+ type: RelationshipType.incoming,
+ to: user,
+ from: friend,
+ });
+ let outgoing_relationship = Relationship.create({
+ nickname: undefined,
+ type: RelationshipType.outgoing,
+ to: friend,
+ from: user,
+ });
- if (friendRequest) {
- if (friendRequest.type === RelationshipType.blocked) throw new HTTPError("The user blocked you");
- if (friendRequest.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user");
- // accept friend request
- incoming_relationship = friendRequest;
- incoming_relationship.type = RelationshipType.friends;
- }
+ if (friendRequest) {
+ if (friendRequest.type === RelationshipType.blocked) throw new HTTPError("The user blocked you");
+ if (friendRequest.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user");
+ // accept friend request
+ incoming_relationship = friendRequest;
+ incoming_relationship.type = RelationshipType.friends;
+ }
- if (relationship) {
- if (relationship.type === RelationshipType.outgoing) throw new HTTPError("You already sent a friend request");
- if (relationship.type === RelationshipType.blocked) throw new HTTPError("Unblock the user before sending a friend request");
- if (relationship.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user");
- outgoing_relationship = relationship;
- outgoing_relationship.type = RelationshipType.friends;
- }
+ if (relationship) {
+ if (relationship.type === RelationshipType.outgoing) throw new HTTPError("You already sent a friend request");
+ if (relationship.type === RelationshipType.blocked) throw new HTTPError("Unblock the user before sending a friend request");
+ if (relationship.type === RelationshipType.friends) throw new HTTPError("You are already friends with the user");
+ outgoing_relationship = relationship;
+ outgoing_relationship.type = RelationshipType.friends;
+ }
- await Promise.all([
- incoming_relationship.save(),
- outgoing_relationship.save(),
- emitEvent({
- event: "RELATIONSHIP_ADD",
- data: outgoing_relationship.toPublicRelationship(),
- user_id: req.user_id,
- } as RelationshipAddEvent),
- emitEvent({
- event: "RELATIONSHIP_ADD",
- data: {
- ...incoming_relationship.toPublicRelationship(),
- should_notify: true,
- },
- user_id: id,
- } as RelationshipAddEvent),
- ]);
+ await Promise.all([
+ incoming_relationship.save(),
+ outgoing_relationship.save(),
+ emitEvent({
+ event: "RELATIONSHIP_ADD",
+ data: outgoing_relationship.toPublicRelationship(),
+ user_id: req.user_id,
+ } as RelationshipAddEvent),
+ emitEvent({
+ event: "RELATIONSHIP_ADD",
+ data: {
+ ...incoming_relationship.toPublicRelationship(),
+ should_notify: true,
+ },
+ user_id: id,
+ } as RelationshipAddEvent),
+ ]);
- return res.sendStatus(204);
+ return res.sendStatus(204);
}
diff --git a/src/api/routes/users/@me/settings-proto/1.ts b/src/api/routes/users/@me/settings-proto/1.ts
index 6f58b42..d54bdf3 100644
--- a/src/api/routes/users/@me/settings-proto/1.ts
+++ b/src/api/routes/users/@me/settings-proto/1.ts
@@ -27,159 +27,159 @@
//#region Protobuf
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "SettingsProtoResponse",
- },
- },
- query: {
- atomic: {
- type: "boolean",
- description: "Whether to try to apply the settings update atomically (default false)",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const userSettings = await UserSettingsProtos.getOrDefault(req.user_id);
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "SettingsProtoResponse",
+ },
+ },
+ query: {
+ atomic: {
+ type: "boolean",
+ description: "Whether to try to apply the settings update atomically (default false)",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const userSettings = await UserSettingsProtos.getOrDefault(req.user_id);
- res.json({
- settings: PreloadedUserSettings.toBase64(userSettings.userSettings!),
- } as SettingsProtoResponse);
- },
+ res.json({
+ settings: PreloadedUserSettings.toBase64(userSettings.userSettings!),
+ } as SettingsProtoResponse);
+ },
);
router.patch(
- "/",
- route({
- requestBody: "SettingsProtoUpdateSchema",
- responses: {
- 200: {
- body: "SettingsProtoUpdateResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { settings, required_data_version } = req.body as SettingsProtoUpdateSchema;
- const { atomic } = req.query;
- const updatedSettings = PreloadedUserSettings.fromBase64(settings);
+ "/",
+ route({
+ requestBody: "SettingsProtoUpdateSchema",
+ responses: {
+ 200: {
+ body: "SettingsProtoUpdateResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { settings, required_data_version } = req.body as SettingsProtoUpdateSchema;
+ const { atomic } = req.query;
+ const updatedSettings = PreloadedUserSettings.fromBase64(settings);
- const resultObj = await patchUserSettings(req.user_id, updatedSettings, required_data_version, atomic == "true");
+ const resultObj = await patchUserSettings(req.user_id, updatedSettings, required_data_version, atomic == "true");
- res.json({
- settings: PreloadedUserSettings.toBase64(resultObj.settings),
- out_of_date: resultObj.out_of_date,
- });
- },
+ res.json({
+ settings: PreloadedUserSettings.toBase64(resultObj.settings),
+ out_of_date: resultObj.out_of_date,
+ });
+ },
);
//#endregion
//#region JSON
router.get(
- "/json",
- route({
- responses: {
- 200: {
- body: "SettingsProtoJsonResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const userSettings = await UserSettingsProtos.getOrDefault(req.user_id);
+ "/json",
+ route({
+ responses: {
+ 200: {
+ body: "SettingsProtoJsonResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const userSettings = await UserSettingsProtos.getOrDefault(req.user_id);
- res.json({
- settings: PreloadedUserSettings.toJson(userSettings.userSettings!),
- } as SettingsProtoJsonResponse);
- },
+ res.json({
+ settings: PreloadedUserSettings.toJson(userSettings.userSettings!),
+ } as SettingsProtoJsonResponse);
+ },
);
router.patch(
- "/json",
- route({
- requestBody: "SettingsProtoUpdateJsonSchema",
- responses: {
- 200: {
- body: "SettingsProtoUpdateJsonResponse",
- },
- },
- query: {
- atomic: {
- type: "boolean",
- description: "Whether to try to apply the settings update atomically (default false)",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { settings, required_data_version } = req.body as SettingsProtoUpdateJsonSchema;
- const { atomic } = req.query;
- const updatedSettings = PreloadedUserSettings.fromJson(settings);
+ "/json",
+ route({
+ requestBody: "SettingsProtoUpdateJsonSchema",
+ responses: {
+ 200: {
+ body: "SettingsProtoUpdateJsonResponse",
+ },
+ },
+ query: {
+ atomic: {
+ type: "boolean",
+ description: "Whether to try to apply the settings update atomically (default false)",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { settings, required_data_version } = req.body as SettingsProtoUpdateJsonSchema;
+ const { atomic } = req.query;
+ const updatedSettings = PreloadedUserSettings.fromJson(settings);
- const resultObj = await patchUserSettings(req.user_id, updatedSettings, required_data_version, atomic == "true");
+ const resultObj = await patchUserSettings(req.user_id, updatedSettings, required_data_version, atomic == "true");
- res.json({
- settings: PreloadedUserSettings.toJson(resultObj.settings),
- out_of_date: resultObj.out_of_date,
- });
- },
+ res.json({
+ settings: PreloadedUserSettings.toJson(resultObj.settings),
+ out_of_date: resultObj.out_of_date,
+ });
+ },
);
//#endregion
async function patchUserSettings(userId: string, updatedSettings: PreloadedUserSettings, required_data_version: number | undefined, atomic: boolean = false) {
- const userSettings = await UserSettingsProtos.getOrDefault(userId);
- let settings = userSettings.userSettings!;
+ const userSettings = await UserSettingsProtos.getOrDefault(userId);
+ let settings = userSettings.userSettings!;
- if (required_data_version && settings.versions && settings.versions.dataVersion > required_data_version) {
- return {
- settings: settings,
- out_of_date: true,
- };
- }
+ if (required_data_version && settings.versions && settings.versions.dataVersion > required_data_version) {
+ return {
+ settings: settings,
+ out_of_date: true,
+ };
+ }
- if ((process.env.LOG_PROTO_UPDATES || process.env.LOG_PROTO_SETTINGS_UPDATES) && process.env.LOG_PROTO_SETTINGS_UPDATES !== "false")
- console.log(`Updating user settings for user ${userId} with atomic=${atomic}:`, updatedSettings);
+ if ((process.env.LOG_PROTO_UPDATES || process.env.LOG_PROTO_SETTINGS_UPDATES) && process.env.LOG_PROTO_SETTINGS_UPDATES !== "false")
+ console.log(`Updating user settings for user ${userId} with atomic=${atomic}:`, updatedSettings);
- if (!atomic) {
- settings = PreloadedUserSettings.fromJson(
- Object.assign(PreloadedUserSettings.toJson(settings) as object, PreloadedUserSettings.toJson(updatedSettings) as object) as JsonValue,
- );
- } else {
- settings = PreloadedUserSettings.fromJson(
- OrmUtils.mergeDeep(PreloadedUserSettings.toJson(settings) as object, PreloadedUserSettings.toJson(updatedSettings) as object) as JsonValue,
- );
- }
+ if (!atomic) {
+ settings = PreloadedUserSettings.fromJson(
+ Object.assign(PreloadedUserSettings.toJson(settings) as object, PreloadedUserSettings.toJson(updatedSettings) as object) as JsonValue,
+ );
+ } else {
+ settings = PreloadedUserSettings.fromJson(
+ OrmUtils.mergeDeep(PreloadedUserSettings.toJson(settings) as object, PreloadedUserSettings.toJson(updatedSettings) as object) as JsonValue,
+ );
+ }
- settings.versions = {
- clientVersion: updatedSettings.versions?.clientVersion ?? settings.versions?.clientVersion ?? 0,
- serverVersion: settings.versions?.serverVersion ?? 0,
- dataVersion: (settings.versions?.dataVersion ?? 0) + 1,
- };
- userSettings.userSettings = settings;
- await userSettings.save();
+ settings.versions = {
+ clientVersion: updatedSettings.versions?.clientVersion ?? settings.versions?.clientVersion ?? 0,
+ serverVersion: settings.versions?.serverVersion ?? 0,
+ dataVersion: (settings.versions?.dataVersion ?? 0) + 1,
+ };
+ userSettings.userSettings = settings;
+ await userSettings.save();
- await emitEvent({
- user_id: userId,
- event: "USER_SETTINGS_PROTO_UPDATE",
- data: {
- settings: {
- proto: PreloadedUserSettings.toBase64(settings),
- type: 1,
- },
- json_settings: {
- proto: PreloadedUserSettings.toJson(settings),
- type: "user_settings",
- },
- partial: false, // Unsure how this should behave
- },
- });
- // This should also send a USER_SETTINGS_UPDATE event, but that isn't sent
- // when using the USER_SETTINGS_PROTOS capability, so we ignore it for now.
+ await emitEvent({
+ user_id: userId,
+ event: "USER_SETTINGS_PROTO_UPDATE",
+ data: {
+ settings: {
+ proto: PreloadedUserSettings.toBase64(settings),
+ type: 1,
+ },
+ json_settings: {
+ proto: PreloadedUserSettings.toJson(settings),
+ type: "user_settings",
+ },
+ partial: false, // Unsure how this should behave
+ },
+ });
+ // This should also send a USER_SETTINGS_UPDATE event, but that isn't sent
+ // when using the USER_SETTINGS_PROTOS capability, so we ignore it for now.
- return {
- settings: settings,
- out_of_date: false,
- };
+ return {
+ settings: settings,
+ out_of_date: false,
+ };
}
export default router;
diff --git a/src/api/routes/users/@me/settings-proto/2.ts b/src/api/routes/users/@me/settings-proto/2.ts
index b37805f..809db84 100644
--- a/src/api/routes/users/@me/settings-proto/2.ts
+++ b/src/api/routes/users/@me/settings-proto/2.ts
@@ -27,159 +27,159 @@
//#region Protobuf
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "SettingsProtoResponse",
- },
- },
- query: {
- atomic: {
- type: "boolean",
- description: "Whether to try to apply the settings update atomically (default false)",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const userSettings = await UserSettingsProtos.getOrDefault(req.user_id);
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "SettingsProtoResponse",
+ },
+ },
+ query: {
+ atomic: {
+ type: "boolean",
+ description: "Whether to try to apply the settings update atomically (default false)",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const userSettings = await UserSettingsProtos.getOrDefault(req.user_id);
- res.json({
- settings: FrecencyUserSettings.toBase64(userSettings.frecencySettings!),
- } as SettingsProtoResponse);
- },
+ res.json({
+ settings: FrecencyUserSettings.toBase64(userSettings.frecencySettings!),
+ } as SettingsProtoResponse);
+ },
);
router.patch(
- "/",
- route({
- requestBody: "SettingsProtoUpdateSchema",
- responses: {
- 200: {
- body: "SettingsProtoUpdateResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { settings, required_data_version } = req.body as SettingsProtoUpdateSchema;
- const { atomic } = req.query;
- const updatedSettings = FrecencyUserSettings.fromBase64(settings);
+ "/",
+ route({
+ requestBody: "SettingsProtoUpdateSchema",
+ responses: {
+ 200: {
+ body: "SettingsProtoUpdateResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { settings, required_data_version } = req.body as SettingsProtoUpdateSchema;
+ const { atomic } = req.query;
+ const updatedSettings = FrecencyUserSettings.fromBase64(settings);
- const resultObj = await patchUserSettings(req.user_id, updatedSettings, required_data_version, atomic == "true");
+ const resultObj = await patchUserSettings(req.user_id, updatedSettings, required_data_version, atomic == "true");
- res.json({
- settings: FrecencyUserSettings.toBase64(resultObj.settings),
- out_of_date: resultObj.out_of_date,
- });
- },
+ res.json({
+ settings: FrecencyUserSettings.toBase64(resultObj.settings),
+ out_of_date: resultObj.out_of_date,
+ });
+ },
);
//#endregion
//#region JSON
router.get(
- "/json",
- route({
- responses: {
- 200: {
- body: "SettingsProtoJsonResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const userSettings = await UserSettingsProtos.getOrDefault(req.user_id);
+ "/json",
+ route({
+ responses: {
+ 200: {
+ body: "SettingsProtoJsonResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const userSettings = await UserSettingsProtos.getOrDefault(req.user_id);
- res.json({
- settings: FrecencyUserSettings.toJson(userSettings.frecencySettings!),
- } as SettingsProtoJsonResponse);
- },
+ res.json({
+ settings: FrecencyUserSettings.toJson(userSettings.frecencySettings!),
+ } as SettingsProtoJsonResponse);
+ },
);
router.patch(
- "/json",
- route({
- requestBody: "SettingsProtoUpdateJsonSchema",
- responses: {
- 200: {
- body: "SettingsProtoUpdateJsonResponse",
- },
- },
- query: {
- atomic: {
- type: "boolean",
- description: "Whether to try to apply the settings update atomically (default false)",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const { settings, required_data_version } = req.body as SettingsProtoUpdateJsonSchema;
- const { atomic } = req.query;
- const updatedSettings = FrecencyUserSettings.fromJson(settings);
+ "/json",
+ route({
+ requestBody: "SettingsProtoUpdateJsonSchema",
+ responses: {
+ 200: {
+ body: "SettingsProtoUpdateJsonResponse",
+ },
+ },
+ query: {
+ atomic: {
+ type: "boolean",
+ description: "Whether to try to apply the settings update atomically (default false)",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { settings, required_data_version } = req.body as SettingsProtoUpdateJsonSchema;
+ const { atomic } = req.query;
+ const updatedSettings = FrecencyUserSettings.fromJson(settings);
- const resultObj = await patchUserSettings(req.user_id, updatedSettings, required_data_version, atomic == "true");
+ const resultObj = await patchUserSettings(req.user_id, updatedSettings, required_data_version, atomic == "true");
- res.json({
- settings: FrecencyUserSettings.toJson(resultObj.settings),
- out_of_date: resultObj.out_of_date,
- });
- },
+ res.json({
+ settings: FrecencyUserSettings.toJson(resultObj.settings),
+ out_of_date: resultObj.out_of_date,
+ });
+ },
);
//#endregion
async function patchUserSettings(userId: string, updatedSettings: FrecencyUserSettings, required_data_version: number | undefined, atomic: boolean = false) {
- const userSettings = await UserSettingsProtos.getOrDefault(userId);
- let settings = userSettings.frecencySettings!;
+ const userSettings = await UserSettingsProtos.getOrDefault(userId);
+ let settings = userSettings.frecencySettings!;
- if (required_data_version && settings.versions && settings.versions.dataVersion > required_data_version) {
- return {
- settings: settings,
- out_of_date: true,
- };
- }
+ if (required_data_version && settings.versions && settings.versions.dataVersion > required_data_version) {
+ return {
+ settings: settings,
+ out_of_date: true,
+ };
+ }
- if ((process.env.LOG_PROTO_UPDATES || process.env.LOG_PROTO_FRECENCY_UPDATES) && process.env.LOG_PROTO_FRECENCY_UPDATES !== "false")
- console.log(`Updating frecency settings for user ${userId} with atomic=${atomic}:`, updatedSettings);
+ if ((process.env.LOG_PROTO_UPDATES || process.env.LOG_PROTO_FRECENCY_UPDATES) && process.env.LOG_PROTO_FRECENCY_UPDATES !== "false")
+ console.log(`Updating frecency settings for user ${userId} with atomic=${atomic}:`, updatedSettings);
- if (!atomic) {
- settings = FrecencyUserSettings.fromJson(
- Object.assign(FrecencyUserSettings.toJson(settings) as object, FrecencyUserSettings.toJson(updatedSettings) as object) as JsonValue,
- );
- } else {
- settings = FrecencyUserSettings.fromJson(
- OrmUtils.mergeDeep(FrecencyUserSettings.toJson(settings) as object, FrecencyUserSettings.toJson(updatedSettings) as object) as JsonValue,
- );
- }
+ if (!atomic) {
+ settings = FrecencyUserSettings.fromJson(
+ Object.assign(FrecencyUserSettings.toJson(settings) as object, FrecencyUserSettings.toJson(updatedSettings) as object) as JsonValue,
+ );
+ } else {
+ settings = FrecencyUserSettings.fromJson(
+ OrmUtils.mergeDeep(FrecencyUserSettings.toJson(settings) as object, FrecencyUserSettings.toJson(updatedSettings) as object) as JsonValue,
+ );
+ }
- settings.versions = {
- clientVersion: updatedSettings.versions?.clientVersion ?? settings.versions?.clientVersion ?? 0,
- serverVersion: settings.versions?.serverVersion ?? 0,
- dataVersion: (settings.versions?.dataVersion ?? 0) + 1,
- };
- userSettings.frecencySettings = settings;
- await userSettings.save();
+ settings.versions = {
+ clientVersion: updatedSettings.versions?.clientVersion ?? settings.versions?.clientVersion ?? 0,
+ serverVersion: settings.versions?.serverVersion ?? 0,
+ dataVersion: (settings.versions?.dataVersion ?? 0) + 1,
+ };
+ userSettings.frecencySettings = settings;
+ await userSettings.save();
- await emitEvent({
- user_id: userId,
- event: "USER_SETTINGS_PROTO_UPDATE",
- data: {
- settings: {
- proto: FrecencyUserSettings.toBase64(settings),
- type: 2,
- },
- json_settings: {
- proto: FrecencyUserSettings.toJson(settings),
- type: "frecency_settings",
- },
- partial: false, // Unsure how this should behave
- },
- });
- // This should also send a USER_SETTINGS_UPDATE event, but that isn't sent
- // when using the USER_SETTINGS_PROTOS capability, so we ignore it for now.
+ await emitEvent({
+ user_id: userId,
+ event: "USER_SETTINGS_PROTO_UPDATE",
+ data: {
+ settings: {
+ proto: FrecencyUserSettings.toBase64(settings),
+ type: 2,
+ },
+ json_settings: {
+ proto: FrecencyUserSettings.toJson(settings),
+ type: "frecency_settings",
+ },
+ partial: false, // Unsure how this should behave
+ },
+ });
+ // This should also send a USER_SETTINGS_UPDATE event, but that isn't sent
+ // when using the USER_SETTINGS_PROTOS capability, so we ignore it for now.
- return {
- settings: settings,
- out_of_date: false,
- };
+ return {
+ settings: settings,
+ out_of_date: false,
+ };
}
export default router;
diff --git a/src/api/routes/users/@me/settings.ts b/src/api/routes/users/@me/settings.ts
index d220b85..57ffba1 100644
--- a/src/api/routes/users/@me/settings.ts
+++ b/src/api/routes/users/@me/settings.ts
@@ -24,81 +24,81 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "UserSettings",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const settings = await UserSettings.getOrDefault(req.user_id);
- return res.json(settings);
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "UserSettings",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const settings = await UserSettings.getOrDefault(req.user_id);
+ return res.json(settings);
+ },
);
router.patch(
- "/",
- route({
- requestBody: "UserSettingsUpdateSchema",
- responses: {
- 200: {
- body: "UserSettings",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 404: {
- body: "APIErrorResponse",
- },
- },
- }),
- async (req: Request, res: Response) => {
- const body = req.body as UserSettingsUpdateSchema;
- if (!body) return res.status(400).json({ code: 400, message: "Invalid request body" });
- if (body.locale === "en") body.locale = "en-US"; // fix discord client crash on unknown locale
+ "/",
+ route({
+ requestBody: "UserSettingsUpdateSchema",
+ responses: {
+ 200: {
+ body: "UserSettings",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {
+ body: "APIErrorResponse",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const body = req.body as UserSettingsUpdateSchema;
+ if (!body) return res.status(400).json({ code: 400, message: "Invalid request body" });
+ if (body.locale === "en") body.locale = "en-US"; // fix discord client crash on unknown locale
- const user = await User.findOneOrFail({
- where: { id: req.user_id, bot: false },
- relations: ["settings"],
- });
+ const user = await User.findOneOrFail({
+ where: { id: req.user_id, bot: false },
+ relations: ["settings"],
+ });
- if (!user.settings) user.settings = UserSettings.create(body);
- else user.settings.assign(body);
+ if (!user.settings) user.settings = UserSettings.create(body);
+ else user.settings.assign(body);
- if (body.guild_folders) user.settings.guild_folders = body.guild_folders;
+ if (body.guild_folders) user.settings.guild_folders = body.guild_folders;
- await user.settings.save();
- await user.save();
- if (body.status) {
- const [session] = (await Session.find({
- where: { user_id: user.id },
- })) as [Session | undefined];
- if (session) {
- session.status = body.status;
+ await user.settings.save();
+ await user.save();
+ if (body.status) {
+ const [session] = (await Session.find({
+ where: { user_id: user.id },
+ })) as [Session | undefined];
+ if (session) {
+ session.status = body.status;
- await Promise.all([
- emitEvent({
- event: "PRESENCE_UPDATE",
- user_id: user.id,
- data: {
- user: user.toPublicUser(),
- activities: session.activities,
- client_status: session?.client_status,
- status: session.getPublicStatus(),
- },
- } as PresenceUpdateEvent),
- session.save(),
- ]);
- }
- }
+ await Promise.all([
+ emitEvent({
+ event: "PRESENCE_UPDATE",
+ user_id: user.id,
+ data: {
+ user: user.toPublicUser(),
+ activities: session.activities,
+ client_status: session?.client_status,
+ status: session.getPublicStatus(),
+ },
+ } as PresenceUpdateEvent),
+ session.save(),
+ ]);
+ }
+ }
- res.json({ ...user.settings, index: undefined });
- },
+ res.json({ ...user.settings, index: undefined });
+ },
);
export default router;
diff --git a/src/api/routes/voice/regions.ts b/src/api/routes/voice/regions.ts
index ba26123..a6759b5 100644
--- a/src/api/routes/voice/regions.ts
+++ b/src/api/routes/voice/regions.ts
@@ -22,17 +22,17 @@
const router: Router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- responses: {
- 200: {
- body: "APIGuildVoiceRegion",
- },
- },
- }),
- async (req: Request, res: Response) => {
- res.json(await getVoiceRegions(req.ip!, true)); //vip true?
- },
+ "/",
+ route({
+ responses: {
+ 200: {
+ body: "APIGuildVoiceRegion",
+ },
+ },
+ }),
+ async (req: Request, res: Response) => {
+ res.json(await getVoiceRegions(req.ip!, true)); //vip true?
+ },
);
export default router;
diff --git "a/src/api/routes/webhooks/\043webhook_id/\043token/github.ts" "b/src/api/routes/webhooks/\043webhook_id/\043token/github.ts"
index 78d6bbb..81aa40a 100644
--- "a/src/api/routes/webhooks/\043webhook_id/\043token/github.ts"
+++ "b/src/api/routes/webhooks/\043webhook_id/\043token/github.ts"
@@ -7,402 +7,402 @@
const router = Router({ mergeParams: true });
const parseGitHubWebhook = (req: Request, res: Response, next: NextFunction) => {
- const eventType = req.headers["x-github-event"] as string;
- if (!eventType) {
- throw new HTTPError("Missing X-GitHub-Event header", 400);
- }
+ const eventType = req.headers["x-github-event"] as string;
+ if (!eventType) {
+ throw new HTTPError("Missing X-GitHub-Event header", 400);
+ }
- const discordPayload: WebhookExecuteSchema = {
- username: "GitHub",
- avatar_url: "https://github.githubassets.com/assets/GitHub-Mark-ea2971cee799.png",
- };
+ const discordPayload: WebhookExecuteSchema = {
+ username: "GitHub",
+ avatar_url: "https://github.githubassets.com/assets/GitHub-Mark-ea2971cee799.png",
+ };
- switch (eventType) {
- case "commit_comment":
- if (req.body.action !== "created") {
- return;
- }
+ switch (eventType) {
+ case "commit_comment":
+ if (req.body.action !== "created") {
+ return;
+ }
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- title: `[${req.body.repository.full_name}] New comment on commit \`${req.body.comment.commit_id.slice(0, 7)}\``,
- description: req.body.comment.body.length > 500 ? `${req.body.comment.body.slice(0, 497)}...` : req.body.comment.body,
- url: req.body.comment.html_url,
- },
- ];
- break;
- case "create":
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- title: `[${req.body.repository.full_name}] New ${req.body.ref_type} created: ${req.body.ref}`,
- },
- ];
- break;
- case "delete":
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- title: `[${req.body.repository.full_name}] ${req.body.ref_type} deleted: ${req.body.ref}`,
- },
- ];
- break;
- case "fork":
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- title: `[${req.body.repository.full_name}] Fork created: ${req.body.forkee.full_name}`,
- url: req.body.forkee.html_url,
- },
- ];
- break;
- case "issue_comment":
- if (req.body.action !== "created") {
- return;
- }
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ title: `[${req.body.repository.full_name}] New comment on commit \`${req.body.comment.commit_id.slice(0, 7)}\``,
+ description: req.body.comment.body.length > 500 ? `${req.body.comment.body.slice(0, 497)}...` : req.body.comment.body,
+ url: req.body.comment.html_url,
+ },
+ ];
+ break;
+ case "create":
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ title: `[${req.body.repository.full_name}] New ${req.body.ref_type} created: ${req.body.ref}`,
+ },
+ ];
+ break;
+ case "delete":
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ title: `[${req.body.repository.full_name}] ${req.body.ref_type} deleted: ${req.body.ref}`,
+ },
+ ];
+ break;
+ case "fork":
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ title: `[${req.body.repository.full_name}] Fork created: ${req.body.forkee.full_name}`,
+ url: req.body.forkee.html_url,
+ },
+ ];
+ break;
+ case "issue_comment":
+ if (req.body.action !== "created") {
+ return;
+ }
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- color: "pull_request" in req.body.issue ? 12576191 : 15109472,
- title: `[${req.body.repository.full_name}] New comment on ${"pull_request" in req.body.issue ? "pull request" : "issue"} #${req.body.issue.number}: ${
- req.body.issue.title.length > 150 ? `${req.body.issue.title.slice(0, 147)}...` : req.body.issue.title
- }`,
- url: req.body.comment.html_url,
- description: req.body.comment.body.length > 150 ? `${req.body.comment.body.slice(0, 497)}...` : req.body.comment.body,
- },
- ];
- break;
- case "issues":
- if (!["opened", "closed"].includes(req.body.action)) {
- return;
- }
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ color: "pull_request" in req.body.issue ? 12576191 : 15109472,
+ title: `[${req.body.repository.full_name}] New comment on ${"pull_request" in req.body.issue ? "pull request" : "issue"} #${req.body.issue.number}: ${
+ req.body.issue.title.length > 150 ? `${req.body.issue.title.slice(0, 147)}...` : req.body.issue.title
+ }`,
+ url: req.body.comment.html_url,
+ description: req.body.comment.body.length > 150 ? `${req.body.comment.body.slice(0, 497)}...` : req.body.comment.body,
+ },
+ ];
+ break;
+ case "issues":
+ if (!["opened", "closed"].includes(req.body.action)) {
+ return;
+ }
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- title: `[${req.body.repository.full_name}] Issue ${req.body.action} #${req.body.issue.number}: ${req.body.issue.title}`,
- url: req.body.issue.html_url,
- },
- ];
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ title: `[${req.body.repository.full_name}] Issue ${req.body.action} #${req.body.issue.number}: ${req.body.issue.title}`,
+ url: req.body.issue.html_url,
+ },
+ ];
- if (req.body.action === "opened") {
- discordPayload.embeds[0].color = 15426592;
- discordPayload.embeds[0].description = req.body.issue.body.length > 150 ? `${req.body.issue.body.slice(0, 147)}...` : req.body.issue.body;
- }
- break;
- case "member":
- if (req.body.action !== "added") {
- return;
- }
+ if (req.body.action === "opened") {
+ discordPayload.embeds[0].color = 15426592;
+ discordPayload.embeds[0].description = req.body.issue.body.length > 150 ? `${req.body.issue.body.slice(0, 147)}...` : req.body.issue.body;
+ }
+ break;
+ case "member":
+ if (req.body.action !== "added") {
+ return;
+ }
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- title: `[${req.body.repository.full_name}] New collaborator added: ${req.body.member.login}`,
- url: req.body.member.html_url,
- },
- ];
- break;
- case "public":
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- title: `[${req.body.repository.full_name}] Now open sourced!`,
- },
- ];
- break;
- case "pull_request": // funfact: for some reason, if a PR's title is over 216 chars in length you won't see any actions taken on the PR on discord
- if (!["opened", "closed"].includes(req.body.action)) {
- return;
- }
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ title: `[${req.body.repository.full_name}] New collaborator added: ${req.body.member.login}`,
+ url: req.body.member.html_url,
+ },
+ ];
+ break;
+ case "public":
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ title: `[${req.body.repository.full_name}] Now open sourced!`,
+ },
+ ];
+ break;
+ case "pull_request": // funfact: for some reason, if a PR's title is over 216 chars in length you won't see any actions taken on the PR on discord
+ if (!["opened", "closed"].includes(req.body.action)) {
+ return;
+ }
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- title: `[${req.body.repository.full_name}] Pull request ${req.body.action}: #${req.body.number} ${req.body.pull_request.title.length > 216 ? `${req.body.pull_request.title.slice(0, 213)}...` : req.body.pull_request.title}`,
- url: req.body.pull_request.html_url,
- },
- ];
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ title: `[${req.body.repository.full_name}] Pull request ${req.body.action}: #${req.body.number} ${req.body.pull_request.title.length > 216 ? `${req.body.pull_request.title.slice(0, 213)}...` : req.body.pull_request.title}`,
+ url: req.body.pull_request.html_url,
+ },
+ ];
- if (req.body.action === "opened") {
- if (req.body.pull_request.body != null) {
- discordPayload.embeds[0].description = req.body.pull_request.body.length > 500 ? `${req.body.pull_request.body.slice(0, 497)}...` : req.body.pull_request.body;
- }
- discordPayload.embeds[0].color = 38912;
- }
- break;
- case "pull_request_review": // funfact: for some reason, if a PR's title is over 216 chars in length you won't see any actions taken on the PR on discord
- if (req.body.action !== "submitted") {
- return;
- }
+ if (req.body.action === "opened") {
+ if (req.body.pull_request.body != null) {
+ discordPayload.embeds[0].description = req.body.pull_request.body.length > 500 ? `${req.body.pull_request.body.slice(0, 497)}...` : req.body.pull_request.body;
+ }
+ discordPayload.embeds[0].color = 38912;
+ }
+ break;
+ case "pull_request_review": // funfact: for some reason, if a PR's title is over 216 chars in length you won't see any actions taken on the PR on discord
+ if (req.body.action !== "submitted") {
+ return;
+ }
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- title: `[${req.body.repository.full_name}] Pull request review submitted: #${req.body.pull_request.number} ${req.body.pull_request.title.length > 216 ? `${req.body.pull_request.title.slice(0, 213)}...` : req.body.pull_request.title}`,
- description: req.body.review.body.length > 500 ? `${req.body.review.body.slice(0, 497)}...` : req.body.review.body,
- url: req.body.review.html_url,
- },
- ];
- break;
- case "pull_request_review_comment": // funfact: for some reason, if a PR's title is over 216 chars in length you won't see any actions taken on the PR on discord
- if (req.body.action !== "created") {
- return;
- }
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ title: `[${req.body.repository.full_name}] Pull request review submitted: #${req.body.pull_request.number} ${req.body.pull_request.title.length > 216 ? `${req.body.pull_request.title.slice(0, 213)}...` : req.body.pull_request.title}`,
+ description: req.body.review.body.length > 500 ? `${req.body.review.body.slice(0, 497)}...` : req.body.review.body,
+ url: req.body.review.html_url,
+ },
+ ];
+ break;
+ case "pull_request_review_comment": // funfact: for some reason, if a PR's title is over 216 chars in length you won't see any actions taken on the PR on discord
+ if (req.body.action !== "created") {
+ return;
+ }
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- color: 12576191,
- title: `[${req.body.repository.full_name}] New review comment on pull request: #${req.body.pull_request.number} ${req.body.pull_request.title.length > 216 ? `${req.body.pull_request.title.slice(0, 213)}...` : req.body.pull_request.title}`,
- description: req.body.comment.body.length > 500 ? `${req.body.comment.body.slice(0, 497)}...` : req.body.comment.body,
- url: req.body.comment.html_url,
- },
- ];
- break;
- case "push":
- if (!req.body.ref.startsWith("refs/heads/")) {
- return;
- }
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ color: 12576191,
+ title: `[${req.body.repository.full_name}] New review comment on pull request: #${req.body.pull_request.number} ${req.body.pull_request.title.length > 216 ? `${req.body.pull_request.title.slice(0, 213)}...` : req.body.pull_request.title}`,
+ description: req.body.comment.body.length > 500 ? `${req.body.comment.body.slice(0, 497)}...` : req.body.comment.body,
+ url: req.body.comment.html_url,
+ },
+ ];
+ break;
+ case "push":
+ if (!req.body.ref.startsWith("refs/heads/")) {
+ return;
+ }
- if (req.body.forced) {
- discordPayload.embeds = [
- {
- color: 16525609,
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- title: `[${req.body.repository.name}] Branch ${req.body.ref.slice(11)} was force-pushed to \`${req.body.head_commit.id.slice(0, 7)}\``,
- description: `[Compare changes](${req.body.compare})`,
- },
- ];
- } else {
- discordPayload.embeds = [
- {
- color: 7506394,
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- title: `[${req.body.repository.name}:${req.body.ref.slice(11)}] ${req.body.commits.length} new commit${req.body.commits.length > 1 ? "s" : ""}`,
- url: req.body.commits.length > 1 ? req.body.compare : req.body.head_commit.url,
- description: req.body.commits
- .slice(0, 5) // Discord only shows 5 first commits
- .map(
- (c: { id: string; url: string; message: string; author: { username: string } }) =>
- `[\`${c.id.slice(0, 7)}\`](${c.url}) ${c.message.split("\n")[0].length > 46 ? `${c.message.slice(0, 47)}...` : c.message.split("\n")[0]} - ${c.author.username}`,
- )
- .join("\n"),
- },
- ];
- }
- break;
- case "release":
- if (req.body.action !== "created") {
- return;
- }
+ if (req.body.forced) {
+ discordPayload.embeds = [
+ {
+ color: 16525609,
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ title: `[${req.body.repository.name}] Branch ${req.body.ref.slice(11)} was force-pushed to \`${req.body.head_commit.id.slice(0, 7)}\``,
+ description: `[Compare changes](${req.body.compare})`,
+ },
+ ];
+ } else {
+ discordPayload.embeds = [
+ {
+ color: 7506394,
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ title: `[${req.body.repository.name}:${req.body.ref.slice(11)}] ${req.body.commits.length} new commit${req.body.commits.length > 1 ? "s" : ""}`,
+ url: req.body.commits.length > 1 ? req.body.compare : req.body.head_commit.url,
+ description: req.body.commits
+ .slice(0, 5) // Discord only shows 5 first commits
+ .map(
+ (c: { id: string; url: string; message: string; author: { username: string } }) =>
+ `[\`${c.id.slice(0, 7)}\`](${c.url}) ${c.message.split("\n")[0].length > 46 ? `${c.message.slice(0, 47)}...` : c.message.split("\n")[0]} - ${c.author.username}`,
+ )
+ .join("\n"),
+ },
+ ];
+ }
+ break;
+ case "release":
+ if (req.body.action !== "created") {
+ return;
+ }
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- title: `[${req.body.repository.full_name}] New release published: ${req.body.release.tag_name}`,
- url: req.body.release.html_url,
- },
- ];
- break;
- case "watch":
- if (req.body.action !== "started") {
- return;
- }
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ title: `[${req.body.repository.full_name}] New release published: ${req.body.release.tag_name}`,
+ url: req.body.release.html_url,
+ },
+ ];
+ break;
+ case "watch":
+ if (req.body.action !== "started") {
+ return;
+ }
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- title: `[${req.body.repository.full_name}] New star added`,
- url: req.body.repository.html_url,
- },
- ];
- break;
- case "check_run":
- if (req.body.action !== "completed") {
- return;
- }
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ title: `[${req.body.repository.full_name}] New star added`,
+ url: req.body.repository.html_url,
+ },
+ ];
+ break;
+ case "check_run":
+ if (req.body.action !== "completed") {
+ return;
+ }
- discordPayload.embeds = [
- {
- color: req.body.check_run.conclusion == "success" ? 38912 : 16525609,
- title: `[${req.body.repository.name}] ${req.body.check_run.name} ${req.body.check_run.conclusion} on ${req.body.check_run.check_suite.head_branch}`,
- url: req.body.check_run.html_url,
- },
- ];
- break;
- case "check_suite":
- if (req.body.action !== "completed") {
- return;
- }
+ discordPayload.embeds = [
+ {
+ color: req.body.check_run.conclusion == "success" ? 38912 : 16525609,
+ title: `[${req.body.repository.name}] ${req.body.check_run.name} ${req.body.check_run.conclusion} on ${req.body.check_run.check_suite.head_branch}`,
+ url: req.body.check_run.html_url,
+ },
+ ];
+ break;
+ case "check_suite":
+ if (req.body.action !== "completed") {
+ return;
+ }
- discordPayload.embeds = [
- {
- color: req.body.check_suite.conclusion == "success" ? 38912 : 16525609,
- title: `[${req.body.repository.name}] GitHub Actions checks ${req.body.check_suite.conclusion} on ${req.body.check_suite.head_branch}`,
- url: `https://github.com/${req.body.repository.full_name}/commit/${req.body.check_suite.head_commit.id}`,
- },
- ];
- break;
- case "discussion":
- if (req.body.action !== "created") {
- return;
- }
+ discordPayload.embeds = [
+ {
+ color: req.body.check_suite.conclusion == "success" ? 38912 : 16525609,
+ title: `[${req.body.repository.name}] GitHub Actions checks ${req.body.check_suite.conclusion} on ${req.body.check_suite.head_branch}`,
+ url: `https://github.com/${req.body.repository.full_name}/commit/${req.body.check_suite.head_commit.id}`,
+ },
+ ];
+ break;
+ case "discussion":
+ if (req.body.action !== "created") {
+ return;
+ }
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- color: 15109472,
- title: `[${req.body.repository.name}] New discussion #${req.body.discussion.number}: ${req.body.discussion.title.length > 150 ? `${req.body.discussion.title.slice(0, 151)}...` : req.body.discussion.title}`,
- url: req.body.discussion.html_url,
- description: req.body.discussion.body.length > 500 ? `${req.body.discussion.body.slice(0, 497)}...` : req.body.discussion.body,
- },
- ];
- break;
- case "discussion_comment":
- if (req.body.action !== "created") {
- return;
- }
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ color: 15109472,
+ title: `[${req.body.repository.name}] New discussion #${req.body.discussion.number}: ${req.body.discussion.title.length > 150 ? `${req.body.discussion.title.slice(0, 151)}...` : req.body.discussion.title}`,
+ url: req.body.discussion.html_url,
+ description: req.body.discussion.body.length > 500 ? `${req.body.discussion.body.slice(0, 497)}...` : req.body.discussion.body,
+ },
+ ];
+ break;
+ case "discussion_comment":
+ if (req.body.action !== "created") {
+ return;
+ }
- discordPayload.embeds = [
- {
- author: {
- name: req.body.sender.login,
- icon_url: req.body.sender.avatar_url,
- proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
- url: req.body.sender.html_url,
- },
- color: 15109472,
- title: `[${req.body.comment.repository_url}] New comment on discussion #${req.body.discussion.number}: ${req.body.discussion.title.length > 150 ? `${req.body.discussion.title.slice(0, 151)}...` : req.body.discussion.title}`,
- url: req.body.comment.html_url,
- description: req.body.comment.body.length > 500 ? `${req.body.comment.body.slice(0, 497)}...` : req.body.comment.body,
- },
- ];
- break;
- default:
- return res.status(204).end(); // Yes, discord sends 204 even on invalid event
- }
+ discordPayload.embeds = [
+ {
+ author: {
+ name: req.body.sender.login,
+ icon_url: req.body.sender.avatar_url,
+ proxy_icon_url: getProxyUrl(new URL(req.body.sender.avatar_url), 80, 80),
+ url: req.body.sender.html_url,
+ },
+ color: 15109472,
+ title: `[${req.body.comment.repository_url}] New comment on discussion #${req.body.discussion.number}: ${req.body.discussion.title.length > 150 ? `${req.body.discussion.title.slice(0, 151)}...` : req.body.discussion.title}`,
+ url: req.body.comment.html_url,
+ description: req.body.comment.body.length > 500 ? `${req.body.comment.body.slice(0, 497)}...` : req.body.comment.body,
+ },
+ ];
+ break;
+ default:
+ return res.status(204).end(); // Yes, discord sends 204 even on invalid event
+ }
- req.body = discordPayload;
- req.query.wait ||= "true";
+ req.body = discordPayload;
+ req.query.wait ||= "true";
- next();
+ next();
};
router.post(
- "/",
- parseGitHubWebhook,
- (req, _res, next) => {
- if (req.body.payload_json) {
- req.body = JSON.parse(req.body.payload_json);
- }
- next();
- },
- route({
- requestBody: "WebhookExecuteSchema",
- query: {
- wait: {
- type: "boolean",
- required: false,
- description: "waits for server confirmation of message send before response, and returns the created message body",
- },
- thread_id: {
- type: "string",
- required: false,
- description: "Send a message to the specified thread within a webhook's channel.",
- },
- },
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {},
- },
- }),
- executeWebhook,
+ "/",
+ parseGitHubWebhook,
+ (req, _res, next) => {
+ if (req.body.payload_json) {
+ req.body = JSON.parse(req.body.payload_json);
+ }
+ next();
+ },
+ route({
+ requestBody: "WebhookExecuteSchema",
+ query: {
+ wait: {
+ type: "boolean",
+ required: false,
+ description: "waits for server confirmation of message send before response, and returns the created message body",
+ },
+ thread_id: {
+ type: "string",
+ required: false,
+ description: "Send a message to the specified thread within a webhook's channel.",
+ },
+ },
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {},
+ },
+ }),
+ executeWebhook,
);
export default router;
diff --git "a/src/api/routes/webhooks/\043webhook_id/\043token/index.ts" "b/src/api/routes/webhooks/\043webhook_id/\043token/index.ts"
index 1b589a7..eecbfca 100644
--- "a/src/api/routes/webhooks/\043webhook_id/\043token/index.ts"
+++ "b/src/api/routes/webhooks/\043webhook_id/\043token/index.ts"
@@ -8,179 +8,179 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- description: "Returns a webhook object for the given id and token.",
- responses: {
- 200: {
- body: "APIWebhook",
- },
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { webhook_id, token } = req.params;
- const webhook = await Webhook.findOne({
- where: {
- id: webhook_id,
- },
- relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
- });
+ "/",
+ route({
+ description: "Returns a webhook object for the given id and token.",
+ responses: {
+ 200: {
+ body: "APIWebhook",
+ },
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { webhook_id, token } = req.params;
+ const webhook = await Webhook.findOne({
+ where: {
+ id: webhook_id,
+ },
+ relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
+ });
- if (!webhook) {
- throw DiscordApiErrors.UNKNOWN_WEBHOOK;
- }
+ if (!webhook) {
+ throw DiscordApiErrors.UNKNOWN_WEBHOOK;
+ }
- if (webhook.token !== token) {
- throw DiscordApiErrors.INVALID_WEBHOOK_TOKEN_PROVIDED;
- }
+ if (webhook.token !== token) {
+ throw DiscordApiErrors.INVALID_WEBHOOK_TOKEN_PROVIDED;
+ }
- return res.json({
- ...webhook,
- url: Config.get().api.endpointPublic + "/webhooks/" + webhook.id + "/" + webhook.token,
- });
- },
+ return res.json({
+ ...webhook,
+ url: Config.get().api.endpointPublic + "/webhooks/" + webhook.id + "/" + webhook.token,
+ });
+ },
);
// TODO: config max upload size
const messageUpload = multer({
- limits: {
- fileSize: Config.get().limits.message.maxAttachmentSize,
- fields: 10,
- // files: 1
- },
- storage: multer.memoryStorage(),
+ limits: {
+ fileSize: Config.get().limits.message.maxAttachmentSize,
+ fields: 10,
+ // files: 1
+ },
+ storage: multer.memoryStorage(),
}); // max upload 50 mb
// https://discord.com/developers/docs/resources/webhook#execute-webhook
// TODO: Slack compatible hooks
router.post(
- "/",
- messageUpload.any(),
- (req, _res, next) => {
- if (req.body.payload_json) {
- req.body = JSON.parse(req.body.payload_json);
- }
+ "/",
+ messageUpload.any(),
+ (req, _res, next) => {
+ if (req.body.payload_json) {
+ req.body = JSON.parse(req.body.payload_json);
+ }
- next();
- },
- route({
- requestBody: "WebhookExecuteSchema",
- query: {
- wait: {
- type: "boolean",
- required: false,
- description: "waits for server confirmation of message send before response, and returns the created message body",
- },
- thread_id: {
- type: "string",
- required: false,
- description: "Send a message to the specified thread within a webhook's channel.",
- },
- },
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {},
- },
- }),
- executeWebhook,
+ next();
+ },
+ route({
+ requestBody: "WebhookExecuteSchema",
+ query: {
+ wait: {
+ type: "boolean",
+ required: false,
+ description: "waits for server confirmation of message send before response, and returns the created message body",
+ },
+ thread_id: {
+ type: "string",
+ required: false,
+ description: "Send a message to the specified thread within a webhook's channel.",
+ },
+ },
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {},
+ },
+ }),
+ executeWebhook,
);
router.delete(
- "/",
- route({
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { webhook_id, token } = req.params;
+ "/",
+ route({
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { webhook_id, token } = req.params;
- const webhook = await Webhook.findOne({
- where: {
- id: webhook_id,
- },
- relations: ["channel", "guild", "application"],
- });
+ const webhook = await Webhook.findOne({
+ where: {
+ id: webhook_id,
+ },
+ relations: ["channel", "guild", "application"],
+ });
- if (!webhook) {
- throw DiscordApiErrors.UNKNOWN_WEBHOOK;
- }
+ if (!webhook) {
+ throw DiscordApiErrors.UNKNOWN_WEBHOOK;
+ }
- if (webhook.token !== token) {
- throw DiscordApiErrors.INVALID_WEBHOOK_TOKEN_PROVIDED;
- }
- const channel_id = webhook.channel_id;
- await Webhook.delete({ id: webhook_id });
+ if (webhook.token !== token) {
+ throw DiscordApiErrors.INVALID_WEBHOOK_TOKEN_PROVIDED;
+ }
+ const channel_id = webhook.channel_id;
+ await Webhook.delete({ id: webhook_id });
- await emitEvent({
- event: "WEBHOOKS_UPDATE",
- channel_id,
- data: {
- channel_id,
- guild_id: webhook.guild_id,
- },
- } as WebhooksUpdateEvent);
+ await emitEvent({
+ event: "WEBHOOKS_UPDATE",
+ channel_id,
+ data: {
+ channel_id,
+ guild_id: webhook.guild_id,
+ },
+ } as WebhooksUpdateEvent);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
router.patch(
- "/",
- route({
- requestBody: "WebhookUpdateSchema",
- responses: {
- 200: {
- body: "Message",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {},
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { webhook_id, token } = req.params;
- const body = req.body as WebhookUpdateSchema;
+ "/",
+ route({
+ requestBody: "WebhookUpdateSchema",
+ responses: {
+ 200: {
+ body: "Message",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {},
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { webhook_id, token } = req.params;
+ const body = req.body as WebhookUpdateSchema;
- const webhook = await Webhook.findOneOrFail({
- where: { id: webhook_id },
- relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
- });
- const channel_id = webhook.channel_id;
- if (!body.name && !body.avatar) {
- throw new HTTPError("Empty webhook updates are not allowed", 50006);
- }
- if (body.avatar) body.avatar = await handleFile(`/avatars/${webhook_id}`, body.avatar as string);
+ const webhook = await Webhook.findOneOrFail({
+ where: { id: webhook_id },
+ relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
+ });
+ const channel_id = webhook.channel_id;
+ if (!body.name && !body.avatar) {
+ throw new HTTPError("Empty webhook updates are not allowed", 50006);
+ }
+ if (body.avatar) body.avatar = await handleFile(`/avatars/${webhook_id}`, body.avatar as string);
- if (body.name) {
- ValidateName(body.name);
- }
+ if (body.name) {
+ ValidateName(body.name);
+ }
- webhook.assign(body);
+ webhook.assign(body);
- await Promise.all([
- webhook.save(),
- emitEvent({
- event: "WEBHOOKS_UPDATE",
- channel_id,
- data: {
- channel_id,
- guild_id: webhook.guild_id,
- },
- } as WebhooksUpdateEvent),
- ]);
- res.status(204);
- },
+ await Promise.all([
+ webhook.save(),
+ emitEvent({
+ event: "WEBHOOKS_UPDATE",
+ channel_id,
+ data: {
+ channel_id,
+ guild_id: webhook.guild_id,
+ },
+ } as WebhooksUpdateEvent),
+ ]);
+ res.status(204);
+ },
);
export default router;
diff --git "a/src/api/routes/webhooks/\043webhook_id/index.ts" "b/src/api/routes/webhooks/\043webhook_id/index.ts"
index 9c0a641..8844b8e 100644
--- "a/src/api/routes/webhooks/\043webhook_id/index.ts"
+++ "b/src/api/routes/webhooks/\043webhook_id/index.ts"
@@ -6,141 +6,141 @@
const router = Router({ mergeParams: true });
router.get(
- "/",
- route({
- description: "Returns a webhook object for the given id. Requires the MANAGE_WEBHOOKS permission or to be the owner of the webhook.",
- responses: {
- 200: {
- body: "APIWebhook",
- },
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { webhook_id } = req.params;
- const webhook = await Webhook.findOneOrFail({
- where: { id: webhook_id },
- relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
- });
+ "/",
+ route({
+ description: "Returns a webhook object for the given id. Requires the MANAGE_WEBHOOKS permission or to be the owner of the webhook.",
+ responses: {
+ 200: {
+ body: "APIWebhook",
+ },
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { webhook_id } = req.params;
+ const webhook = await Webhook.findOneOrFail({
+ where: { id: webhook_id },
+ relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
+ });
- if (webhook.guild_id) {
- const permission = await getPermission(req.user_id, webhook.guild_id);
+ if (webhook.guild_id) {
+ const permission = await getPermission(req.user_id, webhook.guild_id);
- if (!permission.has("MANAGE_WEBHOOKS")) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
- } else if (webhook.user_id != req.user_id) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
+ if (!permission.has("MANAGE_WEBHOOKS")) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
+ } else if (webhook.user_id != req.user_id) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
- return res.json({
- ...webhook,
- url: Config.get().api.endpointPublic + "/webhooks/" + webhook.id + "/" + webhook.token,
- });
- },
+ return res.json({
+ ...webhook,
+ url: Config.get().api.endpointPublic + "/webhooks/" + webhook.id + "/" + webhook.token,
+ });
+ },
);
router.delete(
- "/",
- route({
- responses: {
- 204: {},
- 400: {
- body: "APIErrorResponse",
- },
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { webhook_id } = req.params;
+ "/",
+ route({
+ responses: {
+ 204: {},
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { webhook_id } = req.params;
- const webhook = await Webhook.findOneOrFail({
- where: { id: webhook_id },
- relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
- });
+ const webhook = await Webhook.findOneOrFail({
+ where: { id: webhook_id },
+ relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
+ });
- if (webhook.guild_id) {
- const permission = await getPermission(req.user_id, webhook.guild_id);
+ if (webhook.guild_id) {
+ const permission = await getPermission(req.user_id, webhook.guild_id);
- if (!permission.has("MANAGE_WEBHOOKS")) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
- } else if (webhook.user_id != req.user_id) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
+ if (!permission.has("MANAGE_WEBHOOKS")) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
+ } else if (webhook.user_id != req.user_id) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
- const channel_id = webhook.channel_id;
- await Webhook.delete({ id: webhook_id });
+ const channel_id = webhook.channel_id;
+ await Webhook.delete({ id: webhook_id });
- await emitEvent({
- event: "WEBHOOKS_UPDATE",
- channel_id,
- data: {
- channel_id,
- guild_id: webhook.guild_id,
- },
- } as WebhooksUpdateEvent);
+ await emitEvent({
+ event: "WEBHOOKS_UPDATE",
+ channel_id,
+ data: {
+ channel_id,
+ guild_id: webhook.guild_id,
+ },
+ } as WebhooksUpdateEvent);
- res.sendStatus(204);
- },
+ res.sendStatus(204);
+ },
);
router.patch(
- "/",
- route({
- requestBody: "WebhookUpdateSchema",
- responses: {
- 200: {
- body: "WebhookCreateResponse",
- },
- 400: {
- body: "APIErrorResponse",
- },
- 403: {},
- 404: {},
- },
- }),
- async (req: Request, res: Response) => {
- const { webhook_id } = req.params;
- const body = req.body as WebhookUpdateSchema;
+ "/",
+ route({
+ requestBody: "WebhookUpdateSchema",
+ responses: {
+ 200: {
+ body: "WebhookCreateResponse",
+ },
+ 400: {
+ body: "APIErrorResponse",
+ },
+ 403: {},
+ 404: {},
+ },
+ }),
+ async (req: Request, res: Response) => {
+ const { webhook_id } = req.params;
+ const body = req.body as WebhookUpdateSchema;
- const webhook = await Webhook.findOneOrFail({
- where: { id: webhook_id },
- relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
- });
+ const webhook = await Webhook.findOneOrFail({
+ where: { id: webhook_id },
+ relations: ["user", "channel", "source_channel", "guild", "source_guild", "application"],
+ });
- if (webhook.guild_id) {
- const permission = await getPermission(req.user_id, webhook.guild_id);
+ if (webhook.guild_id) {
+ const permission = await getPermission(req.user_id, webhook.guild_id);
- if (!permission.has("MANAGE_WEBHOOKS")) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
- } else if (webhook.user_id != req.user_id) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
+ if (!permission.has("MANAGE_WEBHOOKS")) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
+ } else if (webhook.user_id != req.user_id) throw DiscordApiErrors.UNKNOWN_WEBHOOK;
- if (!body.name && !body.avatar && !body.channel_id) {
- throw new HTTPError("Empty webhook updates are not allowed", 50006);
- }
+ if (!body.name && !body.avatar && !body.channel_id) {
+ throw new HTTPError("Empty webhook updates are not allowed", 50006);
+ }
- if (body.avatar) body.avatar = await handleFile(`/avatars/${webhook_id}`, body.avatar as string);
+ if (body.avatar) body.avatar = await handleFile(`/avatars/${webhook_id}`, body.avatar as string);
- if (body.name) {
- ValidateName(body.name);
- }
+ if (body.name) {
+ ValidateName(body.name);
+ }
- const channel_id = body.channel_id || webhook.channel_id;
- webhook.assign(body);
+ const channel_id = body.channel_id || webhook.channel_id;
+ webhook.assign(body);
- if (body.channel_id)
- webhook.assign({
- channel: await Channel.findOneOrFail({
- where: { id: channel_id },
- }),
- });
+ if (body.channel_id)
+ webhook.assign({
+ channel: await Channel.findOneOrFail({
+ where: { id: channel_id },
+ }),
+ });
- await Promise.all([
- webhook.save(),
- emitEvent({
- event: "WEBHOOKS_UPDATE",
- channel_id,
- data: {
- channel_id,
- guild_id: webhook.guild_id,
- },
- } as WebhooksUpdateEvent),
- ]);
+ await Promise.all([
+ webhook.save(),
+ emitEvent({
+ event: "WEBHOOKS_UPDATE",
+ channel_id,
+ data: {
+ channel_id,
+ guild_id: webhook.guild_id,
+ },
+ } as WebhooksUpdateEvent),
+ ]);
- res.json(webhook);
- },
+ res.json(webhook);
+ },
);
export default router;
diff --git a/src/api/start.ts b/src/api/start.ts
index cd3373b..96c0c34 100644
--- a/src/api/start.ts
+++ b/src/api/start.ts
@@ -28,30 +28,30 @@
import os from "os";
let cores = 1;
try {
- cores = Number(process.env.THREADS) || os.cpus().length;
+ cores = Number(process.env.THREADS) || os.cpus().length;
} catch {
- console.log("[API] Failed to get thread count! Using 1...");
+ console.log("[API] Failed to get thread count! Using 1...");
}
if (cluster.isPrimary && process.env.NODE_ENV == "production") {
- console.log(`Primary PID: ${process.pid}`);
+ console.log(`Primary PID: ${process.pid}`);
- // Fork workers.
- for (let i = 0; i < cores; i++) {
- cluster.fork();
- }
+ // Fork workers.
+ for (let i = 0; i < cores; i++) {
+ cluster.fork();
+ }
- cluster.on("exit", (worker) => {
- console.log(`Worker ${worker.process.pid} died, restarting worker`);
- cluster.fork();
- });
+ cluster.on("exit", (worker) => {
+ console.log(`Worker ${worker.process.pid} died, restarting worker`);
+ cluster.fork();
+ });
} else {
- const port = Number(process.env.PORT) || 3001;
+ const port = Number(process.env.PORT) || 3001;
- const server = new SpacebarServer({ port });
- server.start().catch(console.error);
+ const server = new SpacebarServer({ port });
+ server.start().catch(console.error);
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- // @ts-ignore
- global.server = server;
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ global.server = server;
}
diff --git a/src/api/util/handlers/Instance.ts b/src/api/util/handlers/Instance.ts
index 86dda74..e71c3ed 100644
--- a/src/api/util/handlers/Instance.ts
+++ b/src/api/util/handlers/Instance.ts
@@ -21,34 +21,34 @@
import { setInterval } from "timers";
export async function initInstance() {
- // TODO: clean up database and delete tombstone data
- // TODO: set first user as instance administrator/or generate one if none exists and output it in the terminal
+ // TODO: clean up database and delete tombstone data
+ // TODO: set first user as instance administrator/or generate one if none exists and output it in the terminal
- // create default guild and add it to auto join
- // TODO: check if any current user is not part of autoJoinGuilds
- // const { autoJoin } = Config.get().guild;
+ // create default guild and add it to auto join
+ // TODO: check if any current user is not part of autoJoinGuilds
+ // const { autoJoin } = Config.get().guild;
- // if (autoJoin.enabled && !autoJoin.guilds?.length) {
- // const guild = await Guild.findOne({ where: {}, select: ["id"] });
- // if (guild) {
- // await Config.set({ guild: { autoJoin: { guilds: [guild.id] } } });
- // }
- // }
+ // if (autoJoin.enabled && !autoJoin.guilds?.length) {
+ // const guild = await Guild.findOne({ where: {}, select: ["id"] });
+ // if (guild) {
+ // await Config.set({ guild: { autoJoin: { guilds: [guild.id] } } });
+ // }
+ // }
- // TODO: do no clear sessions for instance cluster
- // await Session.clear(); // This is now used as part of authentication...
- // ... but we can still expire temporary sessions for legacy tokens
- setInterval(
- async () => {
- for await (const session of await Session.createQueryBuilder("session").where("last_seen = '1970/01/01'").select().stream()) {
- // session object has all fields prefixed with `session_`... thanks typeorm
- if (TimeSpan.fromDates((session.session_created_at as Date).getTime(), new Date().getTime()).totalHours > 1) {
- console.log(`[API/Instance.ts] Deleting unused session ${session.session_session_id} created at ${session.session_created_at}`);
- await Session.delete({ session_id: session.session_session_id });
- }
- }
- },
- 1000 * 60 * 5,
- );
- // await Session.delete({ session_id: Like("TEMP_%") });
+ // TODO: do no clear sessions for instance cluster
+ // await Session.clear(); // This is now used as part of authentication...
+ // ... but we can still expire temporary sessions for legacy tokens
+ setInterval(
+ async () => {
+ for await (const session of await Session.createQueryBuilder("session").where("last_seen = '1970/01/01'").select().stream()) {
+ // session object has all fields prefixed with `session_`... thanks typeorm
+ if (TimeSpan.fromDates((session.session_created_at as Date).getTime(), new Date().getTime()).totalHours > 1) {
+ console.log(`[API/Instance.ts] Deleting unused session ${session.session_session_id} created at ${session.session_created_at}`);
+ await Session.delete({ session_id: session.session_session_id });
+ }
+ }
+ },
+ 1000 * 60 * 5,
+ );
+ // await Session.delete({ session_id: Like("TEMP_%") });
}
diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts
index 06a3e08..65583f5 100644
--- a/src/api/util/handlers/Message.ts
+++ b/src/api/util/handlers/Message.ts
@@ -18,36 +18,36 @@
import { EmbedHandlers } from "@spacebar/api";
import {
- Application,
- Attachment,
- Channel,
- Config,
- EmbedCache,
- emitEvent,
- EVERYONE_MENTION,
- getPermission,
- getRights,
- Guild,
- HERE_MENTION,
- Message,
- MessageCreateEvent,
- MessageUpdateEvent,
- Role,
- ROLE_MENTION,
- Sticker,
- User,
- //CHANNEL_MENTION,
- USER_MENTION,
- Webhook,
- handleFile,
- Permissions,
- normalizeUrl,
- DiscordApiErrors,
- CloudAttachment,
- ReadState,
- Member,
- Session,
- MessageFlags,
+ Application,
+ Attachment,
+ Channel,
+ Config,
+ EmbedCache,
+ emitEvent,
+ EVERYONE_MENTION,
+ getPermission,
+ getRights,
+ Guild,
+ HERE_MENTION,
+ Message,
+ MessageCreateEvent,
+ MessageUpdateEvent,
+ Role,
+ ROLE_MENTION,
+ Sticker,
+ User,
+ //CHANNEL_MENTION,
+ USER_MENTION,
+ Webhook,
+ handleFile,
+ Permissions,
+ normalizeUrl,
+ DiscordApiErrors,
+ CloudAttachment,
+ ReadState,
+ Member,
+ Session,
+ MessageFlags,
} from "@spacebar/util";
import { HTTPError } from "lambert-server";
import { In, Or, Equal, IsNull } from "typeorm";
@@ -59,515 +59,515 @@
const LINK_REGEX = /?/g;
export async function handleMessage(opts: MessageOptions): Promise {
- const channel = await Channel.findOneOrFail({
- where: { id: opts.channel_id },
- relations: ["recipients"],
- });
- if (!channel || !opts.channel_id) throw new HTTPError("Channel not found", 404);
+ const channel = await Channel.findOneOrFail({
+ where: { id: opts.channel_id },
+ relations: ["recipients"],
+ });
+ if (!channel || !opts.channel_id) throw new HTTPError("Channel not found", 404);
- let permission: undefined | Permissions;
- const limit = channel.rate_limit_per_user;
+ let permission: undefined | Permissions;
+ const limit = channel.rate_limit_per_user;
- if (limit) {
- const lastMsgTime = (await Message.findOne({ where: { channel_id: channel.id, author_id: opts.author_id }, select: { timestamp: true }, order: { timestamp: "DESC" } }))
- ?.timestamp;
- if (lastMsgTime && Date.now() - limit * 1000 < +lastMsgTime) {
- permission ||= await getPermission(opts.author_id, channel.guild_id, channel);
- //FIXME MANAGE_MESSAGES and MANAGE_CHANNELS will need to be removed once they're gone as checks
- if (!permission.has("MANAGE_MESSAGES") && !permission.has("MANAGE_CHANNELS") && !permission.has("BYPASS_SLOWMODE")) {
- throw DiscordApiErrors.SLOWMODE_RATE_LIMIT;
- }
- }
- }
+ if (limit) {
+ const lastMsgTime = (await Message.findOne({ where: { channel_id: channel.id, author_id: opts.author_id }, select: { timestamp: true }, order: { timestamp: "DESC" } }))
+ ?.timestamp;
+ if (lastMsgTime && Date.now() - limit * 1000 < +lastMsgTime) {
+ permission ||= await getPermission(opts.author_id, channel.guild_id, channel);
+ //FIXME MANAGE_MESSAGES and MANAGE_CHANNELS will need to be removed once they're gone as checks
+ if (!permission.has("MANAGE_MESSAGES") && !permission.has("MANAGE_CHANNELS") && !permission.has("BYPASS_SLOWMODE")) {
+ throw DiscordApiErrors.SLOWMODE_RATE_LIMIT;
+ }
+ }
+ }
- const stickers = opts.sticker_ids ? await Sticker.find({ where: { id: In(opts.sticker_ids) } }) : undefined;
- // cloud attachments with indexes
- const cloudAttachments = opts.attachments?.reduce(
- (acc, att, index) => {
- if ("uploaded_filename" in att) {
- acc.push({ attachment: att, index });
- }
- return acc;
- },
- [] as { attachment: MessageCreateCloudAttachment; index: number }[],
- );
+ const stickers = opts.sticker_ids ? await Sticker.find({ where: { id: In(opts.sticker_ids) } }) : undefined;
+ // cloud attachments with indexes
+ const cloudAttachments = opts.attachments?.reduce(
+ (acc, att, index) => {
+ if ("uploaded_filename" in att) {
+ acc.push({ attachment: att, index });
+ }
+ return acc;
+ },
+ [] as { attachment: MessageCreateCloudAttachment; index: number }[],
+ );
- const message = Message.create({
- ...opts,
- poll: opts.poll,
- sticker_items: stickers,
- guild_id: channel.guild_id,
- channel_id: opts.channel_id,
- attachments: opts.attachments || [],
- embeds: opts.embeds || [],
- reactions: opts.reactions || [],
- type: opts.type ?? 0,
- mentions: [],
- components: opts.components ?? undefined, // Fix Discord-Go?
- });
- const ephermal = (message.flags & (1 << 6)) !== 0;
+ const message = Message.create({
+ ...opts,
+ poll: opts.poll,
+ sticker_items: stickers,
+ guild_id: channel.guild_id,
+ channel_id: opts.channel_id,
+ attachments: opts.attachments || [],
+ embeds: opts.embeds || [],
+ reactions: opts.reactions || [],
+ type: opts.type ?? 0,
+ mentions: [],
+ components: opts.components ?? undefined, // Fix Discord-Go?
+ });
+ const ephermal = (message.flags & (1 << 6)) !== 0;
- if (cloudAttachments && cloudAttachments.length > 0) {
- console.log("[Message] Processing attachments for message", message.id, ":", message.attachments);
- const uploadedAttachments = await Promise.all(
- cloudAttachments.map(async (att) => {
- const cAtt = att.attachment;
- const attEnt = await CloudAttachment.findOneOrFail({
- where: {
- uploadFilename: cAtt.uploaded_filename,
- },
- });
+ if (cloudAttachments && cloudAttachments.length > 0) {
+ console.log("[Message] Processing attachments for message", message.id, ":", message.attachments);
+ const uploadedAttachments = await Promise.all(
+ cloudAttachments.map(async (att) => {
+ const cAtt = att.attachment;
+ const attEnt = await CloudAttachment.findOneOrFail({
+ where: {
+ uploadFilename: cAtt.uploaded_filename,
+ },
+ });
- const cloneResponse = await fetch(`${Config.get().cdn.endpointPrivate}/attachments/${attEnt.uploadFilename}/clone_to_message/${message.id}`, {
- method: "POST",
- headers: {
- signature: Config.get().security.requestSignature || "",
- },
- });
+ const cloneResponse = await fetch(`${Config.get().cdn.endpointPrivate}/attachments/${attEnt.uploadFilename}/clone_to_message/${message.id}`, {
+ method: "POST",
+ headers: {
+ signature: Config.get().security.requestSignature || "",
+ },
+ });
- if (!cloneResponse.ok) {
- console.error(`[Message] Failed to clone attachment ${attEnt.userFilename} to message ${message.id}`);
- throw new HTTPError("Failed to process attachment: " + (await cloneResponse.text()), 500);
- }
+ if (!cloneResponse.ok) {
+ console.error(`[Message] Failed to clone attachment ${attEnt.userFilename} to message ${message.id}`);
+ throw new HTTPError("Failed to process attachment: " + (await cloneResponse.text()), 500);
+ }
- const cloneRespBody = (await cloneResponse.json()) as { success: boolean; new_path: string };
+ const cloneRespBody = (await cloneResponse.json()) as { success: boolean; new_path: string };
- const realAtt = Attachment.create({
- filename: attEnt.userFilename,
- url: `${Config.get().cdn.endpointPublic}/${cloneRespBody.new_path}`,
- proxy_url: `${Config.get().cdn.endpointPublic}/${cloneRespBody.new_path}`,
- size: attEnt.size,
- height: attEnt.height,
- width: attEnt.width,
- content_type: attEnt.contentType || attEnt.userOriginalContentType,
- });
- await realAtt.save();
- return { attachment: realAtt, index: att.index };
- }),
- );
- console.log("[Message] Processed attachments for message", message.id, ":", message.attachments);
+ const realAtt = Attachment.create({
+ filename: attEnt.userFilename,
+ url: `${Config.get().cdn.endpointPublic}/${cloneRespBody.new_path}`,
+ proxy_url: `${Config.get().cdn.endpointPublic}/${cloneRespBody.new_path}`,
+ size: attEnt.size,
+ height: attEnt.height,
+ width: attEnt.width,
+ content_type: attEnt.contentType || attEnt.userOriginalContentType,
+ });
+ await realAtt.save();
+ return { attachment: realAtt, index: att.index };
+ }),
+ );
+ console.log("[Message] Processed attachments for message", message.id, ":", message.attachments);
- for (const att of uploadedAttachments) {
- message.attachments![att.index] = att.attachment;
- }
- }
- // else console.log("[Message] No cloud attachments to process for message", message.id, ":", message.attachments);
+ for (const att of uploadedAttachments) {
+ message.attachments![att.index] = att.attachment;
+ }
+ }
+ // else console.log("[Message] No cloud attachments to process for message", message.id, ":", message.attachments);
- if (message.content && message.content.length > Config.get().limits.message.maxCharacters) {
- throw new HTTPError("Content length over max character limit");
- }
+ if (message.content && message.content.length > Config.get().limits.message.maxCharacters) {
+ throw new HTTPError("Content length over max character limit");
+ }
- if (opts.author_id) {
- message.author = await User.getPublicUser(opts.author_id);
- const rights = await getRights(opts.author_id);
- rights.hasThrow("SEND_MESSAGES");
- }
- if (opts.application_id) {
- message.application = await Application.findOneOrFail({
- where: { id: opts.application_id },
- });
- }
+ if (opts.author_id) {
+ message.author = await User.getPublicUser(opts.author_id);
+ const rights = await getRights(opts.author_id);
+ rights.hasThrow("SEND_MESSAGES");
+ }
+ if (opts.application_id) {
+ message.application = await Application.findOneOrFail({
+ where: { id: opts.application_id },
+ });
+ }
- if (opts.webhook_id) {
- message.webhook = await Webhook.findOneOrFail({
- where: { id: opts.webhook_id },
- });
+ if (opts.webhook_id) {
+ message.webhook = await Webhook.findOneOrFail({
+ where: { id: opts.webhook_id },
+ });
- message.author =
- (await User.findOne({
- where: { id: opts.webhook_id },
- })) || undefined;
+ message.author =
+ (await User.findOne({
+ where: { id: opts.webhook_id },
+ })) || undefined;
- if (!message.author) {
- message.author = User.create({
- id: opts.webhook_id,
- username: message.webhook.name,
- discriminator: "0000",
- avatar: message.webhook.avatar,
- public_flags: 0,
- premium: false,
- premium_type: 0,
- bot: true,
- created_at: new Date(),
- verified: true,
- rights: "0",
- data: {
- valid_tokens_since: new Date(),
- },
- });
+ if (!message.author) {
+ message.author = User.create({
+ id: opts.webhook_id,
+ username: message.webhook.name,
+ discriminator: "0000",
+ avatar: message.webhook.avatar,
+ public_flags: 0,
+ premium: false,
+ premium_type: 0,
+ bot: true,
+ created_at: new Date(),
+ verified: true,
+ rights: "0",
+ data: {
+ valid_tokens_since: new Date(),
+ },
+ });
- await message.author.save();
- }
+ await message.author.save();
+ }
- if (opts.username) {
- message.username = opts.username;
- message.author.username = message.username;
- }
- if (opts.avatar_url) {
- const avatarData = await fetch(opts.avatar_url);
- const base64 = await avatarData.arrayBuffer().then((x) => Buffer.from(x).toString("base64"));
+ if (opts.username) {
+ message.username = opts.username;
+ message.author.username = message.username;
+ }
+ if (opts.avatar_url) {
+ const avatarData = await fetch(opts.avatar_url);
+ const base64 = await avatarData.arrayBuffer().then((x) => Buffer.from(x).toString("base64"));
- const dataUri = "data:" + avatarData.headers.get("content-type") + ";base64," + base64;
+ const dataUri = "data:" + avatarData.headers.get("content-type") + ";base64," + base64;
- message.avatar = await handleFile(`/avatars/${opts.webhook_id}`, dataUri as string);
- message.author.avatar = message.avatar;
- }
- } else {
- permission ||= await getPermission(opts.author_id, channel.guild_id, channel);
- permission.hasThrow("SEND_MESSAGES");
- if (permission.cache.member) {
- message.member = permission.cache.member;
- }
+ message.avatar = await handleFile(`/avatars/${opts.webhook_id}`, dataUri as string);
+ message.author.avatar = message.avatar;
+ }
+ } else {
+ permission ||= await getPermission(opts.author_id, channel.guild_id, channel);
+ permission.hasThrow("SEND_MESSAGES");
+ if (permission.cache.member) {
+ message.member = permission.cache.member;
+ }
- if (opts.tts) permission.hasThrow("SEND_TTS_MESSAGES");
- if (opts.message_reference) {
- permission.hasThrow("READ_MESSAGE_HISTORY");
- // code below has to be redone when we add custom message routing
- if (message.guild_id !== null) {
- const guild = await Guild.findOneOrFail({
- where: { id: channel.guild_id },
- });
- if (!opts.message_reference.guild_id) opts.message_reference.guild_id = channel.guild_id;
- if (!opts.message_reference.channel_id) opts.message_reference.channel_id = opts.channel_id;
+ if (opts.tts) permission.hasThrow("SEND_TTS_MESSAGES");
+ if (opts.message_reference) {
+ permission.hasThrow("READ_MESSAGE_HISTORY");
+ // code below has to be redone when we add custom message routing
+ if (message.guild_id !== null) {
+ const guild = await Guild.findOneOrFail({
+ where: { id: channel.guild_id },
+ });
+ if (!opts.message_reference.guild_id) opts.message_reference.guild_id = channel.guild_id;
+ if (!opts.message_reference.channel_id) opts.message_reference.channel_id = opts.channel_id;
- if (!guild.features.includes("CROSS_CHANNEL_REPLIES")) {
- if (opts.message_reference.guild_id !== channel.guild_id) throw new HTTPError("You can only reference messages from this guild");
- if (opts.message_reference.channel_id !== opts.channel_id) throw new HTTPError("You can only reference messages from this channel");
- }
+ if (!guild.features.includes("CROSS_CHANNEL_REPLIES")) {
+ if (opts.message_reference.guild_id !== channel.guild_id) throw new HTTPError("You can only reference messages from this guild");
+ if (opts.message_reference.channel_id !== opts.channel_id) throw new HTTPError("You can only reference messages from this channel");
+ }
- message.message_reference = opts.message_reference;
- message.referenced_message = await Message.findOneOrFail({
- where: {
- id: opts.message_reference.message_id,
- },
- relations: ["author", "webhook", "application", "mentions", "mention_roles", "mention_channels", "sticker_items", "attachments"],
- });
+ message.message_reference = opts.message_reference;
+ message.referenced_message = await Message.findOneOrFail({
+ where: {
+ id: opts.message_reference.message_id,
+ },
+ relations: ["author", "webhook", "application", "mentions", "mention_roles", "mention_channels", "sticker_items", "attachments"],
+ });
- if (message.referenced_message.channel_id && message.referenced_message.channel_id !== opts.message_reference.channel_id)
- throw new HTTPError("Referenced message not found in the specified channel", 404);
- if (message.referenced_message.guild_id && message.referenced_message.guild_id !== opts.message_reference.guild_id)
- throw new HTTPError("Referenced message not found in the specified channel", 404);
- }
- /** Q: should be checked if the referenced message exists? ANSWER: NO
+ if (message.referenced_message.channel_id && message.referenced_message.channel_id !== opts.message_reference.channel_id)
+ throw new HTTPError("Referenced message not found in the specified channel", 404);
+ if (message.referenced_message.guild_id && message.referenced_message.guild_id !== opts.message_reference.guild_id)
+ throw new HTTPError("Referenced message not found in the specified channel", 404);
+ }
+ /** Q: should be checked if the referenced message exists? ANSWER: NO
otherwise backfilling won't work **/
- message.type = MessageType.REPLY;
- }
- }
+ message.type = MessageType.REPLY;
+ }
+ }
- // TODO: stickers/activity
- if (!allow_empty && !opts.content && !opts.embeds?.length && !opts.attachments?.length && !opts.sticker_ids?.length && !opts.poll && !opts.components?.length) {
- console.log("[Message] Rejecting empty message:", opts, message);
- throw new HTTPError("Empty messages are not allowed", 50006);
- }
+ // TODO: stickers/activity
+ if (!allow_empty && !opts.content && !opts.embeds?.length && !opts.attachments?.length && !opts.sticker_ids?.length && !opts.poll && !opts.components?.length) {
+ console.log("[Message] Rejecting empty message:", opts, message);
+ throw new HTTPError("Empty messages are not allowed", 50006);
+ }
- let content = opts.content;
+ let content = opts.content;
- // root@Rory - 20/02/2023 - This breaks channel mentions in test client. We're not sure this was used in older clients.
- //const mention_channel_ids = [] as string[];
- const mention_role_ids = [] as string[];
- const mention_user_ids = [] as string[];
- let mention_everyone = false;
+ // root@Rory - 20/02/2023 - This breaks channel mentions in test client. We're not sure this was used in older clients.
+ //const mention_channel_ids = [] as string[];
+ const mention_role_ids = [] as string[];
+ const mention_user_ids = [] as string[];
+ let mention_everyone = false;
- if (content) {
- // TODO: explicit-only mentions
- message.content = content.trim();
- content = content.replace(/ *`[^)]*` */g, ""); // remove codeblocks
- // root@Rory - 20/02/2023 - This breaks channel mentions in test client. We're not sure this was used in older clients.
- /*for (const [, mention] of content.matchAll(CHANNEL_MENTION)) {
+ if (content) {
+ // TODO: explicit-only mentions
+ message.content = content.trim();
+ content = content.replace(/ *`[^)]*` */g, ""); // remove codeblocks
+ // root@Rory - 20/02/2023 - This breaks channel mentions in test client. We're not sure this was used in older clients.
+ /*for (const [, mention] of content.matchAll(CHANNEL_MENTION)) {
if (!mention_channel_ids.includes(mention))
mention_channel_ids.push(mention);
}*/
- for (const [, mention] of content.matchAll(USER_MENTION)) {
- if (!mention_user_ids.includes(mention)) mention_user_ids.push(mention);
- }
+ for (const [, mention] of content.matchAll(USER_MENTION)) {
+ if (!mention_user_ids.includes(mention)) mention_user_ids.push(mention);
+ }
- await Promise.all(
- Array.from(content.matchAll(ROLE_MENTION)).map(async ([, mention]) => {
- const role = await Role.findOneOrFail({
- where: { id: mention, guild_id: channel.guild_id },
- });
- if (role.mentionable || opts.webhook_id || permission?.has("MANAGE_ROLES")) {
- mention_role_ids.push(mention);
- }
- }),
- );
+ await Promise.all(
+ Array.from(content.matchAll(ROLE_MENTION)).map(async ([, mention]) => {
+ const role = await Role.findOneOrFail({
+ where: { id: mention, guild_id: channel.guild_id },
+ });
+ if (role.mentionable || opts.webhook_id || permission?.has("MANAGE_ROLES")) {
+ mention_role_ids.push(mention);
+ }
+ }),
+ );
- if (opts.webhook_id || permission?.has("MENTION_EVERYONE")) {
- mention_everyone = !!content.match(EVERYONE_MENTION) || !!content.match(HERE_MENTION);
- }
- }
+ if (opts.webhook_id || permission?.has("MENTION_EVERYONE")) {
+ mention_everyone = !!content.match(EVERYONE_MENTION) || !!content.match(HERE_MENTION);
+ }
+ }
- if (message.message_reference?.message_id) {
- const referencedMessage = await Message.findOne({
- where: {
- id: message.message_reference.message_id,
- channel_id: message.channel_id,
- },
- });
- if (referencedMessage && referencedMessage.author_id !== message.author_id) {
- message.mentions.push(
- User.create({
- id: referencedMessage.author_id,
- }),
- );
- }
- }
+ if (message.message_reference?.message_id) {
+ const referencedMessage = await Message.findOne({
+ where: {
+ id: message.message_reference.message_id,
+ channel_id: message.channel_id,
+ },
+ });
+ if (referencedMessage && referencedMessage.author_id !== message.author_id) {
+ message.mentions.push(
+ User.create({
+ id: referencedMessage.author_id,
+ }),
+ );
+ }
+ }
- // root@Rory - 20/02/2023 - This breaks channel mentions in test client. We're not sure this was used in older clients.
- /*message.mention_channels = mention_channel_ids.map((x) =>
+ // root@Rory - 20/02/2023 - This breaks channel mentions in test client. We're not sure this was used in older clients.
+ /*message.mention_channels = mention_channel_ids.map((x) =>
Channel.create({ id: x }),
);*/
- message.mention_roles = (
- await Promise.all(
- mention_role_ids.map((x) => {
- return Role.findOne({ where: { id: x } });
- }),
- )
- ).filter((role) => role !== null);
+ message.mention_roles = (
+ await Promise.all(
+ mention_role_ids.map((x) => {
+ return Role.findOne({ where: { id: x } });
+ }),
+ )
+ ).filter((role) => role !== null);
- message.mentions = [
- ...message.mentions,
- ...(
- await Promise.all(
- mention_user_ids.map((x) => {
- return User.findOne({ where: { id: x } });
- }),
- )
- ).filter((user) => user !== null),
- ];
+ message.mentions = [
+ ...message.mentions,
+ ...(
+ await Promise.all(
+ mention_user_ids.map((x) => {
+ return User.findOne({ where: { id: x } });
+ }),
+ )
+ ).filter((user) => user !== null),
+ ];
- message.mention_everyone = mention_everyone;
- async function fillInMissingIDs(ids: string[]) {
- const states = await ReadState.findBy({
- user_id: Or(...ids.map((id) => Equal(id))),
- channel_id: channel.id,
- });
- const users = new Set(ids);
- states.forEach((state) => users.delete(state.user_id));
- if (!users.size) {
- return;
- }
- return Promise.all(
- [...users].map((user_id) => {
- return ReadState.create({ user_id, channel_id: channel.id }).save();
- }),
- );
- }
- if (ephermal) {
- const id = message.interaction_metadata?.user_id;
- if (id) {
- let pinged = mention_everyone || channel.type === ChannelType.DM || channel.type === ChannelType.GROUP_DM;
- if (!pinged) pinged = !!message.mentions.find((user) => user.id === id);
- if (!pinged) pinged = !!(await Member.find({ where: { id, roles: Or(...message.mention_roles.map(({ id }) => Equal(id))) } }));
- if (pinged) {
- //stuff
- }
- }
- } else if ((!!message.content?.match(EVERYONE_MENTION) && permission?.has("MENTION_EVERYONE")) || channel.type === ChannelType.DM || channel.type === ChannelType.GROUP_DM) {
- if (channel.type === ChannelType.DM || channel.type === ChannelType.GROUP_DM) {
- if (channel.recipients) {
- await fillInMissingIDs(channel.recipients.map(({ user_id }) => user_id));
- }
- } else {
- console.log(channel.guild_id);
- await fillInMissingIDs((await Member.find({ where: { guild_id: channel.guild_id } })).map(({ id }) => id));
- }
- const repository = ReadState.getRepository();
- const condition = { channel_id: channel.id };
- await repository.update({ ...condition, mention_count: IsNull() }, { mention_count: 0 });
- await repository.increment(condition, "mention_count", 1);
- } else {
- const users = new Set([
- ...(message.mention_roles.length
- ? await Member.find({
- where: [
- ...message.mention_roles.map((role) => {
- return { roles: { id: role.id } };
- }),
- ],
- })
- : []
- ).map((member) => member.id),
- ...message.mentions.map((user) => user.id),
- ]);
- if (!!message.content?.match(HERE_MENTION) && permission?.has("MENTION_EVERYONE")) {
- const ids = (await Member.find({ where: { guild_id: channel.guild_id } })).map(({ id }) => id);
- (await Session.find({ where: { user_id: Or(...ids.map((id) => Equal(id))) } })).forEach(({ user_id }) => users.add(user_id));
- }
- if (users.size) {
- const repository = ReadState.getRepository();
- const condition = { user_id: Or(...[...users].map((id) => Equal(id))), channel_id: channel.id };
+ message.mention_everyone = mention_everyone;
+ async function fillInMissingIDs(ids: string[]) {
+ const states = await ReadState.findBy({
+ user_id: Or(...ids.map((id) => Equal(id))),
+ channel_id: channel.id,
+ });
+ const users = new Set(ids);
+ states.forEach((state) => users.delete(state.user_id));
+ if (!users.size) {
+ return;
+ }
+ return Promise.all(
+ [...users].map((user_id) => {
+ return ReadState.create({ user_id, channel_id: channel.id }).save();
+ }),
+ );
+ }
+ if (ephermal) {
+ const id = message.interaction_metadata?.user_id;
+ if (id) {
+ let pinged = mention_everyone || channel.type === ChannelType.DM || channel.type === ChannelType.GROUP_DM;
+ if (!pinged) pinged = !!message.mentions.find((user) => user.id === id);
+ if (!pinged) pinged = !!(await Member.find({ where: { id, roles: Or(...message.mention_roles.map(({ id }) => Equal(id))) } }));
+ if (pinged) {
+ //stuff
+ }
+ }
+ } else if ((!!message.content?.match(EVERYONE_MENTION) && permission?.has("MENTION_EVERYONE")) || channel.type === ChannelType.DM || channel.type === ChannelType.GROUP_DM) {
+ if (channel.type === ChannelType.DM || channel.type === ChannelType.GROUP_DM) {
+ if (channel.recipients) {
+ await fillInMissingIDs(channel.recipients.map(({ user_id }) => user_id));
+ }
+ } else {
+ console.log(channel.guild_id);
+ await fillInMissingIDs((await Member.find({ where: { guild_id: channel.guild_id } })).map(({ id }) => id));
+ }
+ const repository = ReadState.getRepository();
+ const condition = { channel_id: channel.id };
+ await repository.update({ ...condition, mention_count: IsNull() }, { mention_count: 0 });
+ await repository.increment(condition, "mention_count", 1);
+ } else {
+ const users = new Set([
+ ...(message.mention_roles.length
+ ? await Member.find({
+ where: [
+ ...message.mention_roles.map((role) => {
+ return { roles: { id: role.id } };
+ }),
+ ],
+ })
+ : []
+ ).map((member) => member.id),
+ ...message.mentions.map((user) => user.id),
+ ]);
+ if (!!message.content?.match(HERE_MENTION) && permission?.has("MENTION_EVERYONE")) {
+ const ids = (await Member.find({ where: { guild_id: channel.guild_id } })).map(({ id }) => id);
+ (await Session.find({ where: { user_id: Or(...ids.map((id) => Equal(id))) } })).forEach(({ user_id }) => users.add(user_id));
+ }
+ if (users.size) {
+ const repository = ReadState.getRepository();
+ const condition = { user_id: Or(...[...users].map((id) => Equal(id))), channel_id: channel.id };
- await fillInMissingIDs([...users]);
+ await fillInMissingIDs([...users]);
- await repository.update({ ...condition, mention_count: IsNull() }, { mention_count: 0 });
- await repository.increment(condition, "mention_count", 1);
- }
- }
+ await repository.update({ ...condition, mention_count: IsNull() }, { mention_count: 0 });
+ await repository.increment(condition, "mention_count", 1);
+ }
+ }
- // TODO: check and put it all in the body
+ // TODO: check and put it all in the body
- return message;
+ return message;
}
// TODO: cache link result in db
export async function postHandleMessage(message: Message) {
- const content = message.content?.replace(/ *`[^)]*` */g, ""); // remove markdown
+ const content = message.content?.replace(/ *`[^)]*` */g, ""); // remove markdown
- const linkMatches = content?.match(LINK_REGEX) || [];
+ const linkMatches = content?.match(LINK_REGEX) || [];
- const data = { ...message };
+ const data = { ...message };
- const currentNormalizedUrls = new Set();
- for (const link of linkMatches) {
- // Don't process links in <>
- if (link.startsWith("<") && link.endsWith(">")) {
- continue;
- }
- try {
- const normalized = normalizeUrl(link);
- currentNormalizedUrls.add(normalized);
- } catch (e) {
- continue;
- }
- }
+ const currentNormalizedUrls = new Set();
+ for (const link of linkMatches) {
+ // Don't process links in <>
+ if (link.startsWith("<") && link.endsWith(">")) {
+ continue;
+ }
+ try {
+ const normalized = normalizeUrl(link);
+ currentNormalizedUrls.add(normalized);
+ } catch (e) {
+ continue;
+ }
+ }
- data.embeds.forEach((embed) => {
- if (!embed.type) {
- embed.type = EmbedType.rich;
- }
- });
- // Filter out embeds that could be links, start from scratch
- data.embeds = data.embeds.filter((embed) => embed.type === "rich");
+ data.embeds.forEach((embed) => {
+ if (!embed.type) {
+ embed.type = EmbedType.rich;
+ }
+ });
+ // Filter out embeds that could be links, start from scratch
+ data.embeds = data.embeds.filter((embed) => embed.type === "rich");
- const seenNormalizedUrls = new Set();
- const uniqueLinks: string[] = [];
+ const seenNormalizedUrls = new Set();
+ const uniqueLinks: string[] = [];
- for (const link of linkMatches.slice(0, 20)) {
- // embed max 20 links - TODO: make this configurable with instance policies
- // Don't embed links in <>
- if (link.startsWith("<") && link.endsWith(">")) continue;
+ for (const link of linkMatches.slice(0, 20)) {
+ // embed max 20 links - TODO: make this configurable with instance policies
+ // Don't embed links in <>
+ if (link.startsWith("<") && link.endsWith(">")) continue;
- try {
- const normalized = normalizeUrl(link);
+ try {
+ const normalized = normalizeUrl(link);
- if (!seenNormalizedUrls.has(normalized)) {
- seenNormalizedUrls.add(normalized);
- uniqueLinks.push(link);
- }
- } catch (e) {
- // Invalid URL, skip
- continue;
- }
- }
+ if (!seenNormalizedUrls.has(normalized)) {
+ seenNormalizedUrls.add(normalized);
+ uniqueLinks.push(link);
+ }
+ } catch (e) {
+ // Invalid URL, skip
+ continue;
+ }
+ }
- if (uniqueLinks.length === 0) {
- // No valid unique links found, update message to remove old embeds
- data.embeds = data.embeds.filter((embed) => embed.type === "rich");
- const author = data.author?.toPublicUser();
- const event = {
- event: "MESSAGE_UPDATE",
- channel_id: message.channel_id,
- data: {
- ...data,
- author,
- },
- } as MessageUpdateEvent;
- await Promise.all([emitEvent(event), Message.update({ id: message.id, channel_id: message.channel_id }, { embeds: data.embeds })]);
- return;
- }
+ if (uniqueLinks.length === 0) {
+ // No valid unique links found, update message to remove old embeds
+ data.embeds = data.embeds.filter((embed) => embed.type === "rich");
+ const author = data.author?.toPublicUser();
+ const event = {
+ event: "MESSAGE_UPDATE",
+ channel_id: message.channel_id,
+ data: {
+ ...data,
+ author,
+ },
+ } as MessageUpdateEvent;
+ await Promise.all([emitEvent(event), Message.update({ id: message.id, channel_id: message.channel_id }, { embeds: data.embeds })]);
+ return;
+ }
- const cachePromises = [];
+ const cachePromises = [];
- for (const link of uniqueLinks) {
- let url: URL;
- try {
- url = new URL(link);
- } catch (e) {
- // Skip invalid URLs
- continue;
- }
+ for (const link of uniqueLinks) {
+ let url: URL;
+ try {
+ url = new URL(link);
+ } catch (e) {
+ // Skip invalid URLs
+ continue;
+ }
- const normalizedUrl = normalizeUrl(link);
+ const normalizedUrl = normalizeUrl(link);
- // Check cache using normalized URL
- const cached = await EmbedCache.findOne({
- where: { url: normalizedUrl },
- });
+ // Check cache using normalized URL
+ const cached = await EmbedCache.findOne({
+ where: { url: normalizedUrl },
+ });
- if (cached) {
- data.embeds.push(cached.embed);
- continue;
- }
+ if (cached) {
+ data.embeds.push(cached.embed);
+ continue;
+ }
- // bit gross, but whatever!
- const endpointPublic = Config.get().cdn.endpointPublic; // lol
- const handler = url.hostname === new URL(endpointPublic!).hostname ? EmbedHandlers["self"] : EmbedHandlers[url.hostname] || EmbedHandlers["default"];
+ // bit gross, but whatever!
+ const endpointPublic = Config.get().cdn.endpointPublic; // lol
+ const handler = url.hostname === new URL(endpointPublic!).hostname ? EmbedHandlers["self"] : EmbedHandlers[url.hostname] || EmbedHandlers["default"];
- try {
- let res = await handler(url);
- if (!res) continue;
- // tried to use shorthand but types didn't like me L
- if (!Array.isArray(res)) res = [res];
+ try {
+ let res = await handler(url);
+ if (!res) continue;
+ // tried to use shorthand but types didn't like me L
+ if (!Array.isArray(res)) res = [res];
- for (const embed of res) {
- // Cache with normalized URL
- const cache = EmbedCache.create({
- url: normalizedUrl,
- embed: embed,
- });
- cachePromises.push(cache.save());
- data.embeds.push(embed);
- }
- } catch (e) {
- console.error(`[Embeds] Error while generating embed for ${link}`, e);
- }
- }
+ for (const embed of res) {
+ // Cache with normalized URL
+ const cache = EmbedCache.create({
+ url: normalizedUrl,
+ embed: embed,
+ });
+ cachePromises.push(cache.save());
+ data.embeds.push(embed);
+ }
+ } catch (e) {
+ console.error(`[Embeds] Error while generating embed for ${link}`, e);
+ }
+ }
- await Promise.all([
- emitEvent({
- event: "MESSAGE_UPDATE",
- channel_id: message.channel_id,
- data,
- } as MessageUpdateEvent),
- Message.update({ id: message.id, channel_id: message.channel_id }, { embeds: data.embeds }),
- ...cachePromises,
- ]);
+ await Promise.all([
+ emitEvent({
+ event: "MESSAGE_UPDATE",
+ channel_id: message.channel_id,
+ data,
+ } as MessageUpdateEvent),
+ Message.update({ id: message.id, channel_id: message.channel_id }, { embeds: data.embeds }),
+ ...cachePromises,
+ ]);
}
export async function sendMessage(opts: MessageOptions) {
- const message = await handleMessage({ ...opts, timestamp: new Date() });
+ const message = await handleMessage({ ...opts, timestamp: new Date() });
- const ephemeral = (message.flags & Number(MessageFlags.FLAGS.EPHEMERAL)) !== 0;
- await Promise.all([
- Message.insert(message),
- emitEvent({
- event: "MESSAGE_CREATE",
- ...(ephemeral ? { user_id: message.interaction_metadata?.user_id } : { channel_id: message.channel_id }),
- data: message.toJSON(),
- } as MessageCreateEvent),
- ]);
+ const ephemeral = (message.flags & Number(MessageFlags.FLAGS.EPHEMERAL)) !== 0;
+ await Promise.all([
+ Message.insert(message),
+ emitEvent({
+ event: "MESSAGE_CREATE",
+ ...(ephemeral ? { user_id: message.interaction_metadata?.user_id } : { channel_id: message.channel_id }),
+ data: message.toJSON(),
+ } as MessageCreateEvent),
+ ]);
- // no await as it should catch error non-blockingly
- postHandleMessage(message).catch((e) => console.error("[Message] post-message handler failed", e));
+ // no await as it should catch error non-blockingly
+ postHandleMessage(message).catch((e) => console.error("[Message] post-message handler failed", e));
- return message;
+ return message;
}
interface MessageOptions extends MessageCreateSchema {
- id?: string;
- type?: MessageType;
- pinned?: boolean;
- author_id?: string;
- webhook_id?: string;
- application_id?: string;
- embeds?: Embed[];
- reactions?: Reaction[];
- channel_id?: string;
- attachments?: (MessageCreateAttachment | MessageCreateCloudAttachment | Attachment)[]; // why are we masking this?
- edited_timestamp?: Date;
- timestamp?: Date;
- username?: string;
- avatar_url?: string;
+ id?: string;
+ type?: MessageType;
+ pinned?: boolean;
+ author_id?: string;
+ webhook_id?: string;
+ application_id?: string;
+ embeds?: Embed[];
+ reactions?: Reaction[];
+ channel_id?: string;
+ attachments?: (MessageCreateAttachment | MessageCreateCloudAttachment | Attachment)[]; // why are we masking this?
+ edited_timestamp?: Date;
+ timestamp?: Date;
+ username?: string;
+ avatar_url?: string;
}
diff --git a/src/api/util/handlers/Voice.ts b/src/api/util/handlers/Voice.ts
index e34b679..409338f 100644
--- a/src/api/util/handlers/Voice.ts
+++ b/src/api/util/handlers/Voice.ts
@@ -20,31 +20,31 @@
import { distanceBetweenLocations } from "../utility/ipAddress";
export async function getVoiceRegions(ipAddress: string, vip: boolean) {
- const regions = Config.get().regions;
- const availableRegions = regions.available.filter((ar) => (vip ? true : !ar.vip));
- let optimalId = regions.default;
+ const regions = Config.get().regions;
+ const availableRegions = regions.available.filter((ar) => (vip ? true : !ar.vip));
+ let optimalId = regions.default;
- if (!regions.useDefaultAsOptimal) {
- const clientIpAnalysis = await IpDataClient.getIpInfo(ipAddress);
+ if (!regions.useDefaultAsOptimal) {
+ const clientIpAnalysis = await IpDataClient.getIpInfo(ipAddress);
- let min = Number.POSITIVE_INFINITY;
+ let min = Number.POSITIVE_INFINITY;
- for (const ar of availableRegions) {
- //TODO the endpoint location should be saved in the database if not already present to prevent IPAnalysis call
- const dist = distanceBetweenLocations(clientIpAnalysis!, ar.location || (await IpDataClient.getIpInfo(ar.endpoint))!);
+ for (const ar of availableRegions) {
+ //TODO the endpoint location should be saved in the database if not already present to prevent IPAnalysis call
+ const dist = distanceBetweenLocations(clientIpAnalysis!, ar.location || (await IpDataClient.getIpInfo(ar.endpoint))!);
- if (dist < min) {
- min = dist;
- optimalId = ar.id;
- }
- }
- }
+ if (dist < min) {
+ min = dist;
+ optimalId = ar.id;
+ }
+ }
+ }
- return availableRegions.map((ar) => ({
- id: ar.id,
- name: ar.name,
- custom: ar.custom,
- deprecated: ar.deprecated,
- optimal: ar.id === optimalId,
- }));
+ return availableRegions.map((ar) => ({
+ id: ar.id,
+ name: ar.name,
+ custom: ar.custom,
+ deprecated: ar.deprecated,
+ optimal: ar.id === optimalId,
+ }));
}
diff --git a/src/api/util/handlers/Webhook.ts b/src/api/util/handlers/Webhook.ts
index 54ef26e..cd0f2f6 100644
--- a/src/api/util/handlers/Webhook.ts
+++ b/src/api/util/handlers/Webhook.ts
@@ -6,118 +6,118 @@
import { WebhookExecuteSchema } from "@spacebar/schemas";
export const executeWebhook = async (req: Request, res: Response) => {
- const body = req.body as WebhookExecuteSchema;
+ const body = req.body as WebhookExecuteSchema;
- const { webhook_id, token } = req.params;
+ const { webhook_id, token } = req.params;
- const webhook = await Webhook.findOne({
- where: {
- id: webhook_id,
- },
- relations: ["channel", "guild", "application"],
- });
+ const webhook = await Webhook.findOne({
+ where: {
+ id: webhook_id,
+ },
+ relations: ["channel", "guild", "application"],
+ });
- if (!webhook) {
- throw DiscordApiErrors.UNKNOWN_WEBHOOK;
- }
+ if (!webhook) {
+ throw DiscordApiErrors.UNKNOWN_WEBHOOK;
+ }
- if (webhook.token !== token) {
- throw DiscordApiErrors.INVALID_WEBHOOK_TOKEN_PROVIDED;
- }
+ if (webhook.token !== token) {
+ throw DiscordApiErrors.INVALID_WEBHOOK_TOKEN_PROVIDED;
+ }
- if (body.username) {
- ValidateName(body.username);
- }
+ if (body.username) {
+ ValidateName(body.username);
+ }
- // ensure one of content, embeds, components, or file is present
- if (!body.content && !body.embeds && !body.components && !body.file && !body.attachments) {
- throw DiscordApiErrors.CANNOT_SEND_EMPTY_MESSAGE;
- }
+ // ensure one of content, embeds, components, or file is present
+ if (!body.content && !body.embeds && !body.components && !body.file && !body.attachments) {
+ throw DiscordApiErrors.CANNOT_SEND_EMPTY_MESSAGE;
+ }
- const wait = req.query.wait === "true";
+ const wait = req.query.wait === "true";
- if (!wait) {
- res.status(204).send();
- }
+ if (!wait) {
+ res.status(204).send();
+ }
- const attachments: Attachment[] = [];
+ const attachments: Attachment[] = [];
- if (!webhook.channel.isWritable()) {
- if (wait) {
- throw new HTTPError(`Cannot send messages to channel of type ${webhook.channel.type}`, 400);
- } else {
- return;
- }
- }
+ if (!webhook.channel.isWritable()) {
+ if (wait) {
+ throw new HTTPError(`Cannot send messages to channel of type ${webhook.channel.type}`, 400);
+ } else {
+ return;
+ }
+ }
- // TODO: creating messages by users checks if the user can bypass rate limits, we cant do that on webhooks, but maybe we could check the application if there is one?
- const limits = Config.get().limits;
- if (limits.absoluteRate.register.enabled) {
- const count = await Message.count({
- where: {
- channel_id: webhook.channel_id,
- timestamp: MoreThan(new Date(Date.now() - limits.absoluteRate.sendMessage.window)),
- },
- });
+ // TODO: creating messages by users checks if the user can bypass rate limits, we cant do that on webhooks, but maybe we could check the application if there is one?
+ const limits = Config.get().limits;
+ if (limits.absoluteRate.register.enabled) {
+ const count = await Message.count({
+ where: {
+ channel_id: webhook.channel_id,
+ timestamp: MoreThan(new Date(Date.now() - limits.absoluteRate.sendMessage.window)),
+ },
+ });
- if (count >= limits.absoluteRate.sendMessage.limit)
- if (wait) {
- throw FieldErrors({
- channel_id: {
- code: "TOO_MANY_MESSAGES",
- message: req.t("common:toomany.MESSAGE"),
- },
- });
- } else {
- return;
- }
- }
+ if (count >= limits.absoluteRate.sendMessage.limit)
+ if (wait) {
+ throw FieldErrors({
+ channel_id: {
+ code: "TOO_MANY_MESSAGES",
+ message: req.t("common:toomany.MESSAGE"),
+ },
+ });
+ } else {
+ return;
+ }
+ }
- const files = (req.files as Express.Multer.File[]) ?? [];
- for (const currFile of files) {
- try {
- const file = await uploadFile(`/attachments/${webhook.channel.id}`, currFile);
- attachments.push(Attachment.create({ ...file, proxy_url: file.url }));
- } catch (error) {
- if (wait) res.status(400).json({ message: error?.toString() });
- return;
- }
- }
+ const files = (req.files as Express.Multer.File[]) ?? [];
+ for (const currFile of files) {
+ try {
+ const file = await uploadFile(`/attachments/${webhook.channel.id}`, currFile);
+ attachments.push(Attachment.create({ ...file, proxy_url: file.url }));
+ } catch (error) {
+ if (wait) res.status(400).json({ message: error?.toString() });
+ return;
+ }
+ }
- const embeds = body.embeds || [];
- const message = await handleMessage({
- ...body,
- username: body.username || webhook.name,
- avatar_url: body.avatar_url || webhook.avatar,
- type: 0,
- pinned: false,
- webhook_id: webhook.id,
- application_id: webhook.application?.id,
- embeds,
- // TODO: Support thread_id/thread_name once threads are implemented
- channel_id: webhook.channel_id,
- attachments,
- timestamp: new Date(),
- });
+ const embeds = body.embeds || [];
+ const message = await handleMessage({
+ ...body,
+ username: body.username || webhook.name,
+ avatar_url: body.avatar_url || webhook.avatar,
+ type: 0,
+ pinned: false,
+ webhook_id: webhook.id,
+ application_id: webhook.application?.id,
+ embeds,
+ // TODO: Support thread_id/thread_name once threads are implemented
+ channel_id: webhook.channel_id,
+ attachments,
+ timestamp: new Date(),
+ });
- // eslint-disable-next-line @typescript-eslint/ban-ts-comment
- //@ts-ignore dont care2
- message.edited_timestamp = null;
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ //@ts-ignore dont care2
+ message.edited_timestamp = null;
- webhook.channel.last_message_id = message.id;
+ webhook.channel.last_message_id = message.id;
- await Promise.all([
- message.save(),
- webhook.channel.save(),
- emitEvent({
- event: "MESSAGE_CREATE",
- channel_id: webhook.channel_id,
- data: message,
- } as MessageCreateEvent),
- ]);
+ await Promise.all([
+ message.save(),
+ webhook.channel.save(),
+ emitEvent({
+ event: "MESSAGE_CREATE",
+ channel_id: webhook.channel_id,
+ data: message,
+ } as MessageCreateEvent),
+ ]);
- // no await as it shouldnt block the message send function and silently catch error
- postHandleMessage(message).catch((e) => console.error("[Message] post-message handler failed", e));
- if (wait) res.json(message);
- return;
+ // no await as it shouldnt block the message send function and silently catch error
+ postHandleMessage(message).catch((e) => console.error("[Message] post-message handler failed", e));
+ if (wait) res.json(message);
+ return;
};
diff --git a/src/api/util/handlers/route.ts b/src/api/util/handlers/route.ts
index bb38c53..7ae00a5 100644
--- a/src/api/util/handlers/route.ts
+++ b/src/api/util/handlers/route.ts
@@ -22,107 +22,107 @@
import { ajv } from "@spacebar/schemas";
const ignoredRequestSchemas = [
- // skip validation for settings proto JSON updates - TODO: figure out if this even possible to fix?
- "SettingsProtoUpdateJsonSchema",
+ // skip validation for settings proto JSON updates - TODO: figure out if this even possible to fix?
+ "SettingsProtoUpdateJsonSchema",
];
declare global {
- // TODO: fix this
- // eslint-disable-next-line @typescript-eslint/no-namespace
- namespace Express {
- interface Request {
- permission?: Permissions;
- }
- }
+ // TODO: fix this
+ // eslint-disable-next-line @typescript-eslint/no-namespace
+ namespace Express {
+ interface Request {
+ permission?: Permissions;
+ }
+ }
}
export type RouteResponse = {
- status?: number;
- body?: `${string}Response`;
- headers?: Record;
+ status?: number;
+ body?: `${string}Response`;
+ headers?: Record;
};
export interface RouteOptions {
- permission?: PermissionResolvable;
- right?: RightResolvable;
- requestBody?: `${string}Schema`; // typescript interface name
- responses?: {
- [status: number]: {
- // body?: `${string}Response`;
- body?: string;
- };
- };
- event?: EVENT | EVENT[];
- summary?: string;
- description?: string;
- query?: {
- [key: string]: {
- type: string;
- required?: boolean;
- description?: string;
- values?: string[];
- };
- };
- deprecated?: boolean;
- // test?: {
- // response?: RouteResponse;
- // body?: unknown;
- // path?: string;
- // event?: EVENT | EVENT[];
- // headers?: Record;
- // };
+ permission?: PermissionResolvable;
+ right?: RightResolvable;
+ requestBody?: `${string}Schema`; // typescript interface name
+ responses?: {
+ [status: number]: {
+ // body?: `${string}Response`;
+ body?: string;
+ };
+ };
+ event?: EVENT | EVENT[];
+ summary?: string;
+ description?: string;
+ query?: {
+ [key: string]: {
+ type: string;
+ required?: boolean;
+ description?: string;
+ values?: string[];
+ };
+ };
+ deprecated?: boolean;
+ // test?: {
+ // response?: RouteResponse;
+ // body?: unknown;
+ // path?: string;
+ // event?: EVENT | EVENT[];
+ // headers?: Record;
+ // };
}
export function route(opts: RouteOptions) {
- let validate: AnyValidateFunction | undefined;
- if (opts.requestBody) {
- try {
- validate = ajv.getSchema(opts.requestBody);
- } catch (e) {
- console.error("AJV getSchema failed!");
- throw e;
- }
+ let validate: AnyValidateFunction | undefined;
+ if (opts.requestBody) {
+ try {
+ validate = ajv.getSchema(opts.requestBody);
+ } catch (e) {
+ console.error("AJV getSchema failed!");
+ throw e;
+ }
- if (!validate) throw new Error(`Body schema ${opts.requestBody} not found`);
- }
+ if (!validate) throw new Error(`Body schema ${opts.requestBody} not found`);
+ }
- return async (req: Request, res: Response, next: NextFunction) => {
- if (opts.permission) {
- req.permission = await getPermission(req.user_id, req.params.guild_id, req.params.channel_id);
+ return async (req: Request, res: Response, next: NextFunction) => {
+ if (opts.permission) {
+ req.permission = await getPermission(req.user_id, req.params.guild_id, req.params.channel_id);
- const requiredPerms = Array.isArray(opts.permission) ? opts.permission : [opts.permission];
- requiredPerms.forEach((perm) => {
- // bitfield comparison: check if user lacks certain permission
- if (!req.permission!.has(new Permissions(perm))) {
- throw DiscordApiErrors.MISSING_PERMISSIONS.withParams(perm as string);
- }
- });
- }
+ const requiredPerms = Array.isArray(opts.permission) ? opts.permission : [opts.permission];
+ requiredPerms.forEach((perm) => {
+ // bitfield comparison: check if user lacks certain permission
+ if (!req.permission!.has(new Permissions(perm))) {
+ throw DiscordApiErrors.MISSING_PERMISSIONS.withParams(perm as string);
+ }
+ });
+ }
- if (opts.right) {
- const required = new Rights(opts.right);
- req.rights = await getRights(req.user_id);
+ if (opts.right) {
+ const required = new Rights(opts.right);
+ req.rights = await getRights(req.user_id);
- if (!req.rights || !req.rights.has(required)) {
- throw SpacebarApiErrors.MISSING_RIGHTS.withParams(opts.right as string);
- }
- }
+ if (!req.rights || !req.rights.has(required)) {
+ throw SpacebarApiErrors.MISSING_RIGHTS.withParams(opts.right as string);
+ }
+ }
- if (validate && !ignoredRequestSchemas.includes(opts.requestBody!)) {
- const valid = validate(req.body);
- if (!valid) {
- const fields: Record = {};
- validate.errors?.forEach(
- (x) =>
- (fields[x.instancePath.slice(1)] = {
- code: x.keyword,
- message: x.message || "",
- }),
- );
- if (process.env.LOG_VALIDATION_ERRORS) console.log(`[VALIDATION ERROR] ${req.method} ${req.originalUrl} - SCHEMA='${opts.requestBody}' -`, validate?.errors);
- throw FieldErrors(fields, validate.errors!);
- }
- }
- next();
- };
+ if (validate && !ignoredRequestSchemas.includes(opts.requestBody!)) {
+ const valid = validate(req.body);
+ if (!valid) {
+ const fields: Record = {};
+ validate.errors?.forEach(
+ (x) =>
+ (fields[x.instancePath.slice(1)] = {
+ code: x.keyword,
+ message: x.message || "",
+ }),
+ );
+ if (process.env.LOG_VALIDATION_ERRORS) console.log(`[VALIDATION ERROR] ${req.method} ${req.originalUrl} - SCHEMA='${opts.requestBody}' -`, validate?.errors);
+ throw FieldErrors(fields, validate.errors!);
+ }
+ }
+ next();
+ };
}
diff --git a/src/api/util/utility/Base64.ts b/src/api/util/utility/Base64.ts
index 7426d22..78a56f6 100644
--- a/src/api/util/utility/Base64.ts
+++ b/src/api/util/utility/Base64.ts
@@ -25,41 +25,41 @@
// 123 == 'z'.charCodeAt(0) + 1
const s2b = new Array(123);
for (let i = 0; i < alphabet.length; i++) {
- s2b[alphabet.charCodeAt(i)] = i;
+ s2b[alphabet.charCodeAt(i)] = i;
}
// number to base64
export const ntob = (n: number): string => {
- if (n < 0) return `-${ntob(-n)}`;
+ if (n < 0) return `-${ntob(-n)}`;
- let lo = n >>> 0;
- let hi = (n / 4294967296) >>> 0;
+ let lo = n >>> 0;
+ let hi = (n / 4294967296) >>> 0;
- let right = "";
- while (hi > 0) {
- right = b2s[0x3f & lo] + right;
- lo >>>= 6;
- lo |= (0x3f & hi) << 26;
- hi >>>= 6;
- }
+ let right = "";
+ while (hi > 0) {
+ right = b2s[0x3f & lo] + right;
+ lo >>>= 6;
+ lo |= (0x3f & hi) << 26;
+ hi >>>= 6;
+ }
- let left = "";
- do {
- left = b2s[0x3f & lo] + left;
- lo >>>= 6;
- } while (lo > 0);
+ let left = "";
+ do {
+ left = b2s[0x3f & lo] + left;
+ lo >>>= 6;
+ } while (lo > 0);
- return left + right;
+ return left + right;
};
// base64 to number
export const bton = (base64: string) => {
- let number = 0;
- const sign = base64.charAt(0) === "-" ? 1 : 0;
+ let number = 0;
+ const sign = base64.charAt(0) === "-" ? 1 : 0;
- for (let i = sign; i < base64.length; i++) {
- number = number * 64 + s2b[base64.charCodeAt(i)];
- }
+ for (let i = sign; i < base64.length; i++) {
+ number = number * 64 + s2b[base64.charCodeAt(i)];
+ }
- return sign ? -number : number;
+ return sign ? -number : number;
};
diff --git a/src/api/util/utility/EmbedHandlers.ts b/src/api/util/utility/EmbedHandlers.ts
index 8bbd628..2e50c53 100644
--- a/src/api/util/utility/EmbedHandlers.ts
+++ b/src/api/util/utility/EmbedHandlers.ts
@@ -24,494 +24,494 @@
import probe from "probe-image-size";
export const DEFAULT_FETCH_OPTIONS: RequestInit = {
- redirect: "follow",
- headers: {
- "user-agent": "Mozilla/5.0 (compatible; Spacebar/1.0; +https://github.com/spacebarchat/server)",
- },
- // size: 1024 * 1024 * 5, // grabbed from config later
- method: "GET",
+ redirect: "follow",
+ headers: {
+ "user-agent": "Mozilla/5.0 (compatible; Spacebar/1.0; +https://github.com/spacebarchat/server)",
+ },
+ // size: 1024 * 1024 * 5, // grabbed from config later
+ method: "GET",
};
const makeEmbedImage = (url: string | undefined, width: number | undefined, height: number | undefined): Required | undefined => {
- if (!url || !width || !height) return undefined;
- return {
- url,
- width,
- height,
- proxy_url: getProxyUrl(new URL(url), width, height),
- };
+ if (!url || !width || !height) return undefined;
+ return {
+ url,
+ width,
+ height,
+ proxy_url: getProxyUrl(new URL(url), width, height),
+ };
};
let hasWarnedAboutImagor = false;
export const getProxyUrl = (url: URL, width: number, height: number): string => {
- const { resizeWidthMax, resizeHeightMax, imagorServerUrl } = Config.get().cdn;
- const secret = Config.get().security.requestSignature;
- width = Math.min(width || 500, resizeWidthMax || width);
- height = Math.min(height || 500, resizeHeightMax || width);
+ const { resizeWidthMax, resizeHeightMax, imagorServerUrl } = Config.get().cdn;
+ const secret = Config.get().security.requestSignature;
+ width = Math.min(width || 500, resizeWidthMax || width);
+ height = Math.min(height || 500, resizeHeightMax || width);
- // Imagor
- if (imagorServerUrl) {
- const path = `${width}x${height}/${url.host}${url.pathname}`;
+ // Imagor
+ if (imagorServerUrl) {
+ const path = `${width}x${height}/${url.host}${url.pathname}`;
- const hash = crypto.createHmac("sha1", secret).update(path).digest("base64").replace(/\+/g, "-").replace(/\//g, "_");
+ const hash = crypto.createHmac("sha1", secret).update(path).digest("base64").replace(/\+/g, "-").replace(/\//g, "_");
- return `${imagorServerUrl}/${hash}/${path}`;
- }
+ return `${imagorServerUrl}/${hash}/${path}`;
+ }
- if (!hasWarnedAboutImagor) {
- hasWarnedAboutImagor = true;
- console.log("[Embeds]", yellow("Imagor has not been set up correctly. https://docs.spacebar.chat/setup/server/configuration/imagor/"));
- }
+ if (!hasWarnedAboutImagor) {
+ hasWarnedAboutImagor = true;
+ console.log("[Embeds]", yellow("Imagor has not been set up correctly. https://docs.spacebar.chat/setup/server/configuration/imagor/"));
+ }
- return url.toString();
+ return url.toString();
};
const getMeta = ($: cheerio.CheerioAPI, name: string): string | undefined => {
- let elem = $(`meta[property="${name}"]`);
- if (!elem.length) elem = $(`meta[name="${name}"]`);
- const ret = elem.attr("content") || elem.text();
- return ret.trim().length == 0 ? undefined : ret;
+ let elem = $(`meta[property="${name}"]`);
+ if (!elem.length) elem = $(`meta[name="${name}"]`);
+ const ret = elem.attr("content") || elem.text();
+ return ret.trim().length == 0 ? undefined : ret;
};
const tryParseInt = (str: string | undefined) => {
- if (!str) return undefined;
- try {
- return parseInt(str);
- } catch (e) {
- return undefined;
- }
+ if (!str) return undefined;
+ try {
+ return parseInt(str);
+ } catch (e) {
+ return undefined;
+ }
};
export const getMetaDescriptions = (text: string) => {
- const $ = cheerio.load(text);
+ const $ = cheerio.load(text);
- return {
- type: getMeta($, "og:type"),
- title: getMeta($, "og:title") || $("title").first().text(),
- provider_name: getMeta($, "og:site_name"),
- author: getMeta($, "article:author"),
- description: getMeta($, "og:description") || getMeta($, "description"),
- image: getMeta($, "og:image") || getMeta($, "twitter:image"),
- image_fallback: $(`image`).attr("src"),
- video_fallback: $(`video`).attr("src"),
- width: tryParseInt(getMeta($, "og:image:width")),
- height: tryParseInt(getMeta($, "og:image:height")),
- url: getMeta($, "og:url"),
- youtube_embed: getMeta($, "og:video:secure_url"),
- site_name: getMeta($, "og:site_name"),
+ return {
+ type: getMeta($, "og:type"),
+ title: getMeta($, "og:title") || $("title").first().text(),
+ provider_name: getMeta($, "og:site_name"),
+ author: getMeta($, "article:author"),
+ description: getMeta($, "og:description") || getMeta($, "description"),
+ image: getMeta($, "og:image") || getMeta($, "twitter:image"),
+ image_fallback: $(`image`).attr("src"),
+ video_fallback: $(`video`).attr("src"),
+ width: tryParseInt(getMeta($, "og:image:width")),
+ height: tryParseInt(getMeta($, "og:image:height")),
+ url: getMeta($, "og:url"),
+ youtube_embed: getMeta($, "og:video:secure_url"),
+ site_name: getMeta($, "og:site_name"),
- $,
- };
+ $,
+ };
};
const doFetch = async (url: URL) => {
- try {
- const res = await fetch(url, {
- ...DEFAULT_FETCH_OPTIONS,
- });
- if (res.headers.get("content-length")) {
- const contentLength = parseInt(res.headers.get("content-length")!);
- if (Config.get().limits.message.maxEmbedDownloadSize && contentLength > Config.get().limits.message.maxEmbedDownloadSize) {
- return null;
- }
- }
- return res;
- } catch (e) {
- return null;
- }
+ try {
+ const res = await fetch(url, {
+ ...DEFAULT_FETCH_OPTIONS,
+ });
+ if (res.headers.get("content-length")) {
+ const contentLength = parseInt(res.headers.get("content-length")!);
+ if (Config.get().limits.message.maxEmbedDownloadSize && contentLength > Config.get().limits.message.maxEmbedDownloadSize) {
+ return null;
+ }
+ }
+ return res;
+ } catch (e) {
+ return null;
+ }
};
const genericImageHandler = async (url: URL): Promise