From dc24d32836a8ab9f8d64f41c72685e29516ca354 Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Fri, 7 Jul 2023 06:10:29 +0000 Subject: [PATCH 01/14] feat: add log server --- services/log-server/.dockerignore | 3 + services/log-server/.gitignore | 3 + services/log-server/.prettierrc | 5 + services/log-server/Dockerfile | 29 + services/log-server/commitlint.config.js | 1 + services/log-server/package-lock.json | 2463 +++++++++++++++++ services/log-server/package.json | 28 + services/log-server/src/config.ts | 44 + services/log-server/src/db.ts | 45 + .../src/handler/add-function-log.ts | 23 + .../src/handler/get-function-log.ts | 42 + .../src/helper/ensure-collection-exist.ts | 31 + services/log-server/src/index.ts | 47 + services/log-server/src/logger.ts | 24 + services/log-server/tsconfig.json | 32 + 15 files changed, 2820 insertions(+) create mode 100644 services/log-server/.dockerignore create mode 100644 services/log-server/.gitignore create mode 100644 services/log-server/.prettierrc create mode 100644 services/log-server/Dockerfile create mode 100644 services/log-server/commitlint.config.js create mode 100644 services/log-server/package-lock.json create mode 100644 services/log-server/package.json create mode 100644 services/log-server/src/config.ts create mode 100644 services/log-server/src/db.ts create mode 100644 services/log-server/src/handler/add-function-log.ts create mode 100644 services/log-server/src/handler/get-function-log.ts create mode 100644 services/log-server/src/helper/ensure-collection-exist.ts create mode 100644 services/log-server/src/index.ts create mode 100644 services/log-server/src/logger.ts create mode 100644 services/log-server/tsconfig.json diff --git a/services/log-server/.dockerignore b/services/log-server/.dockerignore new file mode 100644 index 0000000000..d14eab8de7 --- /dev/null +++ b/services/log-server/.dockerignore @@ -0,0 +1,3 @@ +dist +node_modules +.env \ No newline at end of file diff --git a/services/log-server/.gitignore b/services/log-server/.gitignore new file mode 100644 index 0000000000..d14eab8de7 --- /dev/null +++ b/services/log-server/.gitignore @@ -0,0 +1,3 @@ +dist +node_modules +.env \ No newline at end of file diff --git a/services/log-server/.prettierrc b/services/log-server/.prettierrc new file mode 100644 index 0000000000..5a6fd01584 --- /dev/null +++ b/services/log-server/.prettierrc @@ -0,0 +1,5 @@ +{ + "singleQuote": true, + "trailingComma": "all", + "semi": false +} \ No newline at end of file diff --git a/services/log-server/Dockerfile b/services/log-server/Dockerfile new file mode 100644 index 0000000000..98bdc39e46 --- /dev/null +++ b/services/log-server/Dockerfile @@ -0,0 +1,29 @@ +FROM node:18-slim AS build + +WORKDIR /app + +COPY . /app + +RUN npm install +RUN npm run build + + +FROM node:18-slim AS production + +ENV LOG_LEVEL=debug +WORKDIR /app + +COPY --from=build /app/dist /app/dist +COPY --from=build /app/node_modules /app/node_modules +COPY --from=build /app/package.json /app/package.json +COPY --from=build /app/package-lock.json /app/package-lock.json + +RUN npm ci --production + +RUN chown -R node:node /app/ + +USER node + +EXPOSE 5060 + +CMD [ "npm", "run", "start" ] \ No newline at end of file diff --git a/services/log-server/commitlint.config.js b/services/log-server/commitlint.config.js new file mode 100644 index 0000000000..4fedde6daf --- /dev/null +++ b/services/log-server/commitlint.config.js @@ -0,0 +1 @@ +module.exports = { extends: ['@commitlint/config-conventional'] } diff --git a/services/log-server/package-lock.json b/services/log-server/package-lock.json new file mode 100644 index 0000000000..feb6d279c4 --- /dev/null +++ b/services/log-server/package-lock.json @@ -0,0 +1,2463 @@ +{ + "name": "log-server", + "version": "1.0.0-beta.9", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "log-server", + "version": "1.0.0-beta.9", + "dependencies": { + "database-proxy": "^1.0.0-beta.2", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "express-async-errors": "^3.1.1", + "log4js": "^6.9.1", + "mongodb": "^5.6.0", + "mongodb-uri": "^0.9.7" + }, + "devDependencies": { + "@types/express": "^4.17.17", + "@types/mongodb-uri": "^0.9.1", + "typescript": "^5.1.6" + } + }, + "node_modules/@aws-crypto/crc32": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/crc32/-/crc32-3.0.0.tgz", + "integrity": "sha512-IzSgsrxUcsrejQbPVilIKy16kAT52EwB6zSaI+M3xxIhKh5+aldEyvI+z6erM7TCLB2BJsFrtHjp6/4/sr+3dA==", + "optional": true, + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/crc32/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "optional": true + }, + "node_modules/@aws-crypto/ie11-detection": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/ie11-detection/-/ie11-detection-3.0.0.tgz", + "integrity": "sha512-341lBBkiY1DfDNKai/wXM3aujNBkXR7tq1URPQDL9wi3AUbI80NR74uF1TXHMm7po1AcnFk8iu2S2IeU/+/A+Q==", + "optional": true, + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/ie11-detection/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "optional": true + }, + "node_modules/@aws-crypto/sha256-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-3.0.0.tgz", + "integrity": "sha512-8VLmW2B+gjFbU5uMeqtQM6Nj0/F1bro80xQXCW6CQBWgosFWXTx77aeOF5CAIAmbOK64SdMBJdNr6J41yP5mvQ==", + "optional": true, + "dependencies": { + "@aws-crypto/ie11-detection": "^3.0.0", + "@aws-crypto/sha256-js": "^3.0.0", + "@aws-crypto/supports-web-crypto": "^3.0.0", + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-locate-window": "^3.0.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-browser/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "optional": true + }, + "node_modules/@aws-crypto/sha256-js": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-js/-/sha256-js-3.0.0.tgz", + "integrity": "sha512-PnNN7os0+yd1XvXAy23CFOmTbMaDxgxXtTKHybrJ39Y8kGzBATgBFibWJKH6BhytLI/Zyszs87xCOBNyBig6vQ==", + "optional": true, + "dependencies": { + "@aws-crypto/util": "^3.0.0", + "@aws-sdk/types": "^3.222.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/sha256-js/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "optional": true + }, + "node_modules/@aws-crypto/supports-web-crypto": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/supports-web-crypto/-/supports-web-crypto-3.0.0.tgz", + "integrity": "sha512-06hBdMwUAb2WFTuGG73LSC0wfPu93xWwo5vL2et9eymgmu3Id5vFAHBbajVWiGhPO37qcsdCap/FqXvJGJWPIg==", + "optional": true, + "dependencies": { + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/supports-web-crypto/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "optional": true + }, + "node_modules/@aws-crypto/util": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@aws-crypto/util/-/util-3.0.0.tgz", + "integrity": "sha512-2OJlpeJpCR48CC8r+uKVChzs9Iungj9wkZrl8Z041DWEWvyIHILYKCPNzJghKsivj+S3mLo6BVc7mBNzdxA46w==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "^3.222.0", + "@aws-sdk/util-utf8-browser": "^3.0.0", + "tslib": "^1.11.1" + } + }, + "node_modules/@aws-crypto/util/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==", + "optional": true + }, + "node_modules/@aws-sdk/client-cognito-identity": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.363.0.tgz", + "integrity": "sha512-tsJzgBSCpna85IVsuS7FBIK9wkSl7fs8TJ/QzapIgu8rKss0ySHVO6TeMVAdw2BvaQl7CxU9c3PosjhLWHu6KQ==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/client-sts": "3.363.0", + "@aws-sdk/credential-provider-node": "3.363.0", + "@aws-sdk/middleware-host-header": "3.363.0", + "@aws-sdk/middleware-logger": "3.363.0", + "@aws-sdk/middleware-recursion-detection": "3.363.0", + "@aws-sdk/middleware-signing": "3.363.0", + "@aws-sdk/middleware-user-agent": "3.363.0", + "@aws-sdk/types": "3.357.0", + "@aws-sdk/util-endpoints": "3.357.0", + "@aws-sdk/util-user-agent-browser": "3.363.0", + "@aws-sdk/util-user-agent-node": "3.363.0", + "@smithy/config-resolver": "^1.0.1", + "@smithy/fetch-http-handler": "^1.0.1", + "@smithy/hash-node": "^1.0.1", + "@smithy/invalid-dependency": "^1.0.1", + "@smithy/middleware-content-length": "^1.0.1", + "@smithy/middleware-endpoint": "^1.0.1", + "@smithy/middleware-retry": "^1.0.2", + "@smithy/middleware-serde": "^1.0.1", + "@smithy/middleware-stack": "^1.0.1", + "@smithy/node-config-provider": "^1.0.1", + "@smithy/node-http-handler": "^1.0.2", + "@smithy/protocol-http": "^1.0.1", + "@smithy/smithy-client": "^1.0.3", + "@smithy/types": "^1.0.0", + "@smithy/url-parser": "^1.0.1", + "@smithy/util-base64": "^1.0.1", + "@smithy/util-body-length-browser": "^1.0.1", + "@smithy/util-body-length-node": "^1.0.1", + "@smithy/util-defaults-mode-browser": "^1.0.1", + "@smithy/util-defaults-mode-node": "^1.0.1", + "@smithy/util-retry": "^1.0.2", + "@smithy/util-utf8": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sso": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.363.0.tgz", + "integrity": "sha512-PZ+HfKSgS4hlMnJzG+Ev8/mgHd/b/ETlJWPSWjC/f2NwVoBQkBnqHjdyEx7QjF6nksJozcVh5Q+kkYLKc/QwBQ==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.363.0", + "@aws-sdk/middleware-logger": "3.363.0", + "@aws-sdk/middleware-recursion-detection": "3.363.0", + "@aws-sdk/middleware-user-agent": "3.363.0", + "@aws-sdk/types": "3.357.0", + "@aws-sdk/util-endpoints": "3.357.0", + "@aws-sdk/util-user-agent-browser": "3.363.0", + "@aws-sdk/util-user-agent-node": "3.363.0", + "@smithy/config-resolver": "^1.0.1", + "@smithy/fetch-http-handler": "^1.0.1", + "@smithy/hash-node": "^1.0.1", + "@smithy/invalid-dependency": "^1.0.1", + "@smithy/middleware-content-length": "^1.0.1", + "@smithy/middleware-endpoint": "^1.0.1", + "@smithy/middleware-retry": "^1.0.2", + "@smithy/middleware-serde": "^1.0.1", + "@smithy/middleware-stack": "^1.0.1", + "@smithy/node-config-provider": "^1.0.1", + "@smithy/node-http-handler": "^1.0.2", + "@smithy/protocol-http": "^1.0.1", + "@smithy/smithy-client": "^1.0.3", + "@smithy/types": "^1.0.0", + "@smithy/url-parser": "^1.0.1", + "@smithy/util-base64": "^1.0.1", + "@smithy/util-body-length-browser": "^1.0.1", + "@smithy/util-body-length-node": "^1.0.1", + "@smithy/util-defaults-mode-browser": "^1.0.1", + "@smithy/util-defaults-mode-node": "^1.0.1", + "@smithy/util-retry": "^1.0.2", + "@smithy/util-utf8": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sso-oidc": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.363.0.tgz", + "integrity": "sha512-V3Ebiq/zNtDS/O92HUWGBa7MY59RYSsqWd+E0XrXv6VYTA00RlMTbNcseivNgp2UghOgB9a20Nkz6EqAeIN+RQ==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/middleware-host-header": "3.363.0", + "@aws-sdk/middleware-logger": "3.363.0", + "@aws-sdk/middleware-recursion-detection": "3.363.0", + "@aws-sdk/middleware-user-agent": "3.363.0", + "@aws-sdk/types": "3.357.0", + "@aws-sdk/util-endpoints": "3.357.0", + "@aws-sdk/util-user-agent-browser": "3.363.0", + "@aws-sdk/util-user-agent-node": "3.363.0", + "@smithy/config-resolver": "^1.0.1", + "@smithy/fetch-http-handler": "^1.0.1", + "@smithy/hash-node": "^1.0.1", + "@smithy/invalid-dependency": "^1.0.1", + "@smithy/middleware-content-length": "^1.0.1", + "@smithy/middleware-endpoint": "^1.0.1", + "@smithy/middleware-retry": "^1.0.2", + "@smithy/middleware-serde": "^1.0.1", + "@smithy/middleware-stack": "^1.0.1", + "@smithy/node-config-provider": "^1.0.1", + "@smithy/node-http-handler": "^1.0.2", + "@smithy/protocol-http": "^1.0.1", + "@smithy/smithy-client": "^1.0.3", + "@smithy/types": "^1.0.0", + "@smithy/url-parser": "^1.0.1", + "@smithy/util-base64": "^1.0.1", + "@smithy/util-body-length-browser": "^1.0.1", + "@smithy/util-body-length-node": "^1.0.1", + "@smithy/util-defaults-mode-browser": "^1.0.1", + "@smithy/util-defaults-mode-node": "^1.0.1", + "@smithy/util-retry": "^1.0.2", + "@smithy/util-utf8": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/client-sts": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.363.0.tgz", + "integrity": "sha512-0jj14WvBPJQ8xr72cL0mhlmQ90tF0O0wqXwSbtog6PsC8+KDE6Yf+WsxsumyI8E5O8u3eYijBL+KdqG07F/y/w==", + "optional": true, + "dependencies": { + "@aws-crypto/sha256-browser": "3.0.0", + "@aws-crypto/sha256-js": "3.0.0", + "@aws-sdk/credential-provider-node": "3.363.0", + "@aws-sdk/middleware-host-header": "3.363.0", + "@aws-sdk/middleware-logger": "3.363.0", + "@aws-sdk/middleware-recursion-detection": "3.363.0", + "@aws-sdk/middleware-sdk-sts": "3.363.0", + "@aws-sdk/middleware-signing": "3.363.0", + "@aws-sdk/middleware-user-agent": "3.363.0", + "@aws-sdk/types": "3.357.0", + "@aws-sdk/util-endpoints": "3.357.0", + "@aws-sdk/util-user-agent-browser": "3.363.0", + "@aws-sdk/util-user-agent-node": "3.363.0", + "@smithy/config-resolver": "^1.0.1", + "@smithy/fetch-http-handler": "^1.0.1", + "@smithy/hash-node": "^1.0.1", + "@smithy/invalid-dependency": "^1.0.1", + "@smithy/middleware-content-length": "^1.0.1", + "@smithy/middleware-endpoint": "^1.0.1", + "@smithy/middleware-retry": "^1.0.1", + "@smithy/middleware-serde": "^1.0.1", + "@smithy/middleware-stack": "^1.0.1", + "@smithy/node-config-provider": "^1.0.1", + "@smithy/node-http-handler": "^1.0.1", + "@smithy/protocol-http": "^1.1.0", + "@smithy/smithy-client": "^1.0.2", + "@smithy/types": "^1.1.0", + "@smithy/url-parser": "^1.0.1", + "@smithy/util-base64": "^1.0.1", + "@smithy/util-body-length-browser": "^1.0.1", + "@smithy/util-body-length-node": "^1.0.1", + "@smithy/util-defaults-mode-browser": "^1.0.1", + "@smithy/util-defaults-mode-node": "^1.0.1", + "@smithy/util-retry": "^1.0.1", + "@smithy/util-utf8": "^1.0.1", + "fast-xml-parser": "4.2.5", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-cognito-identity": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.363.0.tgz", + "integrity": "sha512-5x42JvqEsBUrm6/qdf0WWe4mlmJjPItxamQhRjuOzeQD/BxsA2W5VS/7n0Ws0e27DNhlnUErcIJd+bBy6j1fqA==", + "optional": true, + "dependencies": { + "@aws-sdk/client-cognito-identity": "3.363.0", + "@aws-sdk/types": "3.357.0", + "@smithy/property-provider": "^1.0.1", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-env": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.363.0.tgz", + "integrity": "sha512-VAQ3zITT2Q0acht0HezouYnMFKZ2vIOa20X4zQA3WI0HfaP4D6ga6KaenbDcb/4VFiqfqiRHfdyXHP0ThcDRMA==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.357.0", + "@smithy/property-provider": "^1.0.1", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-ini": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.363.0.tgz", + "integrity": "sha512-ZYN+INoqyX5FVC3rqUxB6O8nOWkr0gHRRBm1suoOlmuFJ/WSlW/uUGthRBY5x1AQQnBF8cpdlxZzGHd41lFVNw==", + "optional": true, + "dependencies": { + "@aws-sdk/credential-provider-env": "3.363.0", + "@aws-sdk/credential-provider-process": "3.363.0", + "@aws-sdk/credential-provider-sso": "3.363.0", + "@aws-sdk/credential-provider-web-identity": "3.363.0", + "@aws-sdk/types": "3.357.0", + "@smithy/credential-provider-imds": "^1.0.1", + "@smithy/property-provider": "^1.0.1", + "@smithy/shared-ini-file-loader": "^1.0.1", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-node": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.363.0.tgz", + "integrity": "sha512-C1qXFIN2yMxD6pGgug0vR1UhScOki6VqdzuBHzXZAGu7MOjvgHNdscEcb3CpWnITHaPL2ztkiw75T1sZ7oIgQg==", + "optional": true, + "dependencies": { + "@aws-sdk/credential-provider-env": "3.363.0", + "@aws-sdk/credential-provider-ini": "3.363.0", + "@aws-sdk/credential-provider-process": "3.363.0", + "@aws-sdk/credential-provider-sso": "3.363.0", + "@aws-sdk/credential-provider-web-identity": "3.363.0", + "@aws-sdk/types": "3.357.0", + "@smithy/credential-provider-imds": "^1.0.1", + "@smithy/property-provider": "^1.0.1", + "@smithy/shared-ini-file-loader": "^1.0.1", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-process": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.363.0.tgz", + "integrity": "sha512-fOKAINU7Rtj2T8pP13GdCt+u0Ml3gYynp8ki+1jMZIQ+Ju/MdDOqZpKMFKicMn3Z1ttUOgqr+grUdus6z8ceBQ==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.357.0", + "@smithy/property-provider": "^1.0.1", + "@smithy/shared-ini-file-loader": "^1.0.1", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-sso": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.363.0.tgz", + "integrity": "sha512-5RUZ5oM0lwZSo3EehT0dXggOjgtxFogpT3cZvoLGtIwrPBvm8jOQPXQUlaqCj10ThF1sYltEyukz/ovtDwYGew==", + "optional": true, + "dependencies": { + "@aws-sdk/client-sso": "3.363.0", + "@aws-sdk/token-providers": "3.363.0", + "@aws-sdk/types": "3.357.0", + "@smithy/property-provider": "^1.0.1", + "@smithy/shared-ini-file-loader": "^1.0.1", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-provider-web-identity": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.363.0.tgz", + "integrity": "sha512-Z6w7fjgy79pAax580wdixbStQw10xfyZ+hOYLcPudoYFKjoNx0NQBejg5SwBzCF/HQL23Ksm9kDfbXDX9fkPhA==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.357.0", + "@smithy/property-provider": "^1.0.1", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/credential-providers": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.363.0.tgz", + "integrity": "sha512-hVa1DdYasnLud2EKjDAlDHiV/+H/Zq52chHU00c/R8XwPu1s0kZX3NMmlt0D2HhYqC1mUwtdmE58Jra2POviQQ==", + "optional": true, + "dependencies": { + "@aws-sdk/client-cognito-identity": "3.363.0", + "@aws-sdk/client-sso": "3.363.0", + "@aws-sdk/client-sts": "3.363.0", + "@aws-sdk/credential-provider-cognito-identity": "3.363.0", + "@aws-sdk/credential-provider-env": "3.363.0", + "@aws-sdk/credential-provider-ini": "3.363.0", + "@aws-sdk/credential-provider-node": "3.363.0", + "@aws-sdk/credential-provider-process": "3.363.0", + "@aws-sdk/credential-provider-sso": "3.363.0", + "@aws-sdk/credential-provider-web-identity": "3.363.0", + "@aws-sdk/types": "3.357.0", + "@smithy/credential-provider-imds": "^1.0.1", + "@smithy/property-provider": "^1.0.1", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-host-header": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.363.0.tgz", + "integrity": "sha512-FobpclDCf5Y1ueyJDmb9MqguAdPssNMlnqWQpujhYVABq69KHu73fSCWSauFPUrw7YOpV8kG1uagDF0POSxHzA==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.357.0", + "@smithy/protocol-http": "^1.1.0", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-logger": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.363.0.tgz", + "integrity": "sha512-SSGgthScYnFGTOw8EzbkvquqweFmvn7uJihkpFekbtBNGC/jGOGO+8ziHjTQ8t/iI/YKubEwv+LMi0f77HKSEg==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.357.0", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-recursion-detection": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.363.0.tgz", + "integrity": "sha512-MWD/57QgI/N7fG8rtzDTUdSqNpYohQfgj9XCFAoVeI/bU4usrkOrew43L4smJG4XrDxlNT8lSJlDtd64tuiUZA==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.357.0", + "@smithy/protocol-http": "^1.1.0", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-sdk-sts": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-sdk-sts/-/middleware-sdk-sts-3.363.0.tgz", + "integrity": "sha512-1yy2Ac50FO8BrODaw5bPWvVrRhaVLqXTFH6iHB+dJLPUkwtY5zLM3Mp+9Ilm7kME+r7oIB1wuO6ZB1Lf4ZszIw==", + "optional": true, + "dependencies": { + "@aws-sdk/middleware-signing": "3.363.0", + "@aws-sdk/types": "3.357.0", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-signing": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-signing/-/middleware-signing-3.363.0.tgz", + "integrity": "sha512-/7qia715pt9JKYIPDGu22WmdZxD8cfF/5xB+1kmILg7ZtjO0pPuTaCNJ7xiIuFd7Dn7JXp5lop08anX/GOhNRQ==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.357.0", + "@smithy/property-provider": "^1.0.1", + "@smithy/protocol-http": "^1.1.0", + "@smithy/signature-v4": "^1.0.1", + "@smithy/types": "^1.1.0", + "@smithy/util-middleware": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/middleware-user-agent": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.363.0.tgz", + "integrity": "sha512-ri8YaQvXP6odteVTMfxPqFR26Q0h9ejtqhUDv47P34FaKXedEM4nC6ix6o+5FEYj6l8syGyktftZ5O70NoEhug==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.357.0", + "@aws-sdk/util-endpoints": "3.357.0", + "@smithy/protocol-http": "^1.1.0", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/token-providers": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.363.0.tgz", + "integrity": "sha512-6+0aJ1zugNgsMmhTtW2LBWxOVSaXCUk2q3xyTchSXkNzallYaRiZMRkieW+pKNntnu0g5H1T0zyfCO0tbXwxEA==", + "optional": true, + "dependencies": { + "@aws-sdk/client-sso-oidc": "3.363.0", + "@aws-sdk/types": "3.357.0", + "@smithy/property-provider": "^1.0.1", + "@smithy/shared-ini-file-loader": "^1.0.1", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/types": { + "version": "3.357.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.357.0.tgz", + "integrity": "sha512-/riCRaXg3p71BeWnShrai0y0QTdXcouPSM0Cn1olZbzTf7s71aLEewrc96qFrL70XhY4XvnxMpqQh+r43XIL3g==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-endpoints": { + "version": "3.357.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.357.0.tgz", + "integrity": "sha512-XHKyS5JClT9su9hDif715jpZiWHQF9gKZXER8tW0gOizU3R9cyWc9EsJ2BRhFNhi7nt/JF/CLUEc5qDx3ETbUw==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.357.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-locate-window": { + "version": "3.310.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.310.0.tgz", + "integrity": "sha512-qo2t/vBTnoXpjKxlsC2e1gBrRm80M3bId27r0BRB2VniSSe7bL1mmzM+/HFtujm0iAxtPM+aLEflLJlJeDPg0w==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-browser": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.363.0.tgz", + "integrity": "sha512-fk9ymBUIYbxiGm99Cn+kAAXmvMCWTf/cHAcB79oCXV4ELXdPa9lN5xQhZRFNxLUeXG4OAMEuCAUUuZEj8Fnc1Q==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.357.0", + "@smithy/types": "^1.1.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@aws-sdk/util-user-agent-node": { + "version": "3.363.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.363.0.tgz", + "integrity": "sha512-Fli/dvgGA9hdnQUrYb1//wNSFlK2jAfdJcfNXA6SeBYzSeH5pVGYF4kXF0FCdnMA3Fef+Zn1zAP/hw9v8VJHWQ==", + "optional": true, + "dependencies": { + "@aws-sdk/types": "3.357.0", + "@smithy/node-config-provider": "^1.0.1", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "aws-crt": ">=1.0.0" + }, + "peerDependenciesMeta": { + "aws-crt": { + "optional": true + } + } + }, + "node_modules/@aws-sdk/util-utf8-browser": { + "version": "3.259.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-utf8-browser/-/util-utf8-browser-3.259.0.tgz", + "integrity": "sha512-UvFa/vR+e19XookZF8RzFZBrw2EUkQWxiBW0yYQAhvk3C+QVGl0H3ouca8LDBlBfQKXwmW3huo/59H8rwb1wJw==", + "optional": true, + "dependencies": { + "tslib": "^2.3.1" + } + }, + "node_modules/@smithy/abort-controller": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-1.0.1.tgz", + "integrity": "sha512-An6irzp9NCji2JtJHhrEFlDbxLwHd6c6Y9fq3ZeomyUR8BIXlGXVTxsemUSZVVgOq3166iYbYs/CrPAmgRSFLw==", + "optional": true, + "dependencies": { + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/config-resolver": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-1.0.1.tgz", + "integrity": "sha512-quj0xUiEVG/UHfY82EtthR/+S5/17p3IxXArC3NFSNqryMobWbG9oWgJy2s2cgUSVZLzxevjKKvxrilK7JEDaA==", + "optional": true, + "dependencies": { + "@smithy/types": "^1.1.0", + "@smithy/util-config-provider": "^1.0.1", + "@smithy/util-middleware": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/credential-provider-imds": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-1.0.1.tgz", + "integrity": "sha512-hkRJoxVCh4CEt1zYOBElE+G/MV6lyx3g68hSJpesM4pwMT/bzEVo5E5XzXY+6dVq8yszeatWKbFuqCCBQte8tg==", + "optional": true, + "dependencies": { + "@smithy/node-config-provider": "^1.0.1", + "@smithy/property-provider": "^1.0.1", + "@smithy/types": "^1.1.0", + "@smithy/url-parser": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/eventstream-codec": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/eventstream-codec/-/eventstream-codec-1.0.1.tgz", + "integrity": "sha512-cpcTXQEOEs2wEvIyxW/iTHJ2m0RVqoEOTjjWEXD6SY8Gcs3FCFP6E8MXadC098tdH5ctMIUXc8POXyMpxzGnjw==", + "optional": true, + "dependencies": { + "@aws-crypto/crc32": "3.0.0", + "@smithy/types": "^1.1.0", + "@smithy/util-hex-encoding": "^1.0.1", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/fetch-http-handler": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-1.0.1.tgz", + "integrity": "sha512-/e2A8eOMk4FVZBQ0o6uF/ttLtFZcmsK5MIwDu1UE3crM4pCAIP19Ul8U9rdLlHhIu81X4AcJmSw55RDSpVRL/w==", + "optional": true, + "dependencies": { + "@smithy/protocol-http": "^1.1.0", + "@smithy/querystring-builder": "^1.0.1", + "@smithy/types": "^1.1.0", + "@smithy/util-base64": "^1.0.1", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/hash-node": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-1.0.1.tgz", + "integrity": "sha512-eCz08BySBcOjVObjbRAS/XMKUGY4ujnuS+GoWeEpzpCSKDnO8/YQ0rStRt4C0llRmhApizYc1tK9DiJwfvXcBg==", + "optional": true, + "dependencies": { + "@smithy/types": "^1.1.0", + "@smithy/util-buffer-from": "^1.0.1", + "@smithy/util-utf8": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/invalid-dependency": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-1.0.1.tgz", + "integrity": "sha512-kib63GFlAzRn/wf8M0cRWrZA1cyOy5IvpTkLavCY782DPFMP0EaEeD6VrlNIOvD6ncf7uCJ68HqckhwK1qLT3g==", + "optional": true, + "dependencies": { + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/is-array-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-1.0.1.tgz", + "integrity": "sha512-fHSTW70gANnzPYWNDcWkPXpp+QMbHhKozbQm/+Denkhp4gwSiPuAovWZRpJa9sXO+Q4dOnNzYN2max1vTCEroA==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-content-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-1.0.1.tgz", + "integrity": "sha512-vWWigayk5i2cFp9xPX5vdzHyK+P0t/xZ3Ovp4Ss+c8JQ1Hlq2kpJZVWtTKsmdfND5rVo5lu0kD5wgAMUCcmuhw==", + "optional": true, + "dependencies": { + "@smithy/protocol-http": "^1.1.0", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-endpoint": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-1.0.2.tgz", + "integrity": "sha512-F3CyXgjtDI4quGFkDmVNytt6KMwlzzeMxtopk6Edue4uKdKcMC1vUmoRS5xTbFzKDDp4XwpnEV7FshPaL3eCPw==", + "optional": true, + "dependencies": { + "@smithy/middleware-serde": "^1.0.1", + "@smithy/types": "^1.1.0", + "@smithy/url-parser": "^1.0.1", + "@smithy/util-middleware": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-retry": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-1.0.3.tgz", + "integrity": "sha512-ZRsjG8adtxQ456FULPqPFmWtrW44Fq8IgdQvQB+rC2RSho3OUzS+TiEIwb5Zs6rf2IoewITKtfdtsUZcxXO0ng==", + "optional": true, + "dependencies": { + "@smithy/protocol-http": "^1.1.0", + "@smithy/service-error-classification": "^1.0.2", + "@smithy/types": "^1.1.0", + "@smithy/util-middleware": "^1.0.1", + "@smithy/util-retry": "^1.0.3", + "tslib": "^2.5.0", + "uuid": "^8.3.2" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-1.0.1.tgz", + "integrity": "sha512-bn5lWk8UUeXFCQfkrNErz5SbeNd+2hgYegHMLsOLPt4URDIsyREar6wMsdsR+8UCdgR5s8udG3Zalgc7puizIQ==", + "optional": true, + "dependencies": { + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/middleware-stack": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-1.0.1.tgz", + "integrity": "sha512-T6+gsAO1JYamOJqmORCrByDeQ/NB+ggjHb33UDOgdX4xIjXz/FB/3UqHgQu6PL1cSFrK+i4oteDIwqARDs/Szw==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-config-provider": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-1.0.1.tgz", + "integrity": "sha512-FRxifH/J2SgOaVLihIqBFuGhiHR/NfzbZYp5nYO7BGgT/gc/f9nAuuRJcEy/hwO3aI6ThyG5apH4tGec6A2sCw==", + "optional": true, + "dependencies": { + "@smithy/property-provider": "^1.0.1", + "@smithy/shared-ini-file-loader": "^1.0.1", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/node-http-handler": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-1.0.2.tgz", + "integrity": "sha512-PzPrGRSt3kNuruLCeR4ffJp57ZLVnIukMXVL3Ppr65ZoxiE+HBsOVAa/Z/T+4HzjCM6RaXnnmB8YKfsDjlb0iA==", + "optional": true, + "dependencies": { + "@smithy/abort-controller": "^1.0.1", + "@smithy/protocol-http": "^1.1.0", + "@smithy/querystring-builder": "^1.0.1", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-1.0.1.tgz", + "integrity": "sha512-3EG/61Ls1MrgEaafpltXBJHSqFPqmTzEX7QKO7lOEHuYGmGYzZ08t1SsTgd1vM74z0IihoZyGPynZ7WmXKvTeg==", + "optional": true, + "dependencies": { + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-1.1.0.tgz", + "integrity": "sha512-H5y/kZOqfJSqRkwtcAoVbqONmhdXwSgYNJ1Glk5Ry8qlhVVy5qUzD9EklaCH8/XLnoCsLO/F/Giee8MIvaBRkg==", + "optional": true, + "dependencies": { + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-builder": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-1.0.1.tgz", + "integrity": "sha512-J5Tzkw1PMtu01h6wl+tlN5vsyROmS6/z5lEfNlLo/L4ELHeVkQ4Q0PEIjDddPLfjVLCm8biQTESE5GCMixSRNQ==", + "optional": true, + "dependencies": { + "@smithy/types": "^1.1.0", + "@smithy/util-uri-escape": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/querystring-parser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-1.0.1.tgz", + "integrity": "sha512-zauxdMc3cwxoLitI5DZqH7xN6Fk0mwRxrUMAETbav2j6Se2U0UGak/55rZcDg2yGzOURaLYi5iOm1gHr98P+Bw==", + "optional": true, + "dependencies": { + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-1.0.2.tgz", + "integrity": "sha512-Q5CCuzYL5FGo6Rr/O+lZxXHm2hrRgbmMn8MgyjqZUWZg20COg20DuNtIbho2iht6CoB7jOpmpBqhWizLlzUZgg==", + "optional": true, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/shared-ini-file-loader": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-1.0.1.tgz", + "integrity": "sha512-EztziuIPoNronENGqh+MWVKJErA4rJpaPzJCPukzBeEoG2USka0/q4B5Mr/1zszOnrb49fPNh4u3u5LfiH7QzA==", + "optional": true, + "dependencies": { + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/signature-v4": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-1.0.1.tgz", + "integrity": "sha512-2D69je14ou1vBTnAQeysSK4QVMm0j3WHS3MDg/DnHnFFcXRCzVl/xAARO7POD8+fpi4tMFPs8Z4hzo1Zw40L0Q==", + "optional": true, + "dependencies": { + "@smithy/eventstream-codec": "^1.0.1", + "@smithy/is-array-buffer": "^1.0.1", + "@smithy/types": "^1.1.0", + "@smithy/util-hex-encoding": "^1.0.1", + "@smithy/util-middleware": "^1.0.1", + "@smithy/util-uri-escape": "^1.0.1", + "@smithy/util-utf8": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/smithy-client": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-1.0.3.tgz", + "integrity": "sha512-Wh1mNP/1yUZK0uYkgCQ6NMxpBT3Fmc45TMdUfOlH1xD2zGYL7U4yDHFOhEZdi/suyjaelFobXB2p9pPIw6LjRQ==", + "optional": true, + "dependencies": { + "@smithy/middleware-stack": "^1.0.1", + "@smithy/types": "^1.1.0", + "@smithy/util-stream": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/types": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-1.1.0.tgz", + "integrity": "sha512-KzmvisMmuwD2jZXuC9e65JrgsZM97y5NpDU7g347oB+Q+xQLU6hQZ5zFNNbEfwwOJHoOvEVTna+dk1h/lW7alw==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/url-parser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-1.0.1.tgz", + "integrity": "sha512-33vWEtE6HzmwjEcEb4I58XMLRAchwPS93YhfDyXAXr1jwDCzfXmMayQwwpyW847rpWj0XJimxqia8q0z+k/ybw==", + "optional": true, + "dependencies": { + "@smithy/querystring-parser": "^1.0.1", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-base64": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-1.0.1.tgz", + "integrity": "sha512-rJcpRi/yUi6TyCEkjdTH86/ExBuKlfctEXhG9/4gMJ3/cnPcHJJnr0mQ9evSEO+3DbpT/Nxq90bcTBdTIAmCig==", + "optional": true, + "dependencies": { + "@smithy/util-buffer-from": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-body-length-browser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-1.0.1.tgz", + "integrity": "sha512-Pdp744fmF7E1NWoSb7256Anhm8eYoCubvosdMwXzOnHuPRVbDa15pKUz2027K3+jrfGpXo1r+MnDerajME1Osw==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" + } + }, + "node_modules/@smithy/util-body-length-node": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-1.0.1.tgz", + "integrity": "sha512-4PIHjDFwG07SNensAiVq/CJmubEVuwclWSYOTNtzBNTvxOeGLznvygkGYgPzS3erByT8C4S9JvnLYgtrsVV3nQ==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-buffer-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-1.0.1.tgz", + "integrity": "sha512-363N7Wq0ceUgE5lLe6kaR6GlJs2/m4r9V6bRMfIszb6P1FZbbRRM2FQYUWWPFSsRymm9mJL18b3fjiVsIvhDGg==", + "optional": true, + "dependencies": { + "@smithy/is-array-buffer": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-config-provider": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-1.0.1.tgz", + "integrity": "sha512-4Qy38Oy5/q43MpTwCLV1P+7NeaOp4W2etQDxMjgEeRlOyGGNlgttn0syi4g2rVSukFVqQ6FbeRs5xbnFmS6kaQ==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-1.0.1.tgz", + "integrity": "sha512-/9ObwNch4Z/NJYfkO4AvqBWku60Ju+c2Ck32toPOLmWe/V6eI9FLn8C1abri+GxDRCkLIqvkaWU1lgZ3nWZIIw==", + "optional": true, + "dependencies": { + "@smithy/property-provider": "^1.0.1", + "@smithy/types": "^1.1.0", + "bowser": "^2.11.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-defaults-mode-node": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-1.0.1.tgz", + "integrity": "sha512-XQM3KvqRLgv7bwAzVkXTITkOmcOINoG9icJiGT8FA0zV35lY5UvyIsg5kHw01xigQS8ufa/33AwG3ZoXip+V5g==", + "optional": true, + "dependencies": { + "@smithy/config-resolver": "^1.0.1", + "@smithy/credential-provider-imds": "^1.0.1", + "@smithy/node-config-provider": "^1.0.1", + "@smithy/property-provider": "^1.0.1", + "@smithy/types": "^1.1.0", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/@smithy/util-hex-encoding": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-1.0.1.tgz", + "integrity": "sha512-FPTtMz/t02/rbfq5Pdll/TWUYP+GVFLCQNr+DgifrLzVRU0g8rdRjyFpDh8nPTdkDDusTTo9P1bepAYj68s0eA==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-middleware": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-1.0.1.tgz", + "integrity": "sha512-u9akN3Zmbr0vZH4F+2iehG7cFg+3fvDfnvS/hhsXH4UHuhqiQ+ADefibnLzPoz1pooY7rvwaQ/TVHyJmZHdLdQ==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-retry": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-1.0.3.tgz", + "integrity": "sha512-gYQnZDD8I2XJFspVwUISyukjPWVikTzKR0IdG8hCWYPTpeULFl1o6yzXlT5SL63TBkuEYl0R1/93cdNtMiNnoA==", + "optional": true, + "dependencies": { + "@smithy/service-error-classification": "^1.0.2", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">= 14.0.0" + } + }, + "node_modules/@smithy/util-stream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-1.0.1.tgz", + "integrity": "sha512-4aBCIz35aZAnt2Rbq341KrnUzGhWv2/Zu8HouJqYLvSWCzlrvsNCGlXP4e70Kjzcw8hSuuCNtdUICwQ5qUWLxg==", + "optional": true, + "dependencies": { + "@smithy/fetch-http-handler": "^1.0.1", + "@smithy/node-http-handler": "^1.0.2", + "@smithy/types": "^1.1.0", + "@smithy/util-base64": "^1.0.1", + "@smithy/util-buffer-from": "^1.0.1", + "@smithy/util-hex-encoding": "^1.0.1", + "@smithy/util-utf8": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-uri-escape": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-1.0.1.tgz", + "integrity": "sha512-IJUrRnXKEIc+PKnU1XzTsIENVR+60jUDPBP3iWX/EvuuT3Xfob47x1FGUe2c3yMXNuU6ax8VDk27hL5LKNoehQ==", + "optional": true, + "dependencies": { + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@smithy/util-utf8": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-1.0.1.tgz", + "integrity": "sha512-iX6XHpjh4DFEUIBSKp2tjy3pYnLQMsJ62zYi1BVAC0kobE6p8AVpiZnxsU3ZkgQatAsUaEspFHUZ7CL7oSqaPQ==", + "optional": true, + "dependencies": { + "@smithy/util-buffer-from": "^1.0.1", + "tslib": "^2.5.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.2", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz", + "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==", + "dev": true, + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.35", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz", + "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.17", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.17.tgz", + "integrity": "sha512-Q4FmmuLGBG58btUnfS1c1r/NQdlp3DMfGDGig8WhfpA2YRUtEkxAjkZb0yvplJGYdF1fsQ81iMDcH24sSCNC/Q==", + "dev": true, + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/express-serve-static-core": { + "version": "4.17.35", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.35.tgz", + "integrity": "sha512-wALWQwrgiB2AWTT91CB62b6Yt0sNHpznUXeZEcnPU3DRdlDIz74x8Qg1UUYKSVFi+va5vKOLYRBI1bRKiLLKIg==", + "dev": true, + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==", + "dev": true + }, + "node_modules/@types/mime": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", + "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==", + "dev": true + }, + "node_modules/@types/mongodb-uri": { + "version": "0.9.1", + "resolved": "https://registry.npmjs.org/@types/mongodb-uri/-/mongodb-uri-0.9.1.tgz", + "integrity": "sha512-Rxyje0yj8zI8GX4qKtroVpidJglBLZBjZG9QLizHdymZmvmVZdOkseje7Qrk9Kpbjopis9ZAvMnkEArQYV0ZaA==", + "dev": true + }, + "node_modules/@types/node": { + "version": "20.3.3", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.3.3.tgz", + "integrity": "sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw==" + }, + "node_modules/@types/qs": { + "version": "6.9.7", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz", + "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==", + "dev": true + }, + "node_modules/@types/range-parser": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz", + "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==", + "dev": true + }, + "node_modules/@types/send": { + "version": "0.17.1", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.1.tgz", + "integrity": "sha512-Cwo8LE/0rnvX7kIIa3QHCkcuF21c05Ayb0ZfxPiv0W8VRiZiNW/WuRupHKpqqGVGf7SUA44QSOUKaEd9lIrd/Q==", + "dev": true, + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.2", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.2.tgz", + "integrity": "sha512-J2LqtvFYCzaj8pVYKw8klQXrLLk7TBZmQ4ShlcdkELFKGwGMfevMLneMMRkMgZxotOD9wg497LpC7O8PcvAmfw==", + "dev": true, + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-xTE1E+YF4aWPJJeUzaZI5DRntlkY3+BCVJi0axFptnjGmAoWxkyREIh/XMrfxVLejwQxMCfDXdICo0VLxThrog==" + }, + "node_modules/@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "dependencies": { + "@types/node": "*", + "@types/webidl-conversions": "*" + } + }, + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", + "dependencies": { + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==" + }, + "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" + } + ] + }, + "node_modules/body-parser": { + "version": "1.20.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.1.tgz", + "integrity": "sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.11.0", + "raw-body": "2.5.1", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "optional": true + }, + "node_modules/bson": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz", + "integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==", + "dependencies": { + "buffer": "^5.6.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "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" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz", + "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==", + "dependencies": { + "function-bind": "^1.1.1", + "get-intrinsic": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", + "dependencies": { + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.5.0.tgz", + "integrity": "sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==" + }, + "node_modules/database-proxy": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/database-proxy/-/database-proxy-1.0.0-beta.2.tgz", + "integrity": "sha512-sN4TffB5on0vqNs7pNOzgQLkNmVphotehI1ZMpnSXSMDjXN2RQVwMrOWhOFScuF63efj3dlHPahdgmsbzh9KMA==", + "dependencies": { + "database-ql": "^1.0.0-beta.2", + "lodash": "^4.17.21", + "mongodb": "^4.1.1", + "mysql2": "^2.2.5", + "validator": "^13.7.0" + } + }, + "node_modules/database-proxy/node_modules/mongodb": { + "version": "4.16.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.16.0.tgz", + "integrity": "sha512-0EB113Fsucaq1wsY0dOhi1fmZOwFtLOtteQkiqOXGklvWMnSH3g2QS53f0KTP+/6qOkuoXE2JksubSZNmxeI+g==", + "dependencies": { + "bson": "^4.7.2", + "mongodb-connection-string-url": "^2.5.4", + "socks": "^2.7.1" + }, + "engines": { + "node": ">=12.9.0" + }, + "optionalDependencies": { + "@aws-sdk/credential-providers": "^3.186.0", + "saslprep": "^1.0.3" + } + }, + "node_modules/database-ql": { + "version": "1.0.0-beta.2", + "resolved": "https://registry.npmjs.org/database-ql/-/database-ql-1.0.0-beta.2.tgz", + "integrity": "sha512-3q1ttPwaOdaOpG8BiKZOs6Jr8g9cxCM4hBbmFP1VOwijAcXNsbEj04dB6WJjX+THFxa3VFSxvReGC0TfHFxo5g==", + "dependencies": { + "bson": "^4.5.3", + "lodash.clonedeep": "4.5.0", + "lodash.set": "4.3.2", + "lodash.unset": "4.5.2" + } + }, + "node_modules/date-format": { + "version": "4.0.14", + "resolved": "https://registry.npmjs.org/date-format/-/date-format-4.0.14.tgz", + "integrity": "sha512-39BOQLs9ZjKh0/patS9nrT8wc3ioX3/eA/zgbKNopnF2wCqJEoxywwwElATYvRsXdnOxA/OQeQoFZ3rFjVajhg==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "dependencies": { + "ms": "2.0.0" + } + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "engines": { + "node": ">=0.10" + } + }, + "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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/dotenv": { + "version": "16.3.1", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.1.tgz", + "integrity": "sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=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==" + }, + "node_modules/encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==", + "engines": { + "node": ">= 0.8" + } + }, + "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==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/express": { + "version": "4.18.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.18.2.tgz", + "integrity": "sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.1", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.5.0", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.2.0", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.7", + "qs": "6.11.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.18.0", + "serve-static": "1.15.0", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "engines": { + "node": ">= 0.10.0" + } + }, + "node_modules/express-async-errors": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/express-async-errors/-/express-async-errors-3.1.1.tgz", + "integrity": "sha512-h6aK1da4tpqWSbyCa3FxB/V6Ehd4EEB15zyQq9qe75OZBp0krinNKuH4rAY+S/U/2I36vdLAUFSjQJ+TFmODng==", + "peerDependencies": { + "express": "^4.16.2" + } + }, + "node_modules/fast-xml-parser": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz", + "integrity": "sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==", + "funding": [ + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + }, + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + } + ], + "optional": true, + "dependencies": { + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/finalhandler": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz", + "integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==", + "dependencies": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/flatted": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz", + "integrity": "sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ==" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fs-extra": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", + "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + }, + "engines": { + "node": ">=6 <7 || >=8" + } + }, + "node_modules/function-bind": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" + }, + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", + "dependencies": { + "is-property": "^1.0.2" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.1.tgz", + "integrity": "sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw==", + "dependencies": { + "function-bind": "^1.1.1", + "has": "^1.0.3", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3" + }, + "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==" + }, + "node_modules/has": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", + "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", + "dependencies": { + "function-bind": "^1.1.1" + }, + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/has-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.1.tgz", + "integrity": "sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "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==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "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" + } + ] + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ip": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ip/-/ip-2.0.0.tgz", + "integrity": "sha512-WKa+XuLG1A1R0UWhl2+1XQSi+fZWMsYKffMZTTYsiZaUD8k2yDAj5atimTUD2TZkyCkNEeYE5NhFZmupOGtjYQ==" + }, + "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==", + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/is-property": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-property/-/is-property-1.0.2.tgz", + "integrity": "sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==" + }, + "node_modules/jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/lodash.clonedeep": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", + "integrity": "sha512-H5ZhCF25riFd9uB5UCkVKo61m3S/xZk1x4wA6yp/L3RFP6Z/eHH1ymQcGLo7J3GMPfm0V/7m1tryHuGVxpqEBQ==" + }, + "node_modules/lodash.set": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/lodash.set/-/lodash.set-4.3.2.tgz", + "integrity": "sha512-4hNPN5jlm/N/HLMCO43v8BXKq9Z7QdAGc/VGrRD61w8gN9g/6jF9A4L1pbUgBLCffi0w9VsXfTOij5x8iTyFvg==" + }, + "node_modules/lodash.unset": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/lodash.unset/-/lodash.unset-4.5.2.tgz", + "integrity": "sha512-bwKX88k2JhCV9D1vtE8+naDKlLiGrSmf8zi/Y9ivFHwbmRfA8RxS/aVJ+sIht2XOwqoNr4xUPUkGZpc1sHFEKg==" + }, + "node_modules/log4js": { + "version": "6.9.1", + "resolved": "https://registry.npmjs.org/log4js/-/log4js-6.9.1.tgz", + "integrity": "sha512-1somDdy9sChrr9/f4UlzhdaGfDR2c/SaD2a4T7qEkG4jTS57/B3qmnjLYePwQ8cqWnUHZI0iAKxMBpCZICiZ2g==", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "flatted": "^3.2.7", + "rfdc": "^1.3.0", + "streamroller": "^3.1.5" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/log4js/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/log4js/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==" + }, + "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==", + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/memory-pager": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/memory-pager/-/memory-pager-1.5.0.tgz", + "integrity": "sha512-ZS4Bp4r/Zoeq6+NLJpP+0Zzm0pR8whtGPf1XExKLJBAczGMnSi3It14OiNCStjQjM6NU1okjQGSxgEZN8eBYKg==", + "optional": true + }, + "node_modules/merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==" + }, + "node_modules/methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", + "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==", + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "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==", + "dependencies": { + "mime-db": "1.52.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mongodb": { + "version": "5.6.0", + "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-5.6.0.tgz", + "integrity": "sha512-z8qVs9NfobHJm6uzK56XBZF8XwM9H294iRnB7wNjF0SnY93si5HPziIJn+qqvUR5QOff/4L0gCD6SShdR/GtVQ==", + "dependencies": { + "bson": "^5.3.0", + "mongodb-connection-string-url": "^2.6.0", + "socks": "^2.7.1" + }, + "engines": { + "node": ">=14.20.1" + }, + "optionalDependencies": { + "saslprep": "^1.0.3" + }, + "peerDependencies": { + "@aws-sdk/credential-providers": "^3.201.0", + "mongodb-client-encryption": ">=2.3.0 <3", + "snappy": "^7.2.2" + }, + "peerDependenciesMeta": { + "@aws-sdk/credential-providers": { + "optional": true + }, + "mongodb-client-encryption": { + "optional": true + }, + "snappy": { + "optional": true + } + } + }, + "node_modules/mongodb-connection-string-url": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mongodb-connection-string-url/-/mongodb-connection-string-url-2.6.0.tgz", + "integrity": "sha512-WvTZlI9ab0QYtTYnuMLgobULWhokRjtC7db9LtcVfJ+Hsnyr5eo6ZtNAt3Ly24XZScGMelOcGtm7lSn0332tPQ==", + "dependencies": { + "@types/whatwg-url": "^8.2.1", + "whatwg-url": "^11.0.0" + } + }, + "node_modules/mongodb-uri": { + "version": "0.9.7", + "resolved": "https://registry.npmjs.org/mongodb-uri/-/mongodb-uri-0.9.7.tgz", + "integrity": "sha512-s6BdnqNoEYfViPJgkH85X5Nw5NpzxN8hoflKLweNa7vBxt2V7kaS06d74pAtqDxde8fn4r9h4dNdLiFGoNV0KA==", + "engines": { + "node": ">= 0.6.0" + } + }, + "node_modules/mongodb/node_modules/bson": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/bson/-/bson-5.4.0.tgz", + "integrity": "sha512-WRZ5SQI5GfUuKnPTNmAYPiKIof3ORXAF4IRU5UcgmivNIon01rWQlw5RUH954dpu8yGL8T59YShVddIPaU/gFA==", + "engines": { + "node": ">=14.20.1" + } + }, + "node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" + }, + "node_modules/mysql2": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-2.3.3.tgz", + "integrity": "sha512-wxJUev6LgMSgACDkb/InIFxDprRa6T95+VEoR+xPvtngtccNH2dGjEB/fVZ8yg1gWv1510c9CvXuJHi5zUm0ZA==", + "dependencies": { + "denque": "^2.0.1", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^4.0.0", + "lru-cache": "^6.0.0", + "named-placeholders": "^1.1.2", + "seq-queue": "^0.0.5", + "sqlstring": "^2.3.2" + }, + "engines": { + "node": ">= 8.0" + } + }, + "node_modules/mysql2/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==", + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/named-placeholders": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", + "integrity": "sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==", + "dependencies": { + "lru-cache": "^7.14.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/named-placeholders/node_modules/lru-cache": { + "version": "7.18.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", + "integrity": "sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==", + "engines": { + "node": ">=12" + } + }, + "node_modules/negotiator": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/object-inspect": { + "version": "1.12.3", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.12.3.tgz", + "integrity": "sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==" + }, + "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==", + "dependencies": { + "forwarded": "0.2.0", + "ipaddr.js": "1.9.1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/punycode": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.0.tgz", + "integrity": "sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/qs": { + "version": "6.11.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz", + "integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==", + "dependencies": { + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.1.tgz", + "integrity": "sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==", + "dependencies": { + "bytes": "3.1.2", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/rfdc": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.0.tgz", + "integrity": "sha512-V2hovdzFbOi77/WajaSMXk2OLm+xNIeQdMMuB7icj7bk6zi2F8GGAxigcnDFpJHbNyNcgyJDiP+8nOrY5cZGrA==" + }, + "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" + } + ] + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "node_modules/saslprep": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/saslprep/-/saslprep-1.0.3.tgz", + "integrity": "sha512-/MY/PEMbk2SuY5sScONwhUDsV2p77Znkb/q3nSVstq/yQzYJOH/Azh29p9oJLsl3LnQwSvZDKagDGBsBwSooag==", + "optional": true, + "dependencies": { + "sparse-bitfield": "^3.0.3" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/send": { + "version": "0.18.0", + "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", + "integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==", + "dependencies": { + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "mime": "1.6.0", + "ms": "2.1.3", + "on-finished": "2.4.1", + "range-parser": "~1.2.1", + "statuses": "2.0.1" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/send/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==" + }, + "node_modules/seq-queue": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/seq-queue/-/seq-queue-0.0.5.tgz", + "integrity": "sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==" + }, + "node_modules/serve-static": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz", + "integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==", + "dependencies": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.3", + "send": "0.18.0" + }, + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/side-channel": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", + "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==", + "dependencies": { + "call-bind": "^1.0.0", + "get-intrinsic": "^1.0.2", + "object-inspect": "^1.9.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "engines": { + "node": ">= 6.0.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/socks": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/socks/-/socks-2.7.1.tgz", + "integrity": "sha512-7maUZy1N7uo6+WVEX6psASxtNlKaNVMlGQKkG/63nEDdLOWNbiUMoLK7X4uYoLhQstau72mLgfEWcXcwsaHbYQ==", + "dependencies": { + "ip": "^2.0.0", + "smart-buffer": "^4.2.0" + }, + "engines": { + "node": ">= 10.13.0", + "npm": ">= 3.0.0" + } + }, + "node_modules/sparse-bitfield": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", + "integrity": "sha512-kvzhi7vqKTfkh0PZU+2D2PIllw2ymqJKujUcyPMd9Y75Nv4nPbGJZXNhxsgdQab2BmlDct1YnfQCguEvHr7VsQ==", + "optional": true, + "dependencies": { + "memory-pager": "^1.0.2" + } + }, + "node_modules/sqlstring": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.3.tgz", + "integrity": "sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/statuses": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz", + "integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/streamroller": { + "version": "3.1.5", + "resolved": "https://registry.npmjs.org/streamroller/-/streamroller-3.1.5.tgz", + "integrity": "sha512-KFxaM7XT+irxvdqSP1LGLgNWbYN7ay5owZ3r/8t77p+EtSUAfUgtl7be3xtqtOmGUl9K9YPO2ca8133RlTjvKw==", + "dependencies": { + "date-format": "^4.0.14", + "debug": "^4.3.4", + "fs-extra": "^8.1.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/streamroller/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/streamroller/node_modules/ms": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" + }, + "node_modules/strnum": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/strnum/-/strnum-1.0.5.tgz", + "integrity": "sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA==", + "optional": true + }, + "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==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/tr46": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-3.0.0.tgz", + "integrity": "sha512-l7FvfAHlcmulp8kr+flpQZmVwtu7nfRV7NZujtN0OqES8EL4O4e0qqzL0DC5gAvx/ZC/9lk6rhcUwYvkBnBnYA==", + "dependencies": { + "punycode": "^2.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/tslib": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.0.tgz", + "integrity": "sha512-7At1WUettjcSRHXCyYtTselblcHl9PJFFVKiCAy/bY97+BPZXSQ2wbq0P9s8tK2G7dFQfNnlJnPAiArVBVBsfA==", + "optional": true + }, + "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==", + "dependencies": { + "media-typer": "0.3.0", + "mime-types": "~2.1.24" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.1.6.tgz", + "integrity": "sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==", + "dev": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", + "engines": { + "node": ">= 4.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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==", + "engines": { + "node": ">= 0.4.0" + } + }, + "node_modules/uuid": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz", + "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/validator": { + "version": "13.9.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.9.0.tgz", + "integrity": "sha512-B+dGG8U3fdtM0/aNK4/X8CXq/EcxU2WPrPEkJGslb47qyHsxmbggTWK0yEA4qnYVNF+nxNlN88o14hIcPmSIEA==", + "engines": { + "node": ">= 0.10" + } + }, + "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==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/webidl-conversions": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-7.0.0.tgz", + "integrity": "sha512-VwddBukDzu71offAQR975unBIGqfKZpM+8ZX6ySk8nYhVoo5CYaZyzt3YBvYtRtO+aoGlqxPg/B87NGVZ/fu6g==", + "engines": { + "node": ">=12" + } + }, + "node_modules/whatwg-url": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-11.0.0.tgz", + "integrity": "sha512-RKT8HExMpoYx4igMiVMY83lN6UeITKJlBQ+vR/8ZJ8OCdSiN3RwCq+9gH0+Xzj0+5IrM6i4j/6LuvzbZIQgEcQ==", + "dependencies": { + "tr46": "^3.0.0", + "webidl-conversions": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + } + } +} diff --git a/services/log-server/package.json b/services/log-server/package.json new file mode 100644 index 0000000000..276c75ebc6 --- /dev/null +++ b/services/log-server/package.json @@ -0,0 +1,28 @@ +{ + "name": "log-server", + "version": "1.0.0-beta.9", + "description": "the function log server for laf", + "main": "./dist/index.js", + "private": true, + "scripts": { + "dev": "NODE_ENV=development npm run start", + "build": "tsc -p tsconfig.json", + "watch": "tsc -p tsconfig.json -w", + "start": "NODE_ENV=production node dist/index.js", + "prettier": "npx prettier --write ./src" + }, + "devDependencies": { + "@types/express": "^4.17.17", + "@types/mongodb-uri": "^0.9.1", + "typescript": "^5.1.6" + }, + "dependencies": { + "database-proxy": "^1.0.0-beta.2", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "express-async-errors": "^3.1.1", + "log4js": "^6.9.1", + "mongodb": "^5.6.0", + "mongodb-uri": "^0.9.7" + } +} diff --git a/services/log-server/src/config.ts b/services/log-server/src/config.ts new file mode 100644 index 0000000000..b8cefab07c --- /dev/null +++ b/services/log-server/src/config.ts @@ -0,0 +1,44 @@ +import dotenv from 'dotenv' + +dotenv.config() + +export default class Config { + static get DB_URI() { + return process.env['DB_URI'] || '' + } + + /** + * the logger level : 'fatal', 'error', 'warning', 'info', 'debug', 'trace' + */ + static get LOG_LEVEL(): + | 'fatal' + | 'error' + | 'warning' + | 'info' + | 'debug' + | 'trace' { + return (process.env['LOG_LEVEL'] as any) ?? (this.isProd ? 'info' : 'debug') + } + + /** + * in production deploy or not + */ + static get isProd(): boolean { + return process.env.NODE_ENV === 'production' + } + + /** + * the serving port, default is 5060 + */ + static get PORT(): number { + return (process.env.PORT ?? 5060) as number + } + + static get LOG_CAP(): number { + return (process.env.LOG_CAP ?? 10000) as number + } + + static get LOG_SIZE(): number { + return (process.env.LOG_SIZE ?? 10 * 1024 * 1024) as number // 10 MB + } +} diff --git a/services/log-server/src/db.ts b/services/log-server/src/db.ts new file mode 100644 index 0000000000..5d311c9c42 --- /dev/null +++ b/services/log-server/src/db.ts @@ -0,0 +1,45 @@ +import { MongoAccessor } from 'database-proxy' +import * as mongodb_uri from 'mongodb-uri' +import Config from './config' +import { createLogger, logger } from './logger' + +export class DatabaseAgent { + private static _accessor: MongoAccessor = DatabaseAgent._createAccessor() + + /** + * MongoAccessor instance + */ + static get accessor() { + return this._accessor + } + + /** + * Database instance + */ + static get db() { + return this._accessor?.db + } + + /** + * Create MongoAccessor instance + * @returns + */ + private static _createAccessor() { + const { database } = mongodb_uri.parse(Config.DB_URI) + if (!database) throw new Error('db uri parse failed') + const accessor = new MongoAccessor(database, Config.DB_URI) + + accessor.setLogger(createLogger('accessor', 'warning')) + accessor + .init() + .then(async () => { + logger.info('db connected') + }) + .catch((error) => { + logger.error(error) + setTimeout(() => process.exit(101), 0) + }) + + return accessor + } +} diff --git a/services/log-server/src/handler/add-function-log.ts b/services/log-server/src/handler/add-function-log.ts new file mode 100644 index 0000000000..2ab3e89504 --- /dev/null +++ b/services/log-server/src/handler/add-function-log.ts @@ -0,0 +1,23 @@ +import { RequestHandler } from 'express' +import { DatabaseAgent } from '../db' +import ensureCollectionExist from '../helper/ensure-collection-exist' + +const addFunctionLog: RequestHandler = async (req, res) => { + const { appid, log } = req.body + + if (!appid) { + return res.status(400).send('appid is required') + } + + if (!log || typeof log !== 'object' || !log.request_id || !log.func) { + return res.status(400).send('bad log format') + } + + await ensureCollectionExist(appid) + + await DatabaseAgent.db.collection(appid).insertOne(log) + + res.send('ok') +} + +export default addFunctionLog diff --git a/services/log-server/src/handler/get-function-log.ts b/services/log-server/src/handler/get-function-log.ts new file mode 100644 index 0000000000..1bef00df61 --- /dev/null +++ b/services/log-server/src/handler/get-function-log.ts @@ -0,0 +1,42 @@ +import { RequestHandler } from 'express' +import { DatabaseAgent } from '../db' +import ensureCollectionExist from '../helper/ensure-collection-exist' + +const getFunctionLog: RequestHandler = async (req, res) => { + let { page, pageSize, requestId, functionName, appid } = req.query as Record< + string, + any + > + + if (!appid) { + console.log(11) + return res.status(400).send('appid is required') + } + + page = Number(page) || 1 + pageSize = Number(pageSize) || 10 + + await ensureCollectionExist(appid) + + const coll = DatabaseAgent.db.collection(appid) + const query: any = {} + if (requestId) { + query.request_id = requestId + } + if (functionName) { + query.func = functionName + } + + const data = await coll + .find(query, { + limit: pageSize, + skip: (page - 1) * pageSize, + sort: { _id: -1 }, + }) + .toArray() + + const total = await coll.countDocuments(query) + res.send({ data, total }) +} + +export default getFunctionLog diff --git a/services/log-server/src/helper/ensure-collection-exist.ts b/services/log-server/src/helper/ensure-collection-exist.ts new file mode 100644 index 0000000000..9042e93203 --- /dev/null +++ b/services/log-server/src/helper/ensure-collection-exist.ts @@ -0,0 +1,31 @@ +import Config from '../config' +import { DatabaseAgent } from '../db' + +const cache: Record = {} + +const ensureCollectionExist = async (appid: string) => { + if (!appid) throw new Error('appid is required') + if (cache[appid]) return true + + const colls = await DatabaseAgent.db + .listCollections({ name: appid }) + .toArray() + + if (colls.length > 0) { + cache[appid] = true + return true + } + + await DatabaseAgent.db.createCollection(appid, { + capped: true, + max: Config.LOG_CAP, + size: Config.LOG_SIZE, + }) + await DatabaseAgent.db.collection(appid).createIndex({ created_at: 1 }) + + cache[appid] = true + + return true +} + +export default ensureCollectionExist diff --git a/services/log-server/src/index.ts b/services/log-server/src/index.ts new file mode 100644 index 0000000000..96357c5f58 --- /dev/null +++ b/services/log-server/src/index.ts @@ -0,0 +1,47 @@ +import express from 'express' +import { DatabaseAgent } from './db' +import Config from './config' +import { logger } from './logger' +import addFunctionLog from './handler/add-function-log' +import getFunctionLog from './handler/get-function-log' + +require('express-async-errors') +const app = express() + +process.on('unhandledRejection', (reason, promise) => { + logger.error('Caught unhandledRejection:', reason, promise) +}) +process.on('uncaughtException', (err) => { + logger.error('Caught uncaughtException:', err) +}) + +app.use(express.json()) +app.use( + express.urlencoded({ + extended: true, + }), +) + +app.post('/log/add', addFunctionLog) +app.get('/log/functions', getFunctionLog) + +// @ts-ignore +app.use((err, req, res, next) => { + logger.error('Caught error:', err) + res.status(500).send('Internal Server Error') +}) + +const server = app.listen(Config.PORT, () => + logger.info(`server ${process.pid} listened on ${Config.PORT}`), +) + +process.on('SIGTERM', gracefullyExit) +process.on('SIGINT', gracefullyExit) + +async function gracefullyExit() { + await DatabaseAgent.accessor.close() + server.close(async () => { + logger.info('process gracefully exited!') + process.exit(0) + }) +} diff --git a/services/log-server/src/logger.ts b/services/log-server/src/logger.ts new file mode 100644 index 0000000000..16e9b4e816 --- /dev/null +++ b/services/log-server/src/logger.ts @@ -0,0 +1,24 @@ +import { LoggerInterface } from 'database-proxy' +import * as log4js from 'log4js' +import Config from './config' + +/** + * Create logger instance + * @param category log category + * @param level the logger level : 'fatal', 'error', 'warning', 'info', 'debug', 'trace' + * @returns + */ +export function createLogger( + category: string, + level?: string, +): LoggerInterface { + const logger = log4js.getLogger(category) + logger.level = level ?? Config.LOG_LEVEL + + return logger as any +} + +/** + * The global logger instance + */ +export const logger = createLogger('server') diff --git a/services/log-server/tsconfig.json b/services/log-server/tsconfig.json new file mode 100644 index 0000000000..5633583470 --- /dev/null +++ b/services/log-server/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compileOnSave": true, + "compilerOptions": { + "allowJs": false, + "allowUnreachableCode": false, + "allowUnusedLabels": false, + "declaration": false, + "module": "CommonJS", + "target": "ES2022", + "moduleResolution": "NodeNext", + "esModuleInterop": true, + "declarationMap": false, + "noEmitOnError": true, + "noFallthroughCasesInSwitch": true, + "noImplicitAny": false, + "noUnusedLocals": true, + "noUnusedParameters": true, + "outDir": "dist", + "pretty": false, + "removeComments": true, + "stripInternal": true, + "skipDefaultLibCheck": true, + "skipLibCheck": true, + "alwaysStrict": true, + "lib": [ + "ES2022" + ] + }, + "include": [ + "src/**/*", + ], +} \ No newline at end of file From 6f14899663a88969f0daaa1b144f6e17c3acef9b Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Fri, 7 Jul 2023 07:02:33 +0000 Subject: [PATCH 02/14] feat(runtimes&server): adapt to log server --- runtimes/nodejs/src/config.ts | 4 +++ runtimes/nodejs/src/index.ts | 2 -- runtimes/nodejs/src/support/function-log.ts | 25 ++++--------------- server/src/constants.ts | 11 ++++++++ server/src/initializer/initializer.service.ts | 1 + server/src/instance/instance.service.ts | 4 +++ server/src/region/entities/region.ts | 1 + 7 files changed, 26 insertions(+), 22 deletions(-) diff --git a/runtimes/nodejs/src/config.ts b/runtimes/nodejs/src/config.ts index 2ef0e876a2..a536ccfa38 100644 --- a/runtimes/nodejs/src/config.ts +++ b/runtimes/nodejs/src/config.ts @@ -83,4 +83,8 @@ export default class Config { static get REQUEST_LIMIT_SIZE(): string { return process.env.REQUEST_LIMIT_SIZE || '10mb' } + + static get LOG_SERVER_URL(): string { + return process.env.LOG_SERVER_URL || '' + } } diff --git a/runtimes/nodejs/src/index.ts b/runtimes/nodejs/src/index.ts index 9c3735160f..6566ef2a99 100644 --- a/runtimes/nodejs/src/index.ts +++ b/runtimes/nodejs/src/index.ts @@ -21,12 +21,10 @@ import xmlparser from 'express-xml-bodyparser' import './support/cloud-sdk' import { FunctionCache } from './support/function-engine/cache' import { DatabaseChangeStream } from './support/db-change-stream' -import { ensureCollectionIndexes } from './support/function-log' const app = express() DatabaseAgent.accessor.ready.then(() => { - ensureCollectionIndexes() FunctionCache.initialize() DatabaseChangeStream.initialize() }) diff --git a/runtimes/nodejs/src/support/function-log.ts b/runtimes/nodejs/src/support/function-log.ts index a8c900e470..3147f344f8 100644 --- a/runtimes/nodejs/src/support/function-log.ts +++ b/runtimes/nodejs/src/support/function-log.ts @@ -1,5 +1,5 @@ +import axios from 'axios' import Config from '../config' -import { FUNCTION_LOG_COLLECTION } from '../constants' import { DatabaseAgent } from '../db' import { FunctionConsole, FunctionContext } from './function-engine' @@ -21,23 +21,8 @@ FunctionConsole.write = (message: string, ctx: FunctionContext) => { created_at: new Date(), } - db.collection(FUNCTION_LOG_COLLECTION).insertOne(doc) -} - - -/** - * Create necessary indexes of collections - * @param data - * @returns - */ -export async function ensureCollectionIndexes(): Promise { - const db = DatabaseAgent.db - await db.collection(FUNCTION_LOG_COLLECTION).createIndexes([ - { - key: { created_at: 1 }, - expireAfterSeconds: Config.FUNCTION_LOG_EXPIRED_TIME, - }, - ]) - - return true + axios.post(Config.LOG_SERVER_URL, { + appid: Config.APPID, + log: doc, + }) } diff --git a/server/src/constants.ts b/server/src/constants.ts index 1c883c0a5c..df58cf6e0f 100644 --- a/server/src/constants.ts +++ b/server/src/constants.ts @@ -17,6 +17,13 @@ export class ServerConfig { return process.env.METERING_DATABASE_URL } + static get LOG_SERVER_URL() { + if (!process.env.LOG_SERVER_URL) { + throw new Error('LOG_SERVER_URL is not defined') + } + return process.env.LOG_SERVER_URL + } + static get JWT_SECRET() { if (!process.env.JWT_SECRET) { throw new Error('JWT_SECRET is not defined') @@ -143,6 +150,10 @@ export class ServerConfig { static get DEFAULT_REGION_MINIO_ROOT_SECRET_KEY() { return process.env.DEFAULT_REGION_MINIO_ROOT_SECRET_KEY } + + static get DEFAULT_REGION_LOG_SERVER_URL() { + return process.env.DEFAULT_REGION_LOG_SERVER_URL + } } export const LABEL_KEY_USER_ID = 'laf.dev/user.id' diff --git a/server/src/initializer/initializer.service.ts b/server/src/initializer/initializer.service.ts index dcf4cb0471..070a9a0ad1 100644 --- a/server/src/initializer/initializer.service.ts +++ b/server/src/initializer/initializer.service.ts @@ -66,6 +66,7 @@ export class InitializerService { apiUrl: ServerConfig.DEFAULT_REGION_APISIX_API_URL, apiKey: ServerConfig.DEFAULT_REGION_APISIX_API_KEY, }, + logServerUrl: ServerConfig.DEFAULT_REGION_LOG_SERVER_URL, updatedAt: new Date(), createdAt: new Date(), state: 'Active', diff --git a/server/src/instance/instance.service.ts b/server/src/instance/instance.service.ts index 1ca8c17532..b0ff493c02 100644 --- a/server/src/instance/instance.service.ts +++ b/server/src/instance/instance.service.ts @@ -248,6 +248,10 @@ export class InstanceService { name: 'RESTART_AT', value: new Date().getTime().toString(), }, + { + name: 'LOG_SERVER_URL', + value: app.region.logServerUrl, + }, ] // merge env from app configuration, override if exists diff --git a/server/src/region/entities/region.ts b/server/src/region/entities/region.ts index ec38932456..91e43f936b 100644 --- a/server/src/region/entities/region.ts +++ b/server/src/region/entities/region.ts @@ -46,6 +46,7 @@ export class Region { databaseConf: RegionDatabaseConf gatewayConf: RegionGatewayConf storageConf: RegionStorageConf + logServerUrl: string @ApiProperty() tls: boolean From f1337b9b1c5616cdc1a84c6d8e7ca367d402b5da Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Fri, 7 Jul 2023 07:06:37 +0000 Subject: [PATCH 03/14] chore(build): add helm template for log-server --- .../charts/laf-server/templates/_helpers.tpl | 20 +++++++ .../laf-server/templates/deployment.yaml | 4 ++ .../laf-server/templates/log-server.yaml | 52 +++++++++++++++++++ build/charts/laf-server/values.yaml | 4 ++ build/start.sh | 5 ++ 5 files changed, 85 insertions(+) create mode 100644 build/charts/laf-server/templates/log-server.yaml diff --git a/build/charts/laf-server/templates/_helpers.tpl b/build/charts/laf-server/templates/_helpers.tpl index 6870fee0bb..765e59e997 100644 --- a/build/charts/laf-server/templates/_helpers.tpl +++ b/build/charts/laf-server/templates/_helpers.tpl @@ -42,6 +42,18 @@ app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} app.kubernetes.io/managed-by: {{ .Release.Service }} {{- end }} +{{/* +Common labels +*/}} +{{- define "log-server.labels" -}} +helm.sh/chart: {{ include "laf-server.chart" . }} +{{ include "log-server.selectorLabels" . }} +{{- if .Chart.AppVersion }} +app.kubernetes.io/version: {{ .Chart.AppVersion | quote }} +{{- end }} +app.kubernetes.io/managed-by: {{ .Release.Service }} +{{- end }} + {{/* Selector labels */}} @@ -50,6 +62,14 @@ app.kubernetes.io/name: {{ include "laf-server.name" . }} app.kubernetes.io/instance: {{ .Release.Name }} {{- end }} +{{/* +Selector labels +*/}} +{{- define "log-server.selectorLabels" -}} +app.kubernetes.io/name: log-server +app.kubernetes.io/instance: {{ .Release.Name }} +{{- end }} + {{/* Create the name of the service account to use */}} diff --git a/build/charts/laf-server/templates/deployment.yaml b/build/charts/laf-server/templates/deployment.yaml index f23cdbed21..83fe578e18 100644 --- a/build/charts/laf-server/templates/deployment.yaml +++ b/build/charts/laf-server/templates/deployment.yaml @@ -53,6 +53,8 @@ spec: value: {{ .Values.databaseUrl | quote}} - name: METERING_DATABASE_URL value: {{ .Values.meteringDatabaseUrl | quote}} + - name: LOG_SERVER_URL + value: {{ .Values.logServerUrl| quote}} - name: JWT_SECRET value: {{ .Values.jwt.secret | quote}} - name: API_SERVER_URL @@ -83,6 +85,8 @@ spec: value: {{ .Values.default_region.apisix_api_url }} - name: DEFAULT_REGION_APISIX_API_KEY value: {{ .Values.default_region.apisix_api_key }} + - name: DEFAULT_REGION_LOG_SERVER_URL + value: {{ .Values.default_region.log_server_url }} - name: SITE_NAME value: {{ .Values.siteName | quote}} {{- with .Values.nodeSelector }} diff --git a/build/charts/laf-server/templates/log-server.yaml b/build/charts/laf-server/templates/log-server.yaml new file mode 100644 index 0000000000..05c876be29 --- /dev/null +++ b/build/charts/laf-server/templates/log-server.yaml @@ -0,0 +1,52 @@ +apiVersion: apps/v1 +kind: Deployment +metadata: + labels: + {{- include "log-server.labels" . | nindent 4 }} + name: log-server +spec: + replicas: 1 + selector: + matchLabels: + {{- include "log-server.selectorLabels" . | nindent 6 }} + template: + metadata: + labels: + {{- include "log-server.selectorLabels" . | nindent 8 }} + spec: + securityContext: + runAsNonRoot: true + containers: + - image: docker.io/lafyun/log-server:latest + imagePullPolicy: Always + name: log-server + ports: + - name: http + containerPort: 5060 + protocol: TCP + livenessProbe: + httpGet: + path: /healthz + port: http + readinessProbe: + httpGet: + path: /healthz + port: http + env: + - name: DB_URI + value: {{ .Values.logServerDatabaseUrl | quote }} +--- +apiVersion: v1 +kind: Service +metadata: + labels: + {{- include "log-server.labels" . | nindent 4 }} + name: log-server +spec: + ports: + - name: http + port: 5060 + protocol: TCP + targetPort: http + selector: + {{- include "log-server.selectorLabels" . | nindent 4 }} diff --git a/build/charts/laf-server/values.yaml b/build/charts/laf-server/values.yaml index 57e1e7ed4a..490c7eb533 100644 --- a/build/charts/laf-server/values.yaml +++ b/build/charts/laf-server/values.yaml @@ -5,6 +5,8 @@ apiServerHost: "" databaseUrl: "" meteringDatabaseUrl: "" +logServerDatabaseUrl: "" +logServerUrl: "" apiServerUrl: "" siteName: "laf" # init default region conf @@ -24,6 +26,8 @@ default_region: tls: false runtime_domain: "" website_domain: "" + # log-server + log_server_url: "" jwt: secret: laf_server_abc123 expires_in: 7d diff --git a/build/start.sh b/build/start.sh index 1274459ac9..9670bf9595 100644 --- a/build/start.sh +++ b/build/start.sh @@ -71,9 +71,13 @@ helm install minio -n ${NAMESPACE} \ ## 4. install laf-server SERVER_JWT_SECRET=$PASSWD_OR_SECRET +LOG_SERVER_URL="http://log-server-0.log-server.${NAMESPACE}.svc.cluster.local:5060" +LOG_SERVER_DATABASE_URL="mongodb://log-server:${PASSWD_OR_SECRET}@mongodb-0.mongo.${NAMESPACE}.svc.cluster.local:27017/functions-log?authSource=admin&replicaSet=rs0&w=majority" helm install server -n ${NAMESPACE} \ --set databaseUrl=${DATABASE_URL} \ --set meteringDatabaseUrl=${METERING_DATABASE_URL} \ + --set logServerDatabaseUrl=${LOG_SERVER_DATABASE_URL} \ + --set logServerUrl=${LOG_SERVER_URL} \ --set jwt.secret=${SERVER_JWT_SECRET} \ --set apiServerHost=api.${DOMAIN} \ --set apiServerUrl=${HTTP_SCHEMA}://api.${DOMAIN} \ @@ -90,6 +94,7 @@ helm install server -n ${NAMESPACE} \ --set default_region.apisix_api_url=${APISIX_API_URL} \ --set default_region.apisix_api_key=${APISIX_API_KEY} \ --set default_region.apisix_public_port=80 \ + --set default_region.log_server_url=${LOG_SERVER_URL} \ ./charts/laf-server ## 6. install laf-web From c77f48c2b1411daf9c3a8deae638aa31f352e9f9 Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Fri, 7 Jul 2023 07:08:40 +0000 Subject: [PATCH 04/14] chore --- .prettierignore | 1 + lerna.json | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 .prettierignore diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000000..80bf7fc709 --- /dev/null +++ b/.prettierignore @@ -0,0 +1 @@ +charts \ No newline at end of file diff --git a/lerna.json b/lerna.json index 2445dd368f..9acc1444f0 100644 --- a/lerna.json +++ b/lerna.json @@ -5,7 +5,8 @@ "./server", "./web", "./runtimes/nodejs", - "./cli" + "./cli", + "./services/*" ], "version": "1.0.0-beta.9", "command": { From 91908a7e481e833d0e348c6b90dcb2a8c4e07c21 Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Fri, 7 Jul 2023 07:10:14 +0000 Subject: [PATCH 05/14] feat(log-server): health check --- services/log-server/src/index.ts | 1 + 1 file changed, 1 insertion(+) diff --git a/services/log-server/src/index.ts b/services/log-server/src/index.ts index 96357c5f58..4fea1c6035 100644 --- a/services/log-server/src/index.ts +++ b/services/log-server/src/index.ts @@ -24,6 +24,7 @@ app.use( app.post('/log/add', addFunctionLog) app.get('/log/functions', getFunctionLog) +app.get('/healthz', (_, res) => res.send('ok')) // @ts-ignore app.use((err, req, res, next) => { From ecc386553e977308d92d0ae5666f78ce54704c40 Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Fri, 7 Jul 2023 07:36:00 +0000 Subject: [PATCH 06/14] refactor(server): fetch function logs from log server --- server/src/constants.ts | 1 - server/src/function/function.service.ts | 41 ++++++++----------------- 2 files changed, 13 insertions(+), 29 deletions(-) diff --git a/server/src/constants.ts b/server/src/constants.ts index df58cf6e0f..8814166692 100644 --- a/server/src/constants.ts +++ b/server/src/constants.ts @@ -171,7 +171,6 @@ export const HTTP_METHODS = ['HEAD', 'GET', 'POST', 'PUT', 'DELETE', 'PATCH'] export const CN_PUBLISHED_FUNCTIONS = '__functions__' export const CN_PUBLISHED_POLICIES = '__policies__' -export const CN_FUNCTION_LOGS = '__function_logs__' export const CN_PUBLISHED_CONF = '__conf__' export const X_LAF_TRIGGER_TOKEN_KEY = 'x-laf-trigger-token' diff --git a/server/src/function/function.service.ts b/server/src/function/function.service.ts index d9dc36332f..e762d1ac9b 100644 --- a/server/src/function/function.service.ts +++ b/server/src/function/function.service.ts @@ -2,8 +2,8 @@ import { Injectable, Logger } from '@nestjs/common' import { compileTs2js } from '../utils/lang' import { APPLICATION_SECRET_KEY, - CN_FUNCTION_LOGS, CN_PUBLISHED_FUNCTIONS, + ServerConfig, TASK_LOCK_INIT_TIME, } from '../constants' import { CreateFunctionDto } from './dto/create-function.dto' @@ -17,11 +17,11 @@ import { SystemDatabase } from 'src/system-database' import { ObjectId } from 'mongodb' import { CloudFunction } from './entities/cloud-function' import { ApplicationConfiguration } from 'src/application/entities/application-configuration' -import { FunctionLog } from 'src/log/entities/function-log' import { CloudFunctionHistory } from './entities/cloud-function-history' import { TriggerService } from 'src/trigger/trigger.service' import { TriggerPhase } from 'src/trigger/entities/cron-trigger' import { UpdateFunctionDebugDto } from './dto/update-function-debug.dto' +import { HttpService } from '@nestjs/axios' @Injectable() export class FunctionService { @@ -32,6 +32,7 @@ export class FunctionService { private readonly databaseService: DatabaseService, private readonly jwtService: JwtService, private readonly triggerService: TriggerService, + private readonly httpService: HttpService, ) {} async create(appid: string, userid: ObjectId, dto: CreateFunctionDto) { await this.db.collection('CloudFunction').insertOne({ @@ -320,32 +321,16 @@ export class FunctionService { functionName?: string }, ) { - const { page, pageSize, requestId, functionName } = params - const { db, client } = await this.databaseService.findAndConnect(appid) - - try { - const coll = db.collection(CN_FUNCTION_LOGS) - const query: any = {} - if (requestId) { - query.request_id = requestId - } - if (functionName) { - query.func = functionName - } - - const data = await coll - .find(query, { - limit: pageSize, - skip: (page - 1) * pageSize, - sort: { _id: -1 }, - }) - .toArray() - - const total = await coll.countDocuments(query) - return { data, total } - } finally { - await client.close() - } + const res = await this.httpService.axiosRef.get( + ServerConfig.LOG_SERVER_URL, + { + params: { + ...params, + appid, + }, + }, + ) + return res.data } async getHistory(func: CloudFunction) { From cc5df51fd0bca85a2a8bade3d2abe92610a44881 Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Fri, 7 Jul 2023 07:45:01 +0000 Subject: [PATCH 07/14] chore(docs): tidy docs for function log --- docs/en/guide/function/logs.md | 22 ---------------------- docs/guide/function/logs.md | 24 ------------------------ 2 files changed, 46 deletions(-) diff --git a/docs/en/guide/function/logs.md b/docs/en/guide/function/logs.md index 696fe014c6..337262bd8f 100644 --- a/docs/en/guide/function/logs.md +++ b/docs/en/guide/function/logs.md @@ -17,25 +17,3 @@ You can filter logs based on the `requestId` and the name of the cloud function. 1. Click on a log to switch to the log section. 2. Use the `requestId` and the name of the cloud function to search for specific logs. 3. Click on an individual log to view detailed content. - -## Manual Log Cleaning - -The running logs of Laf cloud functions are stored in a hidden collection called `__function_logs__`. Therefore, we can use the method to manipulate the database in cloud functions to clean the logs. - -The following is the code to clean all logs in a cloud function: - -::: danger -The following operation will delete all historical logs. Please proceed with caution. -::: - -```typescript -import cloud from '@lafjs/cloud' - -export async function main(ctx: FunctionContext) { - console.log('Hello World') - // Database, remove all logs - const db = cloud.database(); - const res = await db.collection('__function_logs__').remove({multi:true}) - console.log(res) -} -``` diff --git a/docs/guide/function/logs.md b/docs/guide/function/logs.md index 4e9676f0cf..f1609149cf 100644 --- a/docs/guide/function/logs.md +++ b/docs/guide/function/logs.md @@ -19,27 +19,3 @@ title: 云函数历史日志 2、可根据 `requestId` 和云函数名搜索指定日志 3、点击单个日志,可查看详细内容 - -## 手动清理日志 - -Laf 云函数的运行日志都在一个隐藏的集合中:`__function_logs__` - -所以我们可以通过云函数操作数据库的方法,清理日志 - -以下是清理全部日志的云函数写法: - -::: danger -以下操作会删除全部历史日志,请谨慎操作 -::: - -```typescript -import cloud from '@lafjs/cloud' - -export async function main(ctx: FunctionContext) { - console.log('Hello World') - // 数据库,删除全部日志 - const db = cloud.database(); - const res = await db.collection('__function_logs__').remove({multi:true}) - console.log(res) -} -``` From 0640108b22847ca4b0db5a620312903d26e3e628 Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Fri, 7 Jul 2023 07:47:33 +0000 Subject: [PATCH 08/14] chore: clean code --- build/start.sh | 2 +- runtimes/nodejs/src/config.ts | 7 ------- runtimes/nodejs/src/constants.ts | 1 - runtimes/nodejs/src/support/function-log.ts | 2 +- server/src/function/function.service.ts | 2 +- services/log-server/src/handler/get-function-log.ts | 1 - services/log-server/src/index.ts | 4 ++-- 7 files changed, 5 insertions(+), 14 deletions(-) diff --git a/build/start.sh b/build/start.sh index 9670bf9595..61a75bb548 100644 --- a/build/start.sh +++ b/build/start.sh @@ -72,7 +72,7 @@ helm install minio -n ${NAMESPACE} \ ## 4. install laf-server SERVER_JWT_SECRET=$PASSWD_OR_SECRET LOG_SERVER_URL="http://log-server-0.log-server.${NAMESPACE}.svc.cluster.local:5060" -LOG_SERVER_DATABASE_URL="mongodb://log-server:${PASSWD_OR_SECRET}@mongodb-0.mongo.${NAMESPACE}.svc.cluster.local:27017/functions-log?authSource=admin&replicaSet=rs0&w=majority" +LOG_SERVER_DATABASE_URL="mongodb://log-server:${PASSWD_OR_SECRET}@mongodb-0.mongo.${NAMESPACE}.svc.cluster.local:27017/function-logs?authSource=admin&replicaSet=rs0&w=majority" helm install server -n ${NAMESPACE} \ --set databaseUrl=${DATABASE_URL} \ --set meteringDatabaseUrl=${METERING_DATABASE_URL} \ diff --git a/runtimes/nodejs/src/config.ts b/runtimes/nodejs/src/config.ts index a536ccfa38..8e3be23bb7 100644 --- a/runtimes/nodejs/src/config.ts +++ b/runtimes/nodejs/src/config.ts @@ -57,13 +57,6 @@ export default class Config { return process.env.NODE_ENV === 'production' } - /** - * Expired time of function logs, in seconds - */ - static get FUNCTION_LOG_EXPIRED_TIME(): number { - return (process.env.FUNCTION_LOG_EXPIRED_TIME ?? 3600 * 24 * 3) as number - } - static get RUNTIME_IMAGE(): string { return process.env.RUNTIME_IMAGE } diff --git a/runtimes/nodejs/src/constants.ts b/runtimes/nodejs/src/constants.ts index a773c49958..9185b94ce2 100644 --- a/runtimes/nodejs/src/constants.ts +++ b/runtimes/nodejs/src/constants.ts @@ -3,7 +3,6 @@ */ export const CLOUD_FUNCTION_COLLECTION = '__functions__' export const POLICY_COLLECTION = '__policies__' -export const FUNCTION_LOG_COLLECTION = '__function_logs__' export const CONFIG_COLLECTION = '__conf__' export const WEBSOCKET_FUNCTION_NAME = '__websocket__' diff --git a/runtimes/nodejs/src/support/function-log.ts b/runtimes/nodejs/src/support/function-log.ts index 3147f344f8..374e3a46db 100644 --- a/runtimes/nodejs/src/support/function-log.ts +++ b/runtimes/nodejs/src/support/function-log.ts @@ -21,7 +21,7 @@ FunctionConsole.write = (message: string, ctx: FunctionContext) => { created_at: new Date(), } - axios.post(Config.LOG_SERVER_URL, { + axios.post(`${Config.LOG_SERVER_URL}/function/log`, { appid: Config.APPID, log: doc, }) diff --git a/server/src/function/function.service.ts b/server/src/function/function.service.ts index e762d1ac9b..7c5cca9453 100644 --- a/server/src/function/function.service.ts +++ b/server/src/function/function.service.ts @@ -322,7 +322,7 @@ export class FunctionService { }, ) { const res = await this.httpService.axiosRef.get( - ServerConfig.LOG_SERVER_URL, + `${ServerConfig.LOG_SERVER_URL}/function/log`, { params: { ...params, diff --git a/services/log-server/src/handler/get-function-log.ts b/services/log-server/src/handler/get-function-log.ts index 1bef00df61..75c224356b 100644 --- a/services/log-server/src/handler/get-function-log.ts +++ b/services/log-server/src/handler/get-function-log.ts @@ -9,7 +9,6 @@ const getFunctionLog: RequestHandler = async (req, res) => { > if (!appid) { - console.log(11) return res.status(400).send('appid is required') } diff --git a/services/log-server/src/index.ts b/services/log-server/src/index.ts index 4fea1c6035..57bf97b359 100644 --- a/services/log-server/src/index.ts +++ b/services/log-server/src/index.ts @@ -22,8 +22,8 @@ app.use( }), ) -app.post('/log/add', addFunctionLog) -app.get('/log/functions', getFunctionLog) +app.post('/function/log', addFunctionLog) +app.get('/function/log', getFunctionLog) app.get('/healthz', (_, res) => res.send('ok')) // @ts-ignore From 32555f48268c895663c1300fbeda65be4cd77eb7 Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Fri, 7 Jul 2023 08:34:53 +0000 Subject: [PATCH 09/14] chore(ci): dockerize log server --- .github/workflows/dockerize-log-server.yml | 76 ++++++++++++++++++++++ 1 file changed, 76 insertions(+) create mode 100644 .github/workflows/dockerize-log-server.yml diff --git a/.github/workflows/dockerize-log-server.yml b/.github/workflows/dockerize-log-server.yml new file mode 100644 index 0000000000..af630d235a --- /dev/null +++ b/.github/workflows/dockerize-log-server.yml @@ -0,0 +1,76 @@ +name: dockerize-log-server + +on: + workflow_dispatch: + push: + branches: + - main + paths: + - "services/log-server/**" + - ".github/workflows/dockerize-log-server.yml" + - "!**/*.md" + - "!services/log-server/package-lock.json" + +concurrency: + group: dockerize-log-server-${{ github.ref }} + cancel-in-progress: true + +jobs: + dockerize-log-server: + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v3 + with: + fetch-depth: 0 + + - name: Docker meta + id: meta + uses: docker/metadata-action@v4 + with: + images: | + ghcr.io/${{ github.repository_owner }}/log-server + docker.io/${{ secrets.DOCKER_USERNAME }}/log-server + # https://github.com/docker/metadata-action#typesemver + tags: | + type=raw,value=latest,enable=true + type=sha,enable=true,format=short + + - name: Set up QEMU + uses: docker/setup-qemu-action@v2 + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + + - name: Login to DockerHub + uses: docker/login-action@v2 + with: + username: ${{ secrets.DOCKER_USERNAME }} + password: ${{ secrets.DOCKER_PASSWORD }} + + - name: Login to Github Container Hub + uses: docker/login-action@v2 + with: + registry: ghcr.io + username: ${{ github.repository_owner }} + password: ${{ secrets.GITHUB_TOKEN }} + + - name: Build and push + uses: docker/build-push-action@v3 + with: + context: ./services/log-server + file: ./services/log-server/Dockerfile + push: true + tags: ${{ steps.meta.outputs.tags }} + labels: ${{ steps.meta.outputs.labels }} + platforms: linux/amd64, linux/arm64 + + trigger-workflow-build-cluster-image: + needs: [dockerize-log-server] + runs-on: ubuntu-latest + steps: + - name: trigger cluster image workflow + uses: peter-evans/repository-dispatch@v2 + with: + event-type: docker_build_success + client-payload: '{"ref": "${{ github.ref }}", "sha": "${{ github.sha }}", "version": "latest"}' From 7777513ec8c0d3c920edc0cf6ecad36ed7b184c4 Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Mon, 10 Jul 2023 10:58:07 +0800 Subject: [PATCH 10/14] fix(server): replace db in FunctionConsole.write --- runtimes/nodejs/src/support/function-log.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/runtimes/nodejs/src/support/function-log.ts b/runtimes/nodejs/src/support/function-log.ts index 374e3a46db..8016436267 100644 --- a/runtimes/nodejs/src/support/function-log.ts +++ b/runtimes/nodejs/src/support/function-log.ts @@ -1,6 +1,5 @@ import axios from 'axios' import Config from '../config' -import { DatabaseAgent } from '../db' import { FunctionConsole, FunctionContext } from './function-engine' export interface IFunctionLog { @@ -11,8 +10,7 @@ export interface IFunctionLog { } FunctionConsole.write = (message: string, ctx: FunctionContext) => { - const db = DatabaseAgent.db - if (!db) return + if (!Config.LOG_SERVER_URL) return const doc = { request_id: ctx.requestId, From c9a5bd344196ea1ed5d87579ecb92aa8e53ef839 Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Mon, 10 Jul 2023 08:30:41 +0000 Subject: [PATCH 11/14] feat: verify appid for log server --- runtimes/nodejs/src/config.ts | 4 + .../src/support/function-engine/console.ts | 22 +++++- runtimes/nodejs/src/support/function-log.ts | 26 ------- server/src/application/application.module.ts | 9 ++- server/src/constants.ts | 11 +++ server/src/function/function.module.ts | 5 +- server/src/initializer/initializer.service.ts | 5 +- server/src/instance/instance.service.ts | 15 +++- server/src/region/entities/region.ts | 7 +- services/log-server/package-lock.json | 77 +++++++++++++++++++ services/log-server/package.json | 2 + services/log-server/src/config.ts | 7 ++ .../src/handler/add-function-log.ts | 8 +- .../src/handler/get-function-log.ts | 8 +- .../log-server/src/helper/verify-appid.ts | 13 ++++ 15 files changed, 184 insertions(+), 35 deletions(-) delete mode 100644 runtimes/nodejs/src/support/function-log.ts create mode 100644 services/log-server/src/helper/verify-appid.ts diff --git a/runtimes/nodejs/src/config.ts b/runtimes/nodejs/src/config.ts index 8e3be23bb7..dde5f5d1d5 100644 --- a/runtimes/nodejs/src/config.ts +++ b/runtimes/nodejs/src/config.ts @@ -80,4 +80,8 @@ export default class Config { static get LOG_SERVER_URL(): string { return process.env.LOG_SERVER_URL || '' } + + static get LOG_SERVER_TOKEN(): string { + return process.env.LOG_SERVER_TOKEN || '' + } } diff --git a/runtimes/nodejs/src/support/function-engine/console.ts b/runtimes/nodejs/src/support/function-engine/console.ts index 71e009aafe..ae2f8b8236 100644 --- a/runtimes/nodejs/src/support/function-engine/console.ts +++ b/runtimes/nodejs/src/support/function-engine/console.ts @@ -1,10 +1,30 @@ import * as util from 'util' import { FunctionContext } from './types' +import Config from '../../config' +import axios from 'axios' export class FunctionConsole { ctx: FunctionContext - static write: (message: string, ctx: FunctionContext) => void = console.log + static write(message: string, ctx: FunctionContext) { + if (!Config.LOG_SERVER_URL || !Config.LOG_SERVER_TOKEN) return + + const doc = { + request_id: ctx.requestId, + func: ctx.__function_name, + data: message, + created_at: new Date(), + } + + axios.post(`${Config.LOG_SERVER_URL}/function/log`, { + appid: Config.APPID, + log: doc, + }, { + headers: { + 'x-token': Config.LOG_SERVER_TOKEN + } + }) + } constructor(ctx: FunctionContext) { this.ctx = ctx diff --git a/runtimes/nodejs/src/support/function-log.ts b/runtimes/nodejs/src/support/function-log.ts deleted file mode 100644 index 8016436267..0000000000 --- a/runtimes/nodejs/src/support/function-log.ts +++ /dev/null @@ -1,26 +0,0 @@ -import axios from 'axios' -import Config from '../config' -import { FunctionConsole, FunctionContext } from './function-engine' - -export interface IFunctionLog { - request_id: string - func: string - data: string - created_at: Date -} - -FunctionConsole.write = (message: string, ctx: FunctionContext) => { - if (!Config.LOG_SERVER_URL) return - - const doc = { - request_id: ctx.requestId, - func: ctx.__function_name, - data: message, - created_at: new Date(), - } - - axios.post(`${Config.LOG_SERVER_URL}/function/log`, { - appid: Config.APPID, - log: doc, - }) -} diff --git a/server/src/application/application.module.ts b/server/src/application/application.module.ts index 8d9dd8d301..fe2aea57f5 100644 --- a/server/src/application/application.module.ts +++ b/server/src/application/application.module.ts @@ -16,9 +16,16 @@ import { WebsiteService } from 'src/website/website.service' import { AccountModule } from 'src/account/account.module' import { BundleService } from './bundle.service' import { ResourceService } from 'src/billing/resource.service' +import { HttpModule } from '@nestjs/axios' @Module({ - imports: [StorageModule, DatabaseModule, GatewayModule, AccountModule], + imports: [ + StorageModule, + DatabaseModule, + GatewayModule, + AccountModule, + HttpModule, + ], controllers: [ApplicationController, EnvironmentVariableController], providers: [ ApplicationService, diff --git a/server/src/constants.ts b/server/src/constants.ts index 8814166692..281676f234 100644 --- a/server/src/constants.ts +++ b/server/src/constants.ts @@ -31,6 +31,13 @@ export class ServerConfig { return process.env.JWT_SECRET } + static get LOG_SERVER_SECRET() { + if (!process.env.LOG_SERVER_SECRET) { + throw new Error('LOG_SERVER_SECRET is not defined') + } + return process.env.LOG_SERVER_SECRET + } + static get JWT_EXPIRES_IN() { return process.env.JWT_EXPIRES_IN || '7d' } @@ -154,6 +161,10 @@ export class ServerConfig { static get DEFAULT_REGION_LOG_SERVER_URL() { return process.env.DEFAULT_REGION_LOG_SERVER_URL } + + static get DEFAULT_REGION_LOG_SERVER_SECRET() { + return process.env.DEFAULT_REGION_LOG_SERVER_SECRET + } } export const LABEL_KEY_USER_ID = 'laf.dev/user.id' diff --git a/server/src/function/function.module.ts b/server/src/function/function.module.ts index fb6e9bafd8..143870469b 100644 --- a/server/src/function/function.module.ts +++ b/server/src/function/function.module.ts @@ -1,13 +1,14 @@ import { Module } from '@nestjs/common' import { JwtService } from '@nestjs/jwt' -import { ApplicationModule } from '../application/application.module' import { FunctionController } from './function.controller' import { FunctionService } from './function.service' import { DatabaseModule } from 'src/database/database.module' import { TriggerService } from 'src/trigger/trigger.service' +import { HttpModule } from '@nestjs/axios' +import { ApplicationModule } from 'src/application/application.module' @Module({ - imports: [ApplicationModule, DatabaseModule], + imports: [ApplicationModule, DatabaseModule, HttpModule], controllers: [FunctionController], providers: [FunctionService, JwtService, TriggerService], exports: [FunctionService], diff --git a/server/src/initializer/initializer.service.ts b/server/src/initializer/initializer.service.ts index 070a9a0ad1..1c01990867 100644 --- a/server/src/initializer/initializer.service.ts +++ b/server/src/initializer/initializer.service.ts @@ -66,7 +66,10 @@ export class InitializerService { apiUrl: ServerConfig.DEFAULT_REGION_APISIX_API_URL, apiKey: ServerConfig.DEFAULT_REGION_APISIX_API_KEY, }, - logServerUrl: ServerConfig.DEFAULT_REGION_LOG_SERVER_URL, + logServerConf: { + apiUrl: ServerConfig.DEFAULT_REGION_LOG_SERVER_URL, + secret: ServerConfig.DEFAULT_REGION_LOG_SERVER_SECRET, + }, updatedAt: new Date(), createdAt: new Date(), state: 'Active', diff --git a/server/src/instance/instance.service.ts b/server/src/instance/instance.service.ts index b0ff493c02..3f8255938d 100644 --- a/server/src/instance/instance.service.ts +++ b/server/src/instance/instance.service.ts @@ -18,6 +18,7 @@ import { ClusterService } from 'src/region/cluster/cluster.service' import { SystemDatabase } from 'src/system-database' import { ApplicationWithRelations } from 'src/application/entities/application' import { ApplicationService } from 'src/application/application.service' +import { JwtService } from '@nestjs/jwt' @Injectable() export class InstanceService { @@ -29,6 +30,7 @@ export class InstanceService { private readonly storageService: StorageService, private readonly databaseService: DatabaseService, private readonly applicationService: ApplicationService, + private readonly jwtService: JwtService, ) {} public async create(appid: string) { @@ -250,7 +252,18 @@ export class InstanceService { }, { name: 'LOG_SERVER_URL', - value: app.region.logServerUrl, + value: app.region.logServerConf.apiUrl, + }, + { + name: 'LOG_SERVER_TOKEN', + value: this.jwtService.sign( + { + appid: app.appid, + }, + { + secret: app.region.logServerConf.secret, + }, + ), }, ] diff --git a/server/src/region/entities/region.ts b/server/src/region/entities/region.ts index 91e43f936b..1ee6382a42 100644 --- a/server/src/region/entities/region.ts +++ b/server/src/region/entities/region.ts @@ -32,6 +32,11 @@ export type RegionStorageConf = { controlEndpoint: string } +export type LogServerConf = { + apiUrl: string + secret: string +} + export class Region { @ApiProperty({ type: String }) _id?: ObjectId @@ -46,7 +51,7 @@ export class Region { databaseConf: RegionDatabaseConf gatewayConf: RegionGatewayConf storageConf: RegionStorageConf - logServerUrl: string + logServerConf: LogServerConf @ApiProperty() tls: boolean diff --git a/services/log-server/package-lock.json b/services/log-server/package-lock.json index feb6d279c4..a715e0e014 100644 --- a/services/log-server/package-lock.json +++ b/services/log-server/package-lock.json @@ -12,12 +12,14 @@ "dotenv": "^16.3.1", "express": "^4.18.2", "express-async-errors": "^3.1.1", + "jsonwebtoken": "^9.0.1", "log4js": "^6.9.1", "mongodb": "^5.6.0", "mongodb-uri": "^0.9.7" }, "devDependencies": { "@types/express": "^4.17.17", + "@types/jsonwebtoken": "^9.0.2", "@types/mongodb-uri": "^0.9.1", "typescript": "^5.1.6" } @@ -1211,6 +1213,15 @@ "integrity": "sha512-/K3ds8TRAfBvi5vfjuz8y6+GiAYBZ0x4tXv1Av6CWBWn0IlADc+ZX9pMq7oU0fNQPnBwIZl3rmeLp6SBApbxSQ==", "dev": true }, + "node_modules/@types/jsonwebtoken": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/@types/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", + "integrity": "sha512-drE6uz7QBKq1fYqqoFKTDRdFCPHd5TCub75BM+D+cMx7NU9hUz7SESLfC2fSCXVFMO5Yj8sOWHuGqPgjc+fz0Q==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, "node_modules/@types/mime": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz", @@ -1374,6 +1385,11 @@ "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==" + }, "node_modules/bytes": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", @@ -1518,6 +1534,14 @@ "url": "https://github.com/motdotla/dotenv?sponsor=1" } }, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", @@ -1807,6 +1831,45 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonwebtoken": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.1.tgz", + "integrity": "sha512-K8wx7eJ5TPvEjuiVSkv167EVboBDv9PZdDoF7BgeQnBLVvZWW9clr2PsQHVJDTKaEIH5JBIwHujGcHp7GgI2eg==", + "dependencies": { + "jws": "^3.2.2", + "lodash": "^4.17.21", + "ms": "^2.1.1", + "semver": "^7.3.8" + }, + "engines": { + "node": ">=12", + "npm": ">=6" + } + }, + "node_modules/jsonwebtoken/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==" + }, + "node_modules/jwa": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jwa/-/jwa-1.4.1.tgz", + "integrity": "sha512-qiLX/xhEEFKUAJ6FiBMbes3w9ATzyk5W7Hvzpa/SLYdxNtng+gcurvrI7TbACjIXlsJyr05/S1oUhZrc63evQA==", + "dependencies": { + "buffer-equal-constant-time": "1.0.1", + "ecdsa-sig-formatter": "1.0.11", + "safe-buffer": "^5.0.1" + } + }, + "node_modules/jws": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/jws/-/jws-3.2.2.tgz", + "integrity": "sha512-YHlZCB6lMTllWDtSPHz/ZXTsi8S00usEV6v1tjq8tOUZzw7DpSDWVXjXDre6ed1w/pd495ODpHZYSdkRTsa0HA==", + "dependencies": { + "jwa": "^1.4.1", + "safe-buffer": "^5.0.1" + } + }, "node_modules/lodash": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", @@ -2183,6 +2246,20 @@ "node": ">=6" } }, + "node_modules/semver": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", + "integrity": "sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==", + "dependencies": { + "lru-cache": "^6.0.0" + }, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", diff --git a/services/log-server/package.json b/services/log-server/package.json index 276c75ebc6..a04494b868 100644 --- a/services/log-server/package.json +++ b/services/log-server/package.json @@ -13,6 +13,7 @@ }, "devDependencies": { "@types/express": "^4.17.17", + "@types/jsonwebtoken": "^9.0.2", "@types/mongodb-uri": "^0.9.1", "typescript": "^5.1.6" }, @@ -21,6 +22,7 @@ "dotenv": "^16.3.1", "express": "^4.18.2", "express-async-errors": "^3.1.1", + "jsonwebtoken": "^9.0.1", "log4js": "^6.9.1", "mongodb": "^5.6.0", "mongodb-uri": "^0.9.7" diff --git a/services/log-server/src/config.ts b/services/log-server/src/config.ts index b8cefab07c..add7580fa8 100644 --- a/services/log-server/src/config.ts +++ b/services/log-server/src/config.ts @@ -41,4 +41,11 @@ export default class Config { static get LOG_SIZE(): number { return (process.env.LOG_SIZE ?? 10 * 1024 * 1024) as number // 10 MB } + + static get JWT_SECRET(): string { + if (!process.env.JWT_SECRET) { + throw new Error('JWT_SECRET is not defined') + } + return process.env.JWT_SECRET + } } diff --git a/services/log-server/src/handler/add-function-log.ts b/services/log-server/src/handler/add-function-log.ts index 2ab3e89504..3d6b8bcf70 100644 --- a/services/log-server/src/handler/add-function-log.ts +++ b/services/log-server/src/handler/add-function-log.ts @@ -1,14 +1,20 @@ import { RequestHandler } from 'express' import { DatabaseAgent } from '../db' import ensureCollectionExist from '../helper/ensure-collection-exist' +import verifyAppid from '../helper/verify-appid' const addFunctionLog: RequestHandler = async (req, res) => { const { appid, log } = req.body - + const token = req.headers['x-token'] as string + if (!appid) { return res.status(400).send('appid is required') } + if (!token || !verifyAppid(appid, token)) { + return res.status(403).send('forbidden') + } + if (!log || typeof log !== 'object' || !log.request_id || !log.func) { return res.status(400).send('bad log format') } diff --git a/services/log-server/src/handler/get-function-log.ts b/services/log-server/src/handler/get-function-log.ts index 75c224356b..db179f5813 100644 --- a/services/log-server/src/handler/get-function-log.ts +++ b/services/log-server/src/handler/get-function-log.ts @@ -1,12 +1,18 @@ import { RequestHandler } from 'express' import { DatabaseAgent } from '../db' import ensureCollectionExist from '../helper/ensure-collection-exist' +import Config from '../config' const getFunctionLog: RequestHandler = async (req, res) => { let { page, pageSize, requestId, functionName, appid } = req.query as Record< string, any - > + > + const token = req.headers['x-token'] as string + + if (!token || Config.JWT_SECRET !== token) { + return res.status(403).send('forbidden') + } if (!appid) { return res.status(400).send('appid is required') diff --git a/services/log-server/src/helper/verify-appid.ts b/services/log-server/src/helper/verify-appid.ts new file mode 100644 index 0000000000..593b5a7b81 --- /dev/null +++ b/services/log-server/src/helper/verify-appid.ts @@ -0,0 +1,13 @@ +import jwt from 'jsonwebtoken' +import Config from '../config' + +const verifyAppid = (appid: string, token: string): boolean => { + try { + const decoded = jwt.verify(token, Config.JWT_SECRET) + return decoded['appid'] === appid + } catch { + return false + } +} + +export default verifyAppid \ No newline at end of file From 373b45b8ed823fbeb7264e3cd2686ffa99d04431 Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Mon, 10 Jul 2023 08:36:16 +0000 Subject: [PATCH 12/14] chore(runtimes): restart app when file changes --- runtimes/nodejs/package.json | 8 +++++--- runtimes/nodejs/start.sh | 4 ++-- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/runtimes/nodejs/package.json b/runtimes/nodejs/package.json index 4ac32a38a0..535c5d77fa 100644 --- a/runtimes/nodejs/package.json +++ b/runtimes/nodejs/package.json @@ -6,8 +6,10 @@ "typings": "./dist/index.d.ts", "private": "true", "scripts": { - "start": "node --expose-internals ./dist/index.js", - "dev": "NODE_ENV=development npm run start", + "start": "node ./dist/index.js", + "dev": "npx concurrently npm:dev:*", + "dev:start": "npx nodemon ./dist/index.js", + "dev:watch": "npm run watch", "build": "tsc -p tsconfig.json", "watch": "tsc -p tsconfig.json -w", "prepublishOnly": "npm run build", @@ -73,4 +75,4 @@ ], "delay": 1000 } -} +} \ No newline at end of file diff --git a/runtimes/nodejs/start.sh b/runtimes/nodejs/start.sh index 7cdeb42468..98dd3edf19 100644 --- a/runtimes/nodejs/start.sh +++ b/runtimes/nodejs/start.sh @@ -1,5 +1,5 @@ #!/bin/sh # source .env -echo "****** start service: node $FLAGS --expose-internals --experimental-fetch ./dist/index.js *******" -exec node $FLAGS --expose-internals --experimental-fetch ./dist/index.js \ No newline at end of file +echo "****** start service: node $FLAGS --experimental-fetch ./dist/index.js *******" +exec node $FLAGS --experimental-fetch ./dist/index.js \ No newline at end of file From b169f9b4bdf96a2c0c9ab03249da0f3051f4c475 Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Mon, 10 Jul 2023 09:02:49 +0000 Subject: [PATCH 13/14] chore: adjust env and region conf for supporting log server --- build/charts/laf-server/templates/deployment.yaml | 6 ++++-- build/charts/laf-server/templates/log-server.yaml | 6 +++--- build/charts/laf-server/values.yaml | 4 ++-- build/start.sh | 9 +++++---- server/src/constants.ts | 4 ++++ server/src/initializer/initializer.service.ts | 1 + server/src/region/entities/region.ts | 1 + 7 files changed, 20 insertions(+), 11 deletions(-) diff --git a/build/charts/laf-server/templates/deployment.yaml b/build/charts/laf-server/templates/deployment.yaml index 83fe578e18..23e57414a7 100644 --- a/build/charts/laf-server/templates/deployment.yaml +++ b/build/charts/laf-server/templates/deployment.yaml @@ -53,8 +53,6 @@ spec: value: {{ .Values.databaseUrl | quote}} - name: METERING_DATABASE_URL value: {{ .Values.meteringDatabaseUrl | quote}} - - name: LOG_SERVER_URL - value: {{ .Values.logServerUrl| quote}} - name: JWT_SECRET value: {{ .Values.jwt.secret | quote}} - name: API_SERVER_URL @@ -87,6 +85,10 @@ spec: value: {{ .Values.default_region.apisix_api_key }} - name: DEFAULT_REGION_LOG_SERVER_URL value: {{ .Values.default_region.log_server_url }} + - name: DEFAULT_REGION_LOG_SERVER_SECRET + value: {{ .Values.default_region.log_server_secret }} + - name: DEFAULT_REGION_LOG_SERVER_DATABASE_URL + value: {{ .Values.default_region.log_server_database_url }} - name: SITE_NAME value: {{ .Values.siteName | quote}} {{- with .Values.nodeSelector }} diff --git a/build/charts/laf-server/templates/log-server.yaml b/build/charts/laf-server/templates/log-server.yaml index 05c876be29..4a85e00ab5 100644 --- a/build/charts/laf-server/templates/log-server.yaml +++ b/build/charts/laf-server/templates/log-server.yaml @@ -14,8 +14,6 @@ spec: labels: {{- include "log-server.selectorLabels" . | nindent 8 }} spec: - securityContext: - runAsNonRoot: true containers: - image: docker.io/lafyun/log-server:latest imagePullPolicy: Always @@ -34,7 +32,9 @@ spec: port: http env: - name: DB_URI - value: {{ .Values.logServerDatabaseUrl | quote }} + value: {{ .Values.default_region.log_server_database_url | quote }} + - name: JWT_SECRET + value: {{ .Values.default_region.log_server_secret | quote }} --- apiVersion: v1 kind: Service diff --git a/build/charts/laf-server/values.yaml b/build/charts/laf-server/values.yaml index 490c7eb533..c7c3946020 100644 --- a/build/charts/laf-server/values.yaml +++ b/build/charts/laf-server/values.yaml @@ -5,8 +5,6 @@ apiServerHost: "" databaseUrl: "" meteringDatabaseUrl: "" -logServerDatabaseUrl: "" -logServerUrl: "" apiServerUrl: "" siteName: "laf" # init default region conf @@ -28,6 +26,8 @@ default_region: website_domain: "" # log-server log_server_url: "" + log_server_secret: "" + log_server_database_url: "" jwt: secret: laf_server_abc123 expires_in: 7d diff --git a/build/start.sh b/build/start.sh index 61a75bb548..7a839a36a2 100644 --- a/build/start.sh +++ b/build/start.sh @@ -71,13 +71,12 @@ helm install minio -n ${NAMESPACE} \ ## 4. install laf-server SERVER_JWT_SECRET=$PASSWD_OR_SECRET -LOG_SERVER_URL="http://log-server-0.log-server.${NAMESPACE}.svc.cluster.local:5060" -LOG_SERVER_DATABASE_URL="mongodb://log-server:${PASSWD_OR_SECRET}@mongodb-0.mongo.${NAMESPACE}.svc.cluster.local:27017/function-logs?authSource=admin&replicaSet=rs0&w=majority" +LOG_SERVER_URL="http://log-server.${NAMESPACE}.svc.cluster.local:5060" +LOG_SERVER_DATABASE_URL="mongodb://${DB_USERNAME:-admin}:${PASSWD_OR_SECRET}@mongodb-0.mongo.${NAMESPACE}.svc.cluster.local:27017/function-logs?authSource=admin&replicaSet=rs0&w=majority" +LOG_SERVER_SECRET=$PASSWD_OR_SECRET helm install server -n ${NAMESPACE} \ --set databaseUrl=${DATABASE_URL} \ --set meteringDatabaseUrl=${METERING_DATABASE_URL} \ - --set logServerDatabaseUrl=${LOG_SERVER_DATABASE_URL} \ - --set logServerUrl=${LOG_SERVER_URL} \ --set jwt.secret=${SERVER_JWT_SECRET} \ --set apiServerHost=api.${DOMAIN} \ --set apiServerUrl=${HTTP_SCHEMA}://api.${DOMAIN} \ @@ -95,6 +94,8 @@ helm install server -n ${NAMESPACE} \ --set default_region.apisix_api_key=${APISIX_API_KEY} \ --set default_region.apisix_public_port=80 \ --set default_region.log_server_url=${LOG_SERVER_URL} \ + --set default_region.log_server_secret=${LOG_SERVER_SECRET} \ + --set default_region.log_server_database_url=${LOG_SERVER_DATABASE_URL} \ ./charts/laf-server ## 6. install laf-web diff --git a/server/src/constants.ts b/server/src/constants.ts index 281676f234..fdbb82a45f 100644 --- a/server/src/constants.ts +++ b/server/src/constants.ts @@ -165,6 +165,10 @@ export class ServerConfig { static get DEFAULT_REGION_LOG_SERVER_SECRET() { return process.env.DEFAULT_REGION_LOG_SERVER_SECRET } + + static get DEFAULT_REGION_LOG_SERVER_DATABASE_URL() { + return process.env.DEFAULT_REGION_LOG_SERVER_DATABASE_URL + } } export const LABEL_KEY_USER_ID = 'laf.dev/user.id' diff --git a/server/src/initializer/initializer.service.ts b/server/src/initializer/initializer.service.ts index 1c01990867..6f161bca05 100644 --- a/server/src/initializer/initializer.service.ts +++ b/server/src/initializer/initializer.service.ts @@ -69,6 +69,7 @@ export class InitializerService { logServerConf: { apiUrl: ServerConfig.DEFAULT_REGION_LOG_SERVER_URL, secret: ServerConfig.DEFAULT_REGION_LOG_SERVER_SECRET, + databaseUrl: ServerConfig.DEFAULT_REGION_LOG_SERVER_DATABASE_URL, }, updatedAt: new Date(), createdAt: new Date(), diff --git a/server/src/region/entities/region.ts b/server/src/region/entities/region.ts index 1ee6382a42..c076ad95b9 100644 --- a/server/src/region/entities/region.ts +++ b/server/src/region/entities/region.ts @@ -35,6 +35,7 @@ export type RegionStorageConf = { export type LogServerConf = { apiUrl: string secret: string + databaseUrl: string } export class Region { From bc4dcfc07cf01ff8f548530bef9740c34bc79cf6 Mon Sep 17 00:00:00 2001 From: 0fatal <2816813070@qq.com> Date: Mon, 10 Jul 2023 09:10:05 +0000 Subject: [PATCH 14/14] refactor(server): get logs from log server --- server/src/constants.ts | 14 -------------- server/src/function/function.service.ts | 10 ++++++++-- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/server/src/constants.ts b/server/src/constants.ts index fdbb82a45f..75da98f6e9 100644 --- a/server/src/constants.ts +++ b/server/src/constants.ts @@ -17,13 +17,6 @@ export class ServerConfig { return process.env.METERING_DATABASE_URL } - static get LOG_SERVER_URL() { - if (!process.env.LOG_SERVER_URL) { - throw new Error('LOG_SERVER_URL is not defined') - } - return process.env.LOG_SERVER_URL - } - static get JWT_SECRET() { if (!process.env.JWT_SECRET) { throw new Error('JWT_SECRET is not defined') @@ -31,13 +24,6 @@ export class ServerConfig { return process.env.JWT_SECRET } - static get LOG_SERVER_SECRET() { - if (!process.env.LOG_SERVER_SECRET) { - throw new Error('LOG_SERVER_SECRET is not defined') - } - return process.env.LOG_SERVER_SECRET - } - static get JWT_EXPIRES_IN() { return process.env.JWT_EXPIRES_IN || '7d' } diff --git a/server/src/function/function.service.ts b/server/src/function/function.service.ts index 7c5cca9453..67170dd36c 100644 --- a/server/src/function/function.service.ts +++ b/server/src/function/function.service.ts @@ -3,7 +3,6 @@ import { compileTs2js } from '../utils/lang' import { APPLICATION_SECRET_KEY, CN_PUBLISHED_FUNCTIONS, - ServerConfig, TASK_LOCK_INIT_TIME, } from '../constants' import { CreateFunctionDto } from './dto/create-function.dto' @@ -22,6 +21,7 @@ import { TriggerService } from 'src/trigger/trigger.service' import { TriggerPhase } from 'src/trigger/entities/cron-trigger' import { UpdateFunctionDebugDto } from './dto/update-function-debug.dto' import { HttpService } from '@nestjs/axios' +import { RegionService } from 'src/region/region.service' @Injectable() export class FunctionService { @@ -33,6 +33,7 @@ export class FunctionService { private readonly jwtService: JwtService, private readonly triggerService: TriggerService, private readonly httpService: HttpService, + private readonly regionService: RegionService, ) {} async create(appid: string, userid: ObjectId, dto: CreateFunctionDto) { await this.db.collection('CloudFunction').insertOne({ @@ -321,13 +322,18 @@ export class FunctionService { functionName?: string }, ) { + const region = await this.regionService.findByAppId(appid) + const res = await this.httpService.axiosRef.get( - `${ServerConfig.LOG_SERVER_URL}/function/log`, + `${region.logServerConf.apiUrl}/function/log`, { params: { ...params, appid, }, + headers: { + 'x-token': region.logServerConf.secret, + }, }, ) return res.data