commit 925c5d1ab2ccdf9635841d0380eaec09b9c8ef55 Author: DESKTOP-2S5P7D1\Windows 10 Date: Wed Dec 4 17:25:34 2024 +0700 first diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000..421d949 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,7 @@ +.DS_Store +node_modules +/dist + +.env +.env.* +!.env.example diff --git a/.env.example b/.env.example new file mode 100644 index 0000000..daeaf3a --- /dev/null +++ b/.env.example @@ -0,0 +1,12 @@ +AUTH_REALM_URL=http://192.168.1.200:8080/realms/dev +AUTH_PUBLIC_KEY=MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEA1/QAH75nWgiRzWCTrGJv8q2A7z0qggC2IQ9Sva/Ok1RxeGE/ED2m4ELbF5B9MtugyXYGMUBXaKhooMpTE3wyR1OwsUlv/GtYSmMuKUnsSEXklsP8nIq8gZkCvISOVdvIC4ng5aZ5nBcp9cQ3eVbz4dfZcbLzcqLIIkxQmFBK0m1eFL5IdNj8Ac7U4eH4ylOckOu174f35NnFH6wDva6Iic3EXapMcE2BnXXCTajk2dmlWAzH13ybQBgHDfrOtulrmn1CzQxe9WUJes4qX5z72N05KsHvtUObaeN6cb+mIeH36GdysqgAdd2hhKkgUFXwtLPzldtrEc7xVyf3OLEg1QIDAQAB +AUTH_PREFERRED_MODE=online + +APP_HOST=0.0.0.0 +APP_PORT=3000 + +DB_HOST=192.168.1.200 +DB_PORT=3306 +DB_USERNAME=root +DB_PASSWORD= +DB_NAME=dev diff --git a/.github/workflows/release.yaml b/.github/workflows/release.yaml new file mode 100644 index 0000000..bfae554 --- /dev/null +++ b/.github/workflows/release.yaml @@ -0,0 +1,87 @@ +name: release-test +run-name: release-test ${{ github.actor }} +on: + push: + tags: + - "version-[0-9]+.[0-9]+.[0-9]+" + workflow_dispatch: +env: + REGISTRY: docker.frappet.com + IMAGE_NAME: ehr/bma-ehr-evaluation-service + DEPLOY_HOST: frappet.com + # COMPOSE_PATH: /home/frappet/docker/bma-ehr + COMPOSE_PATH: /home/frappet/docker/bma/bma-ehr-evaluation +jobs: + # act workflow_dispatch -W .github/workflows/release.yaml --input IMAGE_VER=latest -s DOCKER_USER=admin -s DOCKER_PASS=FPTadmin2357 -s SSH_PASSWORD=FPTadmin2357 + release-test: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v3 + # skip Set up QEMU because it fail on act and container + # Gen Version try to get version from tag or inut + - name: Set output tags + id: vars + run: echo "tag=${GITHUB_REF#refs/*/}" >> $GITHUB_OUTPUT + - name: Gen Version + id: gen_ver + run: | + if [[ $GITHUB_REF == 'refs/tags/'* ]]; then + IMAGE_VER=${{ steps.vars.outputs.tag }} + else + IMAGE_VER=${{ github.event.inputs.IMAGE_VER }} + fi + if [[ $IMAGE_VER == '' ]]; then + IMAGE_VER='test-vBeta' + fi + echo '::set-output name=image_ver::'$IMAGE_VER + - name: Check Version + run: | + echo $GITHUB_REF + echo ${{ steps.gen_ver.outputs.image_ver }} + + - name: Set up Docker Buildx + uses: docker/setup-buildx-action@v2 + - name: Login in to registry + uses: docker/login-action@v2 + with: + registry: ${{env.REGISTRY}} + username: ${{secrets.DOCKER_USER}} + password: ${{secrets.DOCKER_PASS}} + - name: Build and push docker image + uses: docker/build-push-action@v3 + with: + context: . + platforms: linux/amd64 + file: docker/Dockerfile + push: true + tags: ${{env.REGISTRY}}/${{env.IMAGE_NAME}}:${{ steps.gen_ver.outputs.image_ver }},${{env.REGISTRY}}/${{env.IMAGE_NAME}}:latest + - name: Remote Deployment + uses: appleboy/ssh-action@v0.1.8 + with: + host: ${{env.DEPLOY_HOST}} + username: frappet + password: ${{ secrets.SSH_PASSWORD }} + port: 10102 + script: | + cd "${{env.COMPOSE_PATH}}" + docker compose pull + docker compose up -d + echo "${{ steps.gen_ver.outputs.image_ver }}"> success + - uses: snow-actions/line-notify@v1.1.0 + if: success() + with: + access_token: ${{ secrets.TOKEN_LINE }} + message: | + -Success✅✅✅ + Image: ${{env.IMAGE_NAME}} + Version: ${{ steps.gen_ver.outputs.IMAGE_VER }} + By: ${{github.actor}} + - uses: snow-actions/line-notify@v1.1.0 + if: failure() + with: + access_token: ${{ secrets.TOKEN_LINE }} + message: | + -Failure❌❌❌ + Image: ${{env.IMAGE_NAME}} + Version: ${{ steps.gen_ver.outputs.IMAGE_VER }} + By: ${{github.actor}} diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..64ba25c --- /dev/null +++ b/.gitignore @@ -0,0 +1,133 @@ +# Logs +logs +*.log +npm-debug.log* +yarn-debug.log* +yarn-error.log* +lerna-debug.log* +.pnpm-debug.log* + +# Diagnostic reports (https://nodejs.org/api/report.html) +report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json + +# Runtime data +pids +*.pid +*.seed +*.pid.lock + +# Directory for instrumented libs generated by jscoverage/JSCover +lib-cov + +# Coverage directory used by tools like istanbul +coverage +*.lcov + +# nyc test coverage +.nyc_output + +# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files) +.grunt + +# Bower dependency directory (https://bower.io/) +bower_components + +# node-waf configuration +.lock-wscript + +# Compiled binary addons (https://nodejs.org/api/addons.html) +build/Release + +# Dependency directories +node_modules/ +jspm_packages/ + +# Snowpack dependency directory (https://snowpack.dev/) +web_modules/ + +# TypeScript cache +*.tsbuildinfo + +# Optional npm cache directory +.npm + +# Optional eslint cache +.eslintcache + +# Optional stylelint cache +.stylelintcache + +# Microbundle cache +.rpt2_cache/ +.rts2_cache_cjs/ +.rts2_cache_es/ +.rts2_cache_umd/ + +# Optional REPL history +.node_repl_history + +# Output of 'npm pack' +*.tgz + +# Yarn Integrity file +.yarn-integrity + +# dotenv environment variable files +.env +.env.evaluation.local +.env.test.local +.env.production.local +.env.local + +[Ss]rc/swagger.json +[Ss]rc/routes.ts + +# parcel-bundler cache (https://parceljs.org/) +.cache +.parcel-cache + +# Next.js build output +.next +out + +# Nuxt.js build / generate output +.nuxt +dist + +# Gatsby files +.cache/ +# Comment in the public line in if your project uses Gatsby and not Next.js +# https://nextjs.org/blog/next-9-1#public-directory-support +# public + +# vuepress build output +.vuepress/dist + +# vuepress v2.x temp and cache directory +.temp +.cache + +# Docusaurus cache and generated files +.docusaurus + +# Serverless directories +.serverless/ + +# FuseBox cache +.fusebox/ + +# DynamoDB Local files +.dynamodb/ + +# TernJS port file +.tern-port + +# Stores VSCode versions used for testing VSCode extensions +.vscode-test + +# yarn v2 +.yarn/cache +.yarn/unplugged +.yarn/build-state.yml +.yarn/install-state.gz +.pnp.* diff --git a/.prettierignore b/.prettierignore new file mode 100644 index 0000000..db4f49d --- /dev/null +++ b/.prettierignore @@ -0,0 +1,18 @@ +.DS_Store +node_modules +.env +.env.* +!.env.example + +/dist +/static +/src/routes.ts +/src/swagger.json + +# Any log +*.log + +# Ignore files for PNPM, NPM and YARN +pnpm-lock.yaml +package-lock.json +yarn.lock diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000..72bb8a7 --- /dev/null +++ b/.prettierrc @@ -0,0 +1,5 @@ +{ + "tabWidth": 2, + "printWidth": 100, + "trailingComma": "all" +} diff --git a/README.md b/README.md new file mode 100644 index 0000000..7c9f202 --- /dev/null +++ b/README.md @@ -0,0 +1 @@ +# bma-ehr-evaluation diff --git a/docker/Dockerfile b/docker/Dockerfile new file mode 100644 index 0000000..07492be --- /dev/null +++ b/docker/Dockerfile @@ -0,0 +1,34 @@ +# Build Stage +FROM node:lts-alpine AS build-stage + +# Create app directory +WORKDIR /app + +# Install app dependencies +COPY package*.json ./ + +RUN npm ci + +# Copy source files and build the app +COPY . . +RUN npm run build + +# Production Stage +FROM node:lts-alpine + +ENV NODE_ENV production +USER node + +# Create app directory +WORKDIR /app + +# Copy built app from build stage +COPY --from=build-stage /app/dist ./dist + +# Install only production dependencies +COPY package*.json ./ +RUN npm ci --production + +# Define the entrypoint and default command +# If you have a custom entrypoint script +CMD [ "node", "dist/app.js" ] diff --git a/nodemon.json b/nodemon.json new file mode 100644 index 0000000..0d5adab --- /dev/null +++ b/nodemon.json @@ -0,0 +1,6 @@ +{ + "exec": "tsoa spec-and-routes && ts-node src/app.ts", + "ext": "ts", + "watch": ["src"], + "ignore": ["src/routes.ts"] +} diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 0000000..4ec9070 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,5438 @@ +{ + "name": "template", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "template", + "version": "1.0.0", + "license": "ISC", + "dependencies": { + "@elastic/elasticsearch": "^8.14.0", + "@nestjs/platform-express": "^10.3.7", + "@tsoa/runtime": "^6.0.0", + "axios": "^1.6.8", + "cors": "^2.8.5", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "fast-jwt": "^3.3.2", + "multer": "^1.4.5-lts.1", + "mysql2": "^3.9.1", + "node-cron": "^3.0.3", + "promise.any": "^2.0.6", + "redis": "~3.1.2", + "reflect-metadata": "^0.2.1", + "swagger-ui-express": "^5.0.0", + "tsoa": "^6.0.1", + "typeorm": "^0.3.19", + "typeorm-cli": "^1.0.7", + "xlsx": "^0.18.5" + }, + "devDependencies": { + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/node": "^20.11.5", + "@types/node-cron": "^3.0.11", + "@types/swagger-ui-express": "^4.1.6", + "nodemon": "^3.0.3", + "prettier": "^3.2.2", + "ts-node": "^10.9.2", + "typescript": "^5.3.3" + } + }, + "node_modules/@cspotcode/source-map-support": { + "version": "0.8.1", + "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz", + "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==", + "devOptional": true, + "dependencies": { + "@jridgewell/trace-mapping": "0.3.9" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@elastic/elasticsearch": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/@elastic/elasticsearch/-/elasticsearch-8.14.0.tgz", + "integrity": "sha512-MGrgCI4y+Ozssf5Q2IkVJlqt5bUMnKIICG2qxeOfrJNrVugMCBCAQypyesmSSocAtNm8IX3LxfJ3jQlFHmKe2w==", + "license": "Apache-2.0", + "dependencies": { + "@elastic/transport": "^8.6.0", + "tslib": "^2.4.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@elastic/transport": { + "version": "8.7.0", + "resolved": "https://registry.npmjs.org/@elastic/transport/-/transport-8.7.0.tgz", + "integrity": "sha512-IqXT7a8DZPJtqP2qmX1I2QKmxYyN27kvSW4g6pInESE1SuGwZDp2FxHJ6W2kwmYOJwQdAt+2aWwzXO5jHo9l4A==", + "license": "Apache-2.0", + "dependencies": { + "@opentelemetry/api": "1.x", + "debug": "^4.3.4", + "hpagent": "^1.0.0", + "ms": "^2.1.3", + "secure-json-parse": "^2.4.0", + "tslib": "^2.4.0", + "undici": "^6.12.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@elastic/transport/node_modules/debug": { + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.5.tgz", + "integrity": "sha512-pt0bNEmneDIvdL1Xsd9oDQ/wrQRkXDT4AUWlNZNPKvW5x/jyO9VFXkJUP07vQ2upmw5PlaITaPKc31jK13V+jg==", + "license": "MIT", + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/@elastic/transport/node_modules/debug/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==", + "license": "MIT" + }, + "node_modules/@elastic/transport/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.1.tgz", + "integrity": "sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==", + "devOptional": true, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.4.15", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz", + "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==", + "devOptional": true + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.9", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz", + "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==", + "devOptional": true, + "dependencies": { + "@jridgewell/resolve-uri": "^3.0.3", + "@jridgewell/sourcemap-codec": "^1.4.10" + } + }, + "node_modules/@lukeed/csprng": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", + "integrity": "sha512-Z7C/xXCiGWsg0KuKsHTKJxbWhpI3Vs5GwLfOean7MGyVFGqdRgBbAjOCh6u4bbjPc/8MJ2pZmK/0DLdCbivLDA==", + "peer": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/@lukeed/ms": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/@lukeed/ms/-/ms-2.0.2.tgz", + "integrity": "sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==", + "engines": { + "node": ">=8" + } + }, + "node_modules/@nestjs/common": { + "version": "10.3.7", + "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.3.7.tgz", + "integrity": "sha512-gKFtFzcJznrwsRYjtNZoPAvSOPYdNgxbTYoAyLTpoy393cIKgLmJTHu6ReH8/qIB9AaZLdGaFLkx98W/tFWFUw==", + "peer": true, + "dependencies": { + "iterare": "1.2.1", + "tslib": "2.6.2", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "class-transformer": "*", + "class-validator": "*", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "class-transformer": { + "optional": true + }, + "class-validator": { + "optional": true + } + } + }, + "node_modules/@nestjs/core": { + "version": "10.3.7", + "resolved": "https://registry.npmjs.org/@nestjs/core/-/core-10.3.7.tgz", + "integrity": "sha512-hsdlnfiQ3kgqHL5k7js3CU0PV7hBJVi+LfFMgCkoagRxNMf67z0GFGeOV2jk5d65ssB19qdYsDa1MGVuEaoUpg==", + "hasInstallScript": true, + "peer": true, + "dependencies": { + "@nuxtjs/opencollective": "0.3.2", + "fast-safe-stringify": "2.1.1", + "iterare": "1.2.1", + "path-to-regexp": "3.2.0", + "tslib": "2.6.2", + "uid": "2.0.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/microservices": "^10.0.0", + "@nestjs/platform-express": "^10.0.0", + "@nestjs/websockets": "^10.0.0", + "reflect-metadata": "^0.1.12 || ^0.2.0", + "rxjs": "^7.1.0" + }, + "peerDependenciesMeta": { + "@nestjs/microservices": { + "optional": true + }, + "@nestjs/platform-express": { + "optional": true + }, + "@nestjs/websockets": { + "optional": true + } + } + }, + "node_modules/@nestjs/core/node_modules/path-to-regexp": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.2.0.tgz", + "integrity": "sha512-jczvQbCUS7XmS7o+y1aEO9OBVFeZBQ1MDSEqmO7xSoPgOPoowY/SxLpZ6Vh97/8qHZOteiCKb7gkG9gA2ZUxJA==", + "peer": true + }, + "node_modules/@nestjs/platform-express": { + "version": "10.3.7", + "resolved": "https://registry.npmjs.org/@nestjs/platform-express/-/platform-express-10.3.7.tgz", + "integrity": "sha512-noNJ+PyIxQJLCKfuXz0tcQtlVAynfLIuKy62g70lEZ86UrIqSrZFqvWs/rFUgkbT6J8H7Rmv11hASOnX+7M2rA==", + "dependencies": { + "body-parser": "1.20.2", + "cors": "2.8.5", + "express": "4.19.2", + "multer": "1.4.4-lts.1", + "tslib": "2.6.2" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nest" + }, + "peerDependencies": { + "@nestjs/common": "^10.0.0", + "@nestjs/core": "^10.0.0" + } + }, + "node_modules/@nestjs/platform-express/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/@nestjs/platform-express/node_modules/multer": { + "version": "1.4.4-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.4-lts.1.tgz", + "integrity": "sha512-WeSGziVj6+Z2/MwQo3GvqzgR+9Uc+qt8SwHKh3gvNPiISKfsMfG4SvCOFYlxxgkXt7yIV2i1yczehm0EOKIxIg==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/@nuxtjs/opencollective": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@nuxtjs/opencollective/-/opencollective-0.3.2.tgz", + "integrity": "sha512-um0xL3fO7Mf4fDxcqx9KryrB7zgRM5JSlvGN5AGkP6JLM5XEKyjeAiPbNxdXVXQ16isuAhYpvP88NgL2BGd6aA==", + "peer": true, + "dependencies": { + "chalk": "^4.1.0", + "consola": "^2.15.0", + "node-fetch": "^2.6.1" + }, + "bin": { + "opencollective": "bin/opencollective.js" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/@one-ini/wasm": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/@one-ini/wasm/-/wasm-0.1.1.tgz", + "integrity": "sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==" + }, + "node_modules/@opentelemetry/api": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/@opentelemetry/api/-/api-1.9.0.tgz", + "integrity": "sha512-3giAOQvZiH5F9bMlMiv8+GSPMeqg0dbaeo58/0SlA9sxSqZhnUtxzX9/2FzyhS9sWQf5S0GJE0AKBrFqjpeYcg==", + "license": "Apache-2.0", + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", + "optional": true, + "engines": { + "node": ">=14" + } + }, + "node_modules/@sqltools/formatter": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@sqltools/formatter/-/formatter-1.2.5.tgz", + "integrity": "sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==" + }, + "node_modules/@tsconfig/node10": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.9.tgz", + "integrity": "sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==", + "devOptional": true + }, + "node_modules/@tsconfig/node12": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz", + "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==", + "devOptional": true + }, + "node_modules/@tsconfig/node14": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz", + "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==", + "devOptional": true + }, + "node_modules/@tsconfig/node16": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz", + "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==", + "devOptional": true + }, + "node_modules/@tsoa/cli": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/@tsoa/cli/-/cli-6.0.1.tgz", + "integrity": "sha512-SpdWPIzAtfG6Jcb6KIvT4VVo9VnAfAiY6+dCrrlKURlEfah05rRQ7k09jeJdAZoeeoKVwyJNj+43zlh9w1u7bg==", + "dependencies": { + "@tsoa/runtime": "^6.0.0", + "@types/multer": "^1.4.11", + "deepmerge": "^4.3.1", + "fs-extra": "^11.2.0", + "glob": "^10.3.10", + "handlebars": "^4.7.8", + "merge-anything": "^5.1.4", + "minimatch": "^9.0.1", + "typescript": "^5.3.3", + "validator": "^13.11.0", + "yamljs": "^0.3.0", + "yargs": "^17.7.1" + }, + "bin": { + "tsoa": "dist/cli.js" + }, + "engines": { + "node": ">=18.0.0", + "yarn": ">=1.9.4" + } + }, + "node_modules/@tsoa/cli/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@tsoa/cli/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@tsoa/runtime": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/@tsoa/runtime/-/runtime-6.0.0.tgz", + "integrity": "sha512-n0LYcjII313kDn3M4bZdAjU+sX7595sIEA3bw4pvxWRrkandyDdDFNrfQL8nZ3Pw6dkTmK7brZi0YBBDhe0Rzw==", + "dependencies": { + "@types/multer": "^1.4.11", + "reflect-metadata": "^0.2.1", + "validator": "^13.11.0" + }, + "engines": { + "node": ">=18.0.0", + "yarn": ">=1.9.4" + } + }, + "node_modules/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "dependencies": { + "@types/connect": "*", + "@types/node": "*" + } + }, + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "dev": true, + "dependencies": { + "@types/node": "*" + } + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", + "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.41", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.41.tgz", + "integrity": "sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==", + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" + } + }, + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==" + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==" + }, + "node_modules/@types/multer": { + "version": "1.4.11", + "resolved": "https://registry.npmjs.org/@types/multer/-/multer-1.4.11.tgz", + "integrity": "sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==", + "dependencies": { + "@types/express": "*" + } + }, + "node_modules/@types/node": { + "version": "20.11.5", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.11.5.tgz", + "integrity": "sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==", + "dependencies": { + "undici-types": "~5.26.4" + } + }, + "node_modules/@types/node-cron": { + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/node-cron/-/node-cron-3.0.11.tgz", + "integrity": "sha512-0ikrnug3/IyneSHqCBeslAhlK2aBfYek1fGo4bP4QnZPmiqSGRK+Oy7ZMisLWkesffJvQ1cqAcBnJC+8+nxIAg==", + "dev": true + }, + "node_modules/@types/qs": { + "version": "6.9.11", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.11.tgz", + "integrity": "sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==" + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", + "dependencies": { + "@types/mime": "^1", + "@types/node": "*" + } + }, + "node_modules/@types/serve-static": { + "version": "1.15.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.5.tgz", + "integrity": "sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==", + "dependencies": { + "@types/http-errors": "*", + "@types/mime": "*", + "@types/node": "*" + } + }, + "node_modules/@types/swagger-ui-express": { + "version": "4.1.6", + "resolved": "https://registry.npmjs.org/@types/swagger-ui-express/-/swagger-ui-express-4.1.6.tgz", + "integrity": "sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==", + "dev": true, + "dependencies": { + "@types/express": "*", + "@types/serve-static": "*" + } + }, + "node_modules/@types/zen-observable": { + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/@types/zen-observable/-/zen-observable-0.8.3.tgz", + "integrity": "sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==" + }, + "node_modules/abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==", + "dev": true + }, + "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/acorn": { + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", + "devOptional": true, + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-walk": { + "version": "8.3.2", + "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.2.tgz", + "integrity": "sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==", + "devOptional": true, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/adler-32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/adler-32/-/adler-32-1.3.1.tgz", + "integrity": "sha512-ynZ4w/nUUv5rrsR8UUGoe1VC9hZj6V5hU9Qw1HlMDJGEJw5S7TfTErWTjMys6M7vr0YWcPqs3qAr4ss0nDfP+A==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/align-text": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/align-text/-/align-text-0.1.4.tgz", + "integrity": "sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==", + "dependencies": { + "kind-of": "^3.0.2", + "longest": "^1.0.1", + "repeat-string": "^1.5.2" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/ansi-escapes": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz", + "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/ansi-regex": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/app-root-path": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/app-root-path/-/app-root-path-3.1.0.tgz", + "integrity": "sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==", + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/append-field": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", + "integrity": "sha512-klpgFSWLW1ZEs8svjfb7g4qWY0YS5imI82dTg+QahUvJ8YqAY0P10Uk8tTyh9ZGuYEZEMaeJYCF5BFuX552hsw==" + }, + "node_modules/arg": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz", + "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==" + }, + "node_modules/argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dependencies": { + "sprintf-js": "~1.0.2" + } + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz", + "integrity": "sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==", + "dependencies": { + "call-bind": "^1.0.2", + "is-array-buffer": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/array.prototype.map": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/array.prototype.map/-/array.prototype.map-1.0.6.tgz", + "integrity": "sha512-nK1psgF2cXqP3wSyCSq0Hc7zwNq3sfljQqaG27r/7a7ooNUnn5nGq6yYWyks9jMO5EoFQ0ax80hSg6oXSRNXaw==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-array-method-boxes-properly": "^1.0.0", + "is-string": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz", + "integrity": "sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "get-intrinsic": "^1.2.1", + "is-array-buffer": "^3.0.2", + "is-shared-array-buffer": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/asn1.js": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-5.4.1.tgz", + "integrity": "sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==", + "dependencies": { + "bn.js": "^4.0.0", + "inherits": "^2.0.1", + "minimalistic-assert": "^1.0.0", + "safer-buffer": "^2.1.0" + } + }, + "node_modules/async": { + "version": "0.2.10", + "resolved": "https://registry.npmjs.org/async/-/async-0.2.10.tgz", + "integrity": "sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==" + }, + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz", + "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/axios": { + "version": "1.6.8", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.8.tgz", + "integrity": "sha512-v/ZHtJDU39mDpyBoFVkETcd/uNdxrWRrg3bKpOKzXFA6Bvqopts6ALSMU3y6ijYxbw2B+wPrIv46egTzJXCLGQ==", + "dependencies": { + "follow-redirects": "^1.15.6", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" + } + }, + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==" + }, + "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/bignumber.js": { + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/bignumber.js/-/bignumber.js-9.0.0.tgz", + "integrity": "sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==", + "engines": { + "node": "*" + } + }, + "node_modules/binary-extensions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz", + "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/bn.js": { + "version": "4.12.0", + "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz", + "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==" + }, + "node_modules/body-parser": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz", + "integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==", + "dependencies": { + "bytes": "3.1.2", + "content-type": "~1.0.5", + "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.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" + }, + "engines": { + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" + } + }, + "node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "dependencies": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/braces": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", + "dev": true, + "dependencies": { + "fill-range": "^7.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/busboy": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/busboy/-/busboy-1.6.0.tgz", + "integrity": "sha512-8SFQbg/0hQ9xy3UNTB0YEnsNBbWfhf7RtnzpL7TkBiTBRfrQ9Fxcnz7VJsleJpyp6rVLvXiuORqjlHi5q+PYuA==", + "dependencies": { + "streamsearch": "^1.1.0" + }, + "engines": { + "node": ">=10.16.0" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/call-bind": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.5.tgz", + "integrity": "sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==", + "dependencies": { + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.1", + "set-function-length": "^1.1.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/camelcase": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-1.2.1.tgz", + "integrity": "sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/center-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/center-align/-/center-align-0.1.3.tgz", + "integrity": "sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==", + "dependencies": { + "align-text": "^0.1.3", + "lazy-cache": "^1.0.3" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/cfb": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cfb/-/cfb-1.2.2.tgz", + "integrity": "sha512-KfdUZsSOw19/ObEWasvBP/Ac4reZvAGauZhs6S/gqNhXhI7cKwvlH7ulj+dOEYnca4bm4SGo8C1bTAQvnTjgQA==", + "dependencies": { + "adler-32": "~1.3.0", + "crc-32": "~1.2.0" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chalk/node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/chalk/node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==" + }, + "node_modules/chokidar": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.3.tgz", + "integrity": "sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==", + "dependencies": { + "restore-cursor": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cli-highlight": { + "version": "2.1.11", + "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz", + "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==", + "dependencies": { + "chalk": "^4.0.0", + "highlight.js": "^10.7.1", + "mz": "^2.4.0", + "parse5": "^5.1.1", + "parse5-htmlparser2-tree-adapter": "^6.0.0", + "yargs": "^16.0.0" + }, + "bin": { + "highlight": "bin/highlight" + }, + "engines": { + "node": ">=8.0.0", + "npm": ">=5.0.0" + } + }, + "node_modules/cli-highlight/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-highlight/node_modules/cliui": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz", + "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.0", + "wrap-ansi": "^7.0.0" + } + }, + "node_modules/cli-highlight/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/cli-highlight/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-highlight/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-highlight/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/cli-highlight/node_modules/yargs": { + "version": "16.2.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz", + "integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==", + "dependencies": { + "cliui": "^7.0.2", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.0", + "y18n": "^5.0.5", + "yargs-parser": "^20.2.2" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/cli-highlight/node_modules/yargs-parser": { + "version": "20.2.9", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz", + "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==", + "engines": { + "node": ">=10" + } + }, + "node_modules/cli-width": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.1.tgz", + "integrity": "sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==" + }, + "node_modules/cliui": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz", + "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==", + "dependencies": { + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/cliui/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/cliui/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cliui/node_modules/wrap-ansi": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/codepage": { + "version": "1.15.0", + "resolved": "https://registry.npmjs.org/codepage/-/codepage-1.15.0.tgz", + "integrity": "sha512-3g6NUTPd/YtuuGrhMnOMRjFc+LJw/bnMp3+0r/Wcz3IXUuCosKRJvMphm5+Q+bvTVGcJJuRvVLuYba+WojaFaA==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/color-convert": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", + "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/colors-console": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/colors-console/-/colors-console-1.0.3.tgz", + "integrity": "sha512-Q31K32UwadWqAxs+Iu46gNm4HJqUwrTJT2zen5NnhkKE5w7uqeZQZiuODUOxM/zOtHfiUTkia0io6zbN/VcCUQ==" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", + "dependencies": { + "delayed-stream": "~1.0.0" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==" + }, + "node_modules/concat-stream": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz", + "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==", + "engines": [ + "node >= 0.8" + ], + "dependencies": { + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^2.2.2", + "typedarray": "^0.0.6" + } + }, + "node_modules/config-chain": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.13.tgz", + "integrity": "sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==", + "dependencies": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "node_modules/consola": { + "version": "2.15.3", + "resolved": "https://registry.npmjs.org/consola/-/consola-2.15.3.tgz", + "integrity": "sha512-9vAdYbHj6x2fLKC4+oPH0kFzY/orMZyG2Aj+kNylHxKGJ/Ed4dpNyAQYwJOdqO4zdM7XpVHmyejQDcQHrnuXbw==", + "peer": true + }, + "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.6.0", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz", + "integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==", + "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/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==" + }, + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "dependencies": { + "object-assign": "^4", + "vary": "^1" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "bin": { + "crc32": "bin/crc32.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/create-require": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz", + "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==", + "devOptional": true + }, + "node_modules/cross-spawn": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", + "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", + "dependencies": { + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/dayjs": { + "version": "1.11.10", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.10.tgz", + "integrity": "sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==" + }, + "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/decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/define-data-property": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.1.tgz", + "integrity": "sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==", + "dependencies": { + "get-intrinsic": "^1.2.1", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", + "dependencies": { + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "engines": { + "node": ">=0.4.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/diff": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.2.tgz", + "integrity": "sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==", + "engines": { + "node": ">=0.3.1" + } + }, + "node_modules/dotenv": { + "version": "16.3.2", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.3.2.tgz", + "integrity": "sha512-HTlk5nmhkm8F6JcdXvHIzaorzCoziNQT9mGxLPVXW8wJF1TiGSL60ZGB4gHWabHOaMmWmhvk2/lPHfnBiT78AQ==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/motdotla/dotenv?sponsor=1" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==" + }, + "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/editorconfig": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-1.0.4.tgz", + "integrity": "sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==", + "dependencies": { + "@one-ini/wasm": "0.1.1", + "commander": "^10.0.0", + "minimatch": "9.0.1", + "semver": "^7.5.3" + }, + "bin": { + "editorconfig": "bin/editorconfig" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/editorconfig/node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", + "engines": { + "node": ">=14" + } + }, + "node_modules/editorconfig/node_modules/minimatch": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.1.tgz", + "integrity": "sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "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/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==" + }, + "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/es-abstract": { + "version": "1.22.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.22.3.tgz", + "integrity": "sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==", + "dependencies": { + "array-buffer-byte-length": "^1.0.0", + "arraybuffer.prototype.slice": "^1.0.2", + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.5", + "es-set-tostringtag": "^2.0.1", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.2", + "get-symbol-description": "^1.0.0", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0", + "internal-slot": "^1.0.5", + "is-array-buffer": "^3.0.2", + "is-callable": "^1.2.7", + "is-negative-zero": "^2.0.2", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.2", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.12", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.4", + "regexp.prototype.flags": "^1.5.1", + "safe-array-concat": "^1.0.1", + "safe-regex-test": "^1.0.0", + "string.prototype.trim": "^1.2.8", + "string.prototype.trimend": "^1.0.7", + "string.prototype.trimstart": "^1.0.7", + "typed-array-buffer": "^1.0.0", + "typed-array-byte-length": "^1.0.0", + "typed-array-byte-offset": "^1.0.0", + "typed-array-length": "^1.0.4", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.13" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-aggregate-error": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.11.tgz", + "integrity": "sha512-DCiZiNlMlbvofET/cE55My387NiLvuGToBEZDdK9U2G3svDCjL8WOgO5Il6lO83nQ8qmag/R9nArdpaFQ/m3lA==", + "dependencies": { + "define-data-property": "^1.1.0", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.1", + "function-bind": "^1.1.1", + "get-intrinsic": "^1.2.1", + "globalthis": "^1.0.3", + "has-property-descriptors": "^1.0.0", + "set-function-name": "^2.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-array-method-boxes-properly": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz", + "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==" + }, + "node_modules/es-get-iterator": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/es-get-iterator/-/es-get-iterator-1.1.3.tgz", + "integrity": "sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.3", + "has-symbols": "^1.0.3", + "is-arguments": "^1.1.1", + "is-map": "^2.0.2", + "is-set": "^2.0.2", + "is-string": "^1.0.7", + "isarray": "^2.0.5", + "stop-iteration-iterator": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/es-set-tostringtag": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.2.tgz", + "integrity": "sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==", + "dependencies": { + "get-intrinsic": "^1.2.2", + "has-tostringtag": "^1.0.0", + "hasown": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dependencies": { + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/escalade": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz", + "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==" + }, + "node_modules/escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", + "engines": { + "node": ">=0.8.0" + } + }, + "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.19.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz", + "integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==", + "dependencies": { + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.2", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.6.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/external-editor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz", + "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fast-jwt": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-jwt/-/fast-jwt-3.3.2.tgz", + "integrity": "sha512-H+JYxaFy2LepiC1AQWM/2hzKlQOWaWUkEnu/yebhYu4+ameb3qG77WiRZ1Ct6YBk6d/ESsNguBfTT5+q0XMtKg==", + "dependencies": { + "@lukeed/ms": "^2.0.1", + "asn1.js": "^5.4.1", + "ecdsa-sig-formatter": "^1.0.11", + "mnemonist": "^0.39.5" + }, + "engines": { + "node": ">=16 <22" + } + }, + "node_modules/fast-safe-stringify": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz", + "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==", + "peer": true + }, + "node_modules/figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/fill-range": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", + "dev": true, + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "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/follow-redirects": { + "version": "1.15.6", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz", + "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "node_modules/for-each": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz", + "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==", + "dependencies": { + "is-callable": "^1.1.3" + } + }, + "node_modules/foreground-child": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.1.1.tgz", + "integrity": "sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/form-data": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.0.tgz", + "integrity": "sha512-ETEklSGi5t0QMZuiXoA/Q6vcnxcLQP5vdugSpuAyi6SVGi2clPPp+xgEhuMaHC+zGgn31Kd235W35f7Hykkaww==", + "dependencies": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" + }, + "engines": { + "node": ">= 6" + } + }, + "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/frac": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/frac/-/frac-1.1.2.tgz", + "integrity": "sha512-w/XBfkibaTl3YDqASwfDUqkna4Z2p9cFSr1aHDt0WoMTECnRfBOv2WArlZILlqgWlmdIlALXGpM2AOhEk5W3IA==", + "engines": { + "node": ">=0.8" + } + }, + "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": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "engines": { + "node": "6.* || 8.* || >= 10.*" + } + }, + "node_modules/get-intrinsic": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.2.tgz", + "integrity": "sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==", + "dependencies": { + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-symbol-description": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz", + "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/glob": { + "version": "10.3.10", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.10.tgz", + "integrity": "sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^2.3.5", + "minimatch": "^9.0.1", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0", + "path-scurry": "^1.10.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob/node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/globalthis": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.3.tgz", + "integrity": "sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==", + "dependencies": { + "define-properties": "^1.1.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", + "dependencies": { + "get-intrinsic": "^1.1.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/handlebars": { + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", + "dependencies": { + "minimist": "^1.2.5", + "neo-async": "^2.6.2", + "source-map": "^0.6.1", + "wordwrap": "^1.0.0" + }, + "bin": { + "handlebars": "bin/handlebars" + }, + "engines": { + "node": ">=0.4.7" + }, + "optionalDependencies": { + "uglify-js": "^3.1.4" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.1.tgz", + "integrity": "sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==", + "dependencies": { + "get-intrinsic": "^1.2.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/has-tostringtag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz", + "integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.0.tgz", + "integrity": "sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/highlight.js": { + "version": "10.7.3", + "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz", + "integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==", + "engines": { + "node": "*" + } + }, + "node_modules/hpagent": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/hpagent/-/hpagent-1.2.0.tgz", + "integrity": "sha512-A91dYTeIB6NoXG+PxTQpCCDDnfHsW9kc06Lvpu1TEe9gnd6ZFeiBoRO9JvzEv6xK7EX97/dUE8g/vBMTqTS3CA==", + "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "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/ignore-by-default": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/ignore-by-default/-/ignore-by-default-1.0.1.tgz", + "integrity": "sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==", + "dev": true + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==" + }, + "node_modules/inquirer": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.5.2.tgz", + "integrity": "sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==", + "dependencies": { + "ansi-escapes": "^3.2.0", + "chalk": "^2.4.2", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.3", + "figures": "^2.0.0", + "lodash": "^4.17.12", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.4.0", + "string-width": "^2.1.0", + "strip-ansi": "^5.1.0", + "through": "^2.3.6" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/inquirer/node_modules/ansi-regex": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.1.tgz", + "integrity": "sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==", + "engines": { + "node": ">=6" + } + }, + "node_modules/inquirer/node_modules/ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "dependencies": { + "color-convert": "^1.9.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/inquirer/node_modules/chalk": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", + "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", + "dependencies": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/inquirer/node_modules/color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "dependencies": { + "color-name": "1.1.3" + } + }, + "node_modules/inquirer/node_modules/color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==" + }, + "node_modules/inquirer/node_modules/is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/inquirer/node_modules/rxjs": { + "version": "6.6.7", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz", + "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==", + "dependencies": { + "tslib": "^1.9.0" + }, + "engines": { + "npm": ">=2.0.0" + } + }, + "node_modules/inquirer/node_modules/string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dependencies": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/inquirer/node_modules/string-width/node_modules/ansi-regex": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.1.tgz", + "integrity": "sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/inquirer/node_modules/string-width/node_modules/strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==", + "dependencies": { + "ansi-regex": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/inquirer/node_modules/strip-ansi": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz", + "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==", + "dependencies": { + "ansi-regex": "^4.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/inquirer/node_modules/tslib": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz", + "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==" + }, + "node_modules/internal-slot": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.6.tgz", + "integrity": "sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==", + "dependencies": { + "get-intrinsic": "^1.2.2", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "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-arguments": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", + "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-array-buffer": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.2.tgz", + "integrity": "sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.0", + "is-typed-array": "^1.1.10" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dependencies": { + "has-bigints": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-binary-path": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz", + "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==", + "dev": true, + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-buffer": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz", + "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==" + }, + "node_modules/is-callable": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz", + "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", + "engines": { + "node": ">=8" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dev": true, + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.2.tgz", + "integrity": "sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-negative-zero": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.2.tgz", + "integrity": "sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", + "dependencies": { + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-set": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", + "integrity": "sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-shared-array-buffer": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz", + "integrity": "sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", + "dependencies": { + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", + "dependencies": { + "has-symbols": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-typed-array": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.12.tgz", + "integrity": "sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==", + "dependencies": { + "which-typed-array": "^1.1.11" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", + "dependencies": { + "call-bind": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-what": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", + "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==" + }, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" + }, + "node_modules/iterare": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/iterare/-/iterare-1.2.1.tgz", + "integrity": "sha512-RKYVTCjAnRthyJes037NX/IiqeidgN1xc3j1RjFfECFp28A1GVwK9nA+i0rJPaHqSZwygLzRnFlzUuHFoWWy+Q==", + "peer": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/iterate-iterator": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-iterator/-/iterate-iterator-1.0.2.tgz", + "integrity": "sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/iterate-value": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/iterate-value/-/iterate-value-1.0.2.tgz", + "integrity": "sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==", + "dependencies": { + "es-get-iterator": "^1.0.2", + "iterate-iterator": "^1.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/jackspeak": { + "version": "2.3.6", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-2.3.6.tgz", + "integrity": "sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/js-beautify": { + "version": "1.14.11", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.14.11.tgz", + "integrity": "sha512-rPogWqAfoYh1Ryqqh2agUpVfbxAhbjuN1SmU86dskQUKouRiggUTCO4+2ym9UPXllc2WAp0J+T5qxn7Um3lCdw==", + "dependencies": { + "config-chain": "^1.1.13", + "editorconfig": "^1.0.3", + "glob": "^10.3.3", + "nopt": "^7.2.0" + }, + "bin": { + "css-beautify": "js/bin/css-beautify.js", + "html-beautify": "js/bin/html-beautify.js", + "js-beautify": "js/bin/js-beautify.js" + }, + "engines": { + "node": ">=14" + } + }, + "node_modules/js-beautify/node_modules/abbrev": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-2.0.0.tgz", + "integrity": "sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/js-beautify/node_modules/nopt": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-7.2.0.tgz", + "integrity": "sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==", + "dependencies": { + "abbrev": "^2.0.0" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==" + }, + "node_modules/js-yaml": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", + "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==", + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/js-yaml/node_modules/argparse": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz", + "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, + "node_modules/kind-of": { + "version": "3.2.2", + "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz", + "integrity": "sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==", + "dependencies": { + "is-buffer": "^1.1.5" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lazy-cache": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/lazy-cache/-/lazy-cache-1.0.4.tgz", + "integrity": "sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" + }, + "node_modules/long": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", + "integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==" + }, + "node_modules/longest": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/longest/-/longest-1.0.1.tgz", + "integrity": "sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/loose-envify": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz", + "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==", + "dependencies": { + "js-tokens": "^3.0.0 || ^4.0.0" + }, + "bin": { + "loose-envify": "cli.js" + } + }, + "node_modules/lru-cache": { + "version": "8.0.5", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", + "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", + "engines": { + "node": ">=16.14" + } + }, + "node_modules/make-error": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz", + "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==" + }, + "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/merge-anything": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/merge-anything/-/merge-anything-5.1.7.tgz", + "integrity": "sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==", + "dependencies": { + "is-what": "^4.1.8" + }, + "engines": { + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" + } + }, + "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/mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/minimalistic-assert": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz", + "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==" + }, + "node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } + }, + "node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/minipass": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", + "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/mkdirp": { + "version": "2.1.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-2.1.6.tgz", + "integrity": "sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==", + "bin": { + "mkdirp": "dist/cjs/src/bin.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/mnemonist": { + "version": "0.39.7", + "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.7.tgz", + "integrity": "sha512-ix3FwHWZgdXUt0dHM8bCrI4r1KMeYx8bCunPCYmvKXq4tn6gbNsqrsb4q0kDbDqbpIOvEaW5Sn+dmDwGydfrwA==", + "dependencies": { + "obliterator": "^2.0.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/multer": { + "version": "1.4.5-lts.1", + "resolved": "https://registry.npmjs.org/multer/-/multer-1.4.5-lts.1.tgz", + "integrity": "sha512-ywPWvcDMeH+z9gQq5qYHCCy+ethsk4goepZ45GLD63fOu0YcNecQxi64nDs3qluZB+murG3/D4dJ7+dGctcCQQ==", + "dependencies": { + "append-field": "^1.0.0", + "busboy": "^1.0.0", + "concat-stream": "^1.5.2", + "mkdirp": "^0.5.4", + "object-assign": "^4.1.1", + "type-is": "^1.6.4", + "xtend": "^4.0.0" + }, + "engines": { + "node": ">= 6.0.0" + } + }, + "node_modules/multer/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==" + }, + "node_modules/mysql": { + "version": "2.18.1", + "resolved": "https://registry.npmjs.org/mysql/-/mysql-2.18.1.tgz", + "integrity": "sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==", + "dependencies": { + "bignumber.js": "9.0.0", + "readable-stream": "2.3.7", + "safe-buffer": "5.1.2", + "sqlstring": "2.3.1" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mysql/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/mysql/node_modules/sqlstring": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/sqlstring/-/sqlstring-2.3.1.tgz", + "integrity": "sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mysql2": { + "version": "3.9.1", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.1.tgz", + "integrity": "sha512-3njoWAAhGBYy0tWBabqUQcLtczZUxrmmtc2vszQUekg3kTJyZ5/IeLC3Fo04u6y6Iy5Sba7pIIa2P/gs8D3ZeQ==", + "dependencies": { + "denque": "^2.1.0", + "generate-function": "^2.3.1", + "iconv-lite": "^0.6.3", + "long": "^5.2.1", + "lru-cache": "^8.0.0", + "named-placeholders": "^1.1.3", + "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/mz": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz", + "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==", + "dependencies": { + "any-promise": "^1.0.0", + "object-assign": "^4.0.1", + "thenify-all": "^1.0.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/neo-async": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", + "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==" + }, + "node_modules/node-cron": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/node-cron/-/node-cron-3.0.3.tgz", + "integrity": "sha512-dOal67//nohNgYWb+nWmg5dkFdIwDm8EpeGYMekPMrngV3637lqnX0lbUcCtgibHTz6SEz7DAIjKvKDFYCnO1A==", + "dependencies": { + "uuid": "8.3.2" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/node-cron/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==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/node-fetch": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", + "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==", + "peer": true, + "dependencies": { + "whatwg-url": "^5.0.0" + }, + "engines": { + "node": "4.x || >=6.0.0" + }, + "peerDependencies": { + "encoding": "^0.1.0" + }, + "peerDependenciesMeta": { + "encoding": { + "optional": true + } + } + }, + "node_modules/nodemon": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/nodemon/-/nodemon-3.0.3.tgz", + "integrity": "sha512-7jH/NXbFPxVaMwmBCC2B9F/V6X1VkEdNgx3iu9jji8WxWcvhMWkmhNWhI5077zknOnZnBzba9hZP6bCPJLSReQ==", + "dev": true, + "dependencies": { + "chokidar": "^3.5.2", + "debug": "^4", + "ignore-by-default": "^1.0.1", + "minimatch": "^3.1.2", + "pstree.remy": "^1.1.8", + "semver": "^7.5.3", + "simple-update-notifier": "^2.0.0", + "supports-color": "^5.5.0", + "touch": "^3.1.0", + "undefsafe": "^2.0.5" + }, + "bin": { + "nodemon": "bin/nodemon.js" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/nodemon" + } + }, + "node_modules/nodemon/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", + "dev": true, + "dependencies": { + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/nodemon/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==", + "dev": true + }, + "node_modules/nopt": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-1.0.10.tgz", + "integrity": "sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==", + "dev": true, + "dependencies": { + "abbrev": "1" + }, + "bin": { + "nopt": "bin/nopt.js" + }, + "engines": { + "node": "*" + } + }, + "node_modules/normalize-path": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz", + "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==", + "dev": true, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.1", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz", + "integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/object-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/object.assign": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dependencies": { + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "has-symbols": "^1.0.3", + "object-keys": "^1.1.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/obliterator": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz", + "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==" + }, + "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/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==", + "dependencies": { + "mimic-fn": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/optimist": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/optimist/-/optimist-0.6.1.tgz", + "integrity": "sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==", + "dependencies": { + "minimist": "~0.0.1", + "wordwrap": "~0.0.2" + } + }, + "node_modules/optimist/node_modules/minimist": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.10.tgz", + "integrity": "sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==" + }, + "node_modules/optimist/node_modules/wordwrap": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.3.tgz", + "integrity": "sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/parse5": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz", + "integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==" + }, + "node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "dependencies": { + "parse5": "^6.0.1" + } + }, + "node_modules/parse5-htmlparser2-tree-adapter/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==" + }, + "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-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/path-key": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", + "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", + "engines": { + "node": ">=8" + } + }, + "node_modules/path-scurry": { + "version": "1.10.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.1.tgz", + "integrity": "sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==", + "dependencies": { + "lru-cache": "^9.1.1 || ^10.0.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/lru-cache": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.1.0.tgz", + "integrity": "sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==", + "engines": { + "node": "14 || >=16.14" + } + }, + "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/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/prettier": { + "version": "3.2.4", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.2.4.tgz", + "integrity": "sha512-FWu1oLHKCrtpO1ypU6J0SbK2d9Ckwysq6bHj/uaCP26DxrPpppCLQRGVuqAxSTvhF00AcvDRyYrLNW7ocBhFFQ==", + "dev": true, + "bin": { + "prettier": "bin/prettier.cjs" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/prettier/prettier?sponsor=1" + } + }, + "node_modules/process-nextick-args": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz", + "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==" + }, + "node_modules/promise.any": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/promise.any/-/promise.any-2.0.6.tgz", + "integrity": "sha512-Ew/MrPtTjiHnnki0AA2hS2o65JaZ5n+5pp08JSyWWUdeOGF4F41P+Dn+rdqnaOV/FTxhR6eBDX412luwn3th9g==", + "dependencies": { + "array.prototype.map": "^1.0.5", + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "es-aggregate-error": "^1.0.10", + "get-intrinsic": "^1.2.1", + "iterate-value": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==" + }, + "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/proxy-from-env": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz", + "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==" + }, + "node_modules/pstree.remy": { + "version": "1.1.8", + "resolved": "https://registry.npmjs.org/pstree.remy/-/pstree.remy-1.1.8.tgz", + "integrity": "sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==", + "dev": true + }, + "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.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz", + "integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==", + "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/readable-stream": { + "version": "2.3.7", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz", + "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/readable-stream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==" + }, + "node_modules/readable-stream/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/redis": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/redis/-/redis-3.1.2.tgz", + "integrity": "sha512-grn5KoZLr/qrRQVwoSkmzdbw6pwF+/rwODtrOr6vuBRiR/f3rjSTGupbF90Zpqm2oenix8Do6RV7pYEkGwlKkw==", + "dependencies": { + "denque": "^1.5.0", + "redis-commands": "^1.7.0", + "redis-errors": "^1.2.0", + "redis-parser": "^3.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/node-redis" + } + }, + "node_modules/redis-commands": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/redis-commands/-/redis-commands-1.7.0.tgz", + "integrity": "sha512-nJWqw3bTFy21hX/CPKHth6sfhZbdiHP6bTawSgQBlKOVRG7EZkfHbbHwQJnrE4vsQf0CMNE+3gJ4Fmm16vdVlQ==" + }, + "node_modules/redis-errors": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/redis-errors/-/redis-errors-1.2.0.tgz", + "integrity": "sha512-1qny3OExCf0UvUV/5wpYKf2YwPcOqXzkwKKSmKHiE6ZMQs5heeE/c8eXK+PNllPvmjgAbfnsbpkGZWy8cBpn9w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/redis-parser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/redis-parser/-/redis-parser-3.0.0.tgz", + "integrity": "sha512-DJnGAeenTdpMEH6uAJRK/uiyEIH9WVsUmoLwzudwGJUwZPp80PDBWPHXSAGNPwNvIXAbe7MSUB1zQFugFml66A==", + "dependencies": { + "redis-errors": "^1.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/redis/node_modules/denque": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/denque/-/denque-1.5.1.tgz", + "integrity": "sha512-XwE+iZ4D6ZUB7mfYRMb5wByE8L74HCn30FBN7sWnXksWc1LO1bPDl67pBR9o/kC4z/xSNAwkMYcGgqDV3BE3Hw==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/reflect-metadata": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.1.tgz", + "integrity": "sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==" + }, + "node_modules/regexp.prototype.flags": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz", + "integrity": "sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "set-function-name": "^2.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/repeat-string": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz", + "integrity": "sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==", + "dependencies": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/restore-cursor/node_modules/signal-exit": { + "version": "3.0.7", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" + }, + "node_modules/right-align": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/right-align/-/right-align-0.1.3.tgz", + "integrity": "sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==", + "dependencies": { + "align-text": "^0.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/run-async": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz", + "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/rxjs": { + "version": "7.8.1", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-7.8.1.tgz", + "integrity": "sha512-AA3TVj+0A2iuIoQkWEK/tqFjBq2j+6PO6Y0zJcvzLAFhEFIO3HL0vls9hWLncZbAAbK0mar7oZ4V079I/qPMxg==", + "peer": true, + "dependencies": { + "tslib": "^2.1.0" + } + }, + "node_modules/safe-array-concat": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.0.tgz", + "integrity": "sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==", + "dependencies": { + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "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/safe-regex-test": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.2.tgz", + "integrity": "sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==", + "dependencies": { + "call-bind": "^1.0.5", + "get-intrinsic": "^1.2.2", + "is-regex": "^1.1.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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/sax": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.3.0.tgz", + "integrity": "sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==" + }, + "node_modules/secure-json-parse": { + "version": "2.7.0", + "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", + "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==", + "license": "BSD-3-Clause" + }, + "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/semver/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/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/set-function-length": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.0.tgz", + "integrity": "sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==", + "dependencies": { + "define-data-property": "^1.1.1", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.2", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/set-function-name": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.1.tgz", + "integrity": "sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==", + "dependencies": { + "define-data-property": "^1.0.1", + "functions-have-names": "^1.2.3", + "has-property-descriptors": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" + }, + "node_modules/sha.js": { + "version": "2.4.11", + "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz", + "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==", + "dependencies": { + "inherits": "^2.0.1", + "safe-buffer": "^5.0.1" + }, + "bin": { + "sha.js": "bin.js" + } + }, + "node_modules/shebang-command": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", + "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", + "dependencies": { + "shebang-regex": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/shebang-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", + "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", + "engines": { + "node": ">=8" + } + }, + "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/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/simple-update-notifier": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/simple-update-notifier/-/simple-update-notifier-2.0.0.tgz", + "integrity": "sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==", + "dev": true, + "dependencies": { + "semver": "^7.5.3" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==" + }, + "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/ssf": { + "version": "0.11.2", + "resolved": "https://registry.npmjs.org/ssf/-/ssf-0.11.2.tgz", + "integrity": "sha512-+idbmIXoYET47hH+d7dfm2epdOMUDjqcB4648sTZ+t2JwoyBFL/insLfB/racrDmsKB3diwsDA696pZMieAC5g==", + "dependencies": { + "frac": "~1.1.2" + }, + "engines": { + "node": ">=0.8" + } + }, + "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/stop-iteration-iterator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.0.0.tgz", + "integrity": "sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==", + "dependencies": { + "internal-slot": "^1.0.4" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/streamsearch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/streamsearch/-/streamsearch-1.1.0.tgz", + "integrity": "sha512-Mcc5wHehp9aXz1ax6bZUyY5afg9u2rv5cqQI3mRrYkGC8rW2hM02jWuwjtL++LS5qinSyhj2QfLyNsuc+VsExg==", + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/string-width-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string.prototype.trim": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz", + "integrity": "sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimend": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz", + "integrity": "sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/string.prototype.trimstart": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz", + "integrity": "sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "dependencies": { + "has-flag": "^3.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/swagger-ui-dist": { + "version": "5.11.0", + "resolved": "https://registry.npmjs.org/swagger-ui-dist/-/swagger-ui-dist-5.11.0.tgz", + "integrity": "sha512-j0PIATqQSEFGOLmiJOJZj1X1Jt6bFIur3JpY7+ghliUnfZs0fpWDdHEkn9q7QUlBtKbkn6TepvSxTqnE8l3s0A==" + }, + "node_modules/swagger-ui-express": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/swagger-ui-express/-/swagger-ui-express-5.0.0.tgz", + "integrity": "sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==", + "dependencies": { + "swagger-ui-dist": ">=5.0.0" + }, + "engines": { + "node": ">= v0.10.32" + }, + "peerDependencies": { + "express": ">=4.0.0 || >=5.0.0-beta" + } + }, + "node_modules/swig-templates": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/swig-templates/-/swig-templates-2.0.3.tgz", + "integrity": "sha512-QojPTuZWdpznSZWZDB63/grsZuDwT/7geMeGlftbJXDoYBIZEnTcKvz4iwYDv3SwfPX9/B4RtGRSXNnm3S2wwg==", + "deprecated": "unmaintained", + "dependencies": { + "optimist": "~0.6", + "uglify-js": "2.6.0" + }, + "bin": { + "swig": "bin/swig.js" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/swig-templates/node_modules/cliui": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-2.1.0.tgz", + "integrity": "sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==", + "dependencies": { + "center-align": "^0.1.1", + "right-align": "^0.1.1", + "wordwrap": "0.0.2" + } + }, + "node_modules/swig-templates/node_modules/source-map": { + "version": "0.5.7", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz", + "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/swig-templates/node_modules/uglify-js": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-2.6.0.tgz", + "integrity": "sha512-SYZzhZQRrlAc6QT3Eqz4WHuyrCLjvvKmfII/of82rVACMxsIwb/CqlZVbUwOIq8Xd1EMp2WTtCrIxFYF+779zw==", + "dependencies": { + "async": "~0.2.6", + "source-map": "~0.5.1", + "uglify-to-browserify": "~1.0.0", + "yargs": "~3.10.0" + }, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/swig-templates/node_modules/wordwrap": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-0.0.2.tgz", + "integrity": "sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==", + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/swig-templates/node_modules/yargs": { + "version": "3.10.0", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-3.10.0.tgz", + "integrity": "sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==", + "dependencies": { + "camelcase": "^1.0.2", + "cliui": "^2.1.0", + "decamelize": "^1.0.0", + "window-size": "0.1.0" + } + }, + "node_modules/thenify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz", + "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==", + "dependencies": { + "any-promise": "^1.0.0" + } + }, + "node_modules/thenify-all": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz", + "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==", + "dependencies": { + "thenify": ">= 3.1.0 < 4" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==" + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dependencies": { + "os-tmpdir": "~1.0.2" + }, + "engines": { + "node": ">=0.6.0" + } + }, + "node_modules/to-regex-range": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", + "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", + "dev": true, + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "engines": { + "node": ">=0.6" + } + }, + "node_modules/touch": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/touch/-/touch-3.1.0.tgz", + "integrity": "sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==", + "dev": true, + "dependencies": { + "nopt": "~1.0.10" + }, + "bin": { + "nodetouch": "bin/nodetouch.js" + } + }, + "node_modules/tr46": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz", + "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", + "peer": true + }, + "node_modules/ts-node": { + "version": "10.9.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz", + "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==", + "devOptional": true, + "dependencies": { + "@cspotcode/source-map-support": "^0.8.0", + "@tsconfig/node10": "^1.0.7", + "@tsconfig/node12": "^1.0.7", + "@tsconfig/node14": "^1.0.0", + "@tsconfig/node16": "^1.0.2", + "acorn": "^8.4.1", + "acorn-walk": "^8.1.1", + "arg": "^4.1.0", + "create-require": "^1.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "v8-compile-cache-lib": "^3.0.1", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-cwd": "dist/bin-cwd.js", + "ts-node-esm": "dist/bin-esm.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "peerDependencies": { + "@swc/core": ">=1.2.50", + "@swc/wasm": ">=1.2.50", + "@types/node": "*", + "typescript": ">=2.7" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "@swc/wasm": { + "optional": true + } + } + }, + "node_modules/tslib": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz", + "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==" + }, + "node_modules/tsoa": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/tsoa/-/tsoa-6.0.1.tgz", + "integrity": "sha512-Far5BFpFvMYVMZxt87O7hOFGpa6dALQ8XHhdDytry0IhIUJnRliVXLZ2t2KGcgNw0bIwsk+2XkWra18LL6cORA==", + "dependencies": { + "@tsoa/cli": "^6.0.1", + "@tsoa/runtime": "^6.0.0" + }, + "bin": { + "tsoa": "dist/cli.js" + }, + "engines": { + "node": ">=18.0.0", + "yarn": ">=1.9.4" + } + }, + "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/typed-array-buffer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz", + "integrity": "sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==", + "dependencies": { + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/typed-array-byte-length": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz", + "integrity": "sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz", + "integrity": "sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "has-proto": "^1.0.1", + "is-typed-array": "^1.1.10" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typed-array-length": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.4.tgz", + "integrity": "sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==", + "dependencies": { + "call-bind": "^1.0.2", + "for-each": "^0.3.3", + "is-typed-array": "^1.1.9" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/typedarray": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", + "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" + }, + "node_modules/typeorm": { + "version": "0.3.19", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.3.19.tgz", + "integrity": "sha512-OGelrY5qEoAU80mR1iyvmUHiKCPUydL6xp6bebXzS7jyv/X70Gp/jBWRAfF4qGOfy2A7orMiGRfwsBUNbEL65g==", + "dependencies": { + "@sqltools/formatter": "^1.2.5", + "app-root-path": "^3.1.0", + "buffer": "^6.0.3", + "chalk": "^4.1.2", + "cli-highlight": "^2.1.11", + "dayjs": "^1.11.9", + "debug": "^4.3.4", + "dotenv": "^16.0.3", + "glob": "^10.3.10", + "mkdirp": "^2.1.3", + "reflect-metadata": "^0.1.13", + "sha.js": "^2.4.11", + "tslib": "^2.5.0", + "uuid": "^9.0.0", + "yargs": "^17.6.2" + }, + "bin": { + "typeorm": "cli.js", + "typeorm-ts-node-commonjs": "cli-ts-node-commonjs.js", + "typeorm-ts-node-esm": "cli-ts-node-esm.js" + }, + "engines": { + "node": ">= 12.9.0" + }, + "funding": { + "url": "https://opencollective.com/typeorm" + }, + "peerDependencies": { + "@google-cloud/spanner": "^5.18.0", + "@sap/hana-client": "^2.12.25", + "better-sqlite3": "^7.1.2 || ^8.0.0 || ^9.0.0", + "hdb-pool": "^0.1.6", + "ioredis": "^5.0.4", + "mongodb": "^5.8.0", + "mssql": "^9.1.1 || ^10.0.1", + "mysql2": "^2.2.5 || ^3.0.1", + "oracledb": "^6.3.0", + "pg": "^8.5.1", + "pg-native": "^3.0.0", + "pg-query-stream": "^4.0.0", + "redis": "^3.1.1 || ^4.0.0", + "sql.js": "^1.4.0", + "sqlite3": "^5.0.3", + "ts-node": "^10.7.0", + "typeorm-aurora-data-api-driver": "^2.0.0" + }, + "peerDependenciesMeta": { + "@google-cloud/spanner": { + "optional": true + }, + "@sap/hana-client": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "hdb-pool": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "mongodb": { + "optional": true + }, + "mssql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "pg-query-stream": { + "optional": true + }, + "redis": { + "optional": true + }, + "sql.js": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "ts-node": { + "optional": true + }, + "typeorm-aurora-data-api-driver": { + "optional": true + } + } + }, + "node_modules/typeorm-cli": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/typeorm-cli/-/typeorm-cli-1.0.7.tgz", + "integrity": "sha512-BJ/F728MZFfkS+2HREdB+KqAEUuvmlzUlJdcUdH0KP+2h9bVEmcPDSjeMFXssWZoHsmtrny/8iI9Sshrx7UTGg==", + "dependencies": { + "@types/node": "^12.7.1", + "colors-console": "^1.0.3", + "commander": "^2.20.0", + "inquirer": "^6.5.1", + "js-beautify": "^1.10.2", + "mkdirp": "^0.5.1", + "mysql": "^2.17.1", + "reflect-metadata": "^0.1.13", + "swig-templates": "^2.0.3", + "ts-node": "^8.3.0", + "typeorm": "^0.2.18", + "typescript": "^3.5.3", + "warning": "^4.0.3" + }, + "bin": { + "typeorm-cli": "build/cli.js" + } + }, + "node_modules/typeorm-cli/node_modules/@types/node": { + "version": "12.20.55", + "resolved": "https://registry.npmjs.org/@types/node/-/node-12.20.55.tgz", + "integrity": "sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==" + }, + "node_modules/typeorm-cli/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/typeorm-cli/node_modules/dotenv": { + "version": "8.6.0", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz", + "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==", + "engines": { + "node": ">=10" + } + }, + "node_modules/typeorm-cli/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/typeorm-cli/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==", + "optional": true, + "peer": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/typeorm-cli/node_modules/long": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/long/-/long-4.0.0.tgz", + "integrity": "sha512-XsP+KhQif4bjX1kbuSiySJFNAehNxgLb6hPRGJ9QsUr8ajHkuXGdrHmFUTUUXhDwVX2R5bY4JNZEwbUiMhV+MA==", + "optional": true, + "peer": true + }, + "node_modules/typeorm-cli/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==", + "optional": true, + "peer": true, + "dependencies": { + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/typeorm-cli/node_modules/mkdirp": { + "version": "0.5.6", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.6.tgz", + "integrity": "sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==", + "dependencies": { + "minimist": "^1.2.6" + }, + "bin": { + "mkdirp": "bin/cmd.js" + } + }, + "node_modules/typeorm-cli/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/typeorm-cli/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==", + "optional": true, + "peer": true, + "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/typeorm-cli/node_modules/reflect-metadata": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==" + }, + "node_modules/typeorm-cli/node_modules/ts-node": { + "version": "8.10.2", + "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-8.10.2.tgz", + "integrity": "sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==", + "dependencies": { + "arg": "^4.1.0", + "diff": "^4.0.1", + "make-error": "^1.1.1", + "source-map-support": "^0.5.17", + "yn": "3.1.1" + }, + "bin": { + "ts-node": "dist/bin.js", + "ts-node-script": "dist/bin-script.js", + "ts-node-transpile-only": "dist/bin-transpile.js", + "ts-script": "dist/bin-script-deprecated.js" + }, + "engines": { + "node": ">=6.0.0" + }, + "peerDependencies": { + "typescript": ">=2.7" + } + }, + "node_modules/typeorm-cli/node_modules/typeorm": { + "version": "0.2.45", + "resolved": "https://registry.npmjs.org/typeorm/-/typeorm-0.2.45.tgz", + "integrity": "sha512-c0rCO8VMJ3ER7JQ73xfk0zDnVv0WDjpsP6Q1m6CVKul7DB9iVdWLRjPzc8v2eaeBuomsbZ2+gTaYr8k1gm3bYA==", + "dependencies": { + "@sqltools/formatter": "^1.2.2", + "app-root-path": "^3.0.0", + "buffer": "^6.0.3", + "chalk": "^4.1.0", + "cli-highlight": "^2.1.11", + "debug": "^4.3.1", + "dotenv": "^8.2.0", + "glob": "^7.1.6", + "js-yaml": "^4.0.0", + "mkdirp": "^1.0.4", + "reflect-metadata": "^0.1.13", + "sha.js": "^2.4.11", + "tslib": "^2.1.0", + "uuid": "^8.3.2", + "xml2js": "^0.4.23", + "yargs": "^17.0.1", + "zen-observable-ts": "^1.0.0" + }, + "bin": { + "typeorm": "cli.js" + }, + "funding": { + "url": "https://opencollective.com/typeorm" + }, + "peerDependencies": { + "@sap/hana-client": "^2.11.14", + "better-sqlite3": "^7.1.2", + "hdb-pool": "^0.1.6", + "ioredis": "^4.28.3", + "mongodb": "^3.6.0", + "mssql": "^6.3.1", + "mysql2": "^2.2.5", + "oracledb": "^5.1.0", + "pg": "^8.5.1", + "pg-native": "^3.0.0", + "pg-query-stream": "^4.0.0", + "redis": "^3.1.1", + "sql.js": "^1.4.0", + "sqlite3": "^5.0.2", + "typeorm-aurora-data-api-driver": "^2.0.0" + }, + "peerDependenciesMeta": { + "@sap/hana-client": { + "optional": true + }, + "better-sqlite3": { + "optional": true + }, + "hdb-pool": { + "optional": true + }, + "ioredis": { + "optional": true + }, + "mongodb": { + "optional": true + }, + "mssql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "oracledb": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "pg-query-stream": { + "optional": true + }, + "redis": { + "optional": true + }, + "sql.js": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "typeorm-aurora-data-api-driver": { + "optional": true + } + } + }, + "node_modules/typeorm-cli/node_modules/typeorm/node_modules/mkdirp": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", + "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", + "bin": { + "mkdirp": "bin/cmd.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/typeorm-cli/node_modules/typescript": { + "version": "3.9.10", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-3.9.10.tgz", + "integrity": "sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=4.2.0" + } + }, + "node_modules/typeorm-cli/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==", + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/typeorm/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/typeorm/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/typeorm/node_modules/reflect-metadata": { + "version": "0.1.14", + "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", + "integrity": "sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==" + }, + "node_modules/typescript": { + "version": "5.3.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.3.3.tgz", + "integrity": "sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "node_modules/uglify-js": { + "version": "3.17.4", + "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.17.4.tgz", + "integrity": "sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==", + "optional": true, + "bin": { + "uglifyjs": "bin/uglifyjs" + }, + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/uglify-to-browserify": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/uglify-to-browserify/-/uglify-to-browserify-1.0.2.tgz", + "integrity": "sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==" + }, + "node_modules/uid": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", + "integrity": "sha512-u3xV3X7uzvi5b1MncmZo3i2Aw222Zk1keqLA1YkHldREkAhAqi65wuPfe7lHx8H/Wzy+8CE7S7uS3jekIM5s8g==", + "peer": true, + "dependencies": { + "@lukeed/csprng": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/unbox-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dependencies": { + "call-bind": "^1.0.2", + "has-bigints": "^1.0.2", + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/undefsafe": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/undefsafe/-/undefsafe-2.0.5.tgz", + "integrity": "sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==", + "dev": true + }, + "node_modules/undici": { + "version": "6.19.2", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.19.2.tgz", + "integrity": "sha512-JfjKqIauur3Q6biAtHJ564e3bWa8VvT+7cSiOJHFbX4Erv6CLGDpg8z+Fmg/1OI/47RA+GI2QZaF48SSaLvyBA==", + "license": "MIT", + "engines": { + "node": ">=18.17" + } + }, + "node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==" + }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "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": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/v8-compile-cache-lib": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz", + "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==", + "devOptional": true + }, + "node_modules/validator": { + "version": "13.11.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", + "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "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/warning": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz", + "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==", + "dependencies": { + "loose-envify": "^1.0.0" + } + }, + "node_modules/webidl-conversions": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", + "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", + "peer": true + }, + "node_modules/whatwg-url": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", + "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==", + "peer": true, + "dependencies": { + "tr46": "~0.0.3", + "webidl-conversions": "^3.0.0" + } + }, + "node_modules/which": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", + "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "node-which": "bin/node-which" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/which-boxed-primitive": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dependencies": { + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/which-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.13.tgz", + "integrity": "sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==", + "dependencies": { + "available-typed-arrays": "^1.0.5", + "call-bind": "^1.0.4", + "for-each": "^0.3.3", + "gopd": "^1.0.1", + "has-tostringtag": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/window-size": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.0.tgz", + "integrity": "sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==", + "engines": { + "node": ">= 0.8.0" + } + }, + "node_modules/wmf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wmf/-/wmf-1.0.2.tgz", + "integrity": "sha512-/p9K7bEh0Dj6WbXg4JG0xvLQmIadrner1bi45VMJTfnbVHsc7yIajZyoSoK60/dtVBs12Fm6WkUI5/3WAVsNMw==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/word": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/word/-/word-0.3.0.tgz", + "integrity": "sha512-OELeY0Q61OXpdUfTp+oweA/vtLVg5VDOXh+3he3PNzLGG/y0oylSOC1xRVj0+l4vQ3tj/bB1HVHv1ocXkQceFA==", + "engines": { + "node": ">=0.8" + } + }, + "node_modules/wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==" + }, + "node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/wrap-ansi-cjs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/xlsx": { + "version": "0.18.5", + "resolved": "https://registry.npmjs.org/xlsx/-/xlsx-0.18.5.tgz", + "integrity": "sha512-dmg3LCjBPHZnQp5/F/+nnTa+miPJxUXB6vtk42YjBBKayDNagxGEeIdWApkYPOf3Z3pm3k62Knjzp7lMeTEtFQ==", + "dependencies": { + "adler-32": "~1.3.0", + "cfb": "~1.2.1", + "codepage": "~1.15.0", + "crc-32": "~1.2.1", + "ssf": "~0.11.2", + "wmf": "~1.0.1", + "word": "~0.3.0" + }, + "bin": { + "xlsx": "bin/xlsx.njs" + }, + "engines": { + "node": ">=0.8" + } + }, + "node_modules/xml2js": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.4.23.tgz", + "integrity": "sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==", + "dependencies": { + "sax": ">=0.6.0", + "xmlbuilder": "~11.0.0" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "node_modules/xmlbuilder": { + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz", + "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==", + "engines": { + "node": ">=4.0" + } + }, + "node_modules/xtend": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", + "integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==", + "engines": { + "node": ">=0.4" + } + }, + "node_modules/y18n": { + "version": "5.0.8", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz", + "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==", + "engines": { + "node": ">=10" + } + }, + "node_modules/yallist": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" + }, + "node_modules/yamljs": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/yamljs/-/yamljs-0.3.0.tgz", + "integrity": "sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==", + "dependencies": { + "argparse": "^1.0.7", + "glob": "^7.0.5" + }, + "bin": { + "json2yaml": "bin/json2yaml", + "yaml2json": "bin/yaml2json" + } + }, + "node_modules/yamljs/node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/yargs": { + "version": "17.7.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", + "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==", + "dependencies": { + "cliui": "^8.0.1", + "escalade": "^3.1.1", + "get-caller-file": "^2.0.5", + "require-directory": "^2.1.1", + "string-width": "^4.2.3", + "y18n": "^5.0.5", + "yargs-parser": "^21.1.1" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs-parser": { + "version": "21.1.1", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz", + "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==", + "engines": { + "node": ">=12" + } + }, + "node_modules/yargs/node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==" + }, + "node_modules/yargs/node_modules/string-width": { + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yargs/node_modules/strip-ansi": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/yn": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz", + "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==", + "engines": { + "node": ">=6" + } + }, + "node_modules/zen-observable": { + "version": "0.8.15", + "resolved": "https://registry.npmjs.org/zen-observable/-/zen-observable-0.8.15.tgz", + "integrity": "sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==" + }, + "node_modules/zen-observable-ts": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/zen-observable-ts/-/zen-observable-ts-1.1.0.tgz", + "integrity": "sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==", + "dependencies": { + "@types/zen-observable": "0.8.3", + "zen-observable": "0.8.15" + } + } + } +} diff --git a/package.json b/package.json new file mode 100644 index 0000000..9f2d6c7 --- /dev/null +++ b/package.json @@ -0,0 +1,50 @@ +{ + "name": "template", + "version": "1.0.0", + "description": "", + "main": "src/app.js", + "scripts": { + "dev": "nodemon", + "check": "tsc --noEmit", + "start": "node ./dist/app.js", + "format": "prettier --write .", + "build": "tsoa spec-and-routes && tsc", + "migration:generate": "typeorm-ts-node-commonjs migration:generate -d src/database/data-source.ts", + "migration:run": "typeorm-ts-node-commonjs migration:run -d src/database/data-source.ts" + }, + "keywords": [], + "author": "", + "license": "ISC", + "devDependencies": { + "@types/cors": "^2.8.17", + "@types/express": "^4.17.21", + "@types/node": "^20.11.5", + "@types/node-cron": "^3.0.11", + "@types/swagger-ui-express": "^4.1.6", + "nodemon": "^3.0.3", + "prettier": "^3.2.2", + "ts-node": "^10.9.2", + "typescript": "^5.3.3" + }, + "dependencies": { + "@elastic/elasticsearch": "^8.14.0", + "@nestjs/platform-express": "^10.3.7", + "@tsoa/runtime": "^6.0.0", + "axios": "^1.6.8", + "cors": "^2.8.5", + "dotenv": "^16.3.1", + "express": "^4.18.2", + "fast-jwt": "^3.3.2", + "multer": "^1.4.5-lts.1", + "mysql2": "^3.9.1", + "node-cron": "^3.0.3", + "promise.any": "^2.0.6", + "reflect-metadata": "^0.2.1", + "swagger-ui-express": "^5.0.0", + "tsoa": "^6.0.1", + "typeorm": "^0.3.19", + "typeorm-cli": "^1.0.7", + "xlsx": "^0.18.5", + "redis": "~3.1.2" + } +} diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml new file mode 100644 index 0000000..6970772 --- /dev/null +++ b/pnpm-lock.yaml @@ -0,0 +1,2904 @@ +lockfileVersion: '6.0' + +settings: + autoInstallPeers: true + excludeLinksFromLockfile: false + +dependencies: + '@tsoa/runtime': + specifier: ^6.0.0 + version: 6.0.0 + cors: + specifier: ^2.8.5 + version: 2.8.5 + dotenv: + specifier: ^16.3.1 + version: 16.3.1 + express: + specifier: ^4.18.2 + version: 4.18.2 + fast-jwt: + specifier: ^3.3.2 + version: 3.3.2 + mysql2: + specifier: ^3.7.1 + version: 3.7.1 + promise.any: + specifier: ^2.0.6 + version: 2.0.6 + reflect-metadata: + specifier: ^0.2.1 + version: 0.2.1 + swagger-ui-express: + specifier: ^5.0.0 + version: 5.0.0(express@4.18.2) + tsoa: + specifier: ^6.0.1 + version: 6.0.1 + typeorm: + specifier: ^0.3.19 + version: 0.3.19(mysql2@3.7.1)(ts-node@10.9.2) + typeorm-cli: + specifier: ^1.0.7 + version: 1.0.7(mysql2@3.7.1) + +devDependencies: + '@types/cors': + specifier: ^2.8.17 + version: 2.8.17 + '@types/express': + specifier: ^4.17.21 + version: 4.17.21 + '@types/node': + specifier: ^20.11.5 + version: 20.11.5 + '@types/swagger-ui-express': + specifier: ^4.1.6 + version: 4.1.6 + nodemon: + specifier: ^3.0.3 + version: 3.0.3 + prettier: + specifier: ^3.2.2 + version: 3.2.2 + ts-node: + specifier: ^10.9.2 + version: 10.9.2(@types/node@20.11.5)(typescript@5.3.3) + typescript: + specifier: ^5.3.3 + version: 5.3.3 + +packages: + + /@cspotcode/source-map-support@0.8.1: + resolution: {integrity: sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==} + engines: {node: '>=12'} + dependencies: + '@jridgewell/trace-mapping': 0.3.9 + + /@isaacs/cliui@8.0.2: + resolution: {integrity: sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==} + engines: {node: '>=12'} + dependencies: + string-width: 5.1.2 + string-width-cjs: /string-width@4.2.3 + strip-ansi: 7.1.0 + strip-ansi-cjs: /strip-ansi@6.0.1 + wrap-ansi: 8.1.0 + wrap-ansi-cjs: /wrap-ansi@7.0.0 + dev: false + + /@jridgewell/resolve-uri@3.1.1: + resolution: {integrity: sha512-dSYZh7HhCDtCKm4QakX0xFpsRDqjjtZf/kjI/v3T3Nwt5r8/qz/M19F9ySyOqU94SXBmeG9ttTul+YnR4LOxFA==} + engines: {node: '>=6.0.0'} + + /@jridgewell/sourcemap-codec@1.4.15: + resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==} + + /@jridgewell/trace-mapping@0.3.9: + resolution: {integrity: sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==} + dependencies: + '@jridgewell/resolve-uri': 3.1.1 + '@jridgewell/sourcemap-codec': 1.4.15 + + /@lukeed/ms@2.0.2: + resolution: {integrity: sha512-9I2Zn6+NJLfaGoz9jN3lpwDgAYvfGeNYdbAIjJOqzs4Tpc+VU3Jqq4IofSUBKajiDS8k9fZIg18/z13mpk1bsA==} + engines: {node: '>=8'} + dev: false + + /@one-ini/wasm@0.1.1: + resolution: {integrity: sha512-XuySG1E38YScSJoMlqovLru4KTUNSjgVTIjyh7qMX6aNN5HY5Ct5LhRJdxO79JtTzKfzV/bnWpz+zquYrISsvw==} + dev: false + + /@pkgjs/parseargs@0.11.0: + resolution: {integrity: sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==} + engines: {node: '>=14'} + requiresBuild: true + dev: false + optional: true + + /@sqltools/formatter@1.2.5: + resolution: {integrity: sha512-Uy0+khmZqUrUGm5dmMqVlnvufZRSK0FbYzVgp0UMstm+F5+W2/jnEEQyc9vo1ZR/E5ZI/B1WjjoTqBqwJL6Krw==} + dev: false + + /@tsconfig/node10@1.0.9: + resolution: {integrity: sha512-jNsYVVxU8v5g43Erja32laIDHXeoNvFEpX33OK4d6hljo3jDhCBDhx5dhCCTMWUojscpAagGiRkBKxpdl9fxqA==} + + /@tsconfig/node12@1.0.11: + resolution: {integrity: sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==} + + /@tsconfig/node14@1.0.3: + resolution: {integrity: sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==} + + /@tsconfig/node16@1.0.4: + resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==} + + /@tsoa/cli@6.0.1: + resolution: {integrity: sha512-SpdWPIzAtfG6Jcb6KIvT4VVo9VnAfAiY6+dCrrlKURlEfah05rRQ7k09jeJdAZoeeoKVwyJNj+43zlh9w1u7bg==} + engines: {node: '>=18.0.0', yarn: '>=1.9.4'} + hasBin: true + dependencies: + '@tsoa/runtime': 6.0.0 + '@types/multer': 1.4.11 + deepmerge: 4.3.1 + fs-extra: 11.2.0 + glob: 10.3.10 + handlebars: 4.7.8 + merge-anything: 5.1.7 + minimatch: 9.0.3 + typescript: 5.3.3 + validator: 13.11.0 + yamljs: 0.3.0 + yargs: 17.7.2 + dev: false + + /@tsoa/runtime@6.0.0: + resolution: {integrity: sha512-n0LYcjII313kDn3M4bZdAjU+sX7595sIEA3bw4pvxWRrkandyDdDFNrfQL8nZ3Pw6dkTmK7brZi0YBBDhe0Rzw==} + engines: {node: '>=18.0.0', yarn: '>=1.9.4'} + dependencies: + '@types/multer': 1.4.11 + reflect-metadata: 0.2.1 + validator: 13.11.0 + dev: false + + /@types/body-parser@1.19.5: + resolution: {integrity: sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==} + dependencies: + '@types/connect': 3.4.38 + '@types/node': 20.11.5 + + /@types/connect@3.4.38: + resolution: {integrity: sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==} + dependencies: + '@types/node': 20.11.5 + + /@types/cors@2.8.17: + resolution: {integrity: sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==} + dependencies: + '@types/node': 20.11.5 + dev: true + + /@types/express-serve-static-core@4.17.41: + resolution: {integrity: sha512-OaJ7XLaelTgrvlZD8/aa0vvvxZdUmlCn6MtWeB7TkiKW70BQLc9XEPpDLPdbo52ZhXUCrznlWdCHWxJWtdyajA==} + dependencies: + '@types/node': 20.11.5 + '@types/qs': 6.9.11 + '@types/range-parser': 1.2.7 + '@types/send': 0.17.4 + + /@types/express@4.17.21: + resolution: {integrity: sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==} + dependencies: + '@types/body-parser': 1.19.5 + '@types/express-serve-static-core': 4.17.41 + '@types/qs': 6.9.11 + '@types/serve-static': 1.15.5 + + /@types/http-errors@2.0.4: + resolution: {integrity: sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==} + + /@types/mime@1.3.5: + resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} + + /@types/mime@3.0.4: + resolution: {integrity: sha512-iJt33IQnVRkqeqC7PzBHPTC6fDlRNRW8vjrgqtScAhrmMwe8c4Eo7+fUGTa+XdWrpEgpyKWMYmi2dIwMAYRzPw==} + + /@types/multer@1.4.11: + resolution: {integrity: sha512-svK240gr6LVWvv3YGyhLlA+6LRRWA4mnGIU7RcNmgjBYFl6665wcXrRfxGp5tEPVHUNm5FMcmq7too9bxCwX/w==} + dependencies: + '@types/express': 4.17.21 + dev: false + + /@types/node@12.20.55: + resolution: {integrity: sha512-J8xLz7q2OFulZ2cyGTLE1TbbZcjpno7FaN6zdJNrgAdrJ+DZzh/uFR6YrTb4C+nXakvud8Q4+rbhoIWlYQbUFQ==} + dev: false + + /@types/node@20.11.5: + resolution: {integrity: sha512-g557vgQjUUfN76MZAN/dt1z3dzcUsimuysco0KeluHgrPdJXkP/XdAURgyO2W9fZWHRtRBiVKzKn8vyOAwlG+w==} + dependencies: + undici-types: 5.26.5 + + /@types/qs@6.9.11: + resolution: {integrity: sha512-oGk0gmhnEJK4Yyk+oI7EfXsLayXatCWPHary1MtcmbAifkobT9cM9yutG/hZKIseOU0MqbIwQ/u2nn/Gb+ltuQ==} + + /@types/range-parser@1.2.7: + resolution: {integrity: sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==} + + /@types/send@0.17.4: + resolution: {integrity: sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==} + dependencies: + '@types/mime': 1.3.5 + '@types/node': 20.11.5 + + /@types/serve-static@1.15.5: + resolution: {integrity: sha512-PDRk21MnK70hja/YF8AHfC7yIsiQHn1rcXx7ijCFBX/k+XQJhQT/gw3xekXKJvx+5SXaMMS8oqQy09Mzvz2TuQ==} + dependencies: + '@types/http-errors': 2.0.4 + '@types/mime': 3.0.4 + '@types/node': 20.11.5 + + /@types/swagger-ui-express@4.1.6: + resolution: {integrity: sha512-UVSiGYXa5IzdJJG3hrc86e8KdZWLYxyEsVoUI4iPXc7CO4VZ3AfNP8d/8+hrDRIqz+HAaSMtZSqAsF3Nq2X/Dg==} + dependencies: + '@types/express': 4.17.21 + '@types/serve-static': 1.15.5 + dev: true + + /@types/zen-observable@0.8.3: + resolution: {integrity: sha512-fbF6oTd4sGGy0xjHPKAt+eS2CrxJ3+6gQ3FGcBoIJR2TLAyCkCyI8JqZNy+FeON0AhVgNJoUumVoZQjBFUqHkw==} + dev: false + + /abbrev@1.1.1: + resolution: {integrity: sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==} + dev: true + + /abbrev@2.0.0: + resolution: {integrity: sha512-6/mh1E2u2YgEsCHdY0Yx5oW+61gZU+1vXaoiHHrpKeuRNNgFvS+/jrwHiQhB5apAf5oB7UB7E19ol2R2LKH8hQ==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + dev: false + + /accepts@1.3.8: + resolution: {integrity: sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==} + engines: {node: '>= 0.6'} + dependencies: + mime-types: 2.1.35 + negotiator: 0.6.3 + dev: false + + /acorn-walk@8.3.2: + resolution: {integrity: sha512-cjkyv4OtNCIeqhHrfS81QWXoCBPExR/J62oyEqepVw8WaQeSqpW2uhuLPh1m9eWhDuOo/jUXVTlifvesOWp/4A==} + engines: {node: '>=0.4.0'} + + /acorn@8.11.3: + resolution: {integrity: sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==} + engines: {node: '>=0.4.0'} + hasBin: true + + /align-text@0.1.4: + resolution: {integrity: sha512-GrTZLRpmp6wIC2ztrWW9MjjTgSKccffgFagbNDOX95/dcjEcYZibYTeaOntySQLcdw1ztBoFkviiUvTMbb9MYg==} + engines: {node: '>=0.10.0'} + dependencies: + kind-of: 3.2.2 + longest: 1.0.1 + repeat-string: 1.6.1 + dev: false + + /ansi-escapes@3.2.0: + resolution: {integrity: sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==} + engines: {node: '>=4'} + dev: false + + /ansi-regex@3.0.1: + resolution: {integrity: sha512-+O9Jct8wf++lXxxFc4hc8LsjaSq0HFzzL7cVsw8pRDIPdjKD2mT4ytDZlLuSBZ4cLKZFXIrMGO7DbQCtMJJMKw==} + engines: {node: '>=4'} + dev: false + + /ansi-regex@4.1.1: + resolution: {integrity: sha512-ILlv4k/3f6vfQ4OoP2AGvirOktlQ98ZEL1k9FaQjxa3L1abBgbuTDAdPOpvbGncC0BTVQrl+OM8xZGK6tWXt7g==} + engines: {node: '>=6'} + dev: false + + /ansi-regex@5.0.1: + resolution: {integrity: sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==} + engines: {node: '>=8'} + dev: false + + /ansi-regex@6.0.1: + resolution: {integrity: sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==} + engines: {node: '>=12'} + dev: false + + /ansi-styles@3.2.1: + resolution: {integrity: sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==} + engines: {node: '>=4'} + dependencies: + color-convert: 1.9.3 + dev: false + + /ansi-styles@4.3.0: + resolution: {integrity: sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==} + engines: {node: '>=8'} + dependencies: + color-convert: 2.0.1 + dev: false + + /ansi-styles@6.2.1: + resolution: {integrity: sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==} + engines: {node: '>=12'} + dev: false + + /any-promise@1.3.0: + resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==} + dev: false + + /anymatch@3.1.3: + resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} + engines: {node: '>= 8'} + dependencies: + normalize-path: 3.0.0 + picomatch: 2.3.1 + dev: true + + /app-root-path@3.1.0: + resolution: {integrity: sha512-biN3PwB2gUtjaYy/isrU3aNWI5w+fAfvHkSvCKeQGxhmYpwKFUxudR3Yya+KqVRHBmEDYh+/lTozYCFbmzX4nA==} + engines: {node: '>= 6.0.0'} + dev: false + + /arg@4.1.3: + resolution: {integrity: sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==} + + /argparse@1.0.10: + resolution: {integrity: sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==} + dependencies: + sprintf-js: 1.0.3 + dev: false + + /argparse@2.0.1: + resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} + dev: false + + /array-buffer-byte-length@1.0.0: + resolution: {integrity: sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A==} + dependencies: + call-bind: 1.0.5 + is-array-buffer: 3.0.2 + dev: false + + /array-flatten@1.1.1: + resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + dev: false + + /array.prototype.map@1.0.6: + resolution: {integrity: sha512-nK1psgF2cXqP3wSyCSq0Hc7zwNq3sfljQqaG27r/7a7ooNUnn5nGq6yYWyks9jMO5EoFQ0ax80hSg6oXSRNXaw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-array-method-boxes-properly: 1.0.0 + is-string: 1.0.7 + dev: false + + /arraybuffer.prototype.slice@1.0.2: + resolution: {integrity: sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + get-intrinsic: 1.2.2 + is-array-buffer: 3.0.2 + is-shared-array-buffer: 1.0.2 + dev: false + + /asn1.js@5.4.1: + resolution: {integrity: sha512-+I//4cYPccV8LdmBLiX8CYvf9Sp3vQsrqu2QNXRcrbiWvcx/UdlFiqUJJzxRQxgsZmvhXhn4cSKeSmoFjVdupA==} + dependencies: + bn.js: 4.12.0 + inherits: 2.0.4 + minimalistic-assert: 1.0.1 + safer-buffer: 2.1.2 + dev: false + + /async@0.2.10: + resolution: {integrity: sha512-eAkdoKxU6/LkKDBzLpT+t6Ff5EtfSF4wx1WfJiPEEV7WNLnDaRXk0oVysiEPm262roaachGexwUv94WhSgN5TQ==} + dev: false + + /available-typed-arrays@1.0.5: + resolution: {integrity: sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==} + engines: {node: '>= 0.4'} + dev: false + + /balanced-match@1.0.2: + resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + + /base64-js@1.5.1: + resolution: {integrity: sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==} + dev: false + + /bignumber.js@9.0.0: + resolution: {integrity: sha512-t/OYhhJ2SD+YGBQcjY8GzzDHEk9f3nerxjtfa6tlMXfe7frs/WozhvCNoGvpM0P3bNf3Gq5ZRMlGr5f3r4/N8A==} + dev: false + + /binary-extensions@2.2.0: + resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==} + engines: {node: '>=8'} + dev: true + + /bn.js@4.12.0: + resolution: {integrity: sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==} + dev: false + + /body-parser@1.20.1: + resolution: {integrity: sha512-jWi7abTbYwajOytWCQc37VulmWiRae5RyTpaCyDcS5/lMdtwSz5lOpDE67srw/HYe35f1z3fDQw+3txg7gNtWw==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dependencies: + bytes: 3.1.2 + content-type: 1.0.5 + 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 + transitivePeerDependencies: + - supports-color + dev: false + + /brace-expansion@1.1.11: + resolution: {integrity: sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==} + dependencies: + balanced-match: 1.0.2 + concat-map: 0.0.1 + + /brace-expansion@2.0.1: + resolution: {integrity: sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==} + dependencies: + balanced-match: 1.0.2 + dev: false + + /braces@3.0.2: + resolution: {integrity: sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==} + engines: {node: '>=8'} + dependencies: + fill-range: 7.0.1 + dev: true + + /buffer-from@1.1.2: + resolution: {integrity: sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==} + dev: false + + /buffer@6.0.3: + resolution: {integrity: sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==} + dependencies: + base64-js: 1.5.1 + ieee754: 1.2.1 + dev: false + + /bytes@3.1.2: + resolution: {integrity: sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==} + engines: {node: '>= 0.8'} + dev: false + + /call-bind@1.0.5: + resolution: {integrity: sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ==} + dependencies: + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + set-function-length: 1.2.0 + dev: false + + /camelcase@1.2.1: + resolution: {integrity: sha512-wzLkDa4K/mzI1OSITC+DUyjgIl/ETNHE9QvYgy6J6Jvqyyz4C0Xfd+lQhb19sX2jMpZV4IssUn0VDVmglV+s4g==} + engines: {node: '>=0.10.0'} + dev: false + + /center-align@0.1.3: + resolution: {integrity: sha512-Baz3aNe2gd2LP2qk5U+sDk/m4oSuwSDcBfayTCTBoWpfIGO5XFxPmjILQII4NGiZjD6DoDI6kf7gKaxkf7s3VQ==} + engines: {node: '>=0.10.0'} + dependencies: + align-text: 0.1.4 + lazy-cache: 1.0.4 + dev: false + + /chalk@2.4.2: + resolution: {integrity: sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==} + engines: {node: '>=4'} + dependencies: + ansi-styles: 3.2.1 + escape-string-regexp: 1.0.5 + supports-color: 5.5.0 + dev: false + + /chalk@4.1.2: + resolution: {integrity: sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + supports-color: 7.2.0 + dev: false + + /chardet@0.7.0: + resolution: {integrity: sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==} + dev: false + + /chokidar@3.5.3: + resolution: {integrity: sha512-Dr3sfKRP6oTcjf2JmUmFJfeVMvXBdegxB0iVQ5eb2V10uFJUCAS8OByZdVAyVb8xXNz3GjjTgj9kLWsZTqE6kw==} + engines: {node: '>= 8.10.0'} + dependencies: + anymatch: 3.1.3 + braces: 3.0.2 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + dev: true + + /cli-cursor@2.1.0: + resolution: {integrity: sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==} + engines: {node: '>=4'} + dependencies: + restore-cursor: 2.0.0 + dev: false + + /cli-highlight@2.1.11: + resolution: {integrity: sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==} + engines: {node: '>=8.0.0', npm: '>=5.0.0'} + hasBin: true + dependencies: + chalk: 4.1.2 + highlight.js: 10.7.3 + mz: 2.7.0 + parse5: 5.1.1 + parse5-htmlparser2-tree-adapter: 6.0.1 + yargs: 16.2.0 + dev: false + + /cli-width@2.2.1: + resolution: {integrity: sha512-GRMWDxpOB6Dgk2E5Uo+3eEBvtOOlimMmpbFiKuLFnQzYDavtLFY3K5ona41jgN/WdRZtG7utuVSVTL4HbZHGkw==} + dev: false + + /cliui@2.1.0: + resolution: {integrity: sha512-GIOYRizG+TGoc7Wgc1LiOTLare95R3mzKgoln+Q/lE4ceiYH19gUpl0l0Ffq4lJDEf3FxujMe6IBfOCs7pfqNA==} + dependencies: + center-align: 0.1.3 + right-align: 0.1.3 + wordwrap: 0.0.2 + dev: false + + /cliui@7.0.4: + resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: false + + /cliui@8.0.1: + resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==} + engines: {node: '>=12'} + dependencies: + string-width: 4.2.3 + strip-ansi: 6.0.1 + wrap-ansi: 7.0.0 + dev: false + + /color-convert@1.9.3: + resolution: {integrity: sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==} + dependencies: + color-name: 1.1.3 + dev: false + + /color-convert@2.0.1: + resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==} + engines: {node: '>=7.0.0'} + dependencies: + color-name: 1.1.4 + dev: false + + /color-name@1.1.3: + resolution: {integrity: sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==} + dev: false + + /color-name@1.1.4: + resolution: {integrity: sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==} + dev: false + + /colors-console@1.0.3: + resolution: {integrity: sha512-Q31K32UwadWqAxs+Iu46gNm4HJqUwrTJT2zen5NnhkKE5w7uqeZQZiuODUOxM/zOtHfiUTkia0io6zbN/VcCUQ==} + dev: false + + /commander@10.0.1: + resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} + engines: {node: '>=14'} + dev: false + + /commander@2.20.3: + resolution: {integrity: sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==} + dev: false + + /concat-map@0.0.1: + resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} + + /config-chain@1.1.13: + resolution: {integrity: sha512-qj+f8APARXHrM0hraqXYb2/bOVSV4PvJQlNZ/DVj0QrmNM2q2euizkeuVckQ57J+W0mRH6Hvi+k50M4Jul2VRQ==} + dependencies: + ini: 1.3.8 + proto-list: 1.2.4 + dev: false + + /content-disposition@0.5.4: + resolution: {integrity: sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==} + engines: {node: '>= 0.6'} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /content-type@1.0.5: + resolution: {integrity: sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==} + engines: {node: '>= 0.6'} + dev: false + + /cookie-signature@1.0.6: + resolution: {integrity: sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==} + dev: false + + /cookie@0.5.0: + resolution: {integrity: sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw==} + engines: {node: '>= 0.6'} + dev: false + + /core-util-is@1.0.3: + resolution: {integrity: sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==} + dev: false + + /cors@2.8.5: + resolution: {integrity: sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==} + engines: {node: '>= 0.10'} + dependencies: + object-assign: 4.1.1 + vary: 1.1.2 + dev: false + + /create-require@1.1.1: + resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + + /cross-spawn@7.0.3: + resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} + engines: {node: '>= 8'} + dependencies: + path-key: 3.1.1 + shebang-command: 2.0.0 + which: 2.0.2 + dev: false + + /dayjs@1.11.10: + resolution: {integrity: sha512-vjAczensTgRcqDERK0SR2XMwsF/tSvnvlv6VcF2GIhg6Sx4yOIt/irsr1RDJsKiIyBzJDpCoXiWWq28MqH2cnQ==} + dev: false + + /debug@2.6.9: + resolution: {integrity: sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.0.0 + dev: false + + /debug@4.3.4(supports-color@5.5.0): + resolution: {integrity: sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==} + engines: {node: '>=6.0'} + peerDependencies: + supports-color: '*' + peerDependenciesMeta: + supports-color: + optional: true + dependencies: + ms: 2.1.2 + supports-color: 5.5.0 + + /decamelize@1.2.0: + resolution: {integrity: sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==} + engines: {node: '>=0.10.0'} + dev: false + + /deepmerge@4.3.1: + resolution: {integrity: sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==} + engines: {node: '>=0.10.0'} + dev: false + + /define-data-property@1.1.1: + resolution: {integrity: sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: false + + /define-properties@1.2.1: + resolution: {integrity: sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + has-property-descriptors: 1.0.1 + object-keys: 1.1.1 + dev: false + + /denque@2.1.0: + resolution: {integrity: sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==} + engines: {node: '>=0.10'} + dev: false + + /depd@2.0.0: + resolution: {integrity: sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==} + engines: {node: '>= 0.8'} + dev: false + + /destroy@1.2.0: + resolution: {integrity: sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==} + engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} + dev: false + + /diff@4.0.2: + resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} + engines: {node: '>=0.3.1'} + + /dotenv@16.3.1: + resolution: {integrity: sha512-IPzF4w4/Rd94bA9imS68tZBaYyBWSCE47V1RGuMrB94iyTOIEwRmVL2x/4An+6mETpLrKJ5hQkB8W4kFAadeIQ==} + engines: {node: '>=12'} + dev: false + + /dotenv@8.6.0: + resolution: {integrity: sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==} + engines: {node: '>=10'} + dev: false + + /eastasianwidth@0.2.0: + resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} + dev: false + + /ecdsa-sig-formatter@1.0.11: + resolution: {integrity: sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==} + dependencies: + safe-buffer: 5.2.1 + dev: false + + /editorconfig@1.0.4: + resolution: {integrity: sha512-L9Qe08KWTlqYMVvMcTIvMAdl1cDUubzRNYL+WfA4bLDMHe4nemKkpmYzkznE1FwLKu0EEmy6obgQKzMJrg4x9Q==} + engines: {node: '>=14'} + hasBin: true + dependencies: + '@one-ini/wasm': 0.1.1 + commander: 10.0.1 + minimatch: 9.0.1 + semver: 7.5.4 + dev: false + + /ee-first@1.1.1: + resolution: {integrity: sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==} + dev: false + + /emoji-regex@8.0.0: + resolution: {integrity: sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==} + dev: false + + /emoji-regex@9.2.2: + resolution: {integrity: sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==} + dev: false + + /encodeurl@1.0.2: + resolution: {integrity: sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==} + engines: {node: '>= 0.8'} + dev: false + + /es-abstract@1.22.3: + resolution: {integrity: sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA==} + engines: {node: '>= 0.4'} + dependencies: + array-buffer-byte-length: 1.0.0 + arraybuffer.prototype.slice: 1.0.2 + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + es-set-tostringtag: 2.0.2 + es-to-primitive: 1.2.1 + function.prototype.name: 1.1.6 + get-intrinsic: 1.2.2 + get-symbol-description: 1.0.0 + globalthis: 1.0.3 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + internal-slot: 1.0.6 + is-array-buffer: 3.0.2 + is-callable: 1.2.7 + is-negative-zero: 2.0.2 + is-regex: 1.1.4 + is-shared-array-buffer: 1.0.2 + is-string: 1.0.7 + is-typed-array: 1.1.12 + is-weakref: 1.0.2 + object-inspect: 1.13.1 + object-keys: 1.1.1 + object.assign: 4.1.5 + regexp.prototype.flags: 1.5.1 + safe-array-concat: 1.1.0 + safe-regex-test: 1.0.2 + string.prototype.trim: 1.2.8 + string.prototype.trimend: 1.0.7 + string.prototype.trimstart: 1.0.7 + typed-array-buffer: 1.0.0 + typed-array-byte-length: 1.0.0 + typed-array-byte-offset: 1.0.0 + typed-array-length: 1.0.4 + unbox-primitive: 1.0.2 + which-typed-array: 1.1.13 + dev: false + + /es-aggregate-error@1.0.11: + resolution: {integrity: sha512-DCiZiNlMlbvofET/cE55My387NiLvuGToBEZDdK9U2G3svDCjL8WOgO5Il6lO83nQ8qmag/R9nArdpaFQ/m3lA==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + define-properties: 1.2.1 + es-abstract: 1.22.3 + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + globalthis: 1.0.3 + has-property-descriptors: 1.0.1 + set-function-name: 2.0.1 + dev: false + + /es-array-method-boxes-properly@1.0.0: + resolution: {integrity: sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==} + dev: false + + /es-get-iterator@1.1.3: + resolution: {integrity: sha512-sPZmqHBe6JIiTfN5q2pEi//TwxmAFHwj/XEuYjTuse78i8KxaqMTTzxPoFKuzRpDpTJ+0NAbpfenkmH2rePtuw==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + has-symbols: 1.0.3 + is-arguments: 1.1.1 + is-map: 2.0.2 + is-set: 2.0.2 + is-string: 1.0.7 + isarray: 2.0.5 + stop-iteration-iterator: 1.0.0 + dev: false + + /es-set-tostringtag@2.0.2: + resolution: {integrity: sha512-BuDyupZt65P9D2D2vA/zqcI3G5xRsklm5N3xCwuiy+/vKy8i0ifdsQP1sLgO4tZDSCaQUSnmC48khknGMV3D2Q==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + has-tostringtag: 1.0.0 + hasown: 2.0.0 + dev: false + + /es-to-primitive@1.2.1: + resolution: {integrity: sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==} + engines: {node: '>= 0.4'} + dependencies: + is-callable: 1.2.7 + is-date-object: 1.0.5 + is-symbol: 1.0.4 + dev: false + + /escalade@3.1.1: + resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==} + engines: {node: '>=6'} + dev: false + + /escape-html@1.0.3: + resolution: {integrity: sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==} + dev: false + + /escape-string-regexp@1.0.5: + resolution: {integrity: sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==} + engines: {node: '>=0.8.0'} + dev: false + + /etag@1.8.1: + resolution: {integrity: sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==} + engines: {node: '>= 0.6'} + dev: false + + /express@4.18.2: + resolution: {integrity: sha512-5/PsL6iGPdfQ/lKM1UuielYgv3BUoJfz1aUwU9vHZ+J7gyvwdQXFEBIEIaxeGf0GIcreATNyBExtalisDbuMqQ==} + engines: {node: '>= 0.10.0'} + dependencies: + accepts: 1.3.8 + array-flatten: 1.1.1 + body-parser: 1.20.1 + content-disposition: 0.5.4 + content-type: 1.0.5 + 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 + transitivePeerDependencies: + - supports-color + dev: false + + /external-editor@3.1.0: + resolution: {integrity: sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==} + engines: {node: '>=4'} + dependencies: + chardet: 0.7.0 + iconv-lite: 0.4.24 + tmp: 0.0.33 + dev: false + + /fast-jwt@3.3.2: + resolution: {integrity: sha512-H+JYxaFy2LepiC1AQWM/2hzKlQOWaWUkEnu/yebhYu4+ameb3qG77WiRZ1Ct6YBk6d/ESsNguBfTT5+q0XMtKg==} + engines: {node: '>=16 <22'} + dependencies: + '@lukeed/ms': 2.0.2 + asn1.js: 5.4.1 + ecdsa-sig-formatter: 1.0.11 + mnemonist: 0.39.7 + dev: false + + /figures@2.0.0: + resolution: {integrity: sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==} + engines: {node: '>=4'} + dependencies: + escape-string-regexp: 1.0.5 + dev: false + + /fill-range@7.0.1: + resolution: {integrity: sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==} + engines: {node: '>=8'} + dependencies: + to-regex-range: 5.0.1 + dev: true + + /finalhandler@1.2.0: + resolution: {integrity: sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==} + engines: {node: '>= 0.8'} + 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 + transitivePeerDependencies: + - supports-color + dev: false + + /for-each@0.3.3: + resolution: {integrity: sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==} + dependencies: + is-callable: 1.2.7 + dev: false + + /foreground-child@3.1.1: + resolution: {integrity: sha512-TMKDUnIte6bfb5nWv7V/caI169OHgvwjb7V4WkeUvbQQdjr5rWKqHFiKWb/fcOwB+CzBT+qbWjvj+DVwRskpIg==} + engines: {node: '>=14'} + dependencies: + cross-spawn: 7.0.3 + signal-exit: 4.1.0 + dev: false + + /forwarded@0.2.0: + resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==} + engines: {node: '>= 0.6'} + dev: false + + /fresh@0.5.2: + resolution: {integrity: sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==} + engines: {node: '>= 0.6'} + dev: false + + /fs-extra@11.2.0: + resolution: {integrity: sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==} + engines: {node: '>=14.14'} + dependencies: + graceful-fs: 4.2.11 + jsonfile: 6.1.0 + universalify: 2.0.1 + dev: false + + /fs.realpath@1.0.0: + resolution: {integrity: sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==} + dev: false + + /fsevents@2.3.3: + resolution: {integrity: sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==} + engines: {node: ^8.16.0 || ^10.6.0 || >=11.0.0} + os: [darwin] + requiresBuild: true + dev: true + optional: true + + /function-bind@1.1.2: + resolution: {integrity: sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==} + dev: false + + /function.prototype.name@1.1.6: + resolution: {integrity: sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + functions-have-names: 1.2.3 + dev: false + + /functions-have-names@1.2.3: + resolution: {integrity: sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==} + dev: false + + /generate-function@2.3.1: + resolution: {integrity: sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==} + dependencies: + is-property: 1.0.2 + dev: false + + /get-caller-file@2.0.5: + resolution: {integrity: sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==} + engines: {node: 6.* || 8.* || >= 10.*} + dev: false + + /get-intrinsic@1.2.2: + resolution: {integrity: sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA==} + dependencies: + function-bind: 1.1.2 + has-proto: 1.0.1 + has-symbols: 1.0.3 + hasown: 2.0.0 + dev: false + + /get-symbol-description@1.0.0: + resolution: {integrity: sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + dev: false + + /glob-parent@5.1.2: + resolution: {integrity: sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==} + engines: {node: '>= 6'} + dependencies: + is-glob: 4.0.3 + dev: true + + /glob@10.3.10: + resolution: {integrity: sha512-fa46+tv1Ak0UPK1TOy/pZrIybNNt4HCv7SDzwyfiOZkvZLEbjsZkJBPtDHVshZjbecAoAGSC20MjLDG/qr679g==} + engines: {node: '>=16 || 14 >=14.17'} + hasBin: true + dependencies: + foreground-child: 3.1.1 + jackspeak: 2.3.6 + minimatch: 9.0.3 + minipass: 7.0.4 + path-scurry: 1.10.1 + dev: false + + /glob@7.2.3: + resolution: {integrity: sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==} + dependencies: + fs.realpath: 1.0.0 + inflight: 1.0.6 + inherits: 2.0.4 + minimatch: 3.1.2 + once: 1.4.0 + path-is-absolute: 1.0.1 + dev: false + + /globalthis@1.0.3: + resolution: {integrity: sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA==} + engines: {node: '>= 0.4'} + dependencies: + define-properties: 1.2.1 + dev: false + + /gopd@1.0.1: + resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} + dependencies: + get-intrinsic: 1.2.2 + dev: false + + /graceful-fs@4.2.11: + resolution: {integrity: sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==} + dev: false + + /handlebars@4.7.8: + resolution: {integrity: sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==} + engines: {node: '>=0.4.7'} + hasBin: true + dependencies: + minimist: 1.2.8 + neo-async: 2.6.2 + source-map: 0.6.1 + wordwrap: 1.0.0 + optionalDependencies: + uglify-js: 3.17.4 + dev: false + + /has-bigints@1.0.2: + resolution: {integrity: sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==} + dev: false + + /has-flag@3.0.0: + resolution: {integrity: sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==} + engines: {node: '>=4'} + + /has-flag@4.0.0: + resolution: {integrity: sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==} + engines: {node: '>=8'} + dev: false + + /has-property-descriptors@1.0.1: + resolution: {integrity: sha512-VsX8eaIewvas0xnvinAe9bw4WfIeODpGYikiWYLH+dma0Jw6KHYqWiWfhQlgOVK8D6PvjubK5Uc4P0iIhIcNVg==} + dependencies: + get-intrinsic: 1.2.2 + dev: false + + /has-proto@1.0.1: + resolution: {integrity: sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg==} + engines: {node: '>= 0.4'} + dev: false + + /has-symbols@1.0.3: + resolution: {integrity: sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==} + engines: {node: '>= 0.4'} + dev: false + + /has-tostringtag@1.0.0: + resolution: {integrity: sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: false + + /hasown@2.0.0: + resolution: {integrity: sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA==} + engines: {node: '>= 0.4'} + dependencies: + function-bind: 1.1.2 + dev: false + + /highlight.js@10.7.3: + resolution: {integrity: sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==} + dev: false + + /http-errors@2.0.0: + resolution: {integrity: sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==} + engines: {node: '>= 0.8'} + dependencies: + depd: 2.0.0 + inherits: 2.0.4 + setprototypeof: 1.2.0 + statuses: 2.0.1 + toidentifier: 1.0.1 + dev: false + + /iconv-lite@0.4.24: + resolution: {integrity: sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /iconv-lite@0.6.3: + resolution: {integrity: sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==} + engines: {node: '>=0.10.0'} + dependencies: + safer-buffer: 2.1.2 + dev: false + + /ieee754@1.2.1: + resolution: {integrity: sha512-dcyqhDvX1C46lXZcVqCpK+FtMRQVdIMN6/Df5js2zouUsqG7I6sFxitIC+7KYK29KdXOLHdu9zL4sFnoVQnqaA==} + dev: false + + /ignore-by-default@1.0.1: + resolution: {integrity: sha512-Ius2VYcGNk7T90CppJqcIkS5ooHUZyIQK+ClZfMfMNFEF9VSE73Fq+906u/CWu92x4gzZMWOwfFYckPObzdEbA==} + dev: true + + /inflight@1.0.6: + resolution: {integrity: sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==} + dependencies: + once: 1.4.0 + wrappy: 1.0.2 + dev: false + + /inherits@2.0.4: + resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==} + dev: false + + /ini@1.3.8: + resolution: {integrity: sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==} + dev: false + + /inquirer@6.5.2: + resolution: {integrity: sha512-cntlB5ghuB0iuO65Ovoi8ogLHiWGs/5yNrtUcKjFhSSiVeAIVpD7koaSU9RM8mpXw5YDi9RdYXGQMaOURB7ycQ==} + engines: {node: '>=6.0.0'} + dependencies: + ansi-escapes: 3.2.0 + chalk: 2.4.2 + cli-cursor: 2.1.0 + cli-width: 2.2.1 + external-editor: 3.1.0 + figures: 2.0.0 + lodash: 4.17.21 + mute-stream: 0.0.7 + run-async: 2.4.1 + rxjs: 6.6.7 + string-width: 2.1.1 + strip-ansi: 5.2.0 + through: 2.3.8 + dev: false + + /internal-slot@1.0.6: + resolution: {integrity: sha512-Xj6dv+PsbtwyPpEflsejS+oIZxmMlV44zAhG479uYu89MsjcYOhCFnNyKrkJrihbsiasQyY0afoCl/9BLR65bg==} + engines: {node: '>= 0.4'} + dependencies: + get-intrinsic: 1.2.2 + hasown: 2.0.0 + side-channel: 1.0.4 + dev: false + + /ipaddr.js@1.9.1: + resolution: {integrity: sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==} + engines: {node: '>= 0.10'} + dev: false + + /is-arguments@1.1.1: + resolution: {integrity: sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: false + + /is-array-buffer@3.0.2: + resolution: {integrity: sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: false + + /is-bigint@1.0.4: + resolution: {integrity: sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==} + dependencies: + has-bigints: 1.0.2 + dev: false + + /is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + dependencies: + binary-extensions: 2.2.0 + dev: true + + /is-boolean-object@1.1.2: + resolution: {integrity: sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: false + + /is-buffer@1.1.6: + resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} + dev: false + + /is-callable@1.2.7: + resolution: {integrity: sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==} + engines: {node: '>= 0.4'} + dev: false + + /is-date-object@1.0.5: + resolution: {integrity: sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: false + + /is-extglob@2.1.1: + resolution: {integrity: sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==} + engines: {node: '>=0.10.0'} + dev: true + + /is-fullwidth-code-point@2.0.0: + resolution: {integrity: sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==} + engines: {node: '>=4'} + dev: false + + /is-fullwidth-code-point@3.0.0: + resolution: {integrity: sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==} + engines: {node: '>=8'} + dev: false + + /is-glob@4.0.3: + resolution: {integrity: sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==} + engines: {node: '>=0.10.0'} + dependencies: + is-extglob: 2.1.1 + dev: true + + /is-map@2.0.2: + resolution: {integrity: sha512-cOZFQQozTha1f4MxLFzlgKYPTyj26picdZTx82hbc/Xf4K/tZOOXSCkMvU4pKioRXGDLJRn0GM7Upe7kR721yg==} + dev: false + + /is-negative-zero@2.0.2: + resolution: {integrity: sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA==} + engines: {node: '>= 0.4'} + dev: false + + /is-number-object@1.0.7: + resolution: {integrity: sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: false + + /is-number@7.0.0: + resolution: {integrity: sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==} + engines: {node: '>=0.12.0'} + dev: true + + /is-property@1.0.2: + resolution: {integrity: sha512-Ks/IoX00TtClbGQr4TWXemAnktAQvYB7HzcCxDGqEZU6oCmb2INHuOoKxbtR+HFkmYWBKv/dOZtGRiAjDhj92g==} + dev: false + + /is-regex@1.1.4: + resolution: {integrity: sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + has-tostringtag: 1.0.0 + dev: false + + /is-set@2.0.2: + resolution: {integrity: sha512-+2cnTEZeY5z/iXGbLhPrOAaK/Mau5k5eXq9j14CpRTftq0pAJu2MwVRSZhyZWBzx3o6X795Lz6Bpb6R0GKf37g==} + dev: false + + /is-shared-array-buffer@1.0.2: + resolution: {integrity: sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA==} + dependencies: + call-bind: 1.0.5 + dev: false + + /is-string@1.0.7: + resolution: {integrity: sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==} + engines: {node: '>= 0.4'} + dependencies: + has-tostringtag: 1.0.0 + dev: false + + /is-symbol@1.0.4: + resolution: {integrity: sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==} + engines: {node: '>= 0.4'} + dependencies: + has-symbols: 1.0.3 + dev: false + + /is-typed-array@1.1.12: + resolution: {integrity: sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg==} + engines: {node: '>= 0.4'} + dependencies: + which-typed-array: 1.1.13 + dev: false + + /is-weakref@1.0.2: + resolution: {integrity: sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==} + dependencies: + call-bind: 1.0.5 + dev: false + + /is-what@4.1.16: + resolution: {integrity: sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==} + engines: {node: '>=12.13'} + dev: false + + /isarray@1.0.0: + resolution: {integrity: sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==} + dev: false + + /isarray@2.0.5: + resolution: {integrity: sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==} + dev: false + + /isexe@2.0.0: + resolution: {integrity: sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==} + dev: false + + /iterate-iterator@1.0.2: + resolution: {integrity: sha512-t91HubM4ZDQ70M9wqp+pcNpu8OyJ9UAtXntT/Bcsvp5tZMnz9vRa+IunKXeI8AnfZMTv0jNuVEmGeLSMjVvfPw==} + dev: false + + /iterate-value@1.0.2: + resolution: {integrity: sha512-A6fMAio4D2ot2r/TYzr4yUWrmwNdsN5xL7+HUiyACE4DXm+q8HtPcnFTp+NnW3k4N05tZ7FVYFFb2CR13NxyHQ==} + dependencies: + es-get-iterator: 1.1.3 + iterate-iterator: 1.0.2 + dev: false + + /jackspeak@2.3.6: + resolution: {integrity: sha512-N3yCS/NegsOBokc8GAdM8UcmfsKiSS8cipheD/nivzr700H+nsMOxJjQnvwOcRYVuFkdH0wGUvW2WbXGmrZGbQ==} + engines: {node: '>=14'} + dependencies: + '@isaacs/cliui': 8.0.2 + optionalDependencies: + '@pkgjs/parseargs': 0.11.0 + dev: false + + /js-beautify@1.14.11: + resolution: {integrity: sha512-rPogWqAfoYh1Ryqqh2agUpVfbxAhbjuN1SmU86dskQUKouRiggUTCO4+2ym9UPXllc2WAp0J+T5qxn7Um3lCdw==} + engines: {node: '>=14'} + hasBin: true + dependencies: + config-chain: 1.1.13 + editorconfig: 1.0.4 + glob: 10.3.10 + nopt: 7.2.0 + dev: false + + /js-tokens@4.0.0: + resolution: {integrity: sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==} + dev: false + + /js-yaml@4.1.0: + resolution: {integrity: sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==} + hasBin: true + dependencies: + argparse: 2.0.1 + dev: false + + /jsonfile@6.1.0: + resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==} + dependencies: + universalify: 2.0.1 + optionalDependencies: + graceful-fs: 4.2.11 + dev: false + + /kind-of@3.2.2: + resolution: {integrity: sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==} + engines: {node: '>=0.10.0'} + dependencies: + is-buffer: 1.1.6 + dev: false + + /lazy-cache@1.0.4: + resolution: {integrity: sha512-RE2g0b5VGZsOCFOCgP7omTRYFqydmZkBwl5oNnQ1lDYC57uyO9KqNnNVxT7COSHTxrRCWVcAVOcbjk+tvh/rgQ==} + engines: {node: '>=0.10.0'} + dev: false + + /lodash@4.17.21: + resolution: {integrity: sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==} + dev: false + + /long@5.2.3: + resolution: {integrity: sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q==} + dev: false + + /longest@1.0.1: + resolution: {integrity: sha512-k+yt5n3l48JU4k8ftnKG6V7u32wyH2NfKzeMto9F/QRE0amxy/LayxwlvjjkZEIzqR+19IrtFO8p5kB9QaYUFg==} + engines: {node: '>=0.10.0'} + dev: false + + /loose-envify@1.4.0: + resolution: {integrity: sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==} + hasBin: true + dependencies: + js-tokens: 4.0.0 + dev: false + + /lru-cache@10.1.0: + resolution: {integrity: sha512-/1clY/ui8CzjKFyjdvwPWJUYKiFVXG2I2cY0ssG7h4+hwk+XOIX7ZSG9Q7TW8TW3Kp3BUSqgFWBLgL4PJ+Blag==} + engines: {node: 14 || >=16.14} + dev: false + + /lru-cache@6.0.0: + resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} + engines: {node: '>=10'} + dependencies: + yallist: 4.0.0 + + /lru-cache@7.18.3: + resolution: {integrity: sha512-jumlc0BIUrS3qJGgIkWZsyfAM7NCWiBcCDhnd+3NNM5KbBmLTgHVfWBcg6W+rLUsIpzpERPsvwUP7CckAQSOoA==} + engines: {node: '>=12'} + dev: false + + /lru-cache@8.0.5: + resolution: {integrity: sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==} + engines: {node: '>=16.14'} + dev: false + + /make-error@1.3.6: + resolution: {integrity: sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==} + + /media-typer@0.3.0: + resolution: {integrity: sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==} + engines: {node: '>= 0.6'} + dev: false + + /merge-anything@5.1.7: + resolution: {integrity: sha512-eRtbOb1N5iyH0tkQDAoQ4Ipsp/5qSR79Dzrz8hEPxRX10RWWR/iQXdoKmBSRCThY1Fh5EhISDtpSc93fpxUniQ==} + engines: {node: '>=12.13'} + dependencies: + is-what: 4.1.16 + dev: false + + /merge-descriptors@1.0.1: + resolution: {integrity: sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==} + dev: false + + /methods@1.1.2: + resolution: {integrity: sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==} + engines: {node: '>= 0.6'} + dev: false + + /mime-db@1.52.0: + resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==} + engines: {node: '>= 0.6'} + dev: false + + /mime-types@2.1.35: + resolution: {integrity: sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==} + engines: {node: '>= 0.6'} + dependencies: + mime-db: 1.52.0 + dev: false + + /mime@1.6.0: + resolution: {integrity: sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==} + engines: {node: '>=4'} + hasBin: true + dev: false + + /mimic-fn@1.2.0: + resolution: {integrity: sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==} + engines: {node: '>=4'} + dev: false + + /minimalistic-assert@1.0.1: + resolution: {integrity: sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==} + dev: false + + /minimatch@3.1.2: + resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==} + dependencies: + brace-expansion: 1.1.11 + + /minimatch@9.0.1: + resolution: {integrity: sha512-0jWhJpD/MdhPXwPuiRkCbfYfSKp2qnn2eOc279qI7f+osl/l+prKSrvhg157zSYvx/1nmgn2NqdT6k2Z7zSH9w==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: false + + /minimatch@9.0.3: + resolution: {integrity: sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + brace-expansion: 2.0.1 + dev: false + + /minimist@0.0.10: + resolution: {integrity: sha512-iotkTvxc+TwOm5Ieim8VnSNvCDjCK9S8G3scJ50ZthspSxa7jx50jkhYduuAtAjvfDUwSgOwf8+If99AlOEhyw==} + dev: false + + /minimist@1.2.8: + resolution: {integrity: sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==} + dev: false + + /minipass@7.0.4: + resolution: {integrity: sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==} + engines: {node: '>=16 || 14 >=14.17'} + dev: false + + /mkdirp@0.5.6: + resolution: {integrity: sha512-FP+p8RB8OWpF3YZBCrP5gtADmtXApB5AMLn+vdyA+PyxCjrCs00mjyUozssO33cwDeT3wNGdLxJ5M//YqtHAJw==} + hasBin: true + dependencies: + minimist: 1.2.8 + dev: false + + /mkdirp@1.0.4: + resolution: {integrity: sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==} + engines: {node: '>=10'} + hasBin: true + dev: false + + /mkdirp@2.1.6: + resolution: {integrity: sha512-+hEnITedc8LAtIP9u3HJDFIdcLV2vXP33sqLLIzkv1Db1zO/1OxbvYf0Y1OC/S/Qo5dxHXepofhmxL02PsKe+A==} + engines: {node: '>=10'} + hasBin: true + dev: false + + /mnemonist@0.39.7: + resolution: {integrity: sha512-ix3FwHWZgdXUt0dHM8bCrI4r1KMeYx8bCunPCYmvKXq4tn6gbNsqrsb4q0kDbDqbpIOvEaW5Sn+dmDwGydfrwA==} + dependencies: + obliterator: 2.0.4 + dev: false + + /ms@2.0.0: + resolution: {integrity: sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==} + dev: false + + /ms@2.1.2: + resolution: {integrity: sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==} + + /ms@2.1.3: + resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + dev: false + + /mute-stream@0.0.7: + resolution: {integrity: sha512-r65nCZhrbXXb6dXOACihYApHw2Q6pV0M3V0PSxd74N0+D8nzAdEAITq2oAjA1jVnKI+tGvEBUpqiMh0+rW6zDQ==} + dev: false + + /mysql2@3.7.1: + resolution: {integrity: sha512-4EEqYu57mnkW5+Bvp5wBebY7PpfyrmvJ3knHcmLkp8FyBu4kqgrF2GxIjsC2tbLNZWqJaL21v/MYH7bU5f03oA==} + engines: {node: '>= 8.0'} + dependencies: + denque: 2.1.0 + generate-function: 2.3.1 + iconv-lite: 0.6.3 + long: 5.2.3 + lru-cache: 8.0.5 + named-placeholders: 1.1.3 + seq-queue: 0.0.5 + sqlstring: 2.3.3 + dev: false + + /mysql@2.18.1: + resolution: {integrity: sha512-Bca+gk2YWmqp2Uf6k5NFEurwY/0td0cpebAucFpY/3jhrwrVGuxU2uQFCHjU19SJfje0yQvi+rVWdq78hR5lig==} + engines: {node: '>= 0.6'} + dependencies: + bignumber.js: 9.0.0 + readable-stream: 2.3.7 + safe-buffer: 5.1.2 + sqlstring: 2.3.1 + dev: false + + /mz@2.7.0: + resolution: {integrity: sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==} + dependencies: + any-promise: 1.3.0 + object-assign: 4.1.1 + thenify-all: 1.6.0 + dev: false + + /named-placeholders@1.1.3: + resolution: {integrity: sha512-eLoBxg6wE/rZkJPhU/xRX1WTpkFEwDJEN96oxFrTsqBdbT5ec295Q+CoHrL9IT0DipqKhmGcaZmwOt8OON5x1w==} + engines: {node: '>=12.0.0'} + dependencies: + lru-cache: 7.18.3 + dev: false + + /negotiator@0.6.3: + resolution: {integrity: sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==} + engines: {node: '>= 0.6'} + dev: false + + /neo-async@2.6.2: + resolution: {integrity: sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==} + dev: false + + /nodemon@3.0.3: + resolution: {integrity: sha512-7jH/NXbFPxVaMwmBCC2B9F/V6X1VkEdNgx3iu9jji8WxWcvhMWkmhNWhI5077zknOnZnBzba9hZP6bCPJLSReQ==} + engines: {node: '>=10'} + hasBin: true + dependencies: + chokidar: 3.5.3 + debug: 4.3.4(supports-color@5.5.0) + ignore-by-default: 1.0.1 + minimatch: 3.1.2 + pstree.remy: 1.1.8 + semver: 7.5.4 + simple-update-notifier: 2.0.0 + supports-color: 5.5.0 + touch: 3.1.0 + undefsafe: 2.0.5 + dev: true + + /nopt@1.0.10: + resolution: {integrity: sha512-NWmpvLSqUrgrAC9HCuxEvb+PSloHpqVu+FqcO4eeF2h5qYRhA7ev6KvelyQAKtegUbC6RypJnlEOhd8vloNKYg==} + hasBin: true + dependencies: + abbrev: 1.1.1 + dev: true + + /nopt@7.2.0: + resolution: {integrity: sha512-CVDtwCdhYIvnAzFoJ6NJ6dX3oga9/HyciQDnG1vQDjSLMeKLJ4A93ZqYKDrgYSr1FBY5/hMYC+2VCi24pgpkGA==} + engines: {node: ^14.17.0 || ^16.13.0 || >=18.0.0} + hasBin: true + dependencies: + abbrev: 2.0.0 + dev: false + + /normalize-path@3.0.0: + resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==} + engines: {node: '>=0.10.0'} + dev: true + + /object-assign@4.1.1: + resolution: {integrity: sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==} + engines: {node: '>=0.10.0'} + dev: false + + /object-inspect@1.13.1: + resolution: {integrity: sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==} + dev: false + + /object-keys@1.1.1: + resolution: {integrity: sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==} + engines: {node: '>= 0.4'} + dev: false + + /object.assign@4.1.5: + resolution: {integrity: sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + has-symbols: 1.0.3 + object-keys: 1.1.1 + dev: false + + /obliterator@2.0.4: + resolution: {integrity: sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ==} + dev: false + + /on-finished@2.4.1: + resolution: {integrity: sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==} + engines: {node: '>= 0.8'} + dependencies: + ee-first: 1.1.1 + dev: false + + /once@1.4.0: + resolution: {integrity: sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==} + dependencies: + wrappy: 1.0.2 + dev: false + + /onetime@2.0.1: + resolution: {integrity: sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==} + engines: {node: '>=4'} + dependencies: + mimic-fn: 1.2.0 + dev: false + + /optimist@0.6.1: + resolution: {integrity: sha512-snN4O4TkigujZphWLN0E//nQmm7790RYaE53DdL7ZYwee2D8DDo9/EyYiKUfN3rneWUjhJnueija3G9I2i0h3g==} + dependencies: + minimist: 0.0.10 + wordwrap: 0.0.3 + dev: false + + /os-tmpdir@1.0.2: + resolution: {integrity: sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==} + engines: {node: '>=0.10.0'} + dev: false + + /parse5-htmlparser2-tree-adapter@6.0.1: + resolution: {integrity: sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==} + dependencies: + parse5: 6.0.1 + dev: false + + /parse5@5.1.1: + resolution: {integrity: sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==} + dev: false + + /parse5@6.0.1: + resolution: {integrity: sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==} + dev: false + + /parseurl@1.3.3: + resolution: {integrity: sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==} + engines: {node: '>= 0.8'} + dev: false + + /path-is-absolute@1.0.1: + resolution: {integrity: sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==} + engines: {node: '>=0.10.0'} + dev: false + + /path-key@3.1.1: + resolution: {integrity: sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==} + engines: {node: '>=8'} + dev: false + + /path-scurry@1.10.1: + resolution: {integrity: sha512-MkhCqzzBEpPvxxQ71Md0b1Kk51W01lrYvlMzSUaIzNsODdd7mqhiimSZlr+VegAz5Z6Vzt9Xg2ttE//XBhH3EQ==} + engines: {node: '>=16 || 14 >=14.17'} + dependencies: + lru-cache: 10.1.0 + minipass: 7.0.4 + dev: false + + /path-to-regexp@0.1.7: + resolution: {integrity: sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==} + dev: false + + /picomatch@2.3.1: + resolution: {integrity: sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==} + engines: {node: '>=8.6'} + dev: true + + /prettier@3.2.2: + resolution: {integrity: sha512-HTByuKZzw7utPiDO523Tt2pLtEyK7OibUD9suEJQrPUCYQqrHr74GGX6VidMrovbf/I50mPqr8j/II6oBAuc5A==} + engines: {node: '>=14'} + hasBin: true + dev: true + + /process-nextick-args@2.0.1: + resolution: {integrity: sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==} + dev: false + + /promise.any@2.0.6: + resolution: {integrity: sha512-Ew/MrPtTjiHnnki0AA2hS2o65JaZ5n+5pp08JSyWWUdeOGF4F41P+Dn+rdqnaOV/FTxhR6eBDX412luwn3th9g==} + engines: {node: '>= 0.4'} + dependencies: + array.prototype.map: 1.0.6 + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + es-aggregate-error: 1.0.11 + get-intrinsic: 1.2.2 + iterate-value: 1.0.2 + dev: false + + /proto-list@1.2.4: + resolution: {integrity: sha512-vtK/94akxsTMhe0/cbfpR+syPuszcuwhqVjJq26CuNDgFGj682oRBXOP5MJpv2r7JtE8MsiepGIqvvOTBwn2vA==} + dev: false + + /proxy-addr@2.0.7: + resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} + engines: {node: '>= 0.10'} + dependencies: + forwarded: 0.2.0 + ipaddr.js: 1.9.1 + dev: false + + /pstree.remy@1.1.8: + resolution: {integrity: sha512-77DZwxQmxKnu3aR542U+X8FypNzbfJ+C5XQDk3uWjWxn6151aIMGthWYRXTqT1E5oJvg+ljaa2OJi+VfvCOQ8w==} + dev: true + + /qs@6.11.0: + resolution: {integrity: sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==} + engines: {node: '>=0.6'} + dependencies: + side-channel: 1.0.4 + dev: false + + /range-parser@1.2.1: + resolution: {integrity: sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==} + engines: {node: '>= 0.6'} + dev: false + + /raw-body@2.5.1: + resolution: {integrity: sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig==} + engines: {node: '>= 0.8'} + dependencies: + bytes: 3.1.2 + http-errors: 2.0.0 + iconv-lite: 0.4.24 + unpipe: 1.0.0 + dev: false + + /readable-stream@2.3.7: + resolution: {integrity: sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==} + dependencies: + core-util-is: 1.0.3 + inherits: 2.0.4 + isarray: 1.0.0 + process-nextick-args: 2.0.1 + safe-buffer: 5.1.2 + string_decoder: 1.1.1 + util-deprecate: 1.0.2 + dev: false + + /readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + dependencies: + picomatch: 2.3.1 + dev: true + + /reflect-metadata@0.1.14: + resolution: {integrity: sha512-ZhYeb6nRaXCfhnndflDK8qI6ZQ/YcWZCISRAWICW9XYqMUwjZM9Z0DveWX/ABN01oxSHwVxKQmxeYZSsm0jh5A==} + dev: false + + /reflect-metadata@0.2.1: + resolution: {integrity: sha512-i5lLI6iw9AU3Uu4szRNPPEkomnkjRTaVt9hy/bn5g/oSzekBSMeLZblcjP74AW0vBabqERLLIrz+gR8QYR54Tw==} + dev: false + + /regexp.prototype.flags@1.5.1: + resolution: {integrity: sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + set-function-name: 2.0.1 + dev: false + + /repeat-string@1.6.1: + resolution: {integrity: sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==} + engines: {node: '>=0.10'} + dev: false + + /require-directory@2.1.1: + resolution: {integrity: sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==} + engines: {node: '>=0.10.0'} + dev: false + + /restore-cursor@2.0.0: + resolution: {integrity: sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==} + engines: {node: '>=4'} + dependencies: + onetime: 2.0.1 + signal-exit: 3.0.7 + dev: false + + /right-align@0.1.3: + resolution: {integrity: sha512-yqINtL/G7vs2v+dFIZmFUDbnVyFUJFKd6gK22Kgo6R4jfJGFtisKyncWDDULgjfqf4ASQuIQyjJ7XZ+3aWpsAg==} + engines: {node: '>=0.10.0'} + dependencies: + align-text: 0.1.4 + dev: false + + /run-async@2.4.1: + resolution: {integrity: sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==} + engines: {node: '>=0.12.0'} + dev: false + + /rxjs@6.6.7: + resolution: {integrity: sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==} + engines: {npm: '>=2.0.0'} + dependencies: + tslib: 1.14.1 + dev: false + + /safe-array-concat@1.1.0: + resolution: {integrity: sha512-ZdQ0Jeb9Ofti4hbt5lX3T2JcAamT9hfzYU1MNB+z/jaEbB6wfFfPIR/zEORmZqobkCCJhSjodobH6WHNmJ97dg==} + engines: {node: '>=0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + has-symbols: 1.0.3 + isarray: 2.0.5 + dev: false + + /safe-buffer@5.1.2: + resolution: {integrity: sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==} + dev: false + + /safe-buffer@5.2.1: + resolution: {integrity: sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==} + dev: false + + /safe-regex-test@1.0.2: + resolution: {integrity: sha512-83S9w6eFq12BBIJYvjMux6/dkirb8+4zJRA9cxNBVb7Wq5fJBW+Xze48WqR8pxua7bDuAaaAxtVVd4Idjp1dBQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-regex: 1.1.4 + dev: false + + /safer-buffer@2.1.2: + resolution: {integrity: sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==} + dev: false + + /sax@1.3.0: + resolution: {integrity: sha512-0s+oAmw9zLl1V1cS9BtZN7JAd0cW5e0QH4W3LWEK6a4LaLEA2OTpGYWDY+6XasBLtz6wkm3u1xRw95mRuJ59WA==} + dev: false + + /semver@7.5.4: + resolution: {integrity: sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA==} + engines: {node: '>=10'} + hasBin: true + dependencies: + lru-cache: 6.0.0 + + /send@0.18.0: + resolution: {integrity: sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==} + engines: {node: '>= 0.8.0'} + 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 + transitivePeerDependencies: + - supports-color + dev: false + + /seq-queue@0.0.5: + resolution: {integrity: sha512-hr3Wtp/GZIc/6DAGPDcV4/9WoZhjrkXsi5B/07QgX8tsdc6ilr7BFM6PM6rbdAX1kFSDYeZGLipIZZKyQP0O5Q==} + dev: false + + /serve-static@1.15.0: + resolution: {integrity: sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==} + engines: {node: '>= 0.8.0'} + dependencies: + encodeurl: 1.0.2 + escape-html: 1.0.3 + parseurl: 1.3.3 + send: 0.18.0 + transitivePeerDependencies: + - supports-color + dev: false + + /set-function-length@1.2.0: + resolution: {integrity: sha512-4DBHDoyHlM1IRPGYcoxexgh67y4ueR53FKV1yyxwFMY7aCqcN/38M1+SwZ/qJQ8iLv7+ck385ot4CcisOAPT9w==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + function-bind: 1.1.2 + get-intrinsic: 1.2.2 + gopd: 1.0.1 + has-property-descriptors: 1.0.1 + dev: false + + /set-function-name@2.0.1: + resolution: {integrity: sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA==} + engines: {node: '>= 0.4'} + dependencies: + define-data-property: 1.1.1 + functions-have-names: 1.2.3 + has-property-descriptors: 1.0.1 + dev: false + + /setprototypeof@1.2.0: + resolution: {integrity: sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==} + dev: false + + /sha.js@2.4.11: + resolution: {integrity: sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==} + hasBin: true + dependencies: + inherits: 2.0.4 + safe-buffer: 5.2.1 + dev: false + + /shebang-command@2.0.0: + resolution: {integrity: sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==} + engines: {node: '>=8'} + dependencies: + shebang-regex: 3.0.0 + dev: false + + /shebang-regex@3.0.0: + resolution: {integrity: sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==} + engines: {node: '>=8'} + dev: false + + /side-channel@1.0.4: + resolution: {integrity: sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + object-inspect: 1.13.1 + dev: false + + /signal-exit@3.0.7: + resolution: {integrity: sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==} + dev: false + + /signal-exit@4.1.0: + resolution: {integrity: sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==} + engines: {node: '>=14'} + dev: false + + /simple-update-notifier@2.0.0: + resolution: {integrity: sha512-a2B9Y0KlNXl9u/vsW6sTIu9vGEpfKu2wRV6l1H3XEas/0gUIzGzBoP/IouTcUQbm9JWZLH3COxyn03TYlFax6w==} + engines: {node: '>=10'} + dependencies: + semver: 7.5.4 + dev: true + + /source-map-support@0.5.21: + resolution: {integrity: sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==} + dependencies: + buffer-from: 1.1.2 + source-map: 0.6.1 + dev: false + + /source-map@0.5.7: + resolution: {integrity: sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==} + engines: {node: '>=0.10.0'} + dev: false + + /source-map@0.6.1: + resolution: {integrity: sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==} + engines: {node: '>=0.10.0'} + dev: false + + /sprintf-js@1.0.3: + resolution: {integrity: sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==} + dev: false + + /sqlstring@2.3.1: + resolution: {integrity: sha512-ooAzh/7dxIG5+uDik1z/Rd1vli0+38izZhGzSa34FwR7IbelPWCCKSNIl8jlL/F7ERvy8CB2jNeM1E9i9mXMAQ==} + engines: {node: '>= 0.6'} + dev: false + + /sqlstring@2.3.3: + resolution: {integrity: sha512-qC9iz2FlN7DQl3+wjwn3802RTyjCx7sDvfQEXchwa6CWOx07/WVfh91gBmQ9fahw8snwGEWU3xGzOt4tFyHLxg==} + engines: {node: '>= 0.6'} + dev: false + + /statuses@2.0.1: + resolution: {integrity: sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ==} + engines: {node: '>= 0.8'} + dev: false + + /stop-iteration-iterator@1.0.0: + resolution: {integrity: sha512-iCGQj+0l0HOdZ2AEeBADlsRC+vsnDsZsbdSiH1yNSjcfKM7fdpCMfqAL/dwF5BLiw/XhRft/Wax6zQbhq2BcjQ==} + engines: {node: '>= 0.4'} + dependencies: + internal-slot: 1.0.6 + dev: false + + /string-width@2.1.1: + resolution: {integrity: sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==} + engines: {node: '>=4'} + dependencies: + is-fullwidth-code-point: 2.0.0 + strip-ansi: 4.0.0 + dev: false + + /string-width@4.2.3: + resolution: {integrity: sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==} + engines: {node: '>=8'} + dependencies: + emoji-regex: 8.0.0 + is-fullwidth-code-point: 3.0.0 + strip-ansi: 6.0.1 + dev: false + + /string-width@5.1.2: + resolution: {integrity: sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==} + engines: {node: '>=12'} + dependencies: + eastasianwidth: 0.2.0 + emoji-regex: 9.2.2 + strip-ansi: 7.1.0 + dev: false + + /string.prototype.trim@1.2.8: + resolution: {integrity: sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: false + + /string.prototype.trimend@1.0.7: + resolution: {integrity: sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: false + + /string.prototype.trimstart@1.0.7: + resolution: {integrity: sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg==} + dependencies: + call-bind: 1.0.5 + define-properties: 1.2.1 + es-abstract: 1.22.3 + dev: false + + /string_decoder@1.1.1: + resolution: {integrity: sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==} + dependencies: + safe-buffer: 5.1.2 + dev: false + + /strip-ansi@4.0.0: + resolution: {integrity: sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==} + engines: {node: '>=4'} + dependencies: + ansi-regex: 3.0.1 + dev: false + + /strip-ansi@5.2.0: + resolution: {integrity: sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==} + engines: {node: '>=6'} + dependencies: + ansi-regex: 4.1.1 + dev: false + + /strip-ansi@6.0.1: + resolution: {integrity: sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==} + engines: {node: '>=8'} + dependencies: + ansi-regex: 5.0.1 + dev: false + + /strip-ansi@7.1.0: + resolution: {integrity: sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==} + engines: {node: '>=12'} + dependencies: + ansi-regex: 6.0.1 + dev: false + + /supports-color@5.5.0: + resolution: {integrity: sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==} + engines: {node: '>=4'} + dependencies: + has-flag: 3.0.0 + + /supports-color@7.2.0: + resolution: {integrity: sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==} + engines: {node: '>=8'} + dependencies: + has-flag: 4.0.0 + dev: false + + /swagger-ui-dist@5.11.0: + resolution: {integrity: sha512-j0PIATqQSEFGOLmiJOJZj1X1Jt6bFIur3JpY7+ghliUnfZs0fpWDdHEkn9q7QUlBtKbkn6TepvSxTqnE8l3s0A==} + dev: false + + /swagger-ui-express@5.0.0(express@4.18.2): + resolution: {integrity: sha512-tsU9tODVvhyfkNSvf03E6FAk+z+5cU3lXAzMy6Pv4av2Gt2xA0++fogwC4qo19XuFf6hdxevPuVCSKFuMHJhFA==} + engines: {node: '>= v0.10.32'} + peerDependencies: + express: '>=4.0.0 || >=5.0.0-beta' + dependencies: + express: 4.18.2 + swagger-ui-dist: 5.11.0 + dev: false + + /swig-templates@2.0.3: + resolution: {integrity: sha512-QojPTuZWdpznSZWZDB63/grsZuDwT/7geMeGlftbJXDoYBIZEnTcKvz4iwYDv3SwfPX9/B4RtGRSXNnm3S2wwg==} + engines: {node: '>=0.10.0'} + deprecated: unmaintained + hasBin: true + dependencies: + optimist: 0.6.1 + uglify-js: 2.6.0 + dev: false + + /thenify-all@1.6.0: + resolution: {integrity: sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==} + engines: {node: '>=0.8'} + dependencies: + thenify: 3.3.1 + dev: false + + /thenify@3.3.1: + resolution: {integrity: sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==} + dependencies: + any-promise: 1.3.0 + dev: false + + /through@2.3.8: + resolution: {integrity: sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==} + dev: false + + /tmp@0.0.33: + resolution: {integrity: sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==} + engines: {node: '>=0.6.0'} + dependencies: + os-tmpdir: 1.0.2 + dev: false + + /to-regex-range@5.0.1: + resolution: {integrity: sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==} + engines: {node: '>=8.0'} + dependencies: + is-number: 7.0.0 + dev: true + + /toidentifier@1.0.1: + resolution: {integrity: sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==} + engines: {node: '>=0.6'} + dev: false + + /touch@3.1.0: + resolution: {integrity: sha512-WBx8Uy5TLtOSRtIq+M03/sKDrXCLHxwDcquSP2c43Le03/9serjQBIztjRz6FkJez9D/hleyAXTBGLwwZUw9lA==} + hasBin: true + dependencies: + nopt: 1.0.10 + dev: true + + /ts-node@10.9.2(@types/node@20.11.5)(typescript@5.3.3): + resolution: {integrity: sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==} + hasBin: true + peerDependencies: + '@swc/core': '>=1.2.50' + '@swc/wasm': '>=1.2.50' + '@types/node': '*' + typescript: '>=2.7' + peerDependenciesMeta: + '@swc/core': + optional: true + '@swc/wasm': + optional: true + dependencies: + '@cspotcode/source-map-support': 0.8.1 + '@tsconfig/node10': 1.0.9 + '@tsconfig/node12': 1.0.11 + '@tsconfig/node14': 1.0.3 + '@tsconfig/node16': 1.0.4 + '@types/node': 20.11.5 + acorn: 8.11.3 + acorn-walk: 8.3.2 + arg: 4.1.3 + create-require: 1.1.1 + diff: 4.0.2 + make-error: 1.3.6 + typescript: 5.3.3 + v8-compile-cache-lib: 3.0.1 + yn: 3.1.1 + + /ts-node@8.10.2(typescript@3.9.10): + resolution: {integrity: sha512-ISJJGgkIpDdBhWVu3jufsWpK3Rzo7bdiIXJjQc0ynKxVOVcg2oIrf2H2cejminGrptVc6q6/uynAHNCuWGbpVA==} + engines: {node: '>=6.0.0'} + hasBin: true + peerDependencies: + typescript: '>=2.7' + dependencies: + arg: 4.1.3 + diff: 4.0.2 + make-error: 1.3.6 + source-map-support: 0.5.21 + typescript: 3.9.10 + yn: 3.1.1 + dev: false + + /tslib@1.14.1: + resolution: {integrity: sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==} + dev: false + + /tslib@2.6.2: + resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} + dev: false + + /tsoa@6.0.1: + resolution: {integrity: sha512-Far5BFpFvMYVMZxt87O7hOFGpa6dALQ8XHhdDytry0IhIUJnRliVXLZ2t2KGcgNw0bIwsk+2XkWra18LL6cORA==} + engines: {node: '>=18.0.0', yarn: '>=1.9.4'} + hasBin: true + dependencies: + '@tsoa/cli': 6.0.1 + '@tsoa/runtime': 6.0.0 + dev: false + + /type-is@1.6.18: + resolution: {integrity: sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==} + engines: {node: '>= 0.6'} + dependencies: + media-typer: 0.3.0 + mime-types: 2.1.35 + dev: false + + /typed-array-buffer@1.0.0: + resolution: {integrity: sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + get-intrinsic: 1.2.2 + is-typed-array: 1.1.12 + dev: false + + /typed-array-byte-length@1.0.0: + resolution: {integrity: sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA==} + engines: {node: '>= 0.4'} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: false + + /typed-array-byte-offset@1.0.0: + resolution: {integrity: sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + has-proto: 1.0.1 + is-typed-array: 1.1.12 + dev: false + + /typed-array-length@1.0.4: + resolution: {integrity: sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng==} + dependencies: + call-bind: 1.0.5 + for-each: 0.3.3 + is-typed-array: 1.1.12 + dev: false + + /typeorm-cli@1.0.7(mysql2@3.7.1): + resolution: {integrity: sha512-BJ/F728MZFfkS+2HREdB+KqAEUuvmlzUlJdcUdH0KP+2h9bVEmcPDSjeMFXssWZoHsmtrny/8iI9Sshrx7UTGg==} + hasBin: true + dependencies: + '@types/node': 12.20.55 + colors-console: 1.0.3 + commander: 2.20.3 + inquirer: 6.5.2 + js-beautify: 1.14.11 + mkdirp: 0.5.6 + mysql: 2.18.1 + reflect-metadata: 0.1.14 + swig-templates: 2.0.3 + ts-node: 8.10.2(typescript@3.9.10) + typeorm: 0.2.45(mysql2@3.7.1) + typescript: 3.9.10 + warning: 4.0.3 + transitivePeerDependencies: + - '@sap/hana-client' + - better-sqlite3 + - hdb-pool + - ioredis + - mongodb + - mssql + - mysql2 + - oracledb + - pg + - pg-native + - pg-query-stream + - redis + - sql.js + - sqlite3 + - supports-color + - typeorm-aurora-data-api-driver + dev: false + + /typeorm@0.2.45(mysql2@3.7.1): + resolution: {integrity: sha512-c0rCO8VMJ3ER7JQ73xfk0zDnVv0WDjpsP6Q1m6CVKul7DB9iVdWLRjPzc8v2eaeBuomsbZ2+gTaYr8k1gm3bYA==} + hasBin: true + peerDependencies: + '@sap/hana-client': ^2.11.14 + better-sqlite3: ^7.1.2 + hdb-pool: ^0.1.6 + ioredis: ^4.28.3 + mongodb: ^3.6.0 + mssql: ^6.3.1 + mysql2: ^2.2.5 + oracledb: ^5.1.0 + pg: ^8.5.1 + pg-native: ^3.0.0 + pg-query-stream: ^4.0.0 + redis: ^3.1.1 + sql.js: ^1.4.0 + sqlite3: ^5.0.2 + typeorm-aurora-data-api-driver: ^2.0.0 + peerDependenciesMeta: + '@sap/hana-client': + optional: true + better-sqlite3: + optional: true + hdb-pool: + optional: true + ioredis: + optional: true + mongodb: + optional: true + mssql: + optional: true + mysql2: + optional: true + oracledb: + optional: true + pg: + optional: true + pg-native: + optional: true + pg-query-stream: + optional: true + redis: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + typeorm-aurora-data-api-driver: + optional: true + dependencies: + '@sqltools/formatter': 1.2.5 + app-root-path: 3.1.0 + buffer: 6.0.3 + chalk: 4.1.2 + cli-highlight: 2.1.11 + debug: 4.3.4(supports-color@5.5.0) + dotenv: 8.6.0 + glob: 7.2.3 + js-yaml: 4.1.0 + mkdirp: 1.0.4 + mysql2: 3.7.1 + reflect-metadata: 0.1.14 + sha.js: 2.4.11 + tslib: 2.6.2 + uuid: 8.3.2 + xml2js: 0.4.23 + yargs: 17.7.2 + zen-observable-ts: 1.1.0 + transitivePeerDependencies: + - supports-color + dev: false + + /typeorm@0.3.19(mysql2@3.7.1)(ts-node@10.9.2): + resolution: {integrity: sha512-OGelrY5qEoAU80mR1iyvmUHiKCPUydL6xp6bebXzS7jyv/X70Gp/jBWRAfF4qGOfy2A7orMiGRfwsBUNbEL65g==} + engines: {node: '>= 12.9.0'} + hasBin: true + peerDependencies: + '@google-cloud/spanner': ^5.18.0 + '@sap/hana-client': ^2.12.25 + better-sqlite3: ^7.1.2 || ^8.0.0 || ^9.0.0 + hdb-pool: ^0.1.6 + ioredis: ^5.0.4 + mongodb: ^5.8.0 + mssql: ^9.1.1 || ^10.0.1 + mysql2: ^2.2.5 || ^3.0.1 + oracledb: ^6.3.0 + pg: ^8.5.1 + pg-native: ^3.0.0 + pg-query-stream: ^4.0.0 + redis: ^3.1.1 || ^4.0.0 + sql.js: ^1.4.0 + sqlite3: ^5.0.3 + ts-node: ^10.7.0 + typeorm-aurora-data-api-driver: ^2.0.0 + peerDependenciesMeta: + '@google-cloud/spanner': + optional: true + '@sap/hana-client': + optional: true + better-sqlite3: + optional: true + hdb-pool: + optional: true + ioredis: + optional: true + mongodb: + optional: true + mssql: + optional: true + mysql2: + optional: true + oracledb: + optional: true + pg: + optional: true + pg-native: + optional: true + pg-query-stream: + optional: true + redis: + optional: true + sql.js: + optional: true + sqlite3: + optional: true + ts-node: + optional: true + typeorm-aurora-data-api-driver: + optional: true + dependencies: + '@sqltools/formatter': 1.2.5 + app-root-path: 3.1.0 + buffer: 6.0.3 + chalk: 4.1.2 + cli-highlight: 2.1.11 + dayjs: 1.11.10 + debug: 4.3.4(supports-color@5.5.0) + dotenv: 16.3.1 + glob: 10.3.10 + mkdirp: 2.1.6 + mysql2: 3.7.1 + reflect-metadata: 0.1.14 + sha.js: 2.4.11 + ts-node: 10.9.2(@types/node@20.11.5)(typescript@5.3.3) + tslib: 2.6.2 + uuid: 9.0.1 + yargs: 17.7.2 + transitivePeerDependencies: + - supports-color + dev: false + + /typescript@3.9.10: + resolution: {integrity: sha512-w6fIxVE/H1PkLKcCPsFqKE7Kv7QUwhU8qQY2MueZXWx5cPZdwFupLgKK3vntcK98BtNHZtAF4LA/yl2a7k8R6Q==} + engines: {node: '>=4.2.0'} + hasBin: true + dev: false + + /typescript@5.3.3: + resolution: {integrity: sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw==} + engines: {node: '>=14.17'} + hasBin: true + + /uglify-js@2.6.0: + resolution: {integrity: sha512-SYZzhZQRrlAc6QT3Eqz4WHuyrCLjvvKmfII/of82rVACMxsIwb/CqlZVbUwOIq8Xd1EMp2WTtCrIxFYF+779zw==} + engines: {node: '>=0.8.0'} + hasBin: true + dependencies: + async: 0.2.10 + source-map: 0.5.7 + uglify-to-browserify: 1.0.2 + yargs: 3.10.0 + dev: false + + /uglify-js@3.17.4: + resolution: {integrity: sha512-T9q82TJI9e/C1TAxYvfb16xO120tMVFZrGA3f9/P4424DNu6ypK103y0GPFVa17yotwSyZW5iYXgjYHkGrJW/g==} + engines: {node: '>=0.8.0'} + hasBin: true + requiresBuild: true + dev: false + optional: true + + /uglify-to-browserify@1.0.2: + resolution: {integrity: sha512-vb2s1lYx2xBtUgy+ta+b2J/GLVUR+wmpINwHePmPRhOsIVCG2wDzKJ0n14GslH1BifsqVzSOwQhRaCAsZ/nI4Q==} + dev: false + + /unbox-primitive@1.0.2: + resolution: {integrity: sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==} + dependencies: + call-bind: 1.0.5 + has-bigints: 1.0.2 + has-symbols: 1.0.3 + which-boxed-primitive: 1.0.2 + dev: false + + /undefsafe@2.0.5: + resolution: {integrity: sha512-WxONCrssBM8TSPRqN5EmsjVrsv4A8X12J4ArBiiayv3DyyG3ZlIg6yysuuSYdZsVz3TKcTg2fd//Ujd4CHV1iA==} + dev: true + + /undici-types@5.26.5: + resolution: {integrity: sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==} + + /universalify@2.0.1: + resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==} + engines: {node: '>= 10.0.0'} + dev: false + + /unpipe@1.0.0: + resolution: {integrity: sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==} + engines: {node: '>= 0.8'} + dev: false + + /util-deprecate@1.0.2: + resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + dev: false + + /utils-merge@1.0.1: + resolution: {integrity: sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==} + engines: {node: '>= 0.4.0'} + dev: false + + /uuid@8.3.2: + resolution: {integrity: sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==} + hasBin: true + dev: false + + /uuid@9.0.1: + resolution: {integrity: sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==} + hasBin: true + dev: false + + /v8-compile-cache-lib@3.0.1: + resolution: {integrity: sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==} + + /validator@13.11.0: + resolution: {integrity: sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==} + engines: {node: '>= 0.10'} + dev: false + + /vary@1.1.2: + resolution: {integrity: sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==} + engines: {node: '>= 0.8'} + dev: false + + /warning@4.0.3: + resolution: {integrity: sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==} + dependencies: + loose-envify: 1.4.0 + dev: false + + /which-boxed-primitive@1.0.2: + resolution: {integrity: sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==} + dependencies: + is-bigint: 1.0.4 + is-boolean-object: 1.1.2 + is-number-object: 1.0.7 + is-string: 1.0.7 + is-symbol: 1.0.4 + dev: false + + /which-typed-array@1.1.13: + resolution: {integrity: sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow==} + engines: {node: '>= 0.4'} + dependencies: + available-typed-arrays: 1.0.5 + call-bind: 1.0.5 + for-each: 0.3.3 + gopd: 1.0.1 + has-tostringtag: 1.0.0 + dev: false + + /which@2.0.2: + resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} + engines: {node: '>= 8'} + hasBin: true + dependencies: + isexe: 2.0.0 + dev: false + + /window-size@0.1.0: + resolution: {integrity: sha512-1pTPQDKTdd61ozlKGNCjhNRd+KPmgLSGa3mZTHoOliaGcESD8G1PXhh7c1fgiPjVbNVfgy2Faw4BI8/m0cC8Mg==} + engines: {node: '>= 0.8.0'} + dev: false + + /wordwrap@0.0.2: + resolution: {integrity: sha512-xSBsCeh+g+dinoBv3GAOWM4LcVVO68wLXRanibtBSdUvkGWQRGeE9P7IwU9EmDDi4jA6L44lz15CGMwdw9N5+Q==} + engines: {node: '>=0.4.0'} + dev: false + + /wordwrap@0.0.3: + resolution: {integrity: sha512-1tMA907+V4QmxV7dbRvb4/8MaRALK6q9Abid3ndMYnbyo8piisCmeONVqVSXqQA3KaP4SLt5b7ud6E2sqP8TFw==} + engines: {node: '>=0.4.0'} + dev: false + + /wordwrap@1.0.0: + resolution: {integrity: sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==} + dev: false + + /wrap-ansi@7.0.0: + resolution: {integrity: sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==} + engines: {node: '>=10'} + dependencies: + ansi-styles: 4.3.0 + string-width: 4.2.3 + strip-ansi: 6.0.1 + dev: false + + /wrap-ansi@8.1.0: + resolution: {integrity: sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==} + engines: {node: '>=12'} + dependencies: + ansi-styles: 6.2.1 + string-width: 5.1.2 + strip-ansi: 7.1.0 + dev: false + + /wrappy@1.0.2: + resolution: {integrity: sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==} + dev: false + + /xml2js@0.4.23: + resolution: {integrity: sha512-ySPiMjM0+pLDftHgXY4By0uswI3SPKLDw/i3UXbnO8M/p28zqexCUoPmQFrYD+/1BzhGJSs2i1ERWKJAtiLrug==} + engines: {node: '>=4.0.0'} + dependencies: + sax: 1.3.0 + xmlbuilder: 11.0.1 + dev: false + + /xmlbuilder@11.0.1: + resolution: {integrity: sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==} + engines: {node: '>=4.0'} + dev: false + + /y18n@5.0.8: + resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==} + engines: {node: '>=10'} + dev: false + + /yallist@4.0.0: + resolution: {integrity: sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==} + + /yamljs@0.3.0: + resolution: {integrity: sha512-C/FsVVhht4iPQYXOInoxUM/1ELSf9EsgKH34FofQOp6hwCPrW4vG4w5++TED3xRUo8gD7l0P1J1dLlDYzODsTQ==} + hasBin: true + dependencies: + argparse: 1.0.10 + glob: 7.2.3 + dev: false + + /yargs-parser@20.2.9: + resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==} + engines: {node: '>=10'} + dev: false + + /yargs-parser@21.1.1: + resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==} + engines: {node: '>=12'} + dev: false + + /yargs@16.2.0: + resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==} + engines: {node: '>=10'} + dependencies: + cliui: 7.0.4 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 20.2.9 + dev: false + + /yargs@17.7.2: + resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==} + engines: {node: '>=12'} + dependencies: + cliui: 8.0.1 + escalade: 3.1.1 + get-caller-file: 2.0.5 + require-directory: 2.1.1 + string-width: 4.2.3 + y18n: 5.0.8 + yargs-parser: 21.1.1 + dev: false + + /yargs@3.10.0: + resolution: {integrity: sha512-QFzUah88GAGy9lyDKGBqZdkYApt63rCXYBGYnEP4xDJPXNqXXnBDACnbrXnViV6jRSqAePwrATi2i8mfYm4L1A==} + dependencies: + camelcase: 1.2.1 + cliui: 2.1.0 + decamelize: 1.2.0 + window-size: 0.1.0 + dev: false + + /yn@3.1.1: + resolution: {integrity: sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==} + engines: {node: '>=6'} + + /zen-observable-ts@1.1.0: + resolution: {integrity: sha512-1h4zlLSqI2cRLPJUHJFL8bCWHhkpuXkF+dbGkRaWjgDIG26DmzyshUMrdV/rL3UnR+mhaX4fRq8LPouq0MYYIA==} + dependencies: + '@types/zen-observable': 0.8.3 + zen-observable: 0.8.15 + dev: false + + /zen-observable@0.8.15: + resolution: {integrity: sha512-PQ2PC7R9rslx84ndNBZB/Dkv8V8fZEpk83RLgXtYd0fwUgEjseMn1Dgajh2x6S8QbZAFa9p2qVCEuYZNgve0dQ==} + dev: false diff --git a/src/app.ts b/src/app.ts new file mode 100644 index 0000000..2580fda --- /dev/null +++ b/src/app.ts @@ -0,0 +1,45 @@ +import "dotenv/config"; +import "reflect-metadata"; +import cors from "cors"; +import express from "express"; +import swaggerUi from "swagger-ui-express"; +import swaggerDocument from "./swagger.json"; +import * as cron from "node-cron"; +import error from "./middlewares/error"; +import { AppDataSource } from "./database/data-source"; +import { RegisterRoutes } from "./routes"; +import logMiddleware from "./middlewares/logs"; + +async function main() { + await AppDataSource.initialize(); + + const app = express(); + + app.use( + cors({ + origin: "*", + }), + ); + app.use(express.json()); + app.use(express.urlencoded({ extended: true })); + app.use(logMiddleware); + app.use("/", express.static("static")); + app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument)); + + RegisterRoutes(app); + + app.use(error); + const APP_HOST = process.env.APP_HOST || "0.0.0.0"; + const APP_PORT = +(process.env.APP_PORT || 3000); + + app.listen( + APP_PORT, + APP_HOST, + () => ( + console.log(`[APP] Application is running on: http://localhost:${APP_PORT}`), + console.log(`[APP] Swagger on: http://localhost:${APP_PORT}/api-docs`) + ), + ); +} + +main(); diff --git a/src/controllers/DirectorController.ts b/src/controllers/DirectorController.ts new file mode 100644 index 0000000..1446b00 --- /dev/null +++ b/src/controllers/DirectorController.ts @@ -0,0 +1,271 @@ +import { AppDataSource } from "../database/data-source"; +import { CreateDirector, Director } from "../entities/Director"; +import { + Body, + Delete, + Get, + Path, + Post, + Put, + Response, + Route, + SuccessResponse, + Tags, + Query, + Request, + Security, +} from "tsoa"; +import HttpStatusCode from "../interfaces/http-status"; +import HttpSuccess from "../interfaces/http-success"; +import HttpError from "../interfaces/http-error"; +import { Not, Brackets } from "typeorm"; +import permission from "../interfaces/permission"; +import { RequestWithUser } from "../middlewares/user"; +import { setLogDataDiff } from "../interfaces/utils"; +@Route("api/v1/evaluation/director") +@Tags("director") +@Security("bearerAuth") +@Response( + HttpStatusCode.INTERNAL_SERVER_ERROR, + "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", +) +@SuccessResponse(HttpStatusCode.OK, "สำเร็จ") +export class DirectorController { + private directorRepository = AppDataSource.getRepository(Director); + + /** + * API สำหรับแสดงรายการกรรมการ + * + * @summary EV4_001 - รายการกรรมการ (ADMIN) + * + */ + @Get() + async all( + @Request() request: RequestWithUser, + @Query("page") page: number = 1, + @Query("pageSize") pageSize: number = 10, + @Query("keyword") keyword?: string, + ) { + await new permission().PermissionList(request, "SYS_EVA_INFO"); + // const directors = await this.directorRepository.find({ + // skip: (page - 1) * pageSize, + // take: pageSize, + // }); + // if (keyword != undefined && keyword !== "") { + // return directors.filter( + // (x) => + // x.prefix?.includes(keyword) || + // x.firstName?.includes(keyword) || + // x.lastName?.includes(keyword) || + // x.position?.includes(keyword) || + // x.email?.includes(keyword) || + // x.phone?.includes(keyword), + // ); + // } + const directors = await AppDataSource.getRepository(Director) + .createQueryBuilder("director") + .andWhere( + new Brackets((qb) => { + qb.where( + keyword != null && keyword != "" + ? "CONCAT(director.prefix, director.firstName, ' ', director.lastName) LIKE :keyword" + : "1=1", + { + keyword: `%${keyword}%`, + }, + ) + .orWhere( + keyword != null && keyword != "" + ? "director.position LIKE :keyword" + : "1=1", + { + keyword: `%${keyword}%`, + }, + ) + .orWhere( + keyword != null && keyword != "" + ? "director.email LIKE :keyword" + : "1=1", + { + keyword: `%${keyword}%`, + }, + ) + .orWhere( + keyword != null && keyword != "" + ? "director.phone LIKE :keyword" + : "1=1", + { + keyword: `%${keyword}%`, + }, + ); + }), + ) + .orderBy("director.createdAt", "DESC") + .skip((page - 1) * pageSize) + .take(pageSize) + .getMany(); + + return new HttpSuccess(directors); + } + + @Get("admin") + async allAdmin( + @Request() request: RequestWithUser, + @Query("page") page: number = 1, + @Query("pageSize") pageSize: number = 10, + @Query("keyword") keyword?: string, + ) { + // const directors = await this.directorRepository.find({ + // skip: (page - 1) * pageSize, + // take: pageSize, + // }); + // if (keyword != undefined && keyword !== "") { + // return directors.filter( + // (x) => + // x.prefix?.includes(keyword) || + // x.firstName?.includes(keyword) || + // x.lastName?.includes(keyword) || + // x.position?.includes(keyword) || + // x.email?.includes(keyword) || + // x.phone?.includes(keyword), + // ); + // } + const directors = await AppDataSource.getRepository(Director) + .createQueryBuilder("director") + .andWhere( + new Brackets((qb) => { + qb.where( + keyword != null && keyword != "" + ? "CONCAT(director.prefix, director.firstName, ' ', director.lastName) LIKE :keyword" + : "1=1", + { + keyword: `%${keyword}%`, + }, + ) + .orWhere( + keyword != null && keyword != "" + ? "director.position LIKE :keyword" + : "1=1", + { + keyword: `%${keyword}%`, + }, + ) + .orWhere( + keyword != null && keyword != "" + ? "director.email LIKE :keyword" + : "1=1", + { + keyword: `%${keyword}%`, + }, + ) + .orWhere( + keyword != null && keyword != "" + ? "director.phone LIKE :keyword" + : "1=1", + { + keyword: `%${keyword}%`, + }, + ); + }), + ) + .orderBy("director.createdAt", "DESC") + .skip((page - 1) * pageSize) + .take(pageSize) + .getMany(); + return new HttpSuccess(directors); + } + + /** + * API สำหรับแสดงรายละเอียดกรรมการ + * + * @summary EV4_002 - รายละเอียดกรรมการ (ADMIN) + * + */ + @Get("{id}") + async one(@Path() id: string, @Request() request: RequestWithUser) { + let _workflow = await new permission().Workflow(request, id, "SYS_EVA_INFO"); + if (_workflow == false) await new permission().PermissionGet(request, "SYS_EVA_INFO"); + const director = await this.directorRepository.findOne({ where: { id } }); + if (!director) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + return new HttpSuccess(director); + } + + /** + * API สำหรับเพิ่มรายละเอียดกรรมการ + * + * @summary EV4_003 - เพิ่มรายละเอียดกรรมการ (ADMIN) + * + */ + @Post() + async save(@Body() requestBody: CreateDirector, @Request() request: RequestWithUser) { + await new permission().PermissionCreate(request, "SYS_EVA_INFO"); + let directorDup = await this.directorRepository.findOne({ + where: { firstName: requestBody.firstName, lastName: requestBody.lastName }, + }); + if (directorDup != null) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ชื่อกรรมการนี้มีอยู่ในระบบแล้ว"); + } + const director = Object.assign(new Director(), requestBody); + director.createdUserId = request.user.sub; + director.createdFullName = request.user.name; + director.createdAt = new Date(); + director.lastUpdateUserId = request.user.sub; + director.lastUpdateFullName = request.user.name; + director.lastUpdatedAt = new Date(); + + const before = null; + + await this.directorRepository.save(director, { data: request }); + setLogDataDiff(request, { before, after: director }); + + return new HttpSuccess(); + } + + /** + * API สำหรับแก้ไขรายละเอียดกรรมการ + * + * @summary EV4_004 - แก้ไขรายละเอียดกรรมการ (ADMIN) + * + */ + @Put("{id}") + async update(@Path() id: string, @Body() u: CreateDirector, @Request() request: RequestWithUser) { + await new permission().PermissionUpdate(request, "SYS_EVA_INFO"); + let directorDup = await this.directorRepository.findOne({ + where: { firstName: u.firstName, lastName: u.lastName, id: Not(id) }, + }); + if (directorDup != null) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ชื่อกรรมการนี้มีอยู่ในระบบแล้ว"); + } + let director = await this.directorRepository.findOneBy({ id }); + if (!director) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + const before = structuredClone(directorDup); + director.lastUpdateUserId = request.user.sub; + director.lastUpdateFullName = request.user.name; + director.lastUpdatedAt = new Date(); + this.directorRepository.merge(director, u); + await this.directorRepository.save(director, { data: request }); + setLogDataDiff(request, { before, after: director }); + return new HttpSuccess(); + } + + /** + * API สำหรับลบรายละเอียดกรรมการ + * + * @summary EV4_005 - ลบรายละเอียดกรรมการ (ADMIN) + * + */ + @Delete("{id}") + async remove(id: string, @Request() request: RequestWithUser) { + await new permission().PermissionDelete(request, "SYS_EVA_INFO"); + let director = await this.directorRepository.findOneBy({ id }); + if (!director) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + await this.directorRepository.remove(director, { data: request }); + return new HttpSuccess(); + } +} diff --git a/src/controllers/DocumentController.ts b/src/controllers/DocumentController.ts new file mode 100644 index 0000000..53745eb --- /dev/null +++ b/src/controllers/DocumentController.ts @@ -0,0 +1,320 @@ +import { + Body, + Controller, + Delete, + Example, + Get, + Patch, + Path, + Post, + Route, + SuccessResponse, + Tags, +} from "tsoa"; +import HttpStatus from "../interfaces/http-status"; +import { + createFile, + createFolder, + deleteFile, + deleteFolder, + downloadFile, + listFile, + updateFile, +} from "../services/storage"; +import { AppDataSource } from "../database/data-source"; +import { Evaluation } from "../entities/Evaluation"; + +@Route("api/v1/evaluation/document") +@Tags("document") +export class DocumentController extends Controller { + /** + * @example volume "เล่ม 1" + * @example id "00000000-0000-0000-0000-000000000000" + * + * @summary ข้อมูลเอกสารทั้งชุด + */ + @Get("{volume}/{id}") + @SuccessResponse(200, "สำเร็จ") + @Example([ + { + pathname: "string", + path: "ระบบประเมิน/เล่ม 1/1-แบบพิจารณาคุณสมบัติบุคคล", + title: "1-แบบพิจารณาคุณสมบัติบุคคล.docx", + description: "", + author: "นายก", + metadata: { + tag: 1, + }, + keyword: [], + category: [], + fileType: "", + fileSize: 1024, + fileName: "1-แบบพิจารณาคุณสมบัติบุคคล.docx", + upload: true, + createdAt: "2021-07-20T12:33:13.018Z", + createdBy: "service-account-ext-api", + updatedAt: "2021-07-20T12:33:13.018Z", + updatedBy: "service-account-ext-api", + }, + ]) + public async getFile(@Path() volume: string, @Path() id: string) { + const list = await listFile(["ระบบประเมิน", volume, id]); + if (!list) throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์ ไม่สามารถสร้างแฟ้มได้"); + return list; + } + + /** + * ข้อควรระวัง: หากลิงก์ยาวเกินไปอาจทำให้ไม่สามารถอัปโหลดได้ + * + * @example volume "เล่ม 1" + * @example id "00000000-0000-0000-0000-000000000000" + * @example file "1-แบบพิจารณาคุณสมบัติบุคคล" + * + * @summary ข้อมูลเอกสารพร้อมลิงก์ดาวน์โหลด + */ + @Get("{volume}/{id}/{file}") + @SuccessResponse(200, "สำเร็จ") + @Example({ + pathname: "string", + path: "ระบบประเมิน/เล่ม 1/1-แบบพิจารณาคุณสมบัติบุคคล", + title: "1-แบบพิจารณาคุณสมบัติบุคคล.docx", + description: "", + author: "นายก", + keyword: [], + category: [], + metadata: { + tag: 1, + }, + fileName: "1-แบบพิจารณาคุณสมบัติบุคคล.docx", + fileType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document", + fileSize: 1024, + hidden: false, + upload: true, + createdAt: "2021-07-20T12:33:13.018Z", + createdBy: "service-account-ext-api", + updatedAt: "2021-07-20T12:33:13.018Z", + updatedBy: "service-account-ext-api", + downloadUrl: "https://.../...", // Presigned Download URL 7 Days Exp + }) + public async getFileDownload(@Path() id: string, @Path() volume: string, @Path() file: string) { + const data = await downloadFile(["ระบบประเมิน", volume, id], file); + if (!data) throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์ ไม่สามารถสร้างแฟ้มได้"); + return data; + } + + /** + * ข้อควรระวัง: หากลิงก์ภาษาไทยยาวเกินไปอาจทำให้ไม่สามารถอัปโหลดได้ (น่าจะเป็นปัญหาทางด้านเทคนิคของ DNS) + * + * เมื่ออัปโหลดไฟล์โดย PUT Method จำเป็นต้องแนบ Content-Type ที่ถูกต้องของไฟล์ไปด้วยเพื่อให้ระบบรู้จักไฟล์นั้นๆ + * โดย Content-Type จะเป็น mime-type เช่น docx เป็น application/vnd.openxmlformats-officedocument.wordprocessingml.document + * ทั้งนี้ Content-Type อาจจะต่างกันแม้นามสกุลจะเหมือนกันได้ + * + * โดยปกติเมื่อเลือกไฟล์แล้ว Browser จะเก็บประเภทของไฟล์ไว้ด้วย ซึ่งเป็น Object ของ File มี attribute ชื่อ type ซึ่งเก็บ mime-type ไว้ + * + * หากไม่มีการป้อนชื่อ title ระบบ EDM จะใช้ title เป็นชื่อเดียวกับ ชื่อไฟล์โดยอัตโนมัติ + * + * @example volume "เล่ม 1" + * @example id "00000000-0000-0000-0000-000000000000" + * + * @summary ร้องขอการอัปโหลดเอกสาร + */ + @Post("{volume}/{id}") + @Example([ + { + pathname: "string", + path: "ระบบประเมิน/เล่ม 1/1-แบบพิจารณาคุณสมบัติบุคคล", + title: "1-แบบพิจารณาคุณสมบัติบุคคล.docx", + description: "1-แบบพิจารณาคุณสมบัติบุคคล.docx", + author: "นายก", + keyword: [], + category: [], + metadata: { + tag: 1, + }, + fileName: "1-แบบพิจารณาคุณสมบัติบุคคล.docx", + fileSize: 0, + fileType: "", + hidden: false, + upload: false, + createdAt: "2021-07-20T12:33:13.018Z", + createdBy: "service-account-ext-api", + updatedAt: "2021-07-20T12:33:13.018Z", + updatedBy: "service-account-ext-api", + uploadUrl: "https://.../...", // Presigned Upload URL 7 Days Exp + }, + ]) + @SuccessResponse(200, "Success") + public async uploadFile( + @Path() volume: string, + @Path() id: string, + @Body() + body: { + /** + * @example [ + * { + * "fileName": "1-แบบพิจารณาคุณสมบัติบุคคล.docx", + * "title": "1-แบบพิจารณาคุณสมบัติบุคคล.docx" + * }, + * { + * "fileName": "2-แบบแสดงรายละเอียดการเสนอผลงาน.docx", + * "description": "2-แบบแสดงรายละเอียดการเสนอผลงาน.docx" + * }, + * { + * "fileName": "3-แบบตรวจสอบความถูกต้องครบถ้วนของข้อมูล.docx", + * "keyword": ["3-แบบตรวจสอบความถูกต้องครบถ้วนของข้อมูล.docx"] + * }, + * { + * "fileName": "4-แบบประเมินคุณลักษณะบุคคล.docx", + * "category": ["4-แบบประเมินคุณลักษณะบุคคล.docx"] + * }, + * { + * "fileName": "5-แบบสรุปข้อมูลของผู้ขอรับการคัดเลือก.docx", + * "author": "นายก" + * }, + * { + * "fileName": "6-ผลงานที่จะส่งประเมิน.docx", + * "metadata": { "tag1": "value1", "tag2": "value2" } + * } + * ] + */ + fileList: { + fileName: string; + title?: string; + description?: string; + keyword?: string[]; + category?: string[]; + author?: string; + metadata?: { + [key: string]: unknown; + }; + }[]; + /** + * @example false + */ + replace?: boolean; + }, + ) { + const path = ["ระบบประเมิน", volume]; + + if (!(await createFolder(path, id, true))) { + throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์ ไม่สามารถสร้างแฟ้มได้"); + } + + const list = await listFile(["ระบบประเมิน", volume, id]); + + if (!list || !Array.isArray(list)) { + throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์ ไม่สามารถสร้างแฟ้มได้"); + } + + let used: string[] = []; + + const evaluation = AppDataSource.getRepository(Evaluation); + + let author = await evaluation.findOne({ + where: { id }, + }); + + let fileList = !body.replace + ? body.fileList.map(({ fileName, ...props }) => { + const dotIndex = fileName.lastIndexOf("."); + const originalName = + dotIndex !== -1 && !fileName.startsWith(".") ? fileName.slice(0, dotIndex) : fileName; + const extension = + dotIndex !== -1 && !fileName.startsWith(".") ? fileName.slice(dotIndex) : ""; + + let i = 1; + while (list.findIndex((v) => v.fileName === fileName) !== -1 || used.includes(fileName)) { + fileName = `${originalName} (${i++})`; + if (dotIndex !== -1) fileName += extension; + } + if(author){ + props.author = `${author.prefix}${author.fullName}`; + }else{ + props.author = "ไม่พบข้อมูล"; + } + + used.push(fileName); + return { fileName: fileName, ...props }; + }) + : body.fileList; + + const map = fileList.map(async ({ fileName, ...props }) => [ + fileName, + await createFile([...path, id], fileName, props), + ]); + + const result = await Promise.all(map).catch((e) => + console.error(`Storage Service Error: ${e}`), + ); + + if (!result || result.some((v) => !v[1])) { + throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์ ไม่สามารถอัปโหลดไฟล์ได้"); + } + + return Object.fromEntries(result); + } + + /** + * @example volume "เล่ม 1" + * @example id "00000000-0000-0000-0000-000000000000" + * @example file "1-แบบพิจารณาคุณสมบัติบุคคล.docx" + * + * @summary แก้ไขข้อมูลไฟล์ของ id นั้นๆ + */ + @Patch("{volume}/{id}/{file}") + public async updateFile( + @Path() volume: string, + @Path() id: string, + @Path() file: string, + @Body() + body: { + title?: string; + description?: string; + keyword?: string[]; + category?: string[]; + author?: string; + metadata?: { [key: string]: unknown }; + }, + ) { + const props = body; + const result = await updateFile(["ระบบประเมิน", volume, id], file, props); + + if (!result) { + throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์ ไม่สามารถอัปโหลดไฟล์ได้"); + } + return this.setStatus(HttpStatus.NO_CONTENT); + } + + /** + * @example volume "เล่ม 1" + * @example id "00000000-0000-0000-0000-000000000000" + * + * @summary ลบไฟล์ทั้งหมดของ id นั้นๆ + */ + @Delete("{volume}/{id}") + public async deleteFolder(@Path() volume: string, @Path() id: string) { + const result = await deleteFolder(["ระบบประเมิน", volume], id); + + if (!result) { + throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์ ไม่สามารถอัปโหลดไฟล์ได้"); + } + return this.setStatus(HttpStatus.NO_CONTENT); + } + + /** + * @example volume "เล่ม 1" + * @example id "00000000-0000-0000-0000-000000000000" + * @example file "1-แบบพิจารณาคุณสมบัติบุคคล.docx" + * + * @summary ลบไฟล์ของ id นั้นๆ + */ + @Delete("{volume}/{id}/{file}") + public async deleteFile(@Path() volume: string, @Path() id: string, @Path() file: string) { + const result = await deleteFile(["ระบบประเมิน", volume, id], file); + + if (!result) { + throw new Error("เกิดข้อผิดพลาดกับระบบจัดการไฟล์ ไม่สามารถอัปโหลดไฟล์ได้"); + } + return this.setStatus(HttpStatus.NO_CONTENT); + } +} diff --git a/src/controllers/EvaluationController.ts b/src/controllers/EvaluationController.ts new file mode 100644 index 0000000..2857673 --- /dev/null +++ b/src/controllers/EvaluationController.ts @@ -0,0 +1,2520 @@ +import { AppDataSource } from "../database/data-source"; +import { + Body, + Example, + Get, + Path, + Post, + Put, + Request, + Response, + Route, + Security, + SuccessResponse, + Tags, + Delete, +} from "tsoa"; +import HttpStatusCode from "../interfaces/http-status"; +import { Evaluation, CreateEvaluation, CreateEvaluationExpertise } from "../entities/Evaluation"; +import HttpSuccess from "../interfaces/http-success"; +import { EvaluationLogs } from "../entities/EvaluationLogs"; +import HttpError from "../interfaces/http-error"; +import { Education } from "../entities/Education"; +import { Certificate } from "../entities/Certificate"; +import { Salary } from "../entities/Salary"; +import { Training } from "../entities/Training"; +import { Assessment } from "../entities/Assessment"; +import { Director } from "../entities/Director"; +import { Meeting } from "../entities/Meeting"; +import { ConvertToThaiStep, ConvertToThaiType } from "../services/storage"; +import { Brackets } from "typeorm"; +import CallAPI from "../interfaces/call-api"; +import permission from "../interfaces/permission"; +import { RequestWithUser } from "../middlewares/user"; +import { setLogDataDiff } from "../interfaces/utils"; + +@Route("api/v1/evaluation") +@Tags("evaluation") +@Security("bearerAuth") +@Response( + HttpStatusCode.INTERNAL_SERVER_ERROR, + "เกิดข้อผิดพลาด ไม่สามารถทำรายการได้ กรุณาลองใหม่ในภายหลัง", +) +@SuccessResponse(HttpStatusCode.OK, "สำเร็จ") +export class EvaluationController { + private evaluationRepository = AppDataSource.getRepository(Evaluation); + private evaluationLogsRepository = AppDataSource.getRepository(EvaluationLogs); + private educationRepository = AppDataSource.getRepository(Education); + private certificateRepository = AppDataSource.getRepository(Certificate); + private salaryRepository = AppDataSource.getRepository(Salary); + private trainingRepository = AppDataSource.getRepository(Training); + private assessmentRepository = AppDataSource.getRepository(Assessment); + private directorRepository = AppDataSource.getRepository(Director); + private meetingRepository = AppDataSource.getRepository(Meeting); + + /** + * ดึงข้อมูลรายการร้องขอการประเมิน + * + * @summary รายการร้องขอการประเมิน + * + */ + @Post() + @Example([ + { + keyword: "นัทธิชา ปุ่นอุดม", + page: "1", + pageSize: "25", + status: ["PREPARE_DOC_V2", "DONE"], + }, + ]) + async lists( + @Request() request: RequestWithUser, + @Body() + body: { + page: number; + pageSize: number; + keyword?: string; + status?: string[]; + }, + ) { + // await new permission().PermissionList(request, "SYS_EVA_REQ"); + let _data = await new permission().PermissionOrgList(request,"SYS_EVA_REQ"); + const [evaluation, total] = await AppDataSource.getRepository(Evaluation) + .createQueryBuilder("evaluation") + .andWhere( + _data.root != undefined && _data.root != null + ? _data.root[0] != null + ? `evaluation.rootId IN (:...root)` + : `evaluation.rootId is null` + : "1=1", + { + root: _data.root, + }, + ) + .andWhere( + _data.child1 != undefined && _data.child1 != null + ? _data.child1[0] != null + ? `evaluation.child1Id IN (:...child1)` + : `evaluation.child1Id is null` + : "1=1", + { + child1: _data.child1, + }, + ) + .andWhere( + _data.child2 != undefined && _data.child2 != null + ? _data.child2[0] != null + ? `evaluation.child2Id IN (:...child2)` + : `evaluation.child2Id is null` + : "1=1", + { + child2: _data.child2, + }, + ) + .andWhere( + _data.child3 != undefined && _data.child3 != null + ? _data.child3[0] != null + ? `evaluation.child3Id IN (:...child3)` + : `evaluation.child3Id is null` + : "1=1", + { + child3: _data.child3, + }, + ) + .andWhere( + _data.child4 != undefined && _data.child4 != null + ? _data.child4[0] != null + ? `evaluation.child4Id IN (:...child4)` + : `evaluation.child4Id is null` + : "1=1", + { + child4: _data.child4, + }, + ) + .andWhere( + new Brackets((qb) => { + qb.andWhere( + body.status == undefined || body.status == null || body.status.every((s) => s === "ALL") + ? "1=1" + : `evaluation.step In (:status)`, + { + status: body.status, + }, + ).andWhere( + new Brackets((qb) => { + qb.orWhere("evaluation.fullName LIKE :keyword", { keyword: `%${body.keyword}%` }) + .orWhere("evaluation.citizenId LIKE :keyword", { keyword: `%${body.keyword}%` }) + .orWhere("evaluation.position LIKE :keyword", { keyword: `%${body.keyword}%` }) + .orWhere("evaluation.posNo LIKE :keyword", { keyword: `%${body.keyword}%` }) + .orWhere("evaluation.oc LIKE :keyword", { keyword: `%${body.keyword}%` }); + }), + ); + }), + ) + .orderBy("evaluation.lastUpdatedAt", "DESC") + .skip((body.page - 1) * body.pageSize) + .take(body.pageSize) + .getManyAndCount(); + + return new HttpSuccess({ data: evaluation, total }); + } + + /** + * ดึงข้อมูลรายการร้องขอการประเมิน สำหรับ USER + * + * @summary รายการร้องขอการประเมิน (USER) + * + */ + @Put("user") + @Example([ + { + keyword: "ชำนาญการพิเศษ", + page: "1", + pageSize: "25", + status: ["PREPARE_DOC_V2", "DONE"], + }, + ]) + async user_lists( + @Request() request: RequestWithUser, + @Body() + body: { + page: number; + pageSize: number; + keyword?: string; + status?: string[]; + }, + ) { + const [evaluation, total] = await AppDataSource.getRepository(Evaluation) + .createQueryBuilder("evaluation") + .andWhere( + new Brackets((qb) => { + qb.andWhere( + body.status == undefined || body.status == null || body.status.every((s) => s === "ALL") + ? "1=1" + : `evaluation.step In (:status)`, + { + status: body.status, + }, + ).andWhere("evaluation.createdUserId = :createdUserId", { + createdUserId: request.user.sub, + }); + // .andWhere( + // new Brackets((qb) => { + // qb.orWhere("evaluation.positionLevel LIKE :keyword", { + // keyword: `%${body.keyword}%`, + // }); + // }), + // ); + }), + ) + .orderBy("evaluation.lastUpdatedAt", "DESC") + .skip((body.page - 1) * body.pageSize) + .take(body.pageSize) + .getManyAndCount(); + + const _evaluation = evaluation.map((item) => ({ + id: item.id, + citizenId: item.citizenId, + fullName: item.fullName, + position: item.position, + oc: item.oc, + posNo: item.posNo, + type: item.type, + type_th: ConvertToThaiType(item.type), + step: item.step, + step_th: ConvertToThaiStep(item.step), + createdAt: item.createdAt, + updatedAt: item.lastUpdatedAt, + })); + + return new HttpSuccess({ data: _evaluation, total }); + } + + /** + * ดึงข้อมูลสถานะสิทธิร้องขอการประเมิน + * + * @summary EV1_001 - เช็คการยื่นขอประเมิน (USER) + * + */ + @Get("check-status") + @Example([ + { + isExpert: "true", + expertId: "00000000-0000-0000-0000-000000000000", + isSpecialExpert: "false", + specialExpertId: "00000000-0000-0000-0000-000000000000", + }, + ]) + async checkStatus(@Request() request: { user: { sub: string; name: string } }) { + const userId = request.user.sub; //UserId + const fullName = request.user.name; //FullName + + const status = await this.evaluationRepository.find({ + where: { + userId: userId, + }, + select: { + type: true, + id: true, + }, + }); + const isExpert = status.some((item) => item.type === "EXPERT"); + const isSpecialExpert = status.some((item) => item.type === "SPECIAL_EXPERT"); + const isExpertise = status.some((item) => item.type === "EXPERTISE"); + const expertId = status.find((item) => item.type === "EXPERT")?.id || null; + const specialExpertId = status.find((item) => item.type === "SPECIAL_EXPERT")?.id || null; + const expertiseId = status.find((item) => item.type === "EXPERTISE")?.id || null; + + const responseData = { + isExpert, + isSpecialExpert, + isExpertise, + expertId, + specialExpertId, + expertiseId, + }; + return new HttpSuccess(responseData); + } + + /** + * ดึงข้อมูลรายละเอียด step การขอประเมิน + * + * @summary EV1_002 - รายละเอียด step การขอประเมิน (USER) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Get("check/{id}") + @Example([ + { + step: "string", + }, + ]) + async check(@Request() request: RequestWithUser, @Path() id: string) { + const evaluation = await this.evaluationRepository.findOne({ + where: { id }, + select: ["step"], + }); + + if (!evaluation) { + return "ไม่พบข้อมูล"; + } + return new HttpSuccess(evaluation); + } + + /** + * เลือกรายละเอียดตรวจสอบคุณสมบัติ + * + * @summary EV1_004 - บันทึกตรวจสอบคุณสมบัติ (USER) + * + */ + @Post("check-spec") + @Example([ + { + isEducationalQft: "false", + isGovermantServiceHtr: "false", + isOperatingExp: "false", + isMinPeriodOfTenure: "false", + isHaveSpecificQft: "false", + isHaveProLicense: "false", + isHaveMinPeriodOrHoldPos: "false", + type: "EXPERT", + prefix: null, + fullname: null, + position: null, + posNo: null, + oc: null, + salary: null, + positionLevel: null, + birthDate: null, + govAge: null, + experience: null, + educations: [ + { + educationLevel: "ต่ำกว่าปริญญาตรี", + institute: "มจธ", + isDate: true, + startDate: "2023-12-14T00:00:00", + endDate: "2023-12-14T00:00:00", + finishDate: "2023-12-14T00:00:00", + isEducation: false, + degree: "-", + field: "-", + fundName: "-", + gpa: "-", + country: "-", + other: "-", + duration: "-", + durationYear: 4, + }, + ], + certificates: [ + { + certificateType: "-", + issuer: "-", + certificateNo: "-", + issueDate: "2023-12-14T00:00:00", + expireDate: "2023-12-14T00:00:00", + }, + ], + salaries: [ + { + date: "2023-10-11T16:15:00.185384", + Amount: 30220, + positionSalaryAmount: null, + mouthSalaryAmount: null, + position: "นักทรัพยากรบุคคล", + posNo: "สกจ.5", + salaryClass: null, + salaryRef: null, + refCommandNo: null, + refCommandDate: null, + salaryStatus: null, + }, + ], + trainings: [ + { + name: "-", + topic: "-", + startDate: "2023-12-14T00:00:00", + endDate: "2023-12-14T00:00:00", + yearly: 2023, + place: "-", + duration: "-", + department: "-", + numberOrder: "-", + dateOrder: "2023-12-14T02:54:30.448", + }, + ], + assessments: [ + { + date: "2023-12-14T00:00:00", + point1Total: 60, + point1: 46, + point2Total: 40, + point2: 34, + pointSumTotal: 100, + pointSum: 80, + }, + ], + }, + ]) + async save(@Body() requestBody: CreateEvaluation, @Request() request: RequestWithUser) { + // await new permission().PermissionCreate(request, "SYS_EVA_REQ"); + try { + const evaluation = Object.assign(new Evaluation(), requestBody); + if (!evaluation) { + return `not found data`; + } + + const before = null; + + //Evaluation + evaluation.step = "PREPARE_DOC_V1"; + evaluation.type = requestBody.type == "EXPERT" ? "EXPERT" : "SPECIAL_EXPERT"; + evaluation.fullName = requestBody.fullName; + evaluation.createdFullName = request.user.name; + evaluation.createdUserId = request.user.sub; + evaluation.createdAt = new Date(); + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + evaluation.userId = request.user.sub; + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + const _null: any = null; + //Education + if (requestBody.educations != null) + requestBody.educations.forEach(async (edu) => { + const education = new Education(); + education.createdUserId = request.user.sub; + education.createdFullName = request.user.name; + education.createdAt = new Date(); + education.lastUpdateUserId = request.user.sub; + education.lastUpdateFullName = request.user.name; + education.lastUpdatedAt = new Date(); + education.educationLevel = edu.educationLevel ?? _null; + education.institute = edu.institute ?? _null; + education.isDate = edu.isDate ?? _null; + education.startDate = edu.startDate ?? _null; + education.endDate = edu.endDate ?? _null; + education.finishDate = edu.finishDate ?? _null; + education.isEducation = edu.isEducation ?? _null; + education.degree = edu.degree ?? _null; + education.field = edu.field ?? _null; + education.fundName = edu.fundName ?? _null; + education.gpa = edu.gpa ?? _null; + education.country = edu.country ?? _null; + education.other = edu.other ?? _null; + education.duration = edu.duration ?? _null; + education.durationYear = edu.durationYear ?? _null; + education.evaluation = evaluation; + await this.educationRepository.save(education, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + }); + + //Certificate + if (requestBody.certificates != null) + requestBody.certificates.forEach(async (certi) => { + const certificate = new Certificate(); + certificate.createdUserId = request.user.sub; + certificate.createdFullName = request.user.name; + certificate.createdAt = new Date(); + certificate.lastUpdateUserId = request.user.sub; + certificate.lastUpdateFullName = request.user.name; + certificate.lastUpdatedAt = new Date(); + certificate.certificateType = certi.certificateType ?? _null; + certificate.issuer = certi.issuer ?? _null; + certificate.certificateNo = certi.certificateNo ?? _null; + certificate.issueDate = certi.issueDate ?? _null; + certificate.expireDate = certi.expireDate ?? _null; + certificate.evaluation = evaluation; + await this.certificateRepository.save(certificate, { data: request }); + setLogDataDiff(request, { before, after: certificate }); + }); + + //Salary + if (requestBody.salaries != null) + requestBody.salaries.forEach(async (salary) => { + const salaries = new Salary(); + salaries.createdUserId = request.user.sub; + salaries.createdFullName = request.user.name; + salaries.createdAt = new Date(); + salaries.lastUpdateUserId = request.user.sub; + salaries.lastUpdateFullName = request.user.name; + salaries.lastUpdatedAt = new Date(); + salaries.date = salary.date ?? _null; + salaries.amount = salary.amount ?? _null; + salaries.positionSalaryAmount = salary.positionSalaryAmount ?? _null; + salaries.mouthSalaryAmount = salary.mouthSalaryAmount ?? _null; + salaries.position = salary.position ?? _null; + salaries.posNo = salary.posNo ?? _null; + salaries.salaryClass = salary.salaryClass ?? _null; + salaries.salaryRef = salary.salaryRef ?? _null; + salaries.refCommandNo = salary.refCommandNo ?? _null; + salaries.refCommandDate = salary.refCommandDate ?? _null; + salaries.salaryStatus = salary.salaryStatus ?? _null; + salaries.evaluation = evaluation; + await this.salaryRepository.save(salaries, { data: request }); + setLogDataDiff(request, { before, after: salaries }); + }); + + //Training + if (requestBody.trainings != null) + requestBody.trainings.forEach(async (train) => { + const training = new Training(); + training.createdUserId = request.user.sub; + training.createdFullName = request.user.name; + training.createdAt = new Date(); + training.lastUpdateUserId = request.user.sub; + training.lastUpdateFullName = request.user.name; + training.lastUpdatedAt = new Date(); + training.name = train.name ?? _null; + training.topic = train.topic ?? _null; + training.startDate = train.startDate ?? _null; + training.endDate = train.endDate ?? _null; + training.yearly = train.yearly ?? _null; + training.place = train.place ?? _null; + training.duration = train.duration ?? _null; + training.department = train.department ?? _null; + training.numberOrder = train.numberOrder ?? _null; + training.dateOrder = train.dateOrder ?? _null; + training.evaluation = evaluation; + await this.trainingRepository.save(training, { data: request }); + setLogDataDiff(request, { before, after: training }); + }); + + //Assessment + if (requestBody.assessments != null) + requestBody.assessments.forEach(async (asmt) => { + const assessment = new Assessment(); + assessment.createdUserId = request.user.sub; + assessment.createdFullName = request.user.name; + assessment.createdAt = new Date(); + assessment.lastUpdateUserId = request.user.sub; + assessment.lastUpdateFullName = request.user.name; + assessment.lastUpdatedAt = new Date(); + assessment.date = asmt.date ?? _null; + assessment.point1Total = asmt.point1Total ?? _null; + assessment.point1 = asmt.point1 ?? _null; + assessment.point2Total = asmt.point2Total ?? _null; + assessment.point2 = asmt.point2 ?? _null; + assessment.pointSumTotal = asmt.pointSumTotal ?? _null; + assessment.pointSum = asmt.pointSum ?? _null; + assessment.evaluation = evaluation; + await this.assessmentRepository.save(assessment, { data: request }); + setLogDataDiff(request, { before, after: assessment }); + }); + + //EvaluationLogs + const evaluationLogs = new EvaluationLogs(); + evaluationLogs.step = (await ConvertToThaiStep("PREPARE_DOC_V1")) ?? _null; + evaluationLogs.createdUserId = request.user.sub; + evaluationLogs.createdFullName = request.user.name; + evaluationLogs.createdAt = new Date(); + evaluationLogs.lastUpdateUserId = request.user.sub; + evaluationLogs.lastUpdateFullName = request.user.name; + evaluationLogs.lastUpdatedAt = new Date(); + evaluationLogs.evaluation = evaluation; + await this.evaluationLogsRepository.save(evaluationLogs); + setLogDataDiff(request, { before, after: evaluationLogs }); + + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: `${requestBody.fullName} ทำการยื่นขอประเมิน`, + body: `${requestBody.fullName} ทำการยื่นขอประเมิน`, + receiverUserId: "59134ef9-9e62-41d0-aac5-339be727f2b0", + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess({ + id: evaluation.id, + }); + } catch (error: any) { + return error.status; + } + } + /** + * + * + */ + @Post("expertise") + async saveExpertise( + @Body() requestBody: CreateEvaluationExpertise, + @Request() request: RequestWithUser, + ) { + // await new permission().PermissionCreate(request, "SYS_EVA_REQ"); + try { + const evaluation = Object.assign(new Evaluation(), requestBody); + const before = null; + let org: any; + await new CallAPI() + .GetData(request, `/org/profile/keycloak/commander/${request.user.sub}`) + .then(async (x) => { + org = x.org; + evaluation.rootId = x.rootId; + evaluation.child1Id = x.child1Id; + evaluation.child2Id = x.child2Id; + evaluation.child3Id = x.child3Id; + evaluation.child4Id = x.child4Id; + }) + .catch(); + //Evaluation + evaluation.oc = org; + evaluation.step = "DONE"; + evaluation.type = "EXPERTISE"; + evaluation.userId = request.user.sub; + evaluation.createdFullName = request.user.name; + evaluation.createdUserId = request.user.sub; + evaluation.createdAt = new Date(); + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + evaluation.userId = request.user.sub; + + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + //EvaluationLogs + const evaluationLogs = new EvaluationLogs(); + const _null: any = null; + evaluationLogs.step = (await ConvertToThaiStep("DONE")) ?? _null; + evaluationLogs.createdUserId = request.user.sub; + evaluationLogs.createdFullName = request.user.name; + evaluationLogs.createdAt = new Date(); + evaluationLogs.lastUpdateUserId = request.user.sub; + evaluationLogs.lastUpdateFullName = request.user.name; + evaluationLogs.lastUpdatedAt = new Date(); + evaluationLogs.evaluation = evaluation; + await this.evaluationLogsRepository.save(evaluationLogs, { data: request }); + setLogDataDiff(request, { before: null, after: evaluationLogs }); + + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: `${request.user.name} ทำการยื่นขอประเมิน`, + body: `${request.user.name} ทำการยื่นขอประเมิน`, + receiverUserId: "59134ef9-9e62-41d0-aac5-339be727f2b0", + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess({ + id: evaluation.id, + }); + } catch (error: any) { + return error.status; + } + } + /** + * + * + */ + @Get("expertise/{id}") + async getExpertise(@Path() id: string) { + try { + const evaluation = await this.evaluationRepository.findOne({ + where: { id }, + select: [ + "id", + "author", + "subject", + "commanderFullname", + "commanderPosition", + "commanderAboveFullname", + "commanderAbovePosition", + ], + }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + return new HttpSuccess(evaluation); + } catch (error: any) { + return error.status; + } + } + + /** + * ดึงข้อมูลรายละเอียดตรวจสอบคุณสมบัติ + * + * @summary EV1_003 - รายละเอียดตรวจสอบคุณสมบัติ (USER) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Get("check-spec/{id}") + @Example([ + { + isEducationalQft: "false", + isGovermantServiceHtr: "false", + isOperatingExp: "false", + isMinPeriodOfTenure: "false", + isHaveSpecificQft: "false", + isHaveProLicense: "false", + isHaveMinPeriodOrHoldPos: "false", + type: "EXPERT", + prefix: null, + fullname: null, + position: null, + posNo: null, + oc: null, + salary: null, + positionLevel: null, + birthDate: null, + govAge: null, + experience: null, + educations: [ + { + educationLevel: "ต่ำกว่าปริญญาตรี", + institute: "มจธ", + isDate: true, + startDate: "2023-12-14T00:00:00", + endDate: "2023-12-14T00:00:00", + finishDate: "2023-12-14T00:00:00", + isEducation: false, + degree: "-", + field: "-", + fundName: "-", + gpa: "-", + country: "-", + other: "-", + duration: "-", + durationYear: 4, + }, + ], + certificates: [ + { + certificateType: "-", + issuer: "-", + certificateNo: "-", + issueDate: "2023-12-14T00:00:00", + expireDate: "2023-12-14T00:00:00", + }, + ], + salaries: [ + { + date: "2023-10-11T16:15:00.185384", + amount: 30220, + positionSalaryAmount: null, + mouthSalaryAmount: null, + position: "นักทรัพยากรบุคคล", + posNo: "สกจ.5", + salaryClass: null, + salaryRef: null, + refCommandNo: null, + refCommandDate: null, + salaryStatus: null, + }, + ], + trainings: [ + { + name: "-", + topic: "-", + startDate: "2023-12-14T00:00:00", + endDate: "2023-12-14T00:00:00", + yearly: 2023, + place: "-", + duration: "-", + department: "-", + numberOrder: "-", + dateOrder: "2023-12-14T02:54:30.448", + }, + ], + assessments: [ + { + date: "2023-12-14T00:00:00", + point1Total: 60, + point1: 46, + point2Total: 40, + point2: 34, + pointSumTotal: 100, + pointSum: 80, + }, + ], + }, + ]) + async checkSpecGet(@Request() request: RequestWithUser, @Path() id: string) { + const evaluation = await AppDataSource.getRepository(Evaluation) + .createQueryBuilder("evaluation") + .leftJoin("evaluation.education", "education") + .leftJoin("evaluation.certificate", "certificate") + .leftJoin("evaluation.salaries", "salaries") + .leftJoin("evaluation.training", "training") + .leftJoin("evaluation.assessment", "assessment") + .where("evaluation.id = :id", { id }) + .select([ + "evaluation.isEducationalQft", + "evaluation.isGovermantServiceHtr", + "evaluation.isOperatingExp", + "evaluation.isMinPeriodOfTenure", + "evaluation.isHaveSpecificQft", + "evaluation.isHaveProLicense", + "evaluation.isHaveMinPeriodOrHoldPos", + "evaluation.type", + "evaluation.prefix", + "evaluation.fullName", + "evaluation.position", + "evaluation.posNo", + "evaluation.oc", + "evaluation.salary", + "evaluation.positionLevel", + "evaluation.birthDate", + "evaluation.govAge", + "evaluation.experience", + + "education.educationLevel", + "education.institute", + "education.isDate", + "education.startDate", + "education.endDate", + "education.finishDate", + "education.isEducation", + "education.degree", + "education.field", + "education.fundName", + "education.gpa", + "education.country", + "education.other", + "education.duration", + "education.durationYear", + + "certificate.certificateType", + "certificate.issuer", + "certificate.certificateNo", + "certificate.issueDate", + "certificate.expireDate", + + "salaries.date", + "salaries.amount", + "salaries.positionSalaryAmount", + "salaries.mouthSalaryAmount", + "salaries.position", + "salaries.posNo", + "salaries.salaryClass", + "salaries.salaryRef", + "salaries.refCommandNo", + "salaries.refCommandDate", + "salaries.salaryStatus", + + "training.name", + "training.topic", + "training.startDate", + "training.endDate", + "training.yearly", + "training.place", + "training.duration", + "training.department", + "training.numberOrder", + "training.dateOrder", + + "assessment.date", + "assessment.point1Total", + "assessment.point1", + "assessment.point2Total", + "assessment.point2", + "assessment.pointSumTotal", + "assessment.pointSum", + ]) + .getOne(); + + if (!evaluation) { + return "ไม่พบข้อมูล"; + } + const dataEvaluation = { + isEducationalQft: evaluation.isEducationalQft, + isGovermantServiceHtr: evaluation.isGovermantServiceHtr, + isOperatingExp: evaluation.isOperatingExp, + isMinPeriodOfTenure: evaluation.isMinPeriodOfTenure, + isHaveSpecificQft: evaluation.isHaveSpecificQft, + isHaveProLicense: evaluation.isHaveProLicense, + isHaveMinPeriodOrHoldPos: evaluation.isHaveMinPeriodOrHoldPos, + type: evaluation.type, + prefix: evaluation.prefix, + fullName: evaluation.fullName, + position: evaluation.position, + posNo: evaluation.posNo, + oc: evaluation.oc, + salary: evaluation.salary, + positionLevel: evaluation.positionLevel, + birthDate: evaluation.birthDate, + govAge: evaluation.govAge, + experience: evaluation.experience, + educations: evaluation.education.map((education) => ({ + educationLevel: education.educationLevel, + institute: education.institute, + isDate: education.isDate, + startDate: education.startDate, + endDate: education.endDate, + finishDate: education.finishDate, + isEducation: education.isEducation, + degree: education.degree, + field: education.field, + fundName: education.fundName, + gpa: education.gpa, + country: education.country, + other: education.other, + duration: education.duration, + durationYear: education.durationYear, + })), + certificates: evaluation.certificate.map((certificate) => ({ + certificateType: certificate.certificateType, + issuer: certificate.issuer, + certificateNo: certificate.certificateNo, + issueDate: certificate.issueDate, + expireDate: certificate.expireDate, + })), + salaries: evaluation.salaries.map((salaries) => ({ + date: salaries.date, + amount: salaries.amount, + positionSalaryAmount: salaries.positionSalaryAmount, + mouthSalaryAmount: salaries.mouthSalaryAmount, + position: salaries.position, + posNo: salaries.posNo, + salaryClass: salaries.salaryClass, + salaryRef: salaries.salaryRef, + refCommandNo: salaries.refCommandNo, + refCommandDate: salaries.refCommandDate, + salaryStatus: salaries.salaryStatus, + })), + trainings: evaluation.training.map((training) => ({ + name: training.name, + topic: training.topic, + startDate: training.startDate, + endDate: training.endDate, + yearly: training.yearly, + place: training.place, + duration: training.duration, + department: training.department, + numberOrder: training.numberOrder, + dateOrder: training.dateOrder, + })), + assessments: evaluation.assessment.map((assessment) => ({ + date: assessment.date, + point1Total: assessment.point1Total, + point1: assessment.point1, + point2Total: assessment.point2Total, + point2: assessment.point2, + pointSumTotal: assessment.pointSumTotal, + pointSum: assessment.pointSum, + })), + }; + + if (!dataEvaluation) { + return "ไม่พบข้อมูล"; + } + return new HttpSuccess(dataEvaluation); + } + + /** + * ดึงข้อมูลรายละเอียดตรวจสอบคุณสมบัติ + * + * @summary EV1_003 - รายละเอียดตรวจสอบคุณสมบัติ (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Get("admin/check-spec/{id}") + @Example([ + { + isEducationalQft: "false", + isGovermantServiceHtr: "false", + isOperatingExp: "false", + isMinPeriodOfTenure: "false", + isHaveSpecificQft: "false", + isHaveProLicense: "false", + isHaveMinPeriodOrHoldPos: "false", + type: "EXPERT", + prefix: null, + fullname: null, + position: null, + posNo: null, + oc: null, + salary: null, + positionLevel: null, + birthDate: null, + govAge: null, + experience: null, + educations: [ + { + educationLevel: "ต่ำกว่าปริญญาตรี", + institute: "มจธ", + isDate: true, + startDate: "2023-12-14T00:00:00", + endDate: "2023-12-14T00:00:00", + finishDate: "2023-12-14T00:00:00", + isEducation: false, + degree: "-", + field: "-", + fundName: "-", + gpa: "-", + country: "-", + other: "-", + duration: "-", + durationYear: 4, + }, + ], + certificates: [ + { + certificateType: "-", + issuer: "-", + certificateNo: "-", + issueDate: "2023-12-14T00:00:00", + expireDate: "2023-12-14T00:00:00", + }, + ], + salaries: [ + { + date: "2023-10-11T16:15:00.185384", + amount: 30220, + positionSalaryAmount: null, + mouthSalaryAmount: null, + position: "นักทรัพยากรบุคคล", + posNo: "สกจ.5", + salaryClass: null, + salaryRef: null, + refCommandNo: null, + refCommandDate: null, + salaryStatus: null, + }, + ], + trainings: [ + { + name: "-", + topic: "-", + startDate: "2023-12-14T00:00:00", + endDate: "2023-12-14T00:00:00", + yearly: 2023, + place: "-", + duration: "-", + department: "-", + numberOrder: "-", + dateOrder: "2023-12-14T02:54:30.448", + }, + ], + assessments: [ + { + date: "2023-12-14T00:00:00", + point1Total: 60, + point1: 46, + point2Total: 40, + point2: 34, + pointSumTotal: 100, + pointSum: 80, + }, + ], + }, + ]) + async checkSpecGetByAdmin(@Request() request: RequestWithUser, @Path() id: string) { + let _workflow = await new permission().Workflow(request, id, "SYS_EVA_REQ"); + if (_workflow == false) await new permission().PermissionGet(request, "SYS_EVA_REQ"); + const evaluation = await AppDataSource.getRepository(Evaluation) + .createQueryBuilder("evaluation") + .leftJoin("evaluation.education", "education") + .leftJoin("evaluation.certificate", "certificate") + .leftJoin("evaluation.salaries", "salaries") + .leftJoin("evaluation.training", "training") + .leftJoin("evaluation.assessment", "assessment") + .where("evaluation.id = :id", { id }) + .select([ + "evaluation.isEducationalQft", + "evaluation.isGovermantServiceHtr", + "evaluation.isOperatingExp", + "evaluation.isMinPeriodOfTenure", + "evaluation.isHaveSpecificQft", + "evaluation.isHaveProLicense", + "evaluation.isHaveMinPeriodOrHoldPos", + "evaluation.type", + "evaluation.prefix", + "evaluation.fullName", + "evaluation.position", + "evaluation.posNo", + "evaluation.oc", + "evaluation.salary", + "evaluation.positionLevel", + "evaluation.birthDate", + "evaluation.govAge", + "evaluation.experience", + + "education.educationLevel", + "education.institute", + "education.isDate", + "education.startDate", + "education.endDate", + "education.finishDate", + "education.isEducation", + "education.degree", + "education.field", + "education.fundName", + "education.gpa", + "education.country", + "education.other", + "education.duration", + "education.durationYear", + + "certificate.certificateType", + "certificate.issuer", + "certificate.certificateNo", + "certificate.issueDate", + "certificate.expireDate", + + "salaries.date", + "salaries.amount", + "salaries.positionSalaryAmount", + "salaries.mouthSalaryAmount", + "salaries.position", + "salaries.posNo", + "salaries.salaryClass", + "salaries.salaryRef", + "salaries.refCommandNo", + "salaries.refCommandDate", + "salaries.salaryStatus", + + "training.name", + "training.topic", + "training.startDate", + "training.endDate", + "training.yearly", + "training.place", + "training.duration", + "training.department", + "training.numberOrder", + "training.dateOrder", + + "assessment.date", + "assessment.point1Total", + "assessment.point1", + "assessment.point2Total", + "assessment.point2", + "assessment.pointSumTotal", + "assessment.pointSum", + ]) + .getOne(); + + if (!evaluation) { + return "ไม่พบข้อมูล"; + } + const dataEvaluation = { + isEducationalQft: evaluation.isEducationalQft, + isGovermantServiceHtr: evaluation.isGovermantServiceHtr, + isOperatingExp: evaluation.isOperatingExp, + isMinPeriodOfTenure: evaluation.isMinPeriodOfTenure, + isHaveSpecificQft: evaluation.isHaveSpecificQft, + isHaveProLicense: evaluation.isHaveProLicense, + isHaveMinPeriodOrHoldPos: evaluation.isHaveMinPeriodOrHoldPos, + type: evaluation.type, + prefix: evaluation.prefix, + fullName: evaluation.fullName, + position: evaluation.position, + posNo: evaluation.posNo, + oc: evaluation.oc, + salary: evaluation.salary, + positionLevel: evaluation.positionLevel, + birthDate: evaluation.birthDate, + govAge: evaluation.govAge, + experience: evaluation.experience, + educations: evaluation.education.map((education) => ({ + educationLevel: education.educationLevel, + institute: education.institute, + isDate: education.isDate, + startDate: education.startDate, + endDate: education.endDate, + finishDate: education.finishDate, + isEducation: education.isEducation, + degree: education.degree, + field: education.field, + fundName: education.fundName, + gpa: education.gpa, + country: education.country, + other: education.other, + duration: education.duration, + durationYear: education.durationYear, + })), + certificates: evaluation.certificate.map((certificate) => ({ + certificateType: certificate.certificateType, + issuer: certificate.issuer, + certificateNo: certificate.certificateNo, + issueDate: certificate.issueDate, + expireDate: certificate.expireDate, + })), + salaries: evaluation.salaries.map((salaries) => ({ + date: salaries.date, + amount: salaries.amount, + positionSalaryAmount: salaries.positionSalaryAmount, + mouthSalaryAmount: salaries.mouthSalaryAmount, + position: salaries.position, + posNo: salaries.posNo, + salaryClass: salaries.salaryClass, + salaryRef: salaries.salaryRef, + refCommandNo: salaries.refCommandNo, + refCommandDate: salaries.refCommandDate, + salaryStatus: salaries.salaryStatus, + })), + trainings: evaluation.training.map((training) => ({ + name: training.name, + topic: training.topic, + startDate: training.startDate, + endDate: training.endDate, + yearly: training.yearly, + place: training.place, + duration: training.duration, + department: training.department, + numberOrder: training.numberOrder, + dateOrder: training.dateOrder, + })), + assessments: evaluation.assessment.map((assessment) => ({ + date: assessment.date, + point1Total: assessment.point1Total, + point1: assessment.point1, + point2Total: assessment.point2Total, + point2: assessment.point2, + pointSumTotal: assessment.pointSumTotal, + pointSum: assessment.pointSum, + })), + }; + + if (!dataEvaluation) { + return "ไม่พบข้อมูล"; + } + return new HttpSuccess(dataEvaluation); + } + /** + * API บันทึกจัดเตรียมเอกสาร + * + * @summary EV1_017 - บันทึกจัดเตรียมเอกสาร (USER) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("prepare-doc-v1/approve/{id}") + async EV1_017(@Path() id: string, @Request() request: RequestWithUser) { + // await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + if (evaluation.step != "CHECK_DOC_V1") { + const evaluationLogs = new EvaluationLogs(); + const _null: any = null; + evaluationLogs.step = (await ConvertToThaiStep("CHECK_DOC_V1")) ?? _null; + evaluationLogs.createdUserId = request.user.sub; + evaluationLogs.createdFullName = request.user.name; + evaluationLogs.createdAt = new Date(); + evaluationLogs.lastUpdateUserId = request.user.sub; + evaluationLogs.lastUpdateFullName = request.user.name; + evaluationLogs.lastUpdatedAt = new Date(); + evaluationLogs.evaluation = evaluation; + await this.evaluationLogsRepository.save(evaluationLogs, { data: request }); + setLogDataDiff(request, { before: null, after: evaluationLogs }); + } + const before = structuredClone(evaluation); + + evaluation.step = "CHECK_DOC_V1"; + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: `${evaluation.fullName} แบบประเมินมีการบันทึกจัดเตรียมเอกสารเล่ม 1`, + body: `${evaluation.fullName} แบบประเมินมีการบันทึกจัดเตรียมเอกสารเล่ม 1`, + receiverUserId: "59134ef9-9e62-41d0-aac5-339be727f2b0", + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API ย้อนกลับจัดเตรียมเอกสาร + * + * @summary EV1_018 - ย้อนกลับจัดเตรียมเอกสาร (USER) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("prepare-doc-v1/reject/{id}") + async EV1_018(@Path() id: string, @Request() request: RequestWithUser) { + // await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + if (evaluation.step != "CHECK_SPEC") { + const evaluationLogs = new EvaluationLogs(); + const _null: any = null; + evaluationLogs.step = (await ConvertToThaiStep("CHECK_SPEC")) ?? _null; + evaluationLogs.createdUserId = request.user.sub; + evaluationLogs.createdFullName = request.user.name; + evaluationLogs.createdAt = new Date(); + evaluationLogs.lastUpdateUserId = request.user.sub; + evaluationLogs.lastUpdateFullName = request.user.name; + evaluationLogs.lastUpdatedAt = new Date(); + evaluationLogs.evaluation = evaluation; + await this.evaluationLogsRepository.save(evaluationLogs, { data: request }); + setLogDataDiff(request, { before: null, after: evaluationLogs }); + } + const before = structuredClone(evaluation); + + evaluation.step = "CHECK_SPEC"; + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API บันทึกตรวจสอบจัดเตรียมเอกสาร + * + * @summary EV1_020 - บันทึกตรวจสอบจัดเตรียมเอกสาร (USER) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("check-doc-v1/approve/{id}") + async EV1_020(@Path() id: string, @Request() request: RequestWithUser) { + // await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + if (evaluation.step != "WAIT_CHECK_DOC_V1") { + const evaluationLogs = new EvaluationLogs(); + const _null: any = null; + evaluationLogs.step = (await ConvertToThaiStep("WAIT_CHECK_DOC_V1")) ?? _null; + evaluationLogs.createdUserId = request.user.sub; + evaluationLogs.createdFullName = request.user.name; + evaluationLogs.createdAt = new Date(); + evaluationLogs.lastUpdateUserId = request.user.sub; + evaluationLogs.lastUpdateFullName = request.user.name; + evaluationLogs.lastUpdatedAt = new Date(); + evaluationLogs.evaluation = evaluation; + await this.evaluationLogsRepository.save(evaluationLogs, { data: request }); + setLogDataDiff(request, { before: null, after: evaluationLogs }); + } + const before = structuredClone(evaluation); + + evaluation.step = "WAIT_CHECK_DOC_V1"; + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: `${evaluation.fullName} แบบประเมินมีการบันทึกตรวจสอบจัดเตรียมเอกสารเล่ม 1`, + body: `${evaluation.fullName} แบบประเมินมีการบันทึกตรวจสอบจัดเตรียมเอกสารเล่ม 1`, + receiverUserId: "59134ef9-9e62-41d0-aac5-339be727f2b0", + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API ย้อนกลับตรวจสอบจัดเตรียมเอกสาร + * + * @summary EV1_021 - ย้อนกลับตรวจสอบจัดเตรียมเอกสาร (USER) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("check-doc-v1/reject/{id}") + async EV1_021(@Path() id: string, @Request() request: RequestWithUser) { + // await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + if (evaluation.step != "PREPARE_DOC_V1") { + const evaluationLogs = new EvaluationLogs(); + const _null: any = null; + evaluationLogs.step = (await ConvertToThaiStep("PREPARE_DOC_V1")) ?? _null; + evaluationLogs.createdUserId = request.user.sub; + evaluationLogs.createdFullName = request.user.name; + evaluationLogs.createdAt = new Date(); + evaluationLogs.lastUpdateUserId = request.user.sub; + evaluationLogs.lastUpdateFullName = request.user.name; + evaluationLogs.lastUpdatedAt = new Date(); + evaluationLogs.evaluation = evaluation; + await this.evaluationLogsRepository.save(evaluationLogs, { data: request }); + setLogDataDiff(request, { before: null, after: evaluationLogs }); + } + const before = structuredClone(evaluation); + + evaluation.step = "PREPARE_DOC_V1"; + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API บันทึกตรวจสอบเอกสาร + * + * @summary EV1_023 - อนุมัติตรวจสอบเอกสาร (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("doc1/approve/{id}") + async EV1_023(@Path() id: string, @Request() request: RequestWithUser) { + await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + if (evaluation.step != "ANNOUNCE_WEB") { + const evaluationLogs = new EvaluationLogs(); + const _null: any = null; + evaluationLogs.step = (await ConvertToThaiStep("ANNOUNCE_WEB")) ?? _null; + evaluationLogs.createdUserId = request.user.sub; + evaluationLogs.createdFullName = request.user.name; + evaluationLogs.createdAt = new Date(); + evaluationLogs.lastUpdateUserId = request.user.sub; + evaluationLogs.lastUpdateFullName = request.user.name; + evaluationLogs.lastUpdatedAt = new Date(); + evaluationLogs.evaluation = evaluation; + await this.evaluationLogsRepository.save(evaluationLogs, { data: request }); + setLogDataDiff(request, { before: null, after: evaluationLogs }); + } + const before = structuredClone(evaluation); + + evaluation.step = "ANNOUNCE_WEB"; + evaluation.dateAnnounce = new Date(); + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: "แบบประเมินของคุณอนุมัติตรวจสอบเอกสารเล่ม 1", + body: "แบบประเมินของคุณอนุมัติตรวจสอบเอกสารเล่ม 1", + receiverUserId: evaluation.userId, + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API ไม่อนุมัติตรวจสอบเอกสาร + * + * @summary EV1_024 - ไม่อนุมัติตรวจสอบเอกสาร (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("doc1/reject/{id}") + async EV1_024( + @Path() id: string, + @Body() body: { reason: string }, + @Request() request: RequestWithUser, + ) { + await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + if (evaluation.step != "CHECK_DOC_V1") { + const evaluationLogs = new EvaluationLogs(); + const _null: any = null; + evaluationLogs.step = (await ConvertToThaiStep("CHECK_DOC_V1")) ?? _null; + evaluationLogs.createdUserId = request.user.sub; + evaluationLogs.createdFullName = request.user.name; + evaluationLogs.createdAt = new Date(); + evaluationLogs.lastUpdateUserId = request.user.sub; + evaluationLogs.lastUpdateFullName = request.user.name; + evaluationLogs.lastUpdatedAt = new Date(); + evaluationLogs.evaluation = evaluation; + await this.evaluationLogsRepository.save(evaluationLogs, { data: request }); + setLogDataDiff(request, { before: null, after: evaluationLogs }); + } + const before = structuredClone(evaluation); + + evaluation.step = "CHECK_DOC_V1"; + evaluation.reason = body.reason; + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: "แบบประเมินของคุณไม่อนุมัติตรวจสอบเอกสารเล่ม 1", + body: "แบบประเมินของคุณไม่อนุมัติตรวจสอบเอกสารเล่ม 1", + receiverUserId: evaluation.userId, + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API บันทึกตรวจสอบจัดเตรียมเอกสารเล่ม 2 + * + * @summary EV1_028 - บันทึกตรวจสอบจัดเตรียมเอกสารเล่ม 2 (USER) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("check-doc-v1/{id}") + async EV1_028(@Path() id: string, @Request() request: RequestWithUser) { + // await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + if (evaluation.step != "WAIT_CHECK_DOC_V2") { + const evaluationLogs = new EvaluationLogs(); + const _null: any = null; + evaluationLogs.step = (await ConvertToThaiStep("WAIT_CHECK_DOC_V2")) ?? _null; + evaluationLogs.createdUserId = request.user.sub; + evaluationLogs.createdFullName = request.user.name; + evaluationLogs.createdAt = new Date(); + evaluationLogs.lastUpdateUserId = request.user.sub; + evaluationLogs.lastUpdateFullName = request.user.name; + evaluationLogs.lastUpdatedAt = new Date(); + evaluationLogs.evaluation = evaluation; + await this.evaluationLogsRepository.save(evaluationLogs, { data: request }); + setLogDataDiff(request, { before: null, after: evaluationLogs }); + } + const before = structuredClone(evaluation); + + evaluation.step = "WAIT_CHECK_DOC_V2"; + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: `${evaluation.fullName} แบบประเมินมีการบันทึกตรวจสอบจัดเตรียมเอกสารเล่ม 2`, + body: `${evaluation.fullName} แบบประเมินมีการบันทึกตรวจสอบจัดเตรียมเอกสารเล่ม 2`, + receiverUserId: "59134ef9-9e62-41d0-aac5-339be727f2b0", + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API บันทึกจัดเตรียมเอกสารเล่ม 2 + * + * @summary EV1_029 - บันทึกจัดเตรียมเอกสารเล่ม 2 (USER) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("prepare-doc-v2/approve/{id}") + async EV1_029(@Path() id: string, @Request() request: RequestWithUser) { + // await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + if (evaluation.step != "CHECK_DOC_V2") { + const evaluationLogs = new EvaluationLogs(); + const _null: any = null; + evaluationLogs.step = (await ConvertToThaiStep("CHECK_DOC_V2")) ?? _null; + evaluationLogs.createdUserId = request.user.sub; + evaluationLogs.createdFullName = request.user.name; + evaluationLogs.createdAt = new Date(); + evaluationLogs.lastUpdateUserId = request.user.sub; + evaluationLogs.lastUpdateFullName = request.user.name; + evaluationLogs.lastUpdatedAt = new Date(); + evaluationLogs.evaluation = evaluation; + await this.evaluationLogsRepository.save(evaluationLogs, { data: request }); + setLogDataDiff(request, { before: null, after: evaluationLogs }); + } + const before = structuredClone(evaluation); + + evaluation.step = "CHECK_DOC_V2"; + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: `${evaluation.fullName} แบบประเมินมีการบันทึกจัดเตรียมเอกสารเล่ม 2`, + body: `${evaluation.fullName} แบบประเมินมีการบันทึกจัดเตรียมเอกสารเล่ม 2`, + receiverUserId: "59134ef9-9e62-41d0-aac5-339be727f2b0", + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API บันทึกแจ้งผลการประกาศคัดเลือก + * + * @summary EV1_042 - บันทึกแจ้งผลการประกาศคัดเลือก (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("announce/{id}") + async EV1_042(@Path() id: string, @Request() request: RequestWithUser) { + await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + if (evaluation.step != "PREPARE_DOC_V2") { + const evaluationLogs = new EvaluationLogs(); + const _null: any = null; + evaluationLogs.step = (await ConvertToThaiStep("PREPARE_DOC_V2")) ?? _null; + evaluationLogs.createdUserId = request.user.sub; + evaluationLogs.createdFullName = request.user.name; + evaluationLogs.createdAt = new Date(); + evaluationLogs.lastUpdateUserId = request.user.sub; + evaluationLogs.lastUpdateFullName = request.user.name; + evaluationLogs.lastUpdatedAt = new Date(); + evaluationLogs.evaluation = evaluation; + await this.evaluationLogsRepository.save(evaluationLogs, { data: request }); + setLogDataDiff(request, { before: null, after: evaluationLogs }); + } + const before = structuredClone(evaluation); + + evaluation.step = "PREPARE_DOC_V2"; + evaluation.datePrepareDoc2 = new Date(); + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: "เจ้าหน้าที่แจ้งผลประกาศคัดเลือก", + body: "เจ้าหน้าที่แจ้งผลประกาศคัดเลือก", + receiverUserId: evaluation.userId, + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API ย้อนกลับจัดเตรียมเอกสารเล่ม 2 + * + * @summary EV1_030 - ย้อนกลับจัดเตรียมเอกสารเล่ม 2 (USER) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("prepare-doc-v2/reject/{id}") + async EV1_030(@Path() id: string, @Request() request: RequestWithUser) { + // await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + if (evaluation.step != "PREPARE_DOC_V2") { + const evaluationLogs = new EvaluationLogs(); + const _null: any = null; + evaluationLogs.step = (await ConvertToThaiStep("PREPARE_DOC_V2")) ?? _null; + evaluationLogs.createdUserId = request.user.sub; + evaluationLogs.createdFullName = request.user.name; + evaluationLogs.createdAt = new Date(); + evaluationLogs.lastUpdateUserId = request.user.sub; + evaluationLogs.lastUpdateFullName = request.user.name; + evaluationLogs.lastUpdatedAt = new Date(); + evaluationLogs.evaluation = evaluation; + await this.evaluationLogsRepository.save(evaluationLogs, { data: request }); + setLogDataDiff(request, { before: null, after: evaluationLogs }); + } + const before = structuredClone(evaluation); + + evaluation.step = "PREPARE_DOC_V2"; + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API บันทึกตรวจสอบเอกสารเล่ม 2 + * + * @summary EV1_031 - อนุมัติตรวจสอบเอกสารเล่ม 2 (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("wait-check-doc-v2/{id}") + async EV1_031(@Path() id: string, @Request() request: RequestWithUser) { + await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + if (evaluation.step != "DONE") { + const evaluationLogs = new EvaluationLogs(); + const _null: any = null; + evaluationLogs.step = (await ConvertToThaiStep("DONE")) ?? _null; + evaluationLogs.createdUserId = request.user.sub; + evaluationLogs.createdFullName = request.user.name; + evaluationLogs.createdAt = new Date(); + evaluationLogs.lastUpdateUserId = request.user.sub; + evaluationLogs.lastUpdateFullName = request.user.name; + evaluationLogs.lastUpdatedAt = new Date(); + evaluationLogs.evaluation = evaluation; + await this.evaluationLogsRepository.save(evaluationLogs, { data: request }); + setLogDataDiff(request, { before: null, after: evaluationLogs }); + } + const before = structuredClone(evaluation); + + evaluation.step = "DONE"; + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: "แบบประเมินของคุณอนุมัติตรวจสอบเอกสารเล่ม 2", + body: "แบบประเมินของคุณอนุมัติตรวจสอบเอกสารเล่ม 2", + receiverUserId: evaluation.userId, + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API ไม่อนุมัติตรวจสอบเอกสารเล่ม 2 + * + * @summary EV1_032 - ไม่อนุมัติตรวจสอบเอกสารเล่ม 2 (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("doc2/reject/{id}") + async EV1_032( + @Path() id: string, + @Body() body: { reason: string }, + @Request() request: RequestWithUser, + ) { + await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + if (evaluation.step != "CHECK_DOC_V2") { + const evaluationLogs = new EvaluationLogs(); + const _null: any = null; + evaluationLogs.step = (await ConvertToThaiStep("CHECK_DOC_V2")) ?? _null; + evaluationLogs.createdUserId = request.user.sub; + evaluationLogs.createdFullName = request.user.name; + evaluationLogs.createdAt = new Date(); + evaluationLogs.lastUpdateUserId = request.user.sub; + evaluationLogs.lastUpdateFullName = request.user.name; + evaluationLogs.lastUpdatedAt = new Date(); + evaluationLogs.evaluation = evaluation; + await this.evaluationLogsRepository.save(evaluationLogs, { data: request }); + setLogDataDiff(request, { before: null, after: evaluationLogs }); + } + + const before = structuredClone(evaluation); + + evaluation.step = "CHECK_DOC_V2"; + evaluation.reason = body.reason; + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: "แบบประเมินของคุณไม่อนุมัติตรวจสอบเอกสารเล่ม 2", + body: "แบบประเมินของคุณไม่อนุมัติตรวจสอบเอกสารเล่ม 2", + receiverUserId: evaluation.userId, + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API ประวัติการเปลี่ยนสถานะรายการคำขอประเมิน + * + * @summary EV1_033 - ประวัติการเปลี่ยนสถานะ (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Get("step-history/{id}") + async StepHistory(@Path() id: string) { + try { + const stepHistory = await this.evaluationLogsRepository.find({ + where: { + evaluationId: id, + }, + select: ["step", "lastUpdateFullName", "lastUpdatedAt"], + order: { + lastUpdatedAt: "ASC", + }, + }); + return new HttpSuccess(stepHistory); + } catch (error: any) { + return error.status; + } + } + + /** + * API เลือกกรรมการรายการคำขอประเมิน + * + * @summary EV1_034 - เลือกกรรมการ (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("choose-directors/{id}") + async ChooseDirectors( + @Path() id: string, + @Body() body: { directors: string[] }, + @Request() request: RequestWithUser, + ) { + // await new permission().PermissionUpdate(request, "SYS_EVA_INFO"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + const before = structuredClone(evaluation); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + if (!evaluation.directors) { + evaluation.directors = []; + } + body.directors.forEach(async (directorId) => { + const director = await this.directorRepository.findOne({ where: { id: directorId } }); + if (director != null) evaluation.directors.push(director); + }); + + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: "แบบประเมินของคุณมีการเลือกกรรมการประเมิน", + body: "แบบประเมินของคุณมีการเลือกกรรมการประเมิน", + receiverUserId: evaluation.userId, + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API เลือกการประชุมรายการคำขอประเมิน + * + * @summary EV1_035 - เลือกประชุม (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("choose-meetings/{id}") + async ChooseMeetings( + @Path() id: string, + @Body() body: { meetings: string[] }, + @Request() request: RequestWithUser, + ) { + // await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + const before = structuredClone(evaluation); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + if (!evaluation.meetings) { + evaluation.meetings = []; + } + body.meetings.forEach(async (meetingId) => { + const meeting = await this.meetingRepository.findOne({ where: { id: meetingId } }); + if (meeting != null) evaluation.meetings.push(meeting); + }); + + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: "มีการประชุมกรรมการประเมินผล", + body: "มีการประชุมกรรมการประเมินผล", + receiverUserId: evaluation.userId, + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API แสดงข้อมูลกรรมการและการประชุม + * + * @summary EV1_036 - แสดงกรรมการและการประชุม (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Get("director-meeting/{id}") + async DirectorAndMeeting(@Request() request: RequestWithUser, @Path() id: string) { + await new permission().PermissionList(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ + where: { id }, + relations: ["directors", "meetings"], + }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + const directors = evaluation.directors.map((director) => ({ + id: director.id, + prefix: director.prefix, + firstName: director.firstName, + lastName: director.lastName, + position: director.position, + positionName: null, + email: director.email, + phone: director.phone, + })); + + const meetings = evaluation.meetings.map((meeting) => ({ + id: meeting.id, + dateStart: meeting.dateStart, + dateEnd: meeting.dateEnd, + result: meeting.result, + duration: meeting.duration, + round: meeting.round, + title: meeting.title, + })); + + return new HttpSuccess({ directors, meetings }); + } catch (error: any) { + return error.status; + } + } + + /** + * API ช่วงเวลาประเมิน + * + * @summary EV1_037 - แสดงช่วงเวลาประเมิน (USER) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Get("check-date/{id}") + async CheckRangeDate(@Path() id: string) { + try { + const evaluation = await this.evaluationRepository.findOne({ + where: { id }, + }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + const responseData = { + dateStartAnnounce: + evaluation.dateAnnounce == null ? null : new Date(evaluation.dateAnnounce.toString()), + dateEndAnnounce: + evaluation.dateAnnounce == null + ? null + : new Date(evaluation.dateAnnounce.setDate(evaluation.dateAnnounce.getDate() + 30)), + dateStartPrepareDoc2: + evaluation.datePrepareDoc2 == null + ? null + : new Date(evaluation.datePrepareDoc2.toString()), + dateEndPrepareDoc2: + evaluation.datePrepareDoc2 == null + ? null + : new Date( + evaluation.datePrepareDoc2.setMonth(evaluation.datePrepareDoc2.getMonth() + 6), + ), + }; + + return new HttpSuccess(responseData); + } catch (error: any) { + return error.status; + } + } + + /** + * API ช่วงเวลาประเมิน + * + * @summary EV1_037 - แสดงช่วงเวลาประเมิน (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Get("admin/check-date/{id}") + async CheckRangeDateByAdmin(@Path() id: string, @Request() request: RequestWithUser) { + let _workflow = await new permission().Workflow(request, id, "SYS_EVA_REQ"); + if (_workflow == false) await new permission().PermissionGet(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ + where: { id }, + }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + const responseData = { + dateStartAnnounce: + evaluation.dateAnnounce == null ? null : new Date(evaluation.dateAnnounce.toString()), + dateEndAnnounce: + evaluation.dateAnnounce == null + ? null + : new Date(evaluation.dateAnnounce.setDate(evaluation.dateAnnounce.getDate() + 30)), + dateStartPrepareDoc2: + evaluation.datePrepareDoc2 == null + ? null + : new Date(evaluation.datePrepareDoc2.toString()), + dateEndPrepareDoc2: + evaluation.datePrepareDoc2 == null + ? null + : new Date( + evaluation.datePrepareDoc2.setMonth(evaluation.datePrepareDoc2.getMonth() + 6), + ), + }; + + return new HttpSuccess(responseData); + } catch (error: any) { + return error.status; + } + } + + /** + * API ตอบกลับข้อความให้ admin + * + * @summary EV1_038 - ตอบกลับข้อความให้ admin (USER) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("contact/admin/{id}") + async SendNotiAdmin( + @Path() id: string, + @Body() body: { subject: string; body: string }, + @Request() request: RequestWithUser, + ) { + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: body.subject, + body: body.body, + receiverUserId: "59134ef9-9e62-41d0-aac5-339be727f2b0", + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API ตอบกลับข้อความให้ user + * + * @summary EV1_039 - ตอบกลับข้อความให้ user (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("contact/user/{id}") + async SendNotiUser( + @Path() id: string, + @Body() body: { subject: string; body: string }, + @Request() request: RequestWithUser, + ) { + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + await new CallAPI() + .PostData(request, "/placement/noti/keycloak", { + subject: body.subject, + body: body.body, + receiverUserId: evaluation.userId, + payload: "", + isSendMail: true, + isSendInbox: true, + isSendNotification: true, + }) + .then((x) => {}) + .catch((x) => {}); + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API แสดงข้อมูลผู้เซ็นเอกสารเล่ม 1 + * + * @summary EV1_040 - แสดงข้อมูลผู้เซ็นเอกสารเล่ม 1 (USER) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Get("doc1-signer/{id}") + async DocumentSigner1(@Path() id: string, @Request() request: RequestWithUser) { + try { + const evaluation = await this.evaluationRepository.findOne({ + where: { id }, + select: [ + "author", + "subject", + "commanderFullname", + "commanderPosition", + "commanderAboveFullname", + "commanderAbovePosition", + ], + }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + return new HttpSuccess(evaluation); + } catch (error: any) { + return error.status; + } + } + + /** + * API แสดงข้อมูลผู้เซ็นเอกสารเล่ม 1 + * + * @summary EV1_040 - แสดงข้อมูลผู้เซ็นเอกสารเล่ม 1 (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Get("admin/doc1-signer/{id}") + async DocumentSigner1ByAdmin(@Path() id: string, @Request() request: RequestWithUser) { + let _workflow = await new permission().Workflow(request, id, "SYS_EVA_REQ"); + if (_workflow == false) await new permission().PermissionGet(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ + where: { id }, + select: [ + "author", + "subject", + "commanderFullname", + "commanderPosition", + "commanderAboveFullname", + "commanderAbovePosition", + ], + }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + return new HttpSuccess(evaluation); + } catch (error: any) { + return error.status; + } + } + + /** + * API แสดงข้อมูลผู้เซ็นเอกสารเล่ม 2 + * + * @summary EV1_041 - แสดงข้อมูลผู้เซ็นเอกสารเล่ม 2 (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Get("doc2-signer/{id}") + async DocumentSigner2(@Path() id: string) { + try { + const evaluation = await this.evaluationRepository.findOne({ + where: { id }, + select: [ + "authorDoc2", + "subjectDoc2", + "assignedPosition", + "commanderFullnameDoc2", + "commanderPositionDoc2", + "commanderAboveFullnameDoc2", + "commanderAbovePositionDoc2", + ], + }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + return new HttpSuccess(evaluation); + } catch (error: any) { + return error.status; + } + } + + /** + * API แสดงข้อมูลผู้เซ็นเอกสารเล่ม 2 + * + * @summary EV1_041 - แสดงข้อมูลผู้เซ็นเอกสารเล่ม 2 (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Get("admin/doc2-signer/{id}") + async DocumentSigner2ByAdmin(@Path() id: string, @Request() request: RequestWithUser) { + let _workflow = await new permission().Workflow(request, id, "SYS_EVA_REQ"); + if (_workflow == false) await new permission().PermissionGet(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ + where: { id }, + select: [ + "authorDoc2", + "subjectDoc2", + "assignedPosition", + "commanderFullnameDoc2", + "commanderPositionDoc2", + "commanderAboveFullnameDoc2", + "commanderAbovePositionDoc2", + ], + }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + return new HttpSuccess(evaluation); + } catch (error: any) { + return error.status; + } + } + + /** + * API บันทึกชื่อผลงาน ชื่อเจ้าของผลงาน และชื่อคณะกรรมการ + * + * @summary บันทึกชื่อผลงาน ชื่อเจ้าของผลงาน และชื่อคณะกรรมการ (User) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("update-author-director/{id}") + @Example([ + { + author: "string", + subject: "string", + commanderFullname: "string", + commanderPosition: "string", + commanderAboveFullname: "string", + commanderAbovePosition: "string", + }, + ]) + async updateAuthorDirector( + @Path() id: string, + @Body() + body: { + author: string; + subject: string; + commanderFullname: string; + commanderPosition: string; + commanderAboveFullname: string; + commanderAbovePosition: string; + }, + @Request() request: RequestWithUser, + ) { + // await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + + evaluation.author = body.author; + evaluation.subject = body.subject; + evaluation.commanderFullname = body.commanderFullname; + evaluation.commanderPosition = body.commanderPosition; + evaluation.commanderAboveFullname = body.commanderAboveFullname; + evaluation.commanderAbovePosition = body.commanderAbovePosition; + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + const before = structuredClone(evaluation); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API บันทึกชื่อผลงาน ชื่อเจ้าของผลงาน และชื่อคณะกรรมการ2 + * + * @summary บันทึกชื่อผลงาน ชื่อเจ้าของผลงาน และชื่อคณะกรรมการ2 (User) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Put("update-author-director2/{id}") + @Example([ + { + authorDoc2: "string", + subjectDoc2: "string", + assignedPosition: "string", + commanderFullnameDoc2: "string", + commanderPositionDoc2: "string", + commanderAboveFullnameDoc2: "string", + commanderAbovePositionDoc2: "string", + }, + ]) + async updateAuthorDirector2( + @Path() id: string, + @Body() + body: { + authorDoc2: string; + subjectDoc2: string; + assignedPosition: string; + commanderFullnameDoc2: string; + commanderPositionDoc2: string; + commanderAboveFullnameDoc2: string; + commanderAbovePositionDoc2: string; + }, + @Request() request: RequestWithUser, + ) { + // await new permission().PermissionUpdate(request, "SYS_EVA_REQ"); + try { + const evaluation = await this.evaluationRepository.findOne({ where: { id } }); + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + + evaluation.authorDoc2 = body.authorDoc2; + evaluation.subjectDoc2 = body.subjectDoc2; + evaluation.assignedPosition = body.assignedPosition; + evaluation.commanderFullnameDoc2 = body.commanderFullnameDoc2; + evaluation.commanderPositionDoc2 = body.commanderPositionDoc2; + evaluation.commanderAboveFullnameDoc2 = body.commanderAboveFullnameDoc2; + evaluation.commanderAbovePositionDoc2 = body.commanderAbovePositionDoc2; + evaluation.lastUpdateUserId = request.user.sub; + evaluation.lastUpdateFullName = request.user.name; + evaluation.lastUpdatedAt = new Date(); + const before = structuredClone(evaluation); + await this.evaluationRepository.save(evaluation, { data: request }); + setLogDataDiff(request, { before, after: evaluation }); + + return new HttpSuccess(); + } catch (error: any) { + return error.status; + } + } + + /** + * API ลบแบบประเมิน (USER) + * + * @summary EV1_037 - ลบแบบประเมิน (USER) + * + * @param {string} id id การประเมิน + */ + @Delete("{id}") + async delete_evaluation(id: string, @Request() request: RequestWithUser) { + // await new permission().PermissionDelete(request, "SYS_EVA_REQ"); + const evaluation = await this.evaluationRepository.findOne({ + where: { id }, + relations: ["meetings", "directors"], + }); + + if (!evaluation) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + evaluation.meetings; + if (["CHECK_SPEC", "PREPARE_DOC_V1", "CHECK_DOC_V1"].includes(evaluation.step)) { + await this.educationRepository.delete({ evaluationId: id }); + await this.certificateRepository.delete({ evaluationId: id }); + await this.salaryRepository.delete({ evaluationId: id }); + await this.trainingRepository.delete({ evaluationId: id }); + await this.assessmentRepository.delete({ evaluationId: id }); + await this.evaluationLogsRepository.delete({ evaluationId: id }); + await this.evaluationLogsRepository.delete({ evaluationId: id }); + await Promise.all( + evaluation.meetings.map((meeting) => + this.meetingRepository.remove(meeting, { data: request }), + ), + ); + await Promise.all( + evaluation.directors.map((director) => + this.directorRepository.remove(director, { data: request }), + ), + ); + await this.evaluationRepository.delete({ id }); + + return new HttpSuccess(); + } else { + throw new HttpError( + HttpStatusCode.BAD_REQUEST, + "ไม่สามารถลบข้อมูลในสถานะ" + "'" + ConvertToThaiStep(evaluation.step) + "'" + "ได้", + ); + } + } + + /** + * ดึงข้อมูลรายละเอียด step การขอประเมิน + * + * @summary EV1_002 - รายละเอียด step การขอประเมิน (ADMIN) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Get("check/admin/{id}") + @Example([ + { + step: "string", + }, + ]) + async checkByAdmin(@Request() request: RequestWithUser, @Path() id: string) { + let _workflow = await new permission().Workflow(request, id, "SYS_EVA_REQ"); + if (_workflow == false) await new permission().PermissionGet(request, "SYS_EVA_REQ"); + const evaluation = await this.evaluationRepository.findOne({ + where: { id }, + select: ["step"], + }); + + if (!evaluation) { + return "ไม่พบข้อมูล"; + } + return new HttpSuccess(evaluation); + } +} diff --git a/src/controllers/MeetingController.ts b/src/controllers/MeetingController.ts new file mode 100644 index 0000000..97aceac --- /dev/null +++ b/src/controllers/MeetingController.ts @@ -0,0 +1,212 @@ +import { AppDataSource } from "../database/data-source"; +import { CreateMeeting, Meeting } from "../entities/Meeting"; +import { + Body, + Delete, + Get, + Path, + Post, + Put, + Response, + Route, + SuccessResponse, + Tags, + Query, + Request, + Security, +} from "tsoa"; +import HttpStatusCode from "../interfaces/http-status"; +import HttpSuccess from "../interfaces/http-success"; +import HttpError from "../interfaces/http-error"; +import { RequestWithUser } from "../middlewares/user"; +import permission from "../interfaces/permission"; +import { setLogDataDiff } from "../interfaces/utils"; +import { Brackets } from "typeorm"; + +@Route("api/v1/evaluation/meeting") +@Tags("meeting") +@Security("bearerAuth") +@Response( + HttpStatusCode.INTERNAL_SERVER_ERROR, + "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", +) +@SuccessResponse(HttpStatusCode.OK, "สำเร็จ") +export class MeetingController { + private meetingRepository = AppDataSource.getRepository(Meeting); + + /** + * API สำหรับแสดงรายการการประชุม + * + * @summary EV4_006 - รายการการประชุม (ADMIN) + * + */ + @Get() + async all( + @Request() request: RequestWithUser, + @Query("page") page: number = 1, + @Query("pageSize") pageSize: number = 10, + @Query("keyword") keyword?: string, + ) { + await new permission().PermissionList(request, "SYS_EVA_INFO"); + // const meetings = await this.meetingRepository.find({ + // skip: (page - 1) * pageSize, + // take: pageSize, + // }); + // if (keyword != undefined && keyword !== "") { + // return meetings.filter((x) => x.title?.includes(keyword) || x.round?.includes(keyword)); + // } + const meetings = await AppDataSource.getRepository(Meeting) + .createQueryBuilder("meeting") + .andWhere( + new Brackets((qb) => { + qb.where( + keyword != null && keyword != "" + ? "meeting.title LIKE :keyword" + : "1=1", + { + keyword: `%${keyword}%`, + }, + ) + .orWhere( + keyword != null && keyword != "" + ? "meeting.round LIKE :keyword" + : "1=1", + { + keyword: `%${keyword}%`, + }, + ); + }), + ) + .orderBy("meeting.createdAt", "DESC") + .skip((page - 1) * pageSize) + .take(pageSize) + .getMany(); + return new HttpSuccess(meetings); + } + + @Get("admin") + async allAdmin( + @Request() request: RequestWithUser, + @Query("page") page: number = 1, + @Query("pageSize") pageSize: number = 10, + @Query("keyword") keyword?: string, + ) { + // const meetings = await this.meetingRepository.find({ + // skip: (page - 1) * pageSize, + // take: pageSize, + // }); + // if (keyword != undefined && keyword !== "") { + // return meetings.filter((x) => x.title?.includes(keyword) || x.round?.includes(keyword)); + // } + + const meetings = await AppDataSource.getRepository(Meeting) + .createQueryBuilder("meeting") + .andWhere( + new Brackets((qb) => { + qb.where( + keyword != null && keyword != "" + ? "meeting.title LIKE :keyword" + : "1=1", + { + keyword: `%${keyword}%`, + }, + ) + .orWhere( + keyword != null && keyword != "" + ? "meeting.round LIKE :keyword" + : "1=1", + { + keyword: `%${keyword}%`, + }, + ); + }), + ) + .orderBy("meeting.createdAt", "DESC") + .skip((page - 1) * pageSize) + .take(pageSize) + .getMany(); + return new HttpSuccess(meetings); + } + + /** + * API สำหรับแสดงรายละเอียดการประชุม + * + * @summary EV4_007 - รายละเอียดการประชุม (ADMIN) + * + */ + @Get("{id}") + async one(@Path() id: string, @Request() request: RequestWithUser) { + let _workflow = await new permission().Workflow(request, id, "SYS_EVA_INFO"); + if (_workflow == false) await new permission().PermissionGet(request, "SYS_EVA_INFO"); + const meeting = await this.meetingRepository.findOne({ where: { id } }); + if (!meeting) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + return new HttpSuccess(meeting); + } + + /** + * API สำหรับเพิ่มรายละเอียดการประชุม + * + * @summary EV4_008 - เพิ่มรายละเอียดการประชุม (ADMIN) + * + */ + @Post() + async save(@Body() requestBody: CreateMeeting, @Request() request: RequestWithUser) { + await new permission().PermissionCreate(request, "SYS_EVA_INFO"); + const meeting = Object.assign(new Meeting(), requestBody); + meeting.createdUserId = request.user.sub; + meeting.createdFullName = request.user.name; + meeting.createdAt = new Date(); + meeting.lastUpdateUserId = request.user.sub; + meeting.lastUpdateFullName = request.user.name; + meeting.lastUpdatedAt = new Date(); + const before = null; + + await this.meetingRepository.save(meeting, { data: request }); + setLogDataDiff(request, { before, after: meeting }); + + return new HttpSuccess(); + } + + /** + * API สำหรับแก้ไขรายละเอียดการประชุม + * + * @summary EV4_009 - แก้ไขรายละเอียดการประชุม (ADMIN) + * + */ + @Put("{id}") + async update(@Path() id: string, @Body() u: CreateMeeting, @Request() request: RequestWithUser) { + await new permission().PermissionUpdate(request, "SYS_EVA_INFO"); + let meeting = await this.meetingRepository.findOneBy({ id }); + if (!meeting) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + const before = structuredClone(meeting); + meeting.lastUpdateUserId = request.user.sub; + meeting.lastUpdateFullName = request.user.name; + meeting.lastUpdatedAt = new Date(); + this.meetingRepository.merge(meeting, u); + await this.meetingRepository.save(meeting, { data: request }); + setLogDataDiff(request, { before, after: meeting }); + + return new HttpSuccess(); + } + + /** + * API สำหรับลบรายละเอียดการประชุม + * + * @summary EV4_010 - ลบรายละเอียดการประชุม (ADMIN) + * + */ + @Delete("{id}") + async remove(id: string, @Request() request: RequestWithUser) { + await new permission().PermissionDelete(request, "SYS_EVA_INFO"); + let meeting = await this.meetingRepository.findOneBy({ id }); + if (!meeting) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "not found."); + } + await this.meetingRepository.remove(meeting, { data: request }); + return new HttpSuccess(); + } +} diff --git a/src/controllers/ReportController.ts b/src/controllers/ReportController.ts new file mode 100644 index 0000000..3979d0f --- /dev/null +++ b/src/controllers/ReportController.ts @@ -0,0 +1,370 @@ +import { AppDataSource } from "../database/data-source"; +import { + Body, + Example, + Get, + Path, + Post, + Put, + Request, + Response, + Route, + Security, + SuccessResponse, + Tags, + Delete, +} from "tsoa"; +import HttpStatusCode from "../interfaces/http-status"; +import { Evaluation } from "../entities/Evaluation"; +import HttpSuccess from "../interfaces/http-success"; +import { EvaluationLogs } from "../entities/EvaluationLogs"; +import HttpError from "../interfaces/http-error"; +import { Education } from "../entities/Education"; +import { Certificate } from "../entities/Certificate"; +import { Salary } from "../entities/Salary"; +import { Training } from "../entities/Training"; +import { Assessment } from "../entities/Assessment"; +import { Director } from "../entities/Director"; +import { Meeting } from "../entities/Meeting"; +import { Brackets } from "typeorm"; +import CallAPI from "../interfaces/call-api"; +import { RequestWithUser } from "../middlewares/user"; +import Extension from "../interfaces/extension"; +import { Not } from "typeorm" +@Route("api/v1/evaluation/report") +@Tags("report") +@Security("bearerAuth") +@Response( + HttpStatusCode.INTERNAL_SERVER_ERROR, + "เกิดข้อผิดพลาด ไม่สามารถทำรายการได้ กรุณาลองใหม่ในภายหลัง", +) +@SuccessResponse(HttpStatusCode.OK, "สำเร็จ") +export class ReoportController { + private evaluationRepository = AppDataSource.getRepository(Evaluation); + private evaluationLogsRepository = AppDataSource.getRepository(EvaluationLogs); + private educationRepository = AppDataSource.getRepository(Education); + private certificateRepository = AppDataSource.getRepository(Certificate); + private salaryRepository = AppDataSource.getRepository(Salary); + private trainingRepository = AppDataSource.getRepository(Training); + private assessmentRepository = AppDataSource.getRepository(Assessment); + private directorRepository = AppDataSource.getRepository(Director); + private meetingRepository = AppDataSource.getRepository(Meeting); + + /** + * Report ระบบประเมินบุคคล + * + * @summary Report ระบบประเมินบุคคล (ADMIN & USER) + * + * @param {string} id id ข้อมูลการประเมิน + */ + @Get("check-spec-report/{id}") + async checkSpecGetReport(@Request() request: RequestWithUser, @Path() id: string) { + const evaluation = await AppDataSource.getRepository(Evaluation) + .createQueryBuilder("evaluation") + .leftJoin("evaluation.education", "education") + .leftJoin("evaluation.certificate", "certificate") + .leftJoin("evaluation.salaries", "salaries") + .leftJoin("evaluation.training", "training") + .leftJoin("evaluation.assessment", "assessment") + .where("evaluation.id = :id", { id }) + .select([ + "evaluation.id", + "evaluation.userId", + "evaluation.subject", + "evaluation.isEducationalQft", + "evaluation.isGovermantServiceHtr", + "evaluation.isOperatingExp", + "evaluation.isMinPeriodOfTenure", + "evaluation.isHaveSpecificQft", + "evaluation.isHaveProLicense", + "evaluation.isHaveMinPeriodOrHoldPos", + "evaluation.type", + "evaluation.prefix", + "evaluation.fullName", + "evaluation.position", + "evaluation.posNo", + "evaluation.oc", + "evaluation.salary", + "evaluation.positionLevel", + "evaluation.birthDate", + "evaluation.govAge", + "evaluation.experience", + + "education.educationLevel", + "education.institute", + "education.isDate", + "education.startDate", + "education.endDate", + "education.finishDate", + "education.isEducation", + "education.degree", + "education.field", + "education.fundName", + "education.gpa", + "education.country", + "education.other", + "education.duration", + "education.durationYear", + + "certificate.certificateType", + "certificate.issuer", + "certificate.certificateNo", + "certificate.issueDate", + "certificate.expireDate", + + "salaries.date", + "salaries.amount", + "salaries.positionSalaryAmount", + "salaries.mouthSalaryAmount", + "salaries.position", + "salaries.posNo", + "salaries.salaryClass", + "salaries.salaryRef", + "salaries.refCommandNo", + "salaries.refCommandDate", + "salaries.salaryStatus", + + "training.name", + "training.topic", + "training.startDate", + "training.endDate", + "training.yearly", + "training.place", + "training.duration", + "training.department", + "training.numberOrder", + "training.dateOrder", + + "assessment.date", + "assessment.point1Total", + "assessment.point1", + "assessment.point2Total", + "assessment.point2", + "assessment.pointSumTotal", + "assessment.pointSum", + ]) + .getOne(); + + if (!evaluation) { + return "ไม่พบข้อมูล"; + } + let root: any + let dateStart: any + let dateRetireLaw: any + let org: any + let commanderFullname: any + let commanderPosition: any + let commanderRootName: any + let commanderOrg: any + let commanderAboveFullname: any + let commanderAbovePosition: any + let commanderAboveRootName: any + let commanderAboveOrg: any + if (!evaluation.userId) { + return "ไม่พบข้อมูลผู้ขอประเมิน"; + } + await new CallAPI() + .GetData(request, `/org/profile/keycloak/commander/${evaluation.userId}`) + .then(async (x) => { + root = x.root, + dateStart = x.dateStart, + dateRetireLaw = x.dateRetireLaw, + org = x.org, + commanderFullname = x.commanderFullname, + commanderPosition = x.commanderPosition, + commanderRootName = x.commanderRootName, + commanderOrg = x.commanderOrg, + commanderAboveFullname = x.commanderAboveFullname, + commanderAbovePosition = x.commanderAbovePosition, + commanderAboveRootName = x.commanderAboveRootName, + commanderAboveOrg = x.commanderAboveOrg + }) + .catch(); + const evaluationOld = await this.evaluationRepository.find({ + where: { + id: Not(id), + userId: evaluation.userId, + step: "DONE" + } + }); + let subjectOld = evaluationOld.length > 0 + ? evaluationOld.map(x => x.subject).join(", ") + : "ไม่มี" + let thaiYear:number = new Date().getFullYear()+543 + let years = { + lastTwoYear: Extension.ToThaiNumber((thaiYear-2).toString()), + lastOneYear: Extension.ToThaiNumber((thaiYear-1).toString()), + currentYear: Extension.ToThaiNumber(thaiYear.toString()), + } + const dataEvaluation = { + isEducationalQft: evaluation.isEducationalQft, + isGovermantServiceHtr: evaluation.isGovermantServiceHtr, + isOperatingExp: evaluation.isOperatingExp, + isMinPeriodOfTenure: evaluation.isMinPeriodOfTenure, + isHaveSpecificQft: evaluation.isHaveSpecificQft, + isHaveProLicense: evaluation.isHaveProLicense, + isHaveMinPeriodOrHoldPos: evaluation.isHaveMinPeriodOrHoldPos, + type: evaluation.type, + prefix: evaluation.prefix, + fullName: evaluation.prefix && evaluation.fullName ? `${evaluation.prefix}${evaluation.fullName}` : "-", + position: evaluation.position ? evaluation.position : "-", + posNo: evaluation.posNo ? Extension.ToThaiNumber(evaluation.posNo) : "-", + oc: evaluation.oc ? evaluation.oc : "-", + org: org ? org : "-", //สังกัด + root: root ? root : "-", //หน่วยงาน + salary: evaluation.salary ? Extension.ToThaiNumber(evaluation.salary) : "-", + positionLevel: evaluation.positionLevel ? evaluation.positionLevel : "-", + birthDate: evaluation.birthDate != null && evaluation.birthDate != "" + ? Extension.ToThaiNumber(Extension.ToThaiShortDate_noPrefix(new Date(evaluation.birthDate))) + : "-", + govAge: evaluation.govAge != null + ? Extension.ToThaiNumber(evaluation.govAge) + : "-", + experience: evaluation.experience ? evaluation.experience : "-", + dateStart: dateStart + ? Extension.ToThaiNumber(Extension.ToThaiShortDate(new Date(dateStart))) + : "-", + dateRetireLaw: dateRetireLaw + ? Extension.ToThaiNumber(Extension.ToThaiShortDate(new Date(dateRetireLaw))) + : "-", + subject: evaluation.subject != null ? evaluation.subject : "-", + subjectOld: subjectOld, + educations: evaluation.education.length > 0 + ? evaluation.education.map((education) => ({ + educationLevel: education.educationLevel + ? Extension.ToThaiNumber(education.educationLevel) + : "-", + institute: education.institute + ? Extension.ToThaiNumber(education.institute) + : "-", + finishYear: education.finishDate + ? Extension.ToThaiNumber((Extension.ToThaiYear(education.finishDate.getFullYear())).toString()) + : "-", + isDate: education.isDate, + startDate: education.startDate, + endDate: education.endDate, + finishDate: education.finishDate + ? Extension.ToThaiNumber(Extension.ToThaiShortDate(education.finishDate).toString()) + : "-", + isEducation: education.isEducation, + degree: education.degree + ? Extension.ToThaiNumber(education.degree) + : "-", + field: education.field + ? Extension.ToThaiNumber(education.field) + : "-", + fundName: education.fundName, + gpa: education.gpa, + country: education.country, + other: education.other, + duration: education.duration, + durationYear: education.durationYear, + })) + : [{ + educationLevel: "-", + institute: "-", + finishYear: "-", + finishDate: "-", + degree: "-", + field: "-" + }], + certificates: evaluation.certificate.length > 0 + ? evaluation.certificate.map((certificate) => ({ + certificateType: certificate.certificateType + ? Extension.ToThaiNumber(certificate.certificateType) + : "-", + issuer: certificate.issuer + ? Extension.ToThaiNumber(certificate.issuer) + : "-", + certificateNo: certificate.certificateNo + ? Extension.ToThaiNumber(certificate.certificateNo) + : "-", + issueDate: certificate.issueDate, + expireDate: certificate.expireDate, + })) + : [{ + certificateType: "-", + issuer: "-", + certificateNo: "-", + issueDate: "-", + expireDate: "-", + }], + salaries: evaluation.salaries.length > 0 + ? evaluation.salaries.map((salaries) => ({ + date: salaries.date + ? Extension.ToThaiNumber(Extension.ToThaiShortDate_noPrefix(salaries.date)) + : "-", + amount: salaries.amount + ? Extension.ToThaiNumber(salaries.amount.toLocaleString()) + : "-", + position: salaries.position + ? Extension.ToThaiNumber(salaries.position) + : "-", + positionSalaryAmount: salaries.positionSalaryAmount, + mouthSalaryAmount: salaries.mouthSalaryAmount, + posNo: salaries.posNo, + salaryClass: salaries.salaryClass, + salaryRef: salaries.salaryRef, + refCommandNo: salaries.refCommandNo, + refCommandDate: salaries.refCommandDate, + salaryStatus: salaries.salaryStatus, + })) + : [{ + date: "-", + amount: "-", + position: "-", + }], + trainings: evaluation.training.length > 0 + ? evaluation.training.map((training) => ({ + name: training.name + ? Extension.ToThaiNumber(training.name) + : "-", + topic: training.topic + ? Extension.ToThaiNumber(training.topic) + : "-", + startDate: training.startDate + ? Extension.ToThaiNumber(Extension.ToThaiShortDate_noPrefix(training.startDate)) + : "-", + endDate: training.endDate + ? Extension.ToThaiNumber(Extension.ToThaiShortDate_noPrefix(training.endDate)) + : "-", + yearly: training.yearly + ? Extension.ToThaiNumber(training.yearly.toString()) + : "-", + place: training.place, + duration: training.duration, + department: training.department, + numberOrder: training.numberOrder, + dateOrder: training.dateOrder, + })) + : [{ + name: "-", + topic: "-", + yearly: "-", + }], + assessments: evaluation.assessment.map((assessment) => ({ + date: assessment.date, + point1Total: assessment.point1Total, + point1: assessment.point1, + point2Total: assessment.point2Total, + point2: assessment.point2, + pointSumTotal: assessment.pointSumTotal, + pointSum: assessment.pointSum, + })), + commanderFullname: commanderFullname ? commanderFullname : "-", + commanderPosition: commanderPosition ? commanderPosition : "-", + commanderRootName: commanderRootName ? commanderRootName : "-", + commanderOrg: commanderOrg ? commanderOrg : "-", + commanderAboveFullname: commanderAboveFullname ? commanderAboveFullname : "-", + commanderAbovePosition: commanderAbovePosition ? commanderAbovePosition : "-", + commanderAboveRootName: commanderAboveRootName ? commanderAboveRootName : "-", + commanderAboveOrg: commanderAboveOrg ? commanderAboveOrg : "-", + years: years + }; + + if (!dataEvaluation) { + return "ไม่พบข้อมูล"; + } + return new HttpSuccess(dataEvaluation); + } +} diff --git a/src/database/data-source.ts b/src/database/data-source.ts new file mode 100644 index 0000000..d713314 --- /dev/null +++ b/src/database/data-source.ts @@ -0,0 +1,65 @@ +import "dotenv/config"; +import "reflect-metadata"; +import { DataSource, LogLevel, LogMessage } from "typeorm"; +import { Logger } from "typeorm"; +import { QueryRunner } from "typeorm/browser"; +import { RequestWithUser } from "../middlewares/user"; +import { addLogSequence } from "../interfaces/utils"; + +export class MyCustomLogger implements Logger { + log(level: "log" | "info" | "warn", message: any, queryRunner?: QueryRunner) {} + + logQuery(query: string, parameters?: any[], queryRunner?: QueryRunner): void { + const req = queryRunner?.data as RequestWithUser; + if (req?.app?.locals.logData?.sequence) { + addLogSequence(req, { + action: "database", + status: "success", + description: "Query Data.", + query: [ + "Query: " + query + (parameters ? " - Parameters:" + JSON.stringify(parameters) : ""), + ], + }); + } + + // const req = queryRunner?.data as RequestWithUser | undefined; + // const logData = req?.app?.locals.logData?.sequence?.at(-1); + + // if (logData && !logData.query) logData.query = []; + // if (logData) logData.query.push( + // "Query: " + query + (parameters ? (" - Parameters:" + JSON.stringify(parameters)) : '') + // ); + } + + logMigration(message: string, queryRunner?: QueryRunner) {} + logQueryError( + error: string | Error, + query: string, + parameters?: any[], + queryRunner?: QueryRunner, + ) {} + logQuerySlow(time: number, query: string, parameters?: any[], queryRunner?: QueryRunner) {} + logSchemaBuild(message: string, queryRunner?: QueryRunner) {} +} + +export const AppDataSource = new DataSource({ + type: "mysql", + database: process.env.DB_NAME, + host: process.env.DB_HOST, + port: +(process.env.DB_PORT || 3306), + username: process.env.DB_USERNAME, + password: process.env.DB_PASSWORD, + connectorPackage: "mysql2", + synchronize: false, + logging: ["query", "error"], + entities: + process.env.NODE_ENV !== "production" + ? ["src/entities/**/*.ts"] + : ["dist/entities/**/*{.ts,.js}"], + migrations: + process.env.NODE_ENV !== "production" + ? ["src/migration/**/*.ts"] + : ["dist/migration/**/*{.ts,.js}"], + subscribers: [], + logger: new MyCustomLogger(), +}); diff --git a/src/entities/Assessment.ts b/src/entities/Assessment.ts new file mode 100644 index 0000000..cba5b99 --- /dev/null +++ b/src/entities/Assessment.ts @@ -0,0 +1,40 @@ +import { Entity, Column, ManyToOne, JoinColumn, OneToOne } from "typeorm"; +import { EntityBase } from "./base/Base"; +import { Evaluation } from "./Evaluation"; + +@Entity("assessment") +export class Assessment extends EntityBase { + @Column({ + comment: "Id การทำรายการระบบประเมิน", + length: 40, + default: "00000000-0000-0000-0000-000000000000", + }) + evaluationId: string; + + @Column({ nullable: true, type: "datetime", comment: "วันที่ได้รับ" }) + date: Date; + + @Column({ nullable: true, type: "double precision", comment: "ส่วนที่1 (คะแนน)" }) + point1Total: number; + + @Column({ nullable: true, type: "double precision", comment: "ผลประเมินส่วนที่2 (คะแนน)" }) + point1: number; + + @Column({ nullable: true, type: "double precision", comment: "ส่วนที่2 (คะแนน)" }) + point2Total: number; + + @Column({ nullable: true, type: "double precision", comment: "ผลประเมินส่วนที่2 (คะแนน)" }) + point2: number; + + @Column({ nullable: true, type: "double precision", comment: "ผลรวม (คะแนน)" }) + pointSumTotal: number; + + @Column({ nullable: true, type: "double precision", comment: "ผลประเมินรวม (คะแนน)" }) + pointSum: number; + + @ManyToOne(() => Evaluation, (Evaluation) => Evaluation.assessment) + @JoinColumn({ name: "evaluationId" }) + evaluation: Evaluation; +} + +export type UpdateAssessment = Partial; diff --git a/src/entities/Certificate.ts b/src/entities/Certificate.ts new file mode 100644 index 0000000..48c13f0 --- /dev/null +++ b/src/entities/Certificate.ts @@ -0,0 +1,37 @@ +import { Entity, Column, ManyToOne, JoinColumn, OneToOne } from "typeorm"; +import { EntityBase } from "./base/Base"; +import { Evaluation } from "./Evaluation"; + +@Entity("certificate") +export class Certificate extends EntityBase { + @Column({ + comment: "Id การทำรายการระบบประเมิน", + length: 40, + default: "00000000-0000-0000-0000-000000000000", + }) + evaluationId: string; + + @Column({ nullable: true, comment: "ชื่อสถานะการประเมิน" }) + statictep: string; + + @Column({ nullable: true, comment: "ชื่อใบอนุญาต" }) + certificateType: string; + + @Column({ nullable: true, comment: "หน่วยงานผู้ออกใบอนุญาต" }) + issuer: string; + + @Column({ nullable: true, comment: "เลขที่ใบอนุญาต" }) + certificateNo: string; + + @Column({ nullable: true, type: "datetime", comment: "วันที่ออกใบอนุญาต" }) + issueDate: Date; + + @Column({ nullable: true, type: "datetime", comment: "วันที่หมดอายุ" }) + expireDate: Date; + + @ManyToOne(() => Evaluation, (Evaluation) => Evaluation.certificate) + @JoinColumn({ name: "evaluationId" }) + evaluation: Evaluation; +} + +export type UpdateCertificate = Partial; diff --git a/src/entities/Director.ts b/src/entities/Director.ts new file mode 100644 index 0000000..dd6a209 --- /dev/null +++ b/src/entities/Director.ts @@ -0,0 +1,51 @@ +import { + Entity, + Column, + ManyToMany, +} from "typeorm"; +import { EntityBase } from "./base/Base"; +import { Evaluation } from "./Evaluation"; +@Entity("director") +export class Director extends EntityBase { + @Column({ nullable: true, comment: "คำนำหน้าชื่อ" }) + prefix: string; + + @Column({ nullable: true, comment: "ชื่อ" }) + firstName: string; + + @Column({ nullable: true, comment: "นามสกุล" }) + lastName: string; + + @Column({ nullable: true, comment: "เบอร์โทรศัพท์" }) + phone: string; + + @Column({ nullable: true, comment: "อีเมล" }) + email: string; + + @Column({ nullable: true, comment: "ตำแหน่ง" }) + position: string; + + @ManyToMany(() => Evaluation, (evaluation) => evaluation.directors) + evaluations: Evaluation[]; +} + +export class CreateDirector { + @Column() + prefix: string; + + @Column() + firstName: string; + + @Column() + lastName: string; + + @Column() + phone: string; + + @Column() + email: string; + + @Column() + position: string; +} +export type UpdateDirector = Partial; diff --git a/src/entities/Education.ts b/src/entities/Education.ts new file mode 100644 index 0000000..b9f4ae8 --- /dev/null +++ b/src/entities/Education.ts @@ -0,0 +1,64 @@ +import { Entity, Column, ManyToOne, JoinColumn, OneToOne } from "typeorm"; +import { EntityBase } from "./base/Base"; +import { Evaluation } from "./Evaluation"; + +@Entity("education") +export class Education extends EntityBase { + @Column({ + comment: "Id การทำรายการระบบประเมิน", + length: 40, + default: "00000000-0000-0000-0000-000000000000", + }) + evaluationId: string; + + @Column({ nullable: true, comment: "ระดับศึกษา" }) + educationLevel: string; + + @Column({ nullable: true, comment: "สถานศึกษา" }) + institute: string; + + @Column({ nullable: true, comment: "ประเภทช่วงเวลาการศึกษา" }) + isDate: boolean; + + @Column({ nullable: true, type: "datetime", comment: "ตั้งแต่" }) + startDate: Date; + + @Column({ nullable: true, type: "datetime", comment: "EndDate" }) + endDate: Date; + + @Column({ nullable: true, type: "datetime", comment: "วันที่สำเร็จการศึกษา" }) + finishDate: Date; + + @Column({ nullable: true, comment: "เป็นวุฒิศึกษาในตำแหน่ง" }) + isEducation: boolean; + + @Column({ nullable: true, comment: "วุฒิการศึกษา" }) + degree: string; + + @Column({ nullable: true, comment: "สาขาวิชา/ทาง" }) + field: string; + + @Column({ nullable: true, comment: "ทุน" }) + fundName: string; + + @Column({ nullable: true, comment: "เกรดเฉลี่ย" }) + gpa: string; + + @Column({ nullable: true, comment: "ประเทศ" }) + country: string; + + @Column({ nullable: true, comment: "ข้อมูลการติดต่อ" }) + other: string; + + @Column({ nullable: true, comment: "ระยะเวลา" }) + duration: string; + + @Column({ nullable: true, comment: "ระยะเวลาหลักสูตร" }) + durationYear: string; + + @ManyToOne(() => Evaluation, (Evaluation) => Evaluation.education) + @JoinColumn({ name: "evaluationId" }) + evaluation: Evaluation; +} + +export type UpdateEducation = Partial; diff --git a/src/entities/Evaluation.ts b/src/entities/Evaluation.ts new file mode 100644 index 0000000..f2d2721 --- /dev/null +++ b/src/entities/Evaluation.ts @@ -0,0 +1,476 @@ +import { Entity, Column, OneToMany, ManyToMany, JoinTable } from "typeorm"; +import { EntityBase } from "./base/Base"; +import { EvaluationLogs } from "./EvaluationLogs"; +import { Education } from "./Education"; +import { Certificate } from "./Certificate"; +import { Salary } from "./Salary"; +import { Training } from "./Training"; +import { Assessment } from "./Assessment"; +import { Director } from "./Director"; +import { Meeting } from "./Meeting"; + +@Entity("evaluation") +export class Evaluation extends EntityBase { + @Column({ + comment: "Id ชื่อผู้ใช้งาน", + length: 40, + default: "00000000-0000-0000-0000-000000000000", + }) + userId: string; + + @Column({ nullable: true, comment: "รหัสบัตรประชาชน", length: 13 }) + citizenId: string; + + @Column({ nullable: true, comment: "คำนำหน้า" }) + prefix: string; + + @Column({ nullable: true, comment: "ชื่อ นามสกุล" }) + fullName: string; + + @Column({ nullable: true, comment: "ตำแหน่ง" }) + position: string; + + @Column({ nullable: true, comment: "สังกัด" }) + oc: string; + + @Column({ + nullable: true, + comment: "root", + length: 255, + default: null, + }) + rootId: string; + + @Column({ + nullable: true, + comment: "child1", + length: 255, + default: null, + }) + child1Id: string; + + @Column({ + nullable: true, + comment: "child2", + length: 255, + default: null, + }) + child2Id: string; + + @Column({ + nullable: true, + comment: "child3", + length: 255, + default: null, + }) + child3Id: string; + + @Column({ + nullable: true, + comment: "child4", + length: 255, + default: null, + }) + child4Id: string; + + @Column({ nullable: true, comment: "เงินเดือนปัจจุบัน" }) + salary: string; + + @Column({ nullable: true, comment: "ระดับปัจจุบัน" }) + positionLevel: string; + + @Column({ nullable: true, comment: "ตำแหน่งเลขที่" }) + posNo: string; + + @Column({ nullable: true, comment: "วันเดือนปีเกิด" }) + birthDate: string; + + @Column({ nullable: true, comment: "อายุราชการ" }) + govAge: string; + + @Column({ nullable: true, comment: "ประเภทแบบประเมิน" }) + type: string; + + @Column({ nullable: true, comment: "ชื่อสถานะการประเมิน" }) + step: string; + + @Column({ comment: "มีคุณวุฒิการศึกษา", default: false }) + isEducationalQft: boolean; + + @Column({ comment: "มีประวัติการรับราชการ", default: false }) + isGovermantServiceHtr: boolean; + + @Column({ comment: "มีประสบการณ์ในการปฏิบัติงาน", default: false }) + isOperatingExp: boolean; + + @Column({ + comment: "มีระยะเวลาขั้นต่ำในการดำรงตำแหน่งในสายงานที่ขอเข้ารับการคัดเลือก", + default: false, + }) + isMinPeriodOfTenure: boolean; + + @Column({ + comment: "มีคุณสมบัติตรงตามคุณสมบัติเฉพาะสำหรับตำแหน่งที่กำหนด ในมาตราฐานกำหนดตำแหน่ง", + default: false, + }) + isHaveSpecificQft: boolean; + + @Column({ + comment: + "มีใบอนุญาตประกอบวิชาชีพของสายงานต่างๆ และ/หรือ คุณวุฒิเพิ่มเติมครบถ้วนตามที่ ก.ก. กำหนด (แพทย์พยาบาล วิศวกรโยธา สถาปนิก ฯลฯ)", + default: false, + }) + isHaveProLicense: boolean; + + @Column({ + comment: + "มีระยะเวลาขั้นต่ำในการดำรงตำแหน่งหรือเคยดำรงตำแหน่งในสายงานที่จะคัดเลือกตามคุณวุฒิของบุคคลและระดับตำแหน่งที่จะคัดเลือก", + default: false, + }) + isHaveMinPeriodOrHoldPos: boolean; + + @Column({ nullable: true, comment: "เหตุผล" }) + reason: string; + + @Column({ nullable: true, comment: "ประสบการณ์ในการปฏิบัติงาน" }) + experience: string; + + @Column({ nullable: true, comment: "ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น" }) + commanderFullname: string; + + @Column({ nullable: true, comment: "ตำแหน่ง ผู้บังคับบัญชาชั้นต้น" }) + commanderPosition: string; + + @Column({ nullable: true, comment: "ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ" }) + commanderAboveFullname: string; + + @Column({ nullable: true, comment: "ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ" }) + commanderAbovePosition: string; + + @Column({ nullable: true, comment: "ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)" }) + commanderFullnameDoc2: string; + + @Column({ nullable: true, comment: "ตำแหน่ง ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)" }) + commanderPositionDoc2: string; + + @Column({ + nullable: true, + comment: "ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)", + }) + commanderAboveFullnameDoc2: string; + + @Column({ + nullable: true, + comment: "ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)", + }) + commanderAbovePositionDoc2: string; + + @Column({ nullable: true, comment: "วันที่ประกาศบนเว็บไซต์" }) + dateAnnounce: Date; + + @Column({ nullable: true, comment: "วันที่จัดเตรียมเอกสารเล่ม 2" }) + datePrepareDoc2: Date; + + @Column({ nullable: true, comment: "ชื่อเจ้าของผลงาน" }) + author: string; + + @Column({ nullable: true, comment: "ชื่อผลงาน" }) + subject: string; + + @Column({ nullable: true, comment: "ชื่อเจ้าของผลงาน2" }) + authorDoc2: string; + + @Column({ nullable: true, comment: "ชื่อผลงาน2" }) + subjectDoc2: string; + + @Column({ nullable: true, comment: "ตำแหน่งที่ได้รับมอบหมาย" }) + assignedPosition: string; + + @OneToMany(() => EvaluationLogs, (evaluationLogs) => evaluationLogs.evaluation) + evaluationLogs: EvaluationLogs[]; + + @OneToMany(() => Education, (education) => education.evaluation) + education: Education[]; + + @OneToMany(() => Certificate, (certificate) => certificate.evaluation) + certificate: Certificate[]; + + @OneToMany(() => Salary, (salary) => salary.evaluation) + salaries: Salary[]; + + @OneToMany(() => Training, (training) => training.evaluation) + training: Training[]; + + @OneToMany(() => Assessment, (assessment) => assessment.evaluation) + assessment: Assessment[]; + + @ManyToMany(() => Director, (director) => director.evaluations) + @JoinTable() + directors: Director[]; + + @ManyToMany(() => Meeting, (meeting) => meeting.evaluations) + @JoinTable() + meetings: Meeting[]; +} + +export class CreateEvaluation { + @Column() + userId?: string; + + @Column() + citizenId?: string; + + @Column() + prefix?: string; + + @Column() + fullName: string; + + @Column() + position?: string | null; + + @Column() + oc?: string | null; + + @Column() + salary?: string | null; + + @Column() + positionLevel?: string | null; + + @Column() + posNo?: string | null; + + @Column() + birthDate?: string | null; + + @Column() + govAge?: string | null; + + @Column() + type?: string | null; + + @Column() + step?: string | null; + + @Column() + isEducationalQft: boolean; //ReqField + + @Column() + isGovermantServiceHtr: boolean; //ReqField + + @Column() + isOperatingExp: boolean; //ReqField + + @Column() + isMinPeriodOfTenure: boolean; //ReqField + + @Column() + isHaveSpecificQft: boolean; //ReqField + + @Column() + isHaveProLicense: boolean; //ReqField + + @Column() + isHaveMinPeriodOrHoldPos: boolean; //ReqField + + @Column() + reason?: string | null; + + @Column() + educations?: CreateEducation[]; + + @Column() + certificates?: CreateCertificate[]; + + @Column() + salaries?: CreateSalary[]; + + @Column() + trainings?: CreateTraining[]; + + @Column() + assessments?: CreateAssessment[]; +} + +export class CreateEducation { + @Column() + educationLevel?: string | null; + + @Column() + institute?: string | null; + + @Column() + isDate?: boolean | null; + + @Column() + startDate?: Date | null; + + @Column() + endDate?: Date | null; + + @Column() + finishDate?: Date | null; + + @Column() + isEducation?: boolean | null; + + @Column() + degree?: string | null; + + @Column() + field?: string | null; + + @Column() + fundName?: string | null; + + @Column() + gpa?: string | null; + + @Column() + country?: string | null; + + @Column() + other?: string | null; + + @Column() + duration?: string | null; + + @Column() + durationYear?: string | null; +} + +export class CreateCertificate { + @Column() + step?: string | null; + + @Column() + certificateType?: string | null; + + @Column() + issuer?: string | null; + + @Column() + certificateNo?: string | null; + + @Column() + issueDate?: Date | null; + + @Column() + expireDate?: Date | null; +} + +export class CreateSalary { + @Column() + step?: string | null; + + @Column() + date?: Date | null; + + @Column() + amount?: number | null; + + @Column() + positionSalaryAmount?: number | null; + + @Column() + mouthSalaryAmount?: number | null; + + @Column() + position?: string | null; + + @Column() + posNo?: string | null; + + @Column() + salaryClass?: string | null; + + @Column() + salaryRef?: string | null; + + @Column() + refCommandNo?: string | null; + + @Column() + refCommandDate?: Date | null; + + @Column() + salaryStatus?: string | null; +} +export class CreateTraining { + @Column() + name?: string | null; + + @Column() + topic?: string | null; + + @Column() + startDate?: Date | null; + + @Column() + endDate?: Date | null; + + @Column() + yearly?: number | null; + + @Column() + place?: string | null; + + @Column() + duration?: string | null; + + @Column() + department?: string | null; + + @Column() + numberOrder?: string | null; + + @Column() + dateOrder?: Date | null; +} +export class CreateAssessment { + @Column() + date?: Date | null; + + @Column() + point1Total?: number | null; + + @Column() + point1?: number | null; + + @Column() + point2Total?: number | null; + + @Column() + point2?: number | null; + + @Column() + pointSumTotal?: number | null; + + @Column() + pointSum?: number | null; +} +export class CreateEvaluationExpertise { + @Column() + author?: string | null; + + @Column() + subject?: string | null; + + @Column() + commanderFullname?: string | null; + + @Column() + commanderPosition?: string | null; + + @Column() + commanderAboveFullname?: string | null; + + @Column() + commanderAbovePosition?: string | null; + + @Column() + oc?: string | null; +} + +export type UpdateEvaluation = Partial; diff --git a/src/entities/EvaluationLogs.ts b/src/entities/EvaluationLogs.ts new file mode 100644 index 0000000..2c72a72 --- /dev/null +++ b/src/entities/EvaluationLogs.ts @@ -0,0 +1,22 @@ +import { Entity, Column, ManyToOne, JoinColumn } from "typeorm"; +import { EntityBase } from "./base/Base"; +import { Evaluation } from "./Evaluation"; + +@Entity("evaluationlogs") +export class EvaluationLogs extends EntityBase { + @Column({ + comment: "Id การทำรายการระบบประเมิน", + length: 40, + default: "00000000-0000-0000-0000-000000000000", + }) + evaluationId: string; + + @Column({ comment: "ชื่อสถานะการประเมิน", default: "string" }) + step: string; + + @ManyToOne(() => Evaluation, (Evaluation) => Evaluation.evaluationLogs) + @JoinColumn({ name: "evaluationId" }) + evaluation: Evaluation; +} + +export type UpdateEvaluationLogs = Partial; diff --git a/src/entities/Meeting.ts b/src/entities/Meeting.ts new file mode 100644 index 0000000..126e586 --- /dev/null +++ b/src/entities/Meeting.ts @@ -0,0 +1,51 @@ +import { + Entity, + Column, + ManyToMany, +} from "typeorm"; +import { EntityBase } from "./base/Base"; +import { Evaluation } from "./Evaluation"; +@Entity("meeting") +export class Meeting extends EntityBase { + @Column({ nullable: true, comment: "ชื่อการประชุม" }) + title: string; + + @Column({ nullable: true, comment: "ครั้งที่" }) + round: string; + + @Column({ nullable: true, comment: "วันเวลาเริ่มในการประชุม" }) + dateStart: Date; + + @Column({ nullable: true, comment: "วันเวลาสิ้นสุดในการประชุม" }) + dateEnd: Date; + + @Column({ nullable: true, comment: "ผลการพิจารณาของคณะกรรมการประเมินผลงานแต่ละคณะ" }) + result: string; + + @Column({ nullable: true, comment: "ระยะเวลาในการแก้ไขผลงาน" }) + duration: string; + + @ManyToMany(() => Evaluation, (evaluation) => evaluation.meetings) + evaluations: Evaluation[]; +} + +export class CreateMeeting { + @Column() + title: string; + + @Column() + round: string; + + @Column() + dateStart: Date; + + @Column() + dateEnd: Date; + + @Column() + result: string; + + @Column() + duration: string; +} +export type UpdateMeeting = Partial; diff --git a/src/entities/Salary.ts b/src/entities/Salary.ts new file mode 100644 index 0000000..062c3fd --- /dev/null +++ b/src/entities/Salary.ts @@ -0,0 +1,52 @@ +import { Entity, Column, ManyToOne, JoinColumn, OneToOne } from "typeorm"; +import { EntityBase } from "./base/Base"; +import { Evaluation } from "./Evaluation"; + +@Entity("salary") +export class Salary extends EntityBase { + @Column({ + comment: "Id การทำรายการระบบประเมิน", + length: 40, + default: "00000000-0000-0000-0000-000000000000", + }) + evaluationId: string; + + @Column({ nullable: true, type: "datetime", comment: "วัน เดือน ปี รับตำแหน่ง" }) + date: Date; + + @Column({ nullable: true, type: "double precision", comment: "เงินเดือน" }) + amount: number; + + @Column({ nullable: true, type: "double precision", comment: "เงินประจำตำแหน่ง" }) + positionSalaryAmount: number; + + @Column({ nullable: true, type: "double precision", comment: "เงินค่าตอบแทนรายเดือน" }) + mouthSalaryAmount: number; + + @Column({ nullable: true, comment: "ตำแหน่ง" }) + position: string; + + @Column({ nullable: true, comment: "เลขที่ตำแหน่ง" }) + posNo: string; + + @Column({ nullable: true, comment: "ตำแหน่ง (รายละเอียด)" }) + salaryClass: string; + + @Column({ nullable: true, comment: "เอกสารอ้างอิง" }) + salaryRef: string; + + @Column({ nullable: true, comment: "เอกสารอ้างอิง (เลขที่คำสั่ง)" }) + refCommandNo: string; + + @Column({ nullable: true, type: "datetime", comment: "เอกสารอ้างอิง (ลงวันที่)" }) + refCommandDate: Date; + + @Column({ nullable: true, comment: "ประเภทตำแหน่งกรณีพิเศษ" }) + salaryStatus: string; + + @ManyToOne(() => Evaluation, (Evaluation) => Evaluation.salaries) + @JoinColumn({ name: "evaluationId" }) + evaluation: Evaluation; +} + +export type UpdateSalary = Partial; diff --git a/src/entities/Training.ts b/src/entities/Training.ts new file mode 100644 index 0000000..70d5afe --- /dev/null +++ b/src/entities/Training.ts @@ -0,0 +1,49 @@ +import { Entity, Column, ManyToOne, JoinColumn, OneToOne } from "typeorm"; +import { EntityBase } from "./base/Base"; +import { Evaluation } from "./Evaluation"; + +@Entity("training") +export class Training extends EntityBase { + @Column({ + comment: "Id การทำรายการระบบประเมิน", + length: 40, + default: "00000000-0000-0000-0000-000000000000", + }) + evaluationId: string; + + @Column({ nullable: true, comment: "ชื่อโครงการ/หลักสูตรการฝึกอบรม" }) + name: string; + + @Column({ nullable: true, comment: "หัวข้อการฝึกอบรม/ดูงาน" }) + topic: string; + + @Column({ nullable: true, type: "datetime", comment: "วันเริ่มต้นการฝึกอบรม/ดูงาน" }) + startDate: Date; + + @Column({ nullable: true, type: "datetime", comment: "วันสิ้นสุดการฝึกอบรม/ดูงาน" }) + endDate: Date; + + @Column({ nullable: true, comment: "ปีที่อบรม (พ.ศ.)" }) + yearly: number; + + @Column({ nullable: true, comment: "สถานที่ฝึกอบรม/ดูงาน" }) + place: string; + + @Column({ nullable: true, comment: "รวมระยะเวลาในการฝึกอบรม/ดูงาน" }) + duration: string; + + @Column({ nullable: true, comment: "หน่วยงานที่รับผิดชอบจัดการฝึกอบรม/ดูงาน" }) + department: string; + + @Column({ nullable: true, comment: "เลขที่คำสั่ง/เลขที่หนังสืออนุมัติ" }) + numberOrder: string; + + @Column({ nullable: true, type: "datetime", comment: "คำสั่งลงวันที่/หนังสืออนุมัติลงวันที่" }) + dateOrder: Date; + + @ManyToOne(() => Evaluation, (Evaluation) => Evaluation.training) + @JoinColumn({ name: "evaluationId" }) + evaluation: Evaluation; +} + +export type UpdateTraining = Partial; diff --git a/src/entities/base/Base.ts b/src/entities/base/Base.ts new file mode 100644 index 0000000..0193458 --- /dev/null +++ b/src/entities/base/Base.ts @@ -0,0 +1,39 @@ +import { + Entity, + PrimaryGeneratedColumn, + Column, + CreateDateColumn, + UpdateDateColumn, +} from "typeorm"; + +@Entity() +export class EntityBase { + @PrimaryGeneratedColumn("uuid") + id: string; + + @CreateDateColumn({ comment: "สร้างข้อมูลเมื่อ" }) + createdAt: Date; + + @Column({ + comment: "User Id ที่สร้างข้อมูล", + length: 40, + default: "00000000-0000-0000-0000-000000000000", + }) + createdUserId: String; + + @UpdateDateColumn({ comment: "แก้ไขข้อมูลล่าสุดเมื่อ" }) + lastUpdatedAt: Date; + + @Column({ + comment: "User Id ที่แก้ไขข้อมูล", + length: 40, + default: "00000000-0000-0000-0000-000000000000", + }) + lastUpdateUserId: String; + + @Column({ comment: "ชื่อ User ที่สร้างข้อมูล", length: 200, default: "string" }) + createdFullName: String; + + @Column({ comment: "ชื่อ User ที่แก้ไขข้อมูลล่าสุด", length: 200, default: "string" }) + lastUpdateFullName: String; +} diff --git a/src/interfaces/call-api.ts b/src/interfaces/call-api.ts new file mode 100644 index 0000000..e1b202a --- /dev/null +++ b/src/interfaces/call-api.ts @@ -0,0 +1,84 @@ +import { Path } from "tsoa"; +import axios from "axios"; +import { addLogSequence } from "./utils"; + +class CallAPI { + //Get + public async GetData(request: any, @Path() path: any, log = true) { + const token = "Bearer " + request.headers.authorization.replace("Bearer ", ""); + const url = process.env.API_URL + path; + try { + const response = await axios.get(url, { + headers: { + Authorization: `${token}`, + "Content-Type": "application/json", + api_key: process.env.API_KEY, + }, + }); + if(log) addLogSequence(request, { + action: "request", + status: "success", + description: "connected", + request: { + method: "GET", + url: url, + response: JSON.stringify(response.data.result), + }, + }); + return response.data.result; + } catch (error) { + if(log) addLogSequence(request, { + action: "request", + status: "error", + description: "unconnected", + request: { + method: "GET", + url: url, + response: JSON.stringify(error), + }, + }); + throw error; + } + } + //Post + public async PostData(request: any, @Path() path: any, sendData: any) { + const token = "Bearer " + request.headers.authorization.replace("Bearer ", ""); + const url = process.env.API_URL + path; + try { + const response = await axios.post(url, sendData, { + headers: { + Authorization: `${token}`, + "Content-Type": "application/json", + api_key: process.env.API_KEY, + }, + }); + addLogSequence(request, { + action: "request", + status: "success", + description: "connected", + request: { + method: "POST", + url: url, + payload: JSON.stringify(sendData), + response: JSON.stringify(response.data.result), + }, + }); + return response.data.result; + } catch (error) { + addLogSequence(request, { + action: "request", + status: "error", + description: "unconnected", + request: { + method: "POST", + url: url, + payload: JSON.stringify(sendData), + response: JSON.stringify(error), + }, + }); + throw error; + } + } +} + +export default CallAPI; diff --git a/src/interfaces/extension.ts b/src/interfaces/extension.ts new file mode 100644 index 0000000..9518f2b --- /dev/null +++ b/src/interfaces/extension.ts @@ -0,0 +1,152 @@ +class Extension { + public static ToThaiMonth(value: number) { + switch (value) { + case 1: + return "มกราคม"; + case 2: + return "กุมภาพันธ์"; + case 3: + return "มีนาคม"; + case 4: + return "เมษายน"; + case 5: + return "พฤษภาคม"; + case 6: + return "มิถุนายน"; + case 7: + return "กรกฎาคม"; + case 8: + return "สิงหาคม"; + case 9: + return "กันยายน"; + case 10: + return "ตุลาคม"; + case 11: + return "พฤศจิกายน"; + case 12: + return "ธันวาคม"; + default: + return ""; + } + } + + public static ToThaiShortMonth(value: number) { + switch (value) { + case 1: + return "ม.ค."; + case 2: + return "ก.พ."; + case 3: + return "มี.ค."; + case 4: + return "เม.ย."; + case 5: + return "พ.ค."; + case 6: + return "มิ.ย."; + case 7: + return "ก.ค."; + case 8: + return "ส.ค."; + case 9: + return "ก.ย."; + case 10: + return "ต.ค."; + case 11: + return "พ.ย."; + case 12: + return "ธ.ค."; + default: + return ""; + } + } + + public static ToThaiYear(value: number) { + if (value < 2400) return value + 543; + else return value; + } + + public static ToCeYear(value: number) { + if (value >= 2400) return value - 543; + else return value; + } + + public static ToThaiNumber(value: string) { + let arabicNumbers = "0123456789"; + let thaiNumbers = "๐๑๒๓๔๕๖๗๘๙"; + let result = ""; + for (let digit of value) { + let index = arabicNumbers.indexOf(digit); + if (index >= 0) { + result += thaiNumbers[index]; + } else { + result += digit; + } + } + return result; + } + + public static ToThaiFullDate(value: Date) { + let yy = value.getFullYear() < 2400 ? value.getFullYear() + 543 : value.getFullYear(); + return ( + "วันที่ " + + value.getDate() + + " เดือน " + + Extension.ToThaiMonth(value.getMonth() + 1) + + " พ.ศ. " + + yy + ); + } + + public static ToThaiFullDate2(value: Date) { + let yy = value.getFullYear() < 2400 ? value.getFullYear() + 543 : value.getFullYear(); + return value.getDate() + " " + Extension.ToThaiMonth(value.getMonth() + 1) + " " + yy; + } + + public static ToThaiFullDate3(value: Date) { + let yy = value.getFullYear() < 2400 ? value.getFullYear() + 543 : value.getFullYear(); + return value.getDate() + " เดือน " + Extension.ToThaiMonth(value.getMonth() + 1) + " พ.ศ. " + yy; + } + + public static ToThaiShortDate(value: Date) { + let yy = value.getFullYear() < 2400 ? value.getFullYear() + 543 : value.getFullYear(); + return ( + "วันที่ " + + value.getDate() + + " " + + Extension.ToThaiShortMonth(value.getMonth() + 1) + + " " + + yy.toString().slice(-2) + ); + } + + public static ToThaiShortDate_noPrefix(value: Date) { + let yy = value.getFullYear() < 2400 ? value.getFullYear() + 543 : value.getFullYear(); + return ( + value.getDate() + + " " + + Extension.ToThaiShortMonth(value.getMonth() + 1) + + " " + + yy.toString().slice(-2) + ); + } + + public static ToThaiShortDate_monthYear(value: Date) { + let yy = value.getFullYear() < 2400 ? value.getFullYear() + 543 : value.getFullYear(); + return ( + value.getDate() + " เดือน " + Extension.ToThaiMonth(value.getMonth() + 1) + " พ.ศ. " + yy + ); + } + + public static sumObjectValues(array: any, propertyName: any) { + let sum = 0; + for (let i = 0; i < array.length; i++) { + if (array[i][propertyName] !== undefined) { + sum += array[i][propertyName]; + } + } + return sum; + } +} + +export default Extension; diff --git a/src/interfaces/http-error.ts b/src/interfaces/http-error.ts new file mode 100644 index 0000000..5d396e2 --- /dev/null +++ b/src/interfaces/http-error.ts @@ -0,0 +1,19 @@ +import HttpStatus from "./http-status"; + +class HttpError extends Error { + /** + * HTTP Status Code + */ + status: HttpStatus; + message: string; + + constructor(status: HttpStatus, message: string) { + super(message); + + this.name = "HttpError"; + this.status = status; + this.message = message; + } +} + +export default HttpError; diff --git a/src/interfaces/http-status.ts b/src/interfaces/http-status.ts new file mode 100644 index 0000000..291446f --- /dev/null +++ b/src/interfaces/http-status.ts @@ -0,0 +1,380 @@ +/** + * Hypertext Transfer Protocol (HTTP) response status codes. + * @see {@link https://en.wikipedia.org/wiki/List_of_HTTP_status_codes} + */ +enum HttpStatus { + /** + * The server has received the request headers and the client should proceed to send the request body + * (in the case of a request for which a body needs to be sent; for example, a POST request). + * Sending a large request body to a server after a request has been rejected for inappropriate headers would be inefficient. + * To have a server check the request's headers, a client must send Expect: 100-continue as a header in its initial request + * and receive a 100 Continue status code in response before sending the body. The response 417 Expectation Failed indicates the request should not be continued. + */ + CONTINUE = 100, + + /** + * The requester has asked the server to switch protocols and the server has agreed to do so. + */ + SWITCHING_PROTOCOLS = 101, + + /** + * A WebDAV request may contain many sub-requests involving file operations, requiring a long time to complete the request. + * This code indicates that the server has received and is processing the request, but no response is available yet. + * This prevents the client from timing out and assuming the request was lost. + */ + PROCESSING = 102, + + /** + * Standard response for successful HTTP requests. + * The actual response will depend on the request method used. + * In a GET request, the response will contain an entity corresponding to the requested resource. + * In a POST request, the response will contain an entity describing or containing the result of the action. + */ + OK = 200, + + /** + * The request has been fulfilled, resulting in the creation of a new resource. + */ + CREATED = 201, + + /** + * The request has been accepted for processing, but the processing has not been completed. + * The request might or might not be eventually acted upon, and may be disallowed when processing occurs. + */ + ACCEPTED = 202, + + /** + * SINCE HTTP/1.1 + * The server is a transforming proxy that received a 200 OK from its origin, + * but is returning a modified version of the origin's response. + */ + NON_AUTHORITATIVE_INFORMATION = 203, + + /** + * The server successfully processed the request and is not returning any content. + */ + NO_CONTENT = 204, + + /** + * The server successfully processed the request, but is not returning any content. + * Unlike a 204 response, this response requires that the requester reset the document view. + */ + RESET_CONTENT = 205, + + /** + * The server is delivering only part of the resource (byte serving) due to a range header sent by the client. + * The range header is used by HTTP clients to enable resuming of interrupted downloads, + * or split a download into multiple simultaneous streams. + */ + PARTIAL_CONTENT = 206, + + /** + * The message body that follows is an XML message and can contain a number of separate response codes, + * depending on how many sub-requests were made. + */ + MULTI_STATUS = 207, + + /** + * The members of a DAV binding have already been enumerated in a preceding part of the (multistatus) response, + * and are not being included again. + */ + ALREADY_REPORTED = 208, + + /** + * The server has fulfilled a request for the resource, + * and the response is a representation of the result of one or more instance-manipulations applied to the current instance. + */ + IM_USED = 226, + + /** + * Indicates multiple options for the resource from which the client may choose (via agent-driven content negotiation). + * For example, this code could be used to present multiple video format options, + * to list files with different filename extensions, or to suggest word-sense disambiguation. + */ + MULTIPLE_CHOICES = 300, + + /** + * This and all future requests should be directed to the given URI. + */ + MOVED_PERMANENTLY = 301, + + /** + * This is an example of industry practice contradicting the standard. + * The HTTP/1.0 specification (RFC 1945) required the client to perform a temporary redirect + * (the original describing phrase was "Moved Temporarily"), but popular browsers implemented 302 + * with the functionality of a 303 See Other. Therefore, HTTP/1.1 added status codes 303 and 307 + * to distinguish between the two behaviours. However, some Web applications and frameworks + * use the 302 status code as if it were the 303. + */ + FOUND = 302, + + /** + * SINCE HTTP/1.1 + * The response to the request can be found under another URI using a GET method. + * When received in response to a POST (or PUT/DELETE), the client should presume that + * the server has received the data and should issue a redirect with a separate GET message. + */ + SEE_OTHER = 303, + + /** + * Indicates that the resource has not been modified since the version specified by the request headers If-Modified-Since or If-None-Match. + * In such case, there is no need to retransmit the resource since the client still has a previously-downloaded copy. + */ + NOT_MODIFIED = 304, + + /** + * SINCE HTTP/1.1 + * The requested resource is available only through a proxy, the address for which is provided in the response. + * Many HTTP clients (such as Mozilla and Internet Explorer) do not correctly handle responses with this status code, primarily for security reasons. + */ + USE_PROXY = 305, + + /** + * No longer used. Originally meant "Subsequent requests should use the specified proxy." + */ + SWITCH_PROXY = 306, + + /** + * SINCE HTTP/1.1 + * In this case, the request should be repeated with another URI; however, future requests should still use the original URI. + * In contrast to how 302 was historically implemented, the request method is not allowed to be changed when reissuing the original request. + * For example, a POST request should be repeated using another POST request. + */ + TEMPORARY_REDIRECT = 307, + + /** + * The request and all future requests should be repeated using another URI. + * 307 and 308 parallel the behaviors of 302 and 301, but do not allow the HTTP method to change. + * So, for example, submitting a form to a permanently redirected resource may continue smoothly. + */ + PERMANENT_REDIRECT = 308, + + /** + * The server cannot or will not process the request due to an apparent client error + * (e.g., malformed request syntax, too large size, invalid request message framing, or deceptive request routing). + */ + BAD_REQUEST = 400, + + /** + * Similar to 403 Forbidden, but specifically for use when authentication is required and has failed or has not yet + * been provided. The response must include a WWW-Authenticate header field containing a challenge applicable to the + * requested resource. See Basic access authentication and Digest access authentication. 401 semantically means + * "unauthenticated",i.e. the user does not have the necessary credentials. + */ + UNAUTHORIZED = 401, + + /** + * Reserved for future use. The original intention was that this code might be used as part of some form of digital + * cash or micro payment scheme, but that has not happened, and this code is not usually used. + * Google Developers API uses this status if a particular developer has exceeded the daily limit on requests. + */ + PAYMENT_REQUIRED = 402, + + /** + * The request was valid, but the server is refusing action. + * The user might not have the necessary permissions for a resource. + */ + FORBIDDEN = 403, + + /** + * The requested resource could not be found but may be available in the future. + * Subsequent requests by the client are permissible. + */ + NOT_FOUND = 404, + + /** + * A request method is not supported for the requested resource; + * for example, a GET request on a form that requires data to be presented via POST, or a PUT request on a read-only resource. + */ + METHOD_NOT_ALLOWED = 405, + + /** + * The requested resource is capable of generating only content not acceptable according to the Accept headers sent in the request. + */ + NOT_ACCEPTABLE = 406, + + /** + * The client must first authenticate itself with the proxy. + */ + PROXY_AUTHENTICATION_REQUIRED = 407, + + /** + * The server timed out waiting for the request. + * According to HTTP specifications: + * "The client did not produce a request within the time that the server was prepared to wait. The client MAY repeat the request without modifications at any later time." + */ + REQUEST_TIMEOUT = 408, + + /** + * Indicates that the request could not be processed because of conflict in the request, + * such as an edit conflict between multiple simultaneous updates. + */ + CONFLICT = 409, + + /** + * Indicates that the resource requested is no longer available and will not be available again. + * This should be used when a resource has been intentionally removed and the resource should be purged. + * Upon receiving a 410 status code, the client should not request the resource in the future. + * Clients such as search engines should remove the resource from their indices. + * Most use cases do not require clients and search engines to purge the resource, and a "404 Not Found" may be used instead. + */ + GONE = 410, + + /** + * The request did not specify the length of its content, which is required by the requested resource. + */ + LENGTH_REQUIRED = 411, + + /** + * The server does not meet one of the preconditions that the requester put on the request. + */ + PRECONDITION_FAILED = 412, + + /** + * The request is larger than the server is willing or able to process. Previously called "Request Entity Too Large". + */ + PAYLOAD_TOO_LARGE = 413, + + /** + * The URI provided was too long for the server to process. Often the result of too much data being encoded as a query-string of a GET request, + * in which case it should be converted to a POST request. + * Called "Request-URI Too Long" previously. + */ + URI_TOO_LONG = 414, + + /** + * The request entity has a media type which the server or resource does not support. + * For example, the client uploads an image as image/svg+xml, but the server requires that images use a different format. + */ + UNSUPPORTED_MEDIA_TYPE = 415, + + /** + * The client has asked for a portion of the file (byte serving), but the server cannot supply that portion. + * For example, if the client asked for a part of the file that lies beyond the end of the file. + * Called "Requested Range Not Satisfiable" previously. + */ + RANGE_NOT_SATISFIABLE = 416, + + /** + * The server cannot meet the requirements of the Expect request-header field. + */ + EXPECTATION_FAILED = 417, + + /** + * This code was defined in 1998 as one of the traditional IETF April Fools' jokes, in RFC 2324, Hyper Text Coffee Pot Control Protocol, + * and is not expected to be implemented by actual HTTP servers. The RFC specifies this code should be returned by + * teapots requested to brew coffee. This HTTP status is used as an Easter egg in some websites, including Google.com. + */ + I_AM_A_TEAPOT = 418, + + /** + * The request was directed at a server that is not able to produce a response (for example because a connection reuse). + */ + MISDIRECTED_REQUEST = 421, + + /** + * The request was well-formed but was unable to be followed due to semantic errors. + */ + UNPROCESSABLE_ENTITY = 422, + + /** + * The resource that is being accessed is locked. + */ + LOCKED = 423, + + /** + * The request failed due to failure of a previous request (e.g., a PROPPATCH). + */ + FAILED_DEPENDENCY = 424, + + /** + * The client should switch to a different protocol such as TLS/1.0, given in the Upgrade header field. + */ + UPGRADE_REQUIRED = 426, + + /** + * The origin server requires the request to be conditional. + * Intended to prevent "the 'lost update' problem, where a client + * GETs a resource's state, modifies it, and PUTs it back to the server, + * when meanwhile a third party has modified the state on the server, leading to a conflict." + */ + PRECONDITION_REQUIRED = 428, + + /** + * The user has sent too many requests in a given amount of time. Intended for use with rate-limiting schemes. + */ + TOO_MANY_REQUESTS = 429, + + /** + * The server is unwilling to process the request because either an individual header field, + * or all the header fields collectively, are too large. + */ + REQUEST_HEADER_FIELDS_TOO_LARGE = 431, + + /** + * A server operator has received a legal demand to deny access to a resource or to a set of resources + * that includes the requested resource. The code 451 was chosen as a reference to the novel Fahrenheit 451. + */ + UNAVAILABLE_FOR_LEGAL_REASONS = 451, + + /** + * A generic error message, given when an unexpected condition was encountered and no more specific message is suitable. + */ + INTERNAL_SERVER_ERROR = 500, + + /** + * The server either does not recognize the request method, or it lacks the ability to fulfill the request. + * Usually this implies future availability (e.g., a new feature of a web-service API). + */ + NOT_IMPLEMENTED = 501, + + /** + * The server was acting as a gateway or proxy and received an invalid response from the upstream server. + */ + BAD_GATEWAY = 502, + + /** + * The server is currently unavailable (because it is overloaded or down for maintenance). + * Generally, this is a temporary state. + */ + SERVICE_UNAVAILABLE = 503, + + /** + * The server was acting as a gateway or proxy and did not receive a timely response from the upstream server. + */ + GATEWAY_TIMEOUT = 504, + + /** + * The server does not support the HTTP protocol version used in the request + */ + HTTP_VERSION_NOT_SUPPORTED = 505, + + /** + * Transparent content negotiation for the request results in a circular reference. + */ + VARIANT_ALSO_NEGOTIATES = 506, + + /** + * The server is unable to store the representation needed to complete the request. + */ + INSUFFICIENT_STORAGE = 507, + + /** + * The server detected an infinite loop while processing the request. + */ + LOOP_DETECTED = 508, + + /** + * Further extensions to the request are required for the server to fulfill it. + */ + NOT_EXTENDED = 510, + + /** + * The client needs to authenticate to gain network access. + * Intended for use by intercepting proxies used to control access to the network (e.g., "captive portals" used + * to require agreement to Terms of Service before granting full Internet access via a Wi-Fi hotspot). + */ + NETWORK_AUTHENTICATION_REQUIRED = 511, +} + +export default HttpStatus; diff --git a/src/interfaces/http-success.ts b/src/interfaces/http-success.ts new file mode 100644 index 0000000..3d931f6 --- /dev/null +++ b/src/interfaces/http-success.ts @@ -0,0 +1,19 @@ +import { RequestWithUser } from "../middlewares/user"; +import HttpStatus from "./http-status"; +import { addLogSequence } from "./utils"; + +class HttpSuccess { + /** + * HTTP Status Code + */ + status: HttpStatus; + message: string; + result?: any; + + constructor(result?: any) { + this.status = HttpStatus.OK; + this.message = "สำเร็จ"; + this.result = result; + } +} +export default HttpSuccess; diff --git a/src/interfaces/permission.ts b/src/interfaces/permission.ts new file mode 100644 index 0000000..6543518 --- /dev/null +++ b/src/interfaces/permission.ts @@ -0,0 +1,269 @@ +import axios from "axios"; +import { RequestWithUser } from "../middlewares/user"; +import CallAPI from "./call-api"; +import HttpError from "./http-error"; +import HttpStatus from "./http-status"; +import { promisify } from "util"; + +class CheckAuth { + private redis = require("redis"); + + public async Permission(req: RequestWithUser, system: string, action: string) { + if ( + req.headers.hasOwnProperty("api_key") && + req.headers["api_key"] && + req.headers["api_key"] == process.env.API_KEY + ) { + return null; + } + return await new CallAPI() + .GetData(req, "/org/permission") + .then((x) => { + let permission = false; + let role = x.roles.find((x: any) => x.authSysId == system); + if (!role) throw "ไม่มีสิทธิ์เข้าระบบ"; + if (role.attrOwnership == "OWNER") return "OWNER"; + if (action.trim().toLocaleUpperCase() == "CREATE") permission = role.attrIsCreate; + if (action.trim().toLocaleUpperCase() == "DELETE") permission = role.attrIsDelete; + if (action.trim().toLocaleUpperCase() == "GET") permission = role.attrIsGet; + if (action.trim().toLocaleUpperCase() == "LIST") permission = role.attrIsList; + if (action.trim().toLocaleUpperCase() == "UPDATE") permission = role.attrIsUpdate; + if (permission == false) throw "ไม่มีสิทธิ์ใช้งานระบบนี้"; + return role.attrPrivilege; + }) + .catch((x) => { + if (x.status != undefined) { + throw new HttpError(x.status, x.message); + } else { + throw new HttpError(HttpStatus.FORBIDDEN, x); + } + }); + } + public async PermissionOrg(req: RequestWithUser, system: string, action: string) { + if ( + req.headers.hasOwnProperty("api_key") && + req.headers["api_key"] && + req.headers["api_key"] == process.env.API_KEY + ) { + return { + root: null, + child1: null, + child2: null, + child3: null, + child4: null, + }; + } + return await new CallAPI() + .GetData(req, `/org/permission/org/${system}/${action}`) + .then(async (x) => { + let privilege = x.privilege; + + let data: any = { + root: [null], + child1: [null], + child2: [null], + child3: [null], + child4: [null], + privilege: [null], + }; + let node = 4; + if (x.orgChild1Id == null) { + node = 0; + } else if (x.orgChild2Id == null) { + node = 1; + } else if (x.orgChild3Id == null) { + node = 2; + } else if (x.orgChild4Id == null) { + node = 3; + } + if (privilege == "OWNER") { + data = { + root: null, + child1: null, + child2: null, + child3: null, + child4: null, + privilege: "OWNER", + }; + } else if (privilege == "ROOT") { + data = { + root: [x.orgRootId], + child1: null, + child2: null, + child3: null, + child4: null, + privilege: "ROOT", + }; + } else if (privilege == "CHILD") { + data = { + root: node >= 0 ? [x.orgRootId] : null, + child1: node >= 1 ? [x.orgChild1Id] : null, + child2: node >= 2 ? [x.orgChild2Id] : null, + child3: node >= 3 ? [x.orgChild3Id] : null, + child4: node >= 4 ? [x.orgChild4Id] : null, + privilege: "CHILD", + }; + } else if (privilege == "NORMAL") { + data = { + root: [x.orgRootId], + child1: [x.orgChild1Id], + child2: [x.orgChild2Id], + child3: [x.orgChild3Id], + child4: [x.orgChild4Id], + privilege: "NORMAL", + }; + } else if (privilege == "SPECIFIC") { + } + + return data; + }) + .catch((x) => { + if (x.status != undefined) { + throw new HttpError(x.status, x.message); + } else { + throw new HttpError(HttpStatus.FORBIDDEN, x); + } + }); + } + public async PermissionOrgByUser( + req: RequestWithUser, + system: string, + action: string, + profileId: string, + ) { + if ( + req.headers.hasOwnProperty("api_key") && + req.headers["api_key"] && + req.headers["api_key"] == process.env.API_KEY + ) { + return true; + } + return await new CallAPI() + .GetData(req, `/org/permission/user/${system}/${action}/${profileId}`) + .then(async (x) => { + let org = x.org; + + if (org.root != null) if (x.orgRootId != org.root[0]) throw "ไม่มีสิทธิ์เข้าถึงข้อมูล"; + if (org.child1 != null) + if (x.orgChild1Id != org.child1[0]) throw "ไม่มีสิทธิ์เข้าถึงข้อมูล"; + if (org.child2 != null) + if (x.orgChild2Id != org.child2[0]) throw "ไม่มีสิทธิ์เข้าถึงข้อมูล"; + if (org.child3 != null) + if (x.orgChild3Id != org.child3[0]) throw "ไม่มีสิทธิ์เข้าถึงข้อมูล"; + if (org.child4 != null) + if (x.orgChild4Id != org.child4[0]) throw "ไม่มีสิทธิ์เข้าถึงข้อมูล"; + + return true; + }) + .catch((x) => { + if (x.status != undefined) { + throw new HttpError(x.status, x.message); + } else { + throw new HttpError(HttpStatus.FORBIDDEN, x); + } + }); + } + public async Workflow(req: RequestWithUser, id: string, sysName: string) { + if ( + req.headers.hasOwnProperty("api_key") && + req.headers["api_key"] && + req.headers["api_key"] == process.env.API_KEY + ) { + return null; + } + return await new CallAPI() + .PostData(req, "/org/workflow/keycloak/isofficer", { + refId: id, + sysName: sysName, + }) + .then((x) => { + return true; + }) + .catch((x) => { + return false; + }); + } + public async checkOrg(token: any,keycloakId: string) { + const redisClient = await this.redis.createClient({ + host: process.env.REDIS_HOST, + port: process.env.REDIS_PORT, + }); + const getAsync = promisify(redisClient.get).bind(redisClient); + let reply = await getAsync("org_" + keycloakId); + if (reply != null) { + reply = JSON.parse(reply); + } else { + try { + const x = await new CallAPI().GetData( + { + headers: { authorization: token }, + }, + `/org/permission/checkOrg/${keycloakId}`, + false + ); + + const data = { + orgRootId: x.orgRootId, + orgChild1Id: x.orgChild1Id, + orgChild2Id: x.orgChild2Id, + orgChild3Id: x.orgChild3Id, + orgChild4Id: x.orgChild4Id, + }; + + return data; + } catch (error) { + console.error("Error calling API:", error); + throw error; + } + } + } + public async PermissionCreate(req: RequestWithUser, system: string) { + return await this.Permission(req, system, "CREATE"); + } + public async PermissionDelete(req: RequestWithUser, system: string) { + return await this.Permission(req, system, "DELETE"); + } + public async PermissionGet(req: RequestWithUser, system: string) { + return await this.Permission(req, system, "GET"); + } + public async PermissionList(req: RequestWithUser, system: string) { + return await this.Permission(req, system, "LIST"); + } + public async PermissionUpdate(req: RequestWithUser, system: string) { + return await this.Permission(req, system, "UPDATE"); + } + + public async PermissionOrgCreate(req: RequestWithUser, system: string) { + return await this.PermissionOrg(req, system, "CREATE"); + } + public async PermissionOrgDelete(req: RequestWithUser, system: string) { + return await this.PermissionOrg(req, system, "DELETE"); + } + public async PermissionOrgGet(req: RequestWithUser, system: string) { + return await this.PermissionOrg(req, system, "GET"); + } + public async PermissionOrgList(req: RequestWithUser, system: string) { + return await this.PermissionOrg(req, system, "LIST"); + } + public async PermissionOrgUpdate(req: RequestWithUser, system: string) { + return await this.PermissionOrg(req, system, "UPDATE"); + } + + public async PermissionOrgUserCreate(req: RequestWithUser, system: string, profileId: string) { + return await this.PermissionOrgByUser(req, system, "CREATE", profileId); + } + public async PermissionOrgUserDelete(req: RequestWithUser, system: string, profileId: string) { + return await this.PermissionOrgByUser(req, system, "DELETE", profileId); + } + public async PermissionOrgUserGet(req: RequestWithUser, system: string, profileId: string) { + return await this.PermissionOrgByUser(req, system, "GET", profileId); + } + public async PermissionOrgUserList(req: RequestWithUser, system: string, profileId: string) { + return await this.PermissionOrgByUser(req, system, "LIST", profileId); + } + public async PermissionOrgUserUpdate(req: RequestWithUser, system: string, profileId: string) { + return await this.PermissionOrgByUser(req, system, "UPDATE", profileId); + } +} + +export default CheckAuth; diff --git a/src/interfaces/storage-fs.ts b/src/interfaces/storage-fs.ts new file mode 100644 index 0000000..63d0769 --- /dev/null +++ b/src/interfaces/storage-fs.ts @@ -0,0 +1,39 @@ +export interface StorageFolder { + /** + * @prop Full path to this folder. It is used as key as there are no files or directories at the same location. + */ + pathname: string; + /** + * @prop Directory / Folder name. + */ + name: string; + + createdAt: string | Date; + createdBy: string | Date; +} + +export interface StorageFile { + /** + * @prop Full path to this folder. It is used as key as there are no files or directories at the same location. + */ + pathname: string; + + fileName: string; + fileSize: number; + fileType: string; + + title: string; + description: string; + author: string; + category: string[]; + keyword: string[]; + metadata: Record; + + path: string; + upload: boolean; + + updatedAt: string | Date; + updatedBy: string; + createdAt: string | Date; + createdBy: string; +} diff --git a/src/interfaces/utils.ts b/src/interfaces/utils.ts new file mode 100644 index 0000000..30035f0 --- /dev/null +++ b/src/interfaces/utils.ts @@ -0,0 +1,37 @@ +import { RequestWithUser } from "../middlewares/user"; + +export type DataDiff = { + before: any; + after: any; +}; + +export type LogSequence = { + action: string; + status: "success" | "error"; + description: string; + query?: any; + request?: { + method?: "GET" | "POST" | "PUT" | "DELETE" | "PATCH"; + url?: string; + payload?: string; + response?: string; + }; +}; + +export function setLogDataDiff(req: RequestWithUser, data: DataDiff) { + req.app.locals.logData.dataDiff = { + before: JSON.stringify(data.before), + after: JSON.stringify(data.after), + }; +} + +export function addLogSequence(req: RequestWithUser, data: LogSequence) { + if (!req?.app?.locals?.logData?.sequence) { + req.app.locals.logData.sequence = []; + } + req.app.locals.logData.sequence = req.app.locals.logData.sequence.concat(data); +} + +export function editLogSequence(req: RequestWithUser, index: number, data: LogSequence) { + req.app.locals.logData.sequence[index] = data; +} diff --git a/src/middlewares/1707895706666-start.ts b/src/middlewares/1707895706666-start.ts new file mode 100644 index 0000000..27e9c2a --- /dev/null +++ b/src/middlewares/1707895706666-start.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class Start1707895706666 implements MigrationInterface { + name = 'Start1707895706666' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE \`entity_base\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`DROP TABLE \`entity_base\``); + } + +} diff --git a/src/middlewares/auth.ts b/src/middlewares/auth.ts new file mode 100644 index 0000000..de43a0c --- /dev/null +++ b/src/middlewares/auth.ts @@ -0,0 +1,88 @@ +import * as express from "express"; +import { createDecoder, createVerifier } from "fast-jwt"; + +import HttpError from "../interfaces/http-error"; +import HttpStatus from "../interfaces/http-status"; +import { addLogSequence } from "../interfaces/utils"; +import { RequestWithUser } from "./user"; + +if (!process.env.AUTH_PUBLIC_KEY && !process.env.AUTH_REALM_URL) { + throw new Error("Require keycloak AUTH_PUBLIC_KEY or AUTH_REALM_URL."); +} +if (process.env.AUTH_PUBLIC_KEY && process.env.AUTH_REALM_URL && !process.env.AUTH_PREFERRED_MODE) { + throw new Error( + "AUTH_PREFFERRED must be specified if AUTH_PUBLIC_KEY and AUTH_REALM_URL is provided.", + ); +} + +const jwtVerify = createVerifier({ + key: async () => { + return `-----BEGIN PUBLIC KEY-----\n${process.env.AUTH_PUBLIC_KEY}\n-----END PUBLIC KEY-----`; + }, +}); + +const jwtDecode = createDecoder(); + +export async function expressAuthentication( + request: RequestWithUser, + securityName: string, + _scopes?: string[], +) { + if (process.env.NODE_ENV !== "production" && process.env.AUTH_BYPASS) { + return { preferred_username: "bypassed" }; + } + + if (securityName !== "bearerAuth") throw new Error("ไม่ทราบวิธีการยืนยันตัวตน"); + + const token = request.headers["authorization"]?.includes("Bearer ") + ? request.headers["authorization"].split(" ")[1] + : request.headers["authorization"]; + + if (!token) throw new HttpError(HttpStatus.UNAUTHORIZED, "ไม่พบข้อมูลสำหรับยืนยันตัวตน"); + + let payload: Record = {}; + + switch (process.env.AUTH_PREFERRED_MODE) { + case "online": + payload = await verifyOnline(token); + break; + case "offline": + payload = await verifyOffline(token); + break; + default: + if (process.env.AUTH_REALM_URL) payload = await verifyOnline(token); + if (process.env.AUTH_PUBLIC_KEY) payload = await verifyOffline(token); + break; + } + if (!request.app.locals.logData) { + request.app.locals.logData = {}; + } + + // addLogSequence(request, { + // action: "database", + // status: "success", + // description: "Query Data.", + // }); + request.app.locals.logData.userId = payload.sub; + request.app.locals.logData.userName = payload.name; + request.app.locals.logData.user = payload.preferred_username; + + return payload; +} + +async function verifyOffline(token: string) { + const payload = await jwtVerify(token).catch((_) => null); + if (!payload) throw new HttpError(HttpStatus.UNAUTHORIZED, "ไม่สามารถยืนยันตัวตนได้"); + return payload; +} + +async function verifyOnline(token: string) { + const res = await fetch(`${process.env.AUTH_REALM_URL}/protocol/openid-connect/userinfo`, { + headers: { authorization: `Bearer ${token}` }, + }).catch((e) => console.error(e)); + + if (!res) throw new Error("ไม่สามารถเข้าถึงระบบยืนยันตัวตน"); + if (!res.ok) throw new HttpError(HttpStatus.UNAUTHORIZED, "ไม่สามารถยืนยันตัวตนได้"); + + return await jwtDecode(token); +} diff --git a/src/middlewares/error.ts b/src/middlewares/error.ts new file mode 100644 index 0000000..f8d0b56 --- /dev/null +++ b/src/middlewares/error.ts @@ -0,0 +1,36 @@ +import { NextFunction, Request, Response } from "express"; +import HttpError from "../interfaces/http-error"; +import HttpStatus from "../interfaces/http-status"; +import { ValidateError } from "tsoa"; + +function error(error: Error, _req: Request, res: Response, _next: NextFunction) { + const logData = _req.app.locals.logData.sequence?.at(-1); + if (logData) { + logData.status = "error"; + logData.description = error.message; + } + + if (error instanceof HttpError) { + return res.status(error.status).json({ + status: error.status, + message: error.message, + }); + } + + if (error instanceof ValidateError) { + return res.status(error.status).json({ + status: HttpStatus.UNPROCESSABLE_ENTITY, + message: "Validation error(s).", + detail: error.fields, + }); + } + + console.error("Exception Caught:" + error); + + return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ + status: HttpStatus.INTERNAL_SERVER_ERROR, + message: error.message, + }); +} + +export default error; diff --git a/src/middlewares/logs.ts b/src/middlewares/logs.ts new file mode 100644 index 0000000..fa92f69 --- /dev/null +++ b/src/middlewares/logs.ts @@ -0,0 +1,80 @@ +import { NextFunction, Request, Response } from "express"; +import { Client } from "@elastic/elasticsearch"; +import permission from "../interfaces/permission"; + +if (!process.env.ELASTICSEARCH_INDEX) { + throw new Error("Require ELASTICSEARCH_INDEX to store log."); +} + +const ELASTICSEARCH_INDEX = process.env.ELASTICSEARCH_INDEX; + +const LOG_LEVEL_MAP: Record = { + debug: 4, + info: 3, + warning: 2, + error: 1, + none: 0, +}; + +const elasticsearch = new Client({ + node: `${process.env.ELASTICSEARCH_PROTOCOL}://${process.env.ELASTICSEARCH_HOST}:${process.env.ELASTICSEARCH_PORT}`, +}); + +async function logMiddleware(req: Request, res: Response, next: NextFunction) { + if (!req.url.startsWith("/api/")) return next(); + + let data: any; + + const originalJson = res.json; + + res.json = function (v: any) { + data = v; + return originalJson.call(this, v); + }; + + const timestamp = new Date().toISOString(); + const start = performance.now(); + + req.app.locals.logData = {}; + + res.on("finish", async () => { + if (!req.url.startsWith("/api/")) return; + + const level = LOG_LEVEL_MAP[process.env.LOG_LEVEL ?? "debug"] || 4; + + if (level === 1 && res.statusCode < 500) return; + if (level === 2 && res.statusCode < 400) return; + if (level === 3 && res.statusCode < 200) return; + let token: any; + token = req.headers['authorization'] + + const rootId = await new permission().checkOrg(token,req.app.locals.logData.userId); + + const obj = { + logType: res.statusCode >= 500 ? "error" : res.statusCode >= 400 ? "warning" : "info", + ip: req.ip, + rootId: rootId?rootId.orgRootId:null, + systemName: "evaluation", + startTimeStamp: timestamp, + endTimeStamp: new Date().toISOString(), + processTime: performance.now() - start, + host: req.hostname, + method: req.method, + endpoint: req.url, + responseCode: String(res.statusCode === 304 ? 200 : res.statusCode), + responseDescription: data?.message, + input: (level === 4 && JSON.stringify(req.body, null, 2)) || undefined, + output: (level === 4 && JSON.stringify(data, null, 2)) || undefined, + ...req.app.locals.logData, + }; + + elasticsearch.index({ + index: ELASTICSEARCH_INDEX, + document: obj, + }); + }); + + return next(); +} + +export default logMiddleware; diff --git a/src/middlewares/user.ts b/src/middlewares/user.ts new file mode 100644 index 0000000..a35cdc4 --- /dev/null +++ b/src/middlewares/user.ts @@ -0,0 +1,13 @@ +import type { Request } from "express"; + +export type RequestWithUser = Request & { + user: { + sub: string; + name: string; + given_name: string; + familiy_name: string; + preferred_username: string; + email: string; + role: string[]; + }; +}; diff --git a/src/migration/1703137040508-create_table_evaluation.ts b/src/migration/1703137040508-create_table_evaluation.ts new file mode 100644 index 0000000..24ebc5e --- /dev/null +++ b/src/migration/1703137040508-create_table_evaluation.ts @@ -0,0 +1,58 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class CreateTableEvaluation1703137040508 implements MigrationInterface { + name = 'CreateTableEvaluation1703137040508' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`CREATE TABLE \`evaluationlogs\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', \`evaluationId\` varchar(40) NOT NULL COMMENT 'Id การทำรายการระบบประเมิน' DEFAULT '00000000-0000-0000-0000-000000000000', \`step\` varchar(255) NOT NULL COMMENT 'ชื่อสถานะการประเมิน' DEFAULT 'string', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`education\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', \`evaluationId\` varchar(40) NOT NULL COMMENT 'Id การทำรายการระบบประเมิน' DEFAULT '00000000-0000-0000-0000-000000000000', \`educationLevel\` varchar(255) NOT NULL COMMENT 'ระดับศึกษา' DEFAULT 'string', \`institute\` varchar(255) NOT NULL COMMENT 'สถานศึกษา' DEFAULT 'string', \`isDate\` tinyint NOT NULL COMMENT 'ประเภทช่วงเวลาการศึกษา' DEFAULT 0, \`startDate\` datetime NOT NULL COMMENT 'ตั้งแต่', \`endDate\` datetime NOT NULL COMMENT 'EndDate', \`finishDate\` datetime NOT NULL COMMENT 'วันที่สำเร็จการศึกษา', \`isEducation\` tinyint NOT NULL COMMENT 'เป็นวุฒิศึกษาในตำแหน่ง' DEFAULT 0, \`degree\` varchar(255) NOT NULL COMMENT 'วุฒิการศึกษา' DEFAULT 'string', \`field\` varchar(255) NOT NULL COMMENT 'สาขาวิชา/ทาง' DEFAULT 'string', \`fundName\` varchar(255) NOT NULL COMMENT 'ทุน' DEFAULT 'string', \`gpa\` varchar(255) NOT NULL COMMENT 'เกรดเฉลี่ย' DEFAULT 'string', \`country\` varchar(255) NOT NULL COMMENT 'ประเทศ' DEFAULT 'string', \`other\` varchar(255) NOT NULL COMMENT 'ข้อมูลการติดต่อ' DEFAULT 'string', \`duration\` varchar(255) NOT NULL COMMENT 'ระยะเวลา' DEFAULT 'string', \`durationYear\` varchar(255) NOT NULL COMMENT 'ระยะเวลาหลักสูตร' DEFAULT 'string', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`certificate\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', \`evaluationId\` varchar(40) NOT NULL COMMENT 'Id การทำรายการระบบประเมิน' DEFAULT '00000000-0000-0000-0000-000000000000', \`statictep\` varchar(255) NOT NULL COMMENT 'ชื่อสถานะการประเมิน' DEFAULT 'string', \`certificateType\` varchar(255) NOT NULL COMMENT 'ชื่อใบอนุญาต' DEFAULT 'string', \`issuer\` varchar(255) NOT NULL COMMENT 'หน่วยงานผู้ออกใบอนุญาต' DEFAULT 'string', \`certificateNo\` varchar(255) NOT NULL COMMENT 'เลขที่ใบอนุญาต' DEFAULT 'string', \`issueDate\` datetime NOT NULL COMMENT 'วันที่ออกใบอนุญาต', \`expireDate\` datetime NOT NULL COMMENT 'วันที่หมดอายุ', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`salary\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', \`evaluationId\` varchar(40) NOT NULL COMMENT 'Id การทำรายการระบบประเมิน' DEFAULT '00000000-0000-0000-0000-000000000000', \`date\` datetime NOT NULL COMMENT 'วัน เดือน ปี รับตำแหน่ง', \`amount\` double NOT NULL COMMENT 'เงินเดือน' DEFAULT '0', \`positionSalaryAmount\` double NOT NULL COMMENT 'เงินประจำตำแหน่ง' DEFAULT '0', \`mouthSalaryAmount\` double NOT NULL COMMENT 'เงินค่าตอบแทนรายเดือน' DEFAULT '0', \`position\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง' DEFAULT 'string', \`posNo\` varchar(255) NOT NULL COMMENT 'เลขที่ตำแหน่ง' DEFAULT 'string', \`salaryClass\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง (รายละเอียด)' DEFAULT 'string', \`salaryRef\` varchar(255) NOT NULL COMMENT 'เอกสารอ้างอิง' DEFAULT 'string', \`refCommandNo\` varchar(255) NOT NULL COMMENT 'เอกสารอ้างอิง (เลขที่คำสั่ง)' DEFAULT 'string', \`refCommandDate\` datetime NOT NULL COMMENT 'เอกสารอ้างอิง (ลงวันที่)', \`salaryStatus\` varchar(255) NOT NULL COMMENT 'ประเภทตำแหน่งกรณีพิเศษ' DEFAULT 'string', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`training\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', \`evaluationId\` varchar(40) NOT NULL COMMENT 'Id การทำรายการระบบประเมิน' DEFAULT '00000000-0000-0000-0000-000000000000', \`name\` varchar(255) NOT NULL COMMENT 'ชื่อโครงการ/หลักสูตรการฝึกอบรม' DEFAULT 'string', \`topic\` varchar(255) NOT NULL COMMENT 'หัวข้อการฝึกอบรม/ดูงาน' DEFAULT 'string', \`startDate\` datetime NOT NULL COMMENT 'วันเริ่มต้นการฝึกอบรม/ดูงาน', \`endDate\` datetime NOT NULL COMMENT 'วันสิ้นสุดการฝึกอบรม/ดูงาน', \`yearly\` int NOT NULL COMMENT 'ปีที่อบรม (พ.ศ.)', \`place\` varchar(255) NOT NULL COMMENT 'สถานที่ฝึกอบรม/ดูงาน' DEFAULT 'string', \`duration\` varchar(255) NOT NULL COMMENT 'รวมระยะเวลาในการฝึกอบรม/ดูงาน' DEFAULT 'string', \`department\` varchar(255) NOT NULL COMMENT 'หน่วยงานที่รับผิดชอบจัดการฝึกอบรม/ดูงาน' DEFAULT 'string', \`numberOrder\` varchar(255) NOT NULL COMMENT 'เลขที่คำสั่ง/เลขที่หนังสืออนุมัติ' DEFAULT 'string', \`dateOrder\` datetime NOT NULL COMMENT 'คำสั่งลงวันที่/หนังสืออนุมัติลงวันที่', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`director\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', \`prefix\` varchar(255) NULL COMMENT 'คำนำหน้าชื่อ', \`firstName\` varchar(255) NULL COMMENT 'ชื่อ', \`lastName\` varchar(255) NULL COMMENT 'นามสกุล', \`phone\` varchar(255) NULL COMMENT 'เบอร์โทรศัพท์', \`email\` varchar(255) NULL COMMENT 'อีเมล', \`position\` varchar(255) NULL COMMENT 'ตำแหน่ง', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`meeting\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', \`tittle\` varchar(255) NULL COMMENT 'ชื่อการประชุม', \`round\` varchar(255) NULL COMMENT 'ครั้งที่', \`dateStart\` datetime NULL COMMENT 'วันเวลาเริ่มในการประชุม', \`dateEnd\` datetime NULL COMMENT 'วันเวลาสิ้นสุดในการประชุม', \`result\` varchar(255) NULL COMMENT 'ผลการพิจารณาของคณะกรรมการประเมินผลงานแต่ละคณะ', \`duration\` varchar(255) NULL COMMENT 'ระยะเวลาในการแก้ไขผลงาน', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`evaluation\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', \`userId\` varchar(40) NOT NULL COMMENT 'Id ชื่อผู้ใช้งาน' DEFAULT '00000000-0000-0000-0000-000000000000', \`citizenId\` varchar(13) NOT NULL COMMENT 'รหัสบัตรประชาชน' DEFAULT 'string', \`prefix\` varchar(255) NOT NULL COMMENT 'คำนำหน้า' DEFAULT 'string', \`fullName\` varchar(255) NOT NULL COMMENT 'ชื่อ นามสกุล' DEFAULT 'string', \`position\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง' DEFAULT 'string', \`oc\` varchar(255) NOT NULL COMMENT 'สังกัด' DEFAULT 'string', \`salary\` varchar(255) NOT NULL COMMENT 'เงินเดือนปัจจุบัน' DEFAULT 'string', \`positionLevel\` varchar(255) NOT NULL COMMENT 'ระดับปัจจุบัน' DEFAULT 'string', \`posNo\` varchar(255) NOT NULL COMMENT 'ตำแหน่งเลขที่' DEFAULT 'string', \`birthDate\` varchar(255) NOT NULL COMMENT 'วันเดือนปีเกิด' DEFAULT 'string', \`govAge\` varchar(255) NOT NULL COMMENT 'อายุราชการ' DEFAULT 'string', \`type\` varchar(255) NOT NULL COMMENT 'ประเภทแบบประเมิน' DEFAULT 'string', \`step\` varchar(255) NOT NULL COMMENT 'ชื่อสถานะการประเมิน' DEFAULT 'string', \`isEducationalQft\` tinyint NOT NULL COMMENT 'มีคุณวุฒิการศึกษา' DEFAULT 0, \`isGovermantServiceHtr\` tinyint NOT NULL COMMENT 'มีประวัติการรับราชการ' DEFAULT 0, \`isOperatingExp\` tinyint NOT NULL COMMENT 'มีประสบการณ์ในการปฏิบัติงาน' DEFAULT 0, \`isMinPeriodOfTenure\` tinyint NOT NULL COMMENT 'มีระยะเวลาขั้นต่ำในการดำรงตำแหน่งในสายงานที่ขอเข้ารับการคัดเลือก' DEFAULT 0, \`isHaveSpecificQft\` tinyint NOT NULL COMMENT 'มีคุณสมบัติตรงตามคุณสมบัติเฉพาะสำหรับตำแหน่งที่กำหนด ในมาตราฐานกำหนดตำแหน่ง' DEFAULT 0, \`isHaveProLicense\` tinyint NOT NULL COMMENT 'มีใบอนุญาตประกอบวิชาชีพของสายงานต่างๆ และ/หรือ คุณวุฒิเพิ่มเติมครบถ้วนตามที่ ก.ก. กำหนด (แพทย์พยาบาล วิศวกรโยธา สถาปนิก ฯลฯ)' DEFAULT 0, \`isHaveMinPeriodOrHoldPos\` tinyint NOT NULL COMMENT 'มีระยะเวลาขั้นต่ำในการดำรงตำแหน่งหรือเคยดำรงตำแหน่งในสายงานที่จะคัดเลือกตามคุณวุฒิของบุคคลและระดับตำแหน่งที่จะคัดเลือก' DEFAULT 0, \`reason\` varchar(255) NOT NULL COMMENT 'เหตุผล' DEFAULT 'string', \`experience\` varchar(255) NOT NULL COMMENT 'ประสบการณ์ในการปฏิบัติงาน' DEFAULT 'string', \`commanderFullname\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น' DEFAULT 'string', \`commanderPosition\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น' DEFAULT 'string', \`commanderAboveFullname\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ' DEFAULT 'string', \`commanderAbovePosition\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ' DEFAULT 'string', \`commanderFullnameDoc2\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)' DEFAULT 'string', \`commanderPositionDoc2\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)' DEFAULT 'string', \`commanderAboveFullnameDoc2\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)' DEFAULT 'string', \`commanderAbovePositionDoc2\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)' DEFAULT 'string', \`dateAnnounce\` datetime NULL COMMENT 'วันที่ประกาศบนเว็บไซต์', \`datePrepareDoc2\` datetime NULL COMMENT 'วันที่จัดเตรียมเอกสารเล่ม 2', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`assessment\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', \`evaluationId\` varchar(40) NOT NULL COMMENT 'Id การทำรายการระบบประเมิน' DEFAULT '00000000-0000-0000-0000-000000000000', \`date\` datetime NOT NULL COMMENT 'วันที่ได้รับ', \`point1Total\` double NOT NULL COMMENT 'ส่วนที่1 (คะแนน)' DEFAULT '0', \`point1\` double NOT NULL COMMENT 'ผลประเมินส่วนที่2 (คะแนน)' DEFAULT '0', \`point2Total\` double NOT NULL COMMENT 'ส่วนที่2 (คะแนน)' DEFAULT '0', \`point2\` double NOT NULL COMMENT 'ผลประเมินส่วนที่2 (คะแนน)' DEFAULT '0', \`pointSumTotal\` double NOT NULL COMMENT 'ผลรวม (คะแนน)' DEFAULT '0', \`pointSum\` double NOT NULL COMMENT 'ผลประเมินรวม (คะแนน)' DEFAULT '0', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`evaluation_directors_director\` (\`evaluationId\` varchar(36) NOT NULL, \`directorId\` varchar(36) NOT NULL, INDEX \`IDX_aee4e7f5076bf5ff10190ddb79\` (\`evaluationId\`), INDEX \`IDX_a1b902762a4a2410a10b672806\` (\`directorId\`), PRIMARY KEY (\`evaluationId\`, \`directorId\`)) ENGINE=InnoDB`); + await queryRunner.query(`CREATE TABLE \`evaluation_meetings_meeting\` (\`evaluationId\` varchar(36) NOT NULL, \`meetingId\` varchar(36) NOT NULL, INDEX \`IDX_396abde27455370a4fa1874fd0\` (\`evaluationId\`), INDEX \`IDX_364351e02ea95293db98488e87\` (\`meetingId\`), PRIMARY KEY (\`evaluationId\`, \`meetingId\`)) ENGINE=InnoDB`); + await queryRunner.query(`ALTER TABLE \`evaluationlogs\` ADD CONSTRAINT \`FK_99760b1a328db79620c0a99d9f2\` FOREIGN KEY (\`evaluationId\`) REFERENCES \`evaluation\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE \`education\` ADD CONSTRAINT \`FK_565e9dc1bc41ac99afa8369bac6\` FOREIGN KEY (\`evaluationId\`) REFERENCES \`evaluation\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE \`certificate\` ADD CONSTRAINT \`FK_78eaea88c74678b3453ecfaa589\` FOREIGN KEY (\`evaluationId\`) REFERENCES \`evaluation\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE \`salary\` ADD CONSTRAINT \`FK_8379066de3be10e3051f7b153bb\` FOREIGN KEY (\`evaluationId\`) REFERENCES \`evaluation\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE \`training\` ADD CONSTRAINT \`FK_44b061ad3c69ee5e213b0bf31e6\` FOREIGN KEY (\`evaluationId\`) REFERENCES \`evaluation\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE \`assessment\` ADD CONSTRAINT \`FK_6115226e85c042608b18ad03e08\` FOREIGN KEY (\`evaluationId\`) REFERENCES \`evaluation\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE \`evaluation_directors_director\` ADD CONSTRAINT \`FK_aee4e7f5076bf5ff10190ddb79b\` FOREIGN KEY (\`evaluationId\`) REFERENCES \`evaluation\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`); + await queryRunner.query(`ALTER TABLE \`evaluation_directors_director\` ADD CONSTRAINT \`FK_a1b902762a4a2410a10b6728065\` FOREIGN KEY (\`directorId\`) REFERENCES \`director\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + await queryRunner.query(`ALTER TABLE \`evaluation_meetings_meeting\` ADD CONSTRAINT \`FK_396abde27455370a4fa1874fd09\` FOREIGN KEY (\`evaluationId\`) REFERENCES \`evaluation\`(\`id\`) ON DELETE CASCADE ON UPDATE CASCADE`); + await queryRunner.query(`ALTER TABLE \`evaluation_meetings_meeting\` ADD CONSTRAINT \`FK_364351e02ea95293db98488e871\` FOREIGN KEY (\`meetingId\`) REFERENCES \`meeting\`(\`id\`) ON DELETE NO ACTION ON UPDATE NO ACTION`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`evaluation_meetings_meeting\` DROP FOREIGN KEY \`FK_364351e02ea95293db98488e871\``); + await queryRunner.query(`ALTER TABLE \`evaluation_meetings_meeting\` DROP FOREIGN KEY \`FK_396abde27455370a4fa1874fd09\``); + await queryRunner.query(`ALTER TABLE \`evaluation_directors_director\` DROP FOREIGN KEY \`FK_a1b902762a4a2410a10b6728065\``); + await queryRunner.query(`ALTER TABLE \`evaluation_directors_director\` DROP FOREIGN KEY \`FK_aee4e7f5076bf5ff10190ddb79b\``); + await queryRunner.query(`ALTER TABLE \`assessment\` DROP FOREIGN KEY \`FK_6115226e85c042608b18ad03e08\``); + await queryRunner.query(`ALTER TABLE \`training\` DROP FOREIGN KEY \`FK_44b061ad3c69ee5e213b0bf31e6\``); + await queryRunner.query(`ALTER TABLE \`salary\` DROP FOREIGN KEY \`FK_8379066de3be10e3051f7b153bb\``); + await queryRunner.query(`ALTER TABLE \`certificate\` DROP FOREIGN KEY \`FK_78eaea88c74678b3453ecfaa589\``); + await queryRunner.query(`ALTER TABLE \`education\` DROP FOREIGN KEY \`FK_565e9dc1bc41ac99afa8369bac6\``); + await queryRunner.query(`ALTER TABLE \`evaluationlogs\` DROP FOREIGN KEY \`FK_99760b1a328db79620c0a99d9f2\``); + await queryRunner.query(`DROP INDEX \`IDX_364351e02ea95293db98488e87\` ON \`evaluation_meetings_meeting\``); + await queryRunner.query(`DROP INDEX \`IDX_396abde27455370a4fa1874fd0\` ON \`evaluation_meetings_meeting\``); + await queryRunner.query(`DROP TABLE \`evaluation_meetings_meeting\``); + await queryRunner.query(`DROP INDEX \`IDX_a1b902762a4a2410a10b672806\` ON \`evaluation_directors_director\``); + await queryRunner.query(`DROP INDEX \`IDX_aee4e7f5076bf5ff10190ddb79\` ON \`evaluation_directors_director\``); + await queryRunner.query(`DROP TABLE \`evaluation_directors_director\``); + await queryRunner.query(`DROP TABLE \`assessment\``); + await queryRunner.query(`DROP TABLE \`evaluation\``); + await queryRunner.query(`DROP TABLE \`meeting\``); + await queryRunner.query(`DROP TABLE \`director\``); + await queryRunner.query(`DROP TABLE \`training\``); + await queryRunner.query(`DROP TABLE \`salary\``); + await queryRunner.query(`DROP TABLE \`certificate\``); + await queryRunner.query(`DROP TABLE \`education\``); + await queryRunner.query(`DROP TABLE \`evaluationlogs\``); + } + +} diff --git a/src/migration/1703317318791-update_table_evaluate_add_DatePrepareDoc2_3.ts b/src/migration/1703317318791-update_table_evaluate_add_DatePrepareDoc2_3.ts new file mode 100644 index 0000000..5fe6199 --- /dev/null +++ b/src/migration/1703317318791-update_table_evaluate_add_DatePrepareDoc2_3.ts @@ -0,0 +1,61 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateTableEvaluateAddDatePrepareDoc231703317318791 implements MigrationInterface { + name = "UpdateTableEvaluateAddDatePrepareDoc231703317318791"; + + public async up(queryRunner: QueryRunner): Promise { + // await queryRunner.query(`CREATE TABLE \`entity_base\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderFullname\` \`commanderFullname\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderPosition\` \`commanderPosition\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullname\` \`commanderAboveFullname\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePosition\` \`commanderAbovePosition\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderFullnameDoc2\` \`commanderFullnameDoc2\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderPositionDoc2\` \`commanderPositionDoc2\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullnameDoc2\` \`commanderAboveFullnameDoc2\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePositionDoc2\` \`commanderAbovePositionDoc2\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePositionDoc2\` \`commanderAbovePositionDoc2\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullnameDoc2\` \`commanderAboveFullnameDoc2\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderPositionDoc2\` \`commanderPositionDoc2\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderFullnameDoc2\` \`commanderFullnameDoc2\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePosition\` \`commanderAbovePosition\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullname\` \`commanderAboveFullname\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderPosition\` \`commanderPosition\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderFullname\` \`commanderFullname\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น' DEFAULT 'string'`, + ); + // await queryRunner.query(`DROP TABLE \`entity_base\``); + } +} diff --git a/src/migration/1703317358364-update_table_evaluate_add_DatePrepareDoc2_4.ts b/src/migration/1703317358364-update_table_evaluate_add_DatePrepareDoc2_4.ts new file mode 100644 index 0000000..70142d5 --- /dev/null +++ b/src/migration/1703317358364-update_table_evaluate_add_DatePrepareDoc2_4.ts @@ -0,0 +1,145 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateTableEvaluateAddDatePrepareDoc241703317358364 implements MigrationInterface { + name = "UpdateTableEvaluateAddDatePrepareDoc241703317358364"; + + public async up(queryRunner: QueryRunner): Promise { + // await queryRunner.query(`CREATE TABLE \`entity_base\` (\`id\` varchar(36) NOT NULL, \`createdAt\` datetime(6) NOT NULL COMMENT 'สร้างข้อมูลเมื่อ' DEFAULT CURRENT_TIMESTAMP(6), \`createdUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่สร้างข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`lastUpdatedAt\` datetime(6) NOT NULL COMMENT 'แก้ไขข้อมูลล่าสุดเมื่อ' DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6), \`lastUpdateUserId\` varchar(40) NOT NULL COMMENT 'User Id ที่แก้ไขข้อมูล' DEFAULT '00000000-0000-0000-0000-000000000000', \`createdFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่สร้างข้อมูล' DEFAULT 'string', \`lastUpdateFullName\` varchar(200) NOT NULL COMMENT 'ชื่อ User ที่แก้ไขข้อมูลล่าสุด' DEFAULT 'string', PRIMARY KEY (\`id\`)) ENGINE=InnoDB`); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`citizenId\` \`citizenId\` varchar(13) NOT NULL COMMENT 'รหัสบัตรประชาชน' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`prefix\` \`prefix\` varchar(255) NOT NULL COMMENT 'คำนำหน้า' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`fullName\` \`fullName\` varchar(255) NOT NULL COMMENT 'ชื่อ นามสกุล' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`position\` \`position\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`oc\` \`oc\` varchar(255) NOT NULL COMMENT 'สังกัด' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`salary\` \`salary\` varchar(255) NOT NULL COMMENT 'เงินเดือนปัจจุบัน' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`positionLevel\` \`positionLevel\` varchar(255) NOT NULL COMMENT 'ระดับปัจจุบัน' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`posNo\` \`posNo\` varchar(255) NOT NULL COMMENT 'ตำแหน่งเลขที่' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`birthDate\` \`birthDate\` varchar(255) NOT NULL COMMENT 'วันเดือนปีเกิด' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`govAge\` \`govAge\` varchar(255) NOT NULL COMMENT 'อายุราชการ' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`type\` \`type\` varchar(255) NOT NULL COMMENT 'ประเภทแบบประเมิน' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`step\` \`step\` varchar(255) NOT NULL COMMENT 'ชื่อสถานะการประเมิน' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`reason\` \`reason\` varchar(255) NOT NULL COMMENT 'เหตุผล' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`experience\` \`experience\` varchar(255) NOT NULL COMMENT 'ประสบการณ์ในการปฏิบัติงาน' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderFullname\` \`commanderFullname\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderPosition\` \`commanderPosition\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullname\` \`commanderAboveFullname\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePosition\` \`commanderAbovePosition\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderFullnameDoc2\` \`commanderFullnameDoc2\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderPositionDoc2\` \`commanderPositionDoc2\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullnameDoc2\` \`commanderAboveFullnameDoc2\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePositionDoc2\` \`commanderAbovePositionDoc2\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePositionDoc2\` \`commanderAbovePositionDoc2\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullnameDoc2\` \`commanderAboveFullnameDoc2\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderPositionDoc2\` \`commanderPositionDoc2\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderFullnameDoc2\` \`commanderFullnameDoc2\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePosition\` \`commanderAbovePosition\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullname\` \`commanderAboveFullname\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderPosition\` \`commanderPosition\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`commanderFullname\` \`commanderFullname\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`experience\` \`experience\` varchar(255) NOT NULL COMMENT 'ประสบการณ์ในการปฏิบัติงาน' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`reason\` \`reason\` varchar(255) NOT NULL COMMENT 'เหตุผล' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`step\` \`step\` varchar(255) NOT NULL COMMENT 'ชื่อสถานะการประเมิน' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`type\` \`type\` varchar(255) NOT NULL COMMENT 'ประเภทแบบประเมิน' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`govAge\` \`govAge\` varchar(255) NOT NULL COMMENT 'อายุราชการ' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`birthDate\` \`birthDate\` varchar(255) NOT NULL COMMENT 'วันเดือนปีเกิด' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`posNo\` \`posNo\` varchar(255) NOT NULL COMMENT 'ตำแหน่งเลขที่' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`positionLevel\` \`positionLevel\` varchar(255) NOT NULL COMMENT 'ระดับปัจจุบัน' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`salary\` \`salary\` varchar(255) NOT NULL COMMENT 'เงินเดือนปัจจุบัน' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`oc\` \`oc\` varchar(255) NOT NULL COMMENT 'สังกัด' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`position\` \`position\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`fullName\` \`fullName\` varchar(255) NOT NULL COMMENT 'ชื่อ นามสกุล' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`prefix\` \`prefix\` varchar(255) NOT NULL COMMENT 'คำนำหน้า' DEFAULT 'string'`, + ); + await queryRunner.query( + `ALTER TABLE \`evaluation\` CHANGE \`citizenId\` \`citizenId\` varchar(13) NOT NULL COMMENT 'รหัสบัตรประชาชน' DEFAULT 'string'`, + ); + // await queryRunner.query(`DROP TABLE \`entity_base\``); + } +} diff --git a/src/migration/1703326121795-update_table_evaluate_null_type.ts b/src/migration/1703326121795-update_table_evaluate_null_type.ts new file mode 100644 index 0000000..5f32203 --- /dev/null +++ b/src/migration/1703326121795-update_table_evaluate_null_type.ts @@ -0,0 +1,56 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateTableEvaluateNullType1703326121795 implements MigrationInterface { + name = 'UpdateTableEvaluateNullType1703326121795' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`citizenId\` \`citizenId\` varchar(13) NULL COMMENT 'รหัสบัตรประชาชน'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`prefix\` \`prefix\` varchar(255) NULL COMMENT 'คำนำหน้า'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`fullName\` \`fullName\` varchar(255) NULL COMMENT 'ชื่อ นามสกุล'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`position\` \`position\` varchar(255) NULL COMMENT 'ตำแหน่ง'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`oc\` \`oc\` varchar(255) NULL COMMENT 'สังกัด'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`salary\` \`salary\` varchar(255) NULL COMMENT 'เงินเดือนปัจจุบัน'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`positionLevel\` \`positionLevel\` varchar(255) NULL COMMENT 'ระดับปัจจุบัน'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`posNo\` \`posNo\` varchar(255) NULL COMMENT 'ตำแหน่งเลขที่'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`birthDate\` \`birthDate\` varchar(255) NULL COMMENT 'วันเดือนปีเกิด'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`govAge\` \`govAge\` varchar(255) NULL COMMENT 'อายุราชการ'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`type\` \`type\` varchar(255) NULL COMMENT 'ประเภทแบบประเมิน'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`step\` \`step\` varchar(255) NULL COMMENT 'ชื่อสถานะการประเมิน'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`reason\` \`reason\` varchar(255) NULL COMMENT 'เหตุผล'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`experience\` \`experience\` varchar(255) NULL COMMENT 'ประสบการณ์ในการปฏิบัติงาน'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderFullname\` \`commanderFullname\` varchar(255) NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderPosition\` \`commanderPosition\` varchar(255) NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullname\` \`commanderAboveFullname\` varchar(255) NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePosition\` \`commanderAbovePosition\` varchar(255) NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderFullnameDoc2\` \`commanderFullnameDoc2\` varchar(255) NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderPositionDoc2\` \`commanderPositionDoc2\` varchar(255) NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullnameDoc2\` \`commanderAboveFullnameDoc2\` varchar(255) NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePositionDoc2\` \`commanderAbovePositionDoc2\` varchar(255) NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)'`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePositionDoc2\` \`commanderAbovePositionDoc2\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullnameDoc2\` \`commanderAboveFullnameDoc2\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderPositionDoc2\` \`commanderPositionDoc2\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderFullnameDoc2\` \`commanderFullnameDoc2\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePosition\` \`commanderAbovePosition\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullname\` \`commanderAboveFullname\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderPosition\` \`commanderPosition\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderFullname\` \`commanderFullname\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`experience\` \`experience\` varchar(255) NOT NULL COMMENT 'ประสบการณ์ในการปฏิบัติงาน' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`reason\` \`reason\` varchar(255) NOT NULL COMMENT 'เหตุผล' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`step\` \`step\` varchar(255) NOT NULL COMMENT 'ชื่อสถานะการประเมิน' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`type\` \`type\` varchar(255) NOT NULL COMMENT 'ประเภทแบบประเมิน' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`govAge\` \`govAge\` varchar(255) NOT NULL COMMENT 'อายุราชการ' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`birthDate\` \`birthDate\` varchar(255) NOT NULL COMMENT 'วันเดือนปีเกิด' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`posNo\` \`posNo\` varchar(255) NOT NULL COMMENT 'ตำแหน่งเลขที่' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`positionLevel\` \`positionLevel\` varchar(255) NOT NULL COMMENT 'ระดับปัจจุบัน' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`salary\` \`salary\` varchar(255) NOT NULL COMMENT 'เงินเดือนปัจจุบัน' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`oc\` \`oc\` varchar(255) NOT NULL COMMENT 'สังกัด' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`position\` \`position\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`fullName\` \`fullName\` varchar(255) NOT NULL COMMENT 'ชื่อ นามสกุล' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`prefix\` \`prefix\` varchar(255) NOT NULL COMMENT 'คำนำหน้า' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`citizenId\` \`citizenId\` varchar(13) NOT NULL COMMENT 'รหัสบัตรประชาชน' DEFAULT ''`); + } + +} diff --git a/src/migration/1703326303281-update_table_evaluate_null_type1.ts b/src/migration/1703326303281-update_table_evaluate_null_type1.ts new file mode 100644 index 0000000..a7167e6 --- /dev/null +++ b/src/migration/1703326303281-update_table_evaluate_null_type1.ts @@ -0,0 +1,154 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateTableEvaluateNullType11703326303281 implements MigrationInterface { + name = 'UpdateTableEvaluateNullType11703326303281' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`educationLevel\` \`educationLevel\` varchar(255) NULL COMMENT 'ระดับศึกษา'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`institute\` \`institute\` varchar(255) NULL COMMENT 'สถานศึกษา'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`isDate\` \`isDate\` tinyint NULL COMMENT 'ประเภทช่วงเวลาการศึกษา'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`startDate\` \`startDate\` datetime NULL COMMENT 'ตั้งแต่'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`endDate\` \`endDate\` datetime NULL COMMENT 'EndDate'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`finishDate\` \`finishDate\` datetime NULL COMMENT 'วันที่สำเร็จการศึกษา'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`isEducation\` \`isEducation\` tinyint NULL COMMENT 'เป็นวุฒิศึกษาในตำแหน่ง'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`degree\` \`degree\` varchar(255) NULL COMMENT 'วุฒิการศึกษา'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`field\` \`field\` varchar(255) NULL COMMENT 'สาขาวิชา/ทาง'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`fundName\` \`fundName\` varchar(255) NULL COMMENT 'ทุน'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`gpa\` \`gpa\` varchar(255) NULL COMMENT 'เกรดเฉลี่ย'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`country\` \`country\` varchar(255) NULL COMMENT 'ประเทศ'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`other\` \`other\` varchar(255) NULL COMMENT 'ข้อมูลการติดต่อ'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`duration\` \`duration\` varchar(255) NULL COMMENT 'ระยะเวลา'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`durationYear\` \`durationYear\` varchar(255) NULL COMMENT 'ระยะเวลาหลักสูตร'`); + await queryRunner.query(`ALTER TABLE \`certificate\` CHANGE \`statictep\` \`statictep\` varchar(255) NULL COMMENT 'ชื่อสถานะการประเมิน'`); + await queryRunner.query(`ALTER TABLE \`certificate\` CHANGE \`certificateType\` \`certificateType\` varchar(255) NULL COMMENT 'ชื่อใบอนุญาต'`); + await queryRunner.query(`ALTER TABLE \`certificate\` CHANGE \`issuer\` \`issuer\` varchar(255) NULL COMMENT 'หน่วยงานผู้ออกใบอนุญาต'`); + await queryRunner.query(`ALTER TABLE \`certificate\` CHANGE \`certificateNo\` \`certificateNo\` varchar(255) NULL COMMENT 'เลขที่ใบอนุญาต'`); + await queryRunner.query(`ALTER TABLE \`certificate\` CHANGE \`issueDate\` \`issueDate\` datetime NULL COMMENT 'วันที่ออกใบอนุญาต'`); + await queryRunner.query(`ALTER TABLE \`certificate\` CHANGE \`expireDate\` \`expireDate\` datetime NULL COMMENT 'วันที่หมดอายุ'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`date\` \`date\` datetime NULL COMMENT 'วัน เดือน ปี รับตำแหน่ง'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`amount\` \`amount\` double NULL COMMENT 'เงินเดือน'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`positionSalaryAmount\` \`positionSalaryAmount\` double NULL COMMENT 'เงินประจำตำแหน่ง'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`mouthSalaryAmount\` \`mouthSalaryAmount\` double NULL COMMENT 'เงินค่าตอบแทนรายเดือน'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`position\` \`position\` varchar(255) NULL COMMENT 'ตำแหน่ง'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`posNo\` \`posNo\` varchar(255) NULL COMMENT 'เลขที่ตำแหน่ง'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`salaryClass\` \`salaryClass\` varchar(255) NULL COMMENT 'ตำแหน่ง (รายละเอียด)'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`salaryRef\` \`salaryRef\` varchar(255) NULL COMMENT 'เอกสารอ้างอิง'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`refCommandNo\` \`refCommandNo\` varchar(255) NULL COMMENT 'เอกสารอ้างอิง (เลขที่คำสั่ง)'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`refCommandDate\` \`refCommandDate\` datetime NULL COMMENT 'เอกสารอ้างอิง (ลงวันที่)'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`salaryStatus\` \`salaryStatus\` varchar(255) NULL COMMENT 'ประเภทตำแหน่งกรณีพิเศษ'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`name\` \`name\` varchar(255) NULL COMMENT 'ชื่อโครงการ/หลักสูตรการฝึกอบรม'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`topic\` \`topic\` varchar(255) NULL COMMENT 'หัวข้อการฝึกอบรม/ดูงาน'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`startDate\` \`startDate\` datetime NULL COMMENT 'วันเริ่มต้นการฝึกอบรม/ดูงาน'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`endDate\` \`endDate\` datetime NULL COMMENT 'วันสิ้นสุดการฝึกอบรม/ดูงาน'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`yearly\` \`yearly\` int NULL COMMENT 'ปีที่อบรม (พ.ศ.)'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`place\` \`place\` varchar(255) NULL COMMENT 'สถานที่ฝึกอบรม/ดูงาน'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`duration\` \`duration\` varchar(255) NULL COMMENT 'รวมระยะเวลาในการฝึกอบรม/ดูงาน'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`department\` \`department\` varchar(255) NULL COMMENT 'หน่วยงานที่รับผิดชอบจัดการฝึกอบรม/ดูงาน'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`numberOrder\` \`numberOrder\` varchar(255) NULL COMMENT 'เลขที่คำสั่ง/เลขที่หนังสืออนุมัติ'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`dateOrder\` \`dateOrder\` datetime NULL COMMENT 'คำสั่งลงวันที่/หนังสืออนุมัติลงวันที่'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`citizenId\` \`citizenId\` varchar(13) NULL COMMENT 'รหัสบัตรประชาชน'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`prefix\` \`prefix\` varchar(255) NULL COMMENT 'คำนำหน้า'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`fullName\` \`fullName\` varchar(255) NULL COMMENT 'ชื่อ นามสกุล'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`position\` \`position\` varchar(255) NULL COMMENT 'ตำแหน่ง'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`oc\` \`oc\` varchar(255) NULL COMMENT 'สังกัด'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`salary\` \`salary\` varchar(255) NULL COMMENT 'เงินเดือนปัจจุบัน'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`positionLevel\` \`positionLevel\` varchar(255) NULL COMMENT 'ระดับปัจจุบัน'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`posNo\` \`posNo\` varchar(255) NULL COMMENT 'ตำแหน่งเลขที่'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`birthDate\` \`birthDate\` varchar(255) NULL COMMENT 'วันเดือนปีเกิด'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`govAge\` \`govAge\` varchar(255) NULL COMMENT 'อายุราชการ'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`type\` \`type\` varchar(255) NULL COMMENT 'ประเภทแบบประเมิน'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`step\` \`step\` varchar(255) NULL COMMENT 'ชื่อสถานะการประเมิน'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`reason\` \`reason\` varchar(255) NULL COMMENT 'เหตุผล'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`experience\` \`experience\` varchar(255) NULL COMMENT 'ประสบการณ์ในการปฏิบัติงาน'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderFullname\` \`commanderFullname\` varchar(255) NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderPosition\` \`commanderPosition\` varchar(255) NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullname\` \`commanderAboveFullname\` varchar(255) NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePosition\` \`commanderAbovePosition\` varchar(255) NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderFullnameDoc2\` \`commanderFullnameDoc2\` varchar(255) NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderPositionDoc2\` \`commanderPositionDoc2\` varchar(255) NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullnameDoc2\` \`commanderAboveFullnameDoc2\` varchar(255) NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePositionDoc2\` \`commanderAbovePositionDoc2\` varchar(255) NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)'`); + await queryRunner.query(`ALTER TABLE \`assessment\` CHANGE \`date\` \`date\` datetime NULL COMMENT 'วันที่ได้รับ'`); + await queryRunner.query(`ALTER TABLE \`assessment\` CHANGE \`point1Total\` \`point1Total\` double NULL COMMENT 'ส่วนที่1 (คะแนน)'`); + await queryRunner.query(`ALTER TABLE \`assessment\` CHANGE \`point1\` \`point1\` double NULL COMMENT 'ผลประเมินส่วนที่2 (คะแนน)'`); + await queryRunner.query(`ALTER TABLE \`assessment\` CHANGE \`point2Total\` \`point2Total\` double NULL COMMENT 'ส่วนที่2 (คะแนน)'`); + await queryRunner.query(`ALTER TABLE \`assessment\` CHANGE \`point2\` \`point2\` double NULL COMMENT 'ผลประเมินส่วนที่2 (คะแนน)'`); + await queryRunner.query(`ALTER TABLE \`assessment\` CHANGE \`pointSumTotal\` \`pointSumTotal\` double NULL COMMENT 'ผลรวม (คะแนน)'`); + await queryRunner.query(`ALTER TABLE \`assessment\` CHANGE \`pointSum\` \`pointSum\` double NULL COMMENT 'ผลประเมินรวม (คะแนน)'`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`assessment\` CHANGE \`pointSum\` \`pointSum\` double NOT NULL COMMENT 'ผลประเมินรวม (คะแนน)' DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE \`assessment\` CHANGE \`pointSumTotal\` \`pointSumTotal\` double NOT NULL COMMENT 'ผลรวม (คะแนน)' DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE \`assessment\` CHANGE \`point2\` \`point2\` double NOT NULL COMMENT 'ผลประเมินส่วนที่2 (คะแนน)' DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE \`assessment\` CHANGE \`point2Total\` \`point2Total\` double NOT NULL COMMENT 'ส่วนที่2 (คะแนน)' DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE \`assessment\` CHANGE \`point1\` \`point1\` double NOT NULL COMMENT 'ผลประเมินส่วนที่2 (คะแนน)' DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE \`assessment\` CHANGE \`point1Total\` \`point1Total\` double NOT NULL COMMENT 'ส่วนที่1 (คะแนน)' DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE \`assessment\` CHANGE \`date\` \`date\` datetime NOT NULL COMMENT 'วันที่ได้รับ'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePositionDoc2\` \`commanderAbovePositionDoc2\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullnameDoc2\` \`commanderAboveFullnameDoc2\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderPositionDoc2\` \`commanderPositionDoc2\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderFullnameDoc2\` \`commanderFullnameDoc2\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น (จัดเตรียมเอกสารเล่ม 2)' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAbovePosition\` \`commanderAbovePosition\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderAboveFullname\` \`commanderAboveFullname\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาเหนือขึ้นไป 1 ระดับ' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderPosition\` \`commanderPosition\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง ผู้บังคับบัญชาชั้นต้น' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`commanderFullname\` \`commanderFullname\` varchar(255) NOT NULL COMMENT 'ชื่อ-นามสกุล ผู้บังคับบัญชาชั้นต้น' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`experience\` \`experience\` varchar(255) NOT NULL COMMENT 'ประสบการณ์ในการปฏิบัติงาน' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`reason\` \`reason\` varchar(255) NOT NULL COMMENT 'เหตุผล' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`step\` \`step\` varchar(255) NOT NULL COMMENT 'ชื่อสถานะการประเมิน' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`type\` \`type\` varchar(255) NOT NULL COMMENT 'ประเภทแบบประเมิน' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`govAge\` \`govAge\` varchar(255) NOT NULL COMMENT 'อายุราชการ' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`birthDate\` \`birthDate\` varchar(255) NOT NULL COMMENT 'วันเดือนปีเกิด' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`posNo\` \`posNo\` varchar(255) NOT NULL COMMENT 'ตำแหน่งเลขที่' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`positionLevel\` \`positionLevel\` varchar(255) NOT NULL COMMENT 'ระดับปัจจุบัน' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`salary\` \`salary\` varchar(255) NOT NULL COMMENT 'เงินเดือนปัจจุบัน' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`oc\` \`oc\` varchar(255) NOT NULL COMMENT 'สังกัด' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`position\` \`position\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`fullName\` \`fullName\` varchar(255) NOT NULL COMMENT 'ชื่อ นามสกุล' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`prefix\` \`prefix\` varchar(255) NOT NULL COMMENT 'คำนำหน้า' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`evaluation\` CHANGE \`citizenId\` \`citizenId\` varchar(13) NOT NULL COMMENT 'รหัสบัตรประชาชน' DEFAULT ''`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`dateOrder\` \`dateOrder\` datetime NOT NULL COMMENT 'คำสั่งลงวันที่/หนังสืออนุมัติลงวันที่'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`numberOrder\` \`numberOrder\` varchar(255) NOT NULL COMMENT 'เลขที่คำสั่ง/เลขที่หนังสืออนุมัติ' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`department\` \`department\` varchar(255) NOT NULL COMMENT 'หน่วยงานที่รับผิดชอบจัดการฝึกอบรม/ดูงาน' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`duration\` \`duration\` varchar(255) NOT NULL COMMENT 'รวมระยะเวลาในการฝึกอบรม/ดูงาน' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`place\` \`place\` varchar(255) NOT NULL COMMENT 'สถานที่ฝึกอบรม/ดูงาน' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`yearly\` \`yearly\` int NOT NULL COMMENT 'ปีที่อบรม (พ.ศ.)'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`endDate\` \`endDate\` datetime NOT NULL COMMENT 'วันสิ้นสุดการฝึกอบรม/ดูงาน'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`startDate\` \`startDate\` datetime NOT NULL COMMENT 'วันเริ่มต้นการฝึกอบรม/ดูงาน'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`topic\` \`topic\` varchar(255) NOT NULL COMMENT 'หัวข้อการฝึกอบรม/ดูงาน' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`training\` CHANGE \`name\` \`name\` varchar(255) NOT NULL COMMENT 'ชื่อโครงการ/หลักสูตรการฝึกอบรม' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`salaryStatus\` \`salaryStatus\` varchar(255) NOT NULL COMMENT 'ประเภทตำแหน่งกรณีพิเศษ' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`refCommandDate\` \`refCommandDate\` datetime NOT NULL COMMENT 'เอกสารอ้างอิง (ลงวันที่)'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`refCommandNo\` \`refCommandNo\` varchar(255) NOT NULL COMMENT 'เอกสารอ้างอิง (เลขที่คำสั่ง)' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`salaryRef\` \`salaryRef\` varchar(255) NOT NULL COMMENT 'เอกสารอ้างอิง' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`salaryClass\` \`salaryClass\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง (รายละเอียด)' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`posNo\` \`posNo\` varchar(255) NOT NULL COMMENT 'เลขที่ตำแหน่ง' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`position\` \`position\` varchar(255) NOT NULL COMMENT 'ตำแหน่ง' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`mouthSalaryAmount\` \`mouthSalaryAmount\` double NOT NULL COMMENT 'เงินค่าตอบแทนรายเดือน' DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`positionSalaryAmount\` \`positionSalaryAmount\` double NOT NULL COMMENT 'เงินประจำตำแหน่ง' DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`amount\` \`amount\` double NOT NULL COMMENT 'เงินเดือน' DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE \`salary\` CHANGE \`date\` \`date\` datetime NOT NULL COMMENT 'วัน เดือน ปี รับตำแหน่ง'`); + await queryRunner.query(`ALTER TABLE \`certificate\` CHANGE \`expireDate\` \`expireDate\` datetime NOT NULL COMMENT 'วันที่หมดอายุ'`); + await queryRunner.query(`ALTER TABLE \`certificate\` CHANGE \`issueDate\` \`issueDate\` datetime NOT NULL COMMENT 'วันที่ออกใบอนุญาต'`); + await queryRunner.query(`ALTER TABLE \`certificate\` CHANGE \`certificateNo\` \`certificateNo\` varchar(255) NOT NULL COMMENT 'เลขที่ใบอนุญาต' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`certificate\` CHANGE \`issuer\` \`issuer\` varchar(255) NOT NULL COMMENT 'หน่วยงานผู้ออกใบอนุญาต' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`certificate\` CHANGE \`certificateType\` \`certificateType\` varchar(255) NOT NULL COMMENT 'ชื่อใบอนุญาต' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`certificate\` CHANGE \`statictep\` \`statictep\` varchar(255) NOT NULL COMMENT 'ชื่อสถานะการประเมิน' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`durationYear\` \`durationYear\` varchar(255) NOT NULL COMMENT 'ระยะเวลาหลักสูตร' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`duration\` \`duration\` varchar(255) NOT NULL COMMENT 'ระยะเวลา' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`other\` \`other\` varchar(255) NOT NULL COMMENT 'ข้อมูลการติดต่อ' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`country\` \`country\` varchar(255) NOT NULL COMMENT 'ประเทศ' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`gpa\` \`gpa\` varchar(255) NOT NULL COMMENT 'เกรดเฉลี่ย' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`fundName\` \`fundName\` varchar(255) NOT NULL COMMENT 'ทุน' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`field\` \`field\` varchar(255) NOT NULL COMMENT 'สาขาวิชา/ทาง' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`degree\` \`degree\` varchar(255) NOT NULL COMMENT 'วุฒิการศึกษา' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`isEducation\` \`isEducation\` tinyint NOT NULL COMMENT 'เป็นวุฒิศึกษาในตำแหน่ง' DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`finishDate\` \`finishDate\` datetime NOT NULL COMMENT 'วันที่สำเร็จการศึกษา'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`endDate\` \`endDate\` datetime NOT NULL COMMENT 'EndDate'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`startDate\` \`startDate\` datetime NOT NULL COMMENT 'ตั้งแต่'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`isDate\` \`isDate\` tinyint NOT NULL COMMENT 'ประเภทช่วงเวลาการศึกษา' DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`institute\` \`institute\` varchar(255) NOT NULL COMMENT 'สถานศึกษา' DEFAULT 'string'`); + await queryRunner.query(`ALTER TABLE \`education\` CHANGE \`educationLevel\` \`educationLevel\` varchar(255) NOT NULL COMMENT 'ระดับศึกษา' DEFAULT 'string'`); + } + +} diff --git a/src/migration/1704279787037-update_table_evaluate_add_author.ts b/src/migration/1704279787037-update_table_evaluate_add_author.ts new file mode 100644 index 0000000..fea7fd8 --- /dev/null +++ b/src/migration/1704279787037-update_table_evaluate_add_author.ts @@ -0,0 +1,22 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateTableEvaluateAddAuthor1704279787037 implements MigrationInterface { + name = 'UpdateTableEvaluateAddAuthor1704279787037' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`evaluation\` ADD \`author\` varchar(255) NULL COMMENT 'ชื่อเจ้าของผลงาน'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` ADD \`subject\` varchar(255) NULL COMMENT 'ชื่อผลงาน'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` ADD \`authorDoc2\` varchar(255) NULL COMMENT 'ชื่อเจ้าของผลงาน2'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` ADD \`subjectDoc2\` varchar(255) NULL COMMENT 'ชื่อผลงาน2'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` ADD \`assignedPosition\` varchar(255) NULL COMMENT 'ตำแหน่งที่ได้รับมอบหมาย'`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`evaluation\` DROP COLUMN \`assignedPosition\``); + await queryRunner.query(`ALTER TABLE \`evaluation\` DROP COLUMN \`subjectDoc2\``); + await queryRunner.query(`ALTER TABLE \`evaluation\` DROP COLUMN \`authorDoc2\``); + await queryRunner.query(`ALTER TABLE \`evaluation\` DROP COLUMN \`subject\``); + await queryRunner.query(`ALTER TABLE \`evaluation\` DROP COLUMN \`author\``); + } + +} diff --git a/src/migration/1706070949738-update_table_evaluate_tittle_to_title.ts b/src/migration/1706070949738-update_table_evaluate_tittle_to_title.ts new file mode 100644 index 0000000..0a458ec --- /dev/null +++ b/src/migration/1706070949738-update_table_evaluate_tittle_to_title.ts @@ -0,0 +1,18 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateTableEvaluateTittleToTitle1706070949738 implements MigrationInterface { + name = 'UpdateTableEvaluateTittleToTitle1706070949738' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`meeting\` CHANGE \`tittle\` \`title\` varchar(255) NULL COMMENT 'ชื่อการประชุม'`); + await queryRunner.query(`ALTER TABLE \`meeting\` DROP COLUMN \`title\``); + await queryRunner.query(`ALTER TABLE \`meeting\` ADD \`title\` varchar(255) NULL COMMENT 'ชื่อการประชุม'`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`meeting\` DROP COLUMN \`title\``); + await queryRunner.query(`ALTER TABLE \`meeting\` ADD \`title\` varchar(255) NULL COMMENT 'ชื่อการประชุม'`); + await queryRunner.query(`ALTER TABLE \`meeting\` CHANGE \`title\` \`tittle\` varchar(255) NULL COMMENT 'ชื่อการประชุม'`); + } + +} diff --git a/src/migration/1730874813739-update_table_eva_add_root.ts b/src/migration/1730874813739-update_table_eva_add_root.ts new file mode 100644 index 0000000..e4e4879 --- /dev/null +++ b/src/migration/1730874813739-update_table_eva_add_root.ts @@ -0,0 +1,22 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateTableEvaAddRoot1730874813739 implements MigrationInterface { + name = 'UpdateTableEvaAddRoot1730874813739' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`evaluation\` ADD \`rootId\` varchar(255) NULL COMMENT 'root'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` ADD \`child1Id\` varchar(255) NULL COMMENT 'child1'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` ADD \`child2Id\` varchar(255) NULL COMMENT 'child2'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` ADD \`child3Id\` varchar(255) NULL COMMENT 'child3'`); + await queryRunner.query(`ALTER TABLE \`evaluation\` ADD \`child4Id\` varchar(255) NULL COMMENT 'child4'`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`evaluation\` DROP COLUMN \`child4Id\``); + await queryRunner.query(`ALTER TABLE \`evaluation\` DROP COLUMN \`child3Id\``); + await queryRunner.query(`ALTER TABLE \`evaluation\` DROP COLUMN \`child2Id\``); + await queryRunner.query(`ALTER TABLE \`evaluation\` DROP COLUMN \`child1Id\``); + await queryRunner.query(`ALTER TABLE \`evaluation\` DROP COLUMN \`rootId\``); + } + +} diff --git a/src/services/README.md b/src/services/README.md new file mode 100644 index 0000000..c2a4dd8 --- /dev/null +++ b/src/services/README.md @@ -0,0 +1,53 @@ +# External Service Library + +## Storage + +- สำหรับจัดเก็บไฟล์เท่านั้น หากต้องการเพิ่มข้อมูลเสริมอาจเก็บไว้ใน description ในรูปแบบของ String โดยอาจใช้ `JSON.stringify` ในการแปลงตัวแปรให้อยู่ในรูป String หรือเก็บแยกคนละส่วน +- เมื่อร้องขอการอัปโหลดไฟล์จำเป็นจะต้องทราบนามสกุล และ/หรือ ประเภทของไฟล์ด้วย สามารถใช้ [mime](https://www.npmjs.com/package/mime) ช่วยในการระบุได้จากชื่อโดยทราบจากการดึงข้อมูลของไฟล์ที่เลือกไว้ รวมถึง ประเภท เช่นกัน + +### Storage - Upload File ผ่าน PresignedURL + +```ts +// file เป็น file ที่เลือกจาก input ประเภท file +await axios + .put(res.data.uploadUrl, file, { + // ระบบ MinIO ใช้ในการระบุ ประเภทไฟล์ (จำเป็นสำหรับดาวน์โหลด) สามารถดึงจาก File ที่เก็บในตัวแปรที่เลือกไว้ในฟอร์มได้ + headers: { "Content-Type": file?.type }, + onUploadProgress: (e) => console.log(e), + }) + .catch((e) => console.error(e)); +``` + +### Storage - Download File ผ่าน PresignedURL + +ข้อมูลที่ API ให้มาเมื่อต้องการดาวน์โหลดจะมีข้อมูลทั้งหมดของไฟล์ รวมถึงลิงก์สำหรับดาวน์โหลดไฟล์ ซึ่งสามารถใช้ในการระบุประเภทไฟล์ที่ใช้ในการดาวน์โหลดได้ +หากชื่อไฟล์ที่มีในระบบ ไม่มีการระบุนามสกุลไฟล์ไว้ อาจจำเป็นต้องใช้ Library อย่าง [mime](https://www.npmjs.com/package/mime) ในการระบุนามสกุลไฟล์และเพิ่มเข้าไปตามท้ายของ ชื่อไฟล์ +และหากไม่มีการระบุประเภทไฟล์ เช่น mimeType ก็จะไม่สามารถรู้ได้ว่าไฟล์เป็นไฟล์อะไร + +```ts +await axios + .get(res.data.downloadUrl, { + method: "GET", + responseType: "blob", + headers: { + "Content-Type": "application/json", + Accept: res.data.fileType, // ถ้ามีการระบุเมื่ออัปโหลด + }, + }) + .then((r) => { + const a = document.createElement("a"); + a.href = window.URL.createObjectURL(r.data); + a.download = res.data.fileName; + // a.download = res.data.fileName + `.${mime.getExtension(res.data.fileType)}` + a.click(); + }); +``` + +### Storage - Waiting File Upload + +เมื่ออัปโหลดเสร็จอาจต้องการอไฟล์ที่อัปโหลดเข้าระบบแล้ว เพื่อนำมาทำอะไรบางอย่างเช่น PDF Preview +อาจจำเป็นต้องใช้ SocketIO ช่วยเนื่องจากระบบนี้ออกแบบให้รับโหลดได้สูง และยังมีการดึงข้อมูลภายใน File มาทำ index การค้นหา +ทำให้เกิดความหน่วยเวลาหลังอัปโหลดเล็กน้อยจากการที่รอ ElasticSearch ทำการ Refresh Index ซึ่งเกิดขึ้น ทุกๆ 1 วินาที ซึ่งเมื่ออัปโหลดแล้วอาจต้องรอรอบในการ Refresh Index +ซึ่งแม้จะเป็นไฟล์ขนาดเล็ก ก็สามารถเกิดความหน่วงของเวลา 1 วินาทีหลังอัปโหลดได้ ขึ้นอยู่กับ จังหวะ ที่อัปโหลดไฟล์ + +ตัวอย่างโค้ด อาจเพิ่มในภายหลัง diff --git a/src/services/callApi.ts b/src/services/callApi.ts new file mode 100644 index 0000000..6d8d378 --- /dev/null +++ b/src/services/callApi.ts @@ -0,0 +1,16 @@ +import { getToken } from "./storage"; +const API_URL = process.env.API_URL; +export async function sendNoti(sendData: any, token: any) { + const res = await fetch(`${API_URL}/placement/noti/keycloak`, { + method: "POST", + headers: { + Authorization: `${token}`, + "Content-Type": "application/json", + }, + body: JSON.stringify(sendData), + }).catch((e) => console.error(e)); + if (!res || !res.ok) { + return Boolean(console.error(res ? await res.json() : res)); + } + return true; +} diff --git a/src/services/storage.ts b/src/services/storage.ts new file mode 100644 index 0000000..b240edf --- /dev/null +++ b/src/services/storage.ts @@ -0,0 +1,265 @@ +import { DecodedJwt } from "fast-jwt"; +import HttpError from "../interfaces/http-error"; +import HttpStatus from "../interfaces/http-status"; +import { StorageFile, StorageFolder } from "../interfaces/storage-fs"; + +import { jwtDecode } from "../utils/jwt"; + +if (!process.env.STORAGE_URL) { + throw new Error("Requires STORAGE_URL env variable."); +} + +if (!process.env.STORAGE_REALM_URL && !process.env.STORAGE_SECRET) { + throw new Error("Requires STORAGE_REALM_URL and STORAGE_SECRET env variable."); +} + +export type FileProps = Partial< + Pick +> & { + metadata?: { [key: string]: unknown }; +}; + +const STORAGE_URL = process.env.STORAGE_URL; +const STORAGE_REALM_URL = process.env.STORAGE_REALM_URL; +const STORAGE_SECRET: any = process.env.STORAGE_SECRET; + +let token: string | null = null; +let decoded: DecodedJwt | null = null; + +/** + * Check if token is expired or will expire in 30 seconds + * @returns true if expire or can't get exp, false otherwise + */ +export function expireCheck(token: string, beforeExpire: number = 30) { + decoded = jwtDecode(token); + + if (decoded && decoded.payload.exp) { + return Date.now() / 1000 >= decoded.payload.exp - beforeExpire; + } + return true; +} + +/** + * Get token from id service if needed + */ +export async function getToken() { + if (!token || expireCheck(token)) { + const body = new URLSearchParams(); + + body.append("client_id", "ext-api"); + body.append("client_secret", STORAGE_SECRET); + body.append("grant_type", "client_credentials"); + + const res = await fetch(`${STORAGE_REALM_URL}/protocol/openid-connect/token`, { + method: "POST", + body: body, + }).catch((e) => console.error(e)); + + if (!res) return; + + const data = await res.json(); + + if (data && data.access_token) { + token = data.access_token; + } + } + return token; +} + +/** + * @param path - Path that new folder will live + * @param name - Name of the folder to create + * @param recursive - Will create parent automatically + */ +export async function createFolder(path: string[], name: string, recursive: boolean = false) { + if (recursive && path.length > 0) { + await createFolder(path.slice(0, -1), path[path.length - 1], true); + } + + const res = await fetch(`${STORAGE_URL}/storage/folder`, { + method: "POST", + headers: { + Authorization: `Bearer ${await getToken()}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ path, name }), + }).catch((e) => console.error(e)); + + if (!res || !res.ok) { + return Boolean(console.error(res ? await res.json() : res)); + } + return true; +} + +/** + * @param path - Path that new file will live + * @param file - Name of the file to create + */ +export async function createFile(path: string[], file: string, props?: FileProps) { + const res = await fetch(`${STORAGE_URL}/storage/file`, { + method: "POST", + headers: { + Authorization: `Bearer ${await getToken()}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + ...props, + path, + file, + hidden: false, + }), + }).catch((e) => console.error(e)); + + if (!res || !res.ok) { + return Boolean(console.error(res ? await res.json() : res)); + } + return (await res.json()) as StorageFile & { uploadUrl: string }; +} + +export async function list(operation: "file" | "folder", path: string[]) { + const res = await fetch(`${STORAGE_URL}/storage/list`, { + method: "POST", + headers: { + Authorization: `Bearer ${await getToken()}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ operation, path, hidden: false }), + }).catch((e) => console.error(e)); + + if (!res || !res.ok) { + if (res && res.status === HttpStatus.NOT_FOUND) { + throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบแฟ้ม/ไฟล์ในระบบ"); + } + return Boolean(console.error(res ? await res.json() : res)); + } + return (await res.json()) as StorageFile & { uploadUrl: string }; +} + +export async function listFolder(path: string[]) { + return (await list("folder", path)) as StorageFolder[] | boolean; +} + +export async function listFile(path: string[]) { + return (await list("file", path)) as StorageFile[] | boolean; +} + +export async function updateFile(path: string[], file: string, metadata: FileProps) { + const res = await fetch(`${STORAGE_URL}/storage/file`, { + method: "PUT", + headers: { + Authorization: `Bearer ${await getToken()}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ + from: { path, file }, + ...metadata, + upload: false, + }), + }).catch((e) => console.error(e)); + + if (!res || !res.ok) { + if (res && res.status === HttpStatus.NOT_FOUND) { + throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบไฟล์ในระบบ"); + } + return Boolean(console.error(res ? await res.json() : res)); + } + + return Boolean(res); +} + +export async function deleteFolder(path: string[], name: string) { + const res = await fetch(`${STORAGE_URL}/storage/folder`, { + method: "DELETE", + headers: { + Authorization: `Bearer ${await getToken()}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ path: [...path, name] }), + }).catch((e) => console.error(e)); + + if (!res || !res.ok) { + return Boolean(console.error(res ? await res.json() : res)); + } + return true; +} + +export async function deleteFile(path: string[], file: string) { + const res = await fetch(`${STORAGE_URL}/storage/file`, { + method: "DELETE", + headers: { + Authorization: `Bearer ${await getToken()}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ path, file }), + }).catch((e) => console.error(e)); + + if (!res || !res.ok) { + return Boolean(console.error(res ? await res.json() : res)); + } + return true; +} + +export async function downloadFile(path: string[], file: string) { + const res = await fetch(`${STORAGE_URL}/storage/file/download`, { + method: "POST", + headers: { + Authorization: `Bearer ${await getToken()}`, + "Content-Type": "application/json", + }, + body: JSON.stringify({ path, file }), + }).catch((e) => console.error(e)); + + if (!res || !res.ok) { + if (res && res.status === HttpStatus.NOT_FOUND) { + throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบไฟล์ในระบบ"); + } + return Boolean(console.error(res ? await res.json() : res)); + } + return (await res.json()) as StorageFile & { downloadUrl: string }; +} + +export function getUserInfoFromRequest(request: { user: { sub: string; name: string } }): { + sub: string; + name: string; +} { + const { sub, name } = request.user; + return { sub, name }; +} + +export function ConvertToThaiStep(val: string) { + switch (val) { + case "CHECK_SPEC": + return "ตรวจสอบคุณสมบัติด้วยตนเอง"; + case "PREPARE_DOC_V1": + return "จัดเตรียมเอกสารเล่ม 1"; + case "CHECK_DOC_V1": + return "ตรวจสอบความถูกต้องของเอกสารเล่ม 1"; + case "WAIT_CHECK_DOC_V1": + return "รอตรวจสอบคุณสมบัติ 1"; + case "ANNOUNCE_WEB": + return "ประกาศบนเว็บไซต์"; + case "PREPARE_DOC_V2": + return "จัดเตรียมเอกสารเล่ม 2"; + case "CHECK_DOC_V2": + return "รอพิจารณาผลการประเมิน 2"; + case "WAIT_CHECK_DOC_V2": + return "ตรวจสอบความถูกต้องของเอกสารเล่ม 2"; + case "DONE": + return "เสร็จสิ้น"; + default: + return null; + } +} + +export function ConvertToThaiType(val: string) { + switch (val) { + case "EXPERT": + return "ชำนาญการ"; + case "SPECIAL_EXPERT": + return "ชำนาญการพิเศษ"; + case "EXPERTISE": + return "เชี่ยวชาญ"; + default: + return null; + } +} diff --git a/src/utils/auth.ts b/src/utils/auth.ts new file mode 100644 index 0000000..9f78531 --- /dev/null +++ b/src/utils/auth.ts @@ -0,0 +1,76 @@ +import * as express from "express"; +import { createDecoder, createVerifier } from "fast-jwt"; + +import HttpError from "../interfaces/http-error"; +import HttpStatusCode from "../interfaces/http-status"; + +if (!process.env.PUBLIC_KEY && !process.env.REALM_URL) { + throw new Error("Requires PUBLIC_KEY or REALM_URL"); +} +if (process.env.PUBLIC_KEY && process.env.REALM_URL && !process.env.PREFERRED_AUTH) { + throw new Error( + "PREFERRED_AUTH must be specified when both REALM_URL and PUBLIC_KEY are provided.", + ); +} + +const jwtVerify = createVerifier({ + key: async () => { + return `-----BEGIN PUBLIC KEY-----\n${process.env.PUBLIC_KEY}\n-----END PUBLIC KEY-----`; + }, +}); + +const jwtDecode = createDecoder(); + +export async function expressAuthentication( + request: express.Request, + securityName: string, + scopes?: string[], +) { + if (process.env.AUTH_BYPASS) return { preferred_username: "bypassed" }; + + if (securityName !== "bearerAuth") throw new Error("Unknown authentication method."); + + const token = request.headers["authorization"]?.includes("Bearer ") + ? request.headers["authorization"].split(" ")[1] + : request.headers["authorization"]; + + if (!token) throw new HttpError(HttpStatusCode.UNAUTHORIZED, "กรุณาเข้าสู่ระบบก่อนใช้งาน!"); + + let payload: Record = {}; + + switch (process.env.PREFERRED_AUTH) { + case "online": + payload = await verifyOnline(token); + break; + case "offline": + payload = await verifyOffline(token); + break; + default: + if (process.env.REALM_URL) payload = await verifyOnline(token); + if (process.env.PUBLIC_KEY) payload = await verifyOffline(token); + break; + } + + if (scopes && scopes.length > 0 && scopes.every((v) => !payload.role.includes(v))) { + throw new HttpError(HttpStatusCode.FORBIDDEN, "You are not allowed to perform this action."); + } + + return payload; +} + +async function verifyOffline(token: string) { + const payload = await jwtVerify(token).catch((_) => null); + if (!payload) throw new HttpError(HttpStatusCode.UNAUTHORIZED, "Invalid token provided."); + return payload; +} + +async function verifyOnline(token: string) { + const res = await fetch(`${process.env.REALM_URL}/protocol/openid-connect/userinfo`, { + headers: { authorization: `Bearer ${token}` }, + }).catch((e) => console.error(e)); + + if (!res) throw new Error("Cannot connect to auth service."); + if (!res.ok) throw new HttpError(HttpStatusCode.UNAUTHORIZED, "Invalid token provided."); + + return await jwtDecode(token); +} diff --git a/src/utils/jwt.ts b/src/utils/jwt.ts new file mode 100644 index 0000000..a3514ac --- /dev/null +++ b/src/utils/jwt.ts @@ -0,0 +1,5 @@ +import { createDecoder } from "fast-jwt"; + +const jwtDecode = createDecoder({ complete: true }); + +export { jwtDecode }; diff --git a/static/index.html b/static/index.html new file mode 100644 index 0000000..6d01669 --- /dev/null +++ b/static/index.html @@ -0,0 +1,266 @@ + + + + + + + +
+ + + + + + + + + + + + + + + + + + + +
+ +

Result

+

+
+    

Events

+

+
+    
+  
+
diff --git a/static/keycloak.js b/static/keycloak.js
new file mode 100644
index 0000000..8fd0ccf
--- /dev/null
+++ b/static/keycloak.js
@@ -0,0 +1,2952 @@
+/*
+ * Copyright 2016 Red Hat, Inc. and/or its affiliates
+ * and other contributors as indicated by the @author tags.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+(function (root, factory) {
+  if (typeof exports === "object") {
+    if (typeof module === "object") {
+      module.exports = factory(require("js-sha256"), require("base64-js"));
+    } else {
+      exports["keycloak"] = factory(require("js-sha256"), require("base64-js"));
+    }
+  } else {
+    /**
+     * [js-sha256]{@link https://github.com/emn178/js-sha256}
+     *
+     * @version 0.9.0
+     * @author Chen, Yi-Cyuan [emn178@gmail.com]
+     * @copyright Chen, Yi-Cyuan 2014-2017
+     * @license MIT
+     */
+    !(function () {
+      "use strict";
+      function t(t, i) {
+        i
+          ? ((d[0] =
+              d[16] =
+              d[1] =
+              d[2] =
+              d[3] =
+              d[4] =
+              d[5] =
+              d[6] =
+              d[7] =
+              d[8] =
+              d[9] =
+              d[10] =
+              d[11] =
+              d[12] =
+              d[13] =
+              d[14] =
+              d[15] =
+                0),
+            (this.blocks = d))
+          : (this.blocks = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]),
+          t
+            ? ((this.h0 = 3238371032),
+              (this.h1 = 914150663),
+              (this.h2 = 812702999),
+              (this.h3 = 4144912697),
+              (this.h4 = 4290775857),
+              (this.h5 = 1750603025),
+              (this.h6 = 1694076839),
+              (this.h7 = 3204075428))
+            : ((this.h0 = 1779033703),
+              (this.h1 = 3144134277),
+              (this.h2 = 1013904242),
+              (this.h3 = 2773480762),
+              (this.h4 = 1359893119),
+              (this.h5 = 2600822924),
+              (this.h6 = 528734635),
+              (this.h7 = 1541459225)),
+          (this.block = this.start = this.bytes = this.hBytes = 0),
+          (this.finalized = this.hashed = !1),
+          (this.first = !0),
+          (this.is224 = t);
+      }
+      function i(i, r, s) {
+        var e,
+          n = typeof i;
+        if ("string" === n) {
+          var o,
+            a = [],
+            u = i.length,
+            c = 0;
+          for (e = 0; e < u; ++e)
+            (o = i.charCodeAt(e)) < 128
+              ? (a[c++] = o)
+              : o < 2048
+              ? ((a[c++] = 192 | (o >> 6)), (a[c++] = 128 | (63 & o)))
+              : o < 55296 || o >= 57344
+              ? ((a[c++] = 224 | (o >> 12)),
+                (a[c++] = 128 | ((o >> 6) & 63)),
+                (a[c++] = 128 | (63 & o)))
+              : ((o =
+                  65536 + (((1023 & o) << 10) | (1023 & i.charCodeAt(++e)))),
+                (a[c++] = 240 | (o >> 18)),
+                (a[c++] = 128 | ((o >> 12) & 63)),
+                (a[c++] = 128 | ((o >> 6) & 63)),
+                (a[c++] = 128 | (63 & o)));
+          i = a;
+        } else {
+          if ("object" !== n) throw new Error(h);
+          if (null === i) throw new Error(h);
+          if (f && i.constructor === ArrayBuffer) i = new Uint8Array(i);
+          else if (!(Array.isArray(i) || (f && ArrayBuffer.isView(i))))
+            throw new Error(h);
+        }
+        i.length > 64 && (i = new t(r, !0).update(i).array());
+        var y = [],
+          p = [];
+        for (e = 0; e < 64; ++e) {
+          var l = i[e] || 0;
+          (y[e] = 92 ^ l), (p[e] = 54 ^ l);
+        }
+        t.call(this, r, s),
+          this.update(p),
+          (this.oKeyPad = y),
+          (this.inner = !0),
+          (this.sharedMemory = s);
+      }
+      var h = "input is invalid type",
+        r = "object" == typeof window,
+        s = r ? window : {};
+      s.JS_SHA256_NO_WINDOW && (r = !1);
+      var e = !r && "object" == typeof self,
+        n =
+          !s.JS_SHA256_NO_NODE_JS &&
+          "object" == typeof process &&
+          process.versions &&
+          process.versions.node;
+      n ? (s = global) : e && (s = self);
+      var o =
+          !s.JS_SHA256_NO_COMMON_JS &&
+          "object" == typeof module &&
+          module.exports,
+        a = "function" == typeof define && define.amd,
+        f = !s.JS_SHA256_NO_ARRAY_BUFFER && "undefined" != typeof ArrayBuffer,
+        u = "0123456789abcdef".split(""),
+        c = [-2147483648, 8388608, 32768, 128],
+        y = [24, 16, 8, 0],
+        p = [
+          1116352408, 1899447441, 3049323471, 3921009573, 961987163, 1508970993,
+          2453635748, 2870763221, 3624381080, 310598401, 607225278, 1426881987,
+          1925078388, 2162078206, 2614888103, 3248222580, 3835390401,
+          4022224774, 264347078, 604807628, 770255983, 1249150122, 1555081692,
+          1996064986, 2554220882, 2821834349, 2952996808, 3210313671,
+          3336571891, 3584528711, 113926993, 338241895, 666307205, 773529912,
+          1294757372, 1396182291, 1695183700, 1986661051, 2177026350,
+          2456956037, 2730485921, 2820302411, 3259730800, 3345764771,
+          3516065817, 3600352804, 4094571909, 275423344, 430227734, 506948616,
+          659060556, 883997877, 958139571, 1322822218, 1537002063, 1747873779,
+          1955562222, 2024104815, 2227730452, 2361852424, 2428436474,
+          2756734187, 3204031479, 3329325298,
+        ],
+        l = ["hex", "array", "digest", "arrayBuffer"],
+        d = [];
+      (!s.JS_SHA256_NO_NODE_JS && Array.isArray) ||
+        (Array.isArray = function (t) {
+          return "[object Array]" === Object.prototype.toString.call(t);
+        }),
+        !f ||
+          (!s.JS_SHA256_NO_ARRAY_BUFFER_IS_VIEW && ArrayBuffer.isView) ||
+          (ArrayBuffer.isView = function (t) {
+            return (
+              "object" == typeof t &&
+              t.buffer &&
+              t.buffer.constructor === ArrayBuffer
+            );
+          });
+      var A = function (i, h) {
+          return function (r) {
+            return new t(h, !0).update(r)[i]();
+          };
+        },
+        w = function (i) {
+          var h = A("hex", i);
+          n && (h = b(h, i)),
+            (h.create = function () {
+              return new t(i);
+            }),
+            (h.update = function (t) {
+              return h.create().update(t);
+            });
+          for (var r = 0; r < l.length; ++r) {
+            var s = l[r];
+            h[s] = A(s, i);
+          }
+          return h;
+        },
+        b = function (t, i) {
+          var r = eval("require('crypto')"),
+            s = eval("require('buffer').Buffer"),
+            e = i ? "sha224" : "sha256",
+            n = function (i) {
+              if ("string" == typeof i)
+                return r.createHash(e).update(i, "utf8").digest("hex");
+              if (null === i || void 0 === i) throw new Error(h);
+              return (
+                i.constructor === ArrayBuffer && (i = new Uint8Array(i)),
+                Array.isArray(i) || ArrayBuffer.isView(i) || i.constructor === s
+                  ? r.createHash(e).update(new s(i)).digest("hex")
+                  : t(i)
+              );
+            };
+          return n;
+        },
+        v = function (t, h) {
+          return function (r, s) {
+            return new i(r, h, !0).update(s)[t]();
+          };
+        },
+        _ = function (t) {
+          var h = v("hex", t);
+          (h.create = function (h) {
+            return new i(h, t);
+          }),
+            (h.update = function (t, i) {
+              return h.create(t).update(i);
+            });
+          for (var r = 0; r < l.length; ++r) {
+            var s = l[r];
+            h[s] = v(s, t);
+          }
+          return h;
+        };
+      (t.prototype.update = function (t) {
+        if (!this.finalized) {
+          var i,
+            r = typeof t;
+          if ("string" !== r) {
+            if ("object" !== r) throw new Error(h);
+            if (null === t) throw new Error(h);
+            if (f && t.constructor === ArrayBuffer) t = new Uint8Array(t);
+            else if (!(Array.isArray(t) || (f && ArrayBuffer.isView(t))))
+              throw new Error(h);
+            i = !0;
+          }
+          for (var s, e, n = 0, o = t.length, a = this.blocks; n < o; ) {
+            if (
+              (this.hashed &&
+                ((this.hashed = !1),
+                (a[0] = this.block),
+                (a[16] =
+                  a[1] =
+                  a[2] =
+                  a[3] =
+                  a[4] =
+                  a[5] =
+                  a[6] =
+                  a[7] =
+                  a[8] =
+                  a[9] =
+                  a[10] =
+                  a[11] =
+                  a[12] =
+                  a[13] =
+                  a[14] =
+                  a[15] =
+                    0)),
+              i)
+            )
+              for (e = this.start; n < o && e < 64; ++n)
+                a[e >> 2] |= t[n] << y[3 & e++];
+            else
+              for (e = this.start; n < o && e < 64; ++n)
+                (s = t.charCodeAt(n)) < 128
+                  ? (a[e >> 2] |= s << y[3 & e++])
+                  : s < 2048
+                  ? ((a[e >> 2] |= (192 | (s >> 6)) << y[3 & e++]),
+                    (a[e >> 2] |= (128 | (63 & s)) << y[3 & e++]))
+                  : s < 55296 || s >= 57344
+                  ? ((a[e >> 2] |= (224 | (s >> 12)) << y[3 & e++]),
+                    (a[e >> 2] |= (128 | ((s >> 6) & 63)) << y[3 & e++]),
+                    (a[e >> 2] |= (128 | (63 & s)) << y[3 & e++]))
+                  : ((s =
+                      65536 +
+                      (((1023 & s) << 10) | (1023 & t.charCodeAt(++n)))),
+                    (a[e >> 2] |= (240 | (s >> 18)) << y[3 & e++]),
+                    (a[e >> 2] |= (128 | ((s >> 12) & 63)) << y[3 & e++]),
+                    (a[e >> 2] |= (128 | ((s >> 6) & 63)) << y[3 & e++]),
+                    (a[e >> 2] |= (128 | (63 & s)) << y[3 & e++]));
+            (this.lastByteIndex = e),
+              (this.bytes += e - this.start),
+              e >= 64
+                ? ((this.block = a[16]),
+                  (this.start = e - 64),
+                  this.hash(),
+                  (this.hashed = !0))
+                : (this.start = e);
+          }
+          return (
+            this.bytes > 4294967295 &&
+              ((this.hBytes += (this.bytes / 4294967296) << 0),
+              (this.bytes = this.bytes % 4294967296)),
+            this
+          );
+        }
+      }),
+        (t.prototype.finalize = function () {
+          if (!this.finalized) {
+            this.finalized = !0;
+            var t = this.blocks,
+              i = this.lastByteIndex;
+            (t[16] = this.block),
+              (t[i >> 2] |= c[3 & i]),
+              (this.block = t[16]),
+              i >= 56 &&
+                (this.hashed || this.hash(),
+                (t[0] = this.block),
+                (t[16] =
+                  t[1] =
+                  t[2] =
+                  t[3] =
+                  t[4] =
+                  t[5] =
+                  t[6] =
+                  t[7] =
+                  t[8] =
+                  t[9] =
+                  t[10] =
+                  t[11] =
+                  t[12] =
+                  t[13] =
+                  t[14] =
+                  t[15] =
+                    0)),
+              (t[14] = (this.hBytes << 3) | (this.bytes >>> 29)),
+              (t[15] = this.bytes << 3),
+              this.hash();
+          }
+        }),
+        (t.prototype.hash = function () {
+          var t,
+            i,
+            h,
+            r,
+            s,
+            e,
+            n,
+            o,
+            a,
+            f = this.h0,
+            u = this.h1,
+            c = this.h2,
+            y = this.h3,
+            l = this.h4,
+            d = this.h5,
+            A = this.h6,
+            w = this.h7,
+            b = this.blocks;
+          for (t = 16; t < 64; ++t)
+            (i =
+              (((s = b[t - 15]) >>> 7) | (s << 25)) ^
+              ((s >>> 18) | (s << 14)) ^
+              (s >>> 3)),
+              (h =
+                (((s = b[t - 2]) >>> 17) | (s << 15)) ^
+                ((s >>> 19) | (s << 13)) ^
+                (s >>> 10)),
+              (b[t] = (b[t - 16] + i + b[t - 7] + h) << 0);
+          for (a = u & c, t = 0; t < 64; t += 4)
+            this.first
+              ? (this.is224
+                  ? ((e = 300032),
+                    (w = ((s = b[0] - 1413257819) - 150054599) << 0),
+                    (y = (s + 24177077) << 0))
+                  : ((e = 704751109),
+                    (w = ((s = b[0] - 210244248) - 1521486534) << 0),
+                    (y = (s + 143694565) << 0)),
+                (this.first = !1))
+              : ((i =
+                  ((f >>> 2) | (f << 30)) ^
+                  ((f >>> 13) | (f << 19)) ^
+                  ((f >>> 22) | (f << 10))),
+                (r = (e = f & u) ^ (f & c) ^ a),
+                (w =
+                  (y +
+                    (s =
+                      w +
+                      (h =
+                        ((l >>> 6) | (l << 26)) ^
+                        ((l >>> 11) | (l << 21)) ^
+                        ((l >>> 25) | (l << 7))) +
+                      ((l & d) ^ (~l & A)) +
+                      p[t] +
+                      b[t])) <<
+                  0),
+                (y = (s + (i + r)) << 0)),
+              (i =
+                ((y >>> 2) | (y << 30)) ^
+                ((y >>> 13) | (y << 19)) ^
+                ((y >>> 22) | (y << 10))),
+              (r = (n = y & f) ^ (y & u) ^ e),
+              (A =
+                (c +
+                  (s =
+                    A +
+                    (h =
+                      ((w >>> 6) | (w << 26)) ^
+                      ((w >>> 11) | (w << 21)) ^
+                      ((w >>> 25) | (w << 7))) +
+                    ((w & l) ^ (~w & d)) +
+                    p[t + 1] +
+                    b[t + 1])) <<
+                0),
+              (i =
+                (((c = (s + (i + r)) << 0) >>> 2) | (c << 30)) ^
+                ((c >>> 13) | (c << 19)) ^
+                ((c >>> 22) | (c << 10))),
+              (r = (o = c & y) ^ (c & f) ^ n),
+              (d =
+                (u +
+                  (s =
+                    d +
+                    (h =
+                      ((A >>> 6) | (A << 26)) ^
+                      ((A >>> 11) | (A << 21)) ^
+                      ((A >>> 25) | (A << 7))) +
+                    ((A & w) ^ (~A & l)) +
+                    p[t + 2] +
+                    b[t + 2])) <<
+                0),
+              (i =
+                (((u = (s + (i + r)) << 0) >>> 2) | (u << 30)) ^
+                ((u >>> 13) | (u << 19)) ^
+                ((u >>> 22) | (u << 10))),
+              (r = (a = u & c) ^ (u & y) ^ o),
+              (l =
+                (f +
+                  (s =
+                    l +
+                    (h =
+                      ((d >>> 6) | (d << 26)) ^
+                      ((d >>> 11) | (d << 21)) ^
+                      ((d >>> 25) | (d << 7))) +
+                    ((d & A) ^ (~d & w)) +
+                    p[t + 3] +
+                    b[t + 3])) <<
+                0),
+              (f = (s + (i + r)) << 0);
+          (this.h0 = (this.h0 + f) << 0),
+            (this.h1 = (this.h1 + u) << 0),
+            (this.h2 = (this.h2 + c) << 0),
+            (this.h3 = (this.h3 + y) << 0),
+            (this.h4 = (this.h4 + l) << 0),
+            (this.h5 = (this.h5 + d) << 0),
+            (this.h6 = (this.h6 + A) << 0),
+            (this.h7 = (this.h7 + w) << 0);
+        }),
+        (t.prototype.hex = function () {
+          this.finalize();
+          var t = this.h0,
+            i = this.h1,
+            h = this.h2,
+            r = this.h3,
+            s = this.h4,
+            e = this.h5,
+            n = this.h6,
+            o = this.h7,
+            a =
+              u[(t >> 28) & 15] +
+              u[(t >> 24) & 15] +
+              u[(t >> 20) & 15] +
+              u[(t >> 16) & 15] +
+              u[(t >> 12) & 15] +
+              u[(t >> 8) & 15] +
+              u[(t >> 4) & 15] +
+              u[15 & t] +
+              u[(i >> 28) & 15] +
+              u[(i >> 24) & 15] +
+              u[(i >> 20) & 15] +
+              u[(i >> 16) & 15] +
+              u[(i >> 12) & 15] +
+              u[(i >> 8) & 15] +
+              u[(i >> 4) & 15] +
+              u[15 & i] +
+              u[(h >> 28) & 15] +
+              u[(h >> 24) & 15] +
+              u[(h >> 20) & 15] +
+              u[(h >> 16) & 15] +
+              u[(h >> 12) & 15] +
+              u[(h >> 8) & 15] +
+              u[(h >> 4) & 15] +
+              u[15 & h] +
+              u[(r >> 28) & 15] +
+              u[(r >> 24) & 15] +
+              u[(r >> 20) & 15] +
+              u[(r >> 16) & 15] +
+              u[(r >> 12) & 15] +
+              u[(r >> 8) & 15] +
+              u[(r >> 4) & 15] +
+              u[15 & r] +
+              u[(s >> 28) & 15] +
+              u[(s >> 24) & 15] +
+              u[(s >> 20) & 15] +
+              u[(s >> 16) & 15] +
+              u[(s >> 12) & 15] +
+              u[(s >> 8) & 15] +
+              u[(s >> 4) & 15] +
+              u[15 & s] +
+              u[(e >> 28) & 15] +
+              u[(e >> 24) & 15] +
+              u[(e >> 20) & 15] +
+              u[(e >> 16) & 15] +
+              u[(e >> 12) & 15] +
+              u[(e >> 8) & 15] +
+              u[(e >> 4) & 15] +
+              u[15 & e] +
+              u[(n >> 28) & 15] +
+              u[(n >> 24) & 15] +
+              u[(n >> 20) & 15] +
+              u[(n >> 16) & 15] +
+              u[(n >> 12) & 15] +
+              u[(n >> 8) & 15] +
+              u[(n >> 4) & 15] +
+              u[15 & n];
+          return (
+            this.is224 ||
+              (a +=
+                u[(o >> 28) & 15] +
+                u[(o >> 24) & 15] +
+                u[(o >> 20) & 15] +
+                u[(o >> 16) & 15] +
+                u[(o >> 12) & 15] +
+                u[(o >> 8) & 15] +
+                u[(o >> 4) & 15] +
+                u[15 & o]),
+            a
+          );
+        }),
+        (t.prototype.toString = t.prototype.hex),
+        (t.prototype.digest = function () {
+          this.finalize();
+          var t = this.h0,
+            i = this.h1,
+            h = this.h2,
+            r = this.h3,
+            s = this.h4,
+            e = this.h5,
+            n = this.h6,
+            o = this.h7,
+            a = [
+              (t >> 24) & 255,
+              (t >> 16) & 255,
+              (t >> 8) & 255,
+              255 & t,
+              (i >> 24) & 255,
+              (i >> 16) & 255,
+              (i >> 8) & 255,
+              255 & i,
+              (h >> 24) & 255,
+              (h >> 16) & 255,
+              (h >> 8) & 255,
+              255 & h,
+              (r >> 24) & 255,
+              (r >> 16) & 255,
+              (r >> 8) & 255,
+              255 & r,
+              (s >> 24) & 255,
+              (s >> 16) & 255,
+              (s >> 8) & 255,
+              255 & s,
+              (e >> 24) & 255,
+              (e >> 16) & 255,
+              (e >> 8) & 255,
+              255 & e,
+              (n >> 24) & 255,
+              (n >> 16) & 255,
+              (n >> 8) & 255,
+              255 & n,
+            ];
+          return (
+            this.is224 ||
+              a.push((o >> 24) & 255, (o >> 16) & 255, (o >> 8) & 255, 255 & o),
+            a
+          );
+        }),
+        (t.prototype.array = t.prototype.digest),
+        (t.prototype.arrayBuffer = function () {
+          this.finalize();
+          var t = new ArrayBuffer(this.is224 ? 28 : 32),
+            i = new DataView(t);
+          return (
+            i.setUint32(0, this.h0),
+            i.setUint32(4, this.h1),
+            i.setUint32(8, this.h2),
+            i.setUint32(12, this.h3),
+            i.setUint32(16, this.h4),
+            i.setUint32(20, this.h5),
+            i.setUint32(24, this.h6),
+            this.is224 || i.setUint32(28, this.h7),
+            t
+          );
+        }),
+        (i.prototype = new t()),
+        (i.prototype.finalize = function () {
+          if ((t.prototype.finalize.call(this), this.inner)) {
+            this.inner = !1;
+            var i = this.array();
+            t.call(this, this.is224, this.sharedMemory),
+              this.update(this.oKeyPad),
+              this.update(i),
+              t.prototype.finalize.call(this);
+          }
+        });
+      var B = w();
+      (B.sha256 = B),
+        (B.sha224 = w(!0)),
+        (B.sha256.hmac = _()),
+        (B.sha224.hmac = _(!0)),
+        o
+          ? (module.exports = B)
+          : ((s.sha256 = B.sha256),
+            (s.sha224 = B.sha224),
+            a &&
+              define(function () {
+                return B;
+              }));
+    })();
+
+    /**
+     * [base64-js]{@link https://github.com/beatgammit/base64-js}
+     *
+     * @version v1.3.0
+     * @author Kirill, Fomichev
+     * @copyright Kirill, Fomichev 2014
+     * @license MIT
+     */
+    (function (r) {
+      if (typeof exports === "object" && typeof module !== "undefined") {
+        module.exports = r();
+      } else if (typeof define === "function" && define.amd) {
+        define([], r);
+      } else {
+        var e;
+        if (typeof window !== "undefined") {
+          e = window;
+        } else if (typeof global !== "undefined") {
+          e = global;
+        } else if (typeof self !== "undefined") {
+          e = self;
+        } else {
+          e = this;
+        }
+        e.base64js = r();
+      }
+    })(function () {
+      var r, e, n;
+      return (function () {
+        function r(e, n, t) {
+          function o(f, i) {
+            if (!n[f]) {
+              if (!e[f]) {
+                var u = "function" == typeof require && require;
+                if (!i && u) return u(f, !0);
+                if (a) return a(f, !0);
+                var v = new Error("Cannot find module '" + f + "'");
+                throw ((v.code = "MODULE_NOT_FOUND"), v);
+              }
+              var d = (n[f] = { exports: {} });
+              e[f][0].call(
+                d.exports,
+                function (r) {
+                  var n = e[f][1][r];
+                  return o(n || r);
+                },
+                d,
+                d.exports,
+                r,
+                e,
+                n,
+                t
+              );
+            }
+            return n[f].exports;
+          }
+          for (
+            var a = "function" == typeof require && require, f = 0;
+            f < t.length;
+            f++
+          )
+            o(t[f]);
+          return o;
+        }
+        return r;
+      })()(
+        {
+          "/": [
+            function (r, e, n) {
+              "use strict";
+              n.byteLength = d;
+              n.toByteArray = h;
+              n.fromByteArray = p;
+              var t = [];
+              var o = [];
+              var a = typeof Uint8Array !== "undefined" ? Uint8Array : Array;
+              var f =
+                "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+              for (var i = 0, u = f.length; i < u; ++i) {
+                t[i] = f[i];
+                o[f.charCodeAt(i)] = i;
+              }
+              o["-".charCodeAt(0)] = 62;
+              o["_".charCodeAt(0)] = 63;
+              function v(r) {
+                var e = r.length;
+                if (e % 4 > 0) {
+                  throw new Error(
+                    "Invalid string. Length must be a multiple of 4"
+                  );
+                }
+                var n = r.indexOf("=");
+                if (n === -1) n = e;
+                var t = n === e ? 0 : 4 - (n % 4);
+                return [n, t];
+              }
+              function d(r) {
+                var e = v(r);
+                var n = e[0];
+                var t = e[1];
+                return ((n + t) * 3) / 4 - t;
+              }
+              function c(r, e, n) {
+                return ((e + n) * 3) / 4 - n;
+              }
+              function h(r) {
+                var e;
+                var n = v(r);
+                var t = n[0];
+                var f = n[1];
+                var i = new a(c(r, t, f));
+                var u = 0;
+                var d = f > 0 ? t - 4 : t;
+                for (var h = 0; h < d; h += 4) {
+                  e =
+                    (o[r.charCodeAt(h)] << 18) |
+                    (o[r.charCodeAt(h + 1)] << 12) |
+                    (o[r.charCodeAt(h + 2)] << 6) |
+                    o[r.charCodeAt(h + 3)];
+                  i[u++] = (e >> 16) & 255;
+                  i[u++] = (e >> 8) & 255;
+                  i[u++] = e & 255;
+                }
+                if (f === 2) {
+                  e = (o[r.charCodeAt(h)] << 2) | (o[r.charCodeAt(h + 1)] >> 4);
+                  i[u++] = e & 255;
+                }
+                if (f === 1) {
+                  e =
+                    (o[r.charCodeAt(h)] << 10) |
+                    (o[r.charCodeAt(h + 1)] << 4) |
+                    (o[r.charCodeAt(h + 2)] >> 2);
+                  i[u++] = (e >> 8) & 255;
+                  i[u++] = e & 255;
+                }
+                return i;
+              }
+              function s(r) {
+                return (
+                  t[(r >> 18) & 63] +
+                  t[(r >> 12) & 63] +
+                  t[(r >> 6) & 63] +
+                  t[r & 63]
+                );
+              }
+              function l(r, e, n) {
+                var t;
+                var o = [];
+                for (var a = e; a < n; a += 3) {
+                  t =
+                    ((r[a] << 16) & 16711680) +
+                    ((r[a + 1] << 8) & 65280) +
+                    (r[a + 2] & 255);
+                  o.push(s(t));
+                }
+                return o.join("");
+              }
+              function p(r) {
+                var e;
+                var n = r.length;
+                var o = n % 3;
+                var a = [];
+                var f = 16383;
+                for (var i = 0, u = n - o; i < u; i += f) {
+                  a.push(l(r, i, i + f > u ? u : i + f));
+                }
+                if (o === 1) {
+                  e = r[n - 1];
+                  a.push(t[e >> 2] + t[(e << 4) & 63] + "==");
+                } else if (o === 2) {
+                  e = (r[n - 2] << 8) + r[n - 1];
+                  a.push(
+                    t[e >> 10] + t[(e >> 4) & 63] + t[(e << 2) & 63] + "="
+                  );
+                }
+                return a.join("");
+              }
+            },
+            {},
+          ],
+        },
+        {},
+        []
+      )("/");
+    });
+
+    /**
+     * [promise-polyfill]{@link https://github.com/taylorhakes/promise-polyfill}
+     *
+     * @version v8.1.3
+     * @author Hakes, Taylor
+     * @copyright Hakes, Taylor 2014
+     * @license MIT
+     */
+    !(function (e, n) {
+      "object" == typeof exports && "undefined" != typeof module
+        ? n()
+        : "function" == typeof define && define.amd
+        ? define(n)
+        : n();
+    })(0, function () {
+      "use strict";
+      function e(e) {
+        var n = this.constructor;
+        return this.then(
+          function (t) {
+            return n.resolve(e()).then(function () {
+              return t;
+            });
+          },
+          function (t) {
+            return n.resolve(e()).then(function () {
+              return n.reject(t);
+            });
+          }
+        );
+      }
+      function n(e) {
+        return !(!e || "undefined" == typeof e.length);
+      }
+      function t() {}
+      function o(e) {
+        if (!(this instanceof o))
+          throw new TypeError("Promises must be constructed via new");
+        if ("function" != typeof e) throw new TypeError("not a function");
+        (this._state = 0),
+          (this._handled = !1),
+          (this._value = undefined),
+          (this._deferreds = []),
+          c(e, this);
+      }
+      function r(e, n) {
+        for (; 3 === e._state; ) e = e._value;
+        0 !== e._state
+          ? ((e._handled = !0),
+            o._immediateFn(function () {
+              var t = 1 === e._state ? n.onFulfilled : n.onRejected;
+              if (null !== t) {
+                var o;
+                try {
+                  o = t(e._value);
+                } catch (r) {
+                  return void f(n.promise, r);
+                }
+                i(n.promise, o);
+              } else (1 === e._state ? i : f)(n.promise, e._value);
+            }))
+          : e._deferreds.push(n);
+      }
+      function i(e, n) {
+        try {
+          if (n === e)
+            throw new TypeError("A promise cannot be resolved with itself.");
+          if (n && ("object" == typeof n || "function" == typeof n)) {
+            var t = n.then;
+            if (n instanceof o)
+              return (e._state = 3), (e._value = n), void u(e);
+            if ("function" == typeof t)
+              return void c(
+                (function (e, n) {
+                  return function () {
+                    e.apply(n, arguments);
+                  };
+                })(t, n),
+                e
+              );
+          }
+          (e._state = 1), (e._value = n), u(e);
+        } catch (r) {
+          f(e, r);
+        }
+      }
+      function f(e, n) {
+        (e._state = 2), (e._value = n), u(e);
+      }
+      function u(e) {
+        2 === e._state &&
+          0 === e._deferreds.length &&
+          o._immediateFn(function () {
+            e._handled || o._unhandledRejectionFn(e._value);
+          });
+        for (var n = 0, t = e._deferreds.length; t > n; n++)
+          r(e, e._deferreds[n]);
+        e._deferreds = null;
+      }
+      function c(e, n) {
+        var t = !1;
+        try {
+          e(
+            function (e) {
+              t || ((t = !0), i(n, e));
+            },
+            function (e) {
+              t || ((t = !0), f(n, e));
+            }
+          );
+        } catch (o) {
+          if (t) return;
+          (t = !0), f(n, o);
+        }
+      }
+      var a = setTimeout;
+      (o.prototype["catch"] = function (e) {
+        return this.then(null, e);
+      }),
+        (o.prototype.then = function (e, n) {
+          var o = new this.constructor(t);
+          return (
+            r(
+              this,
+              new (function (e, n, t) {
+                (this.onFulfilled = "function" == typeof e ? e : null),
+                  (this.onRejected = "function" == typeof n ? n : null),
+                  (this.promise = t);
+              })(e, n, o)
+            ),
+            o
+          );
+        }),
+        (o.prototype["finally"] = e),
+        (o.all = function (e) {
+          return new o(function (t, o) {
+            function r(e, n) {
+              try {
+                if (n && ("object" == typeof n || "function" == typeof n)) {
+                  var u = n.then;
+                  if ("function" == typeof u)
+                    return void u.call(
+                      n,
+                      function (n) {
+                        r(e, n);
+                      },
+                      o
+                    );
+                }
+                (i[e] = n), 0 == --f && t(i);
+              } catch (c) {
+                o(c);
+              }
+            }
+            if (!n(e)) return o(new TypeError("Promise.all accepts an array"));
+            var i = Array.prototype.slice.call(e);
+            if (0 === i.length) return t([]);
+            for (var f = i.length, u = 0; i.length > u; u++) r(u, i[u]);
+          });
+        }),
+        (o.resolve = function (e) {
+          return e && "object" == typeof e && e.constructor === o
+            ? e
+            : new o(function (n) {
+                n(e);
+              });
+        }),
+        (o.reject = function (e) {
+          return new o(function (n, t) {
+            t(e);
+          });
+        }),
+        (o.race = function (e) {
+          return new o(function (t, r) {
+            if (!n(e)) return r(new TypeError("Promise.race accepts an array"));
+            for (var i = 0, f = e.length; f > i; i++)
+              o.resolve(e[i]).then(t, r);
+          });
+        }),
+        (o._immediateFn =
+          ("function" == typeof setImmediate &&
+            function (e) {
+              setImmediate(e);
+            }) ||
+          function (e) {
+            a(e, 0);
+          }),
+        (o._unhandledRejectionFn = function (e) {
+          void 0 !== console &&
+            console &&
+            console.warn("Possible Unhandled Promise Rejection:", e);
+        });
+      var l = (function () {
+        if ("undefined" != typeof self) return self;
+        if ("undefined" != typeof window) return window;
+        if ("undefined" != typeof global) return global;
+        throw Error("unable to locate global object");
+      })();
+      "Promise" in l
+        ? l.Promise.prototype["finally"] || (l.Promise.prototype["finally"] = e)
+        : (l.Promise = o);
+    });
+
+    var Keycloak = factory(root["sha256"], root["base64js"]);
+    root["Keycloak"] = Keycloak;
+
+    if (typeof define === "function" && define.amd) {
+      define("keycloak", [], function () {
+        return Keycloak;
+      });
+    }
+  }
+})(window, function (sha256_imported, base64js_imported) {
+  if (typeof Promise === "undefined") {
+    throw Error(
+      "Keycloak requires an environment that supports Promises. Make sure that you include the appropriate polyfill."
+    );
+  }
+
+  var loggedPromiseDeprecation = false;
+
+  function logPromiseDeprecation() {
+    if (!loggedPromiseDeprecation) {
+      loggedPromiseDeprecation = true;
+      console.warn(
+        "[KEYCLOAK] Usage of legacy style promise methods such as `.error()` and `.success()` has been deprecated and support will be removed in future versions. Use standard style promise methods such as `.then() and `.catch()` instead."
+      );
+    }
+  }
+
+  function Keycloak(config) {
+    if (!(this instanceof Keycloak)) {
+      return new Keycloak(config);
+    }
+
+    var kc = this;
+    var adapter;
+    var refreshQueue = [];
+    var callbackStorage;
+
+    var loginIframe = {
+      enable: true,
+      callbackList: [],
+      interval: 5,
+    };
+
+    var scripts = document.getElementsByTagName("script");
+    for (var i = 0; i < scripts.length; i++) {
+      if (
+        (scripts[i].src.indexOf("keycloak.js") !== -1 ||
+          scripts[i].src.indexOf("keycloak.min.js") !== -1) &&
+        scripts[i].src.indexOf("version=") !== -1
+      ) {
+        kc.iframeVersion = scripts[i].src
+          .substring(scripts[i].src.indexOf("version=") + 8)
+          .split("&")[0];
+      }
+    }
+
+    var useNonce = true;
+    var logInfo = createLogger(console.info);
+    var logWarn = createLogger(console.warn);
+
+    kc.init = function (initOptions) {
+      kc.authenticated = false;
+
+      callbackStorage = createCallbackStorage();
+      var adapters = ["default", "cordova", "cordova-native"];
+
+      if (initOptions && adapters.indexOf(initOptions.adapter) > -1) {
+        adapter = loadAdapter(initOptions.adapter);
+      } else if (initOptions && typeof initOptions.adapter === "object") {
+        adapter = initOptions.adapter;
+      } else {
+        if (window.Cordova || window.cordova) {
+          adapter = loadAdapter("cordova");
+        } else {
+          adapter = loadAdapter();
+        }
+      }
+
+      if (initOptions) {
+        if (typeof initOptions.useNonce !== "undefined") {
+          useNonce = initOptions.useNonce;
+        }
+
+        if (typeof initOptions.checkLoginIframe !== "undefined") {
+          loginIframe.enable = initOptions.checkLoginIframe;
+        }
+
+        if (initOptions.checkLoginIframeInterval) {
+          loginIframe.interval = initOptions.checkLoginIframeInterval;
+        }
+
+        if (initOptions.onLoad === "login-required") {
+          kc.loginRequired = true;
+        }
+
+        if (initOptions.responseMode) {
+          if (
+            initOptions.responseMode === "query" ||
+            initOptions.responseMode === "fragment"
+          ) {
+            kc.responseMode = initOptions.responseMode;
+          } else {
+            throw "Invalid value for responseMode";
+          }
+        }
+
+        if (initOptions.flow) {
+          switch (initOptions.flow) {
+            case "standard":
+              kc.responseType = "code";
+              break;
+            case "implicit":
+              kc.responseType = "id_token token";
+              break;
+            case "hybrid":
+              kc.responseType = "code id_token token";
+              break;
+            default:
+              throw "Invalid value for flow";
+          }
+          kc.flow = initOptions.flow;
+        }
+
+        if (initOptions.timeSkew != null) {
+          kc.timeSkew = initOptions.timeSkew;
+        }
+
+        if (initOptions.redirectUri) {
+          kc.redirectUri = initOptions.redirectUri;
+        }
+
+        if (initOptions.silentCheckSsoRedirectUri) {
+          kc.silentCheckSsoRedirectUri = initOptions.silentCheckSsoRedirectUri;
+        }
+
+        if (typeof initOptions.silentCheckSsoFallback === "boolean") {
+          kc.silentCheckSsoFallback = initOptions.silentCheckSsoFallback;
+        } else {
+          kc.silentCheckSsoFallback = true;
+        }
+
+        if (initOptions.pkceMethod) {
+          if (initOptions.pkceMethod !== "S256") {
+            throw "Invalid value for pkceMethod";
+          }
+          kc.pkceMethod = initOptions.pkceMethod;
+        }
+
+        if (typeof initOptions.enableLogging === "boolean") {
+          kc.enableLogging = initOptions.enableLogging;
+        } else {
+          kc.enableLogging = false;
+        }
+
+        if (typeof initOptions.scope === "string") {
+          kc.scope = initOptions.scope;
+        }
+
+        if (
+          typeof initOptions.messageReceiveTimeout === "number" &&
+          initOptions.messageReceiveTimeout > 0
+        ) {
+          kc.messageReceiveTimeout = initOptions.messageReceiveTimeout;
+        } else {
+          kc.messageReceiveTimeout = 10000;
+        }
+      }
+
+      if (!kc.responseMode) {
+        kc.responseMode = "fragment";
+      }
+      if (!kc.responseType) {
+        kc.responseType = "code";
+        kc.flow = "standard";
+      }
+
+      var promise = createPromise();
+
+      var initPromise = createPromise();
+      initPromise.promise
+        .then(function () {
+          kc.onReady && kc.onReady(kc.authenticated);
+          promise.setSuccess(kc.authenticated);
+        })
+        .catch(function (error) {
+          promise.setError(error);
+        });
+
+      var configPromise = loadConfig(config);
+
+      function onLoad() {
+        var doLogin = function (prompt) {
+          if (!prompt) {
+            options.prompt = "none";
+          }
+
+          kc.login(options)
+            .then(function () {
+              initPromise.setSuccess();
+            })
+            .catch(function (error) {
+              initPromise.setError(error);
+            });
+        };
+
+        var checkSsoSilently = function () {
+          var ifrm = document.createElement("iframe");
+          var src = kc.createLoginUrl({
+            prompt: "none",
+            redirectUri: kc.silentCheckSsoRedirectUri,
+          });
+          ifrm.setAttribute("src", src);
+          ifrm.setAttribute("title", "keycloak-silent-check-sso");
+          ifrm.style.display = "none";
+          document.body.appendChild(ifrm);
+
+          var messageCallback = function (event) {
+            if (
+              event.origin !== window.location.origin ||
+              ifrm.contentWindow !== event.source
+            ) {
+              return;
+            }
+
+            var oauth = parseCallback(event.data);
+            processCallback(oauth, initPromise);
+
+            document.body.removeChild(ifrm);
+            window.removeEventListener("message", messageCallback);
+          };
+
+          window.addEventListener("message", messageCallback);
+        };
+
+        var options = {};
+        switch (initOptions.onLoad) {
+          case "check-sso":
+            if (loginIframe.enable) {
+              setupCheckLoginIframe().then(function () {
+                checkLoginIframe()
+                  .then(function (unchanged) {
+                    if (!unchanged) {
+                      kc.silentCheckSsoRedirectUri
+                        ? checkSsoSilently()
+                        : doLogin(false);
+                    } else {
+                      initPromise.setSuccess();
+                    }
+                  })
+                  .catch(function (error) {
+                    initPromise.setError(error);
+                  });
+              });
+            } else {
+              kc.silentCheckSsoRedirectUri
+                ? checkSsoSilently()
+                : doLogin(false);
+            }
+            break;
+          case "login-required":
+            doLogin(true);
+            break;
+          default:
+            throw "Invalid value for onLoad";
+        }
+      }
+
+      function processInit() {
+        var callback = parseCallback(window.location.href);
+
+        if (callback) {
+          window.history.replaceState(
+            window.history.state,
+            null,
+            callback.newUrl
+          );
+        }
+
+        if (callback && callback.valid) {
+          return setupCheckLoginIframe()
+            .then(function () {
+              processCallback(callback, initPromise);
+            })
+            .catch(function (error) {
+              initPromise.setError(error);
+            });
+        } else if (initOptions) {
+          if (initOptions.token && initOptions.refreshToken) {
+            setToken(
+              initOptions.token,
+              initOptions.refreshToken,
+              initOptions.idToken
+            );
+
+            if (loginIframe.enable) {
+              setupCheckLoginIframe().then(function () {
+                checkLoginIframe()
+                  .then(function (unchanged) {
+                    if (unchanged) {
+                      kc.onAuthSuccess && kc.onAuthSuccess();
+                      initPromise.setSuccess();
+                      scheduleCheckIframe();
+                    } else {
+                      initPromise.setSuccess();
+                    }
+                  })
+                  .catch(function (error) {
+                    initPromise.setError(error);
+                  });
+              });
+            } else {
+              kc.updateToken(-1)
+                .then(function () {
+                  kc.onAuthSuccess && kc.onAuthSuccess();
+                  initPromise.setSuccess();
+                })
+                .catch(function (error) {
+                  kc.onAuthError && kc.onAuthError();
+                  if (initOptions.onLoad) {
+                    onLoad();
+                  } else {
+                    initPromise.setError(error);
+                  }
+                });
+            }
+          } else if (initOptions.onLoad) {
+            onLoad();
+          } else {
+            initPromise.setSuccess();
+          }
+        } else {
+          initPromise.setSuccess();
+        }
+      }
+
+      function domReady() {
+        var promise = createPromise();
+
+        var checkReadyState = function () {
+          if (
+            document.readyState === "interactive" ||
+            document.readyState === "complete"
+          ) {
+            document.removeEventListener("readystatechange", checkReadyState);
+            promise.setSuccess();
+          }
+        };
+        document.addEventListener("readystatechange", checkReadyState);
+
+        checkReadyState(); // just in case the event was already fired and we missed it (in case the init is done later than at the load time, i.e. it's done from code)
+
+        return promise.promise;
+      }
+
+      configPromise.then(function () {
+        domReady()
+          .then(check3pCookiesSupported)
+          .then(processInit)
+          .catch(function (error) {
+            promise.setError(error);
+          });
+      });
+      configPromise.catch(function (error) {
+        promise.setError(error);
+      });
+
+      return promise.promise;
+    };
+
+    kc.login = function (options) {
+      return adapter.login(options);
+    };
+
+    function generateRandomData(len) {
+      // use web crypto APIs if possible
+      var array = null;
+      var crypto = window.crypto || window.msCrypto;
+      if (crypto && crypto.getRandomValues && window.Uint8Array) {
+        array = new Uint8Array(len);
+        crypto.getRandomValues(array);
+        return array;
+      }
+
+      // fallback to Math random
+      array = new Array(len);
+      for (var j = 0; j < array.length; j++) {
+        array[j] = Math.floor(256 * Math.random());
+      }
+      return array;
+    }
+
+    function generateCodeVerifier(len) {
+      return generateRandomString(
+        len,
+        "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789"
+      );
+    }
+
+    function generateRandomString(len, alphabet) {
+      var randomData = generateRandomData(len);
+      var chars = new Array(len);
+      for (var i = 0; i < len; i++) {
+        chars[i] = alphabet.charCodeAt(randomData[i] % alphabet.length);
+      }
+      return String.fromCharCode.apply(null, chars);
+    }
+
+    function generatePkceChallenge(pkceMethod, codeVerifier) {
+      switch (pkceMethod) {
+        // The use of the "plain" method is considered insecure and therefore not supported.
+        case "S256":
+          // hash codeVerifier, then encode as url-safe base64 without padding
+          var hashBytes = new Uint8Array(
+            sha256_imported.arrayBuffer(codeVerifier)
+          );
+          var encodedHash = base64js_imported
+            .fromByteArray(hashBytes)
+            .replace(/\+/g, "-")
+            .replace(/\//g, "_")
+            .replace(/\=/g, "");
+          return encodedHash;
+        default:
+          throw "Invalid value for pkceMethod";
+      }
+    }
+
+    kc.createLoginUrl = function (options) {
+      var state = createUUID();
+      var nonce = createUUID();
+
+      var redirectUri = adapter.redirectUri(options);
+
+      var callbackState = {
+        state: state,
+        nonce: nonce,
+        redirectUri: encodeURIComponent(redirectUri),
+      };
+
+      if (options && options.prompt) {
+        callbackState.prompt = options.prompt;
+      }
+
+      var baseUrl;
+      if (options && options.action == "register") {
+        baseUrl = kc.endpoints.register();
+      } else {
+        baseUrl = kc.endpoints.authorize();
+      }
+
+      var scope = (options && options.scope) || kc.scope;
+      if (!scope) {
+        // if scope is not set, default to "openid"
+        scope = "openid";
+      } else if (scope.indexOf("openid") === -1) {
+        // if openid scope is missing, prefix the given scopes with it
+        scope = "openid " + scope;
+      }
+
+      var url =
+        baseUrl +
+        "?client_id=" +
+        encodeURIComponent(kc.clientId) +
+        "&redirect_uri=" +
+        encodeURIComponent(redirectUri) +
+        "&state=" +
+        encodeURIComponent(state) +
+        "&response_mode=" +
+        encodeURIComponent(kc.responseMode) +
+        "&response_type=" +
+        encodeURIComponent(kc.responseType) +
+        "&scope=" +
+        encodeURIComponent(scope);
+      if (useNonce) {
+        url = url + "&nonce=" + encodeURIComponent(nonce);
+      }
+
+      if (options && options.prompt) {
+        url += "&prompt=" + encodeURIComponent(options.prompt);
+      }
+
+      if (options && options.maxAge) {
+        url += "&max_age=" + encodeURIComponent(options.maxAge);
+      }
+
+      if (options && options.loginHint) {
+        url += "&login_hint=" + encodeURIComponent(options.loginHint);
+      }
+
+      if (options && options.idpHint) {
+        url += "&kc_idp_hint=" + encodeURIComponent(options.idpHint);
+      }
+
+      if (options && options.action && options.action != "register") {
+        url += "&kc_action=" + encodeURIComponent(options.action);
+      }
+
+      if (options && options.locale) {
+        url += "&ui_locales=" + encodeURIComponent(options.locale);
+      }
+
+      if (kc.pkceMethod) {
+        var codeVerifier = generateCodeVerifier(96);
+        callbackState.pkceCodeVerifier = codeVerifier;
+        var pkceChallenge = generatePkceChallenge(kc.pkceMethod, codeVerifier);
+        url += "&code_challenge=" + pkceChallenge;
+        url += "&code_challenge_method=" + kc.pkceMethod;
+      }
+
+      callbackStorage.add(callbackState);
+
+      return url;
+    };
+
+    kc.logout = function (options) {
+      return adapter.logout(options);
+    };
+
+    kc.createLogoutUrl = function (options) {
+      var url =
+        kc.endpoints.logout() +
+        "?redirect_uri=" +
+        encodeURIComponent(adapter.redirectUri(options, false));
+
+      return url;
+    };
+
+    kc.register = function (options) {
+      return adapter.register(options);
+    };
+
+    kc.createRegisterUrl = function (options) {
+      if (!options) {
+        options = {};
+      }
+      options.action = "register";
+      return kc.createLoginUrl(options);
+    };
+
+    kc.createAccountUrl = function (options) {
+      var realm = getRealmUrl();
+      var url = undefined;
+      if (typeof realm !== "undefined") {
+        url =
+          realm +
+          "/account" +
+          "?referrer=" +
+          encodeURIComponent(kc.clientId) +
+          "&referrer_uri=" +
+          encodeURIComponent(adapter.redirectUri(options));
+      }
+      return url;
+    };
+
+    kc.accountManagement = function () {
+      return adapter.accountManagement();
+    };
+
+    kc.hasRealmRole = function (role) {
+      var access = kc.realmAccess;
+      return !!access && access.roles.indexOf(role) >= 0;
+    };
+
+    kc.hasResourceRole = function (role, resource) {
+      if (!kc.resourceAccess) {
+        return false;
+      }
+
+      var access = kc.resourceAccess[resource || kc.clientId];
+      return !!access && access.roles.indexOf(role) >= 0;
+    };
+
+    kc.loadUserProfile = function () {
+      var url = getRealmUrl() + "/account";
+      var req = new XMLHttpRequest();
+      req.open("GET", url, true);
+      req.setRequestHeader("Accept", "application/json");
+      req.setRequestHeader("Authorization", "bearer " + kc.token);
+
+      var promise = createPromise();
+
+      req.onreadystatechange = function () {
+        if (req.readyState == 4) {
+          if (req.status == 200) {
+            kc.profile = JSON.parse(req.responseText);
+            promise.setSuccess(kc.profile);
+          } else {
+            promise.setError();
+          }
+        }
+      };
+
+      req.send();
+
+      return promise.promise;
+    };
+
+    kc.loadUserInfo = function () {
+      var url = kc.endpoints.userinfo();
+      var req = new XMLHttpRequest();
+      req.open("GET", url, true);
+      req.setRequestHeader("Accept", "application/json");
+      req.setRequestHeader("Authorization", "bearer " + kc.token);
+
+      var promise = createPromise();
+
+      req.onreadystatechange = function () {
+        if (req.readyState == 4) {
+          if (req.status == 200) {
+            kc.userInfo = JSON.parse(req.responseText);
+            promise.setSuccess(kc.userInfo);
+          } else {
+            promise.setError();
+          }
+        }
+      };
+
+      req.send();
+
+      return promise.promise;
+    };
+
+    kc.isTokenExpired = function (minValidity) {
+      if (!kc.tokenParsed || (!kc.refreshToken && kc.flow != "implicit")) {
+        throw "Not authenticated";
+      }
+
+      if (kc.timeSkew == null) {
+        logInfo(
+          "[KEYCLOAK] Unable to determine if token is expired as timeskew is not set"
+        );
+        return true;
+      }
+
+      var expiresIn =
+        kc.tokenParsed["exp"] -
+        Math.ceil(new Date().getTime() / 1000) +
+        kc.timeSkew;
+      if (minValidity) {
+        if (isNaN(minValidity)) {
+          throw "Invalid minValidity";
+        }
+        expiresIn -= minValidity;
+      }
+      return expiresIn < 0;
+    };
+
+    kc.updateToken = function (minValidity) {
+      var promise = createPromise();
+
+      if (!kc.refreshToken) {
+        promise.setError();
+        return promise.promise;
+      }
+
+      minValidity = minValidity || 5;
+
+      var exec = function () {
+        var refreshToken = false;
+        if (minValidity == -1) {
+          refreshToken = true;
+          logInfo("[KEYCLOAK] Refreshing token: forced refresh");
+        } else if (!kc.tokenParsed || kc.isTokenExpired(minValidity)) {
+          refreshToken = true;
+          logInfo("[KEYCLOAK] Refreshing token: token expired");
+        }
+
+        if (!refreshToken) {
+          promise.setSuccess(false);
+        } else {
+          var params =
+            "grant_type=refresh_token&" + "refresh_token=" + kc.refreshToken;
+          var url = kc.endpoints.token();
+
+          refreshQueue.push(promise);
+
+          if (refreshQueue.length == 1) {
+            var req = new XMLHttpRequest();
+            req.open("POST", url, true);
+            req.setRequestHeader(
+              "Content-type",
+              "application/x-www-form-urlencoded"
+            );
+            req.withCredentials = true;
+
+            params += "&client_id=" + encodeURIComponent(kc.clientId);
+
+            var timeLocal = new Date().getTime();
+
+            req.onreadystatechange = function () {
+              if (req.readyState == 4) {
+                if (req.status == 200) {
+                  logInfo("[KEYCLOAK] Token refreshed");
+
+                  timeLocal = (timeLocal + new Date().getTime()) / 2;
+
+                  var tokenResponse = JSON.parse(req.responseText);
+
+                  setToken(
+                    tokenResponse["access_token"],
+                    tokenResponse["refresh_token"],
+                    tokenResponse["id_token"],
+                    timeLocal
+                  );
+
+                  kc.onAuthRefreshSuccess && kc.onAuthRefreshSuccess();
+                  for (
+                    var p = refreshQueue.pop();
+                    p != null;
+                    p = refreshQueue.pop()
+                  ) {
+                    p.setSuccess(true);
+                  }
+                } else {
+                  logWarn("[KEYCLOAK] Failed to refresh token");
+
+                  if (req.status == 400) {
+                    kc.clearToken();
+                  }
+
+                  kc.onAuthRefreshError && kc.onAuthRefreshError();
+                  for (
+                    var p = refreshQueue.pop();
+                    p != null;
+                    p = refreshQueue.pop()
+                  ) {
+                    p.setError(true);
+                  }
+                }
+              }
+            };
+
+            req.send(params);
+          }
+        }
+      };
+
+      if (loginIframe.enable) {
+        var iframePromise = checkLoginIframe();
+        iframePromise
+          .then(function () {
+            exec();
+          })
+          .catch(function (error) {
+            promise.setError(error);
+          });
+      } else {
+        exec();
+      }
+
+      return promise.promise;
+    };
+
+    kc.clearToken = function () {
+      if (kc.token) {
+        setToken(null, null, null);
+        kc.onAuthLogout && kc.onAuthLogout();
+        if (kc.loginRequired) {
+          kc.login();
+        }
+      }
+    };
+
+    function getRealmUrl() {
+      if (typeof kc.authServerUrl !== "undefined") {
+        if (kc.authServerUrl.charAt(kc.authServerUrl.length - 1) == "/") {
+          return kc.authServerUrl + "realms/" + encodeURIComponent(kc.realm);
+        } else {
+          return kc.authServerUrl + "/realms/" + encodeURIComponent(kc.realm);
+        }
+      } else {
+        return undefined;
+      }
+    }
+
+    function getOrigin() {
+      if (!window.location.origin) {
+        return (
+          window.location.protocol +
+          "//" +
+          window.location.hostname +
+          (window.location.port ? ":" + window.location.port : "")
+        );
+      } else {
+        return window.location.origin;
+      }
+    }
+
+    function processCallback(oauth, promise) {
+      var code = oauth.code;
+      var error = oauth.error;
+      var prompt = oauth.prompt;
+
+      var timeLocal = new Date().getTime();
+
+      if (oauth["kc_action_status"]) {
+        kc.onActionUpdate && kc.onActionUpdate(oauth["kc_action_status"]);
+      }
+
+      if (error) {
+        if (prompt != "none") {
+          var errorData = {
+            error: error,
+            error_description: oauth.error_description,
+          };
+          kc.onAuthError && kc.onAuthError(errorData);
+          promise && promise.setError(errorData);
+        } else {
+          promise && promise.setSuccess();
+        }
+        return;
+      } else if (
+        kc.flow != "standard" &&
+        (oauth.access_token || oauth.id_token)
+      ) {
+        authSuccess(oauth.access_token, null, oauth.id_token, true);
+      }
+
+      if (kc.flow != "implicit" && code) {
+        var params = "code=" + code + "&grant_type=authorization_code";
+        var url = kc.endpoints.token();
+
+        var req = new XMLHttpRequest();
+        req.open("POST", url, true);
+        req.setRequestHeader(
+          "Content-type",
+          "application/x-www-form-urlencoded"
+        );
+
+        params += "&client_id=" + encodeURIComponent(kc.clientId);
+        params += "&redirect_uri=" + oauth.redirectUri;
+
+        if (oauth.pkceCodeVerifier) {
+          params += "&code_verifier=" + oauth.pkceCodeVerifier;
+        }
+
+        req.withCredentials = true;
+
+        req.onreadystatechange = function () {
+          if (req.readyState == 4) {
+            if (req.status == 200) {
+              var tokenResponse = JSON.parse(req.responseText);
+              authSuccess(
+                tokenResponse["access_token"],
+                tokenResponse["refresh_token"],
+                tokenResponse["id_token"],
+                kc.flow === "standard"
+              );
+              scheduleCheckIframe();
+            } else {
+              kc.onAuthError && kc.onAuthError();
+              promise && promise.setError();
+            }
+          }
+        };
+
+        req.send(params);
+      }
+
+      function authSuccess(accessToken, refreshToken, idToken, fulfillPromise) {
+        timeLocal = (timeLocal + new Date().getTime()) / 2;
+
+        setToken(accessToken, refreshToken, idToken, timeLocal);
+
+        if (
+          useNonce &&
+          ((kc.tokenParsed && kc.tokenParsed.nonce != oauth.storedNonce) ||
+            (kc.refreshTokenParsed &&
+              kc.refreshTokenParsed.nonce != oauth.storedNonce) ||
+            (kc.idTokenParsed && kc.idTokenParsed.nonce != oauth.storedNonce))
+        ) {
+          logInfo("[KEYCLOAK] Invalid nonce, clearing token");
+          kc.clearToken();
+          promise && promise.setError();
+        } else {
+          if (fulfillPromise) {
+            kc.onAuthSuccess && kc.onAuthSuccess();
+            promise && promise.setSuccess();
+          }
+        }
+      }
+    }
+
+    function loadConfig(url) {
+      var promise = createPromise();
+      var configUrl;
+
+      if (!config) {
+        configUrl = "keycloak.json";
+      } else if (typeof config === "string") {
+        configUrl = config;
+      }
+
+      function setupOidcEndoints(oidcConfiguration) {
+        if (!oidcConfiguration) {
+          kc.endpoints = {
+            authorize: function () {
+              return getRealmUrl() + "/protocol/openid-connect/auth";
+            },
+            token: function () {
+              return getRealmUrl() + "/protocol/openid-connect/token";
+            },
+            logout: function () {
+              return getRealmUrl() + "/protocol/openid-connect/logout";
+            },
+            checkSessionIframe: function () {
+              var src =
+                getRealmUrl() +
+                "/protocol/openid-connect/login-status-iframe.html";
+              if (kc.iframeVersion) {
+                src = src + "?version=" + kc.iframeVersion;
+              }
+              return src;
+            },
+            thirdPartyCookiesIframe: function () {
+              var src =
+                getRealmUrl() +
+                "/protocol/openid-connect/3p-cookies/step1.html";
+              if (kc.iframeVersion) {
+                src = src + "?version=" + kc.iframeVersion;
+              }
+              return src;
+            },
+            register: function () {
+              return getRealmUrl() + "/protocol/openid-connect/registrations";
+            },
+            userinfo: function () {
+              return getRealmUrl() + "/protocol/openid-connect/userinfo";
+            },
+          };
+        } else {
+          kc.endpoints = {
+            authorize: function () {
+              return oidcConfiguration.authorization_endpoint;
+            },
+            token: function () {
+              return oidcConfiguration.token_endpoint;
+            },
+            logout: function () {
+              if (!oidcConfiguration.end_session_endpoint) {
+                throw "Not supported by the OIDC server";
+              }
+              return oidcConfiguration.end_session_endpoint;
+            },
+            checkSessionIframe: function () {
+              if (!oidcConfiguration.check_session_iframe) {
+                throw "Not supported by the OIDC server";
+              }
+              return oidcConfiguration.check_session_iframe;
+            },
+            register: function () {
+              throw 'Redirection to "Register user" page not supported in standard OIDC mode';
+            },
+            userinfo: function () {
+              if (!oidcConfiguration.userinfo_endpoint) {
+                throw "Not supported by the OIDC server";
+              }
+              return oidcConfiguration.userinfo_endpoint;
+            },
+          };
+        }
+      }
+
+      if (configUrl) {
+        var req = new XMLHttpRequest();
+        req.open("GET", configUrl, true);
+        req.setRequestHeader("Accept", "application/json");
+
+        req.onreadystatechange = function () {
+          if (req.readyState == 4) {
+            if (req.status == 200 || fileLoaded(req)) {
+              var config = JSON.parse(req.responseText);
+
+              kc.authServerUrl = config["auth-server-url"];
+              kc.realm = config["realm"];
+              kc.clientId = config["resource"];
+              setupOidcEndoints(null);
+              promise.setSuccess();
+            } else {
+              promise.setError();
+            }
+          }
+        };
+
+        req.send();
+      } else {
+        if (!config.clientId) {
+          throw "clientId missing";
+        }
+
+        kc.clientId = config.clientId;
+
+        var oidcProvider = config["oidcProvider"];
+        if (!oidcProvider) {
+          if (!config["url"]) {
+            var scripts = document.getElementsByTagName("script");
+            for (var i = 0; i < scripts.length; i++) {
+              if (scripts[i].src.match(/.*keycloak\.js/)) {
+                config.url = scripts[i].src.substr(
+                  0,
+                  scripts[i].src.indexOf("/js/keycloak.js")
+                );
+                break;
+              }
+            }
+          }
+          if (!config.realm) {
+            throw "realm missing";
+          }
+
+          kc.authServerUrl = config.url;
+          kc.realm = config.realm;
+          setupOidcEndoints(null);
+          promise.setSuccess();
+        } else {
+          if (typeof oidcProvider === "string") {
+            var oidcProviderConfigUrl;
+            if (oidcProvider.charAt(oidcProvider.length - 1) == "/") {
+              oidcProviderConfigUrl =
+                oidcProvider + ".well-known/openid-configuration";
+            } else {
+              oidcProviderConfigUrl =
+                oidcProvider + "/.well-known/openid-configuration";
+            }
+            var req = new XMLHttpRequest();
+            req.open("GET", oidcProviderConfigUrl, true);
+            req.setRequestHeader("Accept", "application/json");
+
+            req.onreadystatechange = function () {
+              if (req.readyState == 4) {
+                if (req.status == 200 || fileLoaded(req)) {
+                  var oidcProviderConfig = JSON.parse(req.responseText);
+                  setupOidcEndoints(oidcProviderConfig);
+                  promise.setSuccess();
+                } else {
+                  promise.setError();
+                }
+              }
+            };
+
+            req.send();
+          } else {
+            setupOidcEndoints(oidcProvider);
+            promise.setSuccess();
+          }
+        }
+      }
+
+      return promise.promise;
+    }
+
+    function fileLoaded(xhr) {
+      return (
+        xhr.status == 0 &&
+        xhr.responseText &&
+        xhr.responseURL.startsWith("file:")
+      );
+    }
+
+    function setToken(token, refreshToken, idToken, timeLocal) {
+      if (kc.tokenTimeoutHandle) {
+        clearTimeout(kc.tokenTimeoutHandle);
+        kc.tokenTimeoutHandle = null;
+      }
+
+      if (refreshToken) {
+        kc.refreshToken = refreshToken;
+        kc.refreshTokenParsed = decodeToken(refreshToken);
+      } else {
+        delete kc.refreshToken;
+        delete kc.refreshTokenParsed;
+      }
+
+      if (idToken) {
+        kc.idToken = idToken;
+        kc.idTokenParsed = decodeToken(idToken);
+      } else {
+        delete kc.idToken;
+        delete kc.idTokenParsed;
+      }
+
+      if (token) {
+        kc.token = token;
+        kc.tokenParsed = decodeToken(token);
+        kc.sessionId = kc.tokenParsed.session_state;
+        kc.authenticated = true;
+        kc.subject = kc.tokenParsed.sub;
+        kc.realmAccess = kc.tokenParsed.realm_access;
+        kc.resourceAccess = kc.tokenParsed.resource_access;
+
+        if (timeLocal) {
+          kc.timeSkew = Math.floor(timeLocal / 1000) - kc.tokenParsed.iat;
+        }
+
+        if (kc.timeSkew != null) {
+          logInfo(
+            "[KEYCLOAK] Estimated time difference between browser and server is " +
+              kc.timeSkew +
+              " seconds"
+          );
+
+          if (kc.onTokenExpired) {
+            var expiresIn =
+              (kc.tokenParsed["exp"] -
+                new Date().getTime() / 1000 +
+                kc.timeSkew) *
+              1000;
+            logInfo(
+              "[KEYCLOAK] Token expires in " +
+                Math.round(expiresIn / 1000) +
+                " s"
+            );
+            if (expiresIn <= 0) {
+              kc.onTokenExpired();
+            } else {
+              kc.tokenTimeoutHandle = setTimeout(kc.onTokenExpired, expiresIn);
+            }
+          }
+        }
+      } else {
+        delete kc.token;
+        delete kc.tokenParsed;
+        delete kc.subject;
+        delete kc.realmAccess;
+        delete kc.resourceAccess;
+
+        kc.authenticated = false;
+      }
+    }
+
+    function decodeToken(str) {
+      str = str.split(".")[1];
+
+      str = str.replace(/-/g, "+");
+      str = str.replace(/_/g, "/");
+      switch (str.length % 4) {
+        case 0:
+          break;
+        case 2:
+          str += "==";
+          break;
+        case 3:
+          str += "=";
+          break;
+        default:
+          throw "Invalid token";
+      }
+
+      str = decodeURIComponent(escape(atob(str)));
+
+      str = JSON.parse(str);
+      return str;
+    }
+
+    function createUUID() {
+      var hexDigits = "0123456789abcdef";
+      var s = generateRandomString(36, hexDigits).split("");
+      s[14] = "4";
+      s[19] = hexDigits.substr((s[19] & 0x3) | 0x8, 1);
+      s[8] = s[13] = s[18] = s[23] = "-";
+      var uuid = s.join("");
+      return uuid;
+    }
+
+    function parseCallback(url) {
+      var oauth = parseCallbackUrl(url);
+      if (!oauth) {
+        return;
+      }
+
+      var oauthState = callbackStorage.get(oauth.state);
+
+      if (oauthState) {
+        oauth.valid = true;
+        oauth.redirectUri = oauthState.redirectUri;
+        oauth.storedNonce = oauthState.nonce;
+        oauth.prompt = oauthState.prompt;
+        oauth.pkceCodeVerifier = oauthState.pkceCodeVerifier;
+      }
+
+      return oauth;
+    }
+
+    function parseCallbackUrl(url) {
+      var supportedParams;
+      switch (kc.flow) {
+        case "standard":
+          supportedParams = [
+            "code",
+            "state",
+            "session_state",
+            "kc_action_status",
+          ];
+          break;
+        case "implicit":
+          supportedParams = [
+            "access_token",
+            "token_type",
+            "id_token",
+            "state",
+            "session_state",
+            "expires_in",
+            "kc_action_status",
+          ];
+          break;
+        case "hybrid":
+          supportedParams = [
+            "access_token",
+            "token_type",
+            "id_token",
+            "code",
+            "state",
+            "session_state",
+            "expires_in",
+            "kc_action_status",
+          ];
+          break;
+      }
+
+      supportedParams.push("error");
+      supportedParams.push("error_description");
+      supportedParams.push("error_uri");
+
+      var queryIndex = url.indexOf("?");
+      var fragmentIndex = url.indexOf("#");
+
+      var newUrl;
+      var parsed;
+
+      if (kc.responseMode === "query" && queryIndex !== -1) {
+        newUrl = url.substring(0, queryIndex);
+        parsed = parseCallbackParams(
+          url.substring(
+            queryIndex + 1,
+            fragmentIndex !== -1 ? fragmentIndex : url.length
+          ),
+          supportedParams
+        );
+        if (parsed.paramsString !== "") {
+          newUrl += "?" + parsed.paramsString;
+        }
+        if (fragmentIndex !== -1) {
+          newUrl += url.substring(fragmentIndex);
+        }
+      } else if (kc.responseMode === "fragment" && fragmentIndex !== -1) {
+        newUrl = url.substring(0, fragmentIndex);
+        parsed = parseCallbackParams(
+          url.substring(fragmentIndex + 1),
+          supportedParams
+        );
+        if (parsed.paramsString !== "") {
+          newUrl += "#" + parsed.paramsString;
+        }
+      }
+
+      if (parsed && parsed.oauthParams) {
+        if (kc.flow === "standard" || kc.flow === "hybrid") {
+          if (
+            (parsed.oauthParams.code || parsed.oauthParams.error) &&
+            parsed.oauthParams.state
+          ) {
+            parsed.oauthParams.newUrl = newUrl;
+            return parsed.oauthParams;
+          }
+        } else if (kc.flow === "implicit") {
+          if (
+            (parsed.oauthParams.access_token || parsed.oauthParams.error) &&
+            parsed.oauthParams.state
+          ) {
+            parsed.oauthParams.newUrl = newUrl;
+            return parsed.oauthParams;
+          }
+        }
+      }
+    }
+
+    function parseCallbackParams(paramsString, supportedParams) {
+      var p = paramsString.split("&");
+      var result = {
+        paramsString: "",
+        oauthParams: {},
+      };
+      for (var i = 0; i < p.length; i++) {
+        var split = p[i].indexOf("=");
+        var key = p[i].slice(0, split);
+        if (supportedParams.indexOf(key) !== -1) {
+          result.oauthParams[key] = p[i].slice(split + 1);
+        } else {
+          if (result.paramsString !== "") {
+            result.paramsString += "&";
+          }
+          result.paramsString += p[i];
+        }
+      }
+      return result;
+    }
+
+    function createPromise() {
+      // Need to create a native Promise which also preserves the
+      // interface of the custom promise type previously used by the API
+      var p = {
+        setSuccess: function (result) {
+          p.resolve(result);
+        },
+
+        setError: function (result) {
+          p.reject(result);
+        },
+      };
+      p.promise = new Promise(function (resolve, reject) {
+        p.resolve = resolve;
+        p.reject = reject;
+      });
+
+      p.promise.success = function (callback) {
+        logPromiseDeprecation();
+
+        this.then(function handleSuccess(value) {
+          callback(value);
+        });
+
+        return this;
+      };
+
+      p.promise.error = function (callback) {
+        logPromiseDeprecation();
+
+        this.catch(function handleError(error) {
+          callback(error);
+        });
+
+        return this;
+      };
+
+      return p;
+    }
+
+    // Function to extend existing native Promise with timeout
+    function applyTimeoutToPromise(promise, timeout, errorMessage) {
+      var timeoutHandle = null;
+      var timeoutPromise = new Promise(function (resolve, reject) {
+        timeoutHandle = setTimeout(function () {
+          reject({
+            error:
+              errorMessage ||
+              "Promise is not settled within timeout of " + timeout + "ms",
+          });
+        }, timeout);
+      });
+
+      return Promise.race([promise, timeoutPromise]).finally(function () {
+        clearTimeout(timeoutHandle);
+      });
+    }
+
+    function setupCheckLoginIframe() {
+      var promise = createPromise();
+
+      if (!loginIframe.enable) {
+        promise.setSuccess();
+        return promise.promise;
+      }
+
+      if (loginIframe.iframe) {
+        promise.setSuccess();
+        return promise.promise;
+      }
+
+      var iframe = document.createElement("iframe");
+      loginIframe.iframe = iframe;
+
+      iframe.onload = function () {
+        var authUrl = kc.endpoints.authorize();
+        if (authUrl.charAt(0) === "/") {
+          loginIframe.iframeOrigin = getOrigin();
+        } else {
+          loginIframe.iframeOrigin = authUrl.substring(
+            0,
+            authUrl.indexOf("/", 8)
+          );
+        }
+        promise.setSuccess();
+      };
+
+      var src = kc.endpoints.checkSessionIframe();
+      iframe.setAttribute("src", src);
+      iframe.setAttribute("title", "keycloak-session-iframe");
+      iframe.style.display = "none";
+      document.body.appendChild(iframe);
+
+      var messageCallback = function (event) {
+        if (
+          event.origin !== loginIframe.iframeOrigin ||
+          loginIframe.iframe.contentWindow !== event.source
+        ) {
+          return;
+        }
+
+        if (
+          !(
+            event.data == "unchanged" ||
+            event.data == "changed" ||
+            event.data == "error"
+          )
+        ) {
+          return;
+        }
+
+        if (event.data != "unchanged") {
+          kc.clearToken();
+        }
+
+        var callbacks = loginIframe.callbackList.splice(
+          0,
+          loginIframe.callbackList.length
+        );
+
+        for (var i = callbacks.length - 1; i >= 0; --i) {
+          var promise = callbacks[i];
+          if (event.data == "error") {
+            promise.setError();
+          } else {
+            promise.setSuccess(event.data == "unchanged");
+          }
+        }
+      };
+
+      window.addEventListener("message", messageCallback, false);
+
+      return promise.promise;
+    }
+
+    function scheduleCheckIframe() {
+      if (loginIframe.enable) {
+        if (kc.token) {
+          setTimeout(function () {
+            checkLoginIframe().then(function (unchanged) {
+              if (unchanged) {
+                scheduleCheckIframe();
+              }
+            });
+          }, loginIframe.interval * 1000);
+        }
+      }
+    }
+
+    function checkLoginIframe() {
+      var promise = createPromise();
+
+      if (loginIframe.iframe && loginIframe.iframeOrigin) {
+        var msg = kc.clientId + " " + (kc.sessionId ? kc.sessionId : "");
+        loginIframe.callbackList.push(promise);
+        var origin = loginIframe.iframeOrigin;
+        if (loginIframe.callbackList.length == 1) {
+          loginIframe.iframe.contentWindow.postMessage(msg, origin);
+        }
+      } else {
+        promise.setSuccess();
+      }
+
+      return promise.promise;
+    }
+
+    function check3pCookiesSupported() {
+      var promise = createPromise();
+
+      if (loginIframe.enable || kc.silentCheckSsoRedirectUri) {
+        var iframe = document.createElement("iframe");
+        iframe.setAttribute("src", kc.endpoints.thirdPartyCookiesIframe());
+        iframe.setAttribute("title", "keycloak-3p-check-iframe");
+        iframe.style.display = "none";
+        document.body.appendChild(iframe);
+
+        var messageCallback = function (event) {
+          if (iframe.contentWindow !== event.source) {
+            return;
+          }
+
+          if (event.data !== "supported" && event.data !== "unsupported") {
+            return;
+          } else if (event.data === "unsupported") {
+            loginIframe.enable = false;
+            if (kc.silentCheckSsoFallback) {
+              kc.silentCheckSsoRedirectUri = false;
+            }
+            logWarn(
+              "[KEYCLOAK] 3rd party cookies aren't supported by this browser. checkLoginIframe and " +
+                "silent check-sso are not available."
+            );
+          }
+
+          document.body.removeChild(iframe);
+          window.removeEventListener("message", messageCallback);
+          promise.setSuccess();
+        };
+
+        window.addEventListener("message", messageCallback, false);
+      } else {
+        promise.setSuccess();
+      }
+
+      return applyTimeoutToPromise(
+        promise.promise,
+        kc.messageReceiveTimeout,
+        "Timeout when waiting for 3rd party check iframe message."
+      );
+    }
+
+    function loadAdapter(type) {
+      if (!type || type == "default") {
+        return {
+          login: function (options) {
+            window.location.replace(kc.createLoginUrl(options));
+            return createPromise().promise;
+          },
+
+          logout: function (options) {
+            window.location.replace(kc.createLogoutUrl(options));
+            return createPromise().promise;
+          },
+
+          register: function (options) {
+            window.location.replace(kc.createRegisterUrl(options));
+            return createPromise().promise;
+          },
+
+          accountManagement: function () {
+            var accountUrl = kc.createAccountUrl();
+            if (typeof accountUrl !== "undefined") {
+              window.location.href = accountUrl;
+            } else {
+              throw "Not supported by the OIDC server";
+            }
+            return createPromise().promise;
+          },
+
+          redirectUri: function (options, encodeHash) {
+            if (arguments.length == 1) {
+              encodeHash = true;
+            }
+
+            if (options && options.redirectUri) {
+              return options.redirectUri;
+            } else if (kc.redirectUri) {
+              return kc.redirectUri;
+            } else {
+              return location.href;
+            }
+          },
+        };
+      }
+
+      if (type == "cordova") {
+        loginIframe.enable = false;
+        var cordovaOpenWindowWrapper = function (loginUrl, target, options) {
+          if (window.cordova && window.cordova.InAppBrowser) {
+            // Use inappbrowser for IOS and Android if available
+            return window.cordova.InAppBrowser.open(loginUrl, target, options);
+          } else {
+            return window.open(loginUrl, target, options);
+          }
+        };
+
+        var shallowCloneCordovaOptions = function (userOptions) {
+          if (userOptions && userOptions.cordovaOptions) {
+            return Object.keys(userOptions.cordovaOptions).reduce(function (
+              options,
+              optionName
+            ) {
+              options[optionName] = userOptions.cordovaOptions[optionName];
+              return options;
+            },
+            {});
+          } else {
+            return {};
+          }
+        };
+
+        var formatCordovaOptions = function (cordovaOptions) {
+          return Object.keys(cordovaOptions)
+            .reduce(function (options, optionName) {
+              options.push(optionName + "=" + cordovaOptions[optionName]);
+              return options;
+            }, [])
+            .join(",");
+        };
+
+        var createCordovaOptions = function (userOptions) {
+          var cordovaOptions = shallowCloneCordovaOptions(userOptions);
+          cordovaOptions.location = "no";
+          if (userOptions && userOptions.prompt == "none") {
+            cordovaOptions.hidden = "yes";
+          }
+          return formatCordovaOptions(cordovaOptions);
+        };
+
+        return {
+          login: function (options) {
+            var promise = createPromise();
+
+            var cordovaOptions = createCordovaOptions(options);
+            var loginUrl = kc.createLoginUrl(options);
+            var ref = cordovaOpenWindowWrapper(
+              loginUrl,
+              "_blank",
+              cordovaOptions
+            );
+            var completed = false;
+
+            var closed = false;
+            var closeBrowser = function () {
+              closed = true;
+              ref.close();
+            };
+
+            ref.addEventListener("loadstart", function (event) {
+              if (event.url.indexOf("http://localhost") == 0) {
+                var callback = parseCallback(event.url);
+                processCallback(callback, promise);
+                closeBrowser();
+                completed = true;
+              }
+            });
+
+            ref.addEventListener("loaderror", function (event) {
+              if (!completed) {
+                if (event.url.indexOf("http://localhost") == 0) {
+                  var callback = parseCallback(event.url);
+                  processCallback(callback, promise);
+                  closeBrowser();
+                  completed = true;
+                } else {
+                  promise.setError();
+                  closeBrowser();
+                }
+              }
+            });
+
+            ref.addEventListener("exit", function (event) {
+              if (!closed) {
+                promise.setError({
+                  reason: "closed_by_user",
+                });
+              }
+            });
+
+            return promise.promise;
+          },
+
+          logout: function (options) {
+            var promise = createPromise();
+
+            var logoutUrl = kc.createLogoutUrl(options);
+            var ref = cordovaOpenWindowWrapper(
+              logoutUrl,
+              "_blank",
+              "location=no,hidden=yes,clearcache=yes"
+            );
+
+            var error;
+
+            ref.addEventListener("loadstart", function (event) {
+              if (event.url.indexOf("http://localhost") == 0) {
+                ref.close();
+              }
+            });
+
+            ref.addEventListener("loaderror", function (event) {
+              if (event.url.indexOf("http://localhost") == 0) {
+                ref.close();
+              } else {
+                error = true;
+                ref.close();
+              }
+            });
+
+            ref.addEventListener("exit", function (event) {
+              if (error) {
+                promise.setError();
+              } else {
+                kc.clearToken();
+                promise.setSuccess();
+              }
+            });
+
+            return promise.promise;
+          },
+
+          register: function (options) {
+            var promise = createPromise();
+            var registerUrl = kc.createRegisterUrl();
+            var cordovaOptions = createCordovaOptions(options);
+            var ref = cordovaOpenWindowWrapper(
+              registerUrl,
+              "_blank",
+              cordovaOptions
+            );
+            ref.addEventListener("loadstart", function (event) {
+              if (event.url.indexOf("http://localhost") == 0) {
+                ref.close();
+                var oauth = parseCallback(event.url);
+                processCallback(oauth, promise);
+              }
+            });
+            return promise.promise;
+          },
+
+          accountManagement: function () {
+            var accountUrl = kc.createAccountUrl();
+            if (typeof accountUrl !== "undefined") {
+              var ref = cordovaOpenWindowWrapper(
+                accountUrl,
+                "_blank",
+                "location=no"
+              );
+              ref.addEventListener("loadstart", function (event) {
+                if (event.url.indexOf("http://localhost") == 0) {
+                  ref.close();
+                }
+              });
+            } else {
+              throw "Not supported by the OIDC server";
+            }
+          },
+
+          redirectUri: function (options) {
+            return "http://localhost";
+          },
+        };
+      }
+
+      if (type == "cordova-native") {
+        loginIframe.enable = false;
+
+        return {
+          login: function (options) {
+            var promise = createPromise();
+            var loginUrl = kc.createLoginUrl(options);
+
+            universalLinks.subscribe("keycloak", function (event) {
+              universalLinks.unsubscribe("keycloak");
+              window.cordova.plugins.browsertab.close();
+              var oauth = parseCallback(event.url);
+              processCallback(oauth, promise);
+            });
+
+            window.cordova.plugins.browsertab.openUrl(loginUrl);
+            return promise.promise;
+          },
+
+          logout: function (options) {
+            var promise = createPromise();
+            var logoutUrl = kc.createLogoutUrl(options);
+
+            universalLinks.subscribe("keycloak", function (event) {
+              universalLinks.unsubscribe("keycloak");
+              window.cordova.plugins.browsertab.close();
+              kc.clearToken();
+              promise.setSuccess();
+            });
+
+            window.cordova.plugins.browsertab.openUrl(logoutUrl);
+            return promise.promise;
+          },
+
+          register: function (options) {
+            var promise = createPromise();
+            var registerUrl = kc.createRegisterUrl(options);
+            universalLinks.subscribe("keycloak", function (event) {
+              universalLinks.unsubscribe("keycloak");
+              window.cordova.plugins.browsertab.close();
+              var oauth = parseCallback(event.url);
+              processCallback(oauth, promise);
+            });
+            window.cordova.plugins.browsertab.openUrl(registerUrl);
+            return promise.promise;
+          },
+
+          accountManagement: function () {
+            var accountUrl = kc.createAccountUrl();
+            if (typeof accountUrl !== "undefined") {
+              window.cordova.plugins.browsertab.openUrl(accountUrl);
+            } else {
+              throw "Not supported by the OIDC server";
+            }
+          },
+
+          redirectUri: function (options) {
+            if (options && options.redirectUri) {
+              return options.redirectUri;
+            } else if (kc.redirectUri) {
+              return kc.redirectUri;
+            } else {
+              return "http://localhost";
+            }
+          },
+        };
+      }
+
+      throw "invalid adapter type: " + type;
+    }
+
+    var LocalStorage = function () {
+      if (!(this instanceof LocalStorage)) {
+        return new LocalStorage();
+      }
+
+      localStorage.setItem("kc-test", "test");
+      localStorage.removeItem("kc-test");
+
+      var cs = this;
+
+      function clearExpired() {
+        var time = new Date().getTime();
+        for (var i = 0; i < localStorage.length; i++) {
+          var key = localStorage.key(i);
+          if (key && key.indexOf("kc-callback-") == 0) {
+            var value = localStorage.getItem(key);
+            if (value) {
+              try {
+                var expires = JSON.parse(value).expires;
+                if (!expires || expires < time) {
+                  localStorage.removeItem(key);
+                }
+              } catch (err) {
+                localStorage.removeItem(key);
+              }
+            }
+          }
+        }
+      }
+
+      cs.get = function (state) {
+        if (!state) {
+          return;
+        }
+
+        var key = "kc-callback-" + state;
+        var value = localStorage.getItem(key);
+        if (value) {
+          localStorage.removeItem(key);
+          value = JSON.parse(value);
+        }
+
+        clearExpired();
+        return value;
+      };
+
+      cs.add = function (state) {
+        clearExpired();
+
+        var key = "kc-callback-" + state.state;
+        state.expires = new Date().getTime() + 60 * 60 * 1000;
+        localStorage.setItem(key, JSON.stringify(state));
+      };
+    };
+
+    var CookieStorage = function () {
+      if (!(this instanceof CookieStorage)) {
+        return new CookieStorage();
+      }
+
+      var cs = this;
+
+      cs.get = function (state) {
+        if (!state) {
+          return;
+        }
+
+        var value = getCookie("kc-callback-" + state);
+        setCookie("kc-callback-" + state, "", cookieExpiration(-100));
+        if (value) {
+          return JSON.parse(value);
+        }
+      };
+
+      cs.add = function (state) {
+        setCookie(
+          "kc-callback-" + state.state,
+          JSON.stringify(state),
+          cookieExpiration(60)
+        );
+      };
+
+      cs.removeItem = function (key) {
+        setCookie(key, "", cookieExpiration(-100));
+      };
+
+      var cookieExpiration = function (minutes) {
+        var exp = new Date();
+        exp.setTime(exp.getTime() + minutes * 60 * 1000);
+        return exp;
+      };
+
+      var getCookie = function (key) {
+        var name = key + "=";
+        var ca = document.cookie.split(";");
+        for (var i = 0; i < ca.length; i++) {
+          var c = ca[i];
+          while (c.charAt(0) == " ") {
+            c = c.substring(1);
+          }
+          if (c.indexOf(name) == 0) {
+            return c.substring(name.length, c.length);
+          }
+        }
+        return "";
+      };
+
+      var setCookie = function (key, value, expirationDate) {
+        var cookie =
+          key +
+          "=" +
+          value +
+          "; " +
+          "expires=" +
+          expirationDate.toUTCString() +
+          "; ";
+        document.cookie = cookie;
+      };
+    };
+
+    function createCallbackStorage() {
+      try {
+        return new LocalStorage();
+      } catch (err) {}
+
+      return new CookieStorage();
+    }
+
+    function createLogger(fn) {
+      return function () {
+        if (kc.enableLogging) {
+          fn.apply(console, Array.prototype.slice.call(arguments));
+        }
+      };
+    }
+  }
+
+  return Keycloak;
+});
diff --git a/static/keycloak.json b/static/keycloak.json
new file mode 100644
index 0000000..d143f91
--- /dev/null
+++ b/static/keycloak.json
@@ -0,0 +1,9 @@
+{
+    "realm": "bma-ehr",
+    "auth-server-url": "https://id.frappet.synology.me",
+    "ssl-required": "external",
+    "resource": "bma-ehr",
+    "public-client": true,
+    "client_secret": "tF0huP4MylOSMVZEohwPMI8DDttW66A7",
+    "realm-public-key":"MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAvYg0ZJvH6HgNOzyPp7PCvY3bJwD9WdsNn6gZbuvIfqJQZ8iSH1t0p3fgODO/fqwcj9UFeh1bVFOSjuW+JpnPehROqzt81KNl9zLLNXoN4LimReQHaMM3dU7DCbRylgVCouIDvObyjg8G+Cy5lZvFKWym/DPwGVpSdbvDZJ83qxq2dp7GJXS8PhOvA+MB1K009/jW5pBTUwNArLjoFccr+gIYIiOJDg2rYyIF3fDkwyWkuxr6xRt10+BRJytselwy/18kbDuJxVPaapdgTXI6wLzx7HWcDk30n5EvhJEumnIPpRst8gucqNYmB4MH+vsyoxV5WLuO3qmVRzFbtAppRQIDAQAB"
+  }
\ No newline at end of file
diff --git a/tsconfig.json b/tsconfig.json
new file mode 100644
index 0000000..3219961
--- /dev/null
+++ b/tsconfig.json
@@ -0,0 +1,18 @@
+{
+  "compilerOptions": {
+    "incremental": true,
+    "outDir": "dist",
+    "lib": ["ESNext", "DOM", "DOM.Iterable"],
+    "target": "ESNext",
+    "module": "NodeNext",
+    "moduleResolution": "NodeNext",
+    "strictPropertyInitialization": false,
+    "strict": true,
+    "esModuleInterop": true,
+    "forceConsistentCasingInFileNames": true,
+    "experimentalDecorators": true,
+    "emitDecoratorMetadata": true,
+    "resolveJsonModule": true,
+    "skipLibCheck": true
+  }
+}
diff --git a/tsoa.json b/tsoa.json
new file mode 100644
index 0000000..b6ba1bd
--- /dev/null
+++ b/tsoa.json
@@ -0,0 +1,38 @@
+{
+  "entryFile": "src/app.ts",
+  "noImplicitAdditionalProperties": "throw-on-extras",
+  "controllerPathGlobs": ["src/controllers/*Controller.ts"],
+  "spec": {
+    "outputDirectory": "src",
+    "specVersion": 3,
+    "spec": {
+      "info": {
+        "title": "bma-ehr-evaluation - API",
+        "version": "0.0.1",
+        "description": "ระบบการประเมินบุคคล (evaluation: DV)",
+        "license": {
+          "name": "by Frappet",
+          "url": "https://frappet.com"
+        }
+      },
+      "basePath": "/"
+    },
+    "securityDefinitions": {
+      "bearerAuth": {
+        "type": "apiKey",
+        "name": "Authorization",
+        "description": "Keycloak Bearer Token",
+        "in": "header"
+      }
+    },
+    "tags": [
+        {
+          "name": "Test", "description": "สำหรับทดสอบ" 
+        }
+    ]
+  },
+  "routes": {
+    "routesDir": "src/",
+    "authenticationModule": "src/middlewares/auth.ts"
+  }
+}