From c34ea76e4e9f634e60b283bdfda3f18c9afb5bc5 Mon Sep 17 00:00:00 2001 From: Matthew Bessette Date: Fri, 20 Dec 2024 01:07:33 -0500 Subject: [PATCH] Sts addition, kms updates, context object, improved exception handling --- package-lock.json | 2514 ++++++++++++++++- package.json | 1 + prisma/local-aws-state.sqlite | Bin 0 -> 364544 bytes .../migrations/20241220030043_/migration.sql | 93 + .../migrations/20241220053141_/migration.sql | 21 + prisma/migrations/migration_lock.toml | 3 + prisma/schema.prisma | 22 +- src/_context/audit.interceptor.ts | 102 + src/_context/exception.filter.ts | 25 + src/_context/request.context.ts | 20 + src/_prisma/prisma.service.ts | 2 - src/action.enum.ts | 11 + src/app.controller.ts | 32 +- src/app.module.ts | 18 +- src/audit/audit.interceptor.ts | 69 - src/aws-shared-entities/aws-exceptions.ts | 156 + src/iam/attach-role-policy.handler.ts | 47 - src/iam/create-policy-version.handler.ts | 62 - src/iam/create-policy.handler.ts | 54 - src/iam/create-role.handler.ts | 65 - src/iam/get-policy-version.handler.ts | 54 - src/iam/get-policy.handler.ts | 58 - src/iam/get-role.handler.ts | 41 - src/iam/iam-policy.entity.ts | 38 - src/iam/iam-role-policy-attachment.entity.ts | 18 - src/iam/iam-role.entity.ts | 52 - src/iam/iam.constants.ts | 5 - src/iam/iam.module.ts | 207 -- src/iam/list-attached-role-policies.ts | 57 - src/iam/list-role-policies.handler.ts | 44 - src/kms/create-alias.handler.ts | 40 - src/kms/create-key.handler.ts | 0 src/kms/describe-key.handler.ts | 25 +- src/kms/get-public-key.handler.ts | 123 - src/kms/kms-key-alias.entity.ts | 26 +- src/kms/kms-key.entity.ts | 31 +- src/kms/kms.module.ts | 15 +- src/kms/kms.service.ts | 32 +- src/kms/list-aliases.handler.ts | 0 src/main.ts | 4 +- src/sns/unsubscribe.handler.ts | 3 +- src/sqs/delete-message-batch.handler.ts | 4 +- src/sqs/delete-message.handler.ts | 4 +- src/sqs/sqs.module.ts | 6 +- src/sts/get-caller-identity.handler.ts | 23 + src/sts/sts.constants.ts | 5 + src/sts/sts.module.ts | 40 + src/sts/sts.service.ts | 0 src/util/breakdown-arn.ts | 4 +- tsconfig.build.ts | 2 +- 50 files changed, 3129 insertions(+), 1149 deletions(-) create mode 100644 prisma/local-aws-state.sqlite create mode 100644 prisma/migrations/20241220030043_/migration.sql create mode 100644 prisma/migrations/20241220053141_/migration.sql create mode 100644 prisma/migrations/migration_lock.toml create mode 100644 src/_context/audit.interceptor.ts create mode 100644 src/_context/exception.filter.ts create mode 100644 src/_context/request.context.ts delete mode 100644 src/audit/audit.interceptor.ts create mode 100644 src/aws-shared-entities/aws-exceptions.ts delete mode 100644 src/iam/attach-role-policy.handler.ts delete mode 100644 src/iam/create-policy-version.handler.ts delete mode 100644 src/iam/create-policy.handler.ts delete mode 100644 src/iam/create-role.handler.ts delete mode 100644 src/iam/get-policy-version.handler.ts delete mode 100644 src/iam/get-policy.handler.ts delete mode 100644 src/iam/get-role.handler.ts delete mode 100644 src/iam/iam-policy.entity.ts delete mode 100644 src/iam/iam-role-policy-attachment.entity.ts delete mode 100644 src/iam/iam-role.entity.ts delete mode 100644 src/iam/iam.constants.ts delete mode 100644 src/iam/iam.module.ts delete mode 100644 src/iam/list-attached-role-policies.ts delete mode 100644 src/iam/list-role-policies.handler.ts delete mode 100644 src/kms/create-alias.handler.ts create mode 100644 src/kms/create-key.handler.ts delete mode 100644 src/kms/get-public-key.handler.ts create mode 100644 src/kms/list-aliases.handler.ts create mode 100644 src/sts/get-caller-identity.handler.ts create mode 100644 src/sts/sts.constants.ts create mode 100644 src/sts/sts.module.ts create mode 100644 src/sts/sts.service.ts 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 0000000000000000000000000000000000000000..58754d2c51dfd98a9079e57040bffd1d42c83662 GIT binary patch literal 364544 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 G>i-AAloHSY literal 0 HcmV?d00001 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