diff --git a/package-lock.json b/package-lock.json index 9a66a43..beb9411 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,6 +22,7 @@ "sqlite3": "^5.1.6" }, "devDependencies": { + "@nestjs/cli": "^10.4.9", "@types/express": "^4.17.17", "@types/joi": "^17.2.2", "@types/node": "^22.10.2", @@ -33,6 +34,208 @@ "npm": ">=10.9.0" } }, + "node_modules/@angular-devkit/core": { + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@angular-devkit/core/-/core-17.3.11.tgz", + "integrity": "sha512-vTNDYNsLIWpYk2I969LMQFH29GTsLzxNk/0cLw5q56ARF0v5sIWfHYwGTS88jdDqIpuuettcSczbxeA7EuAmqQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "8.12.0", + "ajv-formats": "2.1.1", + "jsonc-parser": "3.2.1", + "picomatch": "4.0.1", + "rxjs": "7.8.1", + "source-map": "0.7.4" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + }, + "peerDependencies": { + "chokidar": "^3.5.2" + }, + "peerDependenciesMeta": { + "chokidar": { + "optional": true + } + } + }, + "node_modules/@angular-devkit/schematics": { + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics/-/schematics-17.3.11.tgz", + "integrity": "sha512-I5wviiIqiFwar9Pdk30Lujk8FczEEc18i22A5c6Z9lbmhPQdTroDnEQdsfXjy404wPe8H62s0I15o4pmMGfTYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "17.3.11", + "jsonc-parser": "3.2.1", + "magic-string": "0.30.8", + "ora": "5.4.1", + "rxjs": "7.8.1" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics-cli": { + "version": "17.3.11", + "resolved": "https://registry.npmjs.org/@angular-devkit/schematics-cli/-/schematics-cli-17.3.11.tgz", + "integrity": "sha512-kcOMqp+PHAKkqRad7Zd7PbpqJ0LqLaNZdY1+k66lLWmkEBozgq8v4ASn/puPWf9Bo0HpCiK+EzLf0VHE8Z/y6Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "17.3.11", + "@angular-devkit/schematics": "17.3.11", + "ansi-colors": "4.1.3", + "inquirer": "9.2.15", + "symbol-observable": "4.0.0", + "yargs-parser": "21.1.1" + }, + "bin": { + "schematics": "bin/schematics.js" + }, + "engines": { + "node": "^18.13.0 || >=20.9.0", + "npm": "^6.11.0 || ^7.5.6 || >=8.0.0", + "yarn": ">= 1.13.0" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/chalk": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.0.tgz", + "integrity": "sha512-ZkD35Mx92acjB2yNJgziGqT9oKHEOxjTBTDRpOsRWtdecL/0jM3z5kM/CTzHWvHIen1GvkM85p6TuFfDGfc8/Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": "^12.17.0 || ^14.13 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/cli-width": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-4.1.0.tgz", + "integrity": "sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 12" + } + }, + "node_modules/@angular-devkit/schematics-cli/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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/inquirer": { + "version": "9.2.15", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-9.2.15.tgz", + "integrity": "sha512-vI2w4zl/mDluHt9YEQ/543VTCwPKWiHzKtm9dM2V0NdFcqEexDAjUHzO1oA60HRNaVifGXXM1tRRNluLVHa0Kg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@ljharb/through": "^2.3.12", + "ansi-escapes": "^4.3.2", + "chalk": "^5.3.0", + "cli-cursor": "^3.1.0", + "cli-width": "^4.1.0", + "external-editor": "^3.1.0", + "figures": "^3.2.0", + "lodash": "^4.17.21", + "mute-stream": "1.0.0", + "ora": "^5.4.1", + "run-async": "^3.0.0", + "rxjs": "^7.8.1", + "string-width": "^4.2.3", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^6.2.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/mute-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-1.0.0.tgz", + "integrity": "sha512-avsJQhyd+680gKXyG/sQc0nXaC6rBkPOfyHYcFb9+hdkqQkR9bdnkJ0AMZhke0oesPqIO+mFFJ+IdBc7mst4IA==", + "dev": true, + "license": "ISC", + "engines": { + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/@angular-devkit/schematics-cli/node_modules/run-async": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-3.0.0.tgz", + "integrity": "sha512-540WwVDOMxA6dN6We19EcT9sc3hkXPw5mzRNGM3FkdN/vtE9NFvj5lFAPNwUDmJjXidm3v7TC1cTE7t17Ulm1Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/@babel/code-frame": { + "version": "7.26.2", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", + "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/helper-validator-identifier": "^7.25.9", + "js-tokens": "^4.0.0", + "picocolors": "^1.0.0" + }, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@babel/helper-validator-identifier": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz", + "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@colors/colors": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", + "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=0.1.90" + } + }, "node_modules/@eslint-community/eslint-utils": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", @@ -230,6 +433,186 @@ "dev": true, "license": "BSD-3-Clause" }, + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "dev": true, + "license": "ISC", + "dependencies": { + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "dev": true, + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", + "dev": true, + "license": "MIT", + "dependencies": { + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@isaacs/cliui/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^6.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" + } + }, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.8", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", + "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" + }, + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0.0" + } + }, + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" + } + }, + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@ljharb/through": { + "version": "2.3.13", + "resolved": "https://registry.npmjs.org/@ljharb/through/-/through-2.3.13.tgz", + "integrity": "sha512-/gKJun8NNiWGZJkGzI/Ragc53cOdcLNdzjLaIa+GEjguQs0ulsurx8WN0jijdK9yPqDvziX995sMRLyLt1uZMQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/@lukeed/csprng": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/@lukeed/csprng/-/csprng-1.1.0.tgz", @@ -239,6 +622,109 @@ "node": ">=8" } }, + "node_modules/@nestjs/cli": { + "version": "10.4.9", + "resolved": "https://registry.npmjs.org/@nestjs/cli/-/cli-10.4.9.tgz", + "integrity": "sha512-s8qYd97bggqeK7Op3iD49X2MpFtW4LVNLAwXFkfbRxKME6IYT7X0muNTJ2+QfI8hpbNx9isWkrLWIp+g5FOhiA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "17.3.11", + "@angular-devkit/schematics": "17.3.11", + "@angular-devkit/schematics-cli": "17.3.11", + "@nestjs/schematics": "^10.0.1", + "chalk": "4.1.2", + "chokidar": "3.6.0", + "cli-table3": "0.6.5", + "commander": "4.1.1", + "fork-ts-checker-webpack-plugin": "9.0.2", + "glob": "10.4.5", + "inquirer": "8.2.6", + "node-emoji": "1.11.0", + "ora": "5.4.1", + "tree-kill": "1.2.2", + "tsconfig-paths": "4.2.0", + "tsconfig-paths-webpack-plugin": "4.2.0", + "typescript": "5.7.2", + "webpack": "5.97.1", + "webpack-node-externals": "3.0.0" + }, + "bin": { + "nest": "bin/nest.js" + }, + "engines": { + "node": ">= 16.14" + }, + "peerDependencies": { + "@swc/cli": "^0.1.62 || ^0.3.0 || ^0.4.0 || ^0.5.0", + "@swc/core": "^1.3.62" + }, + "peerDependenciesMeta": { + "@swc/cli": { + "optional": true + }, + "@swc/core": { + "optional": true + } + } + }, + "node_modules/@nestjs/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/@nestjs/cli/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", + "dev": true, + "license": "ISC", + "dependencies": { + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" + }, + "bin": { + "glob": "dist/esm/bin.mjs" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@nestjs/cli/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/@nestjs/cli/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/@nestjs/common": { "version": "10.4.15", "resolved": "https://registry.npmjs.org/@nestjs/common/-/common-10.4.15.tgz", @@ -342,6 +828,30 @@ "@nestjs/core": "^10.0.0" } }, + "node_modules/@nestjs/schematics": { + "version": "10.2.3", + "resolved": "https://registry.npmjs.org/@nestjs/schematics/-/schematics-10.2.3.tgz", + "integrity": "sha512-4e8gxaCk7DhBxVUly2PjYL4xC2ifDFexCqq1/u4TtivLGXotVk0wHdYuPYe1tHTHuR1lsOkRbfOCpkdTnigLVg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@angular-devkit/core": "17.3.11", + "@angular-devkit/schematics": "17.3.11", + "comment-json": "4.2.5", + "jsonc-parser": "3.3.1", + "pluralize": "8.0.0" + }, + "peerDependencies": { + "typescript": ">=4.8.2" + } + }, + "node_modules/@nestjs/schematics/node_modules/jsonc-parser": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.3.1.tgz", + "integrity": "sha512-HUgH65KyejrUFPvHFPbqOY0rsFip3Bo5wb4ngvdi1EpCYWUQDC5V+Y7mZws+DLkr4M//zQJoanu1SP+87Dv1oQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", @@ -454,6 +964,17 @@ "npm": ">=5.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==", + "dev": true, + "license": "MIT", + "optional": true, + "engines": { + "node": ">=14" + } + }, "node_modules/@prisma/client": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/@prisma/client/-/client-6.1.0.tgz", @@ -592,6 +1113,35 @@ "@types/node": "*" } }, + "node_modules/@types/eslint": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz", + "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/estree": "*", + "@types/json-schema": "*" + } + }, + "node_modules/@types/eslint-scope": { + "version": "3.7.7", + "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz", + "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint": "*", + "@types/estree": "*" + } + }, + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/express": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", @@ -635,6 +1185,13 @@ "joi": "*" } }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true, + "license": "MIT" + }, "node_modules/@types/mime": { "version": "1.3.5", "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", @@ -696,6 +1253,181 @@ "dev": true, "license": "ISC" }, + "node_modules/@webassemblyjs/ast": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", + "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/helper-numbers": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + } + }, + "node_modules/@webassemblyjs/floating-point-hex-parser": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", + "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-api-error": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", + "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-buffer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", + "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-numbers": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", + "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/floating-point-hex-parser": "1.13.2", + "@webassemblyjs/helper-api-error": "1.13.2", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/helper-wasm-bytecode": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", + "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/helper-wasm-section": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", + "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/wasm-gen": "1.14.1" + } + }, + "node_modules/@webassemblyjs/ieee754": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", + "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@xtuc/ieee754": "^1.2.0" + } + }, + "node_modules/@webassemblyjs/leb128": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", + "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@webassemblyjs/utf8": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", + "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@webassemblyjs/wasm-edit": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", + "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/helper-wasm-section": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-opt": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1", + "@webassemblyjs/wast-printer": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-gen": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", + "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wasm-opt": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", + "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-buffer": "1.14.1", + "@webassemblyjs/wasm-gen": "1.14.1", + "@webassemblyjs/wasm-parser": "1.14.1" + } + }, + "node_modules/@webassemblyjs/wasm-parser": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", + "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/helper-wasm-bytecode": "1.13.2", + "@webassemblyjs/ieee754": "1.13.2", + "@webassemblyjs/leb128": "1.13.2", + "@webassemblyjs/utf8": "1.13.2" + } + }, + "node_modules/@webassemblyjs/wast-printer": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", + "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@webassemblyjs/ast": "1.14.1", + "@xtuc/long": "4.2.2" + } + }, + "node_modules/@xtuc/ieee754": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@xtuc/long": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/abbrev": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", @@ -804,6 +1536,93 @@ "node": ">=8" } }, + "node_modules/ajv": { + "version": "8.12.0", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz", + "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "json-schema-traverse": "^1.0.0", + "require-from-string": "^2.0.2", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/ajv-formats": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz", + "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ajv": "^8.0.0" + }, + "peerDependencies": { + "ajv": "^8.0.0" + }, + "peerDependenciesMeta": { + "ajv": { + "optional": true + } + } + }, + "node_modules/ajv-keywords": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", + "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.3" + }, + "peerDependencies": { + "ajv": "^8.8.2" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-escapes": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz", + "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "type-fest": "^0.21.3" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ansi-escapes/node_modules/type-fest": { + "version": "0.21.3", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", + "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "dev": true, + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ansi-regex": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", @@ -829,6 +1648,33 @@ "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, + "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, + "license": "ISC", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/append-field": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/append-field/-/append-field-1.0.0.tgz", @@ -885,6 +1731,13 @@ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, + "node_modules/array-timsort": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-timsort/-/array-timsort-1.0.3.tgz", + "integrity": "sha512-/+3GRL7dDAGEfM6TseQk/U+mi18TU2Ms9I3UlLdUMhz2hbvGNTKdj9xniwXfUqgYhHxRx0+8UnKkvlNwVU+cWQ==", + "dev": true, + "license": "MIT" + }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", @@ -912,6 +1765,19 @@ ], "license": "MIT" }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/bindings": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz", @@ -981,6 +1847,52 @@ "concat-map": "0.0.1" } }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.24.3", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", + "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "caniuse-lite": "^1.0.30001688", + "electron-to-chromium": "^1.5.73", + "node-releases": "^2.0.19", + "update-browserslist-db": "^1.1.1" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, "node_modules/buffer": { "version": "5.7.1", "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", @@ -1111,6 +2023,25 @@ "license": "ISC", "optional": true }, + "node_modules/call-bind": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", + "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind-apply-helpers": "^1.0.0", + "es-define-property": "^1.0.0", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/call-bind-apply-helpers": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", @@ -1150,6 +2081,27 @@ "node": ">=6" } }, + "node_modules/caniuse-lite": { + "version": "1.0.30001690", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", + "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", @@ -1166,6 +2118,38 @@ "url": "https://github.com/chalk/chalk?sponsor=1" } }, + "node_modules/chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true, + "license": "MIT" + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, + "license": "MIT", + "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" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, "node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", @@ -1175,6 +2159,16 @@ "node": ">=10" } }, + "node_modules/chrome-trace-event": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", + "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.0" + } + }, "node_modules/class-transformer": { "version": "0.5.1", "resolved": "https://registry.npmjs.org/class-transformer/-/class-transformer-0.5.1.tgz", @@ -1191,6 +2185,68 @@ "node": ">=6" } }, + "node_modules/cli-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", + "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "dev": true, + "license": "MIT", + "dependencies": { + "restore-cursor": "^3.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/cli-spinners": { + "version": "2.9.2", + "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", + "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/cli-table3": { + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "string-width": "^4.2.0" + }, + "engines": { + "node": "10.* || >= 12.*" + }, + "optionalDependencies": { + "@colors/colors": "1.5.0" + } + }, + "node_modules/cli-width": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz", + "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">= 10" + } + }, + "node_modules/clone": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz", + "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==", + "dev": true, + "license": "MIT", + "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", @@ -1219,6 +2275,33 @@ "color-support": "bin.js" } }, + "node_modules/commander": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz", + "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, + "node_modules/comment-json": { + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/comment-json/-/comment-json-4.2.5.tgz", + "integrity": "sha512-bKw/r35jR3HGt5PEPm1ljsQQGyCrR8sFGNiN5L+ykDHdpO8Smxkrkla9Yi6NkQyUrb8V54PGhfMs6NrIwtxtdw==", + "dev": true, + "license": "MIT", + "dependencies": { + "array-timsort": "^1.0.3", + "core-util-is": "^1.0.3", + "esprima": "^4.0.1", + "has-own-prop": "^2.0.0", + "repeat-string": "^1.6.1" + }, + "engines": { + "node": ">= 6" + } + }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", @@ -1309,6 +2392,33 @@ "node": ">= 0.10" } }, + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, + "license": "MIT", + "dependencies": { + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/d-fischer" + }, + "peerDependencies": { + "typescript": ">=4.9.5" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, "node_modules/cross-spawn": { "version": "7.0.6", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", @@ -1363,6 +2473,47 @@ "dev": true, "license": "MIT" }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/defaults": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz", + "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==", + "dev": true, + "license": "MIT", + "dependencies": { + "clone": "^1.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/delegates": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", @@ -1446,18 +2597,32 @@ "node": ">= 0.4" } }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", + "dev": true, + "license": "MIT" + }, "node_modules/ee-first": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", "license": "MIT" }, + "node_modules/electron-to-chromium": { + "version": "1.5.75", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.75.tgz", + "integrity": "sha512-Lf3++DumRE/QmweGjU+ZcKqQ+3bKkU/qjaKYhIJKEOhgIO9Xs6IiAQFkfFoj+RhgDk4LUeNsLo6plExHqSyu6Q==", + "dev": true, + "license": "ISC" + }, "node_modules/emoji-regex": { "version": "8.0.0", "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", - "license": "MIT", - "optional": true + "devOptional": true, + "license": "MIT" }, "node_modules/encodeurl": { "version": "2.0.0", @@ -1500,6 +2665,20 @@ "once": "^1.4.0" } }, + "node_modules/enhanced-resolve": { + "version": "5.17.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", + "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/env-paths": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", @@ -1517,6 +2696,16 @@ "license": "MIT", "optional": true }, + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-arrayish": "^0.2.1" + } + }, "node_modules/es-define-property": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", @@ -1535,6 +2724,13 @@ "node": ">= 0.4" } }, + "node_modules/es-module-lexer": { + "version": "1.5.4", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", + "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", + "dev": true, + "license": "MIT" + }, "node_modules/es-object-atoms": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", @@ -1547,6 +2743,16 @@ "node": ">= 0.4" } }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/escape-html": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", @@ -1733,6 +2939,20 @@ "url": "https://opencollective.com/eslint" } }, + "node_modules/esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true, + "license": "BSD-2-Clause", + "bin": { + "esparse": "bin/esparse.js", + "esvalidate": "bin/esvalidate.js" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/esquery": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", @@ -1788,6 +3008,16 @@ "node": ">= 0.6" } }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, "node_modules/execa": { "version": "9.5.2", "resolved": "https://registry.npmjs.org/execa/-/execa-9.5.2.tgz", @@ -1887,6 +3117,21 @@ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", "license": "MIT" }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "engines": { + "node": ">=4" + } + }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", @@ -1958,6 +3203,19 @@ "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==", "license": "MIT" }, + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/finalhandler": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", @@ -2032,6 +3290,65 @@ "dev": true, "license": "ISC" }, + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", + "dev": true, + "license": "ISC", + "dependencies": { + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/fork-ts-checker-webpack-plugin": { + "version": "9.0.2", + "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-9.0.2.tgz", + "integrity": "sha512-Uochze2R8peoN1XqlSi/rGUkDQpRogtLFocP9+PGu68zk1BDAKXfdeCdyVZpgTk8V8WFVQXdEz426VKjXLO1Gg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.16.7", + "chalk": "^4.1.2", + "chokidar": "^3.5.3", + "cosmiconfig": "^8.2.0", + "deepmerge": "^4.2.2", + "fs-extra": "^10.0.0", + "memfs": "^3.4.1", + "minimatch": "^3.0.4", + "node-abort-controller": "^3.0.1", + "schema-utils": "^3.1.1", + "semver": "^7.3.5", + "tapable": "^2.2.1" + }, + "engines": { + "node": ">=12.13.0", + "yarn": ">=1.0.0" + }, + "peerDependencies": { + "typescript": ">3.6.0", + "webpack": "^5.11.0" + } + }, "node_modules/forwarded": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", @@ -2056,6 +3373,21 @@ "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", "license": "MIT" }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", @@ -2068,6 +3400,13 @@ "node": ">= 8" } }, + "node_modules/fs-monkey": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==", + "dev": true, + "license": "Unlicense" + }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", @@ -2188,6 +3527,26 @@ "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, + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/glob-to-regexp": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", + "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", + "dev": true, + "license": "BSD-2-Clause" + }, "node_modules/globals": { "version": "13.24.0", "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", @@ -2220,8 +3579,8 @@ "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==", - "license": "ISC", - "optional": true + "devOptional": true, + "license": "ISC" }, "node_modules/graphemer": { "version": "1.4.0", @@ -2239,6 +3598,29 @@ "node": ">=8" } }, + "node_modules/has-own-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/has-own-prop/-/has-own-prop-2.0.0.tgz", + "integrity": "sha512-Pq0h+hvsVm6dDEa8x82GnLSYHOzNDt7f0ddFa3FqcQlgzEiptPqL+XrOJNavjOzSYiYWIrgeVYYgGlLmnxwilQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-property-descriptors": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "dev": true, + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/has-symbols": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", @@ -2501,6 +3883,59 @@ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "license": "ISC" }, + "node_modules/inquirer": { + "version": "8.2.6", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-8.2.6.tgz", + "integrity": "sha512-M1WuAmb7pn9zdFRtQYk26ZBoY043Sse0wVDdk4Bppr+JOXyQYybdtvK+l9wUibhtjdjvtoiNy8tk+EgsYIUqKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-escapes": "^4.2.1", + "chalk": "^4.1.1", + "cli-cursor": "^3.1.0", + "cli-width": "^3.0.0", + "external-editor": "^3.0.3", + "figures": "^3.0.0", + "lodash": "^4.17.21", + "mute-stream": "0.0.8", + "ora": "^5.4.1", + "run-async": "^2.4.0", + "rxjs": "^7.5.5", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0", + "through": "^2.3.6", + "wrap-ansi": "^6.0.1" + }, + "engines": { + "node": ">=12.0.0" + } + }, + "node_modules/inquirer/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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.8.0" + } + }, + "node_modules/inquirer/node_modules/figures": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", + "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "dev": true, + "license": "MIT", + "dependencies": { + "escape-string-regexp": "^1.0.5" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/ip-address": { "version": "9.0.5", "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", @@ -2524,6 +3959,26 @@ "node": ">= 0.10" } }, + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", + "dev": true, + "license": "MIT" + }, + "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, + "license": "MIT", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -2538,8 +3993,8 @@ "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==", + "devOptional": true, "license": "MIT", - "optional": true, "engines": { "node": ">=8" } @@ -2557,6 +4012,16 @@ "node": ">=0.10.0" } }, + "node_modules/is-interactive": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", + "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/is-lambda": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", @@ -2564,6 +4029,16 @@ "license": "MIT", "optional": true }, + "node_modules/is-number": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", + "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", @@ -2631,6 +4106,53 @@ "node": ">=6" } }, + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "@isaacs/cliui": "^8.0.2" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" + } + }, + "node_modules/jest-worker": { + "version": "27.5.1", + "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", + "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "merge-stream": "^2.0.0", + "supports-color": "^8.0.0" + }, + "engines": { + "node": ">= 10.13.0" + } + }, + "node_modules/jest-worker/node_modules/supports-color": { + "version": "8.1.1", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", + "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/supports-color?sponsor=1" + } + }, "node_modules/joi": { "version": "17.13.3", "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz", @@ -2644,6 +4166,13 @@ "@sideway/pinpoint": "^2.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==", + "dev": true, + "license": "MIT" + }, "node_modules/js-yaml": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz", @@ -2680,6 +4209,20 @@ "dev": true, "license": "MIT" }, + "node_modules/json-parse-even-better-errors": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", + "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", + "dev": true, + "license": "MIT" + }, + "node_modules/json-schema-traverse": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", + "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", + "dev": true, + "license": "MIT" + }, "node_modules/json-stable-stringify-without-jsonify": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", @@ -2687,6 +4230,39 @@ "dev": true, "license": "MIT" }, + "node_modules/json5": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", + "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", + "dev": true, + "license": "MIT", + "bin": { + "json5": "lib/cli.js" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/jsonc-parser": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.1.tgz", + "integrity": "sha512-AilxAyFOAcK5wA1+LeaySVBrHsGQvUFCDWXKpZjzaL0PqW+xfBOttn8GNtWKFWqneyMZj41MWF9Kl6iPWLwgOA==", + "dev": true, + "license": "MIT" + }, + "node_modules/jsonfile": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz", + "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "universalify": "^2.0.0" + }, + "optionalDependencies": { + "graceful-fs": "^4.1.6" + } + }, "node_modules/keyv": { "version": "4.5.4", "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz", @@ -2711,6 +4287,23 @@ "node": ">= 0.8.0" } }, + "node_modules/lines-and-columns": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", + "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/loader-runner": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6.11.5" + } + }, "node_modules/locate-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", @@ -2740,6 +4333,56 @@ "dev": true, "license": "MIT" }, + "node_modules/log-symbols": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", + "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "is-unicode-supported": "^0.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/log-symbols/node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/lru-cache": { + "version": "10.4.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz", + "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/magic-string": { + "version": "0.30.8", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.8.tgz", + "integrity": "sha512-ISQTe55T2ao7XtlAStud6qwYPZjE4GK1S/BeVPus4jrq6JuOnQ00YKQC581RWhR122W7msZV263KzVeLoqidyQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + }, + "engines": { + "node": ">=12" + } + }, "node_modules/make-fetch-happen": { "version": "9.1.0", "resolved": "https://registry.npmjs.org/make-fetch-happen/-/make-fetch-happen-9.1.0.tgz", @@ -2806,6 +4449,19 @@ "node": ">= 0.6" } }, + "node_modules/memfs": { + "version": "3.5.3", + "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz", + "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==", + "dev": true, + "license": "Unlicense", + "dependencies": { + "fs-monkey": "^1.0.4" + }, + "engines": { + "node": ">= 4.0.0" + } + }, "node_modules/merge-descriptors": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz", @@ -2815,6 +4471,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/merge-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", + "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", + "dev": true, + "license": "MIT" + }, "node_modules/methods": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", @@ -2857,6 +4520,16 @@ "node": ">= 0.6" } }, + "node_modules/mimic-fn": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", + "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/mimic-response": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", @@ -3040,6 +4713,13 @@ "node": ">= 6.0.0" } }, + "node_modules/mute-stream": { + "version": "0.0.8", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz", + "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==", + "dev": true, + "license": "ISC" + }, "node_modules/napi-build-utils": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/napi-build-utils/-/napi-build-utils-1.0.2.tgz", @@ -3062,6 +4742,13 @@ "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==", + "dev": true, + "license": "MIT" + }, "node_modules/node-abi": { "version": "3.71.0", "resolved": "https://registry.npmjs.org/node-abi/-/node-abi-3.71.0.tgz", @@ -3074,12 +4761,29 @@ "node": ">=10" } }, + "node_modules/node-abort-controller": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", + "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", + "dev": true, + "license": "MIT" + }, "node_modules/node-addon-api": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz", "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==", "license": "MIT" }, + "node_modules/node-emoji": { + "version": "1.11.0", + "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz", + "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==", + "dev": true, + "license": "MIT", + "dependencies": { + "lodash": "^4.17.21" + } + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", @@ -3142,6 +4846,13 @@ "url": "https://github.com/sponsors/isaacs" } }, + "node_modules/node-releases": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", + "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "dev": true, + "license": "MIT" + }, "node_modules/nopt": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/nopt/-/nopt-5.0.0.tgz", @@ -3158,6 +4869,16 @@ "node": ">=6" } }, + "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, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/npm-run-path": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-6.0.0.tgz", @@ -3245,6 +4966,22 @@ "wrappy": "1" } }, + "node_modules/onetime": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", + "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "dev": true, + "license": "MIT", + "dependencies": { + "mimic-fn": "^2.1.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -3263,6 +5000,53 @@ "node": ">= 0.8.0" } }, + "node_modules/ora": { + "version": "5.4.1", + "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz", + "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "bl": "^4.1.0", + "chalk": "^4.1.0", + "cli-cursor": "^3.1.0", + "cli-spinners": "^2.5.0", + "is-interactive": "^1.0.0", + "is-unicode-supported": "^0.1.0", + "log-symbols": "^4.1.0", + "strip-ansi": "^6.0.0", + "wcwidth": "^1.0.1" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/ora/node_modules/is-unicode-supported": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", + "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", @@ -3311,6 +5095,13 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -3324,6 +5115,25 @@ "node": ">=6" } }, + "node_modules/parse-json": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", + "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@babel/code-frame": "^7.0.0", + "error-ex": "^1.3.1", + "json-parse-even-better-errors": "^2.3.0", + "lines-and-columns": "^1.1.6" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/parse-ms": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/parse-ms/-/parse-ms-4.0.0.tgz", @@ -3374,12 +5184,79 @@ "node": ">=8" } }, + "node_modules/path-scurry": { + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", + "dev": true, + "license": "BlueOak-1.0.0", + "dependencies": { + "lru-cache": "^10.2.0", + "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" + }, + "engines": { + "node": ">=16 || 14 >=14.18" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/path-scurry/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, "node_modules/path-to-regexp": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-3.3.0.tgz", "integrity": "sha512-qyCH421YQPS2WFDxDjftfc1ZR5WKQzVzqsp4n9M2kQhVOo/ByahFoUNJfl58kOcEGfQ//7weFTDhm+ss8Ecxgw==", "license": "MIT" }, + "node_modules/path-type": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", + "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8" + } + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", + "dev": true, + "license": "ISC" + }, + "node_modules/picomatch": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.1.tgz", + "integrity": "sha512-xUXwsxNjwTQ8K3GnT4pCJm+xq3RUPQbmkYJTP5aFIfNIvbcc/4MUxgBaaRSZJ6yGJZiGSyYlM6MzwTsRk8SYCg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pluralize": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz", + "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/prebuild-install": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/prebuild-install/-/prebuild-install-7.1.2.tgz", @@ -3547,6 +5424,16 @@ ], "license": "MIT" }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, "node_modules/range-parser": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", @@ -3616,6 +5503,32 @@ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dev": true, + "license": "MIT", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, "node_modules/reflect-metadata": { "version": "0.1.14", "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.1.14.tgz", @@ -3623,6 +5536,26 @@ "license": "Apache-2.0", "peer": true }, + "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/require-from-string": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz", + "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -3633,6 +5566,20 @@ "node": ">=4" } }, + "node_modules/restore-cursor": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", + "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", + "dev": true, + "license": "MIT", + "dependencies": { + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/retry": { "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", @@ -3654,6 +5601,16 @@ "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==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.12.0" + } + }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", @@ -3713,6 +5670,59 @@ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", "license": "MIT" }, + "node_modules/schema-utils": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", + "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.8", + "ajv": "^6.12.5", + "ajv-keywords": "^3.5.2" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/schema-utils/node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" + } + }, + "node_modules/schema-utils/node_modules/ajv-keywords": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", + "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "ajv": "^6.9.1" + } + }, + "node_modules/schema-utils/node_modules/json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true, + "license": "MIT" + }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", @@ -3764,6 +5774,16 @@ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", "license": "MIT" }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "randombytes": "^2.1.0" + } + }, "node_modules/serve-static": { "version": "1.16.2", "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.2.tgz", @@ -3786,6 +5806,24 @@ "license": "ISC", "optional": true }, + "node_modules/set-function-length": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz", + "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==", + "dev": true, + "license": "MIT", + "dependencies": { + "define-data-property": "^1.1.4", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + } + }, "node_modules/setprototypeof": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", @@ -3889,8 +5927,8 @@ "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "license": "ISC", - "optional": true + "devOptional": true, + "license": "ISC" }, "node_modules/simple-concat": { "version": "1.0.1", @@ -4003,6 +6041,37 @@ "license": "MIT", "optional": true }, + "node_modules/source-map": { + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">= 8" + } + }, + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/sprintf-js": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.1.3.tgz", @@ -4083,8 +6152,24 @@ "version": "4.2.3", "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "devOptional": true, + "license": "MIT", + "dependencies": { + "emoji-regex": "^8.0.0", + "is-fullwidth-code-point": "^3.0.0", + "strip-ansi": "^6.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/string-width-cjs": { + "name": "string-width", + "version": "4.2.3", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz", + "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==", + "dev": true, "license": "MIT", - "optional": true, "dependencies": { "emoji-regex": "^8.0.0", "is-fullwidth-code-point": "^3.0.0", @@ -4107,6 +6192,30 @@ "node": ">=8" } }, + "node_modules/strip-ansi-cjs": { + "name": "strip-ansi", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz", + "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-regex": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=4" + } + }, "node_modules/strip-final-newline": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-4.0.0.tgz", @@ -4144,6 +6253,26 @@ "node": ">=8" } }, + "node_modules/symbol-observable": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-4.0.0.tgz", + "integrity": "sha512-b19dMThMV4HVFynSAM1++gBHAbk2Tc/osgLIBZMKsyqh34jb2e8Os7T6ZW/Bt3pJFdBTd2JwAnAAEQV7rSNvcQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=0.10" + } + }, + "node_modules/tapable": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -4236,6 +6365,87 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "license": "ISC" }, + "node_modules/terser": { + "version": "5.37.0", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.37.0.tgz", + "integrity": "sha512-B8wRRkmre4ERucLM/uXx4MOV5cbnOlVAqUst+1+iLKPI0dOgFO28f84ptoQt9HEI537PMzfYa/d+GEPKTRXmYA==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.8.2", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser-webpack-plugin": { + "version": "5.3.11", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.11.tgz", + "integrity": "sha512-RVCsMfuD0+cTt3EwX8hSl2Ks56EbFHWmhluwcqoPKtBnfjiT6olaq7PRIRfhyU8nnC2MrnDrBLfrD/RGE+cVXQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@jridgewell/trace-mapping": "^0.3.25", + "jest-worker": "^27.4.5", + "schema-utils": "^4.3.0", + "serialize-javascript": "^6.0.2", + "terser": "^5.31.1" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependencies": { + "webpack": "^5.1.0" + }, + "peerDependenciesMeta": { + "@swc/core": { + "optional": true + }, + "esbuild": { + "optional": true + }, + "uglify-js": { + "optional": true + } + } + }, + "node_modules/terser-webpack-plugin/node_modules/schema-utils": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.0.tgz", + "integrity": "sha512-Gf9qqc58SpCA/xdziiHz35F4GNIWYWZrEshUc/G/r5BnLph6xpKuLeoJoQuj5WfBIx/eQLf+hmVPYHaxJu7V2g==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/json-schema": "^7.0.9", + "ajv": "^8.9.0", + "ajv-formats": "^2.1.1", + "ajv-keywords": "^5.1.0" + }, + "engines": { + "node": ">= 10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/terser/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==", + "dev": true, + "license": "MIT" + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -4243,6 +6453,39 @@ "dev": true, "license": "MIT" }, + "node_modules/through": { + "version": "2.3.8", + "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", + "dev": true, + "license": "MIT" + }, + "node_modules/tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "license": "MIT", + "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, + "license": "MIT", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, "node_modules/toidentifier": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", @@ -4258,6 +6501,47 @@ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==", "license": "MIT" }, + "node_modules/tree-kill": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/tree-kill/-/tree-kill-1.2.2.tgz", + "integrity": "sha512-L0Orpi8qGpRG//Nd+H90vFB+3iHnue1zSSGmNOOCh1GLJ7rUKVwV2HvijphGQS2UmhUZewS9VgvxYIdgr+fG1A==", + "dev": true, + "license": "MIT", + "bin": { + "tree-kill": "cli.js" + } + }, + "node_modules/tsconfig-paths": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-4.2.0.tgz", + "integrity": "sha512-NoZ4roiN7LnbKn9QqE1amc9DJfzvZXxF4xDavcOWt1BPkdx+m+0gJuPM+S0vCe7zTJMYUP0R8pO2XMr+Y8oLIg==", + "dev": true, + "license": "MIT", + "dependencies": { + "json5": "^2.2.2", + "minimist": "^1.2.6", + "strip-bom": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/tsconfig-paths-webpack-plugin": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/tsconfig-paths-webpack-plugin/-/tsconfig-paths-webpack-plugin-4.2.0.tgz", + "integrity": "sha512-zbem3rfRS8BgeNK50Zz5SIQgXzLafiHjOwUAvk/38/o1jHn/V5QAgVUcz884or7WYcPaH3N2CIfUc2u0ul7UcA==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.0", + "enhanced-resolve": "^5.7.0", + "tapable": "^2.2.1", + "tsconfig-paths": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, "node_modules/tslib": { "version": "2.8.1", "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", @@ -4321,6 +6605,20 @@ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==", "license": "MIT" }, + "node_modules/typescript": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz", + "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, "node_modules/uid": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/uid/-/uid-2.0.2.tgz", @@ -4372,6 +6670,16 @@ "imurmurhash": "^0.1.4" } }, + "node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -4381,6 +6689,37 @@ "node": ">= 0.8" } }, + "node_modules/update-browserslist-db": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", + "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "MIT", + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.0" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", @@ -4415,12 +6754,127 @@ "node": ">= 0.8" } }, + "node_modules/watchpack": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", + "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", + "dev": true, + "license": "MIT", + "dependencies": { + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.1.2" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/wcwidth": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz", + "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==", + "dev": true, + "license": "MIT", + "dependencies": { + "defaults": "^1.0.3" + } + }, "node_modules/webidl-conversions": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz", "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==", "license": "BSD-2-Clause" }, + "node_modules/webpack": { + "version": "5.97.1", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz", + "integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/eslint-scope": "^3.7.7", + "@types/estree": "^1.0.6", + "@webassemblyjs/ast": "^1.14.1", + "@webassemblyjs/wasm-edit": "^1.14.1", + "@webassemblyjs/wasm-parser": "^1.14.1", + "acorn": "^8.14.0", + "browserslist": "^4.24.0", + "chrome-trace-event": "^1.0.2", + "enhanced-resolve": "^5.17.1", + "es-module-lexer": "^1.2.1", + "eslint-scope": "5.1.1", + "events": "^3.2.0", + "glob-to-regexp": "^0.4.1", + "graceful-fs": "^4.2.11", + "json-parse-even-better-errors": "^2.3.1", + "loader-runner": "^4.2.0", + "mime-types": "^2.1.27", + "neo-async": "^2.6.2", + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.1", + "webpack-sources": "^3.2.3" + }, + "bin": { + "webpack": "bin/webpack.js" + }, + "engines": { + "node": ">=10.13.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + }, + "peerDependenciesMeta": { + "webpack-cli": { + "optional": true + } + } + }, + "node_modules/webpack-node-externals": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/webpack-node-externals/-/webpack-node-externals-3.0.0.tgz", + "integrity": "sha512-LnL6Z3GGDPht/AigwRh2dvL9PQPFQ8skEpVrWZXLWBYmqcaojHNN0onvHzie6rq7EWKrrBfPYqNEzTJgiwEQDQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/webpack-sources": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/webpack/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/webpack/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } + }, "node_modules/whatwg-url": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz", @@ -4466,6 +6920,40 @@ "node": ">=0.10.0" } }, + "node_modules/wrap-ansi": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", + "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/wrap-ansi-cjs": { + "name": "wrap-ansi", + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz", + "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "ansi-styles": "^4.0.0", + "string-width": "^4.1.0", + "strip-ansi": "^6.0.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" + } + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", @@ -4487,6 +6975,16 @@ "node": ">=0.4" } }, + "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==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=12" + } + }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", diff --git a/package.json b/package.json index b6762fb..e4e4ab9 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "sqlite3": "^5.1.6" }, "devDependencies": { + "@nestjs/cli": "^10.4.9", "@types/express": "^4.17.17", "@types/joi": "^17.2.2", "@types/node": "^22.10.2", diff --git a/prisma/local-aws-state.sqlite b/prisma/local-aws-state.sqlite new file mode 100644 index 0000000..58754d2 Binary files /dev/null and b/prisma/local-aws-state.sqlite differ diff --git a/prisma/migrations/20241220030043_/migration.sql b/prisma/migrations/20241220030043_/migration.sql new file mode 100644 index 0000000..a415abe --- /dev/null +++ b/prisma/migrations/20241220030043_/migration.sql @@ -0,0 +1,93 @@ +-- CreateTable +CREATE TABLE "Attribute" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "arn" TEXT NOT NULL, + "name" TEXT NOT NULL, + "value" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "Audit" ( + "id" TEXT NOT NULL PRIMARY KEY, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "action" TEXT, + "request" TEXT, + "response" TEXT +); + +-- CreateTable +CREATE TABLE "Secret" ( + "versionId" TEXT NOT NULL PRIMARY KEY, + "name" TEXT NOT NULL, + "description" TEXT, + "secretString" TEXT NOT NULL, + "accountId" TEXT NOT NULL, + "region" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "deletionDate" DATETIME +); + +-- CreateTable +CREATE TABLE "SnsTopic" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "name" TEXT NOT NULL, + "accountId" TEXT NOT NULL, + "region" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "SnsTopicSubscription" ( + "id" TEXT NOT NULL PRIMARY KEY, + "topicArn" TEXT NOT NULL, + "endpoint" TEXT, + "protocol" TEXT NOT NULL, + "accountId" TEXT NOT NULL, + "region" TEXT NOT NULL +); + +-- CreateTable +CREATE TABLE "SqsQueue" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "name" TEXT NOT NULL, + "accountId" TEXT NOT NULL, + "region" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + "updatedAt" DATETIME NOT NULL +); + +-- CreateTable +CREATE TABLE "SqsQueueMessage" ( + "id" TEXT NOT NULL PRIMARY KEY, + "queueId" INTEGER NOT NULL, + "senderId" TEXT NOT NULL, + "message" TEXT NOT NULL, + "inFlightRelease" DATETIME NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP, + CONSTRAINT "SqsQueueMessage_queueId_fkey" FOREIGN KEY ("queueId") REFERENCES "SqsQueue" ("id") ON DELETE RESTRICT ON UPDATE CASCADE +); + +-- CreateTable +CREATE TABLE "Tag" ( + "id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + "arn" TEXT NOT NULL, + "name" TEXT NOT NULL, + "value" TEXT NOT NULL +); + +-- CreateIndex +CREATE UNIQUE INDEX "Attribute_arn_name_key" ON "Attribute"("arn", "name"); + +-- CreateIndex +CREATE INDEX "Secret_name_idx" ON "Secret"("name"); + +-- CreateIndex +CREATE UNIQUE INDEX "SnsTopic_accountId_region_name_key" ON "SnsTopic"("accountId", "region", "name"); + +-- CreateIndex +CREATE UNIQUE INDEX "SqsQueue_accountId_region_name_key" ON "SqsQueue"("accountId", "region", "name"); + +-- CreateIndex +CREATE INDEX "SqsQueueMessage_queueId_idx" ON "SqsQueueMessage"("queueId"); + +-- CreateIndex +CREATE UNIQUE INDEX "Tag_arn_name_key" ON "Tag"("arn", "name"); diff --git a/prisma/migrations/20241220053141_/migration.sql b/prisma/migrations/20241220053141_/migration.sql new file mode 100644 index 0000000..af417e4 --- /dev/null +++ b/prisma/migrations/20241220053141_/migration.sql @@ -0,0 +1,21 @@ +-- CreateTable +CREATE TABLE "KmsAlias" ( + "name" TEXT NOT NULL, + "accountId" TEXT NOT NULL, + "region" TEXT NOT NULL, + "kmsKeyId" TEXT NOT NULL, + + PRIMARY KEY ("accountId", "region", "name") +); + +-- CreateTable +CREATE TABLE "KmsKey" ( + "id" TEXT NOT NULL PRIMARY KEY, + "usage" TEXT NOT NULL, + "description" TEXT NOT NULL, + "keySpec" TEXT NOT NULL, + "key" TEXT NOT NULL, + "accountId" TEXT NOT NULL, + "region" TEXT NOT NULL, + "createdAt" DATETIME NOT NULL DEFAULT CURRENT_TIMESTAMP +); diff --git a/prisma/migrations/migration_lock.toml b/prisma/migrations/migration_lock.toml new file mode 100644 index 0000000..e1640d1 --- /dev/null +++ b/prisma/migrations/migration_lock.toml @@ -0,0 +1,3 @@ +# Please do not edit this file manually +# It should be added in your version-control system (e.g., Git) +provider = "sqlite" \ No newline at end of file diff --git a/prisma/schema.prisma b/prisma/schema.prisma index eaa9d50..6eae3e9 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -4,7 +4,7 @@ generator client { datasource db { provider = "sqlite" - url = ":memory:" + url = "file:local-aws-state.sqlite" } model Attribute { @@ -24,6 +24,26 @@ model Audit { response String? } +model KmsAlias { + name String + accountId String + region String + kmsKeyId String + + @@id([accountId, region, name]) +} + +model KmsKey { + id String @id + usage String + description String + keySpec String + key String + accountId String + region String + createdAt DateTime @default(now()) +} + model Secret { versionId String @id name String diff --git a/src/_context/audit.interceptor.ts b/src/_context/audit.interceptor.ts new file mode 100644 index 0000000..6b29d1c --- /dev/null +++ b/src/_context/audit.interceptor.ts @@ -0,0 +1,102 @@ +import { CallHandler, ExecutionContext, HttpException, Inject, Injectable, Logger, NestInterceptor, RequestTimeoutException } from '@nestjs/common'; +import { randomUUID } from 'crypto'; +import { catchError, Observable, tap, throwError } from 'rxjs'; +import { Request as ExpressRequest, Response } from 'express'; +import * as Joi from 'joi'; + +import { PrismaService } from '../_prisma/prisma.service'; +import { ActionHandlers } from '../app.constants'; +import { Action } from '../action.enum'; +import { Format } from '../abstract-action.handler'; +import { AwsException, InternalFailure } from '../aws-shared-entities/aws-exceptions'; +import { IRequest, RequestContext } from './request.context'; + + +@Injectable() +export class AuditInterceptor implements NestInterceptor { + + private readonly logger = new Logger(AuditInterceptor.name); + + constructor( + @Inject(ActionHandlers) + private readonly handlers: ActionHandlers, + private readonly prismaService: PrismaService, + ) {} + + intercept(context: ExecutionContext, next: CallHandler): Observable { + + const requestContext: RequestContext = { + requestId: randomUUID(), + } + + const httpContext = context.switchToHttp(); + const request = httpContext.getRequest(); + request.context = requestContext; + + const hasTargetHeader = Object.keys(request.headers).some( k => k.toLocaleLowerCase() === 'x-amz-target'); + const action = hasTargetHeader ? request.headers['x-amz-target'] : request.body.Action; + const { value: resolvedAction } = Joi.string().required().valid(...Object.values(Action)).validate(action) as { value: Action | undefined }; + requestContext.action = resolvedAction; + + const response = context.switchToHttp().getResponse(); + response.header('x-amzn-RequestId', requestContext.requestId); + + if (!resolvedAction || !this.handlers[resolvedAction]?.audit) { + return next.handle().pipe( + catchError(async (error: Error) => { + await this.prismaService.audit.create({ + data: { + id: requestContext.requestId, + action, + request: JSON.stringify({ __path: request.path, ...request.headers, ...request.body }), + response: JSON.stringify(error), + } + }); + this.logger.error(error.message); + return error; + }) + ); + } + + const handler = this.handlers[resolvedAction]; + requestContext.format = handler.format; + + return next.handle().pipe( + catchError((error: Error) => { + + return throwError(() => { + + if (error instanceof AwsException) { + return error; + } + + const defaultError = new InternalFailure('Unexpected local AWS exception...'); + this.logger.error(error.message); + defaultError.requestId = requestContext.requestId; + return defaultError; + }); + }), + + tap({ + + next: async (data) => await this.prismaService.audit.create({ + data: { + id: requestContext.requestId, + action, + request: JSON.stringify({ __path: request.path, ...request.headers, ...request.body }), + response: JSON.stringify(data), + } + }), + + error: async (error) => await this.prismaService.audit.create({ + data: { + id: requestContext.requestId, + action, + request: JSON.stringify({ __path: request.path, ...request.headers, ...request.body }), + response: JSON.stringify(error), + } + }), + }) + ); + } +} diff --git a/src/_context/exception.filter.ts b/src/_context/exception.filter.ts new file mode 100644 index 0000000..02b2d40 --- /dev/null +++ b/src/_context/exception.filter.ts @@ -0,0 +1,25 @@ +import { ArgumentsHost, Catch, ExceptionFilter } from "@nestjs/common"; +import { Response } from 'express'; + +import { AwsException } from "../aws-shared-entities/aws-exceptions"; +import { IRequest } from "./request.context"; +import { Format } from "../abstract-action.handler"; + +@Catch(AwsException) +export class AwsExceptionFilter implements ExceptionFilter { + catch(exception: AwsException, host: ArgumentsHost) { + const ctx = host.switchToHttp(); + const request = ctx.getRequest(); + const response = ctx.getResponse(); + + exception.requestId = request.context.requestId; + + if (request.context.format === Format.Xml) { + const xml = exception.toXml(); + return response.status(exception.statusCode).send(xml); + } + const [newError, newHeaders] = exception.toJson(); + response.setHeaders(new Map(Object.entries(newHeaders))); + return response.status(exception.statusCode).json(newError.getResponse()); + } +} diff --git a/src/_context/request.context.ts b/src/_context/request.context.ts new file mode 100644 index 0000000..b74a8c6 --- /dev/null +++ b/src/_context/request.context.ts @@ -0,0 +1,20 @@ +import { Request } from "express"; + +import { Action } from "../action.enum"; +import { Format } from "../abstract-action.handler"; + +export interface RequestContext { + action?: Action; + format?: Format; + requestId: string; +} + +export interface IRequest extends Request { + context: RequestContext; + headers: { + 'x-amz-target'?: string; + }, + body: { + 'Action'?: string; + } +} diff --git a/src/_prisma/prisma.service.ts b/src/_prisma/prisma.service.ts index 3781ba6..4608066 100644 --- a/src/_prisma/prisma.service.ts +++ b/src/_prisma/prisma.service.ts @@ -4,7 +4,5 @@ import { PrismaClient } from "@prisma/client"; export class PrismaService extends PrismaClient implements OnModuleInit { async onModuleInit() { await this.$connect(); - const tables = await this.$queryRawUnsafe('.tables'); - console.log({ tables }) } } diff --git a/src/action.enum.ts b/src/action.enum.ts index 9dcbcbb..c1561bd 100644 --- a/src/action.enum.ts +++ b/src/action.enum.ts @@ -301,4 +301,15 @@ export enum Action { SqsSetQueueAttributes = 'SetQueueAttributes', SqsTagQueue = 'TagQueue', SqsUntagQueue = 'UntagQueue', + + // STS + StsAssumeRole = 'AssumeRole', + StsAssumeRoleWithSaml = 'AssumeRoleWithSaml', + StsAssumeRoleWithWebIdentity = 'AssumeRoleWithWebIdentity', + StsAssumeRoot = 'AssumeRoot', + StsDecodeAuthorizationMessage = 'DecodeAuthorizationMessage', + StsGetAccessKeyInfo = 'GetAccessKeyInfo', + StsGetCallerIdentity = 'GetCallerIdentity', + StsGetFederationToken = 'GetFederationToken', + StsGetSessionToken = 'GetSessionToken', } diff --git a/src/app.controller.ts b/src/app.controller.ts index ed3a609..3710be5 100644 --- a/src/app.controller.ts +++ b/src/app.controller.ts @@ -1,13 +1,19 @@ -import { BadRequestException, Body, Controller, Inject, Post, Headers, Req, HttpCode, UseInterceptors } from '@nestjs/common'; -import { ActionHandlers } from './app.constants'; -import * as Joi from 'joi'; -import { Action } from './action.enum'; -import { AbstractActionHandler, Format } from './abstract-action.handler'; -import * as js2xmlparser from 'js2xmlparser'; +import { BadRequestException, Body, Controller, Headers, HttpCode, Inject, Post, Req, UseInterceptors } from '@nestjs/common'; import { ConfigService } from '@nestjs/config'; -import { CommonConfig } from './config/common-config.interface'; import { Request } from 'express'; -import { AuditInterceptor } from './audit/audit.interceptor'; +import * as Joi from 'joi'; +import * as js2xmlparser from 'js2xmlparser'; + +import { AbstractActionHandler, Format } from './abstract-action.handler'; +import { Action } from './action.enum'; +import { ActionHandlers } from './app.constants'; +import { AuditInterceptor } from './_context/audit.interceptor'; +import { CommonConfig } from './config/common-config.interface'; +import { InvalidAction, ValidationError } from './aws-shared-entities/aws-exceptions'; + +type QueryParams = { + __path: string; +} & Record; @Controller() export class AppController { @@ -30,24 +36,24 @@ export class AppController { const lowerCasedHeaders = Object.keys(headers).reduce((o, k) => { o[k.toLocaleLowerCase()] = headers[k]; return o; - }, {}) + }, {} as Record) - const queryParams = { __path: request.path, ...body, ...lowerCasedHeaders }; + const queryParams: QueryParams = { __path: request.path, ...body, ...lowerCasedHeaders }; const actionKey = queryParams['x-amz-target'] ? 'x-amz-target' : 'Action'; const { error: actionError } = Joi.object({ [actionKey]: Joi.string().valid(...Object.values(Action)).required(), }).validate(queryParams, { allowUnknown: true }); if (actionError) { - throw new BadRequestException(actionError.message, { cause: actionError }); + throw new InvalidAction(actionError.message); } - const action = queryParams[actionKey]; + const action = queryParams[actionKey] as Action; const handler: AbstractActionHandler = this.actionHandlers[action]; const { error: validatorError, value: validQueryParams } = handler.validator.validate(queryParams, { allowUnknown: true, abortEarly: false }); if (validatorError) { - throw new BadRequestException(validatorError.message, { cause: validatorError }); + throw new ValidationError(validatorError.message); } const awsProperties = { diff --git a/src/app.module.ts b/src/app.module.ts index 06d3783..827e5b2 100644 --- a/src/app.module.ts +++ b/src/app.module.ts @@ -3,11 +3,9 @@ import { ConfigModule } from '@nestjs/config'; import { ActionHandlers } from './app.constants'; import { AppController } from './app.controller'; -import { AuditInterceptor } from './audit/audit.interceptor'; +import { AuditInterceptor } from './_context/audit.interceptor'; import { AwsSharedEntitiesModule } from './aws-shared-entities/aws-shared-entities.module'; import localConfig from './config/local.config'; -import { IAMHandlers } from './iam/iam.constants'; -import { IamModule } from './iam/iam.module'; import { KMSHandlers } from './kms/kms.constants'; import { KmsModule } from './kms/kms.module'; import { SecretsManagerHandlers } from './secrets-manager/secrets-manager.constants'; @@ -16,6 +14,9 @@ import { SnsHandlers } from './sns/sns.constants'; import { SnsModule } from './sns/sns.module'; import { SqsHandlers } from './sqs/sqs.constants'; import { SqsModule } from './sqs/sqs.module'; +import { PrismaModule } from './_prisma/prisma.module'; +import { StsModule } from './sts/sts.module'; +import { StsHandlers } from './sts/sts.constants'; @Module({ imports: [ @@ -23,12 +24,13 @@ import { SqsModule } from './sqs/sqs.module'; load: [localConfig], isGlobal: true, }), - IamModule, + PrismaModule, + AwsSharedEntitiesModule, KmsModule, SecretsManagerModule, SnsModule, SqsModule, - AwsSharedEntitiesModule, + StsModule, ], controllers: [ AppController, @@ -39,11 +41,11 @@ import { SqsModule } from './sqs/sqs.module'; provide: ActionHandlers, useFactory: (...args) => args.reduce((m, hs) => ({ ...m, ...hs }), {}), inject: [ + KMSHandlers, + SecretsManagerHandlers, SnsHandlers, SqsHandlers, - SecretsManagerHandlers, - KMSHandlers, - IAMHandlers, + StsHandlers, ], }, ], diff --git a/src/audit/audit.interceptor.ts b/src/audit/audit.interceptor.ts deleted file mode 100644 index 8e976d9..0000000 --- a/src/audit/audit.interceptor.ts +++ /dev/null @@ -1,69 +0,0 @@ -import { CallHandler, ExecutionContext, Inject, Injectable, NestInterceptor } from '@nestjs/common'; -import { randomUUID } from 'crypto'; -import { Observable, tap } from 'rxjs'; -import { Request as ExpressRequest } from 'express'; -import * as Joi from 'joi'; - -import { PrismaService } from '../_prisma/prisma.service'; -import { ActionHandlers } from '../app.constants'; -import { Action } from '../action.enum'; - -interface Request extends ExpressRequest { - headers: { - 'x-amz-target'?: string; - }, - body: { - 'Action'?: string; - } -} - -@Injectable() -export class AuditInterceptor implements NestInterceptor { - - constructor( - @Inject(ActionHandlers) - private readonly handlers: ActionHandlers, - private readonly prismaService: PrismaService, - ) {} - - intercept(context: ExecutionContext, next: CallHandler): Observable { - - const requestId = randomUUID(); - const httpContext = context.switchToHttp(); - const request = httpContext.getRequest(); - - const hasTargetHeader = Object.keys(request.headers).some( k => k.toLocaleLowerCase() === 'x-amz-target'); - const action = hasTargetHeader ? request.headers['x-amz-target'] : request.body.Action; - const { value: resolvedAction } = Joi.string().required().valid(...Object.values(Action)).validate(action) as { value: Action | undefined }; - - const response = context.switchToHttp().getResponse(); - response.header('x-amzn-RequestId', requestId); - - if (!resolvedAction || !this.handlers[resolvedAction]?.audit) { - return next.handle(); - } - - return next.handle().pipe( - tap({ - - next: async (data) => await this.prismaService.audit.create({ - data: { - id: requestId, - action, - request: JSON.stringify({ __path: request.path, ...request.headers, ...request.body }), - response: JSON.stringify(data), - } - }), - - error: async (error) => await this.prismaService.audit.create({ - data: { - id: requestId, - action, - request: JSON.stringify({ __path: request.path, ...request.headers, ...request.body }), - response: JSON.stringify(error), - } - }), - }) - ); - } -} diff --git a/src/aws-shared-entities/aws-exceptions.ts b/src/aws-shared-entities/aws-exceptions.ts new file mode 100644 index 0000000..6c14219 --- /dev/null +++ b/src/aws-shared-entities/aws-exceptions.ts @@ -0,0 +1,156 @@ +import { HttpException, HttpStatus } from "@nestjs/common"; +import { randomUUID } from "crypto"; +import * as js2xmlparser from 'js2xmlparser'; + +export abstract class AwsException { + + requestId: string = randomUUID(); + + constructor( + readonly message: string, + readonly errorType: string, + readonly statusCode: HttpStatus, + ) {} + + toXml(): string { + return js2xmlparser.parse(`ErrorResponse`, { + RequestId: this.requestId, + Error: { + Code: this.errorType, + Message: this.message, + } + }); + } + + toJson(): [HttpException, Record] { + return [ + new HttpException({ + message: this.message, + __type: this.errorType, + }, this.statusCode), + { + 'Server': 'NestJS/local-aws', + 'X-Amzn-Errortype': this.errorType, + 'x-amzn-requestid': this.requestId, + } + ]; + } +} + +export class AccessDeniedException extends AwsException { + constructor(message: string) { + super( + message, + AccessDeniedException.name, + HttpStatus.BAD_REQUEST, + ) + } +} +export class IncompleteSignature extends AwsException { + constructor(message: string) { + super( + message, + IncompleteSignature.name, + HttpStatus.BAD_REQUEST, + ) + } +} +export class InternalFailure extends AwsException { + constructor(message: string) { + super( + message, + InternalFailure.name, + HttpStatus.INTERNAL_SERVER_ERROR, + ) + } +} +export class InvalidAction extends AwsException { + constructor(message: string) { + super( + message, + InvalidAction.name, + HttpStatus.BAD_REQUEST, + ) + } +} +export class InvalidClientTokenId extends AwsException { + constructor(message: string) { + super( + message, + InvalidClientTokenId.name, + HttpStatus.FORBIDDEN, + ) + } +} +export class NotAuthorized extends AwsException { + constructor(message: string) { + super( + message, + NotAuthorized.name, + HttpStatus.BAD_REQUEST, + ) + } +} +export class OptInRequired extends AwsException { + constructor(message: string) { + super( + message, + OptInRequired.name, + HttpStatus.FORBIDDEN, + ) + } +} +export class RequestExpired extends AwsException { + constructor(message: string) { + super( + message, + RequestExpired.name, + HttpStatus.BAD_REQUEST, + ) + } +} +export class ServiceUnavailable extends AwsException { + constructor(message: string) { + super( + message, + ServiceUnavailable.name, + HttpStatus.SERVICE_UNAVAILABLE, + ) + } +} +export class ThrottlingException extends AwsException { + constructor(message: string) { + super( + message, + ThrottlingException.name, + HttpStatus.BAD_REQUEST, + ) + } +} +export class ValidationError extends AwsException { + constructor(message: string) { + super( + message, + ValidationError.name, + HttpStatus.BAD_REQUEST, + ) + } +} +export class NotFoundException extends AwsException { + constructor() { + super( + 'The request was rejected because the specified entity or resource could not be found.', + NotFoundException.name, + HttpStatus.BAD_REQUEST, + ) + } +} +export class InvalidArnException extends AwsException { + constructor(message: string) { + super( + message, + InvalidArnException.name, + HttpStatus.BAD_REQUEST, + ) + } +} diff --git a/src/iam/attach-role-policy.handler.ts b/src/iam/attach-role-policy.handler.ts deleted file mode 100644 index 3962eef..0000000 --- a/src/iam/attach-role-policy.handler.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler'; -import { Action } from '../action.enum'; -import * as Joi from 'joi'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import * as uuid from 'uuid'; -import { IamPolicy } from './iam-policy.entity'; -import { IamRolePolicyAttachment } from './iam-role-policy-attachment.entity'; -import { IamRole } from './iam-role.entity'; - -type QueryParams = { - PolicyArn: string; - RoleName: string; -} - -@Injectable() -export class AttachRolePolicyHandler extends AbstractActionHandler { - - constructor( - @InjectRepository(IamRole) - private readonly roleRepo: Repository, - @InjectRepository(IamRolePolicyAttachment) - private readonly attachRepo: Repository, - ) { - super(); - } - - format = Format.Xml; - action = Action.IamAttachRolePolicy; - validator = Joi.object({ - PolicyArn: Joi.string().required(), - RoleName: Joi.string().required(), - }); - - protected async handle({ PolicyArn, RoleName }: QueryParams, awsProperties: AwsProperties) { - - const role = await this.roleRepo.findOne({ where: { roleName: RoleName, accountId: awsProperties.accountId} }); - - await this.attachRepo.create({ - id: uuid.v4(), - policyArn: PolicyArn, - roleId: role.id, - accountId: awsProperties.accountId, - }).save(); - } -} diff --git a/src/iam/create-policy-version.handler.ts b/src/iam/create-policy-version.handler.ts deleted file mode 100644 index 51de055..0000000 --- a/src/iam/create-policy-version.handler.ts +++ /dev/null @@ -1,62 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler'; -import { Action } from '../action.enum'; -import * as Joi from 'joi'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import * as uuid from 'uuid'; -import { IamPolicy } from './iam-policy.entity'; -import { breakdownArn } from '../util/breakdown-arn'; - -type QueryParams = { - PolicyArn: string; - PolicyDocument: string; - SetAsDefault: boolean; -} - -@Injectable() -export class CreatePolicyVersionHandler extends AbstractActionHandler { - - constructor( - @InjectRepository(IamPolicy) - private readonly policyRepo: Repository, - ) { - super(); - } - - format = Format.Xml; - action = Action.IamCreatePolicyVersion; - validator = Joi.object({ - PolicyArn: Joi.string().required(), - PolicyDocument: Joi.string().required(), - SetAsDefault: Joi.boolean().required(), - }); - - protected async handle({ PolicyArn, PolicyDocument, SetAsDefault }: QueryParams, awsProperties: AwsProperties) { - - const { identifier, accountId } = breakdownArn(PolicyArn); - const [_policy, name] = identifier.split('/'); - const currentPolicy = await this.policyRepo.findOne({ where: { accountId, name, isDefault: true } }); - - if (SetAsDefault) { - await this.policyRepo.update({ accountId, name }, { isDefault: false }) - } - - const policy = await this.policyRepo.create({ - id: uuid.v4(), - name: name, - isDefault: SetAsDefault, - version: currentPolicy.version + 1, - document: PolicyDocument, - accountId: awsProperties.accountId, - }).save(); - - return { - PolicyVersion: { - IsDefaultVersion: policy.isDefault, - VersionId: `v${policy.version}`, - CreateDate: new Date(policy.createdAt).toISOString(), - } - } - } -} diff --git a/src/iam/create-policy.handler.ts b/src/iam/create-policy.handler.ts deleted file mode 100644 index 4b187e1..0000000 --- a/src/iam/create-policy.handler.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler'; -import { Action } from '../action.enum'; -import * as Joi from 'joi'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import * as uuid from 'uuid'; -import { IamPolicy } from './iam-policy.entity'; - -type QueryParams = { - PolicyName: string; - PolicyDocument: string; -} - -@Injectable() -export class CreatePolicyHandler extends AbstractActionHandler { - - constructor( - @InjectRepository(IamPolicy) - private readonly policyRepo: Repository, - ) { - super(); - } - - format = Format.Xml; - action = Action.IamCreatePolicy; - validator = Joi.object({ - PolicyName: Joi.string().required(), - PolicyDocument: Joi.string().required(), - }); - - protected async handle({ PolicyName, PolicyDocument }: QueryParams, awsProperties: AwsProperties) { - - const policy = await this.policyRepo.create({ - id: uuid.v4(), - name: PolicyName, - document: PolicyDocument, - accountId: awsProperties.accountId, - }).save(); - - return { - Policy: { - PolicyName: policy.name, - DefaultVersionId: policy.version, - PolicyId: policy.id, - Path: '/', - Arn: policy.arn, - AttachmentCount: 0, - CreateDate: new Date(policy.createdAt).toISOString(), - UpdateDate: new Date(policy.updatedAt).toISOString(), - } - } - } -} diff --git a/src/iam/create-role.handler.ts b/src/iam/create-role.handler.ts deleted file mode 100644 index 8dc9190..0000000 --- a/src/iam/create-role.handler.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler'; -import { Action } from '../action.enum'; -import * as Joi from 'joi'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { IamRole } from './iam-role.entity'; -import * as uuid from 'uuid'; -import { IamPolicy } from './iam-policy.entity'; - -type QueryParams = { - RoleName: string; - Path: string; - AssumeRolePolicyDocument: string; - MaxSessionDuration: number; -} - -@Injectable() -export class CreateRoleHandler extends AbstractActionHandler { - - constructor( - @InjectRepository(IamRole) - private readonly roleRepo: Repository, - @InjectRepository(IamPolicy) - private readonly policyRepo: Repository, - ) { - super(); - } - - format = Format.Xml; - action = Action.IamCreateRole; - validator = Joi.object({ - RoleName: Joi.string().required(), - Path: Joi.string().required(), - AssumeRolePolicyDocument: Joi.string().required(), - MaxSessionDuration: Joi.number().default(3600), - }); - - protected async handle({ RoleName, Path, AssumeRolePolicyDocument, MaxSessionDuration }: QueryParams, awsProperties: AwsProperties) { - - const policy = await this.policyRepo.create({ - id: uuid.v4(), - name: `${RoleName}-AssumeRolePolicyDocument`, - document: AssumeRolePolicyDocument, - accountId: awsProperties.accountId, - }).save(); - - const id = uuid.v4(); - - await this.roleRepo.create({ - id, - roleName: RoleName, - path: Path, - accountId: awsProperties.accountId, - assumeRolePolicyDocumentId: policy.id, - maxSessionDuration: MaxSessionDuration, - }).save(); - - const role = await this.roleRepo.findOne({ where: { id }}); - - return { - Role: role.metadata, - } - } -} diff --git a/src/iam/get-policy-version.handler.ts b/src/iam/get-policy-version.handler.ts deleted file mode 100644 index 981a8c8..0000000 --- a/src/iam/get-policy-version.handler.ts +++ /dev/null @@ -1,54 +0,0 @@ -import { Injectable, NotFoundException, Version } from '@nestjs/common'; -import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler'; -import { Action } from '../action.enum'; -import * as Joi from 'joi'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { IamPolicy } from './iam-policy.entity'; -import { breakdownArn } from '../util/breakdown-arn'; -import { IamRolePolicyAttachment } from './iam-role-policy-attachment.entity'; - -type QueryParams = { - PolicyArn: string; - VersionId: string; -} - -@Injectable() -export class GetPolicyVersionHandler extends AbstractActionHandler { - - constructor( - @InjectRepository(IamPolicy) - private readonly policyRepo: Repository, - @InjectRepository(IamRolePolicyAttachment) - private readonly attachmentRepo: Repository, - ) { - super(); - } - - format = Format.Xml; - action = Action.IamGetPolicyVersion; - validator = Joi.object({ - PolicyArn: Joi.string().required(), - VersionId: Joi.string().required(), - }); - - protected async handle({ PolicyArn, VersionId }: QueryParams, awsProperties: AwsProperties) { - - const { identifier, accountId } = breakdownArn(PolicyArn); - const [_policy, name] = identifier.split('/'); - const policy = await this.policyRepo.findOne({ where: { name, accountId, version: +VersionId }}); - - if (!policy) { - throw new NotFoundException('NoSuchEntity', 'The request was rejected because it referenced a resource entity that does not exist. The error message describes the resource.'); - } - - return { - PolicyVersion: { - Document: policy.document, - IsDefaultVersion: policy.isDefault, - VersionId: `${policy.version}`, - CreateDate: new Date(policy.createdAt).toISOString(), - } - } - } -} diff --git a/src/iam/get-policy.handler.ts b/src/iam/get-policy.handler.ts deleted file mode 100644 index 82e4d1c..0000000 --- a/src/iam/get-policy.handler.ts +++ /dev/null @@ -1,58 +0,0 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; -import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler'; -import { Action } from '../action.enum'; -import * as Joi from 'joi'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { IamPolicy } from './iam-policy.entity'; -import { breakdownArn } from '../util/breakdown-arn'; -import { IamRolePolicyAttachment } from './iam-role-policy-attachment.entity'; - -type QueryParams = { - PolicyArn: string; -} - -@Injectable() -export class GetPolicyHandler extends AbstractActionHandler { - - constructor( - @InjectRepository(IamPolicy) - private readonly policyRepo: Repository, - @InjectRepository(IamRolePolicyAttachment) - private readonly attachmentRepo: Repository, - ) { - super(); - } - - format = Format.Xml; - action = Action.IamGetPolicy; - validator = Joi.object({ - PolicyArn: Joi.string().required(), - }); - - protected async handle({ PolicyArn }: QueryParams, awsProperties: AwsProperties) { - - const { identifier, accountId } = breakdownArn(PolicyArn); - const [_policy, name] = identifier.split('/'); - const policy = await this.policyRepo.findOne({ where: { name, accountId, isDefault: true }}); - - if (!policy) { - throw new NotFoundException('NoSuchEntity', 'The request was rejected because it referenced a resource entity that does not exist. The error message describes the resource.'); - } - - const attachmentCount = await this.attachmentRepo.count({ where: { policyArn: policy.arn } }); - - return { - Policy: { - PolicyName: policy.name, - DefaultVersionId: policy.version, - PolicyId: policy.id, - Path: '/', - Arn: policy.arn, - AttachmentCount: attachmentCount, - CreateDate: new Date(policy.createdAt).toISOString(), - UpdateDate: new Date(policy.updatedAt).toISOString(), - } - } - } -} diff --git a/src/iam/get-role.handler.ts b/src/iam/get-role.handler.ts deleted file mode 100644 index e132be4..0000000 --- a/src/iam/get-role.handler.ts +++ /dev/null @@ -1,41 +0,0 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; -import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler'; -import { Action } from '../action.enum'; -import * as Joi from 'joi'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { IamRole } from './iam-role.entity'; - -type QueryParams = { - RoleName: string; -} - -@Injectable() -export class GetRoleHandler extends AbstractActionHandler { - - constructor( - @InjectRepository(IamRole) - private readonly roleRepo: Repository, - ) { - super(); - } - - format = Format.Xml; - action = Action.IamGetRole; - validator = Joi.object({ - RoleName: Joi.string().required(), - }); - - protected async handle({ RoleName }: QueryParams, awsProperties: AwsProperties) { - - const role = await this.roleRepo.findOne({ where: { roleName: RoleName, accountId: awsProperties.accountId } }); - - if (!role) { - throw new NotFoundException('NoSuchEntity', 'The request was rejected because it referenced a resource entity that does not exist. The error message describes the resource.'); - } - - return { - Role: role.metadata, - } - } -} diff --git a/src/iam/iam-policy.entity.ts b/src/iam/iam-policy.entity.ts deleted file mode 100644 index ce74774..0000000 --- a/src/iam/iam-policy.entity.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { BaseEntity, Column, CreateDateColumn, Entity, JoinColumn, OneToMany, OneToOne, PrimaryColumn, UpdateDateColumn } from 'typeorm'; -import { IamRolePolicyAttachment } from './iam-role-policy-attachment.entity'; -import { IamRole } from './iam-role.entity'; - -@Entity({ name: 'iam_policy' }) -export class IamPolicy extends BaseEntity { - - @PrimaryColumn() - id: string; - - @Column({ default: 1 }) - version: number; - - @Column({ name: 'is_default', default: true }) - isDefault: boolean; - - @Column() - name: string; - - @Column() - document: string; - - @Column({ name: 'account_id', nullable: false }) - accountId: string; - - @CreateDateColumn() - createdAt: string; - - @UpdateDateColumn() - updatedAt: string; - - @OneToOne(() => IamRole, role => role.assumeRolePolicyDocument) - iamRole: IamRole; - - get arn() { - return `arn:aws:iam::${this.accountId}:policy/${this.name}`; - } -} diff --git a/src/iam/iam-role-policy-attachment.entity.ts b/src/iam/iam-role-policy-attachment.entity.ts deleted file mode 100644 index 24d500c..0000000 --- a/src/iam/iam-role-policy-attachment.entity.ts +++ /dev/null @@ -1,18 +0,0 @@ -import { BaseEntity, Column, Entity, JoinColumn, ManyToOne, PrimaryColumn } from 'typeorm'; -import { IamPolicy } from './iam-policy.entity'; - -@Entity({ name: 'iam_role_policy_attachment' }) -export class IamRolePolicyAttachment extends BaseEntity { - - @PrimaryColumn() - id: string; - - @Column({ name: 'policy_arn' }) - policyArn: string; - - @Column({ name: 'role_name' }) - roleId: string; - - @Column({ name: 'account_id'}) - accountId: string; -} diff --git a/src/iam/iam-role.entity.ts b/src/iam/iam-role.entity.ts deleted file mode 100644 index 2676fd0..0000000 --- a/src/iam/iam-role.entity.ts +++ /dev/null @@ -1,52 +0,0 @@ -import { BaseEntity, Column, CreateDateColumn, Entity, JoinColumn, OneToOne, PrimaryColumn, UpdateDateColumn } from 'typeorm'; -import { IamPolicy } from './iam-policy.entity'; - -@Entity({ name: 'iam_role' }) -export class IamRole extends BaseEntity { - - @PrimaryColumn() - id: string - - @Column({ name: 'role_name' }) - roleName: string; - - @Column() - path: string; - - @Column({ name: 'assume_role_policy_document_id', nullable: false }) - assumeRolePolicyDocumentId: string; - - @Column({ name: 'account_id', nullable: false }) - accountId: string; - - @Column({ name: 'max_session_duration', nullable: false, default: 0 }) - maxSessionDuration: number; - - @CreateDateColumn() - createdAt: string; - - @UpdateDateColumn() - updatedAt: string; - - @OneToOne(() => IamPolicy, (policy) => policy.id, { eager: true }) - @JoinColumn({ name: 'assume_role_policy_document_id' }) - assumeRolePolicyDocument: IamPolicy; - - get arn() { - const identifier = this.path.split('/'); - identifier.push(this.roleName); - return `arn:aws:iam::${this.accountId}:role/${identifier.join('/')}`; - } - - get metadata() { - return { - Path: this.path, - Arn: this.arn, - RoleName: this.roleName, - AssumeRolePolicyDocument: this.assumeRolePolicyDocument.document, - CreateDate: new Date(this.createdAt).toISOString(), - RoleId: this.id, - MaxSessionDuration: this.maxSessionDuration, - } - } -} diff --git a/src/iam/iam.constants.ts b/src/iam/iam.constants.ts deleted file mode 100644 index 9cc27d3..0000000 --- a/src/iam/iam.constants.ts +++ /dev/null @@ -1,5 +0,0 @@ -import { AbstractActionHandler } from '../abstract-action.handler'; -import { Action } from '../action.enum'; - -export type IAMHandlers = Record; -export const IAMHandlers = Symbol.for('IAMHandlers'); diff --git a/src/iam/iam.module.ts b/src/iam/iam.module.ts deleted file mode 100644 index 40c8794..0000000 --- a/src/iam/iam.module.ts +++ /dev/null @@ -1,207 +0,0 @@ -import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; -import { Format } from '../abstract-action.handler'; -import { Action } from '../action.enum'; -import { AwsSharedEntitiesModule } from '../aws-shared-entities/aws-shared-entities.module'; -import { DefaultActionHandlerProvider } from '../default-action-handler/default-action-handler.provider'; -import { ExistingActionHandlersProvider } from '../default-action-handler/existing-action-handlers.provider'; -import { AttachRolePolicyHandler } from './attach-role-policy.handler'; -import { CreatePolicyVersionHandler } from './create-policy-version.handler'; -import { CreatePolicyHandler } from './create-policy.handler'; -import { CreateRoleHandler } from './create-role.handler'; -import { GetPolicyVersionHandler } from './get-policy-version.handler'; -import { GetPolicyHandler } from './get-policy.handler'; -import { GetRoleHandler } from './get-role.handler'; -import { IamPolicy } from './iam-policy.entity'; -import { IamRolePolicyAttachment } from './iam-role-policy-attachment.entity'; -import { IamRole } from './iam-role.entity'; -import { IAMHandlers } from './iam.constants'; -import { ListAttachedRolePoliciesHandler } from './list-attached-role-policies'; -import { ListRolePoliciesHandler } from './list-role-policies.handler'; - -const handlers = [ - AttachRolePolicyHandler, - CreatePolicyHandler, - CreatePolicyVersionHandler, - CreateRoleHandler, - GetPolicyHandler, - GetRoleHandler, - GetPolicyVersionHandler, - ListAttachedRolePoliciesHandler, - ListRolePoliciesHandler, -] - -const actions = [ - Action.IamAddClientIDToOpenIDConnectProvider, - Action.IamAddRoleToInstanceProfile, - Action.IamAddUserToGroup, - Action.IamAttachGroupPolicy, - Action.IamAttachRolePolicy, - Action.IamAttachUserPolicy, - Action.IamChangePassword, - Action.IamCreateAccessKey, - Action.IamCreateAccountAlias, - Action.IamCreateGroup, - Action.IamCreateInstanceProfile, - Action.IamCreateLoginProfile, - Action.IamCreateOpenIDConnectProvider, - Action.IamCreatePolicy, - Action.IamCreatePolicyVersion, - Action.IamCreateRole, - Action.IamCreateSAMLProvider, - Action.IamCreateServiceLinkedRole, - Action.IamCreateServiceSpecificCredential, - Action.IamCreateUser, - Action.IamCreateVirtualMFADevice, - Action.IamDeactivateMFADevice, - Action.IamDeleteAccessKey, - Action.IamDeleteAccountAlias, - Action.IamDeleteAccountPasswordPolicy, - Action.IamDeleteGroup, - Action.IamDeleteGroupPolicy, - Action.IamDeleteInstanceProfile, - Action.IamDeleteLoginProfile, - Action.IamDeleteOpenIDConnectProvider, - Action.IamDeletePolicy, - Action.IamDeletePolicyVersion, - Action.IamDeleteRole, - Action.IamDeleteRolePermissionsBoundary, - Action.IamDeleteRolePolicy, - Action.IamDeleteSAMLProvider, - Action.IamDeleteServerCertificate, - Action.IamDeleteServiceLinkedRole, - Action.IamDeleteServiceSpecificCredential, - Action.IamDeleteSigningCertificate, - Action.IamDeleteSSHPublicKey, - Action.IamDeleteUser, - Action.IamDeleteUserPermissionsBoundary, - Action.IamDeleteUserPolicy, - Action.IamDeleteVirtualMFADevice, - Action.IamDetachGroupPolicy, - Action.IamDetachRolePolicy, - Action.IamDetachUserPolicy, - Action.IamEnableMFADevice, - Action.IamGenerateCredentialReport, - Action.IamGenerateOrganizationsAccessReport, - Action.IamGenerateServiceLastAccessedDetails, - Action.IamGetAccessKeyLastUsed, - Action.IamGetAccountAuthorizationDetails, - Action.IamGetAccountPasswordPolicy, - Action.IamGetAccountSummary, - Action.IamGetContextKeysForCustomPolicy, - Action.IamGetContextKeysForPrincipalPolicy, - Action.IamGetCredentialReport, - Action.IamGetGroup, - Action.IamGetGroupPolicy, - Action.IamGetInstanceProfile, - Action.IamGetLoginProfile, - Action.IamGetOpenIDConnectProvider, - Action.IamGetOrganizationsAccessReport, - Action.IamGetPolicy, - Action.IamGetPolicyVersion, - Action.IamGetRole, - Action.IamGetRolePolicy, - Action.IamGetSAMLProvider, - Action.IamGetServerCertificate, - Action.IamGetServiceLastAccessedDetails, - Action.IamGetServiceLastAccessedDetailsWithEntities, - Action.IamGetServiceLinkedRoleDeletionStatus, - Action.IamGetSSHPublicKey, - Action.IamGetUser, - Action.IamGetUserPolicy, - Action.IamListAccessKeys, - Action.IamListAccountAliases, - Action.IamListAttachedGroupPolicies, - Action.IamListAttachedRolePolicies, - Action.IamListAttachedUserPolicies, - Action.IamListEntitiesForPolicy, - Action.IamListGroupPolicies, - Action.IamListGroups, - Action.IamListGroupsForUser, - Action.IamListInstanceProfiles, - Action.IamListInstanceProfilesForRole, - Action.IamListInstanceProfileTags, - Action.IamListMFADevices, - Action.IamListMFADeviceTags, - Action.IamListOpenIDConnectProviders, - Action.IamListOpenIDConnectProviderTags, - Action.IamListPolicies, - Action.IamListPoliciesGrantingServiceAccess, - Action.IamListPolicyTags, - Action.IamListPolicyVersions, - Action.IamListRolePolicies, - Action.IamListRoles, - Action.IamListRoleTags, - Action.IamListSAMLProviders, - Action.IamListSAMLProviderTags, - Action.IamListServerCertificates, - Action.IamListServerCertificateTags, - Action.IamListServiceSpecificCredentials, - Action.IamListSigningCertificates, - Action.IamListSSHPublicKeys, - Action.IamListUserPolicies, - Action.IamListUsers, - Action.IamListUserTags, - Action.IamListVirtualMFADevices, - Action.IamPutGroupPolicy, - Action.IamPutRolePermissionsBoundary, - Action.IamPutRolePolicy, - Action.IamPutUserPermissionsBoundary, - Action.IamPutUserPolicy, - Action.IamRemoveClientIDFromOpenIDConnectProvider, - Action.IamRemoveRoleFromInstanceProfile, - Action.IamRemoveUserFromGroup, - Action.IamResetServiceSpecificCredential, - Action.IamResyncMFADevice, - Action.IamSetDefaultPolicyVersion, - Action.IamSetSecurityTokenServicePreferences, - Action.IamSimulateCustomPolicy, - Action.IamSimulatePrincipalPolicy, - Action.IamTagInstanceProfile, - Action.IamTagMFADevice, - Action.IamTagOpenIDConnectProvider, - Action.IamTagPolicy, - Action.IamTagRole, - Action.IamTagSAMLProvider, - Action.IamTagServerCertificate, - Action.IamTagUser, - Action.IamUntagInstanceProfile, - Action.IamUntagMFADevice, - Action.IamUntagOpenIDConnectProvider, - Action.IamUntagPolicy, - Action.IamUntagRole, - Action.IamUntagSAMLProvider, - Action.IamUntagServerCertificate, - Action.IamUntagUser, - Action.IamUpdateAccessKey, - Action.IamUpdateAccountPasswordPolicy, - Action.IamUpdateAssumeRolePolicy, - Action.IamUpdateGroup, - Action.IamUpdateLoginProfile, - Action.IamUpdateOpenIDConnectProviderThumbprint, - Action.IamUpdateRole, - Action.IamUpdateRoleDescription, - Action.IamUpdateSAMLProvider, - Action.IamUpdateServerCertificate, - Action.IamUpdateServiceSpecificCredential, - Action.IamUpdateSigningCertificate, - Action.IamUpdateSSHPublicKey, - Action.IamUpdateUser, - Action.IamUploadServerCertificate, - Action.IamUploadSigningCertificate, - Action.IamUploadSSHPublicKey, -] - -@Module({ - imports: [ - TypeOrmModule.forFeature([IamPolicy, IamRole, IamRolePolicyAttachment]), - AwsSharedEntitiesModule, - ], - providers: [ - ...handlers, - ExistingActionHandlersProvider(handlers), - DefaultActionHandlerProvider(IAMHandlers, Format.Xml, actions), - ], - exports: [IAMHandlers], -}) -export class IamModule {} diff --git a/src/iam/list-attached-role-policies.ts b/src/iam/list-attached-role-policies.ts deleted file mode 100644 index cd4b5e3..0000000 --- a/src/iam/list-attached-role-policies.ts +++ /dev/null @@ -1,57 +0,0 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; -import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler'; -import { Action } from '../action.enum'; -import * as Joi from 'joi'; -import { InjectRepository } from '@nestjs/typeorm'; -import { In, Repository } from 'typeorm'; -import { IamRole } from './iam-role.entity'; -import { IamRolePolicyAttachment } from './iam-role-policy-attachment.entity'; -import { IamPolicy } from './iam-policy.entity'; -import { breakdownArn } from '../util/breakdown-arn'; - -type QueryParams = { - RoleName: string; -} - -@Injectable() -export class ListAttachedRolePoliciesHandler extends AbstractActionHandler { - - constructor( - @InjectRepository(IamRole) - private readonly roleRepo: Repository, - @InjectRepository(IamPolicy) - private readonly policyRepo: Repository, - @InjectRepository(IamRolePolicyAttachment) - private readonly attachmentRepo: Repository, - ) { - super(); - } - - format = Format.Xml; - action = Action.IamListAttachedRolePolicies; - validator = Joi.object({ - RoleName: Joi.string().required(), - }); - - protected async handle({ RoleName }: QueryParams, awsProperties: AwsProperties) { - - const role = await this.roleRepo.findOne({ where: { roleName: RoleName, accountId: awsProperties.accountId } }); - - if (!role) { - throw new NotFoundException('NoSuchEntity', 'The request was rejected because it referenced a resource entity that does not exist. The error message describes the resource.'); - } - - const attachments = await this.attachmentRepo.find({ where: { roleId: role.id } }) - const policyIds = attachments.map(({ policyArn }) => breakdownArn(policyArn)).map(({ identifier }) => identifier.split('/')[1]); - const policies = await this.policyRepo.find({ where: { name: In(policyIds), isDefault: true } }); - - return { - AttachedPolicies: { - member: [role.assumeRolePolicyDocument, ...policies].map(p => ({ - PolicyName: p.name, - PolicyArn: p.arn, - })), - } - } - } -} diff --git a/src/iam/list-role-policies.handler.ts b/src/iam/list-role-policies.handler.ts deleted file mode 100644 index 9730cf0..0000000 --- a/src/iam/list-role-policies.handler.ts +++ /dev/null @@ -1,44 +0,0 @@ -import { Injectable, NotFoundException } from '@nestjs/common'; -import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler'; -import { Action } from '../action.enum'; -import * as Joi from 'joi'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { IamRole } from './iam-role.entity'; -import { IamRolePolicyAttachment } from './iam-role-policy-attachment.entity'; - -type QueryParams = { - RoleName: string; -} - -@Injectable() -export class ListRolePoliciesHandler extends AbstractActionHandler { - - constructor( - @InjectRepository(IamRole) - private readonly roleRepo: Repository, - @InjectRepository(IamRolePolicyAttachment) - private readonly attachmentRepo: Repository, - ) { - super(); - } - - format = Format.Xml; - action = Action.IamListRolePolicies; - validator = Joi.object({ - RoleName: Joi.string().required(), - }); - - protected async handle({ RoleName }: QueryParams, awsProperties: AwsProperties) { - - const role = await this.roleRepo.findOne({ where: { roleName: RoleName, accountId: awsProperties.accountId } }); - - if (!role) { - throw new NotFoundException('NoSuchEntity', 'The request was rejected because it referenced a resource entity that does not exist. The error message describes the resource.'); - } - - return { - PolicyNames: [], - } - } -} diff --git a/src/kms/create-alias.handler.ts b/src/kms/create-alias.handler.ts deleted file mode 100644 index 2a13a5c..0000000 --- a/src/kms/create-alias.handler.ts +++ /dev/null @@ -1,40 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler'; -import { Action } from '../action.enum'; -import * as Joi from 'joi'; -import { KmsKeyAlias } from './kms-key-alias.entity'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; - -type QueryParams = { - AliasName: string; - TargetKeyId: string; -} - -@Injectable() -export class CreateAliasHandler extends AbstractActionHandler { - - constructor( - @InjectRepository(KmsKeyAlias) - private readonly aliasRepo: Repository, - ) { - super(); - } - - format = Format.Json; - action = Action.KmsCreateAlias; - validator = Joi.object({ - AliasName: Joi.string().required(), - TargetKeyId: Joi.string().required(), - }); - - protected async handle({ AliasName, TargetKeyId }: QueryParams, awsProperties: AwsProperties) { - - await this.aliasRepo.save({ - name: AliasName.split('/')[1], - targetKeyId: TargetKeyId, - accountId: awsProperties.accountId, - region: awsProperties.region, - }); - } -} diff --git a/src/kms/create-key.handler.ts b/src/kms/create-key.handler.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/kms/describe-key.handler.ts b/src/kms/describe-key.handler.ts index b34d722..edcca9c 100644 --- a/src/kms/describe-key.handler.ts +++ b/src/kms/describe-key.handler.ts @@ -2,13 +2,12 @@ import { Injectable } from '@nestjs/common'; import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler'; import { Action } from '../action.enum'; import * as Joi from 'joi'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { KmsKey } from './kms-key.entity'; import { breakdownArn } from '../util/breakdown-arn'; import { KmsService } from './kms.service'; +import { NotFoundException } from '../aws-shared-entities/aws-exceptions'; type QueryParams = { + GrantTokens?: string[]; KeyId: string; } @@ -17,8 +16,6 @@ export class DescribeKeyHandler extends AbstractActionHandler { constructor( private readonly kmsService: KmsService, - @InjectRepository(KmsKey) - private readonly keyRepo: Repository, ) { super(); } @@ -27,6 +24,7 @@ export class DescribeKeyHandler extends AbstractActionHandler { action = Action.KmsDescribeKey; validator = Joi.object({ KeyId: Joi.string().required(), + GrantTokens: Joi.array().items(Joi.string()), }); protected async handle({ KeyId }: QueryParams, awsProperties: AwsProperties) { @@ -38,16 +36,17 @@ export class DescribeKeyHandler extends AbstractActionHandler { identifier: KeyId, }; const [ type, pk ] = searchable.identifier.split('/'); - const keyId: Promise = type === 'key' ? - Promise.resolve(pk) : - this.kmsService.findKeyIdFromAlias(pk, searchable); + const keyId = await (type === 'key' ? Promise.resolve(pk) : this.kmsService.findKeyIdFromAlias(pk, searchable)); + if (!keyId) { + throw new NotFoundException(); + } - const keyRecord = await this.keyRepo.findOne({ where: { - id: await keyId, - region: searchable.region, - accountId: searchable.accountId, - }}); + const keyRecord = await this.kmsService.findOneById(keyId); + + if (!keyRecord) { + throw new NotFoundException(); + } return { KeyMetadata: keyRecord.metadata, diff --git a/src/kms/get-public-key.handler.ts b/src/kms/get-public-key.handler.ts deleted file mode 100644 index e093881..0000000 --- a/src/kms/get-public-key.handler.ts +++ /dev/null @@ -1,123 +0,0 @@ -import { Injectable } from '@nestjs/common'; -import { AbstractActionHandler, AwsProperties, Format } from '../abstract-action.handler'; -import { Action } from '../action.enum'; -import * as Joi from 'joi'; -import { InjectRepository } from '@nestjs/typeorm'; -import { Repository } from 'typeorm'; -import { KeySpec, KeyUsage, KmsKey } from './kms-key.entity'; -import { breakdownArn } from '../util/breakdown-arn'; -import { KmsService } from './kms.service'; -import * as crypto from 'crypto'; - -type QueryParams = { - GrantTokens: string[]; - KeyId: string; -} - -interface StandardOutput { - KeyId: string; - KeySpec: KeySpec; - KeyUsage: KeyUsage; - PublicKey: string; - CustomerMasterKeySpec: KeySpec; -} - -interface EncryptDecrypt extends StandardOutput { - KeyUsage: 'ENCRYPT_DECRYPT'; - EncryptionAlgorithms: ('SYMMETRIC_DEFAULT' | 'RSAES_OAEP_SHA_1' | 'RSAES_OAEP_SHA_256' | 'SM2PKE')[]; -} - -interface SignVerify extends StandardOutput { - KeyUsage: 'SIGN_VERIFY'; - SigningAlgorithms: ('RSASSA_PSS_SHA_256' | 'RSASSA_PSS_SHA_384' | 'RSASSA_PSS_SHA_512' | 'RSASSA_PKCS1_V1_5_SHA_256' | 'RSASSA_PKCS1_V1_5_SHA_384' | 'RSASSA_PKCS1_V1_5_SHA_512' | 'ECDSA_SHA_256' | 'ECDSA_SHA_384' | 'ECDSA_SHA_512' | 'SM2DSA')[]; -} - -type Output = EncryptDecrypt | SignVerify | StandardOutput; - -@Injectable() -export class GetPublicKeyHandler extends AbstractActionHandler { - - constructor( - - @InjectRepository(KmsKey) - private readonly keyRepo: Repository, - private readonly kmsService: KmsService, - ) { - super(); - } - - format = Format.Json; - action = Action.KmsGetPublicKey; - validator = Joi.object({ - KeyId: Joi.string().required(), - GrantTokens: Joi.array().items(Joi.string()), - }); - - protected async handle({ KeyId }: QueryParams, awsProperties: AwsProperties): Promise { - - const searchable = KeyId.startsWith('arn') ? breakdownArn(KeyId) : { - service: 'kms', - region: awsProperties.region, - accountId: awsProperties.accountId, - identifier: KeyId, - }; - const [ type, pk ] = searchable.identifier.split('/'); - const keyId: Promise = type === 'key' ? - Promise.resolve(pk) : - this.kmsService.findKeyIdFromAlias(pk, searchable); - - - const keyRecord = await this.keyRepo.findOne({ where: { - id: await keyId, - region: searchable.region, - accountId: searchable.accountId, - }}); - - const pubKeyObject = crypto.createPublicKey({ - key: keyRecord.key,//.split(String.raw`\n`).join('\n'), - format: 'pem', - }); - - if (keyRecord.usage === 'ENCRYPT_DECRYPT') { - return { - CustomerMasterKeySpec: keyRecord.keySpec, - EncryptionAlgorithms: [ "SYMMETRIC_DEFAULT" ], - KeyId: keyRecord.arn, - KeySpec: keyRecord.keySpec, - KeyUsage: keyRecord.usage, - PublicKey: Buffer.from(pubKeyObject.export({ - format: 'der', - type: 'spki', - })).toString('base64'), - } - } - - if (keyRecord.usage === 'SIGN_VERIFY') { - const PublicKey = Buffer.from(pubKeyObject.export({ - format: 'der', - type: 'spki', - })).toString('base64') - - console.log({PublicKey}) - return { - CustomerMasterKeySpec: keyRecord.keySpec, - KeyId: keyRecord.arn, - KeySpec: keyRecord.keySpec, - KeyUsage: keyRecord.usage, - PublicKey, - SigningAlgorithms: [ 'RSASSA_PKCS1_V1_5_SHA_256' ] - } - } - - return { - CustomerMasterKeySpec: keyRecord.keySpec, - KeyId: keyRecord.arn, - KeySpec: keyRecord.keySpec, - KeyUsage: keyRecord.usage, - PublicKey: Buffer.from(pubKeyObject.export({ - format: 'pem', - type: 'spki', - })).toString('utf-8'), - } - } -} diff --git a/src/kms/kms-key-alias.entity.ts b/src/kms/kms-key-alias.entity.ts index 1862ae1..2a04065 100644 --- a/src/kms/kms-key-alias.entity.ts +++ b/src/kms/kms-key-alias.entity.ts @@ -1,21 +1,11 @@ -import { BaseEntity, Column, Entity, PrimaryColumn } from 'typeorm'; +export class KmsKeyAlias { -@Entity({ name: 'kms_key_alias' }) -export class KmsKeyAlias extends BaseEntity { + // name: string; + // targetKeyId: string; + // accountId: string; + // region: string; - @PrimaryColumn() - name: string; - - @Column({ name: 'target_key_id' }) - targetKeyId: string; - - @Column({ name: 'account_id', nullable: false }) - accountId: string; - - @Column({ name: 'region', nullable: false }) - region: string; - - get arn() { - return `arn:aws:kms:${this.region}:${this.accountId}:alias/${this.name}`; - } + // get arn() { + // return `arn:aws:kms:${this.region}:${this.accountId}:alias/${this.name}`; + // } } diff --git a/src/kms/kms-key.entity.ts b/src/kms/kms-key.entity.ts index 0ef2613..e1b79c1 100644 --- a/src/kms/kms-key.entity.ts +++ b/src/kms/kms-key.entity.ts @@ -1,34 +1,29 @@ -import { BaseEntity, Column, CreateDateColumn, Entity, PrimaryColumn } from 'typeorm'; +import { KmsKey as PrismaKmsKey } from '@prisma/client'; export type KeySpec = 'RSA_2048' | 'RSA_3072' | 'RSA_4096' | 'ECC_NIST_P256' | 'ECC_NIST_P384' | 'ECC_NIST_P521' | 'ECC_SECG_P256K1' | 'SYMMETRIC_DEFAULT' | 'HMAC_224' | 'HMAC_256' | 'HMAC_384' | 'HMAC_512' | 'SM2'; export type KeyUsage = 'SIGN_VERIFY' | 'ENCRYPT_DECRYPT' | 'GENERATE_VERIFY_MAC'; -@Entity({ name: 'kms_key'}) -export class KmsKey extends BaseEntity { +export class KmsKey implements PrismaKmsKey { - @PrimaryColumn() id: string; - - @Column({ name: 'usage' }) usage: KeyUsage; - - @Column({ name: 'description' }) description: string; - - @Column({ name: 'key_spec' }) keySpec: KeySpec; - - @Column({ name: 'key' }) key: string; - - @Column({ name: 'account_id', nullable: false }) accountId: string; - - @Column({ name: 'region', nullable: false }) region: string; + createdAt: Date; - @CreateDateColumn() - createdAt: string; + constructor(p: PrismaKmsKey) { + this.id = p.id; + this.usage = p.usage as KeyUsage; + this.description = p.description; + this.keySpec = p.keySpec as KeySpec; + this.key = p.key; + this.accountId = p.accountId; + this.region = p.region; + this.createdAt = p.createdAt; + } get arn() { return `arn:aws:kms:${this.region}:${this.accountId}:key/${this.id}`; diff --git a/src/kms/kms.module.ts b/src/kms/kms.module.ts index 74dbf75..615a823 100644 --- a/src/kms/kms.module.ts +++ b/src/kms/kms.module.ts @@ -1,22 +1,17 @@ import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; + import { Format } from '../abstract-action.handler'; import { Action } from '../action.enum'; import { AwsSharedEntitiesModule } from '../aws-shared-entities/aws-shared-entities.module'; import { DefaultActionHandlerProvider } from '../default-action-handler/default-action-handler.provider'; import { ExistingActionHandlersProvider } from '../default-action-handler/existing-action-handlers.provider'; -import { CreateAliasHandler } from './create-alias.handler'; -import { DescribeKeyHandler } from './describe-key.handler'; -import { KmsKeyAlias } from './kms-key-alias.entity'; -import { KmsKey } from './kms-key.entity'; -import { KMSHandlers } from './kms.constants'; import { KmsService } from './kms.service'; -import { GetPublicKeyHandler } from './get-public-key.handler'; +import { KMSHandlers } from './kms.constants'; +import { DescribeKeyHandler } from './describe-key.handler'; +import { PrismaModule } from '../_prisma/prisma.module'; const handlers = [ - CreateAliasHandler, DescribeKeyHandler, - GetPublicKeyHandler, ] const actions = [ @@ -74,8 +69,8 @@ const actions = [ @Module({ imports: [ - TypeOrmModule.forFeature([KmsKey, KmsKeyAlias]), AwsSharedEntitiesModule, + PrismaModule, ], providers: [ ...handlers, diff --git a/src/kms/kms.service.ts b/src/kms/kms.service.ts index d5abbb1..fa2c0ab 100644 --- a/src/kms/kms.service.ts +++ b/src/kms/kms.service.ts @@ -1,22 +1,30 @@ import { Injectable } from '@nestjs/common'; + +import { PrismaService } from '../_prisma/prisma.service'; import { ArnParts } from '../util/breakdown-arn'; -import { InjectRepository } from '@nestjs/typeorm'; -import { KmsKeyAlias } from './kms-key-alias.entity'; -import { Repository } from 'typeorm'; +import { KmsKey } from './kms-key.entity'; @Injectable() export class KmsService { constructor( - @InjectRepository(KmsKeyAlias) - private readonly aliasRepo: Repository, + private readonly prismaService: PrismaService, ) {} - async findKeyIdFromAlias(alias: string, arn: ArnParts): Promise { - const record = await this.aliasRepo.findOne({ where: { - name: alias, - accountId: arn.accountId, - region: arn.region, - }}); - return record.targetKeyId; + async findOneById(id: string): Promise { + const pRecord = await this.prismaService.kmsKey.findFirst({ + where: { id } + }); + return pRecord ? new KmsKey(pRecord) : null; + } + + async findKeyIdFromAlias(alias: string, arn: ArnParts): Promise { + const record = await this.prismaService.kmsAlias.findFirst({ + where: { + name: alias, + accountId: arn.accountId, + region: arn.region, + } + }); + return record?.kmsKeyId ?? null; } } diff --git a/src/kms/list-aliases.handler.ts b/src/kms/list-aliases.handler.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/main.ts b/src/main.ts index a8372cb..789c450 100644 --- a/src/main.ts +++ b/src/main.ts @@ -4,13 +4,15 @@ import { NestFactory, Reflector } from '@nestjs/core'; import { AppModule } from './app.module'; import { CommonConfig } from './config/common-config.interface'; +import { AwsExceptionFilter } from './_context/exception.filter'; const bodyParser = require('body-parser'); (async () => { const app = await NestFactory.create(AppModule); - app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector))); + // app.useGlobalInterceptors(new ClassSerializerInterceptor(app.get(Reflector))); + app.useGlobalFilters(new AwsExceptionFilter()); app.use(bodyParser.json({ type: 'application/x-amz-json-1.1'})); const configService: ConfigService = app.get(ConfigService); diff --git a/src/sns/unsubscribe.handler.ts b/src/sns/unsubscribe.handler.ts index de784e3..56d8879 100644 --- a/src/sns/unsubscribe.handler.ts +++ b/src/sns/unsubscribe.handler.ts @@ -6,6 +6,7 @@ import { TagsService } from '../aws-shared-entities/tags.service'; import { AttributesService } from '../aws-shared-entities/attributes.service'; import { PrismaService } from '../_prisma/prisma.service'; import { ArnUtil } from '../util/arn-util.static'; +import { NotFoundException } from '../aws-shared-entities/aws-exceptions'; type QueryParams = { SubscriptionArn: string; @@ -34,7 +35,7 @@ export class UnsubscribeHandler extends AbstractActionHandler { const subscription = await this.prismaService.snsTopicSubscription.findFirst({ where: { id } }); if (!subscription) { - return; + throw new NotFoundException(); } const arn = ArnUtil.fromTopicSub(subscription); diff --git a/src/sqs/delete-message-batch.handler.ts b/src/sqs/delete-message-batch.handler.ts index d374afb..d9f8b72 100644 --- a/src/sqs/delete-message-batch.handler.ts +++ b/src/sqs/delete-message-batch.handler.ts @@ -8,7 +8,7 @@ import { SqsQueue } from './sqs-queue.entity'; type QueryParams = { QueueUrl: string; -} +} & Record; @Injectable() export class DeleteMessageBatchHandler extends AbstractActionHandler { @@ -34,7 +34,7 @@ export class DeleteMessageBatchHandler extends AbstractActionHandler { }); protected async handle({ QueueUrl, ReceiptHandle }: QueryParams, awsProperties: AwsProperties) { - - const [accountId, name] = SqsQueue.tryGetAccountIdAndNameFromPathOrArn(QueueUrl); - await this.sqsQueueEntryService.deleteMessage(accountId, name, ReceiptHandle); + await this.sqsQueueEntryService.deleteMessage(ReceiptHandle); } } diff --git a/src/sqs/sqs.module.ts b/src/sqs/sqs.module.ts index 980c9e1..8e8949c 100644 --- a/src/sqs/sqs.module.ts +++ b/src/sqs/sqs.module.ts @@ -1,5 +1,5 @@ import { Module } from '@nestjs/common'; -import { TypeOrmModule } from '@nestjs/typeorm'; + import { Format } from '../abstract-action.handler'; import { Action } from '../action.enum'; import { AwsSharedEntitiesModule } from '../aws-shared-entities/aws-shared-entities.module'; @@ -14,9 +14,9 @@ import { PurgeQueueHandler } from './purge-queue.handler'; import { ReceiveMessageHandler } from './receive-message.handler'; import { SetQueueAttributesHandler } from './set-queue-attributes.handler'; import { SqsQueueEntryService } from './sqs-queue-entry.service'; -import { SqsQueue } from './sqs-queue.entity'; import { SqsHandlers } from './sqs.constants'; import { DeleteMessageBatchHandler } from './delete-message-batch.handler'; +import { PrismaModule } from '../_prisma/prisma.module'; const handlers = [ CreateQueueHandler, @@ -55,8 +55,8 @@ const actions = [ @Module({ imports: [ - TypeOrmModule.forFeature([SqsQueue]), AwsSharedEntitiesModule, + PrismaModule, ], providers: [ ...handlers, diff --git a/src/sts/get-caller-identity.handler.ts b/src/sts/get-caller-identity.handler.ts new file mode 100644 index 0000000..7e431b0 --- /dev/null +++ b/src/sts/get-caller-identity.handler.ts @@ -0,0 +1,23 @@ +import { Injectable } from "@nestjs/common"; +import * as Joi from "joi"; + +import { AbstractActionHandler, AwsProperties, Format } from "../abstract-action.handler"; +import { Action } from "../action.enum"; + +type QueryParams = {} + +@Injectable() +export class GetCallerIdentityHandler extends AbstractActionHandler { + + format = Format.Xml; + action = Action.StsGetCallerIdentity; + validator = Joi.object(); + + protected async handle(queryParams: QueryParams, awsProperties: AwsProperties) { + return { + "UserId": "AIDASAMPLEUSERID", + "Account": awsProperties.accountId, + "Arn": `arn:aws:iam::${awsProperties.accountId}:user/DevAdmin` + } + } +} diff --git a/src/sts/sts.constants.ts b/src/sts/sts.constants.ts new file mode 100644 index 0000000..cadf058 --- /dev/null +++ b/src/sts/sts.constants.ts @@ -0,0 +1,5 @@ +import { AbstractActionHandler } from '../abstract-action.handler'; +import { Action } from '../action.enum'; + +export type StsHandlers = Record; +export const StsHandlers = Symbol.for('STS_HANDLERS'); diff --git a/src/sts/sts.module.ts b/src/sts/sts.module.ts new file mode 100644 index 0000000..0e2fe60 --- /dev/null +++ b/src/sts/sts.module.ts @@ -0,0 +1,40 @@ +import { Module } from '@nestjs/common'; + +import { Format } from '../abstract-action.handler'; +import { Action } from '../action.enum'; +import { PrismaModule } from '../_prisma/prisma.module'; +import { AwsSharedEntitiesModule } from '../aws-shared-entities/aws-shared-entities.module'; +import { DefaultActionHandlerProvider } from '../default-action-handler/default-action-handler.provider'; +import { ExistingActionHandlersProvider } from '../default-action-handler/existing-action-handlers.provider'; +import { GetCallerIdentityHandler } from './get-caller-identity.handler'; +import { StsHandlers } from './sts.constants'; + +const handlers = [ + GetCallerIdentityHandler, +] + +const actions = [ + Action.StsAssumeRole, + Action.StsAssumeRoleWithSaml, + Action.StsAssumeRoleWithWebIdentity, + Action.StsAssumeRoot, + Action.StsDecodeAuthorizationMessage, + Action.StsGetAccessKeyInfo, + Action.StsGetCallerIdentity, + Action.StsGetFederationToken, + Action.StsGetSessionToken, +] + +@Module({ + imports: [ + AwsSharedEntitiesModule, + PrismaModule, + ], + providers: [ + ...handlers, + ExistingActionHandlersProvider(handlers), + DefaultActionHandlerProvider(StsHandlers, Format.Xml, actions), + ], + exports: [StsHandlers] +}) +export class StsModule {} diff --git a/src/sts/sts.service.ts b/src/sts/sts.service.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/util/breakdown-arn.ts b/src/util/breakdown-arn.ts index 0c92e0b..e496fb3 100644 --- a/src/util/breakdown-arn.ts +++ b/src/util/breakdown-arn.ts @@ -1,3 +1,5 @@ +import { InvalidArnException } from "../aws-shared-entities/aws-exceptions"; + export type ArnParts = { service: string; region: string; @@ -7,7 +9,7 @@ export type ArnParts = { export const breakdownArn = (arn: string): ArnParts => { if (!arn.startsWith('arn')) { - throw new Error('Invalid arn'); + throw new InvalidArnException('Invalid arn'); } const [_arn, _aws, service, region, accountId, ...identifierData] = arn.split(':'); diff --git a/tsconfig.build.ts b/tsconfig.build.ts index 8d7df56..a61dbcd 100644 --- a/tsconfig.build.ts +++ b/tsconfig.build.ts @@ -1,4 +1,4 @@ { "extends": "./tsconfig.json", - "exclude": ["node_modules", "dist", "**/*spec.ts"] + "exclude": ["node_modules", "dist", "src/iam"] } \ No newline at end of file