From 851d37a3037ddb535d60bdd6c01980521025e8e7 Mon Sep 17 00:00:00 2001 From: Bipul Adhikari Date: Mon, 9 Sep 2024 12:31:45 +0545 Subject: [PATCH 01/22] Adds optional chaining for label selector in topology view Removes dependency on app label Signed-off-by: Bipul Adhikari --- packages/odf/components/topology/utils.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/odf/components/topology/utils.ts b/packages/odf/components/topology/utils.ts index ca12b0504..46b6b1d3b 100644 --- a/packages/odf/components/topology/utils.ts +++ b/packages/odf/components/topology/utils.ts @@ -32,7 +32,7 @@ export const generateNodeDeploymentsMap = ( const podsInNode = pods.filter( (pod) => pod.spec.nodeName === getName(node) && - allNames.includes(pod.metadata.labels['app']) + allNames.includes(pod.metadata.labels?.['app']) ); const deploymentsInNode = podsInNode .filter((pod) => _.has(pod, 'metadata.ownerReferences')) From 6b81dac5373645e9edf0f737dc34111136c59641 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alfonso=20Mart=C3=ADnez?= Date: Mon, 9 Sep 2024 14:07:27 +0200 Subject: [PATCH 02/22] Security: fix webpack version --- package.json | 5 +- yarn.lock | 479 ++++++++++++++++++++++++++++----------------------- 2 files changed, 269 insertions(+), 215 deletions(-) diff --git a/package.json b/package.json index 2fee1523c..5341edc00 100644 --- a/package.json +++ b/package.json @@ -60,7 +60,7 @@ "dependencies": { "@openshift-console/dynamic-plugin-sdk": "1.3.0", "@openshift-console/dynamic-plugin-sdk-internal": "1.0.0", - "@openshift-console/dynamic-plugin-sdk-webpack": "1.1.0", + "@openshift-console/dynamic-plugin-sdk-webpack": "1.1.1", "@openshift-console/plugin-shared": "^0.0.1", "@patternfly/patternfly": "5.0.2", "@patternfly/react-charts": "7.1.0", @@ -117,7 +117,7 @@ "typesafe-actions": "^4.2.1", "typescript": "^4.8", "victory-core": "^35.4.4", - "webpack": "5.75.0", + "webpack": "5.94.0", "webpack-bundle-analyzer": "^4.10.2", "webpack-cli": "4.5.x", "yup": "^0.32.11" @@ -174,6 +174,7 @@ }, "resolutions": { "jest-environment-jsdom/jsdom": "^20.0.3", + "webpack": "5.94.0", "webpack-bundle-analyzer/ws": "^7.5.10", "webpack-dev-server/ws": "^8.18.0", "tough-cookie": "^4.1.3" diff --git a/yarn.lock b/yarn.lock index a6ba5bd99..9a3fd7b5a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1023,21 +1023,53 @@ "@jridgewell/sourcemap-codec" "^1.4.10" "@jridgewell/trace-mapping" "^0.3.9" +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.5" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz#dcce6aff74bdf6dad1a95802b69b04a2fcb1fb36" + integrity sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg== + dependencies: + "@jridgewell/set-array" "^1.2.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.24" + "@jridgewell/resolve-uri@3.1.0": version "3.1.0" resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz#7a0ee601f60f99a20c7c7c5ff0c80388c1189bd6" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + "@jridgewell/set-array@^1.0.0", "@jridgewell/set-array@^1.0.1": version "1.1.2" resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== +"@jridgewell/set-array@^1.2.1": + version "1.2.1" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.2.1.tgz#558fb6472ed16a4c850b889530e6b36438c49280" + integrity sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A== + +"@jridgewell/source-map@^0.3.3": + version "0.3.6" + resolved "https://registry.yarnpkg.com/@jridgewell/source-map/-/source-map-0.3.6.tgz#9d71ca886e32502eb9362c9a74a46787c36df81a" + integrity sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.25" + "@jridgewell/sourcemap-codec@1.4.14", "@jridgewell/sourcemap-codec@^1.4.10": version "1.4.14" resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== +"@jridgewell/sourcemap-codec@^1.4.14": + version "1.5.0" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz#3188bcb273a414b0d215fd22a58540b989b9409a" + integrity sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ== + "@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.15", "@jridgewell/trace-mapping@^0.3.9": version "0.3.17" resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.17.tgz#793041277af9073b0951a7fe0f0d8c4c98c36985" @@ -1046,6 +1078,14 @@ "@jridgewell/resolve-uri" "3.1.0" "@jridgewell/sourcemap-codec" "1.4.14" +"@jridgewell/trace-mapping@^0.3.20", "@jridgewell/trace-mapping@^0.3.24", "@jridgewell/trace-mapping@^0.3.25": + version "0.3.25" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz#15f190e98895f3fc23276ee14bc76b675c2e50f0" + integrity sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + "@leichtgewicht/ip-codec@^2.0.1": version "2.0.4" resolved "https://registry.yarnpkg.com/@leichtgewicht/ip-codec/-/ip-codec-2.0.4.tgz#b2ac626d6cb9c8718ab459166d4bb405b8ffa78b" @@ -1124,10 +1164,10 @@ redux "4.0.1" redux-thunk "2.4.0" -"@openshift-console/dynamic-plugin-sdk-webpack@1.1.0": - version "1.1.0" - resolved "https://registry.yarnpkg.com/@openshift-console/dynamic-plugin-sdk-webpack/-/dynamic-plugin-sdk-webpack-1.1.0.tgz#d369c37b93cd0792960385728de5cd1f63c2187f" - integrity sha512-UukGhZOEGc5u22hoO3H0bP58r+Kw1gDFBe0EEJTkYkzYX6S0og5DNAVw/lzhwUorpbmy00B6cqWIuclmTo1+QA== +"@openshift-console/dynamic-plugin-sdk-webpack@1.1.1": + version "1.1.1" + resolved "https://registry.yarnpkg.com/@openshift-console/dynamic-plugin-sdk-webpack/-/dynamic-plugin-sdk-webpack-1.1.1.tgz#349326366f84defa8c81baa8be411257d0b1e954" + integrity sha512-1m1iBpdj0HNWQIEFAhMlI5pmigyN5B/Eqcb2nGAI2n030hOOxAalxySO95dvEFa2hiyXMUt4z/Tyq4fDYKZ2nw== dependencies: "@openshift/dynamic-plugin-sdk-webpack" "^4.0.2" ajv "^6.12.3" @@ -1800,31 +1840,10 @@ resolved "https://registry.yarnpkg.com/@types/dagre/-/dagre-0.7.42.tgz#2b0cd7678d5fc273df7816a88b8b34016e3a5d85" integrity sha512-knVdi1Ul8xYgJ0wdhQ+/2YGJFKJFa/5srcPII9zvOs4KhsHfpnFrSTQXATYmjslglxRMif3Lg+wEZ0beag+94A== -"@types/eslint-scope@^3.7.3": - version "3.7.3" - resolved "https://registry.yarnpkg.com/@types/eslint-scope/-/eslint-scope-3.7.3.tgz#125b88504b61e3c8bc6f870882003253005c3224" - integrity sha512-PB3ldyrcnAicT35TWPs5IcwKD8S333HMaa2VVv4+wdvebJkjWuW/xESoB8IwRcog8HYVYamb1g/R31Qv5Bx03g== - dependencies: - "@types/eslint" "*" - "@types/estree" "*" - -"@types/eslint@*": - version "8.2.0" - resolved "https://registry.yarnpkg.com/@types/eslint/-/eslint-8.2.0.tgz#afd0519223c29c347087542cbaee2fedc0873b16" - integrity sha512-74hbvsnc+7TEDa1z5YLSe4/q8hGYB3USNvCuzHUJrjPV6hXaq8IXcngCrHkuvFt0+8rFz7xYXrHgNayIX0UZvQ== - dependencies: - "@types/estree" "*" - "@types/json-schema" "*" - -"@types/estree@*": - version "0.0.50" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.50.tgz#1e0caa9364d3fccd2931c3ed96fdbeaa5d4cca83" - integrity sha512-C6N5s2ZFtuZRj54k2/zyRhNDjJwwcViAM3Nbm8zjBpbqAdZ00mr0CFxvSKeO8Y/e03WVFLpQMdHYVfUd6SB+Hw== - -"@types/estree@^0.0.51": - version "0.0.51" - resolved "https://registry.yarnpkg.com/@types/estree/-/estree-0.0.51.tgz#cfd70924a25a3fd32b218e5e420e6897e1ac4f40" - integrity sha512-CuPgU6f3eT/XgKKPqKd/gLZV1Xmvf1a2R5POBOGQa6uv82xpls89HU5zKeVoyR8XzHd1RGNOlQlvUe3CFkjWNQ== +"@types/estree@^1.0.5": + version "1.0.5" + resolved "https://registry.yarnpkg.com/@types/estree/-/estree-1.0.5.tgz#a6ce3e556e00fd9895dd872dd172ad0d4bd687f4" + integrity sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw== "@types/express-serve-static-core@*", "@types/express-serve-static-core@^4.17.18": version "4.17.29" @@ -1935,7 +1954,7 @@ "@types/tough-cookie" "*" parse5 "^7.0.0" -"@types/json-schema@*", "@types/json-schema@^7.0.8": +"@types/json-schema@^7.0.8": version "7.0.9" resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.9.tgz#97edc9037ea0c38585320b28964dde3b39e4660d" integrity sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ== @@ -2384,125 +2403,125 @@ "@typescript-eslint/types" "5.43.0" eslint-visitor-keys "^3.3.0" -"@webassemblyjs/ast@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.11.1.tgz#2bfd767eae1a6996f432ff7e8d7fc75679c0b6a7" - integrity sha512-ukBh14qFLjxTQNTXocdyksN5QdM28S1CxHt2rdskFyL+xFV7VremuBLVbmCePj+URalXBENx/9Lm7lnhihtCSw== +"@webassemblyjs/ast@1.12.1", "@webassemblyjs/ast@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ast/-/ast-1.12.1.tgz#bb16a0e8b1914f979f45864c23819cc3e3f0d4bb" + integrity sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg== dependencies: - "@webassemblyjs/helper-numbers" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" + "@webassemblyjs/helper-numbers" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" -"@webassemblyjs/floating-point-hex-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.1.tgz#f6c61a705f0fd7a6aecaa4e8198f23d9dc179e4f" - integrity sha512-iGRfyc5Bq+NnNuX8b5hwBrRjzf0ocrJPI6GWFodBFzmFnyvrQ83SHKhmilCU/8Jv67i4GJZBMhEzltxzcNagtQ== +"@webassemblyjs/floating-point-hex-parser@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz#dacbcb95aff135c8260f77fa3b4c5fea600a6431" + integrity sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw== -"@webassemblyjs/helper-api-error@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.1.tgz#1a63192d8788e5c012800ba6a7a46c705288fd16" - integrity sha512-RlhS8CBCXfRUR/cwo2ho9bkheSXG0+NwooXcc3PAILALf2QLdFyj7KGsKRbVc95hZnhnERon4kW/D3SZpp6Tcg== +"@webassemblyjs/helper-api-error@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz#6132f68c4acd59dcd141c44b18cbebbd9f2fa768" + integrity sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q== -"@webassemblyjs/helper-buffer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.1.tgz#832a900eb444884cde9a7cad467f81500f5e5ab5" - integrity sha512-gwikF65aDNeeXa8JxXa2BAk+REjSyhrNC9ZwdT0f8jc4dQQeDQ7G4m0f2QCLPJiMTTO6wfDmRmj/pW0PsUvIcA== +"@webassemblyjs/helper-buffer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz#6df20d272ea5439bf20ab3492b7fb70e9bfcb3f6" + integrity sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw== -"@webassemblyjs/helper-numbers@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.1.tgz#64d81da219fbbba1e3bd1bfc74f6e8c4e10a62ae" - integrity sha512-vDkbxiB8zfnPdNK9Rajcey5C0w+QJugEglN0of+kmO8l7lDb77AnlKYQF7aarZuCrv+l0UvqL+68gSDr3k9LPQ== +"@webassemblyjs/helper-numbers@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz#cbce5e7e0c1bd32cf4905ae444ef64cea919f1b5" + integrity sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g== dependencies: - "@webassemblyjs/floating-point-hex-parser" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" + "@webassemblyjs/floating-point-hex-parser" "1.11.6" + "@webassemblyjs/helper-api-error" "1.11.6" "@xtuc/long" "4.2.2" -"@webassemblyjs/helper-wasm-bytecode@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.1.tgz#f328241e41e7b199d0b20c18e88429c4433295e1" - integrity sha512-PvpoOGiJwXeTrSf/qfudJhwlvDQxFgelbMqtq52WWiXC6Xgg1IREdngmPN3bs4RoO83PnL/nFrxucXj1+BX62Q== +"@webassemblyjs/helper-wasm-bytecode@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz#bb2ebdb3b83aa26d9baad4c46d4315283acd51e9" + integrity sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA== -"@webassemblyjs/helper-wasm-section@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.1.tgz#21ee065a7b635f319e738f0dd73bfbda281c097a" - integrity sha512-10P9No29rYX1j7F3EVPX3JvGPQPae+AomuSTPiF9eBQeChHI6iqjMIwR9JmOJXwpnn/oVGDk7I5IlskuMwU/pg== +"@webassemblyjs/helper-wasm-section@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz#3da623233ae1a60409b509a52ade9bc22a37f7bf" + integrity sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g== dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/wasm-gen" "1.12.1" -"@webassemblyjs/ieee754@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.1.tgz#963929e9bbd05709e7e12243a099180812992614" - integrity sha512-hJ87QIPtAMKbFq6CGTkZYJivEwZDbQUgYd3qKSadTNOhVY7p+gfP6Sr0lLRVTaG1JjFj+r3YchoqRYxNH3M0GQ== +"@webassemblyjs/ieee754@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz#bb665c91d0b14fffceb0e38298c329af043c6e3a" + integrity sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg== dependencies: "@xtuc/ieee754" "^1.2.0" -"@webassemblyjs/leb128@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.1.tgz#ce814b45574e93d76bae1fb2644ab9cdd9527aa5" - integrity sha512-BJ2P0hNZ0u+Th1YZXJpzW6miwqQUGcIHT1G/sf72gLVD9DZ5AdYTqPNbHZh6K1M5VmKvFXwGSWZADz+qBWxeRw== +"@webassemblyjs/leb128@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/leb128/-/leb128-1.11.6.tgz#70e60e5e82f9ac81118bc25381a0b283893240d7" + integrity sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ== dependencies: "@xtuc/long" "4.2.2" -"@webassemblyjs/utf8@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.1.tgz#d1f8b764369e7c6e6bae350e854dec9a59f0a3ff" - integrity sha512-9kqcxAEdMhiwQkHpkNiorZzqpGrodQQ2IGrHHxCy+Ozng0ofyMA0lTqiLkVs1uzTRejX+/O0EOT7KxqVPuXosQ== - -"@webassemblyjs/wasm-edit@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.1.tgz#ad206ebf4bf95a058ce9880a8c092c5dec8193d6" - integrity sha512-g+RsupUC1aTHfR8CDgnsVRVZFJqdkFHpsHMfJuWQzWU3tvnLC07UqHICfP+4XyL2tnr1amvl1Sdp06TnYCmVkA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/helper-wasm-section" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-opt" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - "@webassemblyjs/wast-printer" "1.11.1" - -"@webassemblyjs/wasm-gen@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.1.tgz#86c5ea304849759b7d88c47a32f4f039ae3c8f76" - integrity sha512-F7QqKXwwNlMmsulj6+O7r4mmtAlCWfO/0HdgOxSklZfQcDu0TpLiD1mRt/zF25Bk59FIjEuGAIyn5ei4yMfLhA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wasm-opt@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.1.tgz#657b4c2202f4cf3b345f8a4c6461c8c2418985f2" - integrity sha512-VqnkNqnZlU5EB64pp1l7hdm3hmQw7Vgqa0KF/KCNO9sIpI6Fk6brDEiX+iCOYrvMuBWDws0NkTOxYEb85XQHHw== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-buffer" "1.11.1" - "@webassemblyjs/wasm-gen" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" - -"@webassemblyjs/wasm-parser@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.1.tgz#86ca734534f417e9bd3c67c7a1c75d8be41fb199" - integrity sha512-rrBujw+dJu32gYB7/Lup6UhdkPx9S9SnobZzRVL7VcBH9Bt9bCBLEuX/YXOOtBsOZ4NQrRykKhffRWHvigQvOA== - dependencies: - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/helper-api-error" "1.11.1" - "@webassemblyjs/helper-wasm-bytecode" "1.11.1" - "@webassemblyjs/ieee754" "1.11.1" - "@webassemblyjs/leb128" "1.11.1" - "@webassemblyjs/utf8" "1.11.1" - -"@webassemblyjs/wast-printer@1.11.1": - version "1.11.1" - resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.11.1.tgz#d0c73beda8eec5426f10ae8ef55cee5e7084c2f0" - integrity sha512-IQboUWM4eKzWW+N/jij2sRatKMh99QEelo3Eb2q0qXkvPRISAj8Qxtmw5itwqK+TTkBuUIE45AxYPToqPtL5gg== - dependencies: - "@webassemblyjs/ast" "1.11.1" +"@webassemblyjs/utf8@1.11.6": + version "1.11.6" + resolved "https://registry.yarnpkg.com/@webassemblyjs/utf8/-/utf8-1.11.6.tgz#90f8bc34c561595fe156603be7253cdbcd0fab5a" + integrity sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA== + +"@webassemblyjs/wasm-edit@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz#9f9f3ff52a14c980939be0ef9d5df9ebc678ae3b" + integrity sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/helper-wasm-section" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-opt" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + "@webassemblyjs/wast-printer" "1.12.1" + +"@webassemblyjs/wasm-gen@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz#a6520601da1b5700448273666a71ad0a45d78547" + integrity sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wasm-opt@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz#9e6e81475dfcfb62dab574ac2dda38226c232bc5" + integrity sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-buffer" "1.12.1" + "@webassemblyjs/wasm-gen" "1.12.1" + "@webassemblyjs/wasm-parser" "1.12.1" + +"@webassemblyjs/wasm-parser@1.12.1", "@webassemblyjs/wasm-parser@^1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz#c47acb90e6f083391e3fa61d113650eea1e95937" + integrity sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ== + dependencies: + "@webassemblyjs/ast" "1.12.1" + "@webassemblyjs/helper-api-error" "1.11.6" + "@webassemblyjs/helper-wasm-bytecode" "1.11.6" + "@webassemblyjs/ieee754" "1.11.6" + "@webassemblyjs/leb128" "1.11.6" + "@webassemblyjs/utf8" "1.11.6" + +"@webassemblyjs/wast-printer@1.12.1": + version "1.12.1" + resolved "https://registry.yarnpkg.com/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz#bcecf661d7d1abdaf989d8341a4833e33e2b31ac" + integrity sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA== + dependencies: + "@webassemblyjs/ast" "1.12.1" "@xtuc/long" "4.2.2" "@webpack-cli/configtest@^1.0.1": @@ -2561,10 +2580,10 @@ acorn-globals@^7.0.0: acorn "^8.1.0" acorn-walk "^8.0.2" -acorn-import-assertions@^1.7.6: - version "1.8.0" - resolved "https://registry.yarnpkg.com/acorn-import-assertions/-/acorn-import-assertions-1.8.0.tgz#ba2b5939ce62c238db6d93d81c9b111b29b855e9" - integrity sha512-m7VZ3jwz4eK6A4Vtt8Ew1/mNbP24u0FhdyfA7fSvnJR6LMdfOYnmuIrrJAgrYfYJ10F/otaHTtrtrtmHdMNzEw== +acorn-import-attributes@^1.9.5: + version "1.9.5" + resolved "https://registry.yarnpkg.com/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz#7eb1557b1ba05ef18b5ed0ec67591bfab04688ef" + integrity sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ== acorn-jsx@^5.3.1: version "5.3.2" @@ -2591,7 +2610,7 @@ acorn@^8.1.0: resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.1.tgz#0a3f9cbecc4ec3bea6f0a80b66ae8dd2da250b73" integrity sha512-7zFpHzhnqYKrkYdUjF1HI1bzd0VygEGX8lFk4k5zVMqHEoES+P+7TKI+EvLO9WVMJ8eekdO0aDEK044xTXwPPA== -acorn@^8.8.1: +acorn@^8.8.1, acorn@^8.8.2: version "8.12.1" resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.12.1.tgz#71616bdccbe25e27a54439e0046e89ca76df2248" integrity sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg== @@ -3173,16 +3192,15 @@ browserslist@^4.12.0, browserslist@^4.16.6: escalade "^3.1.1" node-releases "^1.1.73" -browserslist@^4.14.5: - version "4.18.1" - resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.18.1.tgz#60d3920f25b6860eb917c6c7b185576f4d8b017f" - integrity sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ== +browserslist@^4.21.10: + version "4.23.3" + resolved "https://registry.yarnpkg.com/browserslist/-/browserslist-4.23.3.tgz#debb029d3c93ebc97ffbc8d9cbb03403e227c800" + integrity sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA== dependencies: - caniuse-lite "^1.0.30001280" - electron-to-chromium "^1.3.896" - escalade "^3.1.1" - node-releases "^2.0.1" - picocolors "^1.0.0" + caniuse-lite "^1.0.30001646" + electron-to-chromium "^1.5.4" + node-releases "^2.0.18" + update-browserslist-db "^1.1.0" browserslist@^4.21.3: version "4.21.4" @@ -3314,16 +3332,16 @@ caniuse-lite@^1.0.30001109, caniuse-lite@^1.0.30001248: resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001249.tgz#90a330057f8ff75bfe97a94d047d5e14fabb2ee8" integrity sha512-vcX4U8lwVXPdqzPWi6cAJ3FnQaqXbBqy/GZseKNQzRj37J7qZdGcBtxq/QLFNLLlfsoXLUdHw8Iwenri86Tagw== -caniuse-lite@^1.0.30001280: - version "1.0.30001283" - resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001283.tgz#8573685bdae4d733ef18f78d44ba0ca5fe9e896b" - integrity sha512-9RoKo841j1GQFSJz/nCXOj0sD7tHBtlowjYlrqIUS812x9/emfBLBt6IyMz1zIaYc/eRL8Cs6HPUVi2Hzq4sIg== - caniuse-lite@^1.0.30001400: version "1.0.30001431" resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001431.tgz#e7c59bd1bc518fae03a4656be442ce6c4887a795" integrity sha512-zBUoFU0ZcxpvSt9IU66dXVT/3ctO1cy4y9cscs1szkPlcWb6pasYM144GqrUygUbT+k7cmUCW61cvskjcv0enQ== +caniuse-lite@^1.0.30001646: + version "1.0.30001659" + resolved "https://registry.yarnpkg.com/caniuse-lite/-/caniuse-lite-1.0.30001659.tgz#f370c311ffbc19c4965d8ec0064a3625c8aaa7af" + integrity sha512-Qxxyfv3RdHAfJcXelgf0hU4DFUVXBGTjqrBUZLUh8AtlGnsDo+CnncYtTd95+ZKfnANUOzxyIQCuU/UeBZBYoA== + caseless@~0.12.0: version "0.12.0" resolved "https://registry.yarnpkg.com/caseless/-/caseless-0.12.0.tgz#1b681c21ff84033c826543090689420d187151dc" @@ -4807,16 +4825,16 @@ electron-to-chromium@^1.3.793: resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.3.796.tgz#bd74a4367902c9d432d129f265bf4542cddd9f54" integrity sha512-agwJFgM0FUC1UPPbQ4aII3HamaaJ09fqWGAWYHmzxDWqdmTleCHyyA0kt3fJlTd5M440IaeuBfzXzXzCotnZcQ== -electron-to-chromium@^1.3.896: - version "1.4.6" - resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.6.tgz#7bf0c03001bcdbd0fc57a45c6b23bc6432246ade" - integrity sha512-YDZAXP0P8USm0YoyIXWijxFT3tJHbt3WwY7CTQiK3+Ad6Ai/b9N4GqfDR107jfGilAfxl7Gkhb+h0KPoKXAgqw== - electron-to-chromium@^1.4.251: version "1.4.284" resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.4.284.tgz#61046d1e4cab3a25238f6bf7413795270f125592" integrity sha512-M8WEXFuKXMYMVr45fo8mq0wUrrJHheiKZf6BArTKk9ZBYCKJEOU5H8cdWgDT+qCVZf7Na4lVUaZsA+h6uA9+PA== +electron-to-chromium@^1.5.4: + version "1.5.18" + resolved "https://registry.yarnpkg.com/electron-to-chromium/-/electron-to-chromium-1.5.18.tgz#5fe62b9d21efbcfa26571066502d94f3ed97e495" + integrity sha512-1OfuVACu+zKlmjsNdcJuVQuVE61sZOLbNM4JAQ1Rvh6EOj0/EUKhMJjRH73InPlXSh8HIJk1cVZ8pyOV/FMdUQ== + emittery@^0.13.1: version "0.13.1" resolved "https://registry.yarnpkg.com/emittery/-/emittery-0.13.1.tgz#c04b8c3457490e0847ae51fced3af52d338e3dad" @@ -4861,7 +4879,7 @@ end-of-stream@^1.0.0, end-of-stream@^1.1.0: dependencies: once "^1.4.0" -enhanced-resolve@^5.0.0, enhanced-resolve@^5.10.0: +enhanced-resolve@^5.0.0: version "5.10.0" resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.10.0.tgz#0dc579c3bb2a1032e357ac45b8f3a6f3ad4fb1e6" integrity sha512-T0yTFjdpldGY8PmuXXR0PyQ1ufZpEGiHVrp7zHKB7jdR4qlmZHhONVM5AQOAWXuF/w3dnHbEQVrNptJgt7F+cQ== @@ -4869,6 +4887,14 @@ enhanced-resolve@^5.0.0, enhanced-resolve@^5.10.0: graceful-fs "^4.2.4" tapable "^2.2.0" +enhanced-resolve@^5.17.1: + version "5.17.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz#67bfbbcc2f81d511be77d686a90267ef7f898a15" + integrity sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + enquirer@^2.3.5, enquirer@^2.3.6: version "2.3.6" resolved "https://registry.yarnpkg.com/enquirer/-/enquirer-2.3.6.tgz#2a7fe5dd634a1e4125a975ec994ff5456dc3734d" @@ -4978,10 +5004,10 @@ es-get-iterator@^1.1.2: is-string "^1.0.5" isarray "^2.0.5" -es-module-lexer@^0.9.0: - version "0.9.3" - resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-0.9.3.tgz#6f13db00cc38417137daf74366f535c8eb438f19" - integrity sha512-1HQ2M2sPtxwnvOvT1ZClHyQDiggdNjURWpY2we6aMKCQiUVxTmVs2UYPLIrD84sS+kMdUwfBSylbJPwNnBrnHQ== +es-module-lexer@^1.2.1: + version "1.5.4" + resolved "https://registry.yarnpkg.com/es-module-lexer/-/es-module-lexer-1.5.4.tgz#a8efec3a3da991e60efa6b633a7cad6ab8d26b78" + integrity sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw== es-to-primitive@^1.2.1: version "1.2.1" @@ -5125,6 +5151,11 @@ escalade@^3.1.1: resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== +escalade@^3.1.2: + version "3.2.0" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.2.0.tgz#011a3f69856ba189dffa7dc8fcce99d2a87903e5" + integrity sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA== + escape-html@^1.0.3, escape-html@~1.0.3: version "1.0.3" resolved "https://registry.yarnpkg.com/escape-html/-/escape-html-1.0.3.tgz#0258eae4d3d0c0974de1c169188ef0051d1d1988" @@ -6180,6 +6211,11 @@ graceful-fs@^4.1.11, graceful-fs@^4.1.2, graceful-fs@^4.2.0, graceful-fs@^4.2.4: resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.6.tgz#ff040b2b0853b23c3d31027523706f1885d76bee" integrity sha512-nTnJ528pbqxYanhpDYsi4Rd8MAeaBA67+RZ10CM1m3bTAVFEDcd5AuA4a6W5YkGZ1iNXHzZz8T6TBKLeBuNriQ== +graceful-fs@^4.2.11: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + graceful-fs@^4.2.6, graceful-fs@^4.2.9: version "4.2.10" resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.10.tgz#147d3a006da4ca3ce14728c7aefc287c367d7a6c" @@ -7657,10 +7693,10 @@ jest-watcher@^29.3.1: jest-util "^29.3.1" string-length "^4.0.1" -jest-worker@^27.0.6: - version "27.0.6" - resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.0.6.tgz#a5fdb1e14ad34eb228cfe162d9f729cdbfa28aed" - integrity sha512-qupxcj/dRuA3xHPMUd40gr2EaAurFbkwzOh7wfPaeE9id7hyjURRQoqNfHifHK3XjJU6YJJUQKILGUnwGPEOCA== +jest-worker@^27.4.5: + version "27.5.1" + resolved "https://registry.yarnpkg.com/jest-worker/-/jest-worker-27.5.1.tgz#8d146f0900e8973b106b6f73cc1e9a8cb86f8db0" + integrity sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg== dependencies: "@types/node" "*" merge-stream "^2.0.0" @@ -8582,10 +8618,10 @@ node-releases@^1.1.73: resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-1.1.73.tgz#dd4e81ddd5277ff846b80b52bb40c49edf7a7b20" integrity sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg== -node-releases@^2.0.1: - version "2.0.1" - resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.1.tgz#3d1d395f204f1f2f29a54358b9fb678765ad2fc5" - integrity sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA== +node-releases@^2.0.18: + version "2.0.18" + resolved "https://registry.yarnpkg.com/node-releases/-/node-releases-2.0.18.tgz#f010e8d35e2fe8d6b2944f03f70213ecedc4ca3f" + integrity sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g== node-releases@^2.0.6: version "2.0.6" @@ -9060,6 +9096,11 @@ picocolors@^1.0.0: resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== +picocolors@^1.0.1: + version "1.1.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.1.0.tgz#5358b76a78cde483ba5cef6a9dc9671440b27d59" + integrity sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw== + picomatch@^2.0.4, picomatch@^2.2.3: version "2.3.0" resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.0.tgz#f1f061de8f6a4bf022892e2d128234fb98302972" @@ -10387,7 +10428,7 @@ schema-utils@^1.0.0: ajv-errors "^1.0.0" ajv-keywords "^3.1.0" -schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: +schema-utils@^3.0.0, schema-utils@^3.1.1: version "3.1.1" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.1.1.tgz#bc74c4b6b6995c1d88f76a8b77bea7219e0c8281" integrity sha512-Y5PQxS4ITlC+EahLuXaY86TXfR7Dc5lw294alXOq86JAHCihAIZfqv8nNCWvaEJvaC51uN9hbLGeV0cFBdH+Fw== @@ -10396,6 +10437,15 @@ schema-utils@^3.0.0, schema-utils@^3.1.0, schema-utils@^3.1.1: ajv "^6.12.5" ajv-keywords "^3.5.2" +schema-utils@^3.2.0: + version "3.3.0" + resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-3.3.0.tgz#f50a88877c3c01652a15b622ae9e9795df7a60fe" + integrity sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg== + dependencies: + "@types/json-schema" "^7.0.8" + ajv "^6.12.5" + ajv-keywords "^3.5.2" + schema-utils@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/schema-utils/-/schema-utils-4.0.0.tgz#60331e9e3ae78ec5d16353c467c34b3a0a1d3df7" @@ -10474,10 +10524,10 @@ serialize-javascript@^5.0.1: dependencies: randombytes "^2.1.0" -serialize-javascript@^6.0.0: - version "6.0.0" - resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.0.tgz#efae5d88f45d7924141da8b5c3a7a7e663fefeb8" - integrity sha512-Qr3TosvguFt8ePWqsvRfrKyQXIiW+nGbYpy8XK24NQHE83caxWt+mIymTT19DGFbNWNLfEwsrkSmN64lVWB9ag== +serialize-javascript@^6.0.1: + version "6.0.2" + resolved "https://registry.yarnpkg.com/serialize-javascript/-/serialize-javascript-6.0.2.tgz#defa1e055c83bf6d59ea805d8da862254eb6a6c2" + integrity sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g== dependencies: randombytes "^2.1.0" @@ -10658,11 +10708,6 @@ source-map@^0.5.0, source-map@^0.5.3, source-map@^0.5.6: resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.5.7.tgz#8a039d2d1021d22d1ea14c80d8ea468ba2ef3fcc" integrity sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= -source-map@~0.7.2: - version "0.7.3" - resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.7.3.tgz#5302f8169031735226544092e64981f751750383" - integrity sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ== - spdx-correct@^3.0.0: version "3.1.1" resolved "https://registry.yarnpkg.com/spdx-correct/-/spdx-correct-3.1.1.tgz#dece81ac9c1e6713e5f7d1b6f17d468fa53d89a9" @@ -11182,24 +11227,25 @@ teex@^1.0.1: dependencies: streamx "^2.12.5" -terser-webpack-plugin@^5.1.3: - version "5.2.5" - resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.2.5.tgz#ce65b9880a0c36872555c4874f45bbdb02ee32c9" - integrity sha512-3luOVHku5l0QBeYS8r4CdHYWEGMmIj3H1U64jgkdZzECcSOJAyJ9TjuqcQZvw1Y+4AOBN9SeYJPJmFn2cM4/2g== +terser-webpack-plugin@^5.3.10: + version "5.3.10" + resolved "https://registry.yarnpkg.com/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz#904f4c9193c6fd2a03f693a2150c62a92f40d199" + integrity sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w== dependencies: - jest-worker "^27.0.6" + "@jridgewell/trace-mapping" "^0.3.20" + jest-worker "^27.4.5" schema-utils "^3.1.1" - serialize-javascript "^6.0.0" - source-map "^0.6.1" - terser "^5.7.2" + serialize-javascript "^6.0.1" + terser "^5.26.0" -terser@^5.7.2: - version "5.10.0" - resolved "https://registry.yarnpkg.com/terser/-/terser-5.10.0.tgz#b86390809c0389105eb0a0b62397563096ddafcc" - integrity sha512-AMmF99DMfEDiRJfxfY5jj5wNH/bYO09cniSqhfoyxc8sFoYIgkJy86G04UoZU5VjlpnplVu0K6Tx6E9b5+DlHA== +terser@^5.26.0: + version "5.31.6" + resolved "https://registry.yarnpkg.com/terser/-/terser-5.31.6.tgz#c63858a0f0703988d0266a82fcbf2d7ba76422b1" + integrity sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg== dependencies: + "@jridgewell/source-map" "^0.3.3" + acorn "^8.8.2" commander "^2.20.0" - source-map "~0.7.2" source-map-support "~0.5.20" test-exclude@^6.0.0: @@ -11653,6 +11699,14 @@ update-browserslist-db@^1.0.9: escalade "^3.1.1" picocolors "^1.0.0" +update-browserslist-db@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz#7ca61c0d8650766090728046e416a8cde682859e" + integrity sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ== + dependencies: + escalade "^3.1.2" + picocolors "^1.0.1" + uri-js@^4.2.2: version "4.4.1" resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" @@ -12110,10 +12164,10 @@ walker@^1.0.8: dependencies: makeerror "1.0.12" -watchpack@^2.4.0: - version "2.4.0" - resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.0.tgz#fa33032374962c78113f93c7f2fb4c54c9862a5d" - integrity sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg== +watchpack@^2.4.1: + version "2.4.2" + resolved "https://registry.yarnpkg.com/watchpack/-/watchpack-2.4.2.tgz#2feeaed67412e7c33184e5a79ca738fbd38564da" + integrity sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw== dependencies: glob-to-regexp "^0.4.1" graceful-fs "^4.1.2" @@ -12238,34 +12292,33 @@ webpack-sources@^3.2.3: resolved "https://registry.yarnpkg.com/webpack-sources/-/webpack-sources-3.2.3.tgz#2d4daab8451fd4b240cc27055ff6a0c2ccea0cde" integrity sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w== -webpack@5.75.0: - version "5.75.0" - resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.75.0.tgz#1e440468647b2505860e94c9ff3e44d5b582c152" - integrity sha512-piaIaoVJlqMsPtX/+3KTTO6jfvrSYgauFVdt8cr9LTHKmcq/AMd4mhzsiP7ZF/PGRNPGA8336jldh9l2Kt2ogQ== +webpack@5.75.0, webpack@5.94.0: + version "5.94.0" + resolved "https://registry.yarnpkg.com/webpack/-/webpack-5.94.0.tgz#77a6089c716e7ab90c1c67574a28da518a20970f" + integrity sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg== dependencies: - "@types/eslint-scope" "^3.7.3" - "@types/estree" "^0.0.51" - "@webassemblyjs/ast" "1.11.1" - "@webassemblyjs/wasm-edit" "1.11.1" - "@webassemblyjs/wasm-parser" "1.11.1" + "@types/estree" "^1.0.5" + "@webassemblyjs/ast" "^1.12.1" + "@webassemblyjs/wasm-edit" "^1.12.1" + "@webassemblyjs/wasm-parser" "^1.12.1" acorn "^8.7.1" - acorn-import-assertions "^1.7.6" - browserslist "^4.14.5" + acorn-import-attributes "^1.9.5" + browserslist "^4.21.10" chrome-trace-event "^1.0.2" - enhanced-resolve "^5.10.0" - es-module-lexer "^0.9.0" + 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.9" + 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.1.0" + schema-utils "^3.2.0" tapable "^2.1.1" - terser-webpack-plugin "^5.1.3" - watchpack "^2.4.0" + terser-webpack-plugin "^5.3.10" + watchpack "^2.4.1" webpack-sources "^3.2.3" websocket-driver@>=0.5.1, websocket-driver@^0.7.4: From 8f973cb40822438c2a166351d90dae11ea76a7c9 Mon Sep 17 00:00:00 2001 From: SanjalKatiyar Date: Tue, 10 Sep 2024 15:39:22 +0530 Subject: [PATCH 03/22] Add initial setup for AWS S3 SDK --- package.json | 1 + .../components/s3-browser/noobaa-context.tsx | 81 ++ packages/odf/constants/index.ts | 1 + packages/odf/constants/s3-browser.ts | 4 + packages/shared/src/models/console-models.ts | 14 + packages/shared/src/s3/commands.ts | 31 + packages/shared/src/s3/index.ts | 2 + packages/shared/src/s3/types.ts | 16 + yarn.lock | 1108 +++++++++++++++++ 9 files changed, 1258 insertions(+) create mode 100644 packages/odf/components/s3-browser/noobaa-context.tsx create mode 100644 packages/odf/constants/s3-browser.ts create mode 100644 packages/shared/src/s3/commands.ts create mode 100644 packages/shared/src/s3/index.ts create mode 100644 packages/shared/src/s3/types.ts diff --git a/package.json b/package.json index 2fee1523c..3752a8f66 100644 --- a/package.json +++ b/package.json @@ -58,6 +58,7 @@ "dev:c": "yarn ocp-console & PLUGIN=${PLUGIN} I8N_NS=${I8N_NS} yarn server:plugin & wait" }, "dependencies": { + "@aws-sdk/client-s3": "3.614.0", "@openshift-console/dynamic-plugin-sdk": "1.3.0", "@openshift-console/dynamic-plugin-sdk-internal": "1.0.0", "@openshift-console/dynamic-plugin-sdk-webpack": "1.1.0", diff --git a/packages/odf/components/s3-browser/noobaa-context.tsx b/packages/odf/components/s3-browser/noobaa-context.tsx new file mode 100644 index 000000000..0cd193da7 --- /dev/null +++ b/packages/odf/components/s3-browser/noobaa-context.tsx @@ -0,0 +1,81 @@ +import * as React from 'react'; +import { useSafeK8sGet } from '@odf/core/hooks'; +import { useODFNamespaceSelector } from '@odf/core/redux'; +import { StatusBox } from '@odf/shared/generic/status-box'; +import { SecretModel, RouteModel } from '@odf/shared/models'; +import { S3Commands } from '@odf/shared/s3'; +import { SecretKind, K8sResourceKind } from '@odf/shared/types'; +import * as _ from 'lodash-es'; +import { + NOOBAA_ADMIN_SECRET, + NOOBAA_S3_ROUTE, + NOOBAA_ACCESS_KEY_ID, + NOOBAA_SECRET_ACCESS_KEY, +} from '../../constants'; + +type NoobaaS3ContextType = { + noobaaS3: S3Commands; +}; + +type NoobaaS3ProviderType = { + loading?: boolean; + error?: unknown; +}; + +export const NoobaaS3Context = React.createContext( + {} as NoobaaS3ContextType +); + +// ToDo: In case this provider is needed at too many places, consider applying it to the console's root or use redux instead +export const NoobaaS3Provider: React.FC = ({ + children, + loading, + error, +}) => { + const { isODFNsLoaded, odfNsLoadError } = useODFNamespaceSelector(); + + const [secretData, secretLoaded, secretError] = useSafeK8sGet( + SecretModel, + NOOBAA_ADMIN_SECRET + ); + // ToDo: Configure ConsolePlugin proxy instead of using Route + const [routeData, routeLoaded, routeError] = useSafeK8sGet( + RouteModel, + NOOBAA_S3_ROUTE + ); + + const [noobaaS3, noobaaS3Error]: [S3Commands, unknown] = React.useMemo(() => { + if (!_.isEmpty(secretData) && !_.isEmpty(routeData)) { + try { + // ToDo: Remove this once ConsolePlugin proxy is configured + const endpoint = `http://${routeData.spec.host}`; + const accessKeyId = atob(secretData.data?.[NOOBAA_ACCESS_KEY_ID]); + const secretAccessKey = atob( + secretData.data?.[NOOBAA_SECRET_ACCESS_KEY] + ); + + return [new S3Commands(endpoint, accessKeyId, secretAccessKey), null]; + } catch (err) { + return [{} as S3Commands, err]; + } + } + return [{} as S3Commands, null]; + }, [secretData, routeData]); + + const allLoaded = + isODFNsLoaded && + secretLoaded && + routeLoaded && + !loading && + !_.isEmpty(noobaaS3); + const anyError = + odfNsLoadError || secretError || routeError || noobaaS3Error || error; + + return allLoaded && !anyError ? ( + + {children} + + ) : ( + + ); +}; diff --git a/packages/odf/constants/index.ts b/packages/odf/constants/index.ts index 16fa38e87..e9c6efb9f 100644 --- a/packages/odf/constants/index.ts +++ b/packages/odf/constants/index.ts @@ -6,3 +6,4 @@ export * from './tooltips'; export * from './mcg'; export * from './providerSchema'; export * from './data-protection'; +export * from './s3-browser'; diff --git a/packages/odf/constants/s3-browser.ts b/packages/odf/constants/s3-browser.ts new file mode 100644 index 000000000..08818f723 --- /dev/null +++ b/packages/odf/constants/s3-browser.ts @@ -0,0 +1,4 @@ +export const NOOBAA_ADMIN_SECRET = 'noobaa-admin'; +export const NOOBAA_S3_ROUTE = 's3'; +export const NOOBAA_ACCESS_KEY_ID = 'AWS_ACCESS_KEY_ID'; +export const NOOBAA_SECRET_ACCESS_KEY = 'AWS_SECRET_ACCESS_KEY'; diff --git a/packages/shared/src/models/console-models.ts b/packages/shared/src/models/console-models.ts index 96bf0b6fd..5f1d1e538 100644 --- a/packages/shared/src/models/console-models.ts +++ b/packages/shared/src/models/console-models.ts @@ -62,3 +62,17 @@ export const ProjectModel: K8sKind = { // t('Projects') labelPluralKey: 'Projects', }; + +export const RouteModel: K8sKind = { + label: 'Route', + labelKey: 'Route', + labelPlural: 'Routes', + labelPluralKey: 'Routes', + apiGroup: 'route.openshift.io', + apiVersion: 'v1', + plural: 'routes', + abbr: 'RT', + namespaced: true, + kind: 'Route', + id: 'route', +}; diff --git a/packages/shared/src/s3/commands.ts b/packages/shared/src/s3/commands.ts new file mode 100644 index 000000000..733b6352a --- /dev/null +++ b/packages/shared/src/s3/commands.ts @@ -0,0 +1,31 @@ +import { + S3Client, + ListBucketsCommand, + ListObjectsCommand, +} from '@aws-sdk/client-s3'; +import { ListBuckets, ListObjects } from './types'; + +export class S3Commands { + private s3Client: S3Client; + + constructor(endpoint: string, accessKeyId: string, secretAccessKey: string) { + this.s3Client = new S3Client({ + // "region" is a required parameter for the SDK, using "none" as a workaround + region: 'none', + endpoint, + credentials: { + accessKeyId, + secretAccessKey, + }, + forcePathStyle: true, + }); + } + + // Bucket command members + listBuckets: ListBuckets = (input) => + this.s3Client.send(new ListBucketsCommand(input)); + + // Object command members + listObjects: ListObjects = (input) => + this.s3Client.send(new ListObjectsCommand(input)); +} diff --git a/packages/shared/src/s3/index.ts b/packages/shared/src/s3/index.ts new file mode 100644 index 000000000..b9d7505fe --- /dev/null +++ b/packages/shared/src/s3/index.ts @@ -0,0 +1,2 @@ +export * from './commands'; +export * from './types'; diff --git a/packages/shared/src/s3/types.ts b/packages/shared/src/s3/types.ts new file mode 100644 index 000000000..06e8a7898 --- /dev/null +++ b/packages/shared/src/s3/types.ts @@ -0,0 +1,16 @@ +import { + ListBucketsCommandInput, + ListBucketsCommandOutput, + ListObjectsCommandInput, + ListObjectsCommandOutput, +} from '@aws-sdk/client-s3'; + +// Bucket command types +export type ListBuckets = ( + input?: ListBucketsCommandInput +) => Promise; + +// Object command types +export type ListObjects = ( + input: ListObjectsCommandInput +) => Promise; diff --git a/yarn.lock b/yarn.lock index a6ba5bd99..c91af7bf6 100644 --- a/yarn.lock +++ b/yarn.lock @@ -15,6 +15,598 @@ "@jridgewell/gen-mapping" "^0.1.0" "@jridgewell/trace-mapping" "^0.3.9" +"@aws-crypto/crc32@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32/-/crc32-5.2.0.tgz#cfcc22570949c98c6689cfcbd2d693d36cdae2e1" + integrity sha512-nLbCWqQNgUiwwtFsen1AdzAtvuLRsQS8rYgMuxCrdKf9kOssamGLuPwyTY9wyYblNr9+1XM8v6zoDTPPSIeANg== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/crc32c@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/crc32c/-/crc32c-5.2.0.tgz#4e34aab7f419307821509a98b9b08e84e0c1917e" + integrity sha512-+iWb8qaHLYKrNvGRbiYRHSdKRWhto5XlZUEBwDjYNf+ly5SVYG6zEoYIdxvf5R3zyeP16w4PLBn3rH1xc74Rag== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/sha1-browser@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha1-browser/-/sha1-browser-5.2.0.tgz#b0ee2d2821d3861f017e965ef3b4cb38e3b6a0f4" + integrity sha512-OH6lveCFfcDjX4dbAvCFSYUjJZjDr/3XJ3xHtjn3Oj5b9RjojQo8npoLeA/bNwkOkrSQ0wgrHzXk4tDRxGKJeg== + dependencies: + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-browser@5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz#153895ef1dba6f9fce38af550e0ef58988eb649e" + integrity sha512-AXfN/lGotSQwu6HNcEsIASo7kWXZ5HYWvfOmSNKDsEqC4OashTp8alTmaz+F7TC2L083SFv5RdB+qU3Vs1kZqw== + dependencies: + "@aws-crypto/sha256-js" "^5.2.0" + "@aws-crypto/supports-web-crypto" "^5.2.0" + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + "@aws-sdk/util-locate-window" "^3.0.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-crypto/sha256-js@5.2.0", "@aws-crypto/sha256-js@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/sha256-js/-/sha256-js-5.2.0.tgz#c4fdb773fdbed9a664fc1a95724e206cf3860042" + integrity sha512-FFQQyu7edu4ufvIZ+OadFpHHOt+eSTBaYaki44c+akjg7qZg9oOQeLlk77F6tSYqjDAFClrHJk9tMf0HdVyOvA== + dependencies: + "@aws-crypto/util" "^5.2.0" + "@aws-sdk/types" "^3.222.0" + tslib "^2.6.2" + +"@aws-crypto/supports-web-crypto@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/supports-web-crypto/-/supports-web-crypto-5.2.0.tgz#a1e399af29269be08e695109aa15da0a07b5b5fb" + integrity sha512-iAvUotm021kM33eCdNfwIN//F77/IADDSs58i+MDaOqFrVjZo9bAal0NK7HurRuWLLpF1iLX7gbWrjHjeo+YFg== + dependencies: + tslib "^2.6.2" + +"@aws-crypto/util@^5.2.0": + version "5.2.0" + resolved "https://registry.yarnpkg.com/@aws-crypto/util/-/util-5.2.0.tgz#71284c9cffe7927ddadac793c14f14886d3876da" + integrity sha512-4RkU9EsI6ZpBve5fseQlGNUWKMa1RLPQ1dnjnQoe07ldfIzcsGb5hC5W0Dm7u423KWzawlrpbjXBrXCEv9zazQ== + dependencies: + "@aws-sdk/types" "^3.222.0" + "@smithy/util-utf8" "^2.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-s3@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.614.0.tgz#39620491e328d86282d0f9105fde7dd59427b4a1" + integrity sha512-9BlhfeBegvyjOqHtcr9kvrT80wiy7EVUiqYyTFiiDv/hJIcG88XHQCZdLU7658XBkQ7aFrr5b8rF2HRD1oroxw== + dependencies: + "@aws-crypto/sha1-browser" "5.2.0" + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.614.0" + "@aws-sdk/client-sts" "3.614.0" + "@aws-sdk/core" "3.614.0" + "@aws-sdk/credential-provider-node" "3.614.0" + "@aws-sdk/middleware-bucket-endpoint" "3.614.0" + "@aws-sdk/middleware-expect-continue" "3.609.0" + "@aws-sdk/middleware-flexible-checksums" "3.614.0" + "@aws-sdk/middleware-host-header" "3.609.0" + "@aws-sdk/middleware-location-constraint" "3.609.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.609.0" + "@aws-sdk/middleware-sdk-s3" "3.614.0" + "@aws-sdk/middleware-signing" "3.609.0" + "@aws-sdk/middleware-ssec" "3.609.0" + "@aws-sdk/middleware-user-agent" "3.614.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/signature-v4-multi-region" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.614.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.614.0" + "@aws-sdk/xml-builder" "3.609.0" + "@smithy/config-resolver" "^3.0.5" + "@smithy/core" "^2.2.6" + "@smithy/eventstream-serde-browser" "^3.0.4" + "@smithy/eventstream-serde-config-resolver" "^3.0.3" + "@smithy/eventstream-serde-node" "^3.0.4" + "@smithy/fetch-http-handler" "^3.2.1" + "@smithy/hash-blob-browser" "^3.1.2" + "@smithy/hash-node" "^3.0.3" + "@smithy/hash-stream-node" "^3.1.2" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/md5-js" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.3" + "@smithy/middleware-endpoint" "^3.0.5" + "@smithy/middleware-retry" "^3.0.9" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/node-http-handler" "^3.1.2" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.7" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.9" + "@smithy/util-defaults-mode-node" "^3.0.9" + "@smithy/util-endpoints" "^2.0.5" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-stream" "^3.0.6" + "@smithy/util-utf8" "^3.0.0" + "@smithy/util-waiter" "^3.1.2" + tslib "^2.6.2" + +"@aws-sdk/client-sso-oidc@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.614.0.tgz#61d20af829a17aa15664bcb7a1b4aed165191435" + integrity sha512-BI1NWcpppbHg/28zbUg54dZeckork8BItZIcjls12vxasy+p3iEzrJVG60jcbUTTsk3Qc1tyxNfrdcVqx0y7Ww== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.614.0" + "@aws-sdk/credential-provider-node" "3.614.0" + "@aws-sdk/middleware-host-header" "3.609.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.609.0" + "@aws-sdk/middleware-user-agent" "3.614.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.614.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.614.0" + "@smithy/config-resolver" "^3.0.5" + "@smithy/core" "^2.2.6" + "@smithy/fetch-http-handler" "^3.2.1" + "@smithy/hash-node" "^3.0.3" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.3" + "@smithy/middleware-endpoint" "^3.0.5" + "@smithy/middleware-retry" "^3.0.9" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/node-http-handler" "^3.1.2" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.7" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.9" + "@smithy/util-defaults-mode-node" "^3.0.9" + "@smithy/util-endpoints" "^2.0.5" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-sso@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.614.0.tgz#bf578a579c477e41cea61368fef5394f6ccae45a" + integrity sha512-p5pyYaxRzBttjBkqfc8i3K7DzBdTg3ECdVgBo6INIUxfvDy0J8QUE8vNtCgvFIkq+uPw/8M+Eo4zzln7anuO0Q== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/core" "3.614.0" + "@aws-sdk/middleware-host-header" "3.609.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.609.0" + "@aws-sdk/middleware-user-agent" "3.614.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.614.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.614.0" + "@smithy/config-resolver" "^3.0.5" + "@smithy/core" "^2.2.6" + "@smithy/fetch-http-handler" "^3.2.1" + "@smithy/hash-node" "^3.0.3" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.3" + "@smithy/middleware-endpoint" "^3.0.5" + "@smithy/middleware-retry" "^3.0.9" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/node-http-handler" "^3.1.2" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.7" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.9" + "@smithy/util-defaults-mode-node" "^3.0.9" + "@smithy/util-endpoints" "^2.0.5" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/client-sts@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.614.0.tgz#bb688944e54f147c8093e2d79b618263ee43cb19" + integrity sha512-i6QmaVA1KHHYNnI2VYQy/sc31rLm4+jSp8b/YbQpFnD0w3aXsrEEHHlxek45uSkHb4Nrj1omFBVy/xp1WVYx2Q== + dependencies: + "@aws-crypto/sha256-browser" "5.2.0" + "@aws-crypto/sha256-js" "5.2.0" + "@aws-sdk/client-sso-oidc" "3.614.0" + "@aws-sdk/core" "3.614.0" + "@aws-sdk/credential-provider-node" "3.614.0" + "@aws-sdk/middleware-host-header" "3.609.0" + "@aws-sdk/middleware-logger" "3.609.0" + "@aws-sdk/middleware-recursion-detection" "3.609.0" + "@aws-sdk/middleware-user-agent" "3.614.0" + "@aws-sdk/region-config-resolver" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.614.0" + "@aws-sdk/util-user-agent-browser" "3.609.0" + "@aws-sdk/util-user-agent-node" "3.614.0" + "@smithy/config-resolver" "^3.0.5" + "@smithy/core" "^2.2.6" + "@smithy/fetch-http-handler" "^3.2.1" + "@smithy/hash-node" "^3.0.3" + "@smithy/invalid-dependency" "^3.0.3" + "@smithy/middleware-content-length" "^3.0.3" + "@smithy/middleware-endpoint" "^3.0.5" + "@smithy/middleware-retry" "^3.0.9" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/node-http-handler" "^3.1.2" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.7" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-body-length-node" "^3.0.0" + "@smithy/util-defaults-mode-browser" "^3.0.9" + "@smithy/util-defaults-mode-node" "^3.0.9" + "@smithy/util-endpoints" "^2.0.5" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/core@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.614.0.tgz#7d4ce96cd98f85eb2dd0627586581296b6a26662" + integrity sha512-BUuS5/1YkgmKc4J0bg83XEtMyDHVyqG2QDzfmhYe8gbOIZabUl1FlrFVwhCAthtrrI6MPGTQcERB4BtJKUSplw== + dependencies: + "@smithy/core" "^2.2.6" + "@smithy/protocol-http" "^4.0.3" + "@smithy/signature-v4" "^3.1.2" + "@smithy/smithy-client" "^3.1.7" + "@smithy/types" "^3.3.0" + fast-xml-parser "4.2.5" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-env@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.609.0.tgz#b3f32e5a8ff8b541e151eadadfb60283aa3d835e" + integrity sha512-v69ZCWcec2iuV9vLVJMa6fAb5xwkzN4jYIT8yjo2c4Ia/j976Q+TPf35Pnz5My48Xr94EFcaBazrWedF+kwfuQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-http@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.614.0.tgz#2cdc07e029447182ada8ee18dcdb6bccddc57da5" + integrity sha512-YIEjlNUKb3Vo/iTnGAPdsiDC3FUUnNoex2OwU8LmR7AkYZiWdB8nx99DfgkkY+OFMUpw7nKD2PCOtuFONelfGA== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/fetch-http-handler" "^3.2.1" + "@smithy/node-http-handler" "^3.1.2" + "@smithy/property-provider" "^3.1.3" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.7" + "@smithy/types" "^3.3.0" + "@smithy/util-stream" "^3.0.6" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-ini@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.614.0.tgz#5c3e514d09d37aad167ab3571d10fb18c182ba5e" + integrity sha512-KfLuLFGwlvFSZ2MuzYwWGPb1y5TeiwX5okIDe0aQ1h10oD3924FXbN+mabOnUHQ8EFcGAtCaWbrC86mI7ktC6A== + dependencies: + "@aws-sdk/credential-provider-env" "3.609.0" + "@aws-sdk/credential-provider-http" "3.614.0" + "@aws-sdk/credential-provider-process" "3.614.0" + "@aws-sdk/credential-provider-sso" "3.614.0" + "@aws-sdk/credential-provider-web-identity" "3.609.0" + "@aws-sdk/types" "3.609.0" + "@smithy/credential-provider-imds" "^3.1.4" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-node@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.614.0.tgz#5faf5e3bf02ccb891769e4a28c784a80be42dcfc" + integrity sha512-4J6gPEuFZP0mkWq5E//oMS1vrmMM88iNNcv7TEljYnsc6JTAlKejCyFwx6CN+nkIhmIZsl06SXIhBemzBdBPfg== + dependencies: + "@aws-sdk/credential-provider-env" "3.609.0" + "@aws-sdk/credential-provider-http" "3.614.0" + "@aws-sdk/credential-provider-ini" "3.614.0" + "@aws-sdk/credential-provider-process" "3.614.0" + "@aws-sdk/credential-provider-sso" "3.614.0" + "@aws-sdk/credential-provider-web-identity" "3.609.0" + "@aws-sdk/types" "3.609.0" + "@smithy/credential-provider-imds" "^3.1.4" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-process@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.614.0.tgz#b6b9382346dfe51c8fb448595ae55b930532c897" + integrity sha512-Q0SI0sTRwi8iNODLs5+bbv8vgz8Qy2QdxbCHnPk/6Cx6LMf7i3dqmWquFbspqFRd8QiqxStrblwxrUYZi09tkA== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-sso@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.614.0.tgz#926de80b2f9288469604442bf2a395c5f2bf913d" + integrity sha512-55+gp0JY4451cWI1qXmVMFM0GQaBKiQpXv2P0xmd9P3qLDyeFUSEW8XPh0d2lb1ICr6x4s47ynXVdGCIv2mXMg== + dependencies: + "@aws-sdk/client-sso" "3.614.0" + "@aws-sdk/token-providers" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/credential-provider-web-identity@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.609.0.tgz#d29222d6894347ee89c781ea090d388656df1d2a" + integrity sha512-U+PG8NhlYYF45zbr1km3ROtBMYqyyj/oK8NRp++UHHeuavgrP+4wJ4wQnlEaKvJBjevfo3+dlIBcaeQ7NYejWg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-bucket-endpoint@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.614.0.tgz#28a99d82a0e1f039fda20aa0dc375ec777bd595c" + integrity sha512-TqEY8KcZeZ0LIxXaqG9RSSNnDHvD8RAFP4Xenwsxqnyad0Yn7LgCoFwRByelJ0t54ROYL1/ETJleWE4U4TOXdg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-arn-parser" "3.568.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/protocol-http" "^4.0.3" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-expect-continue@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.609.0.tgz#89af76f115aa5fadd5a82fe4e95a64cb15150517" + integrity sha512-+zeg//mSer4JZRxOB/4mUOMUJyuYPwATnIC5moBB8P8Xe+mJaVRFy8qlCtzYNj2TycnlsBPzTK0j7P1yvDh97w== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-flexible-checksums@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.614.0.tgz#e551aec40228e0891aee1648c6986ba82ea495c7" + integrity sha512-ZLpxVXMboDeMT7p2Kdp5m1uLVKOktkZoMgLvvbe3zbrU4Ji5IU5xVE0aa4X7H28BtuODCs6SLESnPs19bhMKlA== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@aws-crypto/crc32c" "5.2.0" + "@aws-sdk/types" "3.609.0" + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/protocol-http" "^4.0.3" + "@smithy/types" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-host-header@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.609.0.tgz#844302cb905e4d09b9a1ea4bfa96729833068913" + integrity sha512-iTKfo158lc4jLDfYeZmYMIBHsn8m6zX+XB6birCSNZ/rrlzAkPbGE43CNdKfvjyWdqgLMRXF+B+OcZRvqhMXPQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-location-constraint@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.609.0.tgz#7ed82d71e5ddcd50683ef2bbde10d1cc2492057e" + integrity sha512-xzsdoTkszGVqGVPjUmgoP7TORiByLueMHieI1fhQL888WPdqctwAx3ES6d/bA9Q/i8jnc6hs+Fjhy8UvBTkE9A== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-logger@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.609.0.tgz#ed44d201f091b8bac908cbf14724c7a4d492553f" + integrity sha512-S62U2dy4jMDhDFDK5gZ4VxFdWzCtLzwbYyFZx2uvPYTECkepLUfzLic2BHg2Qvtu4QjX+oGE3P/7fwaGIsGNuQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-recursion-detection@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.609.0.tgz#b7b869aaeac021a43dbea1435eaea81e5d2460b1" + integrity sha512-6sewsYB7/o/nbUfA99Aa/LokM+a/u4Wpm/X2o0RxOsDtSB795ObebLJe2BxY5UssbGaWkn7LswyfvrdZNXNj1w== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-sdk-s3@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.614.0.tgz#df5ae294e6c99dbea5288c08c8c210f8e79d0208" + integrity sha512-9fJTaiuuOfFV4FqmUEhPYzrtv7JOfYpB7q65oG3uayVH4ngWHIJkjnnX79zRhNZKdPGta+XIsnZzjEghg82ngA== + dependencies: + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-arn-parser" "3.568.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/protocol-http" "^4.0.3" + "@smithy/signature-v4" "^3.1.2" + "@smithy/smithy-client" "^3.1.7" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-signing@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.609.0.tgz#7e5c4e70302bf87a7aa3dfde83ec1b387bf819f0" + integrity sha512-2w3dBLjQVKIajYzokO4hduq8/0hSMUYHHmIo1Kdl+MSY8uwRBt12bLL6pyreobTcRMxizvn2ph/CQ9I1ST/WGQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/protocol-http" "^4.0.3" + "@smithy/signature-v4" "^3.1.2" + "@smithy/types" "^3.3.0" + "@smithy/util-middleware" "^3.0.3" + tslib "^2.6.2" + +"@aws-sdk/middleware-ssec@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.609.0.tgz#b87a8bc6133f3f6bdc6801183d0f9dad3f93cf9f" + integrity sha512-GZSD1s7+JswWOTamVap79QiDaIV7byJFssBW68GYjyRS5EBjNfwA/8s+6uE6g39R3ojyTbYOmvcANoZEhSULXg== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/middleware-user-agent@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.614.0.tgz#e6e3b5952db26a0452875c864d39d17707e4eccd" + integrity sha512-xUxh0UPQiMTG6E31Yvu6zVYlikrIcFDKljM11CaatInzvZubGTGiX0DjpqRlfGzUNsuPc/zNrKwRP2+wypgqIw== + dependencies: + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-endpoints" "3.614.0" + "@smithy/protocol-http" "^4.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/region-config-resolver@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.614.0.tgz#9cebb31a5bcfea2a41891fff7f28d0164cde179a" + integrity sha512-vDCeMXvic/LU0KFIUjpC3RiSTIkkvESsEfbVHiHH0YINfl8HnEqR5rj+L8+phsCeVg2+LmYwYxd5NRz4PHxt5g== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + tslib "^2.6.2" + +"@aws-sdk/signature-v4-multi-region@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.614.0.tgz#fabcef8b1c8ff052d48221dbff66390d6de89b4e" + integrity sha512-6mW3ONW4oLzxrePznYhz7sNT9ji9Am9ufLeV722tbOVS5lArBOZ6E1oPz0uYBhisUPznWKhcLRMggt7vIJWMng== + dependencies: + "@aws-sdk/middleware-sdk-s3" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@smithy/protocol-http" "^4.0.3" + "@smithy/signature-v4" "^3.1.2" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/token-providers@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.614.0.tgz#88da04f6d4ce916b0b0f6e045676d04201fb47fd" + integrity sha512-okItqyY6L9IHdxqs+Z116y5/nda7rHxLvROxtAJdLavWTYDydxrZstImNgGWTeVdmc0xX2gJCI77UYUTQWnhRw== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/types@3.609.0", "@aws-sdk/types@^3.222.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.609.0.tgz#06b39d799c9f197a7b43670243e8e78a3bf7d6a5" + integrity sha512-+Tqnh9w0h2LcrUsdXyT1F8mNhXz+tVYBtP19LpeEGntmvHwa2XzvLUCWpoIAIVsHp5+HdB2X9Sn0KAtmbFXc2Q== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/util-arn-parser@3.568.0": + version "3.568.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz#6a19a8c6bbaa520b6be1c278b2b8c17875b91527" + integrity sha512-XUKJWWo+KOB7fbnPP0+g/o5Ulku/X53t7i/h+sPHr5xxYTJJ9CYnbToo95mzxe7xWvkLrsNtJ8L+MnNn9INs2w== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-endpoints@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.614.0.tgz#6564b0ffd7dc3728221e9f9821f5aab1cc58468e" + integrity sha512-wK2cdrXHH4oz4IomV/yrGkftU9A+ITB6nFL+rxxyO78is2ifHJpFdV4aqk4LSkXYPi6CXWNru/Dqc7yiKXgJPw== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + "@smithy/util-endpoints" "^2.0.5" + tslib "^2.6.2" + +"@aws-sdk/util-locate-window@^3.0.0": + version "3.568.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz#2acc4b2236af0d7494f7e517401ba6b3c4af11ff" + integrity sha512-3nh4TINkXYr+H41QaPelCceEB2FXP3fxp93YZXB/kqJvX0U9j0N0Uk45gvsjmEPzG8XxkPEeLIfT2I1M7A6Lig== + dependencies: + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-browser@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.609.0.tgz#aa15421b2e32ae8bc589dac2bd6e8969832ce588" + integrity sha512-fojPU+mNahzQ0YHYBsx0ZIhmMA96H+ZIZ665ObU9tl+SGdbLneVZVikGve+NmHTQwHzwkFsZYYnVKAkreJLAtA== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/types" "^3.3.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@aws-sdk/util-user-agent-node@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.614.0.tgz#1e3f49a80f841a3f21647baed2adce01aac5beb5" + integrity sha512-15ElZT88peoHnq5TEoEtZwoXTXRxNrk60TZNdpl/TUBJ5oNJ9Dqb5Z4ryb8ofN6nm9aFf59GVAerFDz8iUoHBA== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@aws-sdk/xml-builder@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.609.0.tgz#eeb3d5cde000a23cfeeefe0354b6193440dc7d87" + integrity sha512-l9XxNcA4HX98rwCC2/KoiWcmEiRfZe4G+mYwDbCFT87JIMj6GBhLDkAzr/W8KAaA2IDr8Vc6J8fZPgVulxxfMA== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + "@babel/code-frame@7.12.11": version "7.12.11" resolved "https://registry.yarnpkg.com/@babel/code-frame/-/code-frame-7.12.11.tgz#f4ad435aa263db935b8f10f2c552d23fb716a63f" @@ -1368,6 +1960,495 @@ dependencies: "@sinonjs/commons" "^1.7.0" +"@smithy/abort-controller@^3.1.1": + version "3.1.1" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-3.1.1.tgz#291210611ff6afecfc198d0ca72d5771d8461d16" + integrity sha512-MBJBiidoe+0cTFhyxT8g+9g7CeVccLM0IOKKUMCNQ1CNMJ/eIfoo0RTfVrXOONEI1UCN1W+zkiHSbzUNE9dZtQ== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader-native@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz#f1104b30030f76f9aadcbd3cdca4377bd1ba2695" + integrity sha512-VDkpCYW+peSuM4zJip5WDfqvg2Mo/e8yxOv3VF1m11y7B8KKMKVFtmZWDe36Fvk8rGuWrPZHHXZ7rR7uM5yWyg== + dependencies: + "@smithy/util-base64" "^3.0.0" + tslib "^2.6.2" + +"@smithy/chunked-blob-reader@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader/-/chunked-blob-reader-3.0.0.tgz#e5d3b04e9b273ba8b7ede47461e2aa96c8aa49e0" + integrity sha512-sbnURCwjF0gSToGlsBiAmd1lRCmSn72nu9axfJu5lIx6RUEgHu6GwTMbqCdhQSi0Pumcm5vFxsi9XWXb2mTaoA== + dependencies: + tslib "^2.6.2" + +"@smithy/config-resolver@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-3.0.5.tgz#727978bba7ace754c741c259486a19d3083431fd" + integrity sha512-SkW5LxfkSI1bUC74OtfBbdz+grQXYiPYolyu8VfpLIjEoN/sHVBlLeGXMQ1vX4ejkgfv6sxVbQJ32yF2cl1veA== + dependencies: + "@smithy/node-config-provider" "^3.1.4" + "@smithy/types" "^3.3.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + tslib "^2.6.2" + +"@smithy/core@^2.2.6": + version "2.4.0" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-2.4.0.tgz#56e917b6ab2dffeba681a05395c40a757d681147" + integrity sha512-cHXq+FneIF/KJbt4q4pjN186+Jf4ZB0ZOqEaZMBhT79srEyGDDBV31NqBRBjazz8ppQ1bJbDJMY9ba5wKFV36w== + dependencies: + "@smithy/middleware-endpoint" "^3.1.0" + "@smithy/middleware-retry" "^3.0.15" + "@smithy/middleware-serde" "^3.0.3" + "@smithy/protocol-http" "^4.1.0" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-body-length-browser" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/credential-provider-imds@^3.1.4", "@smithy/credential-provider-imds@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.0.tgz#0e0e7ddaff1a8633cb927aee1056c0ab506b7ecf" + integrity sha512-0SCIzgd8LYZ9EJxUjLXBmEKSZR/P/w6l7Rz/pab9culE/RWuqelAKGJvn5qUOl8BgX8Yj5HWM50A5hiB/RzsgA== + dependencies: + "@smithy/node-config-provider" "^3.1.4" + "@smithy/property-provider" "^3.1.3" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + tslib "^2.6.2" + +"@smithy/eventstream-codec@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-3.1.2.tgz#4a1c72b34400631b829241151984a1ad8c4f963c" + integrity sha512-0mBcu49JWt4MXhrhRAlxASNy0IjDRFU+aWNDRal9OtUJvJNiwDuyKMUONSOjLjSCeGwZaE0wOErdqULer8r7yw== + dependencies: + "@aws-crypto/crc32" "5.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-hex-encoding" "^3.0.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-browser@^3.0.4": + version "3.0.6" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.6.tgz#a4ab4f7cfbd137bcaa54c375276f9214e568fd8f" + integrity sha512-2hM54UWQUOrki4BtsUI1WzmD13/SeaqT/AB3EUJKbcver/WgKNaiJ5y5F5XXuVe6UekffVzuUDrBZVAA3AWRpQ== + dependencies: + "@smithy/eventstream-serde-universal" "^3.0.5" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-config-resolver@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.3.tgz#f852e096d0ad112363b4685e1d441088d1fce67a" + integrity sha512-NVTYjOuYpGfrN/VbRQgn31x73KDLfCXCsFdad8DiIc3IcdxL+dYA9zEQPyOP7Fy2QL8CPy2WE4WCUD+ZsLNfaQ== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-node@^3.0.4": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.5.tgz#2bbf5c9312a28f23bc55ae284efa9499f8b8f982" + integrity sha512-+upXvnHNyZP095s11jF5dhGw/Ihzqwl5G+/KtMnoQOpdfC3B5HYCcDVG9EmgkhJMXJlM64PyN5gjJl0uXFQehQ== + dependencies: + "@smithy/eventstream-serde-universal" "^3.0.5" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/eventstream-serde-universal@^3.0.5": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.5.tgz#e1cc2f71f4d174a03e00ce4b563395a81dd17bec" + integrity sha512-5u/nXbyoh1s4QxrvNre9V6vfyoLWuiVvvd5TlZjGThIikc3G+uNiG9uOTCWweSRjv1asdDIWK7nOmN7le4RYHQ== + dependencies: + "@smithy/eventstream-codec" "^3.1.2" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/fetch-http-handler@^3.2.1", "@smithy/fetch-http-handler@^3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz#c754de7e0ff2541b73ac9ba7cc955940114b3d62" + integrity sha512-kBprh5Gs5h7ug4nBWZi1FZthdqSM+T7zMmsZxx0IBvWUn7dK3diz2SHn7Bs4dQGFDk8plDv375gzenDoNwrXjg== + dependencies: + "@smithy/protocol-http" "^4.1.0" + "@smithy/querystring-builder" "^3.0.3" + "@smithy/types" "^3.3.0" + "@smithy/util-base64" "^3.0.0" + tslib "^2.6.2" + +"@smithy/hash-blob-browser@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.2.tgz#90281c1f183d93686fb4f26107f1819644d68829" + integrity sha512-hAbfqN2UbISltakCC2TP0kx4LqXBttEv2MqSPE98gVuDFMf05lU+TpC41QtqGP3Ff5A3GwZMPfKnEy0VmEUpmg== + dependencies: + "@smithy/chunked-blob-reader" "^3.0.0" + "@smithy/chunked-blob-reader-native" "^3.0.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/hash-node@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-3.0.3.tgz#82c5cb7b0f1a29ee7319081853d2d158c07dff24" + integrity sha512-2ctBXpPMG+B3BtWSGNnKELJ7SH9e4TNefJS0cd2eSkOOROeBnnVBnAy9LtJ8tY4vUEoe55N4CNPxzbWvR39iBw== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/hash-stream-node@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-3.1.2.tgz#89f0290ae44b113863878e75b10c484ff48af71c" + integrity sha512-PBgDMeEdDzi6JxKwbfBtwQG9eT9cVwsf0dZzLXoJF4sHKHs5HEo/3lJWpn6jibfJwT34I1EBXpBnZE8AxAft6g== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/invalid-dependency@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-3.0.3.tgz#8d9fd70e3a94b565a4eba4ffbdc95238e1930528" + integrity sha512-ID1eL/zpDULmHJbflb864k72/SNOZCADRc9i7Exq3RUNJw6raWUSlFEQ+3PX3EYs++bTxZB2dE9mEHTQLv61tw== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/is-array-buffer@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-2.2.0.tgz#f84f0d9f9a36601a9ca9381688bd1b726fd39111" + integrity sha512-GGP3O9QFD24uGeAXYUjwSTXARoqpZykHadOmA8G5vfJPK0/DC67qa//0qvqrJzL1xc8WQWX7/yc7fwudjPHPhA== + dependencies: + tslib "^2.6.2" + +"@smithy/is-array-buffer@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz#9a95c2d46b8768946a9eec7f935feaddcffa5e7a" + integrity sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ== + dependencies: + tslib "^2.6.2" + +"@smithy/md5-js@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-3.0.3.tgz#55ee40aa24075b096c39f7910590c18ff7660c98" + integrity sha512-O/SAkGVwpWmelpj/8yDtsaVe6sINHLB1q8YE/+ZQbDxIw3SRLbTZuRaI10K12sVoENdnHqzPp5i3/H+BcZ3m3Q== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/middleware-content-length@^3.0.3": + version "3.0.5" + resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-3.0.5.tgz#1680aa4fb2a1c0505756103c9a5c2916307d9035" + integrity sha512-ILEzC2eyxx6ncej3zZSwMpB5RJ0zuqH7eMptxC4KN3f+v9bqT8ohssKbhNR78k/2tWW+KS5Spw+tbPF4Ejyqvw== + dependencies: + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/middleware-endpoint@^3.0.5", "@smithy/middleware-endpoint@^3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.0.tgz#9b8a496d87a68ec43f3f1a0139868d6765a88119" + integrity sha512-5y5aiKCEwg9TDPB4yFE7H6tYvGFf1OJHNczeY10/EFF8Ir8jZbNntQJxMWNfeQjC1mxPsaQ6mR9cvQbf+0YeMw== + dependencies: + "@smithy/middleware-serde" "^3.0.3" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + "@smithy/url-parser" "^3.0.3" + "@smithy/util-middleware" "^3.0.3" + tslib "^2.6.2" + +"@smithy/middleware-retry@^3.0.15", "@smithy/middleware-retry@^3.0.9": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-3.0.15.tgz#9b96900cde70d8aafd267e13f4e79241be90e0c7" + integrity sha512-iTMedvNt1ApdvkaoE8aSDuwaoc+BhvHqttbA/FO4Ty+y/S5hW6Ci/CTScG7vam4RYJWZxdTElc3MEfHRVH6cgQ== + dependencies: + "@smithy/node-config-provider" "^3.1.4" + "@smithy/protocol-http" "^4.1.0" + "@smithy/service-error-classification" "^3.0.3" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-retry" "^3.0.3" + tslib "^2.6.2" + uuid "^9.0.1" + +"@smithy/middleware-serde@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-3.0.3.tgz#74d974460f74d99f38c861e6862984543a880a66" + integrity sha512-puUbyJQBcg9eSErFXjKNiGILJGtiqmuuNKEYNYfUD57fUl4i9+mfmThtQhvFXU0hCVG0iEJhvQUipUf+/SsFdA== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/middleware-stack@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz#91845c7e61e6f137fa912b623b6def719a4f6ce7" + integrity sha512-r4klY9nFudB0r9UdSMaGSyjyQK5adUyPnQN/ZM6M75phTxOdnc/AhpvGD1fQUvgmqjQEBGCwpnPbDm8pH5PapA== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/node-config-provider@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz#05647bed666aa8036a1ad72323c1942e5d421be1" + integrity sha512-YvnElQy8HR4vDcAjoy7Xkx9YT8xZP4cBXcbJSgm/kxmiQu08DwUwj8rkGnyoJTpfl/3xYHH+d8zE+eHqoDCSdQ== + dependencies: + "@smithy/property-provider" "^3.1.3" + "@smithy/shared-ini-file-loader" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/node-http-handler@^3.1.2", "@smithy/node-http-handler@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-3.1.4.tgz#be4195e45639e690d522cd5f11513ea822ff9d5f" + integrity sha512-+UmxgixgOr/yLsUxcEKGH0fMNVteJFGkmRltYFHnBMlogyFdpzn2CwqWmxOrfJELhV34v0WSlaqG1UtE1uXlJg== + dependencies: + "@smithy/abort-controller" "^3.1.1" + "@smithy/protocol-http" "^4.1.0" + "@smithy/querystring-builder" "^3.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/property-provider@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-3.1.3.tgz#afd57ea82a3f6c79fbda95e3cb85c0ee0a79f39a" + integrity sha512-zahyOVR9Q4PEoguJ/NrFP4O7SMAfYO1HLhB18M+q+Z4KFd4V2obiMnlVoUFzFLSPeVt1POyNWneHHrZaTMoc/g== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/protocol-http@^4.0.3", "@smithy/protocol-http@^4.1.0": + version "4.1.0" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-4.1.0.tgz#23519d8f45bf4f33960ea5415847bc2b620a010b" + integrity sha512-dPVoHYQ2wcHooGXg3LQisa1hH0e4y0pAddPMeeUPipI1tEOqL6A4N0/G7abeq+K8wrwSgjk4C0wnD1XZpJm5aA== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/querystring-builder@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz#6b0e566f885bb84938d077c69e8f8555f686af13" + integrity sha512-vyWckeUeesFKzCDaRwWLUA1Xym9McaA6XpFfAK5qI9DKJ4M33ooQGqvM4J+LalH4u/Dq9nFiC8U6Qn1qi0+9zw== + dependencies: + "@smithy/types" "^3.3.0" + "@smithy/util-uri-escape" "^3.0.0" + tslib "^2.6.2" + +"@smithy/querystring-parser@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz#272a6b83f88dfcbbec8283d72a6bde850cc00091" + integrity sha512-zahM1lQv2YjmznnfQsWbYojFe55l0SLG/988brlLv1i8z3dubloLF+75ATRsqPBboUXsW6I9CPGE5rQgLfY0vQ== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/service-error-classification@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-3.0.3.tgz#73484255060a094aa9372f6cd972dcaf97e3ce80" + integrity sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ== + dependencies: + "@smithy/types" "^3.3.0" + +"@smithy/shared-ini-file-loader@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.4.tgz#7dceaf5a5307a2ee347ace8aba17312a1a3ede15" + integrity sha512-qMxS4hBGB8FY2GQqshcRUy1K6k8aBWP5vwm8qKkCT3A9K2dawUwOIJfqh9Yste/Bl0J2lzosVyrXDj68kLcHXQ== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/signature-v4@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-3.1.2.tgz#63fc0d4f9a955e902138fb0a57fafc96b9d4e8bb" + integrity sha512-3BcPylEsYtD0esM4Hoyml/+s7WP2LFhcM3J2AGdcL2vx9O60TtfpDOL72gjb4lU8NeRPeKAwR77YNyyGvMbuEA== + dependencies: + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/types" "^3.3.0" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-middleware" "^3.0.3" + "@smithy/util-uri-escape" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/smithy-client@^3.1.7", "@smithy/smithy-client@^3.2.0": + version "3.2.0" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-3.2.0.tgz#6db94024e4bdaefa079ac68dbea23dafbea230c8" + integrity sha512-pDbtxs8WOhJLJSeaF/eAbPgXg4VVYFlRcL/zoNYA5WbG3wBL06CHtBSg53ppkttDpAJ/hdiede+xApip1CwSLw== + dependencies: + "@smithy/middleware-endpoint" "^3.1.0" + "@smithy/middleware-stack" "^3.0.3" + "@smithy/protocol-http" "^4.1.0" + "@smithy/types" "^3.3.0" + "@smithy/util-stream" "^3.1.3" + tslib "^2.6.2" + +"@smithy/types@^3.3.0": + version "3.3.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.3.0.tgz#fae037c733d09bc758946a01a3de0ef6e210b16b" + integrity sha512-IxvBBCTFDHbVoK7zIxqA1ZOdc4QfM5HM7rGleCuHi7L1wnKv5Pn69xXJQ9hgxH60ZVygH9/JG0jRgtUncE3QUA== + dependencies: + tslib "^2.6.2" + +"@smithy/url-parser@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-3.0.3.tgz#e8a060d9810b24b1870385fc2b02485b8a6c5955" + integrity sha512-pw3VtZtX2rg+s6HMs6/+u9+hu6oY6U7IohGhVNnjbgKy86wcIsSZwgHrFR+t67Uyxvp4Xz3p3kGXXIpTNisq8A== + dependencies: + "@smithy/querystring-parser" "^3.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-base64@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-3.0.0.tgz#f7a9a82adf34e27a72d0719395713edf0e493017" + integrity sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ== + dependencies: + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-body-length-browser@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz#86ec2f6256310b4845a2f064e2f571c1ca164ded" + integrity sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-body-length-node@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz#99a291bae40d8932166907fe981d6a1f54298a6d" + integrity sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA== + dependencies: + tslib "^2.6.2" + +"@smithy/util-buffer-from@^2.2.0": + version "2.2.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-2.2.0.tgz#6fc88585165ec73f8681d426d96de5d402021e4b" + integrity sha512-IJdWBbTcMQ6DA0gdNhh/BwrLkDR+ADW5Kr1aZmd4k3DIF6ezMV4R2NIAmT08wQJ3yUK82thHWmC/TnK/wpMMIA== + dependencies: + "@smithy/is-array-buffer" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-buffer-from@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz#559fc1c86138a89b2edaefc1e6677780c24594e3" + integrity sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA== + dependencies: + "@smithy/is-array-buffer" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-config-provider@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz#62c6b73b22a430e84888a8f8da4b6029dd5b8efe" + integrity sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-defaults-mode-browser@^3.0.9": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.15.tgz#df73b9ae3dddc9126e0bb93ebc720b09d7163858" + integrity sha512-FZ4Psa3vjp8kOXcd3HJOiDPBCWtiilLl57r0cnNtq/Ga9RSDrM5ERL6xt+tO43+2af6Pn5Yp92x2n5vPuduNfg== + dependencies: + "@smithy/property-provider" "^3.1.3" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + bowser "^2.11.0" + tslib "^2.6.2" + +"@smithy/util-defaults-mode-node@^3.0.9": + version "3.0.15" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.15.tgz#d52476e1f2e66525d918b51f8d5a9b0972bf518e" + integrity sha512-KSyAAx2q6d0t6f/S4XB2+3+6aQacm3aLMhs9aLMqn18uYGUepbdssfogW5JQZpc6lXNBnp0tEnR5e9CEKmEd7A== + dependencies: + "@smithy/config-resolver" "^3.0.5" + "@smithy/credential-provider-imds" "^3.2.0" + "@smithy/node-config-provider" "^3.1.4" + "@smithy/property-provider" "^3.1.3" + "@smithy/smithy-client" "^3.2.0" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-endpoints@^2.0.5": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-2.0.5.tgz#e3a7a4d1c41250bfd2b2d890d591273a7d8934be" + integrity sha512-ReQP0BWihIE68OAblC/WQmDD40Gx+QY1Ez8mTdFMXpmjfxSyz2fVQu3A4zXRfQU9sZXtewk3GmhfOHswvX+eNg== + dependencies: + "@smithy/node-config-provider" "^3.1.4" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-hex-encoding@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz#32938b33d5bf2a15796cd3f178a55b4155c535e6" + integrity sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ== + dependencies: + tslib "^2.6.2" + +"@smithy/util-middleware@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-3.0.3.tgz#07bf9602682f5a6c55bc2f0384303f85fc68c87e" + integrity sha512-l+StyYYK/eO3DlVPbU+4Bi06Jjal+PFLSMmlWM1BEwyLxZ3aKkf1ROnoIakfaA7mC6uw3ny7JBkau4Yc+5zfWw== + dependencies: + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-retry@^3.0.3": + version "3.0.3" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-3.0.3.tgz#9b2ac0dbb1c81f69812a8affa4d772bebfc0e049" + integrity sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w== + dependencies: + "@smithy/service-error-classification" "^3.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + +"@smithy/util-stream@^3.0.6", "@smithy/util-stream@^3.1.3": + version "3.1.3" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-3.1.3.tgz#699ee2397cc1d474e46d2034039d5263812dca64" + integrity sha512-FIv/bRhIlAxC0U7xM1BCnF2aDRPq0UaelqBHkM2lsCp26mcBbgI0tCVTv+jGdsQLUmAMybua/bjDsSu8RQHbmw== + dependencies: + "@smithy/fetch-http-handler" "^3.2.4" + "@smithy/node-http-handler" "^3.1.4" + "@smithy/types" "^3.3.0" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-uri-escape@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz#e43358a78bf45d50bb736770077f0f09195b6f54" + integrity sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg== + dependencies: + tslib "^2.6.2" + +"@smithy/util-utf8@^2.0.0": + version "2.3.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-2.3.0.tgz#dd96d7640363259924a214313c3cf16e7dd329c5" + integrity sha512-R8Rdn8Hy72KKcebgLiv8jQcQkXoLMOGGv5uI1/k0l+snqkOzQ1R0ChUBCxWMlBsFMekWjq0wRudIweFs7sKT5A== + dependencies: + "@smithy/util-buffer-from" "^2.2.0" + tslib "^2.6.2" + +"@smithy/util-utf8@^3.0.0": + version "3.0.0" + resolved "https://registry.yarnpkg.com/@smithy/util-utf8/-/util-utf8-3.0.0.tgz#1a6a823d47cbec1fd6933e5fc87df975286d9d6a" + integrity sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA== + dependencies: + "@smithy/util-buffer-from" "^3.0.0" + tslib "^2.6.2" + +"@smithy/util-waiter@^3.1.2": + version "3.1.2" + resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-3.1.2.tgz#2d40c3312f3537feee763459a19acafab4c75cf3" + integrity sha512-4pP0EV3iTsexDx+8PPGAKCQpd/6hsQBaQhqWzU4hqKPHN5epPsxKbvUTIiYIHTxaKt6/kEaqPBpu/ufvfbrRzw== + dependencies: + "@smithy/abort-controller" "^3.1.1" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + "@stylelint/postcss-css-in-js@^0.37.2": version "0.37.2" resolved "https://registry.yarnpkg.com/@stylelint/postcss-css-in-js/-/postcss-css-in-js-0.37.2.tgz#7e5a84ad181f4234a2480803422a47b8749af3d2" @@ -3107,6 +4188,11 @@ boolbase@^1.0.0: resolved "https://registry.yarnpkg.com/boolbase/-/boolbase-1.0.0.tgz#68dff5fbe60c51eb37725ea9e3ed310dcc1e776e" integrity sha1-aN/1++YMUes3cl6p4+0xDcwed24= +bowser@^2.11.0: + version "2.11.0" + resolved "https://registry.yarnpkg.com/bowser/-/bowser-2.11.0.tgz#5ca3c35757a7aa5771500c70a73a9f91ef420a8f" + integrity sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA== + brace-expansion@^1.1.7: version "1.1.11" resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" @@ -5606,6 +6692,13 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= +fast-xml-parser@4.2.5: + version "4.2.5" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f" + integrity sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g== + dependencies: + strnum "^1.0.5" + fastest-levenshtein@^1.0.12: version "1.0.12" resolved "https://registry.yarnpkg.com/fastest-levenshtein/-/fastest-levenshtein-1.0.12.tgz#9990f7d3a88cc5a9ffd1f1745745251700d497e2" @@ -10945,6 +12038,11 @@ strip-json-comments@^3.1.0, strip-json-comments@^3.1.1: resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== +strnum@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/strnum/-/strnum-1.0.5.tgz#5c4e829fe15ad4ff0d20c3db5ac97b73c9b072db" + integrity sha512-J8bbNyKKXl5qYcR36TIO8W3mVGVHrmmxsd5PAItGkmyzwJvybiw2IVq5nqd0i4LSNSkB/sx9VHllbfFdr9k1JA== + style-loader@^0.23.1: version "0.23.1" resolved "https://registry.yarnpkg.com/style-loader/-/style-loader-0.23.1.tgz#cb9154606f3e771ab6c4ab637026a1049174d925" @@ -11421,6 +12519,11 @@ tslib@^2.4.0, tslib@^2.5.0: resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.6.2.tgz#703ac29425e7b37cd6fd456e92404d46d1f3e4ae" integrity sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q== +tslib@^2.6.2: + version "2.7.0" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.7.0.tgz#d9b40c5c40ab59e8738f297df3087bf1a2690c01" + integrity sha512-gLXCKdN1/j47AiHiOkJN69hJmcbGTHI0ImLmbYLHykhgeN0jVGola9yVjFgzCUklsZQMW55o+dW7IXv3RCXDzA== + tsm@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/tsm/-/tsm-2.3.0.tgz#f1a2f21393ca58268ef54ba2246bee5528e2ec43" @@ -11693,6 +12796,11 @@ uuid@^8.3.2: resolved "https://registry.yarnpkg.com/uuid/-/uuid-8.3.2.tgz#80d5b5ced271bb9af6c445f21a1a04c606cefbe2" integrity sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg== +uuid@^9.0.1: + version "9.0.1" + resolved "https://registry.yarnpkg.com/uuid/-/uuid-9.0.1.tgz#e188d4c8853cc722220392c424cd637f32293f30" + integrity sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA== + v8-compile-cache@^2.0.3, v8-compile-cache@^2.2.0, v8-compile-cache@^2.3.0: version "2.3.0" resolved "https://registry.yarnpkg.com/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz#2de19618c66dc247dcfb6f99338035d8245a2cee" From 465b880eadfef48b7e0be311d7531b11d2cae135 Mon Sep 17 00:00:00 2001 From: Bipul Adhikari Date: Fri, 20 Sep 2024 14:55:46 +0545 Subject: [PATCH 04/22] Block creation of external mode when Provider mode is already present Signed-off-by: Bipul Adhikari --- .../backing-storage-step/backing-storage-step.tsx | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/packages/odf/components/create-storage-system/create-storage-system-steps/backing-storage-step/backing-storage-step.tsx b/packages/odf/components/create-storage-system/create-storage-system-steps/backing-storage-step/backing-storage-step.tsx index 5cf11d8bb..08d8d9c32 100644 --- a/packages/odf/components/create-storage-system/create-storage-system-steps/backing-storage-step/backing-storage-step.tsx +++ b/packages/odf/components/create-storage-system/create-storage-system-steps/backing-storage-step/backing-storage-step.tsx @@ -3,6 +3,7 @@ import { STORAGE_CLUSTER_SYSTEM_KIND, NO_PROVISIONER, } from '@odf/core/constants'; +import { PROVIDER_MODE } from '@odf/core/features'; import { useSafeK8sGet } from '@odf/core/hooks'; import { useODFNamespaceSelector } from '@odf/core/redux'; import { scResource } from '@odf/core/resources'; @@ -25,6 +26,7 @@ import { } from '@odf/shared/types'; import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; import { isDefaultClass, getODFCsv, getGVKLabel } from '@odf/shared/utils'; +import { useFlag } from '@openshift-console/dynamic-plugin-sdk'; import * as _ from 'lodash-es'; import { Form, @@ -213,6 +215,7 @@ export const BackingStorage: React.FC = ({ const isFullDeployment = deployment === DeploymentType.FULL; const isProviderMode = deployment === DeploymentType.PROVIDER_MODE; + const isProviderModePresent = useFlag(PROVIDER_MODE) && hasInternal; const isNonRHCSExternalType = type === BackingStorageType.EXTERNAL && externalStorage !== StorageClusterModel.kind; @@ -269,7 +272,7 @@ export const BackingStorage: React.FC = ({ * Allow pre selecting the "external connection" option instead of the "existing" option * if an OCS Storage System is already created. */ - if (hasOCS && allowedExternalStorage.length) { + if (hasOCS && allowedExternalStorage.length && !isProviderModePresent) { dispatch({ type: 'backingStorage/setType', payload: BackingStorageType.EXTERNAL, @@ -384,7 +387,11 @@ export const BackingStorage: React.FC = ({ value={BackingStorageType.EXTERNAL} isChecked={type === BackingStorageType.EXTERNAL} onChange={(event, _unused) => onRadioSelect(_unused, event)} - isDisabled={allowedExternalStorage.length === 0 || isProviderMode} + isDisabled={ + allowedExternalStorage.length === 0 || + isProviderMode || + isProviderModePresent + } body={ showExternalStorageSelection && ( Date: Fri, 20 Sep 2024 10:14:06 +0200 Subject: [PATCH 05/22] Create Bucket page: display CreateOBC form. - Add CreateBucket page. - Refactor CreateOBC form to show the namespace selector when loaded in the CreateBucket page. --- locales/en/plugin__odf-console.json | 9 ++ .../mcg/CreateObjectBucketClaim.tsx | 143 +++++++++++++----- .../s3-browser/create-bucket/CreateBucket.tsx | 73 +++++++++ .../shared/src/dropdown/ResourceDropdown.tsx | 1 + plugins/odf/console-extensions.json | 8 + plugins/odf/console-plugin.json | 1 + 6 files changed, 193 insertions(+), 42 deletions(-) create mode 100644 packages/odf/components/s3-browser/create-bucket/CreateBucket.tsx diff --git a/locales/en/plugin__odf-console.json b/locales/en/plugin__odf-console.json index 0ce5b7c17..d14748138 100644 --- a/locales/en/plugin__odf-console.json +++ b/locales/en/plugin__odf-console.json @@ -1029,6 +1029,7 @@ "BucketClass": "BucketClass", "Enable replication": "Enable replication", "This option provides higher resiliency of objects stored in NooBaa buckets": "This option provides higher resiliency of objects stored in NooBaa buckets", + "A namespace controls access to the OBC and ties the buckets to a specific project.": "A namespace controls access to the OBC and ties the buckets to a specific project.", "Create ObjectBucketClaim": "Create ObjectBucketClaim", "Event log bucket": "Event log bucket", "Enter a bucket name": "Enter a bucket name", @@ -1096,6 +1097,14 @@ "NamespaceStore details": "NamespaceStore details", "Target Blob Container": "Target Blob Container", "Num Volumes": "Num Volumes", + "Create Bucket": "Create Bucket", + "An object bucket is a cloud storage container that organizes and manages files (objects), allowing users to store, retrieve and control access to data efficiently.": "An object bucket is a cloud storage container that organizes and manages files (objects), allowing users to store, retrieve and control access to data efficiently.", + "Select bucket creation method": "Select bucket creation method", + "Create via S3 API": "Create via S3 API", + "Ideal for applications and systems that need to interact directly with S3-compatible storage.": "Ideal for applications and systems that need to interact directly with S3-compatible storage.", + "Create via Object Bucket Claim": "Create via Object Bucket Claim", + "Ideal for Kubernetes environments providing a more abstracted approach to managing storage resources and leveraging dynamic provisioning.": "Ideal for Kubernetes environments providing a more abstracted approach to managing storage resources and leveraging dynamic provisioning.", + "OBC references a StorageClass that uses a provisioner to interact with the S3 API and create the bucket. Kubernetes binds the OBC to the bucket, making it accessible to applications.": "OBC references a StorageClass that uses a provisioner to interact with the S3 API and create the bucket. Kubernetes binds the OBC to the bucket, making it accessible to applications.", "<0>The amount of storage allocated to the client cluster for usage.<1>Due to simultaneous usage by multiple client clusters, actual available storage may vary affecting your allocated storage quota.": "<0>The amount of storage allocated to the client cluster for usage.<1>Due to simultaneous usage by multiple client clusters, actual available storage may vary affecting your allocated storage quota.", "No storage clients found.": "No storage clients found.", "You do not have any storage clients connected to this Data Foundation provider cluster.": "You do not have any storage clients connected to this Data Foundation provider cluster.", diff --git a/packages/odf/components/mcg/CreateObjectBucketClaim.tsx b/packages/odf/components/mcg/CreateObjectBucketClaim.tsx index 29977247a..90e38a626 100644 --- a/packages/odf/components/mcg/CreateObjectBucketClaim.tsx +++ b/packages/odf/components/mcg/CreateObjectBucketClaim.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { NOOBAA_PROVISIONER } from '@odf/core/constants'; +import { namespaceResource } from '@odf/core/resources'; import { BucketClassKind, ObjectBucketClaimKind } from '@odf/core/types'; import { createNewObjectBucketClaim, @@ -13,7 +14,7 @@ import ResourcesDropdown from '@odf/shared/dropdown/ResourceDropdown'; import { FormGroupController } from '@odf/shared/form-group-controller'; import { ButtonBar } from '@odf/shared/generic/ButtonBar'; import { TextInputWithFieldRequirements } from '@odf/shared/input-with-requirements'; -import { StorageClassModel } from '@odf/shared/models'; +import { NamespaceModel, StorageClassModel } from '@odf/shared/models'; import { getName } from '@odf/shared/selectors'; import { K8sResourceKind, StorageClassResourceKind } from '@odf/shared/types'; import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; @@ -22,6 +23,7 @@ import { useYupValidationResolver } from '@odf/shared/yup-validation-resolver'; import { getAPIVersionForModel, k8sCreate, + K8sResourceCommon, NamespaceBar, useActiveNamespace, } from '@openshift-console/dynamic-plugin-sdk'; @@ -364,10 +366,25 @@ export const CreateOBCForm: React.FC = (props) => { ); }; -export const CreateOBCPage: React.FC<{}> = () => { +type CreateOBCProps = { + showNamespaceSelector?: boolean; +}; + +export const CreateOBC: React.FC = ({ + showNamespaceSelector = false, +}) => { const { t } = useCustomTranslation(); const [state, dispatch] = React.useReducer(commonReducer, defaultState); - const [namespace, setNamespace] = useActiveNamespace(); + const [projectNs, setProjectNs] = useActiveNamespace(); + const { odfNamespace } = useODFNamespaceSelector(); + const [namespace, setNamespace] = React.useState( + showNamespaceSelector ? odfNamespace : projectNs + ); + // Keep form namespace in sync with project ns when ns form selector is not shown. + if (!showNamespaceSelector && projectNs !== namespace) { + setNamespace(projectNs); + } + const isAllProjectsInitially = React.useRef( namespace === ALL_NAMESPACES_KEY ); @@ -403,8 +420,11 @@ export const CreateOBCPage: React.FC<{}> = () => { * Also, if initial selection is "All Projects", it automatically re-selects "default" as the initial project. */ React.useEffect(() => { + if (showNamespaceSelector) { + return; + } if (isAllProjectsInitially.current) { - setNamespace(DEFAULT_NS); + setProjectNs(DEFAULT_NS); initialNamespace.current = DEFAULT_NS; isAllProjectsInitially.current = false; } else if (initialNamespace.current !== namespace) { @@ -412,7 +432,7 @@ export const CreateOBCPage: React.FC<{}> = () => { `/odf/object-storage/${referenceForModel(NooBaaObjectBucketClaimModel)}` ); } - }, [navigate, namespace, setNamespace]); + }, [navigate, namespace, setProjectNs, showNamespaceSelector]); const save = ( _unused: any, @@ -455,6 +475,7 @@ export const CreateOBCPage: React.FC<{}> = () => { }) .then((resource) => { dispatch({ type: 'unsetProgress' }); + //@TODO: update the resource path with the new bucket details path. const resourcePath = `${referenceForModel( NooBaaObjectBucketClaimModel )}/${resource.metadata.name}`; @@ -477,6 +498,80 @@ export const CreateOBCPage: React.FC<{}> = () => { // Using "allowFallback" in "NamespaceSafetyBox" so that they can default to "openshift-storage" (if case of access issues), // which is current use case as well (as we do not officially support UI if ODF is installed in any other Namespace). // ToDo (Sanjal): Update the non-admin "Role" to a "ClusterRole", then read list of NooBaa/BucketClasses across all namespaces. + return ( + +
+ {showNamespaceSelector && ( + ( + + resourceModel={NamespaceModel} + onSelect={(selectedNamespace) => + setNamespace(getName(selectedNamespace)) + } + onBlur={onBlur} + initialSelection={(resources) => + resources?.find((res) => getName(res) === namespace) + } + className="odf-mcg__resource-dropdown" + id="ns-dropdown" + data-test="ns-dropdown" + resource={namespaceResource} + /> + )} + /> + )} + + {!isValid && isSubmitted && ( + + )} + + + + + + + +
+ ); +}; + +export const CreateOBCPage: React.FC<{}> = () => { + const { t } = useCustomTranslation(); + return ( <> @@ -487,43 +582,7 @@ export const CreateOBCPage: React.FC<{}> = () => {

{t('Create ObjectBucketClaim')}

- -
- - {!isValid && isSubmitted && ( - - )} - - - - - - - -
+ ); diff --git a/packages/odf/components/s3-browser/create-bucket/CreateBucket.tsx b/packages/odf/components/s3-browser/create-bucket/CreateBucket.tsx new file mode 100644 index 000000000..69578ff8a --- /dev/null +++ b/packages/odf/components/s3-browser/create-bucket/CreateBucket.tsx @@ -0,0 +1,73 @@ +import * as React from 'react'; +import { CreateOBC } from '@odf/core/components/mcg/CreateObjectBucketClaim'; +import { useCustomTranslation } from '@odf/shared'; +import { Alert, FormGroup, Tile } from '@patternfly/react-core'; + +enum CreationMethod { + OBC = 'obc', + S3 = 's3', +} + +const CreateBucket: React.FC<{}> = () => { + const { t } = useCustomTranslation(); + const [method, setMethod] = React.useState(CreationMethod.S3); + + return ( + <> +
+

{t('Create Bucket')}

+

+ {t( + 'An object bucket is a cloud storage container that organizes and manages files (objects), allowing users to store, retrieve and control access to data efficiently.' + )} +

+
+
+
+ + setMethod(CreationMethod.S3)} + className="pf-v5-u-w-33 pf-v5-u-mr-md" + > + {t( + 'Ideal for applications and systems that need to interact directly with S3-compatible storage.' + )} + + setMethod(CreationMethod.OBC)} + className="pf-v5-u-w-33" + > + {t( + 'Ideal for Kubernetes environments providing a more abstracted approach to managing storage resources and leveraging dynamic provisioning.' + )} + + +
+ {method === CreationMethod.OBC && ( + <> + + + + )} + {/* @TODO: implement S3 form. */} +
+ + ); +}; + +export default CreateBucket; diff --git a/packages/shared/src/dropdown/ResourceDropdown.tsx b/packages/shared/src/dropdown/ResourceDropdown.tsx index 9b01dc6ae..8105abbc9 100644 --- a/packages/shared/src/dropdown/ResourceDropdown.tsx +++ b/packages/shared/src/dropdown/ResourceDropdown.tsx @@ -184,6 +184,7 @@ const ResourceDropdown: ResourceDropdown = ({ filterName(searchText, getName(res)) && (filterResource ? filterResource(res) : true) ) + .sort((a, b) => getName(a).localeCompare(getName(b))) .reduce((acc, curr) => { return [ ...acc, diff --git a/plugins/odf/console-extensions.json b/plugins/odf/console-extensions.json index 334da8c7f..a47611d1e 100644 --- a/plugins/odf/console-extensions.json +++ b/plugins/odf/console-extensions.json @@ -129,6 +129,14 @@ } } }, + { + "type": "console.page/route", + "properties": { + "path": ["/odf/object-storage/create-bucket"], + "exact": true, + "component": { "$codeRef": "createBucket.default" } + } + }, { "type": "console.page/route", "properties": { diff --git a/plugins/odf/console-plugin.json b/plugins/odf/console-plugin.json index b21ee624a..d464f0cf1 100644 --- a/plugins/odf/console-plugin.json +++ b/plugins/odf/console-plugin.json @@ -13,6 +13,7 @@ "obc": "@odf/core/components/mcg/ObjectBucketClaim", "createOBC": "@odf/core/components/mcg/CreateObjectBucketClaim", "ob": "@odf/core/components/mcg/ObjectBucket", + "createBucket": "@odf/core/components/s3-browser/create-bucket/CreateBucket", "ocs": "@odf/ocs/dashboards/odf-system-dashboard", "blockPoolDetailsPage": "@odf/ocs/storage-pool/BlockPoolDetailsPage", "createStoragePools": "@odf/ocs/storage-pool/CreateStoragePool", From 46125c993cf2acf63e5dbb94182498af69974f93 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alfonso=20Mart=C3=ADnez?= Date: Thu, 26 Sep 2024 09:40:42 +0200 Subject: [PATCH 06/22] Fix security issue: Backtracking regular expressions --- package.json | 2 +- packages/shared/package.json | 1 - yarn.lock | 224 +++++++++++++++++++++++++---------- 3 files changed, 165 insertions(+), 62 deletions(-) diff --git a/package.json b/package.json index f67e5cc94..89672ebaf 100644 --- a/package.json +++ b/package.json @@ -101,7 +101,6 @@ "react-i18next": "^11.11.4", "react-linkify": "^0.2.2", "react-redux": "7.2.2", - "react-router": "5.3.x", "react-router-dom": "5.3.x", "react-router-dom-v5-compat": "^6.11.2", "react-tagsinput": "^3.19.0", @@ -177,6 +176,7 @@ "jest-environment-jsdom/jsdom": "^20.0.3", "webpack": "5.94.0", "webpack-bundle-analyzer/ws": "^7.5.10", + "webpack-dev-server/express": "^4.21.0", "webpack-dev-server/ws": "^8.18.0", "tough-cookie": "^4.1.3" }, diff --git a/packages/shared/package.json b/packages/shared/package.json index d2655b5c2..6d2c0eceb 100644 --- a/packages/shared/package.json +++ b/packages/shared/package.json @@ -61,7 +61,6 @@ "react": "^17.0.1", "react-dom": "^17.0.1", "react-i18next": "^11.11.4", - "react-router": "5.3.x", "react-router-dom": "5.3.x", "react-router-dom-v5-compat": "^6.11.2" } diff --git a/yarn.lock b/yarn.lock index 11d920d61..a0131253d 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4176,21 +4176,21 @@ bluebird@^3.7.1, bluebird@^3.7.2: resolved "https://registry.yarnpkg.com/bluebird/-/bluebird-3.7.2.tgz#9f229c15be272454ffa973ace0dbee79a1b0c36f" integrity sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg== -body-parser@1.20.0: - version "1.20.0" - resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.0.tgz#3de69bd89011c11573d7bfee6a64f11b6bd27cc5" - integrity sha512-DfJ+q6EPcGKZD1QWUjSpqp+Q7bDQTsQIF4zfUAtZ6qk+H/3/QRhg9CEp39ss+/T2vw0+HaidC0ecJj/DRLIaKg== +body-parser@1.20.3: + version "1.20.3" + resolved "https://registry.yarnpkg.com/body-parser/-/body-parser-1.20.3.tgz#1953431221c6fb5cd63c4b36d53fab0928e548c6" + integrity sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g== dependencies: bytes "3.1.2" - content-type "~1.0.4" + content-type "~1.0.5" debug "2.6.9" depd "2.0.0" destroy "1.2.0" http-errors "2.0.0" iconv-lite "0.4.24" on-finished "2.4.1" - qs "6.10.3" - raw-body "2.5.1" + qs "6.13.0" + raw-body "2.5.2" type-is "~1.6.18" unpipe "1.0.0" @@ -4369,6 +4369,17 @@ call-bind@^1.0.0, call-bind@^1.0.2: function-bind "^1.1.1" get-intrinsic "^1.0.2" +call-bind@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.7.tgz#06016599c40c56498c18769d2730be242b6fa3b9" + integrity sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + function-bind "^1.1.2" + get-intrinsic "^1.2.4" + set-function-length "^1.2.1" + callsites@^3.0.0: version "3.1.0" resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" @@ -4896,6 +4907,11 @@ content-type@^1.0.4, content-type@~1.0.4: resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.4.tgz#e138cc75e040c727b1966fe5e5f8c9aee256fe3b" integrity sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA== +content-type@~1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/content-type/-/content-type-1.0.5.tgz#8b773162656d1d1086784c8f23a54ce6d73d7918" + integrity sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA== + convert-hrtime@^5.0.0: version "5.0.0" resolved "https://registry.yarnpkg.com/convert-hrtime/-/convert-hrtime-5.0.0.tgz#f2131236d4598b95de856926a67100a0a97e9fa3" @@ -4918,10 +4934,10 @@ cookie-signature@1.0.6: resolved "https://registry.yarnpkg.com/cookie-signature/-/cookie-signature-1.0.6.tgz#e303a882b342cc3ee8ca513a79999734dab3ae2c" integrity sha1-4wOogrNCzD7oylE6eZmXNNqzriw= -cookie@0.5.0: - version "0.5.0" - resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.5.0.tgz#d1f5d71adec6558c58f389987c366aa47e994f8b" - integrity sha512-YZ3GUyn/o8gfKJlnlX7g7xq4gyO6OSuhGPKaaGssGB2qgDUS0gPgtTvoyZLTt9Ab6dC4hfc9dV5arkvc/OCmrw== +cookie@0.6.0: + version "0.6.0" + resolved "https://registry.yarnpkg.com/cookie/-/cookie-0.6.0.tgz#2798b04b071b0ecbff0dbb62a505a8efa4e19051" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== copy-to-clipboard@^3: version "3.3.1" @@ -5662,6 +5678,15 @@ default-gateway@^6.0.3: dependencies: execa "^5.0.0" +define-data-property@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.4.tgz#894dc141bb7d3060ae4366f6a0107e68fbe48c5e" + integrity sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A== + dependencies: + es-define-property "^1.0.0" + es-errors "^1.3.0" + gopd "^1.0.1" + define-lazy-prop@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz#3f7ae421129bcaaac9bc74905c98a0009ec9ee7f" @@ -5951,6 +5976,11 @@ encodeurl@~1.0.2: resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-1.0.2.tgz#ad3ff4c86ec2d029322f5a02c3a9a606c95b3f59" integrity sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= +encodeurl@~2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/encodeurl/-/encodeurl-2.0.0.tgz#7b8ea898077d7e409d3ac45474ea38eaf0857a58" + integrity sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg== + encoding@^0.1.13: version "0.1.13" resolved "https://registry.yarnpkg.com/encoding/-/encoding-0.1.13.tgz#56574afdd791f54a8e9b2785c0582a2d26210fa9" @@ -6076,6 +6106,18 @@ es-abstract@^1.19.0, es-abstract@^1.19.1, es-abstract@^1.19.5: string.prototype.trimstart "^1.0.5" unbox-primitive "^1.0.2" +es-define-property@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-define-property/-/es-define-property-1.0.0.tgz#c7faefbdff8b2696cf5f46921edfb77cc4ba3845" + integrity sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ== + dependencies: + get-intrinsic "^1.2.4" + +es-errors@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/es-errors/-/es-errors-1.3.0.tgz#05f75a25dab98e4fb1dcd5e1472c0546d5057c8f" + integrity sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw== + es-get-iterator@^1.1.2: version "1.1.2" resolved "https://registry.yarnpkg.com/es-get-iterator/-/es-get-iterator-1.1.2.tgz#9234c54aba713486d7ebde0220864af5e2b283f7" @@ -6618,37 +6660,37 @@ expect@^29.0.0, expect@^29.3.1: jest-message-util "^29.3.1" jest-util "^29.3.1" -express@^4.17.3: - version "4.18.1" - resolved "https://registry.yarnpkg.com/express/-/express-4.18.1.tgz#7797de8b9c72c857b9cd0e14a5eea80666267caf" - integrity sha512-zZBcOX9TfehHQhtupq57OF8lFZ3UZi08Y97dwFCkD8p9d/d2Y3M+ykKcwaMDEL+4qyUolgBDX6AblpR3fL212Q== +express@^4.17.3, express@^4.21.0: + version "4.21.0" + resolved "https://registry.yarnpkg.com/express/-/express-4.21.0.tgz#d57cb706d49623d4ac27833f1cbc466b668eb915" + integrity sha512-VqcNGcj/Id5ZT1LZ/cfihi3ttTn+NJmkli2eZADigjq29qTlWi/hAQ43t/VLPq8+UX06FCEx3ByOYet6ZFblng== dependencies: accepts "~1.3.8" array-flatten "1.1.1" - body-parser "1.20.0" + body-parser "1.20.3" content-disposition "0.5.4" content-type "~1.0.4" - cookie "0.5.0" + cookie "0.6.0" cookie-signature "1.0.6" debug "2.6.9" depd "2.0.0" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" etag "~1.8.1" - finalhandler "1.2.0" + finalhandler "1.3.1" fresh "0.5.2" http-errors "2.0.0" - merge-descriptors "1.0.1" + merge-descriptors "1.0.3" methods "~1.1.2" on-finished "2.4.1" parseurl "~1.3.3" - path-to-regexp "0.1.7" + path-to-regexp "0.1.10" proxy-addr "~2.0.7" - qs "6.10.3" + qs "6.13.0" range-parser "~1.2.1" safe-buffer "5.2.1" - send "0.18.0" - serve-static "1.15.0" + send "0.19.0" + serve-static "1.16.2" setprototypeof "1.2.0" statuses "2.0.1" type-is "~1.6.18" @@ -6804,13 +6846,13 @@ fill-range@^7.0.1: dependencies: to-regex-range "^5.0.1" -finalhandler@1.2.0: - version "1.2.0" - resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.2.0.tgz#7d23fe5731b207b4640e4fcd00aec1f9207a7b32" - integrity sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg== +finalhandler@1.3.1: + version "1.3.1" + resolved "https://registry.yarnpkg.com/finalhandler/-/finalhandler-1.3.1.tgz#0c575f1d1d324ddd1da35ad7ece3df7d19088019" + integrity sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ== dependencies: debug "2.6.9" - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" on-finished "2.4.1" parseurl "~1.3.3" @@ -7027,6 +7069,11 @@ function-bind@^1.1.1: resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + function-timeout@^0.1.0: version "0.1.1" resolved "https://registry.yarnpkg.com/function-timeout/-/function-timeout-0.1.1.tgz#6bf71d3d24c894d43b2bec312cabb8c5add2e9da" @@ -7085,6 +7132,17 @@ get-intrinsic@^1.1.3: has "^1.0.3" has-symbols "^1.0.3" +get-intrinsic@^1.2.4: + version "1.2.4" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.4.tgz#e385f5a4b5227d449c3eabbad05494ef0abbeadd" + integrity sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ== + dependencies: + es-errors "^1.3.0" + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + get-node-dimensions@^1.2.1: version "1.2.1" resolved "https://registry.yarnpkg.com/get-node-dimensions/-/get-node-dimensions-1.2.1.tgz#fb7b4bb57060fb4247dd51c9d690dfbec56b0823" @@ -7394,6 +7452,18 @@ has-property-descriptors@^1.0.0: dependencies: get-intrinsic "^1.1.1" +has-property-descriptors@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz#963ed7d071dc7bf5f084c5bfbe0d1b6222586854" + integrity sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg== + dependencies: + es-define-property "^1.0.0" + +has-proto@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.3.tgz#b31ddfe9b0e6e9914536a6ab286426d0214f77fd" + integrity sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q== + has-symbols@^1.0.1, has-symbols@^1.0.2: version "1.0.2" resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.2.tgz#165d3070c00309752a1236a479331e3ac56f1423" @@ -7418,6 +7488,13 @@ has@^1.0.1, has@^1.0.3: dependencies: function-bind "^1.1.1" +hasown@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.2.tgz#003eaf91be7adc372e84ec59dc37252cedb80003" + integrity sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ== + dependencies: + function-bind "^1.1.2" + he@^1.1.0, he@^1.1.1: version "1.2.0" resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" @@ -8289,7 +8366,7 @@ is-wsl@^2.2.0: isarray@0.0.1: version "0.0.1" resolved "https://registry.yarnpkg.com/isarray/-/isarray-0.0.1.tgz#8a18acfca9a8f4177e09abfc6038939b05d1eedf" - integrity sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8= + integrity sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ== isarray@^2.0.5: version "2.0.5" @@ -9394,10 +9471,10 @@ meow@^9.0.0: type-fest "^0.18.0" yargs-parser "^20.2.3" -merge-descriptors@1.0.1: - version "1.0.1" - resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.1.tgz#b00aaa556dd8b44568150ec9d1b953f3f90cbb61" - integrity sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= +merge-descriptors@1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/merge-descriptors/-/merge-descriptors-1.0.3.tgz#d80319a65f3c7935351e5cfdac8f9318504dbed5" + integrity sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ== merge-stream@^2.0.0: version "2.0.0" @@ -9824,6 +9901,11 @@ object-inspect@^1.12.0: resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.0.tgz#6e2c120e868fd1fd18cb4f18c31741d0d6e776f0" integrity sha512-Ho2z80bVIvJloH+YzRmpZVQe87+qASmBUKZDWgx9cu+KDrX2ZDH/3tMy+gXbZETVGs2M8YdxObOh7XAtim9Y0g== +object-inspect@^1.13.1: + version "1.13.2" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.2.tgz#dea0088467fb991e67af4058147a24824a3043ff" + integrity sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g== + object-inspect@^1.9.0: version "1.10.3" resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.10.3.tgz#c2aa7d2d09f50c99375704f7a0adf24c5782d369" @@ -10150,15 +10232,15 @@ path-posix@^1.0.0: resolved "https://registry.yarnpkg.com/path-posix/-/path-posix-1.0.0.tgz#06b26113f56beab042545a23bfa88003ccac260f" integrity sha1-BrJhE/Vr6rBCVFojv6iAA8ysJg8= -path-to-regexp@0.1.7: - version "0.1.7" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.7.tgz#df604178005f522f15eb4490e7247a1bfaa67f8c" - integrity sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= +path-to-regexp@0.1.10: + version "0.1.10" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-0.1.10.tgz#67e9108c5c0551b9e5326064387de4763c4d5f8b" + integrity sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w== path-to-regexp@^1.7.0: - version "1.8.0" - resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.8.0.tgz#887b3ba9d84393e87a0a0b9f4cb756198b53548a" - integrity sha512-n43JRhlUKUAlibEJhPeir1ncUID16QnEjNpwzNdO3Lm4ywrBpBZ5oLD0I6br9evr1Y9JTqwRtAh7JLoOzAQdVA== + version "1.9.0" + resolved "https://registry.yarnpkg.com/path-to-regexp/-/path-to-regexp-1.9.0.tgz#5dc0753acbf8521ca2e0f137b4578b917b10cf24" + integrity sha512-xIp7/apCFJuUHdDLWe8O1HIkb0kQrOMb/0u6FXQjemHn/ii5LrIzU6bdECnsiTF/GjZkMEKg1xdiZwNqDYlZ6g== dependencies: isarray "0.0.1" @@ -10779,12 +10861,12 @@ q@^1.1.2: resolved "https://registry.yarnpkg.com/q/-/q-1.5.1.tgz#7e32f75b41381291d04611f1bf14109ac00651d7" integrity sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= -qs@6.10.3: - version "6.10.3" - resolved "https://registry.yarnpkg.com/qs/-/qs-6.10.3.tgz#d6cde1b2ffca87b5aa57889816c5f81535e22e8e" - integrity sha512-wr7M2E0OFRfIfJZjKGieI8lBKb7fRCH4Fv5KNPEs7gJ8jadvotdsS08PzOKR7opXhZ/Xkjtt3WF9g38drmyRqQ== +qs@6.13.0: + version "6.13.0" + resolved "https://registry.yarnpkg.com/qs/-/qs-6.13.0.tgz#6ca3bd58439f7e245655798997787b0d88a51906" + integrity sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg== dependencies: - side-channel "^1.0.4" + side-channel "^1.0.6" qs@^6.4.0: version "6.10.1" @@ -10847,10 +10929,10 @@ range-parser@^1.2.1, range-parser@~1.2.1: resolved "https://registry.yarnpkg.com/range-parser/-/range-parser-1.2.1.tgz#3cf37023d199e1c24d1a55b84800c2f3e6468031" integrity sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg== -raw-body@2.5.1: - version "2.5.1" - resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.1.tgz#fe1b1628b181b700215e5fd42389f98b71392857" - integrity sha512-qqJBtEyVgS0ZmPGdCFPWJ3FreoqvG4MVQln/kCgF7Olq95IbOp0/BWyMwbdtn4VTvkM8Y7khCQ2Xgk/tcrCXig== +raw-body@2.5.2: + version "2.5.2" + resolved "https://registry.yarnpkg.com/raw-body/-/raw-body-2.5.2.tgz#99febd83b90e08975087e8f1f9419a149366b68a" + integrity sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA== dependencies: bytes "3.1.2" http-errors "2.0.0" @@ -11591,10 +11673,10 @@ semver@^7.3.2, semver@^7.3.7: dependencies: lru-cache "^6.0.0" -send@0.18.0: - version "0.18.0" - resolved "https://registry.yarnpkg.com/send/-/send-0.18.0.tgz#670167cc654b05f5aa4a767f9113bb371bc706be" - integrity sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg== +send@0.19.0: + version "0.19.0" + resolved "https://registry.yarnpkg.com/send/-/send-0.19.0.tgz#bbc5a388c8ea6c048967049dbeac0e4a3f09d7f8" + integrity sha512-dW41u5VfLXu8SJh5bwRmyYUbAoSB3c9uQh6L8h/KtsFREPWpbX1lrljJo186Jc4nmci/sGUZ9a0a0J2zgfq2hw== dependencies: debug "2.6.9" depd "2.0.0" @@ -11637,21 +11719,33 @@ serve-index@^1.9.1: mime-types "~2.1.17" parseurl "~1.3.2" -serve-static@1.15.0: - version "1.15.0" - resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.15.0.tgz#faaef08cffe0a1a62f60cad0c4e513cff0ac9540" - integrity sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g== +serve-static@1.16.2: + version "1.16.2" + resolved "https://registry.yarnpkg.com/serve-static/-/serve-static-1.16.2.tgz#b6a5343da47f6bdd2673848bf45754941e803296" + integrity sha512-VqpjJZKadQB/PEbEwvFdO43Ax5dFBZ2UECszz8bQ7pi7wt//PWe1P6MN7eCnjsatYtBT6EuiClbjSWP2WrIoTw== dependencies: - encodeurl "~1.0.2" + encodeurl "~2.0.0" escape-html "~1.0.3" parseurl "~1.3.3" - send "0.18.0" + send "0.19.0" set-blocking@^2.0.0: version "2.0.0" resolved "https://registry.yarnpkg.com/set-blocking/-/set-blocking-2.0.0.tgz#045f9782d011ae9a6803ddd382b24392b3d890f7" integrity sha1-BF+XgtARrppoA93TgrJDkrPYkPc= +set-function-length@^1.2.1: + version "1.2.2" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.2.2.tgz#aac72314198eaed975cf77b2c3b6b880695e5449" + integrity sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg== + 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" + setprototypeof@1.1.0: version "1.1.0" resolved "https://registry.yarnpkg.com/setprototypeof/-/setprototypeof-1.1.0.tgz#d0bd85536887b6fe7c0d818cb962d9d91c54e656" @@ -11695,6 +11789,16 @@ side-channel@^1.0.4: get-intrinsic "^1.0.2" object-inspect "^1.9.0" +side-channel@^1.0.6: + version "1.0.6" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.6.tgz#abd25fb7cd24baf45466406b1096b7831c9215f2" + integrity sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA== + dependencies: + call-bind "^1.0.7" + es-errors "^1.3.0" + get-intrinsic "^1.2.4" + object-inspect "^1.13.1" + signal-exit@^3.0.2, signal-exit@^3.0.3: version "3.0.3" resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-3.0.3.tgz#a1410c2edd8f077b08b4e253c8eacfcaf057461c" From 5474f0c2d28920778ab4d38e8c81377f876eca70 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alfonso=20Mart=C3=ADnez?= Date: Thu, 26 Sep 2024 14:23:37 +0200 Subject: [PATCH 07/22] Fix flaky E2E test --- cypress/views/storage-pool.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/cypress/views/storage-pool.ts b/cypress/views/storage-pool.ts index cd4badd24..0e0d5bf3b 100644 --- a/cypress/views/storage-pool.ts +++ b/cypress/views/storage-pool.ts @@ -178,7 +178,7 @@ export const deleteStoragePool = (poolName: string) => { navigateToStoragePoolList(); openStoragePoolKebab(poolName); cy.byTestActionID('Delete Pool').click(); - cy.contains('Delete Storage Pool'); + cy.contains('Delete Storage Pool', { timeout: 5 * 1000 }); triggerPoolFormFooterAction('delete'); cy.log('Verify that the pool is not found.'); From 896224d2f3e77089fc444ed93d5a53bbe8b5390e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alfonso=20Mart=C3=ADnez?= Date: Fri, 27 Sep 2024 09:10:29 +0200 Subject: [PATCH 08/22] Sanity checks: ensure client plugin build is healthy --- .github/workflows/frontend-build.yml | 2 ++ package.json | 1 + 2 files changed, 3 insertions(+) diff --git a/.github/workflows/frontend-build.yml b/.github/workflows/frontend-build.yml index 14a556faf..ff1928a57 100644 --- a/.github/workflows/frontend-build.yml +++ b/.github/workflows/frontend-build.yml @@ -21,6 +21,7 @@ jobs: - run: yarn install --prod --frozen-lockfile - run: yarn build - run: yarn build-mco + - run: yarn build-client - run: yarn install # Install dev. deps. - run: yarn lint - run: yarn format-test @@ -28,3 +29,4 @@ jobs: - run: yarn test-coverage - run: yarn analyze-odf - run: yarn analyze-mco + - run: yarn analyze-client diff --git a/package.json b/package.json index f67e5cc94..79149b0bf 100644 --- a/package.json +++ b/package.json @@ -31,6 +31,7 @@ "analyze-common": "yarn build:generate && NODE_ENV=production I8N_NS=${I8N_NS} ANALYZE_BUNDLE=true yarn ts-node ./node_modules/.bin/webpack -c ./webpack.config.ts", "analyze-odf": "PLUGIN=odf yarn analyze-common && PLUGIN=odf yarn ts-node ./analyzeTest.ts", "analyze-mco": "PLUGIN=mco yarn analyze-common && PLUGIN=mco yarn ts-node ./analyzeTest.ts", + "analyze-client": "PLUGIN=client yarn analyze-common && PLUGIN=client yarn ts-node ./analyzeTest.ts", "dev": "PLUGIN=odf I8N_NS=plugin__odf-console yarn server:plugin", "dev:no-type-check": "DEV_NO_TYPE_CHECK=true yarn dev", "dev-mco": "PLUGIN=mco I8N_NS=plugin__odf-multicluster-console yarn server:plugin", From baab291877b41a40b23860aa60e518712a7737c9 Mon Sep 17 00:00:00 2001 From: SanjalKatiyar Date: Fri, 20 Sep 2024 15:28:35 +0530 Subject: [PATCH 09/22] Add buckets overview page (header, details/objects list tabs, actions) layout --- locales/en/plugin__odf-console.json | 28 +- package.json | 1 + .../bucket-overview/BucketOverview.tsx | 203 +++++++++++ .../s3-browser/bucket-overview/PageTitle.tsx | 120 +++++++ .../bucket-overview/bucket-overview.scss | 7 + .../s3-browser/objects-list/ObjectsList.tsx | 327 ++++++++++++++++++ .../s3-browser/objects-list/index.ts | 1 + .../objects-list/table-components.tsx | 149 ++++++++ packages/odf/constants/s3-browser.ts | 10 + packages/odf/types/index.ts | 1 + packages/odf/types/s3-browser.ts | 10 + packages/odf/utils/index.ts | 1 + packages/odf/utils/s3-browser.ts | 85 +++++ packages/shared/src/hooks/index.ts | 1 + packages/shared/src/hooks/useRefresh.ts | 33 ++ packages/shared/src/s3/commands.ts | 8 +- packages/shared/src/s3/types.ts | 10 +- .../shared/src/table/selectable-table.tsx | 18 +- plugins/odf/console-extensions.json | 10 + plugins/odf/console-plugin.json | 3 +- yarn.lock | 18 + 21 files changed, 1026 insertions(+), 18 deletions(-) create mode 100644 packages/odf/components/s3-browser/bucket-overview/BucketOverview.tsx create mode 100644 packages/odf/components/s3-browser/bucket-overview/PageTitle.tsx create mode 100644 packages/odf/components/s3-browser/bucket-overview/bucket-overview.scss create mode 100644 packages/odf/components/s3-browser/objects-list/ObjectsList.tsx create mode 100644 packages/odf/components/s3-browser/objects-list/index.ts create mode 100644 packages/odf/components/s3-browser/objects-list/table-components.tsx create mode 100644 packages/odf/types/s3-browser.ts create mode 100644 packages/odf/utils/s3-browser.ts create mode 100644 packages/shared/src/hooks/useRefresh.ts diff --git a/locales/en/plugin__odf-console.json b/locales/en/plugin__odf-console.json index d14748138..01a5a03c2 100644 --- a/locales/en/plugin__odf-console.json +++ b/locales/en/plugin__odf-console.json @@ -1097,6 +1097,19 @@ "NamespaceStore details": "NamespaceStore details", "Target Blob Container": "Target Blob Container", "Num Volumes": "Num Volumes", + "Empty bucket": "Empty bucket", + "Delete bucket": "Delete bucket", + "Edit labels": "Edit labels", + "Edit annotations": "Edit annotations", + "Edit bucket": "Edit bucket", + "Objects": "Objects", + "Refresh": "Refresh", + "Created on: ": "Created on: ", + "Created via OBC": "Created via OBC", + "Created via S3": "Created via S3", + "MCG": "MCG", + "Object path: ": "Object path: ", + "Copy to share": "Copy to share", "Create Bucket": "Create Bucket", "An object bucket is a cloud storage container that organizes and manages files (objects), allowing users to store, retrieve and control access to data efficiently.": "An object bucket is a cloud storage container that organizes and manages files (objects), allowing users to store, retrieve and control access to data efficiently.", "Select bucket creation method": "Select bucket creation method", @@ -1105,6 +1118,18 @@ "Create via Object Bucket Claim": "Create via Object Bucket Claim", "Ideal for Kubernetes environments providing a more abstracted approach to managing storage resources and leveraging dynamic provisioning.": "Ideal for Kubernetes environments providing a more abstracted approach to managing storage resources and leveraging dynamic provisioning.", "OBC references a StorageClass that uses a provisioner to interact with the S3 API and create the bucket. Kubernetes binds the OBC to the bucket, making it accessible to applications.": "OBC references a StorageClass that uses a provisioner to interact with the S3 API and create the bucket. Kubernetes binds the OBC to the bucket, making it accessible to applications.", + "Download objects": "Download objects", + "Delete objects": "Delete objects", + "Actions": "Actions", + "Create folder": "Create folder", + "Size": "Size", + "Last modified": "Last modified", + "Download": "Download", + "Copy Object URL": "Copy Object URL", + "Preview": "Preview", + "Share with presigned URL": "Share with presigned URL", + "No objects found": "No objects found", + "You do not have any objects in the bucket": "You do not have any objects in the bucket", "<0>The amount of storage allocated to the client cluster for usage.<1>Due to simultaneous usage by multiple client clusters, actual available storage may vary affecting your allocated storage quota.": "<0>The amount of storage allocated to the client cluster for usage.<1>Due to simultaneous usage by multiple client clusters, actual available storage may vary affecting your allocated storage quota.", "No storage clients found.": "No storage clients found.", "You do not have any storage clients connected to this Data Foundation provider cluster.": "You do not have any storage clients connected to this Data Foundation provider cluster.", @@ -1345,12 +1370,9 @@ "{{labels}} content is not available in the catalog at this time due to loading failures.": "{{labels}} content is not available in the catalog at this time due to loading failures.", "Timed out fetching new data. The data below is stale.": "Timed out fetching new data. The data below is stale.", "Getting started resources": "Getting started resources", - "Edit labels": "Edit labels", - "Edit annotations": "Edit annotations", "Edit {{resourceLabel}}": "Edit {{resourceLabel}}", "Delete {{resourceLabel}}": "Delete {{resourceLabel}}", "You do not have permission to perform this action": "You do not have permission to perform this action", - "Actions": "Actions", "Expand to fix validation errors": "Expand to fix validation errors", "unknown": "unknown", "equals any of": "equals any of", diff --git a/package.json b/package.json index 79149b0bf..efa42af5b 100644 --- a/package.json +++ b/package.json @@ -112,6 +112,7 @@ "sass-loader": "^13.0.2", "semver": "6.x", "style-loader": "^0.23.1", + "swr": "2.2.5", "thread-loader": "3.0.4", "ts-loader": "^9.4.1", "ts-node": "5.0.1", diff --git a/packages/odf/components/s3-browser/bucket-overview/BucketOverview.tsx b/packages/odf/components/s3-browser/bucket-overview/BucketOverview.tsx new file mode 100644 index 000000000..4d5f50389 --- /dev/null +++ b/packages/odf/components/s3-browser/bucket-overview/BucketOverview.tsx @@ -0,0 +1,203 @@ +import * as React from 'react'; +import { LoadingBox } from '@odf/shared/generic/status-box'; +import PageHeading from '@odf/shared/heading/page-heading'; +import { useRefresh } from '@odf/shared/hooks'; +import { ModalKeys, defaultModalMap } from '@odf/shared/modals/types'; +import { BlueSyncIcon } from '@odf/shared/status'; +import { K8sResourceKind } from '@odf/shared/types'; +import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; +import { + referenceForModel, + getValidWatchK8sResourceObj, +} from '@odf/shared/utils'; +import { YAMLEditorWrapped } from '@odf/shared/utils/Tabs'; +import { + useK8sWatchResource, + HorizontalNav, + useModal, +} from '@openshift-console/dynamic-plugin-sdk'; +import { LaunchModal } from '@openshift-console/dynamic-plugin-sdk/lib/app/modal-support/ModalProvider'; +import { TFunction } from 'i18next'; +import { useNavigate, NavigateFunction } from 'react-router-dom-v5-compat'; +import { useParams, useSearchParams } from 'react-router-dom-v5-compat'; +import { Button, ButtonVariant } from '@patternfly/react-core'; +import { ActionsColumn, IAction } from '@patternfly/react-table'; +import { PREFIX, BUCKETS_BASE_ROUTE } from '../../../constants'; +import { NooBaaObjectBucketModel } from '../../../models'; +import { getBreadcrumbs } from '../../../utils'; +import { NoobaaS3Provider } from '../noobaa-context'; +import { CustomActionsToggle, ObjectsList } from '../objects-list'; +import { PageTitle } from './PageTitle'; + +const getBucketActionsItems = ( + t: TFunction, + launcher: LaunchModal, + navigate: NavigateFunction, + bucketName: string, + isCreatedByOBC: boolean, + noobaaObjectBucket: K8sResourceKind +): IAction[] => [ + // ToDo: add empty/delete bucket actions + { + title: t('Empty bucket'), + onClick: () => undefined, + }, + { + title: t('Delete bucket'), + onClick: () => undefined, + }, + ...(isCreatedByOBC + ? [ + { + title: t('Edit labels'), + onClick: () => + launcher(defaultModalMap[ModalKeys.EDIT_LABELS], { + extraProps: { + resource: noobaaObjectBucket, + resourceModel: NooBaaObjectBucketModel, + }, + isOpen: true, + }), + }, + { + title: t('Edit annotations'), + onClick: () => + launcher(defaultModalMap[ModalKeys.EDIT_ANN], { + extraProps: { + resource: noobaaObjectBucket, + resourceModel: NooBaaObjectBucketModel, + }, + isOpen: true, + }), + }, + { + title: t('Edit bucket'), + onClick: () => navigate(`${BUCKETS_BASE_ROUTE}/${bucketName}/yaml`), + }, + ] + : []), +]; + +const BucketOverview: React.FC<{}> = () => { + const { t } = useCustomTranslation(); + const [fresh, triggerRefresh] = useRefresh(); + + const launcher = useModal(); + const navigate = useNavigate(); + + const { bucketName } = useParams(); + const [searchParams] = useSearchParams(); + + // if non-empty means we are inside particular folder(s) of a bucket, else just inside a bucket (top-level) + const foldersPath = searchParams.get(PREFIX); + + const [objectBuckets, objectBucketsLoaded, objectBucketsError] = + useK8sWatchResource( + getValidWatchK8sResourceObj( + { + kind: referenceForModel(NooBaaObjectBucketModel), + namespaced: false, + isList: true, + }, + !foldersPath + ) + ); + const noobaaObjectBucket: K8sResourceKind = objectBuckets?.find( + (ob) => ob.spec?.endpoint?.bucketName === bucketName + ); + // denotes whether bucket is created via OBC or S3 endpoint (will be false if we are inside folder view) + const isCreatedByOBC = !!noobaaObjectBucket; + + const { breadcrumbs, currentFolder } = React.useMemo( + () => getBreadcrumbs(foldersPath, bucketName, t), + [foldersPath, bucketName, t] + ); + + const navPages = [ + { + href: '', + name: t('Objects'), + component: ObjectsList, + }, + ...(!foldersPath + ? [ + { + href: 'details', + name: t('Details'), + // ToDo: add bucket details page + component: () => <>Bucket details page, + }, + ] + : []), + ...(isCreatedByOBC + ? [ + { + href: 'yaml', + name: t('YAML'), + component: YAMLEditorWrapped, + }, + ] + : []), + ]; + + const actions = () => { + return ( + <> + + {!foldersPath && ( + + )} + + ); + }; + + return ( + + + } + actions={actions} + className="pf-v5-u-mt-md" + /> + {fresh ? ( + + ) : ( + + )} + + ); +}; + +export default BucketOverview; diff --git a/packages/odf/components/s3-browser/bucket-overview/PageTitle.tsx b/packages/odf/components/s3-browser/bucket-overview/PageTitle.tsx new file mode 100644 index 000000000..e06db22d7 --- /dev/null +++ b/packages/odf/components/s3-browser/bucket-overview/PageTitle.tsx @@ -0,0 +1,120 @@ +import * as React from 'react'; +import { resourceStatus as getResourceStatus } from '@odf/shared/status/Resource'; +import { K8sResourceKind } from '@odf/shared/types'; +import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; +import { ResourceStatus } from '@openshift-console/dynamic-plugin-sdk'; +import Status from '@openshift-console/dynamic-plugin-sdk/lib/app/components/status/Status'; +import useSWR from 'swr'; +import { Skeleton, Label, Button, ButtonVariant } from '@patternfly/react-core'; +import { CopyIcon } from '@patternfly/react-icons'; +import { LIST_BUCKET } from '../../../constants'; +import { getPath } from '../../../utils'; +import { NoobaaS3Context } from '../noobaa-context'; +import './bucket-overview.scss'; + +type TitleProps = { + bucketName: string; + foldersPath: string; + currentFolder: string; + fresh: boolean; + isCreatedByOBC: boolean; + noobaaObjectBucket: K8sResourceKind; +}; + +const CreatedOnSkeleton: React.FC<{}> = () => ( + +); + +const CreatedOn: React.FC<{ bucketName: string }> = ({ bucketName }) => { + const { t } = useCustomTranslation(); + + const { noobaaS3 } = React.useContext(NoobaaS3Context); + const { data, error, isLoading } = useSWR(LIST_BUCKET, () => + noobaaS3.listBuckets() + ); + + const bucketCreatedOn = + !isLoading && !error + ? data?.Buckets?.find((bucket) => bucket?.Name === bucketName) + ?.CreationDate + : null; + + return isLoading ? ( + + ) : ( +

+ {t('Created on: ') + bucketCreatedOn?.toString()} +

+ ); +}; + +const BucketResourceStatus: React.FC<{ resourceStatus: string }> = ({ + resourceStatus, +}) => ( + + + +); + +export const PageTitle: React.FC = ({ + bucketName, + foldersPath, + currentFolder, + fresh, + isCreatedByOBC, + noobaaObjectBucket, +}) => { + const { t } = useCustomTranslation(); + + // ToDo: add object name to the path as well (when any object is clicked from the list) + const objectPath = getPath(bucketName, foldersPath); + const resourceStatus = isCreatedByOBC + ? getResourceStatus(noobaaObjectBucket) + : null; + const createdBy = isCreatedByOBC ? t('Created via OBC') : t('Created via S3'); + + return ( +
+
+ {!foldersPath ? bucketName : currentFolder} + {!foldersPath && ( + <> + {/* ToDo: Currently we only support MCG, make is configurable once RGW is supported as well */} + + + {resourceStatus && ( + + )} + + )} +
+ {!foldersPath && + (fresh ? : )} +

+ {t('Object path: ')} + {objectPath} + +

+
+ ); +}; diff --git a/packages/odf/components/s3-browser/bucket-overview/bucket-overview.scss b/packages/odf/components/s3-browser/bucket-overview/bucket-overview.scss new file mode 100644 index 000000000..485c1609d --- /dev/null +++ b/packages/odf/components/s3-browser/bucket-overview/bucket-overview.scss @@ -0,0 +1,7 @@ +.bucket-label--height { + height: 1rem; +} + +.bucket-label--margin-top { + margin-top: calc(0.3rem * -1); +} diff --git a/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx b/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx new file mode 100644 index 000000000..8d17fbe3d --- /dev/null +++ b/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx @@ -0,0 +1,327 @@ +import * as React from 'react'; +import { + ListObjectsV2CommandOutput, + _Object as Content, + CommonPrefix, +} from '@aws-sdk/client-s3'; +import { SelectableTable } from '@odf/shared/table'; +import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; +import { useModal } from '@openshift-console/dynamic-plugin-sdk'; +import { LaunchModal } from '@openshift-console/dynamic-plugin-sdk/lib/app/modal-support/ModalProvider'; +import { TFunction } from 'i18next'; +import * as _ from 'lodash-es'; +import { useParams, useSearchParams } from 'react-router-dom-v5-compat'; +import useSWRMutation, { TriggerWithOptionsArgs } from 'swr/mutation'; +import { + Button, + ButtonVariant, + Level, + LevelItem, + MenuToggle, +} from '@patternfly/react-core'; +import { AngleLeftIcon, AngleRightIcon } from '@patternfly/react-icons'; +import { + ActionsColumn, + IAction, + CustomActionsToggleProps, +} from '@patternfly/react-table'; +import { LIST_OBJECTS, DELIMITER, MAX_KEYS, PREFIX } from '../../../constants'; +import { ObjectCrFormat } from '../../../types'; +import { getPath, convertObjectsDataToCrFormat } from '../../../utils'; +import { NoobaaS3Context } from '../noobaa-context'; +import { + isRowSelectable, + getColumns, + TableRow, + EmptyPage, +} from './table-components'; + +type PaginationProps = { + onNext: () => void; + onPrevious: () => void; + disableNext: boolean; + disablePrevious: boolean; +}; + +type TableActionsProps = { + launcher: LaunchModal; + selectedRows: unknown[]; + loadedWOError: boolean; +}; + +type ContinuationTokens = { + previous: string[]; + current: string; + next: string; +}; + +type Trigger = TriggerWithOptionsArgs< + ListObjectsV2CommandOutput, + any, + string, + string +>; + +const continuationTokensSetter = ( + setContinuationTokens: React.Dispatch< + React.SetStateAction + >, + response: ListObjectsV2CommandOutput, + isNext: boolean, + setSelectedRows: React.Dispatch> +) => { + setContinuationTokens((oldTokens) => { + const newTokens = _.cloneDeep(oldTokens); + if (isNext) { + newTokens.previous.push(newTokens.current); + newTokens.current = newTokens.next; + } else { + newTokens.current = newTokens.previous.pop(); + } + newTokens.next = response.NextContinuationToken; + + return newTokens; + }); + setSelectedRows([]); +}; + +const fetchObjects = async ( + setContinuationTokens: React.Dispatch< + React.SetStateAction + >, + trigger: Trigger, + isNext: boolean, + setSelectedRows: React.Dispatch>, + paginationToken = '' +) => { + try { + const response: ListObjectsV2CommandOutput = await trigger(paginationToken); + continuationTokensSetter( + setContinuationTokens, + response, + isNext, + setSelectedRows + ); + } catch (err) { + // no need to handle any error here, use "error" object directly from the "useSWRMutation" hook + // eslint-disable-next-line no-console + console.error(err); + } +}; + +const getBulkActionsItems = ( + t: TFunction, + _launcher: LaunchModal, + _selectedRows: unknown[] +): IAction[] => [ + // ToDo: add bulk download & delete options + { + title: t('Download objects'), + onClick: () => undefined, + }, + { + title: t('Delete objects'), + onClick: () => undefined, + }, +]; + +export const CustomActionsToggle = (props: CustomActionsToggleProps) => { + const { t } = useCustomTranslation(); + + return ( + + {t('Actions')} + + ); +}; + +const Pagination: React.FC = ({ + onNext, + onPrevious, + disableNext, + disablePrevious, +}) => { + return ( +
+ + +
+ ); +}; + +const TableActions: React.FC = ({ + onNext, + onPrevious, + loadedWOError, + disableNext, + disablePrevious, + launcher, + selectedRows, +}) => { + const { t } = useCustomTranslation(); + + const anySelection = !!selectedRows.length; + + return ( + + +
+ {/* ToDo: add create folder option */} + + +
+
+ + + +
+ ); +}; + +export const ObjectsList: React.FC<{}> = () => { + const { t } = useCustomTranslation(); + + const { bucketName } = useParams(); + const [searchParams] = useSearchParams(); + + const launcher = useModal(); + + // if non-empty means we are inside particular folder(s) of a bucket, else just inside a bucket (top-level) + const foldersPath = searchParams.get(PREFIX); + + const { noobaaS3 } = React.useContext(NoobaaS3Context); + const cacheKey = LIST_OBJECTS + DELIMITER + getPath(bucketName, foldersPath); + const { data, error, isMutating, trigger } = useSWRMutation( + cacheKey, + (_url, { arg }: { arg: string }) => + noobaaS3.listObjects({ + Bucket: bucketName, + MaxKeys: MAX_KEYS, + Delimiter: DELIMITER, + ...(!!foldersPath && { Prefix: foldersPath }), + ...(!!arg && { ContinuationToken: arg }), + }) + ); + + const loadedWOError = !isMutating && !error; + + const [continuationTokens, setContinuationTokens] = + React.useState({ + previous: [], + current: '', + next: '', + }); + const [selectedRows, setSelectedRows] = React.useState([]); + + const structuredObjects: ObjectCrFormat[] = React.useMemo(() => { + const objects: ObjectCrFormat[] = []; + if ( + loadedWOError && + (!!data?.Contents?.length || !!data?.CommonPrefixes?.length) + ) { + data?.CommonPrefixes?.forEach((commonPrefix: CommonPrefix) => { + objects.push(convertObjectsDataToCrFormat(commonPrefix, true, t)); + }); + data?.Contents?.forEach((content: Content) => { + objects.push(convertObjectsDataToCrFormat(content, false, t)); + }); + } + + return objects; + }, [data, loadedWOError, t]); + + // initial fetch on first mount or on route update (drilling in/out of the folder view) + React.useEffect(() => { + fetchObjects(setContinuationTokens, trigger, true, setSelectedRows); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [foldersPath]); + + return ( +
+ {/* ToDo: add upload objects option */} + + { + if (!!continuationTokens.next && loadedWOError) + fetchObjects( + setContinuationTokens, + trigger, + true, + setSelectedRows, + continuationTokens.next + ); + }} + onPrevious={async () => { + if (!!continuationTokens.current && loadedWOError) { + const paginationToken = + continuationTokens.previous[ + continuationTokens.previous.length - 1 + ]; + fetchObjects( + setContinuationTokens, + trigger, + false, + setSelectedRows, + paginationToken + ); + } + }} + selectedRows={selectedRows} + loadedWOError={loadedWOError} + disableNext={!continuationTokens.next || !loadedWOError} + disablePrevious={!continuationTokens.current || !loadedWOError} + launcher={launcher} + /> + + +
+ ); +}; diff --git a/packages/odf/components/s3-browser/objects-list/index.ts b/packages/odf/components/s3-browser/objects-list/index.ts new file mode 100644 index 000000000..f173f45bc --- /dev/null +++ b/packages/odf/components/s3-browser/objects-list/index.ts @@ -0,0 +1 @@ +export * from './ObjectsList'; diff --git a/packages/odf/components/s3-browser/objects-list/table-components.tsx b/packages/odf/components/s3-browser/objects-list/table-components.tsx new file mode 100644 index 000000000..0f4b42c79 --- /dev/null +++ b/packages/odf/components/s3-browser/objects-list/table-components.tsx @@ -0,0 +1,149 @@ +import * as React from 'react'; +import { getName } from '@odf/shared/selectors'; +import { RowComponentType } from '@odf/shared/table'; +import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; +import { sortRows } from '@odf/shared/utils'; +import { LaunchModal } from '@openshift-console/dynamic-plugin-sdk/lib/app/modal-support/ModalProvider'; +import { TFunction } from 'i18next'; +import { Link } from 'react-router-dom-v5-compat'; +import { + EmptyState, + EmptyStateVariant, + EmptyStateIcon, + EmptyStateBody, + EmptyStateHeader, + EmptyStateFooter, +} from '@patternfly/react-core'; +import { CubesIcon } from '@patternfly/react-icons'; +import { ActionsColumn, Td, IAction } from '@patternfly/react-table'; +import { BUCKETS_BASE_ROUTE, PREFIX } from '../../../constants'; +import { ObjectCrFormat } from '../../../types'; + +const getColumnNames = (t: TFunction): string[] => [ + t('Name'), + t('Size'), + t('Type'), + t('Last modified'), + '', +]; + +const getInlineActionsItems = ( + t: TFunction, + _launcher: LaunchModal, + _object: ObjectCrFormat +): IAction[] => [ + // ToDo: add inline download, copy, preview, share & delete options + { + title: t('Download'), + onClick: () => undefined, + }, + { + title: t('Copy Object URL'), + onClick: () => undefined, + }, + { + title: t('Preview'), + onClick: () => undefined, + }, + { + title: t('Share with presigned URL'), + onClick: () => undefined, + }, + { + title: t('Delete'), + onClick: () => undefined, + }, +]; + +export const isRowSelectable = (row: ObjectCrFormat) => !row.isFolder; + +export const getColumns = (t: TFunction) => { + const columnNames = getColumnNames(t); + + return [ + { + columnName: columnNames[0], + sortFunction: (a, b, c) => sortRows(a, b, c, 'metadata.name'), + }, + { + columnName: columnNames[1], + sortFunction: (a, b, c) => sortRows(a, b, c, 'apiResponse.size'), + }, + { + columnName: columnNames[2], + sortFunction: (a, b, c) => sortRows(a, b, c, 'type'), + }, + { + columnName: columnNames[3], + sortFunction: (a, b, c) => sortRows(a, b, c, 'apiResponse.lastModified'), + }, + { columnName: columnNames[4] }, + ]; +}; + +export const TableRow: React.FC> = ({ + row: object, + extraProps, +}) => { + const { t } = useCustomTranslation(); + + const { launcher, bucketName, foldersPath } = extraProps; + const isFolder = object.isFolder; + const name = getName(object).replace(foldersPath, ''); + const prefix = !!foldersPath + ? encodeURIComponent(foldersPath + name) + : encodeURIComponent(name); + + const columnNames = getColumnNames(t); + + return ( + <> + + {isFolder ? ( + + {name} + + ) : ( + name + )} + + + {object.apiResponse.size} + + + {object.type} + + + {object.apiResponse.lastModified} + + + {isFolder ? null : ( + + )} + + + ); +}; + +export const EmptyPage: React.FC<{}> = () => { + const { t } = useCustomTranslation(); + + return ( + + } + headingLevel="h4" + /> + + {t('You do not have any objects in the bucket')} + + + {/* ToDo: add upload objects option */} + + + ); +}; diff --git a/packages/odf/constants/s3-browser.ts b/packages/odf/constants/s3-browser.ts index 08818f723..bc5e354fe 100644 --- a/packages/odf/constants/s3-browser.ts +++ b/packages/odf/constants/s3-browser.ts @@ -2,3 +2,13 @@ export const NOOBAA_ADMIN_SECRET = 'noobaa-admin'; export const NOOBAA_S3_ROUTE = 's3'; export const NOOBAA_ACCESS_KEY_ID = 'AWS_ACCESS_KEY_ID'; export const NOOBAA_SECRET_ACCESS_KEY = 'AWS_SECRET_ACCESS_KEY'; + +export const DELIMITER = '/'; +export const PREFIX = 'prefix'; +export const MAX_KEYS = 300; + +export const BUCKETS_BASE_ROUTE = '/odf/object-storage/buckets'; + +// key to be used by SWR for caching particular API call +export const LIST_BUCKET = 'LIST_BUCKET_CACHE_KEY'; +export const LIST_OBJECTS = 'LIST_OBJECTS_CACHE_KEY'; diff --git a/packages/odf/types/index.ts b/packages/odf/types/index.ts index 35864089c..6faa1dee6 100644 --- a/packages/odf/types/index.ts +++ b/packages/odf/types/index.ts @@ -5,3 +5,4 @@ export * from './lso'; export * from './network'; export * from './mcg'; export * from './storage-consumer'; +export * from './s3-browser'; diff --git a/packages/odf/types/s3-browser.ts b/packages/odf/types/s3-browser.ts new file mode 100644 index 000000000..b0c54b83f --- /dev/null +++ b/packages/odf/types/s3-browser.ts @@ -0,0 +1,10 @@ +import { K8sResourceCommon } from '@openshift-console/dynamic-plugin-sdk'; + +export type ObjectCrFormat = K8sResourceCommon & { + apiResponse?: { + size?: string; + lastModified?: string; + }; + isFolder?: boolean; + type?: string; +}; diff --git a/packages/odf/utils/index.ts b/packages/odf/utils/index.ts index 00cf38262..0887b4c09 100644 --- a/packages/odf/utils/index.ts +++ b/packages/odf/utils/index.ts @@ -4,3 +4,4 @@ export * from './ocs'; export * from './storage'; export * from './mcg'; export * from './horizontal-nav-tab'; +export * from './s3-browser'; diff --git a/packages/odf/utils/s3-browser.ts b/packages/odf/utils/s3-browser.ts new file mode 100644 index 000000000..a30bbe731 --- /dev/null +++ b/packages/odf/utils/s3-browser.ts @@ -0,0 +1,85 @@ +import { _Object as Content, CommonPrefix } from '@aws-sdk/client-s3'; +import { DASH } from '@odf/shared/constants'; +import { humanizeBinaryBytes } from '@odf/shared/utils'; +import { TFunction } from 'i18next'; +import { DELIMITER, BUCKETS_BASE_ROUTE, PREFIX } from '../constants'; +import { ObjectCrFormat } from '../types'; + +export const getBreadcrumbs = ( + foldersPath: string, + bucketName: string, + t: TFunction +) => { + const folders = foldersPath?.split(DELIMITER)?.filter(Boolean); + const foldersCount = folders?.length || 0; + const bucketsListPage = [{ name: t('Buckets'), path: BUCKETS_BASE_ROUTE }]; + + let currentFolder = ''; + + if (!foldersCount) + return { + breadcrumbs: [...bucketsListPage, { name: bucketName, path: '' }], + currentFolder, + }; + + currentFolder = folders[foldersCount - 1] + DELIMITER; + + const initialBreadcrumb = [ + ...bucketsListPage, + { name: bucketName, path: `${BUCKETS_BASE_ROUTE}/${bucketName}` }, + ]; + let encodedPathToFolder = ''; + return { + breadcrumbs: folders.reduce((acc, folderName) => { + const folderNameWDelimiter = folderName + DELIMITER; + encodedPathToFolder = !encodedPathToFolder + ? encodeURIComponent(folderNameWDelimiter) + : encodedPathToFolder + encodeURIComponent(folderNameWDelimiter); + acc.push({ + name: folderNameWDelimiter, + path: `${BUCKETS_BASE_ROUTE}/${bucketName}?${PREFIX}=${encodedPathToFolder}`, + }); + return acc; + }, initialBreadcrumb), + currentFolder, + }; +}; + +export const getPath = (bucketName: string, foldersPath: string) => + !foldersPath ? bucketName + DELIMITER : bucketName + DELIMITER + foldersPath; + +export const convertObjectsDataToCrFormat = ( + objectData: Content | CommonPrefix, + isFolder: boolean, + t: TFunction +): ObjectCrFormat => { + const structuredObjects: ObjectCrFormat = { + metadata: { name: '', uid: '' }, + apiResponse: { lastModified: DASH, size: DASH }, + isFolder: false, + type: '', + }; + if (isFolder) { + const prefix = (objectData as CommonPrefix)?.Prefix; + structuredObjects.metadata.name = prefix; + structuredObjects.metadata.uid = prefix; + structuredObjects.isFolder = true; + structuredObjects.type = t('Folder'); + } else { + const key = (objectData as Content)?.Key; + const lastIndexOfDot = key.lastIndexOf('.'); + structuredObjects.metadata.name = key; + structuredObjects.metadata.uid = key; + structuredObjects.apiResponse.lastModified = + (objectData as Content)?.LastModified?.toString() || DASH; + structuredObjects.apiResponse.size = + humanizeBinaryBytes((objectData as Content)?.Size, 'B', 'GiB')?.string || + DASH; + structuredObjects.type = + (lastIndexOfDot !== -1 + ? key.substring(lastIndexOfDot + 1, key.length) + : DASH) || DASH; + } + + return structuredObjects; +}; diff --git a/packages/shared/src/hooks/index.ts b/packages/shared/src/hooks/index.ts index fc16d2c86..63d16a651 100644 --- a/packages/shared/src/hooks/index.ts +++ b/packages/shared/src/hooks/index.ts @@ -9,3 +9,4 @@ export * from './use-fetch-csv'; export * from './useK8sList'; export * from './scheduler'; export * from './use-doc-version'; +export * from './useRefresh'; diff --git a/packages/shared/src/hooks/useRefresh.ts b/packages/shared/src/hooks/useRefresh.ts new file mode 100644 index 000000000..7f61af4b6 --- /dev/null +++ b/packages/shared/src/hooks/useRefresh.ts @@ -0,0 +1,33 @@ +import * as React from 'react'; + +/** + * Can be used for un-mounting and immediately re-mounting a React component. + * ex: refreshing API calls (re-fetching data on demand). + + * "visualDelay" (optional): visual delay on the UI to make sure loading state can be perceived by the users (needed when data is loaded directly from the cache) + * "shouldUsePromise" (optional): using promise will be faster, but in case of caching we can't add any "visualDelay" on the UI (this method will work best if caching is not enabled) + */ +export const useRefresh = ( + visualDelay = 0, + shouldUsePromise = false +): [boolean, () => void] => { + const [fresh, setFresh] = React.useState(true); + const id = React.useRef(); + + const triggerRefresh = React.useCallback(() => { + setFresh(false); + + if (shouldUsePromise) { + // queuing for immediate re-toggle + const promise = Promise.resolve(() => setFresh(true)); + promise.then((callback) => callback()); + } else { + // clearing older timer and + // queuing for immediate re-toggle + clearTimeout(id.current); + id.current = setTimeout(() => setFresh(true), visualDelay); + } + }, [setFresh, visualDelay, shouldUsePromise]); + + return [fresh, triggerRefresh]; +}; diff --git a/packages/shared/src/s3/commands.ts b/packages/shared/src/s3/commands.ts index 733b6352a..efdc3e604 100644 --- a/packages/shared/src/s3/commands.ts +++ b/packages/shared/src/s3/commands.ts @@ -1,9 +1,9 @@ import { S3Client, ListBucketsCommand, - ListObjectsCommand, + ListObjectsV2Command, } from '@aws-sdk/client-s3'; -import { ListBuckets, ListObjects } from './types'; +import { ListBuckets, ListObjectsV2 } from './types'; export class S3Commands { private s3Client: S3Client; @@ -26,6 +26,6 @@ export class S3Commands { this.s3Client.send(new ListBucketsCommand(input)); // Object command members - listObjects: ListObjects = (input) => - this.s3Client.send(new ListObjectsCommand(input)); + listObjects: ListObjectsV2 = (input) => + this.s3Client.send(new ListObjectsV2Command(input)); } diff --git a/packages/shared/src/s3/types.ts b/packages/shared/src/s3/types.ts index 06e8a7898..bad495736 100644 --- a/packages/shared/src/s3/types.ts +++ b/packages/shared/src/s3/types.ts @@ -1,8 +1,8 @@ import { ListBucketsCommandInput, ListBucketsCommandOutput, - ListObjectsCommandInput, - ListObjectsCommandOutput, + ListObjectsV2CommandInput, + ListObjectsV2CommandOutput, } from '@aws-sdk/client-s3'; // Bucket command types @@ -11,6 +11,6 @@ export type ListBuckets = ( ) => Promise; // Object command types -export type ListObjects = ( - input: ListObjectsCommandInput -) => Promise; +export type ListObjectsV2 = ( + input: ListObjectsV2CommandInput +) => Promise; diff --git a/packages/shared/src/table/selectable-table.tsx b/packages/shared/src/table/selectable-table.tsx index 20927bfa9..127a365de 100644 --- a/packages/shared/src/table/selectable-table.tsx +++ b/packages/shared/src/table/selectable-table.tsx @@ -16,8 +16,9 @@ import { useSortList } from '../hooks/sort-list'; import { getUID } from '../selectors'; import { TableColumnProps, RowComponentType } from './composable-table'; -const isRowSelectable = (row: T) => - !row?.metadata?.deletionTimestamp; +const hasNoDeletionTimestamp: IsRowSelectable = ( + row: T +) => !row?.metadata?.deletionTimestamp; const areAllRowsSelected = ( selectableRows: T[], @@ -57,6 +58,7 @@ export const SelectableTable: SelectableTableProps = < initialSortColumnIndex, borders, className, + isRowSelectable, }) => { const { onSort, @@ -73,10 +75,11 @@ export const SelectableTable: SelectableTableProps = < ); const [selectableRows, rowIds] = React.useMemo(() => { - const selectableRows = sortedRows?.filter(isRowSelectable) || []; + const selectableRows = + sortedRows?.filter(isRowSelectable || hasNoDeletionTimestamp) || []; const rowIds = new Set(selectableRows?.map(getUID)); return [selectableRows, rowIds]; - }, [sortedRows]); + }, [sortedRows, isRowSelectable]); const { onSelect } = useSelectList( selectableRows, @@ -148,7 +151,9 @@ export const SelectableTable: SelectableTableProps = < rowIndex, onSelect: onSelect, isSelected: isRowSelected(getUID(row), selectedRows), - disable: !isRowSelectable(row), + isDisabled: + !isRowSelectable?.(row) || + !hasNoDeletionTimestamp(row), props: { id: getUID(row), }, @@ -165,6 +170,8 @@ export const SelectableTable: SelectableTableProps = < ); }; +type IsRowSelectable = (row: T) => boolean; + type TableProps = { rows: T[]; columns: TableColumnProps[]; @@ -182,6 +189,7 @@ type TableProps = { borders?: boolean; /** Additional classes added to the Table */ className?: string; + isRowSelectable?: IsRowSelectable; }; type SelectableTableProps = ( diff --git a/plugins/odf/console-extensions.json b/plugins/odf/console-extensions.json index a47611d1e..3b33b6a21 100644 --- a/plugins/odf/console-extensions.json +++ b/plugins/odf/console-extensions.json @@ -716,5 +716,15 @@ "path": "/odf/resource/odf.openshift.io~v1alpha1~StorageSystem/create/~new", "component": { "$codeRef": "wizard.default" } } + }, + { + "type": "console.page/route", + "properties": { + "path": "/odf/object-storage/buckets/:bucketName", + "exact": false, + "component": { + "$codeRef": "s3BucketOverview.default" + } + } } ] diff --git a/plugins/odf/console-plugin.json b/plugins/odf/console-plugin.json index d464f0cf1..e3d350199 100644 --- a/plugins/odf/console-plugin.json +++ b/plugins/odf/console-plugin.json @@ -41,6 +41,7 @@ "mutators": "@odf/ocs/storage-class/mutators", "odfReduxReducers": "@odf/core/redux", "monCountAlertModal": "@odf/core/modals/configure-mons/configure-mons", - "storageConsumerListPage": "@odf/core/components/storage-consumers/client-list" + "storageConsumerListPage": "@odf/core/components/storage-consumers/client-list", + "s3BucketOverview": "@odf/core/components/s3-browser/bucket-overview/BucketOverview" } } diff --git a/yarn.lock b/yarn.lock index 11d920d61..d46eec644 100644 --- a/yarn.lock +++ b/yarn.lock @@ -4617,6 +4617,11 @@ cli-truncate@^2.1.0: slice-ansi "^3.0.0" string-width "^4.2.0" +client-only@^0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/client-only/-/client-only-0.0.1.tgz#38bba5d403c41ab150bff64a95c85013cf73bca1" + integrity sha512-IV3Ou0jSMzZrd3pZ48nLkT9DA7Ag1pnPzaiQhpW7c3RbcqqzvzzVu+L8gfqMp/8IM2MQtSiqaCxrrcfu8I8rMA== + cliui@^3.0.3: version "3.2.0" resolved "https://registry.yarnpkg.com/cliui/-/cliui-3.2.0.tgz#120601537a916d29940f934da3b48d585a39213d" @@ -12269,6 +12274,14 @@ svgo@^0.7.0: sax "~1.2.1" whet.extend "~0.9.9" +swr@2.2.5: + version "2.2.5" + resolved "https://registry.yarnpkg.com/swr/-/swr-2.2.5.tgz#063eea0e9939f947227d5ca760cc53696f46446b" + integrity sha512-QtxqyclFeAsxEUeZIYmsaQ0UjimSq1RZ9Un7I68/0ClKK/U3LoyQunwkQfJZr2fc22DfIXLNDc2wFyTEikCUpg== + dependencies: + client-only "^0.0.1" + use-sync-external-store "^1.2.0" + symbol-observable@^1.2.0: version "1.2.0" resolved "https://registry.yarnpkg.com/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" @@ -12830,6 +12843,11 @@ url-parse@^1.5.3: querystringify "^2.1.1" requires-port "^1.0.0" +use-sync-external-store@^1.2.0: + version "1.2.2" + resolved "https://registry.yarnpkg.com/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz#c3b6390f3a30eba13200d2302dcdf1e7b57b2ef9" + integrity sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw== + util-deprecate@^1.0.1, util-deprecate@^1.0.2, util-deprecate@~1.0.1: version "1.0.2" resolved "https://registry.yarnpkg.com/util-deprecate/-/util-deprecate-1.0.2.tgz#450d4dc9fa70de732762fbd2d4a28981419a0ccf" From 99b9bc067a6cff22b4a72127f0b245314a5b0c71 Mon Sep 17 00:00:00 2001 From: SanjalKatiyar Date: Thu, 3 Oct 2024 11:05:03 +0530 Subject: [PATCH 10/22] Update OWNERS file --- OWNERS | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/OWNERS b/OWNERS index d3dbd2fd5..aa1da9290 100644 --- a/OWNERS +++ b/OWNERS @@ -1,11 +1,12 @@ reviewers: - - cloudbehl - bipuladh - SanjalKatiyar - vbnrh - - rexagod + - GowthamShanmugam + - alfonsomthd approvers: - - cloudbehl - bipuladh - SanjalKatiyar + - GowthamShanmugam + - alfonsomthd component: ODF Console From 9c221d5d526e0bed7d39db88979489204e3a8e3a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alfonso=20Mart=C3=ADnez?= Date: Tue, 1 Oct 2024 18:46:14 +0200 Subject: [PATCH 11/22] Add 'Create Bucket' form (via S3-compat API) --- locales/en/plugin__odf-console.json | 8 + .../mcg/CreateObjectBucketClaim.tsx | 4 +- .../s3-browser/create-bucket/CreateBucket.tsx | 10 +- .../create-bucket/CreateBucketForm.tsx | 171 ++++++++++++++++++ .../create-bucket/create-bucket-form.scss | 17 ++ .../useS3BucketFormValidation.ts | 50 +++++ packages/odf/constants/s3-browser.ts | 3 + .../shared/src/constants/fieldRequirements.ts | 4 + packages/shared/src/s3/commands.ts | 15 +- packages/shared/src/s3/types.ts | 12 ++ packages/shared/src/utils/NameValueEditor.tsx | 50 +++-- 11 files changed, 326 insertions(+), 18 deletions(-) create mode 100644 packages/odf/components/s3-browser/create-bucket/CreateBucketForm.tsx create mode 100644 packages/odf/components/s3-browser/create-bucket/create-bucket-form.scss create mode 100644 packages/odf/components/s3-browser/create-bucket/useS3BucketFormValidation.ts diff --git a/locales/en/plugin__odf-console.json b/locales/en/plugin__odf-console.json index 01a5a03c2..e1f709c1b 100644 --- a/locales/en/plugin__odf-console.json +++ b/locales/en/plugin__odf-console.json @@ -1118,6 +1118,14 @@ "Create via Object Bucket Claim": "Create via Object Bucket Claim", "Ideal for Kubernetes environments providing a more abstracted approach to managing storage resources and leveraging dynamic provisioning.": "Ideal for Kubernetes environments providing a more abstracted approach to managing storage resources and leveraging dynamic provisioning.", "OBC references a StorageClass that uses a provisioner to interact with the S3 API and create the bucket. Kubernetes binds the OBC to the bucket, making it accessible to applications.": "OBC references a StorageClass that uses a provisioner to interact with the S3 API and create the bucket. Kubernetes binds the OBC to the bucket, making it accessible to applications.", + "Bucket Name": "Bucket Name", + "my-bucket": "my-bucket", + "A unique name for your bucket.": "A unique name for your bucket.", + "Tags": "Tags", + "Use different criteria for tagging your bucket.": "Use different criteria for tagging your bucket.", + "No tags are attached to this bucket.": "No tags are attached to this bucket.", + "Add tag": "Add tag", + "Value (optional)": "Value (optional)", "Download objects": "Download objects", "Delete objects": "Delete objects", "Actions": "Actions", diff --git a/packages/odf/components/mcg/CreateObjectBucketClaim.tsx b/packages/odf/components/mcg/CreateObjectBucketClaim.tsx index 90e38a626..276853f44 100644 --- a/packages/odf/components/mcg/CreateObjectBucketClaim.tsx +++ b/packages/odf/components/mcg/CreateObjectBucketClaim.tsx @@ -367,10 +367,12 @@ export const CreateOBCForm: React.FC = (props) => { }; type CreateOBCProps = { + className?: string; showNamespaceSelector?: boolean; }; export const CreateOBC: React.FC = ({ + className, showNamespaceSelector = false, }) => { const { t } = useCustomTranslation(); @@ -500,7 +502,7 @@ export const CreateOBC: React.FC = ({ // ToDo (Sanjal): Update the non-admin "Role" to a "ClusterRole", then read list of NooBaa/BucketClasses across all namespaces. return ( -
+ {showNamespaceSelector && ( = () => { )} className="pf-v5-u-mb-md" /> - + )} - {/* @TODO: implement S3 form. */} + {method === CreationMethod.S3 && ( + + + + )} ); diff --git a/packages/odf/components/s3-browser/create-bucket/CreateBucketForm.tsx b/packages/odf/components/s3-browser/create-bucket/CreateBucketForm.tsx new file mode 100644 index 000000000..325934aa5 --- /dev/null +++ b/packages/odf/components/s3-browser/create-bucket/CreateBucketForm.tsx @@ -0,0 +1,171 @@ +import * as React from 'react'; +import { PutBucketTaggingCommandInput } from '@aws-sdk/client-s3'; +import useS3BucketFormValidation from '@odf/core/components/s3-browser/create-bucket/useS3BucketFormValidation'; +import { NoobaaS3Context } from '@odf/core/components/s3-browser/noobaa-context'; +import { BUCKETS_BASE_ROUTE } from '@odf/core/constants'; +import { + ButtonBar, + formSettings, + TextInputWithFieldRequirements, + useCustomTranslation, + useYupValidationResolver, +} from '@odf/shared'; +import { LazyNameValueEditor } from '@odf/shared/utils/NameValueEditor'; +import cn from 'classnames'; +import * as _ from 'lodash-es'; +import { useForm } from 'react-hook-form'; +import { useNavigate } from 'react-router-dom-v5-compat'; +import { + ActionGroup, + Alert, + Button, + Form, + FormGroup, +} from '@patternfly/react-core'; +import { TagIcon } from '@patternfly/react-icons'; +import './create-bucket-form.scss'; + +type FormData = { + bucketName: string; +}; + +const CreateBucketForm: React.FC<{}> = () => { + const { t } = useCustomTranslation(); + const navigate = useNavigate(); + const [inProgress, setInProgress] = React.useState(false); + const [errorMessage, setErrorMessage] = React.useState(''); + const [tagsData, setTagsData] = React.useState([]); + + const { noobaaS3 } = React.useContext(NoobaaS3Context); + const { bucketFormSchema, fieldRequirements } = useS3BucketFormValidation(); + const resolver = useYupValidationResolver(bucketFormSchema); + + const { + control, + handleSubmit, + formState: { isValid, isSubmitted }, + } = useForm({ + ...formSettings, + resolver, + }); + + const save = async (formData: FormData) => { + setInProgress(true); + let bucketCreationError = ''; + setErrorMessage(bucketCreationError); + const { bucketName } = formData; + try { + await noobaaS3.createBucket({ Bucket: bucketName }); + } catch ({ name, message }) { + bucketCreationError = `Error while creating bucket: ${name}: ${message}`; + } + + if (bucketCreationError) { + setInProgress(false); + setErrorMessage(bucketCreationError); + return; + } + + // Update bucket tags: any error here shouldn't prevent redirection + // as the bucket has been created successfully. + try { + const tagSet: PutBucketTaggingCommandInput['Tagging']['TagSet'] = tagsData + .filter((pair: string[]) => !_.isEmpty(pair[0])) + .map((pair: string[]) => ({ Key: pair[0], Value: pair[1] })); + if (!_.isEmpty(tagSet)) { + await noobaaS3.putBucketTags({ + Bucket: bucketName, + Tagging: { TagSet: tagSet }, + }); + } + } catch ({ name, message }) { + // @TODO: add a toast warning that is visible after redirection to bucket details. + // eslint-disable-next-line no-console + console.error(`Error while updating bucket tags: ${name}: ${message}`); + } + navigate(`${BUCKETS_BASE_ROUTE}/${bucketName}`); + }; + + return ( + + + + {_.isEmpty(tagsData) && ( +
+ {t('No tags are attached to this bucket.')} +
+ )} + { + setTagsData(nameValuePairs); + }} + hideHeaderWhenNoItems={true} + IconComponent={TagIcon} + nameMaxLength={128} + valueMaxLength={256} + /> +
+ {!isValid && isSubmitted && ( + + )} + + + + + + + + ); +}; + +export default CreateBucketForm; diff --git a/packages/odf/components/s3-browser/create-bucket/create-bucket-form.scss b/packages/odf/components/s3-browser/create-bucket/create-bucket-form.scss new file mode 100644 index 000000000..e0a5ef902 --- /dev/null +++ b/packages/odf/components/s3-browser/create-bucket/create-bucket-form.scss @@ -0,0 +1,17 @@ +.odf-create-s3-bucket-form__tags { + // Display 'Tags' label description under the title. + .pf-v5-c-form__group-label { + display: block; + } + .pf-v5-c-form__group-label-info { + margin-left: 0; + } +} + +.odf-create-s3-bucket-form__tags--empty { + // Align NameValueEditor icon with 'no tags' text when only icon is shown. + .pf-v5-c-form__group-control { + display: flex; + align-items: center; + } +} diff --git a/packages/odf/components/s3-browser/create-bucket/useS3BucketFormValidation.ts b/packages/odf/components/s3-browser/create-bucket/useS3BucketFormValidation.ts new file mode 100644 index 000000000..02e82fbd9 --- /dev/null +++ b/packages/odf/components/s3-browser/create-bucket/useS3BucketFormValidation.ts @@ -0,0 +1,50 @@ +import * as React from 'react'; +import { + BUCKET_NAME_MAX_LENGTH, + BUCKET_NAME_MIN_LENGTH, +} from '@odf/core/constants'; +import { fieldRequirementsTranslations } from '@odf/shared/constants'; +import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; +import validationRegEx from '@odf/shared/utils/validation'; +import * as Yup from 'yup'; + +export type S3BucketFormSchema = Yup.ObjectSchema<{ + bucketName: Yup.StringSchema; +}>; + +export type S3BucketFormValidation = { + bucketFormSchema: S3BucketFormSchema; + fieldRequirements: string[]; +}; + +const useS3BucketFormValidation = (): S3BucketFormValidation => { + const { t } = useCustomTranslation(); + + return React.useMemo(() => { + const fieldRequirements = [ + fieldRequirementsTranslations.maxChars(t, BUCKET_NAME_MAX_LENGTH), + fieldRequirementsTranslations.minChars(t, BUCKET_NAME_MIN_LENGTH), + fieldRequirementsTranslations.startAndEndName(t), + fieldRequirementsTranslations.alphaNumericPeriodAdnHyphen(t), + ]; + + const bucketFormSchema = Yup.object({ + bucketName: Yup.string() + .max(BUCKET_NAME_MAX_LENGTH, fieldRequirements[0]) + .min(BUCKET_NAME_MIN_LENGTH, fieldRequirements[1]) + .matches( + validationRegEx.startAndEndsWithAlphanumerics, + fieldRequirements[2] + ) + .matches( + validationRegEx.alphaNumericsPeriodsHyphensNonConsecutive, + fieldRequirements[3] + ) + .transform((value: string) => (!!value ? value : '')), + }); + + return { bucketFormSchema, fieldRequirements }; + }, [t]); +}; + +export default useS3BucketFormValidation; diff --git a/packages/odf/constants/s3-browser.ts b/packages/odf/constants/s3-browser.ts index bc5e354fe..3752639d8 100644 --- a/packages/odf/constants/s3-browser.ts +++ b/packages/odf/constants/s3-browser.ts @@ -7,6 +7,9 @@ export const DELIMITER = '/'; export const PREFIX = 'prefix'; export const MAX_KEYS = 300; +export const BUCKET_NAME_MAX_LENGTH = 63; +export const BUCKET_NAME_MIN_LENGTH = 3; + export const BUCKETS_BASE_ROUTE = '/odf/object-storage/buckets'; // key to be used by SWR for caching particular API call diff --git a/packages/shared/src/constants/fieldRequirements.ts b/packages/shared/src/constants/fieldRequirements.ts index 6752ce3ed..946adfe21 100644 --- a/packages/shared/src/constants/fieldRequirements.ts +++ b/packages/shared/src/constants/fieldRequirements.ts @@ -3,6 +3,9 @@ import { TFunction } from 'i18next'; export const maxChars = (t: TFunction, max: number) => t(`No more than ${max} characters`); +export const minChars = (t: TFunction, min: number) => + t(`No less than ${min} characters`); + export const startAndEndName = (t: TFunction) => t('Starts and ends with a lowercase letter or number'); @@ -16,6 +19,7 @@ export const uniqueName = (t: TFunction, fieldName: string) => export const fieldRequirementsTranslations = { maxChars, + minChars, startAndEndName, alphaNumericPeriodAdnHyphen, cannotBeUsedBefore, diff --git a/packages/shared/src/s3/commands.ts b/packages/shared/src/s3/commands.ts index efdc3e604..06c34ada8 100644 --- a/packages/shared/src/s3/commands.ts +++ b/packages/shared/src/s3/commands.ts @@ -2,8 +2,15 @@ import { S3Client, ListBucketsCommand, ListObjectsV2Command, + CreateBucketCommand, + PutBucketTaggingCommand, } from '@aws-sdk/client-s3'; -import { ListBuckets, ListObjectsV2 } from './types'; +import { + CreateBucket, + ListBuckets, + ListObjectsV2, + PutBucketTags, +} from './types'; export class S3Commands { private s3Client: S3Client; @@ -22,9 +29,15 @@ export class S3Commands { } // Bucket command members + createBucket: CreateBucket = (input) => + this.s3Client.send(new CreateBucketCommand(input)); + listBuckets: ListBuckets = (input) => this.s3Client.send(new ListBucketsCommand(input)); + putBucketTags: PutBucketTags = (input) => + this.s3Client.send(new PutBucketTaggingCommand(input)); + // Object command members listObjects: ListObjectsV2 = (input) => this.s3Client.send(new ListObjectsV2Command(input)); diff --git a/packages/shared/src/s3/types.ts b/packages/shared/src/s3/types.ts index bad495736..56ecb27fc 100644 --- a/packages/shared/src/s3/types.ts +++ b/packages/shared/src/s3/types.ts @@ -1,15 +1,27 @@ import { + CreateBucketCommandInput, + CreateBucketCommandOutput, ListBucketsCommandInput, ListBucketsCommandOutput, ListObjectsV2CommandInput, ListObjectsV2CommandOutput, + PutBucketTaggingCommandInput, + PutBucketTaggingCommandOutput, } from '@aws-sdk/client-s3'; // Bucket command types +export type CreateBucket = ( + input?: CreateBucketCommandInput +) => Promise; + export type ListBuckets = ( input?: ListBucketsCommandInput ) => Promise; +export type PutBucketTags = ( + input?: PutBucketTaggingCommandInput +) => Promise; + // Object command types export type ListObjectsV2 = ( input: ListObjectsV2CommandInput diff --git a/packages/shared/src/utils/NameValueEditor.tsx b/packages/shared/src/utils/NameValueEditor.tsx index 822edb90f..1a5e9d636 100644 --- a/packages/shared/src/utils/NameValueEditor.tsx +++ b/packages/shared/src/utils/NameValueEditor.tsx @@ -53,6 +53,10 @@ type NameValueEditorProps = { extraProps?: any; isAddDisabled?: boolean; className?: string; + hideHeaderWhenNoItems?: boolean; + IconComponent?: React.FC; + nameMaxLength?: number; + valueMaxLength?: number; }; export const enum NameValueEditorPair { @@ -80,6 +84,8 @@ export type PairElementProps = { isEmpty: boolean; disableReorder: boolean; extraProps?: any; + nameMaxLength?: number; + valueMaxLength?: number; }; const PairElement: React.FC = ({ @@ -97,6 +103,8 @@ const PairElement: React.FC = ({ toolTip, valueString, alwaysAllowRemove, + nameMaxLength, + valueMaxLength, }) => { const { t } = useCustomTranslation(); const deleteIcon = ( @@ -159,6 +167,7 @@ const PairElement: React.FC = ({ value={pair[NameValueEditorPair.Name]} onChange={onChangeName} disabled={readOnly} + maxLength={nameMaxLength} />
@@ -170,6 +179,7 @@ const PairElement: React.FC = ({ value={pair[NameValueEditorPair.Value] || ''} onChange={onChangeValue} disabled={readOnly} + maxLength={valueMaxLength} />
{!readOnly && ( @@ -210,6 +220,10 @@ export const NameValueEditor: React.FC = extraProps, isAddDisabled, className, + hideHeaderWhenNoItems = false, + nameMaxLength, + valueMaxLength, + IconComponent = PlusCircleIcon, PairElementComponent = PairElement, }) => { const { t } = useCustomTranslation(); @@ -300,24 +314,32 @@ export const NameValueEditor: React.FC = disableReorder={nameValuePairs.length === 1} toolTip={toolTip} extraProps={extraProps} + nameMaxLength={nameMaxLength} + valueMaxLength={valueMaxLength} /> ); }); return ( <> -
- {!readOnly && allowSorting && ( -
- )} -
- {nameStringUpdated} -
-
- {valueStringUpdated} -
-
-
- {pairElems} + {hideHeaderWhenNoItems && _.isEmpty(pairElems) ? ( + <> + ) : ( + <> +
+ {!readOnly && allowSorting && ( +
+ )} +
+ {nameStringUpdated} +
+
+ {valueStringUpdated} +
+
+
+ {pairElems} + + )}
{readOnly ? null : ( @@ -330,7 +352,7 @@ export const NameValueEditor: React.FC = variant="link" isDisabled={isAddDisabled} > - From 14b314a3a34c2c315888f9dfa83f9dad60bd694b Mon Sep 17 00:00:00 2001 From: SanjalKatiyar Date: Tue, 1 Oct 2024 20:13:29 +0530 Subject: [PATCH 12/22] Add object actions - presigned URL --- locales/en/plugin__odf-console.json | 18 +- package.json | 3 + .../bucket-overview/BucketOverview.tsx | 1 - .../s3-browser/bucket-overview/PageTitle.tsx | 36 +-- .../s3-browser/objects-list/ObjectsList.tsx | 2 +- .../objects-list/table-components.tsx | 33 ++- .../presigned-url/PresignedURLModal.tsx | 235 ++++++++++++++++++ .../presigned-url/presigned-modal.scss | 3 + packages/shared/src/s3/commands.ts | 6 + packages/shared/src/s3/types.ts | 6 + packages/shared/src/utils/common.ts | 9 + yarn.lock | 34 +++ 12 files changed, 336 insertions(+), 50 deletions(-) create mode 100644 packages/odf/modals/s3-browser/presigned-url/PresignedURLModal.tsx create mode 100644 packages/odf/modals/s3-browser/presigned-url/presigned-modal.scss diff --git a/locales/en/plugin__odf-console.json b/locales/en/plugin__odf-console.json index e1f709c1b..9799752ac 100644 --- a/locales/en/plugin__odf-console.json +++ b/locales/en/plugin__odf-console.json @@ -1104,7 +1104,6 @@ "Edit bucket": "Edit bucket", "Objects": "Objects", "Refresh": "Refresh", - "Created on: ": "Created on: ", "Created via OBC": "Created via OBC", "Created via S3": "Created via S3", "MCG": "MCG", @@ -1133,7 +1132,6 @@ "Size": "Size", "Last modified": "Last modified", "Download": "Download", - "Copy Object URL": "Copy Object URL", "Preview": "Preview", "Share with presigned URL": "Share with presigned URL", "No objects found": "No objects found", @@ -1300,6 +1298,21 @@ "and": "and", "GiB RAM": "GiB RAM", "Configure Performance": "Configure Performance", + "Expires after": "Expires after", + "minus": "minus", + "plus": "plus", + "Validity period of the presigned URL.": "Validity period of the presigned URL.", + "Share link": "Share link", + "Valid until: ": "Valid until: ", + "Copy": "Copy", + "Copied": "Copied", + "This URL will automatically expire based on your configured time or when your current session expires.": "This URL will automatically expire based on your configured time or when your current session expires.", + "Share object with a presigned URL": "Share object with a presigned URL", + "Grant third-party access to an object for a limited time.": "Grant third-party access to an object for a limited time.", + "Copy presigned URL to clipboard": "Copy presigned URL to clipboard", + "Create presigned URL": "Create presigned URL", + "Object: ": "Object: ", + "A third-party entity can access the object using this presigned URL, which allows sharing without requiring a login, until the URL expires.": "A third-party entity can access the object using this presigned URL, which allows sharing without requiring a login, until the URL expires.", "hr": "hr", "min": "min", "Select at least 2 Backing Store resources": "Select at least 2 Backing Store resources", @@ -1452,7 +1465,6 @@ "Reason": "Reason", "Message": "Message", "No conditions found": "No conditions found", - "Copied": "Copied", "View documentation": "View documentation", "Oh no! Something went wrong.": "Oh no! Something went wrong.", "Copied to clipboard": "Copied to clipboard", diff --git a/package.json b/package.json index 5f5d27eeb..9ad42f1b4 100644 --- a/package.json +++ b/package.json @@ -60,6 +60,7 @@ }, "dependencies": { "@aws-sdk/client-s3": "3.614.0", + "@aws-sdk/s3-request-presigner": "3.614.0", "@openshift-console/dynamic-plugin-sdk": "1.3.0", "@openshift-console/dynamic-plugin-sdk-internal": "1.0.0", "@openshift-console/dynamic-plugin-sdk-webpack": "1.1.1", @@ -91,6 +92,7 @@ "js-base64": "^2.1.9", "js-yaml": "^3.13.1", "lodash-es": "^4.17.21", + "luxon": "^3.3.0", "murmurhash-js": "^1.0.0", "react": "^17.0.1", "react-copy-to-clipboard": "5.x", @@ -133,6 +135,7 @@ "@testing-library/react-hooks": "^8.0.1", "@testing-library/user-event": "^14.5.1", "@types/jest": "29.2.2", + "@types/luxon": "^3.3.1", "@types/node": "^14.14.34", "@types/react": "16.8.13", "@types/react-helmet": "^6.1.1", diff --git a/packages/odf/components/s3-browser/bucket-overview/BucketOverview.tsx b/packages/odf/components/s3-browser/bucket-overview/BucketOverview.tsx index 4d5f50389..6e08a9a34 100644 --- a/packages/odf/components/s3-browser/bucket-overview/BucketOverview.tsx +++ b/packages/odf/components/s3-browser/bucket-overview/BucketOverview.tsx @@ -180,7 +180,6 @@ const BucketOverview: React.FC<{}> = () => { bucketName={bucketName} foldersPath={foldersPath} currentFolder={currentFolder} - fresh={fresh} isCreatedByOBC={isCreatedByOBC} noobaaObjectBucket={noobaaObjectBucket} /> diff --git a/packages/odf/components/s3-browser/bucket-overview/PageTitle.tsx b/packages/odf/components/s3-browser/bucket-overview/PageTitle.tsx index e06db22d7..1f2b39169 100644 --- a/packages/odf/components/s3-browser/bucket-overview/PageTitle.tsx +++ b/packages/odf/components/s3-browser/bucket-overview/PageTitle.tsx @@ -4,50 +4,19 @@ import { K8sResourceKind } from '@odf/shared/types'; import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; import { ResourceStatus } from '@openshift-console/dynamic-plugin-sdk'; import Status from '@openshift-console/dynamic-plugin-sdk/lib/app/components/status/Status'; -import useSWR from 'swr'; -import { Skeleton, Label, Button, ButtonVariant } from '@patternfly/react-core'; +import { Label, Button, ButtonVariant } from '@patternfly/react-core'; import { CopyIcon } from '@patternfly/react-icons'; -import { LIST_BUCKET } from '../../../constants'; import { getPath } from '../../../utils'; -import { NoobaaS3Context } from '../noobaa-context'; import './bucket-overview.scss'; type TitleProps = { bucketName: string; foldersPath: string; currentFolder: string; - fresh: boolean; isCreatedByOBC: boolean; noobaaObjectBucket: K8sResourceKind; }; -const CreatedOnSkeleton: React.FC<{}> = () => ( - -); - -const CreatedOn: React.FC<{ bucketName: string }> = ({ bucketName }) => { - const { t } = useCustomTranslation(); - - const { noobaaS3 } = React.useContext(NoobaaS3Context); - const { data, error, isLoading } = useSWR(LIST_BUCKET, () => - noobaaS3.listBuckets() - ); - - const bucketCreatedOn = - !isLoading && !error - ? data?.Buckets?.find((bucket) => bucket?.Name === bucketName) - ?.CreationDate - : null; - - return isLoading ? ( - - ) : ( -

- {t('Created on: ') + bucketCreatedOn?.toString()} -

- ); -}; - const BucketResourceStatus: React.FC<{ resourceStatus: string }> = ({ resourceStatus, }) => ( @@ -60,7 +29,6 @@ export const PageTitle: React.FC = ({ bucketName, foldersPath, currentFolder, - fresh, isCreatedByOBC, noobaaObjectBucket, }) => { @@ -99,8 +67,6 @@ export const PageTitle: React.FC = ({ )}
- {!foldersPath && - (fresh ? : )}

{t('Object path: ')} {objectPath} diff --git a/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx b/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx index 8d17fbe3d..966f4704e 100644 --- a/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx +++ b/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx @@ -319,7 +319,7 @@ export const ObjectsList: React.FC<{}> = () => { loaded={!isMutating} loadError={error} isRowSelectable={isRowSelectable} - extraProps={{ launcher, bucketName, foldersPath }} + extraProps={{ launcher, bucketName, foldersPath, noobaaS3 }} emptyRowMessage={EmptyPage} />

diff --git a/packages/odf/components/s3-browser/objects-list/table-components.tsx b/packages/odf/components/s3-browser/objects-list/table-components.tsx index 0f4b42c79..0cc917a41 100644 --- a/packages/odf/components/s3-browser/objects-list/table-components.tsx +++ b/packages/odf/components/s3-browser/objects-list/table-components.tsx @@ -1,4 +1,5 @@ import * as React from 'react'; +import { S3Commands } from '@odf/shared/s3'; import { getName } from '@odf/shared/selectors'; import { RowComponentType } from '@odf/shared/table'; import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; @@ -19,6 +20,10 @@ import { ActionsColumn, Td, IAction } from '@patternfly/react-table'; import { BUCKETS_BASE_ROUTE, PREFIX } from '../../../constants'; import { ObjectCrFormat } from '../../../types'; +const LazyPresignedURLModal = React.lazy( + () => import('../../../modals/s3-browser/presigned-url/PresignedURLModal') +); + const getColumnNames = (t: TFunction): string[] => [ t('Name'), t('Size'), @@ -29,25 +34,27 @@ const getColumnNames = (t: TFunction): string[] => [ const getInlineActionsItems = ( t: TFunction, - _launcher: LaunchModal, - _object: ObjectCrFormat + launcher: LaunchModal, + bucketName: string, + object: ObjectCrFormat, + noobaaS3: S3Commands ): IAction[] => [ - // ToDo: add inline download, copy, preview, share & delete options + // ToDo: add inline download, preview & delete options { title: t('Download'), onClick: () => undefined, }, - { - title: t('Copy Object URL'), - onClick: () => undefined, - }, { title: t('Preview'), onClick: () => undefined, }, { title: t('Share with presigned URL'), - onClick: () => undefined, + onClick: () => + launcher(LazyPresignedURLModal, { + isOpen: true, + extraProps: { bucketName, object, noobaaS3 }, + }), }, { title: t('Delete'), @@ -87,7 +94,7 @@ export const TableRow: React.FC> = ({ }) => { const { t } = useCustomTranslation(); - const { launcher, bucketName, foldersPath } = extraProps; + const { launcher, bucketName, foldersPath, noobaaS3 } = extraProps; const isFolder = object.isFolder; const name = getName(object).replace(foldersPath, ''); const prefix = !!foldersPath @@ -120,7 +127,13 @@ export const TableRow: React.FC> = ({ {isFolder ? null : ( )} diff --git a/packages/odf/modals/s3-browser/presigned-url/PresignedURLModal.tsx b/packages/odf/modals/s3-browser/presigned-url/PresignedURLModal.tsx new file mode 100644 index 000000000..d0cc27525 --- /dev/null +++ b/packages/odf/modals/s3-browser/presigned-url/PresignedURLModal.tsx @@ -0,0 +1,235 @@ +import * as React from 'react'; +import StaticDropdown from '@odf/shared/dropdown/StaticDropdown'; +import { ButtonBar } from '@odf/shared/generic/ButtonBar'; +import { CommonModalProps } from '@odf/shared/modals'; +import { S3Commands } from '@odf/shared/s3'; +import { getName } from '@odf/shared/selectors'; +import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; +import { numberInputOnChange } from '@odf/shared/utils'; +import { DateTime } from 'luxon'; +import { + Modal, + ModalVariant, + Button, + ButtonVariant, + Alert, + AlertVariant, + FormGroup, + FormHelperText, + HelperText, + HelperTextItem, + ValidatedOptions, + NumberInput, + ClipboardCopy, +} from '@patternfly/react-core'; +import { ObjectCrFormat } from '../../../types'; +import './presigned-modal.scss'; + +// using same "key" and "value" in the enum on purpose, due to how "StaticDropdown" is implemented +enum TimeUnits { + Hours = 'Hours', + Minutes = 'Minutes', +} + +type PresignedURLModalProps = { + bucketName: string; + object: ObjectCrFormat; + noobaaS3: S3Commands; +}; + +type URLExpiration = { + value: number; + unit: TimeUnits; +}; + +type URLDetails = { + url: string; + validUntil: string; +}; + +type ExpirationInputProps = { + urlExpiration: URLExpiration; + setURLExpiration: React.Dispatch>; +}; + +type CopyURLProps = { + urlDetails: React.MutableRefObject; +}; + +const ExpirationInput: React.FC = ({ + urlExpiration, + setURLExpiration, +}) => { + const { t } = useCustomTranslation(); + + const inputValue = urlExpiration.value; + const minValue = 1; + const maxValue = urlExpiration.unit === TimeUnits.Minutes ? 720 : 12; + + const onInputChange = (value: number) => + setURLExpiration({ ...urlExpiration, value }); + const onUnitChange = (unit: TimeUnits) => + setURLExpiration({ value: minValue, unit }); + + return ( + + onInputChange(inputValue - 1)} + onPlus={(): void => onInputChange(inputValue + 1)} + className="pf-v5-u-mr-xs" + /> + + + + + {t('Validity period of the presigned URL.')} + + + + + ); +}; + +const CopyURL: React.FC = ({ urlDetails }) => { + const { t } = useCustomTranslation(); + + return ( + +
+ {t('Valid until: ')} + {urlDetails.current.validUntil}{' '} +
+ + {urlDetails.current.url} + + +
+ ); +}; + +const PresignedURLModal: React.FC> = ({ + closeModal, + isOpen, + extraProps: { bucketName, object, noobaaS3 }, +}) => { + const { t } = useCustomTranslation(); + + const urlDetails = React.useRef({ url: null, validUntil: null }); + const [urlExpiration, setURLExpiration] = React.useState({ + value: 1, + unit: TimeUnits.Minutes, + }); + const [inProgress, setInProgress] = React.useState(false); + const [error, setError] = React.useState(); + + const objectName = getName(object); + const urlCreated = !!urlDetails.current.url; + + const onCopy = () => { + navigator.clipboard.writeText(urlDetails.current.url); + }; + + const onCreate = (event) => { + event.preventDefault(); + setInProgress(true); + + // in seconds + const expiresIn = + urlExpiration.value * + (urlExpiration.unit === TimeUnits.Minutes ? 60 : 3600); + + noobaaS3 + .getSignedUrl({ Bucket: bucketName, Key: objectName }, expiresIn) + .then((url) => { + urlDetails.current.url = url; + urlDetails.current.validUntil = DateTime.now() + .plus({ seconds: expiresIn }) + .toLocaleString(DateTime.DATETIME_FULL); + setInProgress(false); + }) + .catch((err) => { + setError(err); + setInProgress(false); + }); + }; + + return ( + + {t('Grant third-party access to an object for a limited time.')} +
+ } + variant={ModalVariant.medium} + className="object-presigned-url--height" + actions={[ + + + + + + , + ]} + > +
+ {t('Object: ')} + {objectName} +
+ + {!error && + (urlCreated ? ( + + ) : ( + + ))} + + ); +}; + +export default PresignedURLModal; diff --git a/packages/odf/modals/s3-browser/presigned-url/presigned-modal.scss b/packages/odf/modals/s3-browser/presigned-url/presigned-modal.scss new file mode 100644 index 000000000..aecc62f5a --- /dev/null +++ b/packages/odf/modals/s3-browser/presigned-url/presigned-modal.scss @@ -0,0 +1,3 @@ +.object-presigned-url--height { + height: 26rem; +} diff --git a/packages/shared/src/s3/commands.ts b/packages/shared/src/s3/commands.ts index 06c34ada8..96ba1131b 100644 --- a/packages/shared/src/s3/commands.ts +++ b/packages/shared/src/s3/commands.ts @@ -4,12 +4,15 @@ import { ListObjectsV2Command, CreateBucketCommand, PutBucketTaggingCommand, + GetObjectCommand, } from '@aws-sdk/client-s3'; +import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; import { CreateBucket, ListBuckets, ListObjectsV2, PutBucketTags, + GetSignedUrl, } from './types'; export class S3Commands { @@ -41,4 +44,7 @@ export class S3Commands { // Object command members listObjects: ListObjectsV2 = (input) => this.s3Client.send(new ListObjectsV2Command(input)); + + getSignedUrl: GetSignedUrl = (input, expiresIn) => + getSignedUrl(this.s3Client, new GetObjectCommand(input), { expiresIn }); } diff --git a/packages/shared/src/s3/types.ts b/packages/shared/src/s3/types.ts index 56ecb27fc..6844796b7 100644 --- a/packages/shared/src/s3/types.ts +++ b/packages/shared/src/s3/types.ts @@ -7,6 +7,7 @@ import { ListObjectsV2CommandOutput, PutBucketTaggingCommandInput, PutBucketTaggingCommandOutput, + GetObjectCommandInput, } from '@aws-sdk/client-s3'; // Bucket command types @@ -26,3 +27,8 @@ export type PutBucketTags = ( export type ListObjectsV2 = ( input: ListObjectsV2CommandInput ) => Promise; + +export type GetSignedUrl = ( + input: GetObjectCommandInput, + expiresIn: number +) => Promise; diff --git a/packages/shared/src/utils/common.ts b/packages/shared/src/utils/common.ts index cbf99deb8..a09aec3bc 100644 --- a/packages/shared/src/utils/common.ts +++ b/packages/shared/src/utils/common.ts @@ -172,3 +172,12 @@ export const parseOprMajorMinorVersion = (version: string): string => { export const getOprMajorMinorVersion = (operator: K8sResourceKind): string => parseOprMajorMinorVersion(getOprVersionFromCSV(operator)); + +export const numberInputOnChange = + (min: number, max: number, onChange: (value: number) => void) => + (input: React.FormEvent): void => { + const inputValue = +(input.target as HTMLInputElement)?.value; + if (!!min && inputValue < min) onChange(min); + else if (!!max && inputValue > max) onChange(max); + else onChange(inputValue); + }; diff --git a/yarn.lock b/yarn.lock index 955be995c..f3f6fc4f2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -524,6 +524,20 @@ "@smithy/util-middleware" "^3.0.3" tslib "^2.6.2" +"@aws-sdk/s3-request-presigner@3.614.0": + version "3.614.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.614.0.tgz#9987c353c39d9771a73230a4fe3bc5eacc389895" + integrity sha512-KCXFfnkW8QVtigvStA3zvIHBp/FmwwCBcMgp3WjJNNPVKit3RM70veAWJBZUghHmHtd9fTijO2uwzHtusjkyHw== + dependencies: + "@aws-sdk/signature-v4-multi-region" "3.614.0" + "@aws-sdk/types" "3.609.0" + "@aws-sdk/util-format-url" "3.609.0" + "@smithy/middleware-endpoint" "^3.0.5" + "@smithy/protocol-http" "^4.0.3" + "@smithy/smithy-client" "^3.1.7" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + "@aws-sdk/signature-v4-multi-region@3.614.0": version "3.614.0" resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.614.0.tgz#fabcef8b1c8ff052d48221dbff66390d6de89b4e" @@ -572,6 +586,16 @@ "@smithy/util-endpoints" "^2.0.5" tslib "^2.6.2" +"@aws-sdk/util-format-url@3.609.0": + version "3.609.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-format-url/-/util-format-url-3.609.0.tgz#f53907193bb636b52b61c81bbe6d7bd5ddc76c68" + integrity sha512-fuk29BI/oLQlJ7pfm6iJ4gkEpHdavffAALZwXh9eaY1vQ0ip0aKfRTiNudPoJjyyahnz5yJ1HkmlcDitlzsOrQ== + dependencies: + "@aws-sdk/types" "3.609.0" + "@smithy/querystring-builder" "^3.0.3" + "@smithy/types" "^3.3.0" + tslib "^2.6.2" + "@aws-sdk/util-locate-window@^3.0.0": version "3.568.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-locate-window/-/util-locate-window-3.568.0.tgz#2acc4b2236af0d7494f7e517401ba6b3c4af11ff" @@ -3062,6 +3086,11 @@ resolved "https://registry.yarnpkg.com/@types/lodash/-/lodash-4.14.191.tgz#09511e7f7cba275acd8b419ddac8da9a6a79e2fa" integrity sha512-BdZ5BCCvho3EIXw6wUCXHe7rS53AIDPLE+JzwgT+OsJk53oBfbSmZZ7CX4VaRoN78N+TJpFi9QPlfIVNmJYWxQ== +"@types/luxon@^3.3.1": + version "3.4.2" + resolved "https://registry.yarnpkg.com/@types/luxon/-/luxon-3.4.2.tgz#e4fc7214a420173cea47739c33cdf10874694db7" + integrity sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA== + "@types/mdast@^3.0.0": version "3.0.7" resolved "https://registry.yarnpkg.com/@types/mdast/-/mdast-3.0.7.tgz#cba63d0cc11eb1605cea5c0ad76e02684394166b" @@ -9350,6 +9379,11 @@ lru-cache@^6.0.0: dependencies: yallist "^4.0.0" +luxon@^3.3.0: + version "3.5.0" + resolved "https://registry.yarnpkg.com/luxon/-/luxon-3.5.0.tgz#6b6f65c5cd1d61d1fd19dbf07ee87a50bf4b8e20" + integrity sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ== + lz-string@^1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" From 607cd34b5e12720e5c7585d792d57728691683d7 Mon Sep 17 00:00:00 2001 From: SanjalKatiyar Date: Thu, 3 Oct 2024 10:57:35 +0530 Subject: [PATCH 13/22] Add object actions - download and preview --- locales/en/plugin__odf-console.json | 1 - .../download-and-preview.ts | 95 +++++++++++++++++++ .../s3-browser/objects-list/ObjectsList.tsx | 6 +- .../objects-list/table-components.tsx | 31 +++++- packages/shared/src/s3/commands.ts | 4 + packages/shared/src/s3/types.ts | 5 + 6 files changed, 131 insertions(+), 11 deletions(-) create mode 100644 packages/odf/components/s3-browser/download-and-preview/download-and-preview.ts diff --git a/locales/en/plugin__odf-console.json b/locales/en/plugin__odf-console.json index 9799752ac..501a48d05 100644 --- a/locales/en/plugin__odf-console.json +++ b/locales/en/plugin__odf-console.json @@ -1125,7 +1125,6 @@ "No tags are attached to this bucket.": "No tags are attached to this bucket.", "Add tag": "Add tag", "Value (optional)": "Value (optional)", - "Download objects": "Download objects", "Delete objects": "Delete objects", "Actions": "Actions", "Create folder": "Create folder", diff --git a/packages/odf/components/s3-browser/download-and-preview/download-and-preview.ts b/packages/odf/components/s3-browser/download-and-preview/download-and-preview.ts new file mode 100644 index 000000000..db0043058 --- /dev/null +++ b/packages/odf/components/s3-browser/download-and-preview/download-and-preview.ts @@ -0,0 +1,95 @@ +import { GetObjectCommandOutput } from '@aws-sdk/client-s3'; +import { S3Commands } from '@odf/shared/s3'; +import { getName } from '@odf/shared/selectors'; +import { ObjectCrFormat } from '../../../types'; + +type DownloadAndPreviewFunction = ( + bucketName: string, + object: ObjectCrFormat, + noobaaS3: S3Commands, + setDownloadAndPreview: React.Dispatch< + React.SetStateAction + > +) => void; + +type GetObjectURL = ( + bucketName: string, + object: ObjectCrFormat, + noobaaS3: S3Commands +) => Promise; + +export type DownloadAndPreviewState = { + isDownloading: boolean; + isPreviewing: boolean; +}; + +const getObjectURL: GetObjectURL = async (bucketName, object, noobaaS3) => { + const responseStream: GetObjectCommandOutput = await noobaaS3.getObject({ + Bucket: bucketName, + Key: getName(object), + }); + const blob = await new Response(responseStream.Body as ReadableStream).blob(); + + return window.URL.createObjectURL(blob); +}; + +export const onDownload: DownloadAndPreviewFunction = async ( + bucketName, + object, + noobaaS3, + setDownloadAndPreview +) => { + try { + setDownloadAndPreview((downloadAndPreview) => ({ + ...downloadAndPreview, + isDownloading: true, + })); + + const objectURL = await getObjectURL(bucketName, object, noobaaS3); + + // create a download element and trigger download + const downloadLink = document.createElement('a'); + downloadLink.href = objectURL; + downloadLink.download = getName(object); + document.body.appendChild(downloadLink); + downloadLink.click(); + document.body.removeChild(downloadLink); + + window.URL.revokeObjectURL(objectURL); + } catch (err) { + // eslint-disable-next-line no-console + console.error('Error fetching S3 object:', err); + } finally { + setDownloadAndPreview((downloadAndPreview) => ({ + ...downloadAndPreview, + isDownloading: false, + })); + } +}; + +export const onPreview: DownloadAndPreviewFunction = async ( + bucketName, + object, + noobaaS3, + setDownloadAndPreview +) => { + try { + setDownloadAndPreview((downloadAndPreview) => ({ + ...downloadAndPreview, + isPreviewing: true, + })); + + const objectURL = await getObjectURL(bucketName, object, noobaaS3); + + // open the object URL in a new browser tab + window.open(objectURL, '_blank'); + } catch (err) { + // eslint-disable-next-line no-console + console.error('Error fetching S3 object:', err); + } finally { + setDownloadAndPreview((downloadAndPreview) => ({ + ...downloadAndPreview, + isPreviewing: false, + })); + } +}; diff --git a/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx b/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx index 966f4704e..d113ef44b 100644 --- a/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx +++ b/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx @@ -114,11 +114,7 @@ const getBulkActionsItems = ( _launcher: LaunchModal, _selectedRows: unknown[] ): IAction[] => [ - // ToDo: add bulk download & delete options - { - title: t('Download objects'), - onClick: () => undefined, - }, + // ToDo: add bulk delete option { title: t('Delete objects'), onClick: () => undefined, diff --git a/packages/odf/components/s3-browser/objects-list/table-components.tsx b/packages/odf/components/s3-browser/objects-list/table-components.tsx index 0cc917a41..b23e32231 100644 --- a/packages/odf/components/s3-browser/objects-list/table-components.tsx +++ b/packages/odf/components/s3-browser/objects-list/table-components.tsx @@ -19,6 +19,11 @@ import { CubesIcon } from '@patternfly/react-icons'; import { ActionsColumn, Td, IAction } from '@patternfly/react-table'; import { BUCKETS_BASE_ROUTE, PREFIX } from '../../../constants'; import { ObjectCrFormat } from '../../../types'; +import { + DownloadAndPreviewState, + onDownload, + onPreview, +} from '../download-and-preview/download-and-preview'; const LazyPresignedURLModal = React.lazy( () => import('../../../modals/s3-browser/presigned-url/PresignedURLModal') @@ -37,16 +42,24 @@ const getInlineActionsItems = ( launcher: LaunchModal, bucketName: string, object: ObjectCrFormat, - noobaaS3: S3Commands + noobaaS3: S3Commands, + downloadAndPreview: DownloadAndPreviewState, + setDownloadAndPreview: React.Dispatch< + React.SetStateAction + > ): IAction[] => [ - // ToDo: add inline download, preview & delete options + // ToDo: add inline delete option { title: t('Download'), - onClick: () => undefined, + onClick: () => + onDownload(bucketName, object, noobaaS3, setDownloadAndPreview), + isDisabled: downloadAndPreview.isDownloading, }, { title: t('Preview'), - onClick: () => undefined, + onClick: () => + onPreview(bucketName, object, noobaaS3, setDownloadAndPreview), + isDisabled: downloadAndPreview.isPreviewing, }, { title: t('Share with presigned URL'), @@ -94,6 +107,12 @@ export const TableRow: React.FC> = ({ }) => { const { t } = useCustomTranslation(); + const [downloadAndPreview, setDownloadAndPreview] = + React.useState({ + isDownloading: false, + isPreviewing: false, + }); + const { launcher, bucketName, foldersPath, noobaaS3 } = extraProps; const isFolder = object.isFolder; const name = getName(object).replace(foldersPath, ''); @@ -132,7 +151,9 @@ export const TableRow: React.FC> = ({ launcher, bucketName, object, - noobaaS3 + noobaaS3, + downloadAndPreview, + setDownloadAndPreview )} /> )} diff --git a/packages/shared/src/s3/commands.ts b/packages/shared/src/s3/commands.ts index 96ba1131b..17461d097 100644 --- a/packages/shared/src/s3/commands.ts +++ b/packages/shared/src/s3/commands.ts @@ -13,6 +13,7 @@ import { ListObjectsV2, PutBucketTags, GetSignedUrl, + GetObject, } from './types'; export class S3Commands { @@ -47,4 +48,7 @@ export class S3Commands { getSignedUrl: GetSignedUrl = (input, expiresIn) => getSignedUrl(this.s3Client, new GetObjectCommand(input), { expiresIn }); + + getObject: GetObject = (input) => + this.s3Client.send(new GetObjectCommand(input)); } diff --git a/packages/shared/src/s3/types.ts b/packages/shared/src/s3/types.ts index 6844796b7..1a83fe614 100644 --- a/packages/shared/src/s3/types.ts +++ b/packages/shared/src/s3/types.ts @@ -8,6 +8,7 @@ import { PutBucketTaggingCommandInput, PutBucketTaggingCommandOutput, GetObjectCommandInput, + GetObjectCommandOutput, } from '@aws-sdk/client-s3'; // Bucket command types @@ -32,3 +33,7 @@ export type GetSignedUrl = ( input: GetObjectCommandInput, expiresIn: number ) => Promise; + +export type GetObject = ( + input: GetObjectCommandInput +) => Promise; From e83bb509957ab4932fc9424bd96db138dc76c399 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Alfonso=20Mart=C3=ADnez?= Date: Fri, 4 Oct 2024 10:46:42 +0200 Subject: [PATCH 14/22] Create S3 Bucket form cleanup --- .../create-bucket/CreateBucketForm.tsx | 22 +++++++++---------- 1 file changed, 10 insertions(+), 12 deletions(-) diff --git a/packages/odf/components/s3-browser/create-bucket/CreateBucketForm.tsx b/packages/odf/components/s3-browser/create-bucket/CreateBucketForm.tsx index 325934aa5..4a8755b39 100644 --- a/packages/odf/components/s3-browser/create-bucket/CreateBucketForm.tsx +++ b/packages/odf/components/s3-browser/create-bucket/CreateBucketForm.tsx @@ -18,7 +18,10 @@ import { useNavigate } from 'react-router-dom-v5-compat'; import { ActionGroup, Alert, + AlertVariant, Button, + ButtonType, + ButtonVariant, Form, FormGroup, } from '@patternfly/react-core'; @@ -51,18 +54,13 @@ const CreateBucketForm: React.FC<{}> = () => { const save = async (formData: FormData) => { setInProgress(true); - let bucketCreationError = ''; - setErrorMessage(bucketCreationError); + setErrorMessage(''); const { bucketName } = formData; try { await noobaaS3.createBucket({ Bucket: bucketName }); } catch ({ name, message }) { - bucketCreationError = `Error while creating bucket: ${name}: ${message}`; - } - - if (bucketCreationError) { + setErrorMessage(`Error while creating bucket: ${name}: ${message}`); setInProgress(false); - setErrorMessage(bucketCreationError); return; } @@ -140,7 +138,7 @@ const CreateBucketForm: React.FC<{}> = () => { {!isValid && isSubmitted && ( @@ -149,16 +147,16 @@ const CreateBucketForm: React.FC<{}> = () => { From c27a9c5466d6ce099b3171cf16192eb8b456d5e2 Mon Sep 17 00:00:00 2001 From: Bipul Adhikari Date: Fri, 4 Oct 2024 17:45:58 +0545 Subject: [PATCH 15/22] Reset radio button when Provider mode is selected from dropdown Signed-off-by: Bipul Adhikari --- .../backing-storage-step/backing-storage-step.tsx | 2 +- .../backing-storage-step/select-deployment.tsx | 8 +++++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/odf/components/create-storage-system/create-storage-system-steps/backing-storage-step/backing-storage-step.tsx b/packages/odf/components/create-storage-system/create-storage-system-steps/backing-storage-step/backing-storage-step.tsx index 08d8d9c32..8bed929d4 100644 --- a/packages/odf/components/create-storage-system/create-storage-system-steps/backing-storage-step/backing-storage-step.tsx +++ b/packages/odf/components/create-storage-system/create-storage-system-steps/backing-storage-step/backing-storage-step.tsx @@ -285,7 +285,7 @@ export const BackingStorage: React.FC = ({ }, }); } - }, [dispatch, allowedExternalStorage.length, hasOCS]); + }, [dispatch, allowedExternalStorage.length, hasOCS, isProviderModePresent]); React.useEffect(() => { /* diff --git a/packages/odf/components/create-storage-system/create-storage-system-steps/backing-storage-step/select-deployment.tsx b/packages/odf/components/create-storage-system/create-storage-system-steps/backing-storage-step/select-deployment.tsx index a7300ea6e..a73c2874d 100644 --- a/packages/odf/components/create-storage-system/create-storage-system-steps/backing-storage-step/select-deployment.tsx +++ b/packages/odf/components/create-storage-system/create-storage-system-steps/backing-storage-step/select-deployment.tsx @@ -1,6 +1,6 @@ import * as React from 'react'; import { FDF_FLAG } from '@odf/core/redux'; -import { DeploymentType } from '@odf/core/types'; +import { BackingStorageType, DeploymentType } from '@odf/core/types'; import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; import { useFlag } from '@openshift-console/dynamic-plugin-sdk'; import { @@ -49,6 +49,12 @@ export const SelectDeployment: React.FC = ({ // 'value' on SelectProps['onSelect'] is string hence does not match with payload of type "DeploymentType" payload: value as DeploymentType, }); + if (value === DeploymentType.PROVIDER_MODE) { + dispatch({ + type: 'backingStorage/setType', + payload: BackingStorageType.EXISTING, + }); + } setIsSelectOpen(false); }; From ac126839f410fce142f92097142c89a89708bc40 Mon Sep 17 00:00:00 2001 From: Malay Kumar Parida Date: Mon, 7 Oct 2024 10:38:28 +0000 Subject: [PATCH 16/22] Hide In-transit Encryption checkbox when MCG deployment mode is selected MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The encryption in transit option is based on Ceph’s MSGR v2 protocol and is meant for traffic interacting with & within the ceph cluster (client-osd, osd-osd). MCG is not covered by this, so it doesn't make sense to show the option when deployment mode is MCG Only. Signed-off-by: Malay Kumar Parida --- .../security-and-network-step/encryption.tsx | 30 ++++++++++--------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/packages/odf/components/create-storage-system/create-storage-system-steps/security-and-network-step/encryption.tsx b/packages/odf/components/create-storage-system/create-storage-system-steps/security-and-network-step/encryption.tsx index dc5a1454c..9c756dfea 100644 --- a/packages/odf/components/create-storage-system/create-storage-system-steps/security-and-network-step/encryption.tsx +++ b/packages/odf/components/create-storage-system/create-storage-system-steps/security-and-network-step/encryption.tsx @@ -282,20 +282,22 @@ export const Encryption: React.FC = ({ } /> )} - - handleInTransitEncryptionOnChange(checked) - } - /> + {!isMCG && ( + + handleInTransitEncryptionOnChange(checked) + } + /> + )} {!encryption.hasHandled && ( From 43d1d39aee6dfffaa3cd076521ae3b3460763ff5 Mon Sep 17 00:00:00 2001 From: SanjalKatiyar Date: Thu, 3 Oct 2024 19:00:00 +0530 Subject: [PATCH 17/22] Add object actions - create folder --- locales/en/plugin__odf-console.json | 7 + .../s3-browser/objects-list/ObjectsList.tsx | 22 ++- .../objects-list/table-components.tsx | 5 +- .../create-folder/CreateFolderModal.tsx | 186 ++++++++++++++++++ packages/odf/utils/s3-browser.ts | 8 + 5 files changed, 223 insertions(+), 5 deletions(-) create mode 100644 packages/odf/modals/s3-browser/create-folder/CreateFolderModal.tsx diff --git a/locales/en/plugin__odf-console.json b/locales/en/plugin__odf-console.json index 501a48d05..000cc179e 100644 --- a/locales/en/plugin__odf-console.json +++ b/locales/en/plugin__odf-console.json @@ -1297,6 +1297,13 @@ "and": "and", "GiB RAM": "GiB RAM", "Configure Performance": "Configure Performance", + "This name is already in use. Try using a different name for your folder.": "This name is already in use. Try using a different name for your folder.", + "The forward slash (\"/\") cannot be used.": "The forward slash (\"/\") cannot be used.", + "All characters are allowed except for the forward slash (\"/\").": "All characters are allowed except for the forward slash (\"/\").", + "A unique folder name is required. All characters are allowed except for the forward slash (\"/\").": "A unique folder name is required. All characters are allowed except for the forward slash (\"/\").", + "Organize objects within a bucket by creating virtual folders for easier management and navigation of objects.": "Organize objects within a bucket by creating virtual folders for easier management and navigation of objects.", + "Folders structure and group objects logically by using prefixes in object keys, without enforcing any physical hierarchy.": "Folders structure and group objects logically by using prefixes in object keys, without enforcing any physical hierarchy.", + "Folder name": "Folder name", "Expires after": "Expires after", "minus": "minus", "plus": "plus", diff --git a/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx b/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx index d113ef44b..a5ece1134 100644 --- a/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx +++ b/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx @@ -4,6 +4,7 @@ import { _Object as Content, CommonPrefix, } from '@aws-sdk/client-s3'; +import { S3Commands } from '@odf/shared/s3'; import { SelectableTable } from '@odf/shared/table'; import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; import { useModal } from '@openshift-console/dynamic-plugin-sdk'; @@ -36,6 +37,10 @@ import { EmptyPage, } from './table-components'; +const LazyCreateFolderModal = React.lazy( + () => import('../../../modals/s3-browser/create-folder/CreateFolderModal') +); + type PaginationProps = { onNext: () => void; onPrevious: () => void; @@ -47,6 +52,9 @@ type TableActionsProps = { launcher: LaunchModal; selectedRows: unknown[]; loadedWOError: boolean; + foldersPath: string; + bucketName: string; + noobaaS3: S3Commands; }; type ContinuationTokens = { @@ -171,6 +179,9 @@ const TableActions: React.FC = ({ disablePrevious, launcher, selectedRows, + foldersPath, + bucketName, + noobaaS3, }) => { const { t } = useCustomTranslation(); @@ -180,12 +191,16 @@ const TableActions: React.FC = ({
- {/* ToDo: add create folder option */} @@ -303,6 +318,9 @@ export const ObjectsList: React.FC<{}> = () => { disableNext={!continuationTokens.next || !loadedWOError} disablePrevious={!continuationTokens.current || !loadedWOError} launcher={launcher} + foldersPath={foldersPath} + bucketName={bucketName} + noobaaS3={noobaaS3} /> > = ({ const { launcher, bucketName, foldersPath, noobaaS3 } = extraProps; const isFolder = object.isFolder; const name = getName(object).replace(foldersPath, ''); - const prefix = !!foldersPath - ? encodeURIComponent(foldersPath + name) - : encodeURIComponent(name); + const prefix = getEncodedPrefix(name, foldersPath); const columnNames = getColumnNames(t); diff --git a/packages/odf/modals/s3-browser/create-folder/CreateFolderModal.tsx b/packages/odf/modals/s3-browser/create-folder/CreateFolderModal.tsx new file mode 100644 index 000000000..a5b40550c --- /dev/null +++ b/packages/odf/modals/s3-browser/create-folder/CreateFolderModal.tsx @@ -0,0 +1,186 @@ +import * as React from 'react'; +import { ButtonBar } from '@odf/shared/generic/ButtonBar'; +import { CommonModalProps } from '@odf/shared/modals'; +import { S3Commands } from '@odf/shared/s3'; +import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; +import { TFunction } from 'i18next'; +import { useNavigate } from 'react-router-dom-v5-compat'; +import { + Modal, + ModalVariant, + Button, + ButtonVariant, + Alert, + AlertVariant, + TextInput, + TextInputTypes, + FormGroup, + FormHelperText, + HelperText, + HelperTextItem, + ValidatedOptions, +} from '@patternfly/react-core'; +import { BUCKETS_BASE_ROUTE, DELIMITER, PREFIX } from '../../../constants'; +import { getPrefix, getEncodedPrefix } from '../../../utils'; + +type CreateFolderModalProps = { + foldersPath: string; + bucketName: string; + noobaaS3: S3Commands; +}; + +const getValidations = ( + isExisting: boolean, + containsForwardSlash: boolean, + folderName: string, + t: TFunction +): [ValidatedOptions, string] => { + if (isExisting) + return [ + ValidatedOptions.error, + t( + 'This name is already in use. Try using a different name for your folder.' + ), + ]; + else if (containsForwardSlash) + return [ + ValidatedOptions.error, + t('The forward slash ("/") cannot be used.'), + ]; + else if (!!folderName) + return [ + ValidatedOptions.success, + t('All characters are allowed except for the forward slash ("/").'), + ]; + else + return [ + ValidatedOptions.default, + t( + 'A unique folder name is required. All characters are allowed except for the forward slash ("/").' + ), + ]; +}; + +const CreateFolderModal: React.FC> = ({ + closeModal, + isOpen, + extraProps: { foldersPath, bucketName, noobaaS3 }, +}) => { + const { t } = useCustomTranslation(); + + const navigate = useNavigate(); + + const [folderName, setFolderName] = React.useState(''); + const [inProgress, setInProgress] = React.useState(false); + const [isExisting, setIsExisting] = React.useState(false); + const [error, setError] = React.useState(); + + const containsForwardSlash = folderName.includes(DELIMITER); + const [validationVariant, helperText] = getValidations( + isExisting, + containsForwardSlash, + folderName, + t + ); + + const onCreate = async (event) => { + event.preventDefault(); + setInProgress(true); + + try { + const folderNameWDelimiter = folderName + DELIMITER; + const data = await noobaaS3.listObjects({ + Bucket: bucketName, + MaxKeys: 1, + Delimiter: DELIMITER, + Prefix: getPrefix(folderNameWDelimiter, foldersPath), + }); + + const doesFolderAlreadyExist = + !!data?.Contents?.length || !!data?.CommonPrefixes?.length; + + if (doesFolderAlreadyExist) { + setInProgress(false); + setIsExisting(true); + } else { + const prefix = getEncodedPrefix(folderNameWDelimiter, foldersPath); + navigate(`${BUCKETS_BASE_ROUTE}/${bucketName}?${PREFIX}=${prefix}`); + closeModal(); + } + } catch (err) { + setInProgress(false); + setError(err); + } + }; + + return ( + + {t( + 'Organize objects within a bucket by creating virtual folders for easier management and navigation of objects.' + )} +
+ } + variant={ModalVariant.medium} + actions={[ + + + + + + , + ]} + > + + + { + setFolderName(value); + setIsExisting(false); + }} + isRequired + validated={validationVariant} + type={TextInputTypes.text} + /> + + + + {helperText} + + + + + + ); +}; + +export default CreateFolderModal; diff --git a/packages/odf/utils/s3-browser.ts b/packages/odf/utils/s3-browser.ts index a30bbe731..5f9ac5636 100644 --- a/packages/odf/utils/s3-browser.ts +++ b/packages/odf/utils/s3-browser.ts @@ -48,6 +48,14 @@ export const getBreadcrumbs = ( export const getPath = (bucketName: string, foldersPath: string) => !foldersPath ? bucketName + DELIMITER : bucketName + DELIMITER + foldersPath; +export const getPrefix = (name: string, foldersPath: string) => + !!foldersPath ? foldersPath + name : name; + +export const getEncodedPrefix = (name: string, foldersPath: string) => + !!foldersPath + ? encodeURIComponent(foldersPath + name) + : encodeURIComponent(name); + export const convertObjectsDataToCrFormat = ( objectData: Content | CommonPrefix, isFolder: boolean, From dd3dc119c8dcd70fb7f5ae105b05b099c56b47e0 Mon Sep 17 00:00:00 2001 From: Bipul Adhikari Date: Tue, 8 Oct 2024 13:58:07 +0545 Subject: [PATCH 18/22] Fetch external cluster python script from Rook CM Signed-off-by: Bipul Adhikari --- .../system-connection-details.tsx | 36 ++++++++++--------- packages/shared/src/constants/common.ts | 1 - 2 files changed, 19 insertions(+), 18 deletions(-) diff --git a/packages/odf/components/create-storage-system/external-ceph-storage/system-connection-details.tsx b/packages/odf/components/create-storage-system/external-ceph-storage/system-connection-details.tsx index 6fad5952d..447bf2ebe 100644 --- a/packages/odf/components/create-storage-system/external-ceph-storage/system-connection-details.tsx +++ b/packages/odf/components/create-storage-system/external-ceph-storage/system-connection-details.tsx @@ -16,12 +16,17 @@ import { StorageClassComponentProps as ExternalComponentProps, StorageClassWizardStepExtensionProps as ExternalStorage, } from '@odf/odf-plugin-sdk/extensions'; -import { ROOK_CEPH_OPERATOR, OCS_OPERATOR } from '@odf/shared/constants'; +import { OCS_OPERATOR } from '@odf/shared/constants'; import { useK8sGet } from '@odf/shared/hooks/k8s-get-hook'; import { useFetchCsv } from '@odf/shared/hooks/use-fetch-csv'; -import { PodModel, SecretModel, StorageClusterModel } from '@odf/shared/models'; +import { + ConfigMapModel, + PodModel, + SecretModel, + StorageClusterModel, +} from '@odf/shared/models'; import { getAnnotations } from '@odf/shared/selectors'; -import { ListKind, PodKind } from '@odf/shared/types'; +import { ConfigMapKind, ListKind, PodKind } from '@odf/shared/types'; import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; import { getAPIVersionForModel } from '@odf/shared/utils'; import { K8sKind } from '@openshift-console/dynamic-plugin-sdk/lib/api/common-types'; @@ -50,6 +55,8 @@ export const getValidationKeys = ( return { plainKeys, secretKeys: secrets }; }; +const ROOK_EXTERNAL_SCRIPT_CM = 'rook-ceph-external-cluster-script-config'; + export const ConnectionDetails: React.FC> = ({ setFormState, formState, @@ -61,28 +68,23 @@ export const ConnectionDetails: React.FC> = ({ const [pods, podsLoaded, podsLoadError] = useK8sGet>(PodModel); - // From 4.16 onwards Rook will have separate CSV & Subscription. - const [rookCSV, rookCSVLoaded, rookCSVError] = useFetchCsv({ - specName: ROOK_CEPH_OPERATOR, - namespace: odfNamespace, - startPollingInstantly: isNsSafe, - }); - const [ocsCSV, ocsCSVLoaded, ocsCSVError] = useFetchCsv({ specName: OCS_OPERATOR, namespace: odfNamespace, startPollingInstantly: isNsSafe, }); + const [cm, cmLoaded, cmLoadError] = useK8sGet( + ConfigMapModel, + ROOK_EXTERNAL_SCRIPT_CM, + odfNamespace + ); + const { fileName, fileData, errorMessage, isLoading } = formState; - const rookAnnotations = getAnnotations(rookCSV, {}); + const downloadFile = createDownloadFile(cm?.data?.script); const ocsAnnotations = getAnnotations(ocsCSV, {}); - const downloadFile = createDownloadFile( - rookAnnotations?.['externalClusterScript'] - ); - const handleDataChange: FileUploadProps['onDataChange'] = ( _event, fData: string @@ -116,8 +118,8 @@ export const ConnectionDetails: React.FC> = ({ return (
Date: Tue, 8 Oct 2024 17:13:44 +0530 Subject: [PATCH 19/22] Fix bundle analyzer script Signed-off-by: Gowtham Shanmugasundaram --- .eslintrc.js | 1 + analyzeTest.ts | 15 ++++++++------- package.json | 1 + yarn.lock | 5 +++++ 4 files changed, 15 insertions(+), 7 deletions(-) diff --git a/.eslintrc.js b/.eslintrc.js index 04c0c9de1..ee8c53fce 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -86,6 +86,7 @@ module.exports = { '**/*.spec.tsx', './jest/setup.ts', './cypress/**', + './analyzeTest.ts', ], optionalDependencies: false, peerDependencies: false, diff --git a/analyzeTest.ts b/analyzeTest.ts index b91169808..adbae2323 100644 --- a/analyzeTest.ts +++ b/analyzeTest.ts @@ -1,4 +1,5 @@ import * as fs from 'fs'; +import { parseChunked } from '@discoveryjs/json-ext'; const pluginName = process.env.PLUGIN; const MAX_ASSET_SIZE = 17; //17 MiB @@ -12,17 +13,17 @@ const stringifyMiB = (value: ReturnType): string => const getParsedStatFile = () => { const filePath = getStatsFilePath(); - const statsFile = fs.readFileSync(filePath, 'utf-8'); - return JSON.parse(statsFile); + + return parseChunked(fs.createReadStream(filePath, { encoding: 'utf8' })); }; type BundleDataMap = Record; // [Valid Bundles, Violating Bunldes] -type GetBundleInformation = () => [BundleDataMap, BundleDataMap]; +type GetBundleInformation = () => Promise<[BundleDataMap, BundleDataMap]>; -const getBundleInformation: GetBundleInformation = () => { - const statsData = getParsedStatFile(); +const getBundleInformation: GetBundleInformation = async () => { + const statsData = await getParsedStatFile(); const validAssets = {}; const violatingAssets = {}; @@ -39,8 +40,8 @@ const getBundleInformation: GetBundleInformation = () => { return [validAssets, violatingAssets]; }; -const validateBuild = () => { - const [validAssets, violatingAssets] = getBundleInformation(); +const validateBuild = async () => { + const [validAssets, violatingAssets] = await getBundleInformation(); if (Object.keys(violatingAssets).length > 0) { // eslint-disable-next-line no-console console.error('Assets are larger than expected', violatingAssets); diff --git a/package.json b/package.json index 9ad42f1b4..7db94177e 100644 --- a/package.json +++ b/package.json @@ -128,6 +128,7 @@ }, "devDependencies": { "@cypress/webpack-preprocessor": "^5.9.1", + "@discoveryjs/json-ext": "0.6.1", "@swc/core": "1.3.19", "@swc/jest": "^0.2.23", "@testing-library/jest-dom": "^6.4.5", diff --git a/yarn.lock b/yarn.lock index f3f6fc4f2..58d939acb 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1278,6 +1278,11 @@ resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz#1d572bfbbe14b7704e0ba0f39b74815b84870d70" integrity sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw== +"@discoveryjs/json-ext@0.6.1": + version "0.6.1" + resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.6.1.tgz#593da7a17a31a72a874e313677183334a49b01c9" + integrity sha512-boghen8F0Q8D+0/Q1/1r6DUEieUJ8w2a1gIknExMSHBsJFOr2+0KUfHiVYBvucPwl3+RU5PFBK833FjFCh3BhA== + "@discoveryjs/json-ext@^0.5.0": version "0.5.3" resolved "https://registry.yarnpkg.com/@discoveryjs/json-ext/-/json-ext-0.5.3.tgz#90420f9f9c6d3987f176a19a7d8e764271a2f55d" From 74a0345586f0e1880f228c9ef55c4cf82038bdbd Mon Sep 17 00:00:00 2001 From: Bipul Adhikari Date: Tue, 8 Oct 2024 13:09:46 +0545 Subject: [PATCH 20/22] Adds support for new volume modes in IBM flashsystem Signed-off-by: Bipul Adhikari --- locales/en/plugin__odf-console.json | 6 ++++ packages/ibm/system-connection-details.tsx | 35 ++++++++++++++++++---- 2 files changed, 36 insertions(+), 5 deletions(-) diff --git a/locales/en/plugin__odf-console.json b/locales/en/plugin__odf-console.json index 501a48d05..d2caac1ed 100644 --- a/locales/en/plugin__odf-console.json +++ b/locales/en/plugin__odf-console.json @@ -19,6 +19,12 @@ "Status": "Status", "Storage Client": "Storage Client", "Overview": "Overview", + "Thick": "Thick", + "Thin": "Thin", + "Compressed": "Compressed", + "Deduplicated": "Deduplicated", + "Deduplicated thin": "Deduplicated thin", + "Deduplicated compressed": "Deduplicated compressed", "IP address": "IP address", "Rest API IP address of IBM FlashSystem.": "Rest API IP address of IBM FlashSystem.", "Username": "Username", diff --git a/packages/ibm/system-connection-details.tsx b/packages/ibm/system-connection-details.tsx index 837fc1ef3..697cda563 100644 --- a/packages/ibm/system-connection-details.tsx +++ b/packages/ibm/system-connection-details.tsx @@ -16,6 +16,8 @@ import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; import { getAPIVersionForModel, isValidIP } from '@odf/shared/utils'; import { k8sGet } from '@openshift-console/dynamic-plugin-sdk'; import { Select, SelectOption } from '@patternfly/react-core/deprecated'; +import { TFunction } from 'i18next'; +import * as _ from 'lodash-es'; import * as Yup from 'yup'; import { FormGroup, @@ -34,7 +36,26 @@ import { getFlashSystemSecretName, } from './utils'; -const VOLUME_MODES = ['thick', 'thin']; +const VOLUME_MODES_VALUES = [ + 'thick', + 'thin', + 'compressed', + 'deduplicated', + 'dedup_thin', + 'dedup_compressed', +]; + +const VOLUME_MODES_TEXT = (t: TFunction) => [ + t('Thick'), + t('Thin'), + t('Compressed'), + t('Deduplicated'), + t('Deduplicated thin'), + t('Deduplicated compressed'), +]; + +const volumeModeObject = (t: TFunction) => + _.zipObject(VOLUME_MODES_TEXT(t), VOLUME_MODES_VALUES); export const FlashSystemConnectionDetails: React.FC< ExternalComponentProps @@ -45,9 +66,13 @@ export const FlashSystemConnectionDetails: React.FC< const onToggle = () => setIsOpen(!isOpen); + const volumeMapper = volumeModeObject(t); + const inverseVolumeMapper = _.invert(volumeMapper); + const onModeSelect = (event, value) => { event.preventDefault(); - setFormState('volmode', value); + const volumeMode = volumeMapper[value]; + setFormState('volmode', volumeMode); setIsOpen(!isOpen); }; @@ -160,13 +185,13 @@ export const FlashSystemConnectionDetails: React.FC< From a768cd01d9ed919e5cc7d31ebec04b804d7a83a5 Mon Sep 17 00:00:00 2001 From: SanjalKatiyar Date: Mon, 7 Oct 2024 19:45:56 +0530 Subject: [PATCH 21/22] Add object actions - delete objects --- locales/en/plugin__odf-console.json | 15 ++ .../s3-browser/objects-list/ObjectsList.tsx | 209 ++++++++++++++- .../objects-list/table-components.tsx | 40 ++- .../delete-objects/DeleteObjectsModal.tsx | 242 ++++++++++++++++++ .../delete-objects/DeleteObjectsSummary.tsx | 177 +++++++++++++ .../delete-objects/LazyDeleteModals.ts | 9 + .../delete-objects/delete-objects.scss | 8 + packages/odf/utils/s3-browser.ts | 9 + packages/shared/src/list-page/ListFilter.tsx | 58 +++++ packages/shared/src/list-page/index.ts | 1 + .../src/list-page/paginated-list-page.tsx | 40 ++- packages/shared/src/s3/commands.ts | 5 + packages/shared/src/s3/types.ts | 6 + packages/shared/src/status/icons.tsx | 11 + .../shared/src/table/composable-table.tsx | 8 +- 15 files changed, 804 insertions(+), 34 deletions(-) create mode 100644 packages/odf/modals/s3-browser/delete-objects/DeleteObjectsModal.tsx create mode 100644 packages/odf/modals/s3-browser/delete-objects/DeleteObjectsSummary.tsx create mode 100644 packages/odf/modals/s3-browser/delete-objects/LazyDeleteModals.ts create mode 100644 packages/odf/modals/s3-browser/delete-objects/delete-objects.scss create mode 100644 packages/shared/src/list-page/ListFilter.tsx diff --git a/locales/en/plugin__odf-console.json b/locales/en/plugin__odf-console.json index 000cc179e..aa094ef12 100644 --- a/locales/en/plugin__odf-console.json +++ b/locales/en/plugin__odf-console.json @@ -1128,6 +1128,12 @@ "Delete objects": "Delete objects", "Actions": "Actions", "Create folder": "Create folder", + "Failed to delete {{ errorCount }} object from the bucket. View deletion summary for details.": "Failed to delete {{ errorCount }} object from the bucket. View deletion summary for details.", + "Failed to delete {{ errorCount }} objects from the bucket. View deletion summary for details.": "Failed to delete {{ errorCount }} objects from the bucket. View deletion summary for details.", + "View failed objects": "View failed objects", + "Successfully deleted {{ successCount }} object from the bucket.": "Successfully deleted {{ successCount }} object from the bucket.", + "Successfully deleted {{ successCount }} objects from the bucket.": "Successfully deleted {{ successCount }} objects from the bucket.", + "Objects are the fundamental entities stored in buckets.": "Objects are the fundamental entities stored in buckets.", "Size": "Size", "Last modified": "Last modified", "Download": "Download", @@ -1304,6 +1310,14 @@ "Organize objects within a bucket by creating virtual folders for easier management and navigation of objects.": "Organize objects within a bucket by creating virtual folders for easier management and navigation of objects.", "Folders structure and group objects logically by using prefixes in object keys, without enforcing any physical hierarchy.": "Folders structure and group objects logically by using prefixes in object keys, without enforcing any physical hierarchy.", "Folder name": "Folder name", + "<0>To confirm deletion, type <1>{{delete}} in the text input field.": "<0>To confirm deletion, type <1>{{delete}} in the text input field.", + "Object name": "Object name", + "Delete object?": "Delete object?", + "Deleted objects will no longer be visible in the bucket. If versioning is enabled a delete marker is created, you can recover object from previous versions. For unversioned objects, deletion is final and cannot be undone.": "Deleted objects will no longer be visible in the bucket. If versioning is enabled a delete marker is created, you can recover object from previous versions. For unversioned objects, deletion is final and cannot be undone.", + "Delete object": "Delete object", + "Delete status": "Delete status", + "Failed": "Failed", + "Object delete summary": "Object delete summary", "Expires after": "Expires after", "minus": "minus", "plus": "plus", @@ -1415,6 +1429,7 @@ "Values": "Values", "Select the values": "Select the values", "Add label expression": "Add label expression", + "Search by name...": "Search by name...", "Delete {{kind}}?": "Delete {{kind}}?", "Are you sure you want to delete <2>{{resourceName}} in namespace <6>{{namespace}}?": "Are you sure you want to delete <2>{{resourceName}} in namespace <6>{{namespace}}?", "Are you sure you want to delete <2>{{resourceName}}?": "Are you sure you want to delete <2>{{resourceName}}?", diff --git a/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx b/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx index a5ece1134..2cf0b796a 100644 --- a/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx +++ b/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx @@ -1,9 +1,11 @@ import * as React from 'react'; import { ListObjectsV2CommandOutput, + DeleteObjectsCommandOutput, _Object as Content, CommonPrefix, } from '@aws-sdk/client-s3'; +import { pluralize } from '@odf/core/components/utils'; import { S3Commands } from '@odf/shared/s3'; import { SelectableTable } from '@odf/shared/table'; import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; @@ -19,6 +21,10 @@ import { Level, LevelItem, MenuToggle, + Alert, + AlertVariant, + AlertActionCloseButton, + AlertActionLink, } from '@patternfly/react-core'; import { AngleLeftIcon, AngleRightIcon } from '@patternfly/react-icons'; import { @@ -27,6 +33,14 @@ import { CustomActionsToggleProps, } from '@patternfly/react-table'; import { LIST_OBJECTS, DELIMITER, MAX_KEYS, PREFIX } from '../../../constants'; +import { + ObjectsDeleteResponse, + SetObjectsDeleteResponse, +} from '../../../modals/s3-browser/delete-objects/DeleteObjectsModal'; +import { + LazyDeleteObjectsModal, + LazyDeleteObjectsSummary, +} from '../../../modals/s3-browser/delete-objects/LazyDeleteModals'; import { ObjectCrFormat } from '../../../types'; import { getPath, convertObjectsDataToCrFormat } from '../../../utils'; import { NoobaaS3Context } from '../noobaa-context'; @@ -50,11 +64,18 @@ type PaginationProps = { type TableActionsProps = { launcher: LaunchModal; - selectedRows: unknown[]; + selectedRows: ObjectCrFormat[]; loadedWOError: boolean; foldersPath: string; bucketName: string; noobaaS3: S3Commands; + setDeleteResponse: SetObjectsDeleteResponse; + refreshTokens: () => Promise; +}; + +type DeletionAlertsProps = { + deleteResponse: ObjectsDeleteResponse; + foldersPath: string; }; type ContinuationTokens = { @@ -70,6 +91,7 @@ type Trigger = TriggerWithOptionsArgs< string >; +// for navigating (next/previous) through objects list const continuationTokensSetter = ( setContinuationTokens: React.Dispatch< React.SetStateAction @@ -117,15 +139,53 @@ const fetchObjects = async ( } }; +// for refreshing (re-feching) objects from start, once state of bucket has changed (objects added/deleted) +const continuationTokensRefresher = async ( + setContinuationTokens: React.Dispatch< + React.SetStateAction + >, + trigger: Trigger, + setSelectedRows: React.Dispatch> +) => { + try { + const response: ListObjectsV2CommandOutput = await trigger(); + setContinuationTokens({ + previous: [''], + current: '', + next: response.NextContinuationToken, + }); + setSelectedRows([]); + } catch (err) { + // no need to handle any error here, use "error" object directly from the "useSWRMutation" hook + // eslint-disable-next-line no-console + console.error(err); + } +}; + const getBulkActionsItems = ( t: TFunction, - _launcher: LaunchModal, - _selectedRows: unknown[] + launcher: LaunchModal, + selectedRows: ObjectCrFormat[], + foldersPath: string, + bucketName: string, + noobaaS3: S3Commands, + setDeleteResponse: SetObjectsDeleteResponse, + refreshTokens: () => Promise ): IAction[] => [ - // ToDo: add bulk delete option { title: t('Delete objects'), - onClick: () => undefined, + onClick: () => + launcher(LazyDeleteObjectsModal, { + isOpen: true, + extraProps: { + foldersPath, + bucketName, + objects: selectedRows, + noobaaS3, + setDeleteResponse, + refreshTokens, + }, + }), }, ]; @@ -182,6 +242,8 @@ const TableActions: React.FC = ({ foldersPath, bucketName, noobaaS3, + setDeleteResponse, + refreshTokens, }) => { const { t } = useCustomTranslation(); @@ -193,7 +255,7 @@ const TableActions: React.FC = ({
@@ -225,6 +296,94 @@ const TableActions: React.FC = ({ ); }; +const DeletionAlerts: React.FC = ({ + deleteResponse, + foldersPath, +}) => { + const { t } = useCustomTranslation(); + + const launcher = useModal(); + + const [errorResponse, setErrorResponse] = React.useState< + DeleteObjectsCommandOutput['Errors'] + >([]); + const [successResponse, setSuccessResponse] = React.useState< + DeleteObjectsCommandOutput['Deleted'] + >([]); + + React.useEffect(() => { + setErrorResponse(deleteResponse?.deleteResponse?.Errors || []); + setSuccessResponse(deleteResponse?.deleteResponse?.Deleted || []); + }, [deleteResponse]); + + const errorCount = errorResponse.length; + const successCount = successResponse.length; + return ( + <> + {!!errorCount && ( + setErrorResponse([])} /> + } + actionLinks={ + + launcher(LazyDeleteObjectsSummary, { + isOpen: true, + extraProps: { + foldersPath, + errorResponse, + selectedObjects: deleteResponse.selectedObjects, + }, + }) + } + > + {t('View failed objects')} + + } + /> + )} + {!!successCount && ( + setSuccessResponse([])} /> + } + /> + )} + + ); +}; + export const ObjectsList: React.FC<{}> = () => { const { t } = useCustomTranslation(); @@ -259,6 +418,11 @@ export const ObjectsList: React.FC<{}> = () => { next: '', }); const [selectedRows, setSelectedRows] = React.useState([]); + const [deleteResponse, setDeleteResponse] = + React.useState({ + selectedObjects: [] as ObjectCrFormat[], + deleteResponse: {} as DeleteObjectsCommandOutput, + }); const structuredObjects: ObjectCrFormat[] = React.useMemo(() => { const objects: ObjectCrFormat[] = []; @@ -277,16 +441,29 @@ export const ObjectsList: React.FC<{}> = () => { return objects; }, [data, loadedWOError, t]); + const refreshTokens = () => + continuationTokensRefresher( + setContinuationTokens, + trigger, + setSelectedRows + ); + // initial fetch on first mount or on route update (drilling in/out of the folder view) React.useEffect(() => { - fetchObjects(setContinuationTokens, trigger, true, setSelectedRows); + refreshTokens(); // eslint-disable-next-line react-hooks/exhaustive-deps }, [foldersPath]); return (
+

+ {t('Objects are the fundamental entities stored in buckets.')} +

+ {/* ToDo: add upload objects option */} - { if (!!continuationTokens.next && loadedWOError) @@ -321,8 +498,9 @@ export const ObjectsList: React.FC<{}> = () => { foldersPath={foldersPath} bucketName={bucketName} noobaaS3={noobaaS3} + setDeleteResponse={setDeleteResponse} + refreshTokens={refreshTokens} /> - = () => { loaded={!isMutating} loadError={error} isRowSelectable={isRowSelectable} - extraProps={{ launcher, bucketName, foldersPath, noobaaS3 }} + extraProps={{ + launcher, + bucketName, + foldersPath, + noobaaS3, + setDeleteResponse, + refreshTokens, + }} emptyRowMessage={EmptyPage} />
diff --git a/packages/odf/components/s3-browser/objects-list/table-components.tsx b/packages/odf/components/s3-browser/objects-list/table-components.tsx index 6d898a505..439fe215b 100644 --- a/packages/odf/components/s3-browser/objects-list/table-components.tsx +++ b/packages/odf/components/s3-browser/objects-list/table-components.tsx @@ -1,6 +1,5 @@ import * as React from 'react'; import { S3Commands } from '@odf/shared/s3'; -import { getName } from '@odf/shared/selectors'; import { RowComponentType } from '@odf/shared/table'; import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; import { sortRows } from '@odf/shared/utils'; @@ -18,8 +17,10 @@ import { import { CubesIcon } from '@patternfly/react-icons'; import { ActionsColumn, Td, IAction } from '@patternfly/react-table'; import { BUCKETS_BASE_ROUTE, PREFIX } from '../../../constants'; +import { SetObjectsDeleteResponse } from '../../../modals/s3-browser/delete-objects/DeleteObjectsModal'; +import { LazyDeleteObjectsModal } from '../../../modals/s3-browser/delete-objects/LazyDeleteModals'; import { ObjectCrFormat } from '../../../types'; -import { getEncodedPrefix } from '../../../utils'; +import { getEncodedPrefix, replacePathFromName } from '../../../utils'; import { DownloadAndPreviewState, onDownload, @@ -47,9 +48,11 @@ const getInlineActionsItems = ( downloadAndPreview: DownloadAndPreviewState, setDownloadAndPreview: React.Dispatch< React.SetStateAction - > + >, + foldersPath: string, + setDeleteResponse: SetObjectsDeleteResponse, + refreshTokens: () => Promise ): IAction[] => [ - // ToDo: add inline delete option { title: t('Download'), onClick: () => @@ -72,7 +75,18 @@ const getInlineActionsItems = ( }, { title: t('Delete'), - onClick: () => undefined, + onClick: () => + launcher(LazyDeleteObjectsModal, { + isOpen: true, + extraProps: { + foldersPath, + bucketName, + objects: [object], + noobaaS3, + setDeleteResponse, + refreshTokens, + }, + }), }, ]; @@ -114,9 +128,16 @@ export const TableRow: React.FC> = ({ isPreviewing: false, }); - const { launcher, bucketName, foldersPath, noobaaS3 } = extraProps; + const { + launcher, + bucketName, + foldersPath, + noobaaS3, + setDeleteResponse, + refreshTokens, + } = extraProps; const isFolder = object.isFolder; - const name = getName(object).replace(foldersPath, ''); + const name = replacePathFromName(object, foldersPath); const prefix = getEncodedPrefix(name, foldersPath); const columnNames = getColumnNames(t); @@ -152,7 +173,10 @@ export const TableRow: React.FC> = ({ object, noobaaS3, downloadAndPreview, - setDownloadAndPreview + setDownloadAndPreview, + foldersPath, + setDeleteResponse, + refreshTokens )} /> )} diff --git a/packages/odf/modals/s3-browser/delete-objects/DeleteObjectsModal.tsx b/packages/odf/modals/s3-browser/delete-objects/DeleteObjectsModal.tsx new file mode 100644 index 000000000..5202b331a --- /dev/null +++ b/packages/odf/modals/s3-browser/delete-objects/DeleteObjectsModal.tsx @@ -0,0 +1,242 @@ +import * as React from 'react'; +import { + DeleteObjectsCommandOutput, + ObjectIdentifier, +} from '@aws-sdk/client-s3'; +import { ButtonBar } from '@odf/shared/generic/ButtonBar'; +import { PaginatedListPage, ListFilter } from '@odf/shared/list-page'; +import { CommonModalProps } from '@odf/shared/modals'; +import { S3Commands } from '@odf/shared/s3'; +import { getName } from '@odf/shared/selectors'; +import { RowComponentType } from '@odf/shared/table'; +import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; +import { sortRows } from '@odf/shared/utils'; +import { TFunction } from 'i18next'; +import { Trans } from 'react-i18next'; +import { + Modal, + ModalVariant, + Button, + ButtonVariant, + TextInput, + TextInputTypes, + FormGroup, + PaginationVariant, +} from '@patternfly/react-core'; +import { Tr, Td, TableVariant } from '@patternfly/react-table'; +import { ObjectCrFormat } from '../../../types'; +import { replacePathFromName } from '../../../utils'; +import './delete-objects.scss'; + +const DELETE = 'delete'; + +export type ObjectsDeleteResponse = { + selectedObjects: ObjectCrFormat[]; + deleteResponse: DeleteObjectsCommandOutput; +}; + +export type SetObjectsDeleteResponse = React.Dispatch< + React.SetStateAction +>; + +type DeleteObjectsModalProps = { + foldersPath: string; + bucketName: string; + noobaaS3: S3Commands; + objects: ObjectCrFormat[]; + setDeleteResponse: SetObjectsDeleteResponse; + refreshTokens: () => Promise; +}; + +const getTextInputLabel = (t: TFunction) => ( + + + To confirm deletion, type {{ delete: DELETE }} in the text input + field. + + +); + +const getColumnNames = (t: TFunction) => [ + t('Object name'), + t('Size'), + t('Last modified'), +]; + +const getHeaderColumns = (t: TFunction) => { + const columnNames = getColumnNames(t); + return [ + { + columnName: columnNames[0], + sortFunction: (a, b, c) => sortRows(a, b, c, 'metadata.name'), + }, + { + columnName: columnNames[1], + sortFunction: (a, b, c) => sortRows(a, b, c, 'apiResponse.size'), + }, + { + columnName: columnNames[2], + sortFunction: (a, b, c) => sortRows(a, b, c, 'apiResponse.lastModified'), + }, + ]; +}; + +const DeleteObjectsTableRow: React.FC> = ({ + row: object, + extraProps, +}) => { + const { t } = useCustomTranslation(); + + const { foldersPath } = extraProps; + const name = replacePathFromName(object, foldersPath); + + const columnNames = getColumnNames(t); + + return ( + + + {name} + + + {object.apiResponse.size} + + + {object.apiResponse.lastModified} + + + ); +}; + +const DeleteObjectsModal: React.FC> = + ({ + closeModal, + isOpen, + extraProps: { + foldersPath, + bucketName, + noobaaS3, + objects: data, + setDeleteResponse, + refreshTokens, + }, + }) => { + const { t } = useCustomTranslation(); + + const [deleteText, setDeleteText] = React.useState(''); + const [inProgress, setInProgress] = React.useState(false); + const [error, setError] = React.useState(); + + const onDelete = async (event) => { + event.preventDefault(); + setInProgress(true); + + try { + const deleteObjectKeys: ObjectIdentifier[] = data.map((object) => ({ + Key: getName(object), + })); + const response = await noobaaS3.deleteObjects({ + Bucket: bucketName, + Delete: { Objects: deleteObjectKeys }, + }); + + setInProgress(false); + setDeleteResponse({ + selectedObjects: data, + deleteResponse: response || ({} as DeleteObjectsCommandOutput), + }); + closeModal(); + // need new continuation tokens after state of bucket has changed (objects deleted) + refreshTokens(); + } catch (err) { + setInProgress(false); + setError(err); + } + }; + + return ( + + {t( + 'Deleted objects will no longer be visible in the bucket. If versioning is enabled a delete marker is created, you can recover object from previous versions. For unversioned objects, deletion is final and cannot be undone.' + )} +
+ } + variant={ModalVariant.medium} + actions={[ + + + + + + , + ]} + > +
+ + {(filteredData): React.ReactNode => ( + + )} + +
+ + setDeleteText(value)} + type={TextInputTypes.text} + placeholder={DELETE} + /> + + + ); + }; + +export default DeleteObjectsModal; diff --git a/packages/odf/modals/s3-browser/delete-objects/DeleteObjectsSummary.tsx b/packages/odf/modals/s3-browser/delete-objects/DeleteObjectsSummary.tsx new file mode 100644 index 000000000..8bbf880c8 --- /dev/null +++ b/packages/odf/modals/s3-browser/delete-objects/DeleteObjectsSummary.tsx @@ -0,0 +1,177 @@ +import * as React from 'react'; +import { DeleteObjectsCommandOutput, _Error } from '@aws-sdk/client-s3'; +import { DASH } from '@odf/shared'; +import { PaginatedListPage } from '@odf/shared/list-page'; +import { CommonModalProps } from '@odf/shared/modals'; +import { getName } from '@odf/shared/selectors'; +import { + RedExclamationCircleIcon, + RedExclamationTriangleIcon, +} from '@odf/shared/status/icons'; +import { RowComponentType } from '@odf/shared/table'; +import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; +import { sortRows } from '@odf/shared/utils'; +import { TFunction } from 'i18next'; +import { + Modal, + ModalVariant, + Button, + ButtonVariant, + PaginationVariant, +} from '@patternfly/react-core'; +import { Tr, Td, TableVariant } from '@patternfly/react-table'; +import { ObjectCrFormat } from '../../../types'; +import { replacePathFromName } from '../../../utils'; +import './delete-objects.scss'; + +type DeleteObjectsSummaryProps = { + errorResponse: DeleteObjectsCommandOutput['Errors']; + selectedObjects: ObjectCrFormat[]; + foldersPath: string; +}; + +type DeleteObjectsMap = { [objectName: string]: ObjectCrFormat }; + +type SummaryRowComponent = React.ComponentType>; + +const getColumnNames = (t: TFunction) => [ + '', // expandable + t('Name'), + t('Size'), + t('Last modified'), + t('Delete status'), +]; + +const getHeaderColumns = (t: TFunction) => { + const columnNames = getColumnNames(t); + return [ + { + columnName: columnNames[0], + }, + { + columnName: columnNames[1], + sortFunction: (a, b, c) => sortRows(a, b, c, 'metadata.name'), + }, + { + columnName: columnNames[2], + sortFunction: (a, b, c) => sortRows(a, b, c, 'apiResponse.size'), + }, + { + columnName: columnNames[3], + sortFunction: (a, b, c) => sortRows(a, b, c, 'apiResponse.lastModified'), + }, + { + columnName: columnNames[4], + }, + ]; +}; + +const ObjectsSummaryTableRow: React.FC> = ({ + row: object, + rowIndex, + extraProps, +}) => { + const { t } = useCustomTranslation(); + + const [isExpanded, setIsExpanded] = React.useState(false); + + const { foldersPath, deleteObjectsMap } = extraProps; + const objectName = object?.Key || DASH; + const objectCrFormat = deleteObjectsMap[objectName] || {}; + const name = replacePathFromName(objectName, foldersPath); + + const columnNames = getColumnNames(t); + + return ( + <> + + setIsExpanded(!isExpanded), + expandId: 'expandable-table', + }} + /> + + {name} + + + {objectCrFormat.apiResponse?.size || DASH} + + + {objectCrFormat.apiResponse?.lastModified || DASH} + + + + {t('Failed')} + + + {isExpanded && ( + + + + {object?.Message || DASH} + + + )} + + ); +}; + +const DeleteObjectsSummary: React.FC< + CommonModalProps +> = ({ + closeModal, + isOpen, + extraProps: { errorResponse, selectedObjects, foldersPath }, +}) => { + const { t } = useCustomTranslation(); + + const deleteObjectsMap: DeleteObjectsMap = React.useMemo( + () => + selectedObjects.reduce((acc, object) => { + acc[getName(object)] = object; + return acc; + }, {} as DeleteObjectsMap), + [selectedObjects] + ); + + return ( + + {t('Close')} + , + ]} + > +
+ +
+
+ ); +}; + +export default DeleteObjectsSummary; diff --git a/packages/odf/modals/s3-browser/delete-objects/LazyDeleteModals.ts b/packages/odf/modals/s3-browser/delete-objects/LazyDeleteModals.ts new file mode 100644 index 000000000..0326d6a50 --- /dev/null +++ b/packages/odf/modals/s3-browser/delete-objects/LazyDeleteModals.ts @@ -0,0 +1,9 @@ +import * as React from 'react'; + +export const LazyDeleteObjectsModal = React.lazy( + () => import('./DeleteObjectsModal') +); + +export const LazyDeleteObjectsSummary = React.lazy( + () => import('./DeleteObjectsSummary') +); diff --git a/packages/odf/modals/s3-browser/delete-objects/delete-objects.scss b/packages/odf/modals/s3-browser/delete-objects/delete-objects.scss new file mode 100644 index 000000000..f45e2db90 --- /dev/null +++ b/packages/odf/modals/s3-browser/delete-objects/delete-objects.scss @@ -0,0 +1,8 @@ +.objects-table { + max-height: 25rem; + overflow-y: auto; +} + +.objects-table-paginate--margin-top { + margin-top: calc(2.25rem * -1); +} diff --git a/packages/odf/utils/s3-browser.ts b/packages/odf/utils/s3-browser.ts index 5f9ac5636..a578e1499 100644 --- a/packages/odf/utils/s3-browser.ts +++ b/packages/odf/utils/s3-browser.ts @@ -1,5 +1,6 @@ import { _Object as Content, CommonPrefix } from '@aws-sdk/client-s3'; import { DASH } from '@odf/shared/constants'; +import { getName } from '@odf/shared/selectors'; import { humanizeBinaryBytes } from '@odf/shared/utils'; import { TFunction } from 'i18next'; import { DELIMITER, BUCKETS_BASE_ROUTE, PREFIX } from '../constants'; @@ -91,3 +92,11 @@ export const convertObjectsDataToCrFormat = ( return structuredObjects; }; + +export const replacePathFromName = ( + object: ObjectCrFormat | string, + foldersPath: string +): string => + typeof object === 'string' + ? object.replace(foldersPath, '') + : getName(object).replace(foldersPath, ''); diff --git a/packages/shared/src/list-page/ListFilter.tsx b/packages/shared/src/list-page/ListFilter.tsx new file mode 100644 index 000000000..f5fae6a9c --- /dev/null +++ b/packages/shared/src/list-page/ListFilter.tsx @@ -0,0 +1,58 @@ +import * as React from 'react'; +import { getName } from '@odf/shared/selectors'; +import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; +import { K8sResourceCommon } from '@openshift-console/dynamic-plugin-sdk'; +import * as _ from 'lodash-es'; +import { SearchInput, SearchInputProps } from '@patternfly/react-core'; + +type ListFilterProps = { + data: K8sResourceCommon[]; + loaded: boolean; + dataFilter?: (resource: K8sResourceCommon) => boolean; + textInputProps?: Omit; + children: (filteredData: K8sResourceCommon[]) => React.ReactNode; +}; + +export const ListFilter: React.FC = ({ + data, + loaded, + dataFilter, + textInputProps, + children, +}) => { + const { t } = useCustomTranslation(); + const [input, setInput] = React.useState(''); + + const filteredData = React.useMemo(() => { + if (!input) return data; + const resourceFilter = + dataFilter || + ((resource: K8sResourceCommon): boolean => + _.toLower(getName(resource)).includes(_.toLower(input))); + return (data ?? []).filter(resourceFilter); + }, [input, data, dataFilter]); + + const onChange = ( + inputValue: string | React.FormEvent + ): void => + setInput( + typeof inputValue === 'string' + ? inputValue + : (inputValue.target as HTMLInputElement)?.value + ); + + return ( + <> + {loaded && !_.isEmpty(data) && ( + onChange('')} + /> + )} + {children(filteredData)} + + ); +}; diff --git a/packages/shared/src/list-page/index.ts b/packages/shared/src/list-page/index.ts index d8aa61dda..64827503c 100644 --- a/packages/shared/src/list-page/index.ts +++ b/packages/shared/src/list-page/index.ts @@ -1 +1,2 @@ export * from './paginated-list-page'; +export * from './ListFilter'; diff --git a/packages/shared/src/list-page/paginated-list-page.tsx b/packages/shared/src/list-page/paginated-list-page.tsx index 19eca62d8..8b84aa665 100644 --- a/packages/shared/src/list-page/paginated-list-page.tsx +++ b/packages/shared/src/list-page/paginated-list-page.tsx @@ -8,6 +8,7 @@ import { import { Pagination, PaginationVariant, + PaginationProps, Grid, GridItem, } from '@patternfly/react-core'; @@ -19,12 +20,22 @@ const COUNT_PER_PAGE_NUMBER = 10; export type PaginatedListPageProps = { countPerPage?: number; - filteredData: K8sResourceCommon[]; - CreateButton: React.FC; + filteredData: K8sResourceCommon[] | unknown[]; + CreateButton?: React.FC; Alerts?: React.FC; noData?: boolean; - listPageFilterProps: ListPageFilterProps; + hideFilter?: boolean; + listPageFilterProps?: ListPageFilterProps; composableTableProps: Omit, 'rows'>; + paginationProps?: Omit< + PaginationProps, + | 'itemCount' + | 'widgetId' + | 'perPage' + | 'page' + | 'onSetPage' + | 'onPerPageSelect' + >; }; export const PaginatedListPage: React.FC = ({ @@ -33,8 +44,10 @@ export const PaginatedListPage: React.FC = ({ CreateButton, Alerts, noData, + hideFilter, listPageFilterProps, composableTableProps, + paginationProps, }) => { const [page, setPage] = React.useState(INITIAL_PAGE_NUMBER); const [perPage, setPerPage] = React.useState( @@ -53,24 +66,27 @@ export const PaginatedListPage: React.FC = ({
- - + {!hideFilter && ( + + )} + {!!CreateButton && }
setPage(newPage)} onPerPageSelect={(_event, newPerPage, newPage) => { setPerPage(newPerPage); diff --git a/packages/shared/src/s3/commands.ts b/packages/shared/src/s3/commands.ts index 17461d097..9d0330393 100644 --- a/packages/shared/src/s3/commands.ts +++ b/packages/shared/src/s3/commands.ts @@ -5,6 +5,7 @@ import { CreateBucketCommand, PutBucketTaggingCommand, GetObjectCommand, + DeleteObjectsCommand, } from '@aws-sdk/client-s3'; import { getSignedUrl } from '@aws-sdk/s3-request-presigner'; import { @@ -14,6 +15,7 @@ import { PutBucketTags, GetSignedUrl, GetObject, + DeleteObjects, } from './types'; export class S3Commands { @@ -51,4 +53,7 @@ export class S3Commands { getObject: GetObject = (input) => this.s3Client.send(new GetObjectCommand(input)); + + deleteObjects: DeleteObjects = (input) => + this.s3Client.send(new DeleteObjectsCommand(input)); } diff --git a/packages/shared/src/s3/types.ts b/packages/shared/src/s3/types.ts index 1a83fe614..025d06914 100644 --- a/packages/shared/src/s3/types.ts +++ b/packages/shared/src/s3/types.ts @@ -9,6 +9,8 @@ import { PutBucketTaggingCommandOutput, GetObjectCommandInput, GetObjectCommandOutput, + DeleteObjectsCommandInput, + DeleteObjectsCommandOutput, } from '@aws-sdk/client-s3'; // Bucket command types @@ -37,3 +39,7 @@ export type GetSignedUrl = ( export type GetObject = ( input: GetObjectCommandInput ) => Promise; + +export type DeleteObjects = ( + input: DeleteObjectsCommandInput +) => Promise; diff --git a/packages/shared/src/status/icons.tsx b/packages/shared/src/status/icons.tsx index a1c0dc04c..8d05686b7 100644 --- a/packages/shared/src/status/icons.tsx +++ b/packages/shared/src/status/icons.tsx @@ -46,6 +46,17 @@ export const RedExclamationCircleIcon: React.FC = ({ /> ); +export const RedExclamationTriangleIcon: React.FC = ({ + className, + title, +}) => ( + +); + export const YellowExclamationTriangleIcon: React.FC = ({ className, title, diff --git a/packages/shared/src/table/composable-table.tsx b/packages/shared/src/table/composable-table.tsx index ca07463b9..83f9b2a92 100644 --- a/packages/shared/src/table/composable-table.tsx +++ b/packages/shared/src/table/composable-table.tsx @@ -4,6 +4,7 @@ import { K8sResourceCommon } from '@openshift-console/dynamic-plugin-sdk'; import { SortByDirection, Table, + TableVariant, Tbody, Th, ThProps, @@ -18,7 +19,7 @@ export type TableColumnProps = ThProps & { sortFunction?: (a: T, b: T, c: SortByDirection) => number; }; -export type RowComponentType = { +export type RowComponentType = { row: T; rowIndex?: number; extraProps?: any; @@ -36,6 +37,7 @@ export const ComposableTable: ComposableTableProps = < unfilteredData, noDataMsg, emptyRowMessage, + variant, }) => { const { onSort, @@ -67,6 +69,7 @@ export const ComposableTable: ComposableTableProps = < translate={null} aria-label="Composable table" className="pf-v5-u-mt-md" + variant={variant} > @@ -100,7 +103,7 @@ export const ComposableTable: ComposableTableProps = < // sort is replaced by sortFunction type TableThProps = Omit; -export type TableProps = { +export type TableProps = { rows: T[]; columns: TableColumnProps[]; RowComponent: React.ComponentType>; @@ -110,6 +113,7 @@ export type TableProps = { unfilteredData?: []; noDataMsg?: React.FC; emptyRowMessage?: React.FC; + variant?: TableVariant; }; type ComposableTableProps = ( From 17607995dfb70ebdd57b9e0f673d1098626ae893 Mon Sep 17 00:00:00 2001 From: Gowtham Shanmugasundaram Date: Tue, 8 Oct 2024 16:39:52 +0530 Subject: [PATCH 22/22] RHSTOR-6195: Bucket - list page Signed-off-by: Gowtham Shanmugasundaram --- locales/en/plugin__odf-console.json | 20 +- package.json | 2 +- .../drpolicy-list-page.spec.tsx | 2 +- .../drpolicy-list-page/drpolicy-list-page.tsx | 2 +- .../manage-policy-view.tsx | 2 +- .../protected-applications/components.tsx | 2 +- .../buckets-list-page/bucketListTable.tsx | 205 +++ .../buckets-list-page/bucketPagination.tsx | 83 ++ .../buckets-list-page/bucketsListPage.tsx | 90 ++ .../s3-browser/objects-list/ObjectsList.tsx | 142 +- .../s3-browser/pagination-helper.tsx | 126 ++ packages/odf/constants/s3-browser.ts | 5 + packages/odf/features.ts | 8 +- packages/odf/types/s3-browser.ts | 6 + packages/odf/utils/s3-browser.ts | 22 +- .../shared/src/details-page/timestamp.tsx | 19 +- .../src}/empty-state-page/empty-page.scss | 0 .../src}/empty-state-page/empty-page.tsx | 2 +- packages/shared/src/empty-state-page/index.ts | 1 + packages/shared/src/hooks/index.ts | 1 + .../src/hooks/useUserSettingsLocalStorage.ts | 188 +++ packages/shared/src/index.ts | 1 + packages/shared/src/s3/types.ts | 4 + .../shared/src/table/composable-table.tsx | 7 +- packages/shared/src/utils/table.ts | 21 +- plugins/odf/console-extensions.json | 19 +- plugins/odf/console-plugin.json | 3 +- yarn.lock | 1239 ++++++++++------- 28 files changed, 1557 insertions(+), 665 deletions(-) create mode 100644 packages/odf/components/s3-browser/buckets-list-page/bucketListTable.tsx create mode 100644 packages/odf/components/s3-browser/buckets-list-page/bucketPagination.tsx create mode 100644 packages/odf/components/s3-browser/buckets-list-page/bucketsListPage.tsx create mode 100644 packages/odf/components/s3-browser/pagination-helper.tsx rename packages/{mco/components => shared/src}/empty-state-page/empty-page.scss (100%) rename packages/{mco/components => shared/src}/empty-state-page/empty-page.tsx (98%) create mode 100644 packages/shared/src/empty-state-page/index.ts create mode 100644 packages/shared/src/hooks/useUserSettingsLocalStorage.ts diff --git a/locales/en/plugin__odf-console.json b/locales/en/plugin__odf-console.json index c2d120d7c..f1a6f55d5 100644 --- a/locales/en/plugin__odf-console.json +++ b/locales/en/plugin__odf-console.json @@ -150,10 +150,6 @@ "Clusters": "Clusters", "Connected applications": "Connected applications", "Cannot delete while connected to an application.": "Cannot delete while connected to an application.", - "Loading Empty Page": "Loading Empty Page", - "You are not authorized to complete this action. See your cluster administrator for role-based access control information.": "You are not authorized to complete this action. See your cluster administrator for role-based access control information.", - "Not Authorized": "Not Authorized", - "Empty Page": "Empty Page", "Clean up application resources on current primary cluster {{ failoverCluster }} to start the relocation.": "Clean up application resources on current primary cluster {{ failoverCluster }} to start the relocation.", "Cleanup Pending": "Cleanup Pending", "Relocating to cluster {{ preferredCluster }}": "Relocating to cluster {{ preferredCluster }}", @@ -1115,6 +1111,16 @@ "MCG": "MCG", "Object path: ": "Object path: ", "Copy to share": "Copy to share", + "Erase the contents of your bucket": "Erase the contents of your bucket", + "Storage endpoint": "Storage endpoint", + "Create on": "Create on", + "Owner": "Owner", + "Create and manage your buckets": "Create and manage your buckets", + "Navigate through your buckets effortlessly. View the contents of your S3-managed and Openshift-managed buckets, making it easy to locate and inspect objects.": "Navigate through your buckets effortlessly. View the contents of your S3-managed and Openshift-managed buckets, making it easy to locate and inspect objects.", + "No buckets found": "No buckets found", + "Search a bucket by name": "Search a bucket by name", + "Create bucket": "Create bucket", + "Browse, upload, and manage objects in buckets.": "Browse, upload, and manage objects in buckets.", "Create Bucket": "Create Bucket", "An object bucket is a cloud storage container that organizes and manages files (objects), allowing users to store, retrieve and control access to data efficiently.": "An object bucket is a cloud storage container that organizes and manages files (objects), allowing users to store, retrieve and control access to data efficiently.", "Select bucket creation method": "Select bucket creation method", @@ -1394,7 +1400,6 @@ "{{count}} annotation_one": "{{count}} annotation", "{{count}} annotation_other": "{{count}} annotation", "Created at": "Created at", - "Owner": "Owner", "No labels": "No labels", "No owner": "No owner", "Select input": "Select input", @@ -1403,6 +1408,10 @@ "No resources available": "No resources available", "Select {{resourceLabel}}": "Select {{resourceLabel}}", "Error Loading": "Error Loading", + "Loading empty page": "Loading empty page", + "You are not authorized to complete this action. See your cluster administrator for role-based access control information.": "You are not authorized to complete this action. See your cluster administrator for role-based access control information.", + "Not Authorized": "Not Authorized", + "Empty Page": "Empty Page", "Reset": "Reset", "An error occurred. Please try again.": "An error occurred. Please try again.", "Error Loading {{label}}: {{message}}": "Error Loading {{label}}: {{message}}", @@ -1462,6 +1471,7 @@ "Infrastructures": "Infrastructures", "Subscriptions": "Subscriptions", "Project": "Project", + "Composable table": "Composable table", "Show password": "Show password", "Enter node": "Enter node", "Deployment details": "Deployment details", diff --git a/package.json b/package.json index 7db94177e..5e0df9eac 100644 --- a/package.json +++ b/package.json @@ -59,7 +59,7 @@ "dev:c": "yarn ocp-console & PLUGIN=${PLUGIN} I8N_NS=${I8N_NS} yarn server:plugin & wait" }, "dependencies": { - "@aws-sdk/client-s3": "3.614.0", + "@aws-sdk/client-s3": "3.667.0", "@aws-sdk/s3-request-presigner": "3.614.0", "@openshift-console/dynamic-plugin-sdk": "1.3.0", "@openshift-console/dynamic-plugin-sdk-internal": "1.0.0", diff --git a/packages/mco/components/drpolicy-list-page/drpolicy-list-page.spec.tsx b/packages/mco/components/drpolicy-list-page/drpolicy-list-page.spec.tsx index 6e9ec7166..763f0a64a 100644 --- a/packages/mco/components/drpolicy-list-page/drpolicy-list-page.spec.tsx +++ b/packages/mco/components/drpolicy-list-page/drpolicy-list-page.spec.tsx @@ -92,6 +92,6 @@ describe('Test drpolicy list page', () => { test('Empty page loading test', async () => { testCase = 3; render(); - expect(screen.getByLabelText('Loading Empty Page')).toBeInTheDocument(); + expect(screen.getByLabelText('Loading empty page')).toBeInTheDocument(); }); }); diff --git a/packages/mco/components/drpolicy-list-page/drpolicy-list-page.tsx b/packages/mco/components/drpolicy-list-page/drpolicy-list-page.tsx index 8cb9d1dae..bec655f00 100644 --- a/packages/mco/components/drpolicy-list-page/drpolicy-list-page.tsx +++ b/packages/mco/components/drpolicy-list-page/drpolicy-list-page.tsx @@ -1,5 +1,6 @@ import * as React from 'react'; import { pluralize } from '@odf/core/components/utils'; +import EmptyPage from '@odf/shared/empty-state-page/empty-page'; import { useAccessReview } from '@odf/shared/hooks/rbac-hook'; import { Kebab } from '@odf/shared/kebab/kebab'; import { getName } from '@odf/shared/selectors'; @@ -28,7 +29,6 @@ import { import { DRPolicyModel } from '../../models'; import { DRPolicyKind } from '../../types'; import { getReplicationType, isDRPolicyValidated } from '../../utils'; -import EmptyPage from '../empty-state-page/empty-page'; import { Header, kebabActionItems, tableColumnInfo } from './helper'; import './drpolicy-list-page.scss'; diff --git a/packages/mco/components/modals/app-manage-policies/manage-policy-view.tsx b/packages/mco/components/modals/app-manage-policies/manage-policy-view.tsx index cbd663e2c..da4b1b4bc 100644 --- a/packages/mco/components/modals/app-manage-policies/manage-policy-view.tsx +++ b/packages/mco/components/modals/app-manage-policies/manage-policy-view.tsx @@ -2,6 +2,7 @@ import * as React from 'react'; import { DRPolicyKind, DRPlacementControlKind } from '@odf/mco/types'; import { getDRPolicyStatus, parseSyncInterval } from '@odf/mco/utils'; import { formatTime, getLatestDate } from '@odf/shared/details-page/datetime'; +import EmptyPage from '@odf/shared/empty-state-page/empty-page'; import { StatusBox } from '@odf/shared/generic/status-box'; import { Labels } from '@odf/shared/labels'; import { ModalBody, ModalFooter } from '@odf/shared/modals/Modal'; @@ -31,7 +32,6 @@ import { SYNC_SCHEDULE_DISPLAY_TEXT, } from '../../../constants'; import { getDRPlacementControlResourceObj } from '../../../hooks'; -import EmptyPage from '../../empty-state-page/empty-page'; import { doNotDeletePVCAnnotationPromises, unAssignPromises, diff --git a/packages/mco/components/protected-applications/components.tsx b/packages/mco/components/protected-applications/components.tsx index 04e9e9009..dabfba96c 100644 --- a/packages/mco/components/protected-applications/components.tsx +++ b/packages/mco/components/protected-applications/components.tsx @@ -3,6 +3,7 @@ import { ActionDropdown, ToggleVariant, } from '@odf/shared/dropdown/action-dropdown'; +import EmptyPage from '@odf/shared/empty-state-page/empty-page'; import { DataUnavailableError } from '@odf/shared/generic/Error'; import { NamespaceModel } from '@odf/shared/models'; import { ResourceNameWIcon } from '@odf/shared/resource-link/resource-link'; @@ -36,7 +37,6 @@ import { } from '../../constants'; import { DRPlacementControlModel } from '../../models'; import { DRPlacementControlKind } from '../../types'; -import EmptyPage from '../empty-state-page/empty-page'; import { getCurrentActivity } from '../mco-dashboard/disaster-recovery/cluster-app-card/application'; import { getAlertMessages, diff --git a/packages/odf/components/s3-browser/buckets-list-page/bucketListTable.tsx b/packages/odf/components/s3-browser/buckets-list-page/bucketListTable.tsx new file mode 100644 index 000000000..995a3a6dc --- /dev/null +++ b/packages/odf/components/s3-browser/buckets-list-page/bucketListTable.tsx @@ -0,0 +1,205 @@ +import * as React from 'react'; +import { + BUCKET_BOOKMARKS_USER_SETTINGS_KEY, + BUCKETS_BASE_ROUTE, +} from '@odf/core/constants'; +import { BucketCrFormat } from '@odf/core/types'; +import { Timestamp } from '@odf/shared/details-page/timestamp'; +import { EmptyPage } from '@odf/shared/empty-state-page'; +import { useUserSettingsLocalStorage } from '@odf/shared/hooks/useUserSettingsLocalStorage'; +import { + ComposableTable, + RowComponentType, +} from '@odf/shared/table/composable-table'; +import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; +import { sortRows } from '@odf/shared/utils'; +import { TFunction } from 'react-i18next'; +import { Link } from 'react-router-dom-v5-compat'; +import { Bullseye, Label } from '@patternfly/react-core'; +import { UserIcon } from '@patternfly/react-icons'; +import { + ActionsColumn, + IAction, + TableVariant, + Td, + Tr, +} from '@patternfly/react-table'; + +const getRowActions = (t: TFunction): IAction[] => [ + // ToDo: add empty/delete bucket action + { + title: ( + <> + {t('Empty bucket')} +

+ {t('Erase the contents of your bucket')} +

+ + ), + onClick: () => undefined, + }, + { + title: t('Delete bucket'), + onClick: () => undefined, + }, +]; + +const getColumnNames = (t: TFunction) => [ + '', // favoritable, + t('Name'), + t('Storage endpoint'), + t('Create on'), + t('Owner'), + '', // action kebab +]; + +const getHeaderColumns = (t: TFunction, favorites: string[]) => { + const columnNames = getColumnNames(t); + return [ + { + columnName: columnNames[0], + sortFunction: (a, b, c) => sortRows(a, b, c, 'metadata.name', favorites), + }, + { + columnName: columnNames[1], + sortFunction: (a, b, c) => sortRows(a, b, c, 'metadata.name'), + }, + { + columnName: columnNames[2], + thProps: { + className: 'pf-v5-u-w-16-on-lg', + }, + }, + { + columnName: columnNames[3], + sortFunction: (a, b, c) => + sortRows(a, b, c, 'metadata.creationTimestamp'), + thProps: { + className: 'pf-v5-u-w-16-on-lg', + }, + }, + { + columnName: columnNames[4], + thProps: { + className: 'pf-v5-u-w-16-on-lg', + }, + }, + { + columnName: columnNames[5], + }, + ]; +}; + +const NoBucketMessage: React.FC = () => { + const { t } = useCustomTranslation(); + return ( + <>} + title={t('Create and manage your buckets')} + isLoaded + canAccess + > + {t( + 'Navigate through your buckets effortlessly. View the contents of your S3-managed and Openshift-managed buckets, making it easy to locate and inspect objects.' + )} + + ); +}; + +const EmptyRowMessage: React.FC = () => { + const { t } = useCustomTranslation(); + return {t('No buckets found')}; +}; + +const BucketsTableRow: React.FC> = ({ + row: bucket, + rowIndex, + extraProps, +}) => { + const { t } = useCustomTranslation(); + const columnNames = getColumnNames(t); + const { + apiResponse: { owner }, + metadata: { name, creationTimestamp }, + } = bucket; + const { favorites, setFavorites }: RowExtraPropsType = extraProps; + + const onSetFavorite = (key, active) => { + setFavorites((oldFavorites) => [ + ...oldFavorites.filter((oldFavorite) => oldFavorite !== key), + ...(active ? [key] : []), + ]); + }; + + return ( + + + onSetFavorite(name, isFavoriting), + rowIndex, + }} + /> + + {name} + + + {/* ToDo: Currently we only support MCG, make is configurable once RGW is supported as well */} + + + + {} + + + {owner} + + + + + + ); +}; + +export const BucketsListTable: React.FC = ({ + allBuckets, + filteredBuckets, + loaded, + error, +}) => { + const { t } = useCustomTranslation(); + const [favorites, setFavorites] = useUserSettingsLocalStorage( + BUCKET_BOOKMARKS_USER_SETTINGS_KEY, + true, + [] + ); + return ( + + ); +}; + +type BucketsListTableProps = { + allBuckets: BucketCrFormat[]; + filteredBuckets: BucketCrFormat[]; + loaded: boolean; + error: any; +}; + +type RowExtraPropsType = { + favorites: string[]; + setFavorites: React.Dispatch>; +}; diff --git a/packages/odf/components/s3-browser/buckets-list-page/bucketPagination.tsx b/packages/odf/components/s3-browser/buckets-list-page/bucketPagination.tsx new file mode 100644 index 000000000..13e8c6d21 --- /dev/null +++ b/packages/odf/components/s3-browser/buckets-list-page/bucketPagination.tsx @@ -0,0 +1,83 @@ +import * as React from 'react'; +import { ListBucketsCommandOutput } from '@aws-sdk/client-s3'; +import { LIST_BUCKET, MAX_BUCKETS } from '@odf/core/constants'; +import { BucketCrFormat } from '@odf/core/types'; +import { convertBucketDataToCrFormat } from '@odf/core/utils'; +import useSWRMutation from 'swr/mutation'; +import { NoobaaS3Context } from '../noobaa-context'; +import { + ContinuationTokens, + continuationTokensRefresher, + fetchS3Resources, + Pagination, +} from '../pagination-helper'; + +export const BucketPagination: React.FC = ({ + setBucketInfo, +}) => { + const { noobaaS3 } = React.useContext(NoobaaS3Context); + const { data, error, isMutating, trigger } = useSWRMutation( + LIST_BUCKET, + (_url, { arg }: { arg: string }) => + noobaaS3.listBuckets({ + MaxBuckets: MAX_BUCKETS, + ...(!!arg && { ContinuationToken: arg }), + }) + ); + + const loadedWOError = !isMutating && !error; + const [continuationTokens, setContinuationTokens] = + React.useState({ + previous: [], + current: '', + next: '', + }); + + React.useEffect(() => { + setBucketInfo([convertBucketDataToCrFormat(data), !isMutating, error]); + }, [data, isMutating, error, setBucketInfo]); + + // initial fetch on first mount + React.useEffect(() => { + continuationTokensRefresher(setContinuationTokens, trigger); + // eslint-disable-next-line react-hooks/exhaustive-deps + }, []); + + const onNextClick = async () => { + if (!!continuationTokens.next && loadedWOError) + fetchS3Resources( + setContinuationTokens, + trigger, + true, + continuationTokens.next + ); + }; + + const onPreviousClick = async () => { + if (!!continuationTokens.current && loadedWOError) { + const paginationToken = + continuationTokens.previous[continuationTokens.previous.length - 1]; + fetchS3Resources( + setContinuationTokens, + trigger, + false, + paginationToken + ); + } + }; + + return ( + + ); +}; + +type BucketPaginationProps = { + setBucketInfo: React.Dispatch< + React.SetStateAction<[BucketCrFormat[], boolean, any]> + >; +}; diff --git a/packages/odf/components/s3-browser/buckets-list-page/bucketsListPage.tsx b/packages/odf/components/s3-browser/buckets-list-page/bucketsListPage.tsx new file mode 100644 index 000000000..8acaaf582 --- /dev/null +++ b/packages/odf/components/s3-browser/buckets-list-page/bucketsListPage.tsx @@ -0,0 +1,90 @@ +import * as React from 'react'; +import { useRefresh } from '@odf/shared/hooks'; +import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; +import { getValidFilteredData } from '@odf/shared/utils'; +import { + ListPageBody, + ListPageCreateLink, + ListPageFilter, + ListPageHeader, + useListPageFilter, +} from '@openshift-console/dynamic-plugin-sdk'; +import { Button, ButtonVariant, Flex, FlexItem } from '@patternfly/react-core'; +import { SyncAltIcon } from '@patternfly/react-icons'; +import { BUCKET_CREATE_PAGE_PATH } from '../../../constants'; +import { BucketCrFormat } from '../../../types'; +import { NoobaaS3Provider } from '../noobaa-context'; +import { BucketsListTable } from './bucketListTable'; +import { BucketPagination } from './bucketPagination'; + +const BucketsListPageBody: React.FC = () => { + const { t } = useCustomTranslation(); + const [fresh, triggerRefresh] = useRefresh(); + const [bucketInfo, setBucketInfo] = React.useState< + [BucketCrFormat[], boolean, any] + >([[], false, undefined]); + const [buckets, loaded, loadError] = bucketInfo; + const [allBuckets, filteredBuckets, onFilterChange] = + useListPageFilter(buckets); + + return ( + + + + + + + + + + + + + {fresh && } + + + + {fresh && ( + + )} + + ); +}; + +const BucketsListPage: React.FC = () => { + const { t } = useCustomTranslation(); + + return ( + + + + {t('Create bucket')} + + +
+ {t('Browse, upload, and manage objects in buckets.')} +
+ +
+ ); +}; + +export default BucketsListPage; diff --git a/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx b/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx index 2cf0b796a..58dc86de5 100644 --- a/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx +++ b/packages/odf/components/s3-browser/objects-list/ObjectsList.tsx @@ -12,9 +12,8 @@ import { useCustomTranslation } from '@odf/shared/useCustomTranslationHook'; import { useModal } from '@openshift-console/dynamic-plugin-sdk'; import { LaunchModal } from '@openshift-console/dynamic-plugin-sdk/lib/app/modal-support/ModalProvider'; import { TFunction } from 'i18next'; -import * as _ from 'lodash-es'; import { useParams, useSearchParams } from 'react-router-dom-v5-compat'; -import useSWRMutation, { TriggerWithOptionsArgs } from 'swr/mutation'; +import useSWRMutation from 'swr/mutation'; import { Button, ButtonVariant, @@ -26,7 +25,6 @@ import { AlertActionCloseButton, AlertActionLink, } from '@patternfly/react-core'; -import { AngleLeftIcon, AngleRightIcon } from '@patternfly/react-icons'; import { ActionsColumn, IAction, @@ -44,6 +42,13 @@ import { import { ObjectCrFormat } from '../../../types'; import { getPath, convertObjectsDataToCrFormat } from '../../../utils'; import { NoobaaS3Context } from '../noobaa-context'; +import { + Pagination, + PaginationProps, + ContinuationTokens, + fetchS3Resources, + continuationTokensRefresher, +} from '../pagination-helper'; import { isRowSelectable, getColumns, @@ -55,13 +60,6 @@ const LazyCreateFolderModal = React.lazy( () => import('../../../modals/s3-browser/create-folder/CreateFolderModal') ); -type PaginationProps = { - onNext: () => void; - onPrevious: () => void; - disableNext: boolean; - disablePrevious: boolean; -}; - type TableActionsProps = { launcher: LaunchModal; selectedRows: ObjectCrFormat[]; @@ -78,90 +76,6 @@ type DeletionAlertsProps = { foldersPath: string; }; -type ContinuationTokens = { - previous: string[]; - current: string; - next: string; -}; - -type Trigger = TriggerWithOptionsArgs< - ListObjectsV2CommandOutput, - any, - string, - string ->; - -// for navigating (next/previous) through objects list -const continuationTokensSetter = ( - setContinuationTokens: React.Dispatch< - React.SetStateAction - >, - response: ListObjectsV2CommandOutput, - isNext: boolean, - setSelectedRows: React.Dispatch> -) => { - setContinuationTokens((oldTokens) => { - const newTokens = _.cloneDeep(oldTokens); - if (isNext) { - newTokens.previous.push(newTokens.current); - newTokens.current = newTokens.next; - } else { - newTokens.current = newTokens.previous.pop(); - } - newTokens.next = response.NextContinuationToken; - - return newTokens; - }); - setSelectedRows([]); -}; - -const fetchObjects = async ( - setContinuationTokens: React.Dispatch< - React.SetStateAction - >, - trigger: Trigger, - isNext: boolean, - setSelectedRows: React.Dispatch>, - paginationToken = '' -) => { - try { - const response: ListObjectsV2CommandOutput = await trigger(paginationToken); - continuationTokensSetter( - setContinuationTokens, - response, - isNext, - setSelectedRows - ); - } catch (err) { - // no need to handle any error here, use "error" object directly from the "useSWRMutation" hook - // eslint-disable-next-line no-console - console.error(err); - } -}; - -// for refreshing (re-feching) objects from start, once state of bucket has changed (objects added/deleted) -const continuationTokensRefresher = async ( - setContinuationTokens: React.Dispatch< - React.SetStateAction - >, - trigger: Trigger, - setSelectedRows: React.Dispatch> -) => { - try { - const response: ListObjectsV2CommandOutput = await trigger(); - setContinuationTokens({ - previous: [''], - current: '', - next: response.NextContinuationToken, - }); - setSelectedRows([]); - } catch (err) { - // no need to handle any error here, use "error" object directly from the "useSWRMutation" hook - // eslint-disable-next-line no-console - console.error(err); - } -}; - const getBulkActionsItems = ( t: TFunction, launcher: LaunchModal, @@ -203,34 +117,6 @@ export const CustomActionsToggle = (props: CustomActionsToggleProps) => { ); }; -const Pagination: React.FC = ({ - onNext, - onPrevious, - disableNext, - disablePrevious, -}) => { - return ( -
- - -
- ); -}; - const TableActions: React.FC = ({ onNext, onPrevious, @@ -467,12 +353,12 @@ export const ObjectsList: React.FC<{}> = () => { { if (!!continuationTokens.next && loadedWOError) - fetchObjects( + fetchS3Resources( setContinuationTokens, trigger, true, - setSelectedRows, - continuationTokens.next + continuationTokens.next, + setSelectedRows ); }} onPrevious={async () => { @@ -481,12 +367,12 @@ export const ObjectsList: React.FC<{}> = () => { continuationTokens.previous[ continuationTokens.previous.length - 1 ]; - fetchObjects( + fetchS3Resources( setContinuationTokens, trigger, false, - setSelectedRows, - paginationToken + paginationToken, + setSelectedRows ); } }} diff --git a/packages/odf/components/s3-browser/pagination-helper.tsx b/packages/odf/components/s3-browser/pagination-helper.tsx new file mode 100644 index 000000000..c5c77f9ca --- /dev/null +++ b/packages/odf/components/s3-browser/pagination-helper.tsx @@ -0,0 +1,126 @@ +import * as React from 'react'; +import { ListCommandOutput } from '@odf/shared/s3'; +import { K8sResourceCommon } from '@openshift-console/dynamic-plugin-sdk'; +import * as _ from 'lodash-es'; +import { TriggerWithOptionsArgs } from 'swr/dist/mutation'; +import { Button, ButtonVariant } from '@patternfly/react-core'; +import { AngleLeftIcon, AngleRightIcon } from '@patternfly/react-icons'; + +export type ContinuationTokens = { + previous: string[]; + current: string; + next: string; +}; + +export type PaginationProps = { + onNext: () => void; + onPrevious: () => void; + disableNext: boolean; + disablePrevious: boolean; +}; + +type Trigger = TriggerWithOptionsArgs; + +const getNextContinuationToken = (response: ListCommandOutput) => + 'NextContinuationToken' in response + ? response.NextContinuationToken + : response.ContinuationToken; + +export const continuationTokensSetter = ( + setContinuationTokens: React.Dispatch< + React.SetStateAction + >, + response: T, + isNext: boolean, + setSelectedRows?: React.Dispatch> +) => { + setContinuationTokens((oldTokens) => { + const newTokens = _.cloneDeep(oldTokens); + if (isNext) { + newTokens.previous.push(newTokens.current); + newTokens.current = newTokens.next; + } else { + newTokens.current = newTokens.previous.pop(); + } + + newTokens.next = getNextContinuationToken(response); + + return newTokens; + }); + !!setSelectedRows && setSelectedRows([]); +}; + +export const fetchS3Resources = async ( + setContinuationTokens: React.Dispatch< + React.SetStateAction + >, + trigger: Trigger, + isNext: boolean, + paginationToken = '', + setSelectedRows?: React.Dispatch> +) => { + try { + const response: T = await trigger(paginationToken); + continuationTokensSetter( + setContinuationTokens, + response, + isNext, + setSelectedRows + ); + } catch (err) { + // no need to handle any error here, use "error" object directly from the "useSWRMutation" hook + // eslint-disable-next-line no-console + console.error(err); + } +}; + +// for refreshing (re-feching) s3 resources from start, once state has changed by adding/deleted +export const continuationTokensRefresher = async ( + setContinuationTokens: React.Dispatch< + React.SetStateAction + >, + trigger: Trigger, + setSelectedRows?: React.Dispatch> +) => { + try { + const response: T = await trigger(); + setContinuationTokens({ + previous: [''], + current: '', + next: getNextContinuationToken(response), + }); + !!setSelectedRows && setSelectedRows([]); + } catch (err) { + // no need to handle any error here, use "error" object directly from the "useSWRMutation" hook + // eslint-disable-next-line no-console + console.error(err); + } +}; + +export const Pagination: React.FC = ({ + onNext, + onPrevious, + disableNext, + disablePrevious, +}) => { + return ( +
+ + +
+ ); +}; diff --git a/packages/odf/constants/s3-browser.ts b/packages/odf/constants/s3-browser.ts index 3752639d8..3340bc616 100644 --- a/packages/odf/constants/s3-browser.ts +++ b/packages/odf/constants/s3-browser.ts @@ -6,12 +6,17 @@ export const NOOBAA_SECRET_ACCESS_KEY = 'AWS_SECRET_ACCESS_KEY'; export const DELIMITER = '/'; export const PREFIX = 'prefix'; export const MAX_KEYS = 300; +export const MAX_BUCKETS = 100; export const BUCKET_NAME_MAX_LENGTH = 63; export const BUCKET_NAME_MIN_LENGTH = 3; export const BUCKETS_BASE_ROUTE = '/odf/object-storage/buckets'; +export const BUCKET_CREATE_PAGE_PATH = '/odf/object-storage/create-bucket'; // key to be used by SWR for caching particular API call export const LIST_BUCKET = 'LIST_BUCKET_CACHE_KEY'; export const LIST_OBJECTS = 'LIST_OBJECTS_CACHE_KEY'; + +// Bookmarking / favorites +export const BUCKET_BOOKMARKS_USER_SETTINGS_KEY = 'bucket-bookmarks'; diff --git a/packages/odf/features.ts b/packages/odf/features.ts index 6f73f086f..aaa0642df 100644 --- a/packages/odf/features.ts +++ b/packages/odf/features.ts @@ -17,13 +17,18 @@ import { } from '@openshift-console/dynamic-plugin-sdk'; import * as _ from 'lodash-es'; import { SECOND, RGW_PROVISIONER, NOOBAA_PROVISIONER } from './constants'; -import { isExternalCluster, isClusterIgnored } from './utils'; +import { + isExternalCluster, + isClusterIgnored, + isMCGStandaloneCluster, +} from './utils'; export const ODF_MODEL_FLAG = 'ODF_MODEL'; // Based on the existence of StorageSystem CRD export const RGW_FLAG = 'RGW'; // Based on the existence of StorageClass with RGW provisioner ("openshift-storage.ceph.rook.io/bucket") export const MCG_FLAG = 'MCG'; // Based on the existence of NooBaa StorageClass (which only gets created if NooBaaSystem is present) export const ODF_ADMIN = 'ODF_ADMIN'; // Set to "true" if user is an "openshift-storage" admin (access to StorageSystems) export const PROVIDER_MODE = 'PROVIDER_MODE'; // Set to "true" if user has deployed it in provider mode +export const MCG_STANDALONE = 'MCG_STANDALONE'; // Set to "true" if user has deployed for MCG standalone mode // Check the user's access to some resources. const ssarChecks = [ @@ -59,6 +64,7 @@ export const setOCSFlags = async (setFlag: SetFeatureFlag) => { !isClusterIgnored(sc) && !isExternalCluster(sc) ); setFlag(PROVIDER_MODE, isProviderMode(internalStorageCluster)); + setFlag(MCG_STANDALONE, isMCGStandaloneCluster(internalStorageCluster)); clearInterval(ocsIntervalId); } else if (setFlagFalse) { setFlagFalse = false; diff --git a/packages/odf/types/s3-browser.ts b/packages/odf/types/s3-browser.ts index b0c54b83f..b1f65e437 100644 --- a/packages/odf/types/s3-browser.ts +++ b/packages/odf/types/s3-browser.ts @@ -8,3 +8,9 @@ export type ObjectCrFormat = K8sResourceCommon & { isFolder?: boolean; type?: string; }; + +export type BucketCrFormat = K8sResourceCommon & { + apiResponse?: { + owner?: string; + }; +}; diff --git a/packages/odf/utils/s3-browser.ts b/packages/odf/utils/s3-browser.ts index a578e1499..84e4fb149 100644 --- a/packages/odf/utils/s3-browser.ts +++ b/packages/odf/utils/s3-browser.ts @@ -1,10 +1,14 @@ -import { _Object as Content, CommonPrefix } from '@aws-sdk/client-s3'; +import { + _Object as Content, + CommonPrefix, + ListBucketsCommandOutput, +} from '@aws-sdk/client-s3'; import { DASH } from '@odf/shared/constants'; import { getName } from '@odf/shared/selectors'; import { humanizeBinaryBytes } from '@odf/shared/utils'; import { TFunction } from 'i18next'; import { DELIMITER, BUCKETS_BASE_ROUTE, PREFIX } from '../constants'; -import { ObjectCrFormat } from '../types'; +import { BucketCrFormat, ObjectCrFormat } from '../types'; export const getBreadcrumbs = ( foldersPath: string, @@ -100,3 +104,17 @@ export const replacePathFromName = ( typeof object === 'string' ? object.replace(foldersPath, '') : getName(object).replace(foldersPath, ''); + +export const convertBucketDataToCrFormat = ( + listBucketsCommandOutput: ListBucketsCommandOutput +): BucketCrFormat[] => + listBucketsCommandOutput?.Buckets.map((bucket) => ({ + metadata: { + name: bucket.Name, + uid: bucket.Name, + creationTimestamp: bucket.CreationDate.toString(), + }, + apiResponse: { + owner: listBucketsCommandOutput?.Owner?.DisplayName, + }, + })) || []; diff --git a/packages/shared/src/details-page/timestamp.tsx b/packages/shared/src/details-page/timestamp.tsx index 9e5ecc8a8..e85c0668e 100644 --- a/packages/shared/src/details-page/timestamp.tsx +++ b/packages/shared/src/details-page/timestamp.tsx @@ -8,7 +8,8 @@ const timestampFor = ( mdate: Date, now: Date, omitSuffix: boolean, - simple?: boolean + simple?: boolean, + ignoreRelativeTime?: boolean ) => { if (!dateTime.isValid(mdate)) { return '-'; @@ -20,7 +21,11 @@ const timestampFor = ( } // Show a relative time if within 10.5 minutes in the past from the current time. - if (timeDifference > dateTime.maxClockSkewMS && timeDifference < 630000) { + if ( + timeDifference > dateTime.maxClockSkewMS && + timeDifference < 630000 && + !ignoreRelativeTime + ) { return dateTime.fromNow(mdate); } @@ -39,7 +44,13 @@ export const Timestamp = (props: TimestampProps) => { ? new Date((props.timestamp as number) * 1000) : new Date(props.timestamp); - const timestamp = timestampFor(mdate, new Date(now), props.simple); + const timestamp = timestampFor( + mdate, + new Date(now), + props.omitSuffix, + props.simple, + props?.ignoreRelativeTime + ); if (!dateTime.isValid(mdate)) { return
-
; @@ -73,6 +84,8 @@ export type TimestampProps = { simple?: boolean; omitSuffix?: boolean; className?: string; + // Simple / omitSuffix can overrride this field + ignoreRelativeTime?: boolean; }; Timestamp.displayName = 'Timestamp'; diff --git a/packages/mco/components/empty-state-page/empty-page.scss b/packages/shared/src/empty-state-page/empty-page.scss similarity index 100% rename from packages/mco/components/empty-state-page/empty-page.scss rename to packages/shared/src/empty-state-page/empty-page.scss diff --git a/packages/mco/components/empty-state-page/empty-page.tsx b/packages/shared/src/empty-state-page/empty-page.tsx similarity index 98% rename from packages/mco/components/empty-state-page/empty-page.tsx rename to packages/shared/src/empty-state-page/empty-page.tsx index 99d6402de..80229f5ec 100644 --- a/packages/mco/components/empty-state-page/empty-page.tsx +++ b/packages/shared/src/empty-state-page/empty-page.tsx @@ -30,7 +30,7 @@ const EmptyPage: React.FC = (props) => { return !isLoaded ? (
) : ( diff --git a/packages/shared/src/empty-state-page/index.ts b/packages/shared/src/empty-state-page/index.ts new file mode 100644 index 000000000..3b3dfb735 --- /dev/null +++ b/packages/shared/src/empty-state-page/index.ts @@ -0,0 +1 @@ +export { default as EmptyPage } from './empty-page'; diff --git a/packages/shared/src/hooks/index.ts b/packages/shared/src/hooks/index.ts index 63d16a651..20838fc1a 100644 --- a/packages/shared/src/hooks/index.ts +++ b/packages/shared/src/hooks/index.ts @@ -10,3 +10,4 @@ export * from './useK8sList'; export * from './scheduler'; export * from './use-doc-version'; export * from './useRefresh'; +export * from './useUserSettingsLocalStorage'; diff --git a/packages/shared/src/hooks/useUserSettingsLocalStorage.ts b/packages/shared/src/hooks/useUserSettingsLocalStorage.ts new file mode 100644 index 000000000..e6d92009c --- /dev/null +++ b/packages/shared/src/hooks/useUserSettingsLocalStorage.ts @@ -0,0 +1,188 @@ +import * as React from 'react'; + +// Default ODF user settings storage path +const DEFAULT_ODF_CONSOLE_USER_SETTINGS_KEY = 'odf-console-user-settings'; +const STORAGE_EVENT = 'storage'; + +export const deserializeData = (data: string | null) => { + if (typeof data !== 'string') { + return data; + } + try { + return JSON.parse(data); + } catch { + return data; + } +}; + +export const serializeData = (data: T) => { + if (typeof data === 'string') { + return data; + } + try { + return JSON.stringify(data); + } catch { + return data; + } +}; + +// Get user settings from local storage +const getDataFromLocalStorage = (storageKey: string) => + deserializeData(localStorage.getItem(storageKey)) ?? {}; + +// Initialize state +const initializeDataFromLocalStorage = ( + storageKey: string, + keyRef: string, + defaultValue: T +) => { + const valueInStorage = getDataFromLocalStorage(storageKey); + return valueInStorage?.hasOwnProperty(keyRef) && + valueInStorage[keyRef] !== undefined + ? valueInStorage[keyRef] + : defaultValue; +}; + +// Update local state with user settings by event +const syncLatestDataFromLocalStorage = ( + isMounted: boolean, + storageKey: string, + storage: Storage, + key: string, + newValue: string, + data: T, + userSettingsKey: string, + setData: React.Dispatch +) => { + if (isMounted && storage === localStorage && key === storageKey) { + const newData = deserializeData(newValue)?.[userSettingsKey]; + if ( + newData !== undefined && + serializeData(newData) !== serializeData(data) + ) { + setData(newData); + } + } +}; + +const updateLocalStorage = ( + storageKey: string, + userSettingsKey: string, + localData: any, + newState: T +) => { + // Trigger update also when unmounted + const dataToUpdate = { + ...localData, + ...{ + [userSettingsKey]: newState, + }, + }; + + const newValue = serializeData(dataToUpdate); + + try { + // Update the local storage + localStorage.setItem(storageKey, newValue); + + // Dispatch storage event to sync the settings changes for other tabs + generateStorageEventToUpdate(storageKey, newValue); + } catch (err) { + // eslint-disable-next-line no-console + console.error( + `Error while updating local storage for key ${storageKey}`, + err + ); + } +}; + +// Generate storage event to sync latest settings on other tabs +const generateStorageEventToUpdate = (storageKey, newValue: string) => { + // Create a storage event to dispatch locally since browser windows do not fire the + // storage event if the change originated from the current window + const event = new StorageEvent('storage', { + storageArea: localStorage, + key: storageKey, + newValue, + oldValue: localStorage.getItem(storageKey), + url: window.location.toString(), + }); + + window.dispatchEvent(event); +}; + +export const useUserSettingsLocalStorage = ( + // User settings sub storage path + userSettingsKey: string, + // Sync user settings changes in all tabs + sync = false, + // Default value for the initial settings + defaultValue?: T, + // ODF settings base storage path + storageKey: string = DEFAULT_ODF_CONSOLE_USER_SETTINGS_KEY +): [T, React.Dispatch>] => { + // Mount status for safty state updates + const mounted = React.useRef(true); + React.useEffect(() => () => (mounted.current = false), []); + const keyRef = React.useRef( + userSettingsKey?.replace(/[^-._a-zA-Z0-9]/g, '_') + ); + + const [data, setData] = React.useState(() => + initializeDataFromLocalStorage(storageKey, keyRef.current, defaultValue) + ); + const dataRef = React.useRef(data); + dataRef.current = data; + + // Sync latest user settings across all tabs. + const syncLatestData = React.useCallback( + (event: StorageEvent) => + syncLatestDataFromLocalStorage( + mounted.current, + storageKey, + event.storageArea, + event.key, + event.newValue, + dataRef.current, + keyRef.current, + setData + ), + [storageKey] + ); + + React.useEffect(() => { + if (sync) { + window.addEventListener(STORAGE_EVENT, syncLatestData); + } + return () => { + if (sync) { + window.removeEventListener(STORAGE_EVENT, syncLatestData); + } + }; + }, [syncLatestData, sync]); + + const updateData = React.useCallback>>( + (action: React.SetStateAction) => { + const previousData = dataRef.current; + const newState = + typeof action === 'function' + ? (action as (prevState: T) => T)(previousData) + : action; + const localData = getDataFromLocalStorage(storageKey); + if ( + newState !== undefined && + serializeData(newState) !== serializeData(localData?.[keyRef.current]) + ) { + // Update settings changes for current tab + if (mounted.current) { + setData(newState); + } + // Update user settings changes in local stroage + updateLocalStorage(storageKey, keyRef.current, localData, newState); + } + }, + [storageKey] + ); + + return [data, updateData]; +}; diff --git a/packages/shared/src/index.ts b/packages/shared/src/index.ts index d684ce081..063c2d411 100644 --- a/packages/shared/src/index.ts +++ b/packages/shared/src/index.ts @@ -33,3 +33,4 @@ export * from './yup-validation-resolver'; export * from './file-handling'; export * from './text-inputs'; export * from './label-expression-selector'; +export * from './empty-state-page'; diff --git a/packages/shared/src/s3/types.ts b/packages/shared/src/s3/types.ts index 025d06914..bebe9c3e5 100644 --- a/packages/shared/src/s3/types.ts +++ b/packages/shared/src/s3/types.ts @@ -43,3 +43,7 @@ export type GetObject = ( export type DeleteObjects = ( input: DeleteObjectsCommandInput ) => Promise; + +export type ListCommandOutput = + | ListObjectsV2CommandOutput + | ListBucketsCommandOutput; diff --git a/packages/shared/src/table/composable-table.tsx b/packages/shared/src/table/composable-table.tsx index 83f9b2a92..5baf8d9f1 100644 --- a/packages/shared/src/table/composable-table.tsx +++ b/packages/shared/src/table/composable-table.tsx @@ -12,6 +12,7 @@ import { Tr, } from '@patternfly/react-table'; import { useSortList } from '../hooks/sort-list'; +import { useCustomTranslation } from '../useCustomTranslationHook'; export type TableColumnProps = ThProps & { thProps?: TableThProps; @@ -38,6 +39,7 @@ export const ComposableTable: ComposableTableProps = < noDataMsg, emptyRowMessage, variant, + isFavorites, }) => { const { onSort, @@ -45,8 +47,10 @@ export const ComposableTable: ComposableTableProps = < sortDirection: activeSortDirection, sortedData: sortedRows, } = useSortList(rows, columns, false); + const { t } = useCustomTranslation(); const getSortParams = (columnIndex: number): ThProps['sort'] => ({ + ...(isFavorites ? { isFavorites: columnIndex === 0 } : {}), sortBy: { index: activeSortIndex, direction: activeSortDirection, @@ -67,7 +71,7 @@ export const ComposableTable: ComposableTableProps = < > @@ -114,6 +118,7 @@ export type TableProps = { noDataMsg?: React.FC; emptyRowMessage?: React.FC; variant?: TableVariant; + isFavorites?: boolean; }; type ComposableTableProps = ( diff --git a/packages/shared/src/utils/table.ts b/packages/shared/src/utils/table.ts index bd5900b3b..288eab2d1 100644 --- a/packages/shared/src/utils/table.ts +++ b/packages/shared/src/utils/table.ts @@ -1,15 +1,24 @@ import * as _ from 'lodash-es'; import { SortByDirection } from '@patternfly/react-table'; +const sort = (aValue: any, bValue: any, c: SortByDirection) => { + const negation = c !== SortByDirection.asc; + const sortVal = aValue.localeCompare(bValue); + return negation ? -sortVal : sortVal; +}; + export const sortRows = ( a: any, b: any, c: SortByDirection, - sortField: string + sortField: string, + favoriteNames?: string[] ) => { - const negation = c !== SortByDirection.asc; - const aValue = _.get(a, sortField, '').toString(); - const bValue = _.get(b, sortField, ''); - const sortVal = String(aValue).localeCompare(String(bValue)); - return negation ? -sortVal : sortVal; + let aValue = _.get(a, sortField, '').toString(); + let bValue = _.get(b, sortField, '').toString(); + if (!!favoriteNames) { + aValue = favoriteNames.includes(aValue).toString(); + bValue = favoriteNames.includes(bValue).toString(); + } + return sort(aValue, bValue, c); }; diff --git a/plugins/odf/console-extensions.json b/plugins/odf/console-extensions.json index 3b33b6a21..cf76c0585 100644 --- a/plugins/odf/console-extensions.json +++ b/plugins/odf/console-extensions.json @@ -540,11 +540,27 @@ "required": ["ODF_MODEL"] } }, + { + "type": "odf.horizontalNav/tab", + "properties": { + "id": "buckets", + "name": "%plugin__odf-console~Buckets%", + "contextId": "odf-object-service", + "href": "buckets", + "component": { + "$codeRef": "s3BucketList.default" + } + }, + "flags": { + "required": ["MCG_STANDALONE", "ODF_ADMIN"] + } + }, { "type": "odf.horizontalNav/tab", "properties": { "id": "backing-store", "name": "%plugin__odf-console~Backing Store%", + "after": "buckets", "contextId": "odf-object-service", "href": "noobaa.io~v1alpha1~BackingStore", "component": { @@ -600,7 +616,8 @@ } }, "flags": { - "required": ["MCG"] + "required": ["MCG"], + "disallowed": ["MCG_STANDALONE"] } }, { diff --git a/plugins/odf/console-plugin.json b/plugins/odf/console-plugin.json index e3d350199..5b6222ca3 100644 --- a/plugins/odf/console-plugin.json +++ b/plugins/odf/console-plugin.json @@ -42,6 +42,7 @@ "odfReduxReducers": "@odf/core/redux", "monCountAlertModal": "@odf/core/modals/configure-mons/configure-mons", "storageConsumerListPage": "@odf/core/components/storage-consumers/client-list", - "s3BucketOverview": "@odf/core/components/s3-browser/bucket-overview/BucketOverview" + "s3BucketOverview": "@odf/core/components/s3-browser/bucket-overview/BucketOverview", + "s3BucketList": "@odf/core/components/s3-browser/buckets-list-page/bucketsListPage" } } diff --git a/yarn.lock b/yarn.lock index 58d939acb..363e098b2 100644 --- a/yarn.lock +++ b/yarn.lock @@ -83,385 +83,398 @@ "@smithy/util-utf8" "^2.0.0" tslib "^2.6.2" -"@aws-sdk/client-s3@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.614.0.tgz#39620491e328d86282d0f9105fde7dd59427b4a1" - integrity sha512-9BlhfeBegvyjOqHtcr9kvrT80wiy7EVUiqYyTFiiDv/hJIcG88XHQCZdLU7658XBkQ7aFrr5b8rF2HRD1oroxw== +"@aws-sdk/client-s3@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-s3/-/client-s3-3.667.0.tgz#06fb8ba8d171c6fdc292fd8544f9b7f9f83d4974" + integrity sha512-WKkjRJe93epfIWZa+PUgvMvDQ7IObr4poxqx/3YIsl8FXMSgJP5Woc1kdjeRrfpPWHGTm9O1Bi7XFulzEzUwQA== dependencies: "@aws-crypto/sha1-browser" "5.2.0" "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/client-sso-oidc" "3.614.0" - "@aws-sdk/client-sts" "3.614.0" - "@aws-sdk/core" "3.614.0" - "@aws-sdk/credential-provider-node" "3.614.0" - "@aws-sdk/middleware-bucket-endpoint" "3.614.0" - "@aws-sdk/middleware-expect-continue" "3.609.0" - "@aws-sdk/middleware-flexible-checksums" "3.614.0" - "@aws-sdk/middleware-host-header" "3.609.0" - "@aws-sdk/middleware-location-constraint" "3.609.0" - "@aws-sdk/middleware-logger" "3.609.0" - "@aws-sdk/middleware-recursion-detection" "3.609.0" - "@aws-sdk/middleware-sdk-s3" "3.614.0" - "@aws-sdk/middleware-signing" "3.609.0" - "@aws-sdk/middleware-ssec" "3.609.0" - "@aws-sdk/middleware-user-agent" "3.614.0" - "@aws-sdk/region-config-resolver" "3.614.0" - "@aws-sdk/signature-v4-multi-region" "3.614.0" - "@aws-sdk/types" "3.609.0" - "@aws-sdk/util-endpoints" "3.614.0" - "@aws-sdk/util-user-agent-browser" "3.609.0" - "@aws-sdk/util-user-agent-node" "3.614.0" - "@aws-sdk/xml-builder" "3.609.0" - "@smithy/config-resolver" "^3.0.5" - "@smithy/core" "^2.2.6" - "@smithy/eventstream-serde-browser" "^3.0.4" - "@smithy/eventstream-serde-config-resolver" "^3.0.3" - "@smithy/eventstream-serde-node" "^3.0.4" - "@smithy/fetch-http-handler" "^3.2.1" - "@smithy/hash-blob-browser" "^3.1.2" - "@smithy/hash-node" "^3.0.3" - "@smithy/hash-stream-node" "^3.1.2" - "@smithy/invalid-dependency" "^3.0.3" - "@smithy/md5-js" "^3.0.3" - "@smithy/middleware-content-length" "^3.0.3" - "@smithy/middleware-endpoint" "^3.0.5" - "@smithy/middleware-retry" "^3.0.9" - "@smithy/middleware-serde" "^3.0.3" - "@smithy/middleware-stack" "^3.0.3" - "@smithy/node-config-provider" "^3.1.4" - "@smithy/node-http-handler" "^3.1.2" - "@smithy/protocol-http" "^4.0.3" - "@smithy/smithy-client" "^3.1.7" - "@smithy/types" "^3.3.0" - "@smithy/url-parser" "^3.0.3" + "@aws-sdk/client-sso-oidc" "3.667.0" + "@aws-sdk/client-sts" "3.667.0" + "@aws-sdk/core" "3.667.0" + "@aws-sdk/credential-provider-node" "3.667.0" + "@aws-sdk/middleware-bucket-endpoint" "3.667.0" + "@aws-sdk/middleware-expect-continue" "3.667.0" + "@aws-sdk/middleware-flexible-checksums" "3.667.0" + "@aws-sdk/middleware-host-header" "3.667.0" + "@aws-sdk/middleware-location-constraint" "3.667.0" + "@aws-sdk/middleware-logger" "3.667.0" + "@aws-sdk/middleware-recursion-detection" "3.667.0" + "@aws-sdk/middleware-sdk-s3" "3.667.0" + "@aws-sdk/middleware-ssec" "3.667.0" + "@aws-sdk/middleware-user-agent" "3.667.0" + "@aws-sdk/region-config-resolver" "3.667.0" + "@aws-sdk/signature-v4-multi-region" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@aws-sdk/util-endpoints" "3.667.0" + "@aws-sdk/util-user-agent-browser" "3.667.0" + "@aws-sdk/util-user-agent-node" "3.667.0" + "@aws-sdk/xml-builder" "3.662.0" + "@smithy/config-resolver" "^3.0.9" + "@smithy/core" "^2.4.8" + "@smithy/eventstream-serde-browser" "^3.0.10" + "@smithy/eventstream-serde-config-resolver" "^3.0.7" + "@smithy/eventstream-serde-node" "^3.0.9" + "@smithy/fetch-http-handler" "^3.2.9" + "@smithy/hash-blob-browser" "^3.1.6" + "@smithy/hash-node" "^3.0.7" + "@smithy/hash-stream-node" "^3.1.6" + "@smithy/invalid-dependency" "^3.0.7" + "@smithy/md5-js" "^3.0.7" + "@smithy/middleware-content-length" "^3.0.9" + "@smithy/middleware-endpoint" "^3.1.4" + "@smithy/middleware-retry" "^3.0.23" + "@smithy/middleware-serde" "^3.0.7" + "@smithy/middleware-stack" "^3.0.7" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/node-http-handler" "^3.2.4" + "@smithy/protocol-http" "^4.1.4" + "@smithy/smithy-client" "^3.4.0" + "@smithy/types" "^3.5.0" + "@smithy/url-parser" "^3.0.7" "@smithy/util-base64" "^3.0.0" "@smithy/util-body-length-browser" "^3.0.0" "@smithy/util-body-length-node" "^3.0.0" - "@smithy/util-defaults-mode-browser" "^3.0.9" - "@smithy/util-defaults-mode-node" "^3.0.9" - "@smithy/util-endpoints" "^2.0.5" - "@smithy/util-retry" "^3.0.3" - "@smithy/util-stream" "^3.0.6" + "@smithy/util-defaults-mode-browser" "^3.0.23" + "@smithy/util-defaults-mode-node" "^3.0.23" + "@smithy/util-endpoints" "^2.1.3" + "@smithy/util-middleware" "^3.0.7" + "@smithy/util-retry" "^3.0.7" + "@smithy/util-stream" "^3.1.9" "@smithy/util-utf8" "^3.0.0" - "@smithy/util-waiter" "^3.1.2" + "@smithy/util-waiter" "^3.1.6" tslib "^2.6.2" -"@aws-sdk/client-sso-oidc@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.614.0.tgz#61d20af829a17aa15664bcb7a1b4aed165191435" - integrity sha512-BI1NWcpppbHg/28zbUg54dZeckork8BItZIcjls12vxasy+p3iEzrJVG60jcbUTTsk3Qc1tyxNfrdcVqx0y7Ww== +"@aws-sdk/client-sso-oidc@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.667.0.tgz#36b6e602f2c9b5f0fbbf3630fbd88908d883256f" + integrity sha512-ThLLR0Zn15Rk8Y6rzzVtHREZU4NAsNj9oCiQcXj4/vlBl+J0MbiTCDUJTc559O+DIMekrjusLaPIKfTZmXXuhA== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.614.0" - "@aws-sdk/credential-provider-node" "3.614.0" - "@aws-sdk/middleware-host-header" "3.609.0" - "@aws-sdk/middleware-logger" "3.609.0" - "@aws-sdk/middleware-recursion-detection" "3.609.0" - "@aws-sdk/middleware-user-agent" "3.614.0" - "@aws-sdk/region-config-resolver" "3.614.0" - "@aws-sdk/types" "3.609.0" - "@aws-sdk/util-endpoints" "3.614.0" - "@aws-sdk/util-user-agent-browser" "3.609.0" - "@aws-sdk/util-user-agent-node" "3.614.0" - "@smithy/config-resolver" "^3.0.5" - "@smithy/core" "^2.2.6" - "@smithy/fetch-http-handler" "^3.2.1" - "@smithy/hash-node" "^3.0.3" - "@smithy/invalid-dependency" "^3.0.3" - "@smithy/middleware-content-length" "^3.0.3" - "@smithy/middleware-endpoint" "^3.0.5" - "@smithy/middleware-retry" "^3.0.9" - "@smithy/middleware-serde" "^3.0.3" - "@smithy/middleware-stack" "^3.0.3" - "@smithy/node-config-provider" "^3.1.4" - "@smithy/node-http-handler" "^3.1.2" - "@smithy/protocol-http" "^4.0.3" - "@smithy/smithy-client" "^3.1.7" - "@smithy/types" "^3.3.0" - "@smithy/url-parser" "^3.0.3" + "@aws-sdk/core" "3.667.0" + "@aws-sdk/credential-provider-node" "3.667.0" + "@aws-sdk/middleware-host-header" "3.667.0" + "@aws-sdk/middleware-logger" "3.667.0" + "@aws-sdk/middleware-recursion-detection" "3.667.0" + "@aws-sdk/middleware-user-agent" "3.667.0" + "@aws-sdk/region-config-resolver" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@aws-sdk/util-endpoints" "3.667.0" + "@aws-sdk/util-user-agent-browser" "3.667.0" + "@aws-sdk/util-user-agent-node" "3.667.0" + "@smithy/config-resolver" "^3.0.9" + "@smithy/core" "^2.4.8" + "@smithy/fetch-http-handler" "^3.2.9" + "@smithy/hash-node" "^3.0.7" + "@smithy/invalid-dependency" "^3.0.7" + "@smithy/middleware-content-length" "^3.0.9" + "@smithy/middleware-endpoint" "^3.1.4" + "@smithy/middleware-retry" "^3.0.23" + "@smithy/middleware-serde" "^3.0.7" + "@smithy/middleware-stack" "^3.0.7" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/node-http-handler" "^3.2.4" + "@smithy/protocol-http" "^4.1.4" + "@smithy/smithy-client" "^3.4.0" + "@smithy/types" "^3.5.0" + "@smithy/url-parser" "^3.0.7" "@smithy/util-base64" "^3.0.0" "@smithy/util-body-length-browser" "^3.0.0" "@smithy/util-body-length-node" "^3.0.0" - "@smithy/util-defaults-mode-browser" "^3.0.9" - "@smithy/util-defaults-mode-node" "^3.0.9" - "@smithy/util-endpoints" "^2.0.5" - "@smithy/util-middleware" "^3.0.3" - "@smithy/util-retry" "^3.0.3" + "@smithy/util-defaults-mode-browser" "^3.0.23" + "@smithy/util-defaults-mode-node" "^3.0.23" + "@smithy/util-endpoints" "^2.1.3" + "@smithy/util-middleware" "^3.0.7" + "@smithy/util-retry" "^3.0.7" "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" -"@aws-sdk/client-sso@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.614.0.tgz#bf578a579c477e41cea61368fef5394f6ccae45a" - integrity sha512-p5pyYaxRzBttjBkqfc8i3K7DzBdTg3ECdVgBo6INIUxfvDy0J8QUE8vNtCgvFIkq+uPw/8M+Eo4zzln7anuO0Q== +"@aws-sdk/client-sso@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sso/-/client-sso-3.667.0.tgz#87c3388ee0ed10a6d67fc48c92ff2dfdc73b1adf" + integrity sha512-69nl3BXcAfn/zUdxpxC/5Bi4K46sMgTRFVKHkyiRFO8OQpNJDRzl6eGltESLqtf65rjWfswTDwfYrMd2+tnlDQ== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/core" "3.614.0" - "@aws-sdk/middleware-host-header" "3.609.0" - "@aws-sdk/middleware-logger" "3.609.0" - "@aws-sdk/middleware-recursion-detection" "3.609.0" - "@aws-sdk/middleware-user-agent" "3.614.0" - "@aws-sdk/region-config-resolver" "3.614.0" - "@aws-sdk/types" "3.609.0" - "@aws-sdk/util-endpoints" "3.614.0" - "@aws-sdk/util-user-agent-browser" "3.609.0" - "@aws-sdk/util-user-agent-node" "3.614.0" - "@smithy/config-resolver" "^3.0.5" - "@smithy/core" "^2.2.6" - "@smithy/fetch-http-handler" "^3.2.1" - "@smithy/hash-node" "^3.0.3" - "@smithy/invalid-dependency" "^3.0.3" - "@smithy/middleware-content-length" "^3.0.3" - "@smithy/middleware-endpoint" "^3.0.5" - "@smithy/middleware-retry" "^3.0.9" - "@smithy/middleware-serde" "^3.0.3" - "@smithy/middleware-stack" "^3.0.3" - "@smithy/node-config-provider" "^3.1.4" - "@smithy/node-http-handler" "^3.1.2" - "@smithy/protocol-http" "^4.0.3" - "@smithy/smithy-client" "^3.1.7" - "@smithy/types" "^3.3.0" - "@smithy/url-parser" "^3.0.3" + "@aws-sdk/core" "3.667.0" + "@aws-sdk/middleware-host-header" "3.667.0" + "@aws-sdk/middleware-logger" "3.667.0" + "@aws-sdk/middleware-recursion-detection" "3.667.0" + "@aws-sdk/middleware-user-agent" "3.667.0" + "@aws-sdk/region-config-resolver" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@aws-sdk/util-endpoints" "3.667.0" + "@aws-sdk/util-user-agent-browser" "3.667.0" + "@aws-sdk/util-user-agent-node" "3.667.0" + "@smithy/config-resolver" "^3.0.9" + "@smithy/core" "^2.4.8" + "@smithy/fetch-http-handler" "^3.2.9" + "@smithy/hash-node" "^3.0.7" + "@smithy/invalid-dependency" "^3.0.7" + "@smithy/middleware-content-length" "^3.0.9" + "@smithy/middleware-endpoint" "^3.1.4" + "@smithy/middleware-retry" "^3.0.23" + "@smithy/middleware-serde" "^3.0.7" + "@smithy/middleware-stack" "^3.0.7" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/node-http-handler" "^3.2.4" + "@smithy/protocol-http" "^4.1.4" + "@smithy/smithy-client" "^3.4.0" + "@smithy/types" "^3.5.0" + "@smithy/url-parser" "^3.0.7" "@smithy/util-base64" "^3.0.0" "@smithy/util-body-length-browser" "^3.0.0" "@smithy/util-body-length-node" "^3.0.0" - "@smithy/util-defaults-mode-browser" "^3.0.9" - "@smithy/util-defaults-mode-node" "^3.0.9" - "@smithy/util-endpoints" "^2.0.5" - "@smithy/util-middleware" "^3.0.3" - "@smithy/util-retry" "^3.0.3" + "@smithy/util-defaults-mode-browser" "^3.0.23" + "@smithy/util-defaults-mode-node" "^3.0.23" + "@smithy/util-endpoints" "^2.1.3" + "@smithy/util-middleware" "^3.0.7" + "@smithy/util-retry" "^3.0.7" "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" -"@aws-sdk/client-sts@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.614.0.tgz#bb688944e54f147c8093e2d79b618263ee43cb19" - integrity sha512-i6QmaVA1KHHYNnI2VYQy/sc31rLm4+jSp8b/YbQpFnD0w3aXsrEEHHlxek45uSkHb4Nrj1omFBVy/xp1WVYx2Q== +"@aws-sdk/client-sts@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/client-sts/-/client-sts-3.667.0.tgz#c9e62336449b5f290de62afdbb437531fee777e1" + integrity sha512-SnvkDDuOAwXOxzhGfvvxK8JFFVApVvXrM6+nVmSYwuHjWdI+HwNcsRC6rxZ8uHQEz2fR0a810ckUwFVfpvtIoA== dependencies: "@aws-crypto/sha256-browser" "5.2.0" "@aws-crypto/sha256-js" "5.2.0" - "@aws-sdk/client-sso-oidc" "3.614.0" - "@aws-sdk/core" "3.614.0" - "@aws-sdk/credential-provider-node" "3.614.0" - "@aws-sdk/middleware-host-header" "3.609.0" - "@aws-sdk/middleware-logger" "3.609.0" - "@aws-sdk/middleware-recursion-detection" "3.609.0" - "@aws-sdk/middleware-user-agent" "3.614.0" - "@aws-sdk/region-config-resolver" "3.614.0" - "@aws-sdk/types" "3.609.0" - "@aws-sdk/util-endpoints" "3.614.0" - "@aws-sdk/util-user-agent-browser" "3.609.0" - "@aws-sdk/util-user-agent-node" "3.614.0" - "@smithy/config-resolver" "^3.0.5" - "@smithy/core" "^2.2.6" - "@smithy/fetch-http-handler" "^3.2.1" - "@smithy/hash-node" "^3.0.3" - "@smithy/invalid-dependency" "^3.0.3" - "@smithy/middleware-content-length" "^3.0.3" - "@smithy/middleware-endpoint" "^3.0.5" - "@smithy/middleware-retry" "^3.0.9" - "@smithy/middleware-serde" "^3.0.3" - "@smithy/middleware-stack" "^3.0.3" - "@smithy/node-config-provider" "^3.1.4" - "@smithy/node-http-handler" "^3.1.2" - "@smithy/protocol-http" "^4.0.3" - "@smithy/smithy-client" "^3.1.7" - "@smithy/types" "^3.3.0" - "@smithy/url-parser" "^3.0.3" + "@aws-sdk/client-sso-oidc" "3.667.0" + "@aws-sdk/core" "3.667.0" + "@aws-sdk/credential-provider-node" "3.667.0" + "@aws-sdk/middleware-host-header" "3.667.0" + "@aws-sdk/middleware-logger" "3.667.0" + "@aws-sdk/middleware-recursion-detection" "3.667.0" + "@aws-sdk/middleware-user-agent" "3.667.0" + "@aws-sdk/region-config-resolver" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@aws-sdk/util-endpoints" "3.667.0" + "@aws-sdk/util-user-agent-browser" "3.667.0" + "@aws-sdk/util-user-agent-node" "3.667.0" + "@smithy/config-resolver" "^3.0.9" + "@smithy/core" "^2.4.8" + "@smithy/fetch-http-handler" "^3.2.9" + "@smithy/hash-node" "^3.0.7" + "@smithy/invalid-dependency" "^3.0.7" + "@smithy/middleware-content-length" "^3.0.9" + "@smithy/middleware-endpoint" "^3.1.4" + "@smithy/middleware-retry" "^3.0.23" + "@smithy/middleware-serde" "^3.0.7" + "@smithy/middleware-stack" "^3.0.7" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/node-http-handler" "^3.2.4" + "@smithy/protocol-http" "^4.1.4" + "@smithy/smithy-client" "^3.4.0" + "@smithy/types" "^3.5.0" + "@smithy/url-parser" "^3.0.7" "@smithy/util-base64" "^3.0.0" "@smithy/util-body-length-browser" "^3.0.0" "@smithy/util-body-length-node" "^3.0.0" - "@smithy/util-defaults-mode-browser" "^3.0.9" - "@smithy/util-defaults-mode-node" "^3.0.9" - "@smithy/util-endpoints" "^2.0.5" - "@smithy/util-middleware" "^3.0.3" - "@smithy/util-retry" "^3.0.3" + "@smithy/util-defaults-mode-browser" "^3.0.23" + "@smithy/util-defaults-mode-node" "^3.0.23" + "@smithy/util-endpoints" "^2.1.3" + "@smithy/util-middleware" "^3.0.7" + "@smithy/util-retry" "^3.0.7" "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" -"@aws-sdk/core@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.614.0.tgz#7d4ce96cd98f85eb2dd0627586581296b6a26662" - integrity sha512-BUuS5/1YkgmKc4J0bg83XEtMyDHVyqG2QDzfmhYe8gbOIZabUl1FlrFVwhCAthtrrI6MPGTQcERB4BtJKUSplw== - dependencies: - "@smithy/core" "^2.2.6" - "@smithy/protocol-http" "^4.0.3" - "@smithy/signature-v4" "^3.1.2" - "@smithy/smithy-client" "^3.1.7" - "@smithy/types" "^3.3.0" - fast-xml-parser "4.2.5" +"@aws-sdk/core@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/core/-/core-3.667.0.tgz#ecf93bf8e3ebea3bd972576a67b87dd291d7a90a" + integrity sha512-pMcDVI7Tmdsc8R3sDv0Omj/4iRParGY+uJtAfF669WnZfDfaBQaix2Mq7+Mu08vdjqO9K3gicFvjk9S1VLmOKA== + dependencies: + "@aws-sdk/types" "3.667.0" + "@smithy/core" "^2.4.8" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/property-provider" "^3.1.7" + "@smithy/protocol-http" "^4.1.4" + "@smithy/signature-v4" "^4.2.0" + "@smithy/smithy-client" "^3.4.0" + "@smithy/types" "^3.5.0" + "@smithy/util-middleware" "^3.0.7" + fast-xml-parser "4.4.1" tslib "^2.6.2" -"@aws-sdk/credential-provider-env@3.609.0": - version "3.609.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.609.0.tgz#b3f32e5a8ff8b541e151eadadfb60283aa3d835e" - integrity sha512-v69ZCWcec2iuV9vLVJMa6fAb5xwkzN4jYIT8yjo2c4Ia/j976Q+TPf35Pnz5My48Xr94EFcaBazrWedF+kwfuQ== +"@aws-sdk/credential-provider-env@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-env/-/credential-provider-env-3.667.0.tgz#1b3a4b049fc164a3a3eb3617f7448fed3cb3a2db" + integrity sha512-zZbrkkaPc54WXm+QAnpuv0LPNfsts0HPPd+oCECGs7IQRaFsGj187cwvPg9RMWDFZqpm64MdBDoA8OQHsqzYCw== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/property-provider" "^3.1.3" - "@smithy/types" "^3.3.0" + "@aws-sdk/core" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@smithy/property-provider" "^3.1.7" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@aws-sdk/credential-provider-http@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.614.0.tgz#2cdc07e029447182ada8ee18dcdb6bccddc57da5" - integrity sha512-YIEjlNUKb3Vo/iTnGAPdsiDC3FUUnNoex2OwU8LmR7AkYZiWdB8nx99DfgkkY+OFMUpw7nKD2PCOtuFONelfGA== - dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/fetch-http-handler" "^3.2.1" - "@smithy/node-http-handler" "^3.1.2" - "@smithy/property-provider" "^3.1.3" - "@smithy/protocol-http" "^4.0.3" - "@smithy/smithy-client" "^3.1.7" - "@smithy/types" "^3.3.0" - "@smithy/util-stream" "^3.0.6" +"@aws-sdk/credential-provider-http@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-http/-/credential-provider-http-3.667.0.tgz#ff78b7f76715a7456976930bff6221dfac70afbc" + integrity sha512-sjtybFfERZWiqTY7fswBxKQLvUkiCucOWyqh3IaPo/4nE1PXRnaZCVG0+kRBPrYIxWqiVwytvZzMJy8sVZcG0A== + dependencies: + "@aws-sdk/core" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@smithy/fetch-http-handler" "^3.2.9" + "@smithy/node-http-handler" "^3.2.4" + "@smithy/property-provider" "^3.1.7" + "@smithy/protocol-http" "^4.1.4" + "@smithy/smithy-client" "^3.4.0" + "@smithy/types" "^3.5.0" + "@smithy/util-stream" "^3.1.9" tslib "^2.6.2" -"@aws-sdk/credential-provider-ini@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.614.0.tgz#5c3e514d09d37aad167ab3571d10fb18c182ba5e" - integrity sha512-KfLuLFGwlvFSZ2MuzYwWGPb1y5TeiwX5okIDe0aQ1h10oD3924FXbN+mabOnUHQ8EFcGAtCaWbrC86mI7ktC6A== - dependencies: - "@aws-sdk/credential-provider-env" "3.609.0" - "@aws-sdk/credential-provider-http" "3.614.0" - "@aws-sdk/credential-provider-process" "3.614.0" - "@aws-sdk/credential-provider-sso" "3.614.0" - "@aws-sdk/credential-provider-web-identity" "3.609.0" - "@aws-sdk/types" "3.609.0" - "@smithy/credential-provider-imds" "^3.1.4" - "@smithy/property-provider" "^3.1.3" - "@smithy/shared-ini-file-loader" "^3.1.4" - "@smithy/types" "^3.3.0" +"@aws-sdk/credential-provider-ini@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.667.0.tgz#2b267ca38e8e049889e70eaa99b621a00e0568f6" + integrity sha512-NiEC2Sjut57ajbWEXLFtA8YWA06ulfuaSHOP4YxoQEsL3BjMOkKS1/5eVW2o6XkKVbwt0zbDYSTlIxU5klHpbQ== + dependencies: + "@aws-sdk/core" "3.667.0" + "@aws-sdk/credential-provider-env" "3.667.0" + "@aws-sdk/credential-provider-http" "3.667.0" + "@aws-sdk/credential-provider-process" "3.667.0" + "@aws-sdk/credential-provider-sso" "3.667.0" + "@aws-sdk/credential-provider-web-identity" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@smithy/credential-provider-imds" "^3.2.4" + "@smithy/property-provider" "^3.1.7" + "@smithy/shared-ini-file-loader" "^3.1.8" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@aws-sdk/credential-provider-node@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.614.0.tgz#5faf5e3bf02ccb891769e4a28c784a80be42dcfc" - integrity sha512-4J6gPEuFZP0mkWq5E//oMS1vrmMM88iNNcv7TEljYnsc6JTAlKejCyFwx6CN+nkIhmIZsl06SXIhBemzBdBPfg== - dependencies: - "@aws-sdk/credential-provider-env" "3.609.0" - "@aws-sdk/credential-provider-http" "3.614.0" - "@aws-sdk/credential-provider-ini" "3.614.0" - "@aws-sdk/credential-provider-process" "3.614.0" - "@aws-sdk/credential-provider-sso" "3.614.0" - "@aws-sdk/credential-provider-web-identity" "3.609.0" - "@aws-sdk/types" "3.609.0" - "@smithy/credential-provider-imds" "^3.1.4" - "@smithy/property-provider" "^3.1.3" - "@smithy/shared-ini-file-loader" "^3.1.4" - "@smithy/types" "^3.3.0" +"@aws-sdk/credential-provider-node@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-node/-/credential-provider-node-3.667.0.tgz#e73a8d992763c41bb52768a981dff7309cd9b044" + integrity sha512-+2oNexDvbQD9o5Xdtu1mGE25Nf2/C9KgMnkZzenbgCegw0P0YRdGrJklDF5Aag6lmb80a2vjoViuvm1ORzRAzw== + dependencies: + "@aws-sdk/credential-provider-env" "3.667.0" + "@aws-sdk/credential-provider-http" "3.667.0" + "@aws-sdk/credential-provider-ini" "3.667.0" + "@aws-sdk/credential-provider-process" "3.667.0" + "@aws-sdk/credential-provider-sso" "3.667.0" + "@aws-sdk/credential-provider-web-identity" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@smithy/credential-provider-imds" "^3.2.4" + "@smithy/property-provider" "^3.1.7" + "@smithy/shared-ini-file-loader" "^3.1.8" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@aws-sdk/credential-provider-process@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.614.0.tgz#b6b9382346dfe51c8fb448595ae55b930532c897" - integrity sha512-Q0SI0sTRwi8iNODLs5+bbv8vgz8Qy2QdxbCHnPk/6Cx6LMf7i3dqmWquFbspqFRd8QiqxStrblwxrUYZi09tkA== +"@aws-sdk/credential-provider-process@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-process/-/credential-provider-process-3.667.0.tgz#fa721b1b5b0024156c3852a9fc92c0ed9935959f" + integrity sha512-HZHnvop32fKgsNHkdhVaul7UzQ25sEc0j9yqA4bjhtbk0ECl42kj3f1pJ+ZU/YD9ut8lMJs/vVqiOdNThVdeBw== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/property-provider" "^3.1.3" - "@smithy/shared-ini-file-loader" "^3.1.4" - "@smithy/types" "^3.3.0" + "@aws-sdk/core" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@smithy/property-provider" "^3.1.7" + "@smithy/shared-ini-file-loader" "^3.1.8" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@aws-sdk/credential-provider-sso@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.614.0.tgz#926de80b2f9288469604442bf2a395c5f2bf913d" - integrity sha512-55+gp0JY4451cWI1qXmVMFM0GQaBKiQpXv2P0xmd9P3qLDyeFUSEW8XPh0d2lb1ICr6x4s47ynXVdGCIv2mXMg== - dependencies: - "@aws-sdk/client-sso" "3.614.0" - "@aws-sdk/token-providers" "3.614.0" - "@aws-sdk/types" "3.609.0" - "@smithy/property-provider" "^3.1.3" - "@smithy/shared-ini-file-loader" "^3.1.4" - "@smithy/types" "^3.3.0" +"@aws-sdk/credential-provider-sso@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.667.0.tgz#c1154b30c07279b01e56ed5bd787bce84bb68afd" + integrity sha512-GylJquSQVWlziaEmrX38KzQTWcFL5NKht4OAj7rdo75MssC0qNVSGT+ReFrXZzKQ65eIuRVCMdsp83oNH4nzbQ== + dependencies: + "@aws-sdk/client-sso" "3.667.0" + "@aws-sdk/core" "3.667.0" + "@aws-sdk/token-providers" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@smithy/property-provider" "^3.1.7" + "@smithy/shared-ini-file-loader" "^3.1.8" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@aws-sdk/credential-provider-web-identity@3.609.0": - version "3.609.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.609.0.tgz#d29222d6894347ee89c781ea090d388656df1d2a" - integrity sha512-U+PG8NhlYYF45zbr1km3ROtBMYqyyj/oK8NRp++UHHeuavgrP+4wJ4wQnlEaKvJBjevfo3+dlIBcaeQ7NYejWg== +"@aws-sdk/credential-provider-web-identity@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.667.0.tgz#439e3aa2fc9a081de53186f6d8aa78a8a6913769" + integrity sha512-t8CFlZMD/1p/8Cli3rvRiTJpjr/8BO64gw166AHgFZYSN2h95L2l1tcW0jpsc3PprA32nLg1iQVKYt4WGM4ugw== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/property-provider" "^3.1.3" - "@smithy/types" "^3.3.0" + "@aws-sdk/core" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@smithy/property-provider" "^3.1.7" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@aws-sdk/middleware-bucket-endpoint@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.614.0.tgz#28a99d82a0e1f039fda20aa0dc375ec777bd595c" - integrity sha512-TqEY8KcZeZ0LIxXaqG9RSSNnDHvD8RAFP4Xenwsxqnyad0Yn7LgCoFwRByelJ0t54ROYL1/ETJleWE4U4TOXdg== +"@aws-sdk/middleware-bucket-endpoint@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-bucket-endpoint/-/middleware-bucket-endpoint-3.667.0.tgz#bd0a0a24f71d3709debf6e48f4e503547398e7eb" + integrity sha512-XGz4jMAkDoTyFdtLz7ZF+C05IAhCTC1PllpvTBaj821z/L0ilhbqVhrT/f2Buw8Id/K5A390csGXgusXyrFFjA== dependencies: - "@aws-sdk/types" "3.609.0" + "@aws-sdk/types" "3.667.0" "@aws-sdk/util-arn-parser" "3.568.0" - "@smithy/node-config-provider" "^3.1.4" - "@smithy/protocol-http" "^4.0.3" - "@smithy/types" "^3.3.0" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/protocol-http" "^4.1.4" + "@smithy/types" "^3.5.0" "@smithy/util-config-provider" "^3.0.0" tslib "^2.6.2" -"@aws-sdk/middleware-expect-continue@3.609.0": - version "3.609.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.609.0.tgz#89af76f115aa5fadd5a82fe4e95a64cb15150517" - integrity sha512-+zeg//mSer4JZRxOB/4mUOMUJyuYPwATnIC5moBB8P8Xe+mJaVRFy8qlCtzYNj2TycnlsBPzTK0j7P1yvDh97w== +"@aws-sdk/middleware-expect-continue@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-expect-continue/-/middleware-expect-continue-3.667.0.tgz#d1b9e4871c8bde3402bdd0f73e740f5f5bf190d7" + integrity sha512-0TiSL9S5DSG95NHGIz6qTMuV7GDKVn8tvvGSrSSZu/wXO3JaYSH0AElVpYfc4PtPRqVpEyNA7nnc7W56mMCLWQ== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/protocol-http" "^4.0.3" - "@smithy/types" "^3.3.0" + "@aws-sdk/types" "3.667.0" + "@smithy/protocol-http" "^4.1.4" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@aws-sdk/middleware-flexible-checksums@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.614.0.tgz#e551aec40228e0891aee1648c6986ba82ea495c7" - integrity sha512-ZLpxVXMboDeMT7p2Kdp5m1uLVKOktkZoMgLvvbe3zbrU4Ji5IU5xVE0aa4X7H28BtuODCs6SLESnPs19bhMKlA== +"@aws-sdk/middleware-flexible-checksums@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-flexible-checksums/-/middleware-flexible-checksums-3.667.0.tgz#bbcbb211e844493d6e1cf0b4263b2ddfe876f44a" + integrity sha512-+5B2JuN+/CGZk5HRD9GeeNyTy9ooVFxdnuIAHkDyokJ028/isWw02tcM0rIcI/zK/maV3Z1WXDtkvWKTfB2IqQ== dependencies: "@aws-crypto/crc32" "5.2.0" "@aws-crypto/crc32c" "5.2.0" - "@aws-sdk/types" "3.609.0" + "@aws-sdk/core" "3.667.0" + "@aws-sdk/types" "3.667.0" "@smithy/is-array-buffer" "^3.0.0" - "@smithy/protocol-http" "^4.0.3" - "@smithy/types" "^3.3.0" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/protocol-http" "^4.1.4" + "@smithy/types" "^3.5.0" + "@smithy/util-middleware" "^3.0.7" "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" -"@aws-sdk/middleware-host-header@3.609.0": - version "3.609.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.609.0.tgz#844302cb905e4d09b9a1ea4bfa96729833068913" - integrity sha512-iTKfo158lc4jLDfYeZmYMIBHsn8m6zX+XB6birCSNZ/rrlzAkPbGE43CNdKfvjyWdqgLMRXF+B+OcZRvqhMXPQ== +"@aws-sdk/middleware-host-header@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-host-header/-/middleware-host-header-3.667.0.tgz#d255aa6e73aec9a2d1a241de737679b6d2723c3f" + integrity sha512-Z7fIAMQnPegs7JjAQvlOeWXwpMRfegh5eCoIP6VLJIeR6DLfYKbP35JBtt98R6DXslrN2RsbTogjbxPEDQfw1w== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/protocol-http" "^4.0.3" - "@smithy/types" "^3.3.0" + "@aws-sdk/types" "3.667.0" + "@smithy/protocol-http" "^4.1.4" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@aws-sdk/middleware-location-constraint@3.609.0": - version "3.609.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.609.0.tgz#7ed82d71e5ddcd50683ef2bbde10d1cc2492057e" - integrity sha512-xzsdoTkszGVqGVPjUmgoP7TORiByLueMHieI1fhQL888WPdqctwAx3ES6d/bA9Q/i8jnc6hs+Fjhy8UvBTkE9A== +"@aws-sdk/middleware-location-constraint@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-location-constraint/-/middleware-location-constraint-3.667.0.tgz#e5da0580656a1a385fd5783bb93ea320b4baeb1b" + integrity sha512-ob85H3HhT3/u5O+x0o557xGZ78vSNeSSwMaSitxdsfs2hOuoUl1uk+OeLpi1hkuJnL41FPpokV7TVII2XrFfmg== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/types" "^3.3.0" + "@aws-sdk/types" "3.667.0" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@aws-sdk/middleware-logger@3.609.0": - version "3.609.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.609.0.tgz#ed44d201f091b8bac908cbf14724c7a4d492553f" - integrity sha512-S62U2dy4jMDhDFDK5gZ4VxFdWzCtLzwbYyFZx2uvPYTECkepLUfzLic2BHg2Qvtu4QjX+oGE3P/7fwaGIsGNuQ== +"@aws-sdk/middleware-logger@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-logger/-/middleware-logger-3.667.0.tgz#bf072a1aa5b03239e20d75f9b525d8a990caf29f" + integrity sha512-PtTRNpNm/5c746jRgZCNg4X9xEJIwggkGJrF0GP9AB1ANg4pc/sF2Fvn1NtqPe9wtQ2stunJprnm5WkCHN7QiA== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/types" "^3.3.0" + "@aws-sdk/types" "3.667.0" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@aws-sdk/middleware-recursion-detection@3.609.0": - version "3.609.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.609.0.tgz#b7b869aaeac021a43dbea1435eaea81e5d2460b1" - integrity sha512-6sewsYB7/o/nbUfA99Aa/LokM+a/u4Wpm/X2o0RxOsDtSB795ObebLJe2BxY5UssbGaWkn7LswyfvrdZNXNj1w== +"@aws-sdk/middleware-recursion-detection@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.667.0.tgz#e3f158d5b5ea1b1d73ab280c0cbe5ef077ed3fdc" + integrity sha512-U5glWD3ehFohzpUpopLtmqAlDurGWo2wRGPNgi4SwhWU7UDt6LS7E/UvJjqC0CUrjlzOw+my2A+Ncf+fisMhxQ== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/protocol-http" "^4.0.3" - "@smithy/types" "^3.3.0" + "@aws-sdk/types" "3.667.0" + "@smithy/protocol-http" "^4.1.4" + "@smithy/types" "^3.5.0" tslib "^2.6.2" "@aws-sdk/middleware-sdk-s3@3.614.0": @@ -479,49 +492,58 @@ "@smithy/util-config-provider" "^3.0.0" tslib "^2.6.2" -"@aws-sdk/middleware-signing@3.609.0": - version "3.609.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-signing/-/middleware-signing-3.609.0.tgz#7e5c4e70302bf87a7aa3dfde83ec1b387bf819f0" - integrity sha512-2w3dBLjQVKIajYzokO4hduq8/0hSMUYHHmIo1Kdl+MSY8uwRBt12bLL6pyreobTcRMxizvn2ph/CQ9I1ST/WGQ== +"@aws-sdk/middleware-sdk-s3@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-sdk-s3/-/middleware-sdk-s3-3.667.0.tgz#269abce2bad4025201470413a070907dca065359" + integrity sha512-31SqWDEH340kwRyql6II4wgVTNa2GJypIry5bmEzuSR30tsuWnVQg8y7zgUCDanph2GnlIFp6U+vqC9R8kDRmw== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/property-provider" "^3.1.3" - "@smithy/protocol-http" "^4.0.3" - "@smithy/signature-v4" "^3.1.2" - "@smithy/types" "^3.3.0" - "@smithy/util-middleware" "^3.0.3" + "@aws-sdk/core" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@aws-sdk/util-arn-parser" "3.568.0" + "@smithy/core" "^2.4.8" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/protocol-http" "^4.1.4" + "@smithy/signature-v4" "^4.2.0" + "@smithy/smithy-client" "^3.4.0" + "@smithy/types" "^3.5.0" + "@smithy/util-config-provider" "^3.0.0" + "@smithy/util-middleware" "^3.0.7" + "@smithy/util-stream" "^3.1.9" + "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" -"@aws-sdk/middleware-ssec@3.609.0": - version "3.609.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.609.0.tgz#b87a8bc6133f3f6bdc6801183d0f9dad3f93cf9f" - integrity sha512-GZSD1s7+JswWOTamVap79QiDaIV7byJFssBW68GYjyRS5EBjNfwA/8s+6uE6g39R3ojyTbYOmvcANoZEhSULXg== +"@aws-sdk/middleware-ssec@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-ssec/-/middleware-ssec-3.667.0.tgz#19d510e4882c170eff33a5ced558781eee0ee716" + integrity sha512-1wuAUZIkmZIvOmGg5qNQU821CGFHhkuKioxXgNh0DpUxZ9+AeiV7yorJr+bqkb2KBFv1i1TnzGRecvKf/KvZIQ== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/types" "^3.3.0" + "@aws-sdk/types" "3.667.0" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@aws-sdk/middleware-user-agent@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.614.0.tgz#e6e3b5952db26a0452875c864d39d17707e4eccd" - integrity sha512-xUxh0UPQiMTG6E31Yvu6zVYlikrIcFDKljM11CaatInzvZubGTGiX0DjpqRlfGzUNsuPc/zNrKwRP2+wypgqIw== - dependencies: - "@aws-sdk/types" "3.609.0" - "@aws-sdk/util-endpoints" "3.614.0" - "@smithy/protocol-http" "^4.0.3" - "@smithy/types" "^3.3.0" +"@aws-sdk/middleware-user-agent@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.667.0.tgz#7bc4478d1b9d7a33e20eaa20378df751da8526bc" + integrity sha512-NJoPMV+9hpN90iZ2SgOpFmY6MJW71gGyT28kt0C68B0tBadYpT/J6WW8J7gxwdLA7d2CBwHbFGphTPWXXl+jzw== + dependencies: + "@aws-sdk/core" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@aws-sdk/util-endpoints" "3.667.0" + "@smithy/core" "^2.4.8" + "@smithy/protocol-http" "^4.1.4" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@aws-sdk/region-config-resolver@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.614.0.tgz#9cebb31a5bcfea2a41891fff7f28d0164cde179a" - integrity sha512-vDCeMXvic/LU0KFIUjpC3RiSTIkkvESsEfbVHiHH0YINfl8HnEqR5rj+L8+phsCeVg2+LmYwYxd5NRz4PHxt5g== +"@aws-sdk/region-config-resolver@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/region-config-resolver/-/region-config-resolver-3.667.0.tgz#1804103246e6b6c7586edc57d26801647d2972d8" + integrity sha512-iNr+JhhA902JMKHG9IwT9YdaEx6KGl6vjAL5BRNeOjfj4cZYMog6Lz/IlfOAltMtT0w88DAHDEFrBd2uO0l2eg== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/node-config-provider" "^3.1.4" - "@smithy/types" "^3.3.0" + "@aws-sdk/types" "3.667.0" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/types" "^3.5.0" "@smithy/util-config-provider" "^3.0.0" - "@smithy/util-middleware" "^3.0.3" + "@smithy/util-middleware" "^3.0.7" tslib "^2.6.2" "@aws-sdk/s3-request-presigner@3.614.0": @@ -550,15 +572,27 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" -"@aws-sdk/token-providers@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.614.0.tgz#88da04f6d4ce916b0b0f6e045676d04201fb47fd" - integrity sha512-okItqyY6L9IHdxqs+Z116y5/nda7rHxLvROxtAJdLavWTYDydxrZstImNgGWTeVdmc0xX2gJCI77UYUTQWnhRw== +"@aws-sdk/signature-v4-multi-region@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/signature-v4-multi-region/-/signature-v4-multi-region-3.667.0.tgz#4510327a9504d1e6e3d6af5ed69878f8023b8e1f" + integrity sha512-9HBgapQOvrb3qvZfPcIY41D3YRNfcOuyIKqZ3h9FYbM06qOZXmIN7Y8bYL31ANGR3Mce6yu3mcnaqvrC/j1Q1w== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/property-provider" "^3.1.3" - "@smithy/shared-ini-file-loader" "^3.1.4" - "@smithy/types" "^3.3.0" + "@aws-sdk/middleware-sdk-s3" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@smithy/protocol-http" "^4.1.4" + "@smithy/signature-v4" "^4.2.0" + "@smithy/types" "^3.5.0" + tslib "^2.6.2" + +"@aws-sdk/token-providers@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/token-providers/-/token-providers-3.667.0.tgz#ea990ef364d6bd75f0ebcf19a22f9ccd0edb3c41" + integrity sha512-ZecJlG8p6D4UTYlBHwOWX6nknVtw/OBJ3yPXTSajBjhUlj9lE2xvejI8gl4rqkyLXk7z3bki+KR4tATbMaM9yg== + dependencies: + "@aws-sdk/types" "3.667.0" + "@smithy/property-provider" "^3.1.7" + "@smithy/shared-ini-file-loader" "^3.1.8" + "@smithy/types" "^3.5.0" tslib "^2.6.2" "@aws-sdk/types@3.609.0", "@aws-sdk/types@^3.222.0": @@ -569,6 +603,14 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@aws-sdk/types@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/types/-/types-3.667.0.tgz#1b307c5af5a029ea1893f799fcfa122988f9d025" + integrity sha512-gYq0xCsqFfQaSL/yT1Gl1vIUjtsg7d7RhnUfsXaHt8xTxOKRTdH9GjbesBjXOzgOvB0W0vfssfreSNGFlOOMJg== + dependencies: + "@smithy/types" "^3.5.0" + tslib "^2.6.2" + "@aws-sdk/util-arn-parser@3.568.0": version "3.568.0" resolved "https://registry.yarnpkg.com/@aws-sdk/util-arn-parser/-/util-arn-parser-3.568.0.tgz#6a19a8c6bbaa520b6be1c278b2b8c17875b91527" @@ -576,14 +618,14 @@ dependencies: tslib "^2.6.2" -"@aws-sdk/util-endpoints@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.614.0.tgz#6564b0ffd7dc3728221e9f9821f5aab1cc58468e" - integrity sha512-wK2cdrXHH4oz4IomV/yrGkftU9A+ITB6nFL+rxxyO78is2ifHJpFdV4aqk4LSkXYPi6CXWNru/Dqc7yiKXgJPw== +"@aws-sdk/util-endpoints@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-endpoints/-/util-endpoints-3.667.0.tgz#c880fbc3bda5a11eec81e4ac5f95a256f8dbb24e" + integrity sha512-X22SYDAuQJWnkF1/q17pkX3nGw5XMD9YEUbmt87vUnRq7iyJ3JOpl6UKOBeUBaL838wA5yzdbinmCITJ/VZ1QA== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/types" "^3.3.0" - "@smithy/util-endpoints" "^2.0.5" + "@aws-sdk/types" "3.667.0" + "@smithy/types" "^3.5.0" + "@smithy/util-endpoints" "^2.1.3" tslib "^2.6.2" "@aws-sdk/util-format-url@3.609.0": @@ -603,32 +645,33 @@ dependencies: tslib "^2.6.2" -"@aws-sdk/util-user-agent-browser@3.609.0": - version "3.609.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.609.0.tgz#aa15421b2e32ae8bc589dac2bd6e8969832ce588" - integrity sha512-fojPU+mNahzQ0YHYBsx0ZIhmMA96H+ZIZ665ObU9tl+SGdbLneVZVikGve+NmHTQwHzwkFsZYYnVKAkreJLAtA== +"@aws-sdk/util-user-agent-browser@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.667.0.tgz#4c7e14e7f044e9533a6cdd459a3a7ab90e12ccff" + integrity sha512-y1pKlNzNpxzddM0QSnfIfIbi3Z9LTag1VDjYyZRbEGGSVip2J00qKsET+979nRezWMyJgw5GPBQR3Y+rN+jh0Q== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/types" "^3.3.0" + "@aws-sdk/types" "3.667.0" + "@smithy/types" "^3.5.0" bowser "^2.11.0" tslib "^2.6.2" -"@aws-sdk/util-user-agent-node@3.614.0": - version "3.614.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.614.0.tgz#1e3f49a80f841a3f21647baed2adce01aac5beb5" - integrity sha512-15ElZT88peoHnq5TEoEtZwoXTXRxNrk60TZNdpl/TUBJ5oNJ9Dqb5Z4ryb8ofN6nm9aFf59GVAerFDz8iUoHBA== +"@aws-sdk/util-user-agent-node@3.667.0": + version "3.667.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.667.0.tgz#db0c28a56453c3a14bda4abd63dc54f13c698640" + integrity sha512-4OcWyWUAYRLwXMxqUqnDb/3LoassXvEJcwjiIKEa7p0JvtSa9VjCL6B8Vjw8C/N6YoqrlFEEvcN7SlwBEy74pA== dependencies: - "@aws-sdk/types" "3.609.0" - "@smithy/node-config-provider" "^3.1.4" - "@smithy/types" "^3.3.0" + "@aws-sdk/middleware-user-agent" "3.667.0" + "@aws-sdk/types" "3.667.0" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@aws-sdk/xml-builder@3.609.0": - version "3.609.0" - resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.609.0.tgz#eeb3d5cde000a23cfeeefe0354b6193440dc7d87" - integrity sha512-l9XxNcA4HX98rwCC2/KoiWcmEiRfZe4G+mYwDbCFT87JIMj6GBhLDkAzr/W8KAaA2IDr8Vc6J8fZPgVulxxfMA== +"@aws-sdk/xml-builder@3.662.0": + version "3.662.0" + resolved "https://registry.yarnpkg.com/@aws-sdk/xml-builder/-/xml-builder-3.662.0.tgz#6cbe5aea6205fd2280ec043189985240628d1cb2" + integrity sha512-ikLkXn0igUpnJu2mCZjklvmcDGWT9OaLRv3JyC/cRkTaaSrblPjPM7KKsltxdMTLQ+v7fjCN0TsJpxphMfaOPA== dependencies: - "@smithy/types" "^3.3.0" + "@smithy/types" "^3.5.0" tslib "^2.6.2" "@babel/code-frame@7.12.11": @@ -2037,6 +2080,14 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@smithy/abort-controller@^3.1.5": + version "3.1.5" + resolved "https://registry.yarnpkg.com/@smithy/abort-controller/-/abort-controller-3.1.5.tgz#ca7a86a3c6b20fabe59667143f58d9e198616d14" + integrity sha512-DhNPnqTqPoG8aZ5dWkFOgsuY+i0GQ3CI6hMmvCoduNsnU9gUZWZBwGfDQsTTB7NvFPkom1df7jMIJWU90kuXXg== + dependencies: + "@smithy/types" "^3.5.0" + tslib "^2.6.2" + "@smithy/chunked-blob-reader-native@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@smithy/chunked-blob-reader-native/-/chunked-blob-reader-native-3.0.0.tgz#f1104b30030f76f9aadcbd3cdca4377bd1ba2695" @@ -2052,90 +2103,90 @@ dependencies: tslib "^2.6.2" -"@smithy/config-resolver@^3.0.5": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-3.0.5.tgz#727978bba7ace754c741c259486a19d3083431fd" - integrity sha512-SkW5LxfkSI1bUC74OtfBbdz+grQXYiPYolyu8VfpLIjEoN/sHVBlLeGXMQ1vX4ejkgfv6sxVbQJ32yF2cl1veA== +"@smithy/config-resolver@^3.0.9": + version "3.0.9" + resolved "https://registry.yarnpkg.com/@smithy/config-resolver/-/config-resolver-3.0.9.tgz#dcf4b7747ca481866f9bfac21469ebe2031a599e" + integrity sha512-5d9oBf40qC7n2xUoHmntKLdqsyTMMo/r49+eqSIjJ73eDfEtljAxEhzIQ3bkgXJtR3xiv7YzMT/3FF3ORkjWdg== dependencies: - "@smithy/node-config-provider" "^3.1.4" - "@smithy/types" "^3.3.0" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/types" "^3.5.0" "@smithy/util-config-provider" "^3.0.0" - "@smithy/util-middleware" "^3.0.3" + "@smithy/util-middleware" "^3.0.7" tslib "^2.6.2" -"@smithy/core@^2.2.6": - version "2.4.0" - resolved "https://registry.yarnpkg.com/@smithy/core/-/core-2.4.0.tgz#56e917b6ab2dffeba681a05395c40a757d681147" - integrity sha512-cHXq+FneIF/KJbt4q4pjN186+Jf4ZB0ZOqEaZMBhT79srEyGDDBV31NqBRBjazz8ppQ1bJbDJMY9ba5wKFV36w== - dependencies: - "@smithy/middleware-endpoint" "^3.1.0" - "@smithy/middleware-retry" "^3.0.15" - "@smithy/middleware-serde" "^3.0.3" - "@smithy/protocol-http" "^4.1.0" - "@smithy/smithy-client" "^3.2.0" - "@smithy/types" "^3.3.0" +"@smithy/core@^2.4.8": + version "2.4.8" + resolved "https://registry.yarnpkg.com/@smithy/core/-/core-2.4.8.tgz#397ac17dfa8ad658b77f96f19484f0eeaf22d397" + integrity sha512-x4qWk7p/a4dcf7Vxb2MODIf4OIcqNbK182WxRvZ/3oKPrf/6Fdic5sSElhO1UtXpWKBazWfqg0ZEK9xN1DsuHA== + dependencies: + "@smithy/middleware-endpoint" "^3.1.4" + "@smithy/middleware-retry" "^3.0.23" + "@smithy/middleware-serde" "^3.0.7" + "@smithy/protocol-http" "^4.1.4" + "@smithy/smithy-client" "^3.4.0" + "@smithy/types" "^3.5.0" "@smithy/util-body-length-browser" "^3.0.0" - "@smithy/util-middleware" "^3.0.3" + "@smithy/util-middleware" "^3.0.7" "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" -"@smithy/credential-provider-imds@^3.1.4", "@smithy/credential-provider-imds@^3.2.0": - version "3.2.0" - resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.0.tgz#0e0e7ddaff1a8633cb927aee1056c0ab506b7ecf" - integrity sha512-0SCIzgd8LYZ9EJxUjLXBmEKSZR/P/w6l7Rz/pab9culE/RWuqelAKGJvn5qUOl8BgX8Yj5HWM50A5hiB/RzsgA== +"@smithy/credential-provider-imds@^3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.4.tgz#e1a2bfc8a0066f673756ad8735247cf284b9735c" + integrity sha512-S9bb0EIokfYEuar4kEbLta+ivlKCWOCFsLZuilkNy9i0uEUEHSi47IFLPaxqqCl+0ftKmcOTHayY5nQhAuq7+w== dependencies: - "@smithy/node-config-provider" "^3.1.4" - "@smithy/property-provider" "^3.1.3" - "@smithy/types" "^3.3.0" - "@smithy/url-parser" "^3.0.3" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/property-provider" "^3.1.7" + "@smithy/types" "^3.5.0" + "@smithy/url-parser" "^3.0.7" tslib "^2.6.2" -"@smithy/eventstream-codec@^3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-3.1.2.tgz#4a1c72b34400631b829241151984a1ad8c4f963c" - integrity sha512-0mBcu49JWt4MXhrhRAlxASNy0IjDRFU+aWNDRal9OtUJvJNiwDuyKMUONSOjLjSCeGwZaE0wOErdqULer8r7yw== +"@smithy/eventstream-codec@^3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-codec/-/eventstream-codec-3.1.6.tgz#70ca95aad82d5140522eb883fbc140f1f22dcb27" + integrity sha512-SBiOYPBH+5wOyPS7lfI150ePfGLhnp/eTu5RnV9xvhGvRiKfnl6HzRK9wehBph+il8FxS9KTeadx7Rcmf1GLPQ== dependencies: "@aws-crypto/crc32" "5.2.0" - "@smithy/types" "^3.3.0" + "@smithy/types" "^3.5.0" "@smithy/util-hex-encoding" "^3.0.0" tslib "^2.6.2" -"@smithy/eventstream-serde-browser@^3.0.4": - version "3.0.6" - resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.6.tgz#a4ab4f7cfbd137bcaa54c375276f9214e568fd8f" - integrity sha512-2hM54UWQUOrki4BtsUI1WzmD13/SeaqT/AB3EUJKbcver/WgKNaiJ5y5F5XXuVe6UekffVzuUDrBZVAA3AWRpQ== +"@smithy/eventstream-serde-browser@^3.0.10": + version "3.0.10" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-browser/-/eventstream-serde-browser-3.0.10.tgz#ffca366a4edee5097be5a710f87627a5b2da5dec" + integrity sha512-1i9aMY6Pl/SmA6NjvidxnfBLHMPzhKu2BP148pEt5VwhMdmXn36PE2kWKGa9Hj8b0XGtCTRucpCncylevCtI7g== dependencies: - "@smithy/eventstream-serde-universal" "^3.0.5" - "@smithy/types" "^3.3.0" + "@smithy/eventstream-serde-universal" "^3.0.9" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@smithy/eventstream-serde-config-resolver@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.3.tgz#f852e096d0ad112363b4685e1d441088d1fce67a" - integrity sha512-NVTYjOuYpGfrN/VbRQgn31x73KDLfCXCsFdad8DiIc3IcdxL+dYA9zEQPyOP7Fy2QL8CPy2WE4WCUD+ZsLNfaQ== +"@smithy/eventstream-serde-config-resolver@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-config-resolver/-/eventstream-serde-config-resolver-3.0.7.tgz#1f352f384665f322e024a1396a7a2cca52fce9e3" + integrity sha512-eVzhGQBPEqXXYHvIUku0jMTxd4gDvenRzUQPTmKVWdRvp9JUCKrbAXGQRYiGxUYq9+cqQckRm0wq3kTWnNtDhw== dependencies: - "@smithy/types" "^3.3.0" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@smithy/eventstream-serde-node@^3.0.4": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.5.tgz#2bbf5c9312a28f23bc55ae284efa9499f8b8f982" - integrity sha512-+upXvnHNyZP095s11jF5dhGw/Ihzqwl5G+/KtMnoQOpdfC3B5HYCcDVG9EmgkhJMXJlM64PyN5gjJl0uXFQehQ== +"@smithy/eventstream-serde-node@^3.0.9": + version "3.0.9" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-node/-/eventstream-serde-node-3.0.9.tgz#e985340093c2ca6587ae2fdd0663e6845fbe9463" + integrity sha512-JE0Guqvt0xsmfQ5y1EI342/qtJqznBv8cJqkHZV10PwC8GWGU5KNgFbQnsVCcX+xF+qIqwwfRmeWoJCjuOLmng== dependencies: - "@smithy/eventstream-serde-universal" "^3.0.5" - "@smithy/types" "^3.3.0" + "@smithy/eventstream-serde-universal" "^3.0.9" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@smithy/eventstream-serde-universal@^3.0.5": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.5.tgz#e1cc2f71f4d174a03e00ce4b563395a81dd17bec" - integrity sha512-5u/nXbyoh1s4QxrvNre9V6vfyoLWuiVvvd5TlZjGThIikc3G+uNiG9uOTCWweSRjv1asdDIWK7nOmN7le4RYHQ== +"@smithy/eventstream-serde-universal@^3.0.9": + version "3.0.9" + resolved "https://registry.yarnpkg.com/@smithy/eventstream-serde-universal/-/eventstream-serde-universal-3.0.9.tgz#1832b190a3018204e33487ba1f7f0f6e2fb0da34" + integrity sha512-bydfgSisfepCufw9kCEnWRxqxJFzX/o8ysXWv+W9F2FIyiaEwZ/D8bBKINbh4ONz3i05QJ1xE7A5OKYvgJsXaw== dependencies: - "@smithy/eventstream-codec" "^3.1.2" - "@smithy/types" "^3.3.0" + "@smithy/eventstream-codec" "^3.1.6" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@smithy/fetch-http-handler@^3.2.1", "@smithy/fetch-http-handler@^3.2.4": +"@smithy/fetch-http-handler@^3.2.4": version "3.2.4" resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.4.tgz#c754de7e0ff2541b73ac9ba7cc955940114b3d62" integrity sha512-kBprh5Gs5h7ug4nBWZi1FZthdqSM+T7zMmsZxx0IBvWUn7dK3diz2SHn7Bs4dQGFDk8plDv375gzenDoNwrXjg== @@ -2146,41 +2197,52 @@ "@smithy/util-base64" "^3.0.0" tslib "^2.6.2" -"@smithy/hash-blob-browser@^3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.2.tgz#90281c1f183d93686fb4f26107f1819644d68829" - integrity sha512-hAbfqN2UbISltakCC2TP0kx4LqXBttEv2MqSPE98gVuDFMf05lU+TpC41QtqGP3Ff5A3GwZMPfKnEy0VmEUpmg== +"@smithy/fetch-http-handler@^3.2.9": + version "3.2.9" + resolved "https://registry.yarnpkg.com/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.9.tgz#8d5199c162a37caa37a8b6848eefa9ca58221a0b" + integrity sha512-hYNVQOqhFQ6vOpenifFME546f0GfJn2OiQ3M0FDmuUu8V/Uiwy2wej7ZXxFBNqdx0R5DZAqWM1l6VRhGz8oE6A== + dependencies: + "@smithy/protocol-http" "^4.1.4" + "@smithy/querystring-builder" "^3.0.7" + "@smithy/types" "^3.5.0" + "@smithy/util-base64" "^3.0.0" + tslib "^2.6.2" + +"@smithy/hash-blob-browser@^3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@smithy/hash-blob-browser/-/hash-blob-browser-3.1.6.tgz#d61de344aa3cef0bc83e3ab8166558256262dfcd" + integrity sha512-BKNcMIaeZ9lB67sgo88iCF4YB35KT8X2dNJ8DqrtZNTgN6tUDYBKThzfGtos/mnZkGkW91AYHisESHmSiYQmKw== dependencies: "@smithy/chunked-blob-reader" "^3.0.0" "@smithy/chunked-blob-reader-native" "^3.0.0" - "@smithy/types" "^3.3.0" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@smithy/hash-node@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-3.0.3.tgz#82c5cb7b0f1a29ee7319081853d2d158c07dff24" - integrity sha512-2ctBXpPMG+B3BtWSGNnKELJ7SH9e4TNefJS0cd2eSkOOROeBnnVBnAy9LtJ8tY4vUEoe55N4CNPxzbWvR39iBw== +"@smithy/hash-node@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/hash-node/-/hash-node-3.0.7.tgz#03b5a382fb588b8c2bac11b4fe7300aaf1661c88" + integrity sha512-SAGHN+QkrwcHFjfWzs/czX94ZEjPJ0CrWJS3M43WswDXVEuP4AVy9gJ3+AF6JQHZD13bojmuf/Ap/ItDeZ+Qfw== dependencies: - "@smithy/types" "^3.3.0" + "@smithy/types" "^3.5.0" "@smithy/util-buffer-from" "^3.0.0" "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" -"@smithy/hash-stream-node@^3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-3.1.2.tgz#89f0290ae44b113863878e75b10c484ff48af71c" - integrity sha512-PBgDMeEdDzi6JxKwbfBtwQG9eT9cVwsf0dZzLXoJF4sHKHs5HEo/3lJWpn6jibfJwT34I1EBXpBnZE8AxAft6g== +"@smithy/hash-stream-node@^3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@smithy/hash-stream-node/-/hash-stream-node-3.1.6.tgz#854ad354a865a1334baa2abc2f2247f2723de688" + integrity sha512-sFSSt7cmCpFWZPfVx7k80Bgb1K2VJ27VmMxH8X+dDhp7Wv8IBgID4K2VK5ehMJROF8hQgcj4WywnkHIwX/xlwQ== dependencies: - "@smithy/types" "^3.3.0" + "@smithy/types" "^3.5.0" "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" -"@smithy/invalid-dependency@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-3.0.3.tgz#8d9fd70e3a94b565a4eba4ffbdc95238e1930528" - integrity sha512-ID1eL/zpDULmHJbflb864k72/SNOZCADRc9i7Exq3RUNJw6raWUSlFEQ+3PX3EYs++bTxZB2dE9mEHTQLv61tw== +"@smithy/invalid-dependency@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/invalid-dependency/-/invalid-dependency-3.0.7.tgz#b36f258d94498f3c72ab6020091a66fc7cc16eda" + integrity sha512-Bq00GsAhHeYSuZX8Kpu4sbI9agH2BNYnqUmmbTGWOhki9NVsWn2jFr896vvoTMH8KAjNX/ErC/8t5QHuEXG+IA== dependencies: - "@smithy/types" "^3.3.0" + "@smithy/types" "^3.5.0" tslib "^2.6.2" "@smithy/is-array-buffer@^2.2.0": @@ -2197,22 +2259,22 @@ dependencies: tslib "^2.6.2" -"@smithy/md5-js@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-3.0.3.tgz#55ee40aa24075b096c39f7910590c18ff7660c98" - integrity sha512-O/SAkGVwpWmelpj/8yDtsaVe6sINHLB1q8YE/+ZQbDxIw3SRLbTZuRaI10K12sVoENdnHqzPp5i3/H+BcZ3m3Q== +"@smithy/md5-js@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/md5-js/-/md5-js-3.0.7.tgz#0a645dd9c139254353fd6e6a6b65154baeab7d2e" + integrity sha512-+wco9IN9uOW4tNGkZIqTR6IXyfO7Z8A+IOq82QCRn/f/xcmt7H1fXwmQVbfDSvbeFwfNnhv7s+u0G9PzPG6o2w== dependencies: - "@smithy/types" "^3.3.0" + "@smithy/types" "^3.5.0" "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" -"@smithy/middleware-content-length@^3.0.3": - version "3.0.5" - resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-3.0.5.tgz#1680aa4fb2a1c0505756103c9a5c2916307d9035" - integrity sha512-ILEzC2eyxx6ncej3zZSwMpB5RJ0zuqH7eMptxC4KN3f+v9bqT8ohssKbhNR78k/2tWW+KS5Spw+tbPF4Ejyqvw== +"@smithy/middleware-content-length@^3.0.9": + version "3.0.9" + resolved "https://registry.yarnpkg.com/@smithy/middleware-content-length/-/middleware-content-length-3.0.9.tgz#fb613d1a6b8c91e828d11c0d7a0a8576dba89b8b" + integrity sha512-t97PidoGElF9hTtLCrof32wfWMqC5g2SEJNxaVH3NjlatuNGsdxXRYO/t+RPnxA15RpYiS0f+zG7FuE2DeGgjA== dependencies: - "@smithy/protocol-http" "^4.1.0" - "@smithy/types" "^3.3.0" + "@smithy/protocol-http" "^4.1.4" + "@smithy/types" "^3.5.0" tslib "^2.6.2" "@smithy/middleware-endpoint@^3.0.5", "@smithy/middleware-endpoint@^3.1.0": @@ -2228,18 +2290,31 @@ "@smithy/util-middleware" "^3.0.3" tslib "^2.6.2" -"@smithy/middleware-retry@^3.0.15", "@smithy/middleware-retry@^3.0.9": - version "3.0.15" - resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-3.0.15.tgz#9b96900cde70d8aafd267e13f4e79241be90e0c7" - integrity sha512-iTMedvNt1ApdvkaoE8aSDuwaoc+BhvHqttbA/FO4Ty+y/S5hW6Ci/CTScG7vam4RYJWZxdTElc3MEfHRVH6cgQ== - dependencies: - "@smithy/node-config-provider" "^3.1.4" - "@smithy/protocol-http" "^4.1.0" - "@smithy/service-error-classification" "^3.0.3" - "@smithy/smithy-client" "^3.2.0" - "@smithy/types" "^3.3.0" - "@smithy/util-middleware" "^3.0.3" - "@smithy/util-retry" "^3.0.3" +"@smithy/middleware-endpoint@^3.1.4": + version "3.1.4" + resolved "https://registry.yarnpkg.com/@smithy/middleware-endpoint/-/middleware-endpoint-3.1.4.tgz#222c9fa49c8af6ebf8bea8ab220d92d9b8c90d3d" + integrity sha512-/ChcVHekAyzUbyPRI8CzPPLj6y8QRAfJngWcLMgsWxKVzw/RzBV69mSOzJYDD3pRwushA1+5tHtPF8fjmzBnrQ== + dependencies: + "@smithy/middleware-serde" "^3.0.7" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/shared-ini-file-loader" "^3.1.8" + "@smithy/types" "^3.5.0" + "@smithy/url-parser" "^3.0.7" + "@smithy/util-middleware" "^3.0.7" + tslib "^2.6.2" + +"@smithy/middleware-retry@^3.0.23": + version "3.0.23" + resolved "https://registry.yarnpkg.com/@smithy/middleware-retry/-/middleware-retry-3.0.23.tgz#ce5574e278dd14a7995afd5a4ed2a6c9891da8ed" + integrity sha512-x9PbGXxkcXIpm6L26qRSCC+eaYcHwybRmqU8LO/WM2RRlW0g8lz6FIiKbKgGvHuoK3dLZRiQVSQJveiCzwnA5A== + dependencies: + "@smithy/node-config-provider" "^3.1.8" + "@smithy/protocol-http" "^4.1.4" + "@smithy/service-error-classification" "^3.0.7" + "@smithy/smithy-client" "^3.4.0" + "@smithy/types" "^3.5.0" + "@smithy/util-middleware" "^3.0.7" + "@smithy/util-retry" "^3.0.7" tslib "^2.6.2" uuid "^9.0.1" @@ -2251,6 +2326,14 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@smithy/middleware-serde@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/middleware-serde/-/middleware-serde-3.0.7.tgz#03f0dda75edffc4cc90ea422349cbfb82368efa7" + integrity sha512-VytaagsQqtH2OugzVTq4qvjkLNbWehHfGcGr0JLJmlDRrNCeZoWkWsSOw1nhS/4hyUUWF/TLGGml4X/OnEep5g== + dependencies: + "@smithy/types" "^3.5.0" + tslib "^2.6.2" + "@smithy/middleware-stack@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-3.0.3.tgz#91845c7e61e6f137fa912b623b6def719a4f6ce7" @@ -2259,6 +2342,14 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@smithy/middleware-stack@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/middleware-stack/-/middleware-stack-3.0.7.tgz#813fa7b47895ce0d085eac89c056d21b1e46e771" + integrity sha512-EyTbMCdqS1DoeQsO4gI7z2Gzq1MoRFAeS8GkFYIwbedB7Lp5zlLHJdg+56tllIIG5Hnf9ZWX48YKSHlsKvugGA== + dependencies: + "@smithy/types" "^3.5.0" + tslib "^2.6.2" + "@smithy/node-config-provider@^3.1.4": version "3.1.4" resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-3.1.4.tgz#05647bed666aa8036a1ad72323c1942e5d421be1" @@ -2269,7 +2360,17 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" -"@smithy/node-http-handler@^3.1.2", "@smithy/node-http-handler@^3.1.4": +"@smithy/node-config-provider@^3.1.8": + version "3.1.8" + resolved "https://registry.yarnpkg.com/@smithy/node-config-provider/-/node-config-provider-3.1.8.tgz#2c1092040b4062eae0f7c9e121cc00ac6a77efee" + integrity sha512-E0rU0DglpeJn5ge64mk8wTGEXcQwmpUTY5Zr7IzTpDLmHKiIamINERNZYrPQjg58Ck236sEKSwRSHA4CwshU6Q== + dependencies: + "@smithy/property-provider" "^3.1.7" + "@smithy/shared-ini-file-loader" "^3.1.8" + "@smithy/types" "^3.5.0" + tslib "^2.6.2" + +"@smithy/node-http-handler@^3.1.4": version "3.1.4" resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-3.1.4.tgz#be4195e45639e690d522cd5f11513ea822ff9d5f" integrity sha512-+UmxgixgOr/yLsUxcEKGH0fMNVteJFGkmRltYFHnBMlogyFdpzn2CwqWmxOrfJELhV34v0WSlaqG1UtE1uXlJg== @@ -2280,6 +2381,17 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@smithy/node-http-handler@^3.2.4": + version "3.2.4" + resolved "https://registry.yarnpkg.com/@smithy/node-http-handler/-/node-http-handler-3.2.4.tgz#3c57c40d082c3bacac1e49955bd1240e8ccc40b2" + integrity sha512-49reY3+JgLMFNm7uTAKBWiKCA6XSvkNp9FqhVmusm2jpVnHORYFeFZ704LShtqWfjZW/nhX+7Iexyb6zQfXYIQ== + dependencies: + "@smithy/abort-controller" "^3.1.5" + "@smithy/protocol-http" "^4.1.4" + "@smithy/querystring-builder" "^3.0.7" + "@smithy/types" "^3.5.0" + tslib "^2.6.2" + "@smithy/property-provider@^3.1.3": version "3.1.3" resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-3.1.3.tgz#afd57ea82a3f6c79fbda95e3cb85c0ee0a79f39a" @@ -2288,6 +2400,14 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@smithy/property-provider@^3.1.7": + version "3.1.7" + resolved "https://registry.yarnpkg.com/@smithy/property-provider/-/property-provider-3.1.7.tgz#8a304a4b9110a067a93c784e4c11e175f82da379" + integrity sha512-QfzLi1GPMisY7bAM5hOUqBdGYnY5S2JAlr201pghksrQv139f8iiiMalXtjczIP5f6owxFn3MINLNUNvUkgtPw== + dependencies: + "@smithy/types" "^3.5.0" + tslib "^2.6.2" + "@smithy/protocol-http@^4.0.3", "@smithy/protocol-http@^4.1.0": version "4.1.0" resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-4.1.0.tgz#23519d8f45bf4f33960ea5415847bc2b620a010b" @@ -2296,6 +2416,14 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@smithy/protocol-http@^4.1.4": + version "4.1.4" + resolved "https://registry.yarnpkg.com/@smithy/protocol-http/-/protocol-http-4.1.4.tgz#6940d652b1825bda2422163ec9baab552669a338" + integrity sha512-MlWK8eqj0JlpZBnWmjQLqmFp71Ug00P+m72/1xQB3YByXD4zZ+y9N4hYrR0EDmrUCZIkyATWHOXFgtavwGDTzQ== + dependencies: + "@smithy/types" "^3.5.0" + tslib "^2.6.2" + "@smithy/querystring-builder@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-3.0.3.tgz#6b0e566f885bb84938d077c69e8f8555f686af13" @@ -2305,6 +2433,15 @@ "@smithy/util-uri-escape" "^3.0.0" tslib "^2.6.2" +"@smithy/querystring-builder@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/querystring-builder/-/querystring-builder-3.0.7.tgz#8c443c65f4249ff1637088db1166d18411d41555" + integrity sha512-65RXGZZ20rzqqxTsChdqSpbhA6tdt5IFNgG6o7e1lnPVLCe6TNWQq4rTl4N87hTDD8mV4IxJJnvyE7brbnRkQw== + dependencies: + "@smithy/types" "^3.5.0" + "@smithy/util-uri-escape" "^3.0.0" + tslib "^2.6.2" + "@smithy/querystring-parser@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-3.0.3.tgz#272a6b83f88dfcbbec8283d72a6bde850cc00091" @@ -2313,12 +2450,20 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" -"@smithy/service-error-classification@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-3.0.3.tgz#73484255060a094aa9372f6cd972dcaf97e3ce80" - integrity sha512-Jn39sSl8cim/VlkLsUhRFq/dKDnRUFlfRkvhOJaUbLBXUsLRLNf9WaxDv/z9BjuQ3A6k/qE8af1lsqcwm7+DaQ== +"@smithy/querystring-parser@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/querystring-parser/-/querystring-parser-3.0.7.tgz#936206d1e6da9d862384dae730b4bad042d6a948" + integrity sha512-Fouw4KJVWqqUVIu1gZW8BH2HakwLz6dvdrAhXeXfeymOBrZw+hcqaWs+cS1AZPVp4nlbeIujYrKA921ZW2WMPA== dependencies: - "@smithy/types" "^3.3.0" + "@smithy/types" "^3.5.0" + tslib "^2.6.2" + +"@smithy/service-error-classification@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/service-error-classification/-/service-error-classification-3.0.7.tgz#5bab4ad802d30bd3fa52b8134f6c171582358226" + integrity sha512-91PRkTfiBf9hxkIchhRKJfl1rsplRDyBnmyFca3y0Z3x/q0JJN480S83LBd8R6sBCkm2bBbqw2FHp0Mbh+ecSA== + dependencies: + "@smithy/types" "^3.5.0" "@smithy/shared-ini-file-loader@^3.1.4": version "3.1.4" @@ -2328,6 +2473,14 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@smithy/shared-ini-file-loader@^3.1.8": + version "3.1.8" + resolved "https://registry.yarnpkg.com/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.8.tgz#7a0bf5f20cfe8e0c4a36d8dcab8194d0d2ee958e" + integrity sha512-0NHdQiSkeGl0ICQKcJQ2lCOKH23Nb0EaAa7RDRId6ZqwXkw4LJyIyZ0t3iusD4bnKYDPLGy2/5e2rfUhrt0Acw== + dependencies: + "@smithy/types" "^3.5.0" + tslib "^2.6.2" + "@smithy/signature-v4@^3.1.2": version "3.1.2" resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-3.1.2.tgz#63fc0d4f9a955e902138fb0a57fafc96b9d4e8bb" @@ -2341,7 +2494,21 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" -"@smithy/smithy-client@^3.1.7", "@smithy/smithy-client@^3.2.0": +"@smithy/signature-v4@^4.2.0": + version "4.2.0" + resolved "https://registry.yarnpkg.com/@smithy/signature-v4/-/signature-v4-4.2.0.tgz#291f5a0e756cc251377e1e8af2a1f494e6173029" + integrity sha512-LafbclHNKnsorMgUkKm7Tk7oJ7xizsZ1VwqhGKqoCIrXh4fqDDp73fK99HOEEgcsQbtemmeY/BPv0vTVYYUNEQ== + dependencies: + "@smithy/is-array-buffer" "^3.0.0" + "@smithy/protocol-http" "^4.1.4" + "@smithy/types" "^3.5.0" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-middleware" "^3.0.7" + "@smithy/util-uri-escape" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + +"@smithy/smithy-client@^3.1.7": version "3.2.0" resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-3.2.0.tgz#6db94024e4bdaefa079ac68dbea23dafbea230c8" integrity sha512-pDbtxs8WOhJLJSeaF/eAbPgXg4VVYFlRcL/zoNYA5WbG3wBL06CHtBSg53ppkttDpAJ/hdiede+xApip1CwSLw== @@ -2353,6 +2520,18 @@ "@smithy/util-stream" "^3.1.3" tslib "^2.6.2" +"@smithy/smithy-client@^3.4.0": + version "3.4.0" + resolved "https://registry.yarnpkg.com/@smithy/smithy-client/-/smithy-client-3.4.0.tgz#ceffb92108a4ad60cbede3baf44ed224dc70b333" + integrity sha512-nOfJ1nVQsxiP6srKt43r2My0Gp5PLWCW2ASqUioxIiGmu6d32v4Nekidiv5qOmmtzIrmaD+ADX5SKHUuhReeBQ== + dependencies: + "@smithy/middleware-endpoint" "^3.1.4" + "@smithy/middleware-stack" "^3.0.7" + "@smithy/protocol-http" "^4.1.4" + "@smithy/types" "^3.5.0" + "@smithy/util-stream" "^3.1.9" + tslib "^2.6.2" + "@smithy/types@^3.3.0": version "3.3.0" resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.3.0.tgz#fae037c733d09bc758946a01a3de0ef6e210b16b" @@ -2360,6 +2539,13 @@ dependencies: tslib "^2.6.2" +"@smithy/types@^3.5.0": + version "3.5.0" + resolved "https://registry.yarnpkg.com/@smithy/types/-/types-3.5.0.tgz#9589e154c50d9c5d00feb7d818112ef8fc285d6e" + integrity sha512-QN0twHNfe8mNJdH9unwsCK13GURU7oEAZqkBI+rsvpv1jrmserO+WnLE7jidR9W/1dxwZ0u/CB01mV2Gms/K2Q== + dependencies: + tslib "^2.6.2" + "@smithy/url-parser@^3.0.3": version "3.0.3" resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-3.0.3.tgz#e8a060d9810b24b1870385fc2b02485b8a6c5955" @@ -2369,6 +2555,15 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" +"@smithy/url-parser@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/url-parser/-/url-parser-3.0.7.tgz#9d7d7e4e38514bf75ade6e8a30d2300f3db17d1b" + integrity sha512-70UbSSR8J97c1rHZOWhl+VKiZDqHWxs/iW8ZHrHp5fCCPLSBE7GcUlUvKSle3Ca+J9LLbYCj/A79BxztBvAfpA== + dependencies: + "@smithy/querystring-parser" "^3.0.7" + "@smithy/types" "^3.5.0" + tslib "^2.6.2" + "@smithy/util-base64@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@smithy/util-base64/-/util-base64-3.0.0.tgz#f7a9a82adf34e27a72d0719395713edf0e493017" @@ -2415,37 +2610,37 @@ dependencies: tslib "^2.6.2" -"@smithy/util-defaults-mode-browser@^3.0.9": - version "3.0.15" - resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.15.tgz#df73b9ae3dddc9126e0bb93ebc720b09d7163858" - integrity sha512-FZ4Psa3vjp8kOXcd3HJOiDPBCWtiilLl57r0cnNtq/Ga9RSDrM5ERL6xt+tO43+2af6Pn5Yp92x2n5vPuduNfg== +"@smithy/util-defaults-mode-browser@^3.0.23": + version "3.0.23" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.23.tgz#6920b473126ae8857a04dd6941793bbda12adc8b" + integrity sha512-Y07qslyRtXDP/C5aWKqxTPBl4YxplEELG3xRrz2dnAQ6Lq/FgNrcKWmV561nNaZmFH+EzeGOX3ZRMbU8p1T6Nw== dependencies: - "@smithy/property-provider" "^3.1.3" - "@smithy/smithy-client" "^3.2.0" - "@smithy/types" "^3.3.0" + "@smithy/property-provider" "^3.1.7" + "@smithy/smithy-client" "^3.4.0" + "@smithy/types" "^3.5.0" bowser "^2.11.0" tslib "^2.6.2" -"@smithy/util-defaults-mode-node@^3.0.9": - version "3.0.15" - resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.15.tgz#d52476e1f2e66525d918b51f8d5a9b0972bf518e" - integrity sha512-KSyAAx2q6d0t6f/S4XB2+3+6aQacm3aLMhs9aLMqn18uYGUepbdssfogW5JQZpc6lXNBnp0tEnR5e9CEKmEd7A== - dependencies: - "@smithy/config-resolver" "^3.0.5" - "@smithy/credential-provider-imds" "^3.2.0" - "@smithy/node-config-provider" "^3.1.4" - "@smithy/property-provider" "^3.1.3" - "@smithy/smithy-client" "^3.2.0" - "@smithy/types" "^3.3.0" +"@smithy/util-defaults-mode-node@^3.0.23": + version "3.0.23" + resolved "https://registry.yarnpkg.com/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.23.tgz#d03d21816e8b2f586ccf4a87cd0b1cc55b4d75e0" + integrity sha512-9Y4WH7f0vnDGuHUa4lGX9e2p+sMwODibsceSV6rfkZOvMC+BY3StB2LdO1NHafpsyHJLpwAgChxQ38tFyd6vkg== + dependencies: + "@smithy/config-resolver" "^3.0.9" + "@smithy/credential-provider-imds" "^3.2.4" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/property-provider" "^3.1.7" + "@smithy/smithy-client" "^3.4.0" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@smithy/util-endpoints@^2.0.5": - version "2.0.5" - resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-2.0.5.tgz#e3a7a4d1c41250bfd2b2d890d591273a7d8934be" - integrity sha512-ReQP0BWihIE68OAblC/WQmDD40Gx+QY1Ez8mTdFMXpmjfxSyz2fVQu3A4zXRfQU9sZXtewk3GmhfOHswvX+eNg== +"@smithy/util-endpoints@^2.1.3": + version "2.1.3" + resolved "https://registry.yarnpkg.com/@smithy/util-endpoints/-/util-endpoints-2.1.3.tgz#7498151e9dc714bdd0c6339314dd2350fa4d250a" + integrity sha512-34eACeKov6jZdHqS5hxBMJ4KyWKztTMulhuQ2UdOoP6vVxMLrOKUqIXAwJe/wiWMhXhydLW664B02CNpQBQ4Aw== dependencies: - "@smithy/node-config-provider" "^3.1.4" - "@smithy/types" "^3.3.0" + "@smithy/node-config-provider" "^3.1.8" + "@smithy/types" "^3.5.0" tslib "^2.6.2" "@smithy/util-hex-encoding@^3.0.0": @@ -2463,16 +2658,24 @@ "@smithy/types" "^3.3.0" tslib "^2.6.2" -"@smithy/util-retry@^3.0.3": - version "3.0.3" - resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-3.0.3.tgz#9b2ac0dbb1c81f69812a8affa4d772bebfc0e049" - integrity sha512-AFw+hjpbtVApzpNDhbjNG5NA3kyoMs7vx0gsgmlJF4s+yz1Zlepde7J58zpIRIsdjc+emhpAITxA88qLkPF26w== +"@smithy/util-middleware@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/util-middleware/-/util-middleware-3.0.7.tgz#770d09749b6d170a1641384a2e961487447446fa" + integrity sha512-OVA6fv/3o7TMJTpTgOi1H5OTwnuUa8hzRzhSFDtZyNxi6OZ70L/FHattSmhE212I7b6WSOJAAmbYnvcjTHOJCA== dependencies: - "@smithy/service-error-classification" "^3.0.3" - "@smithy/types" "^3.3.0" + "@smithy/types" "^3.5.0" + tslib "^2.6.2" + +"@smithy/util-retry@^3.0.7": + version "3.0.7" + resolved "https://registry.yarnpkg.com/@smithy/util-retry/-/util-retry-3.0.7.tgz#694e0667574ffe9772f620b35d3c7286aced35e9" + integrity sha512-nh1ZO1vTeo2YX1plFPSe/OXaHkLAHza5jpokNiiKX2M5YpNUv6RxGJZhpfmiR4jSvVHCjIDmILjrxKmP+/Ghug== + dependencies: + "@smithy/service-error-classification" "^3.0.7" + "@smithy/types" "^3.5.0" tslib "^2.6.2" -"@smithy/util-stream@^3.0.6", "@smithy/util-stream@^3.1.3": +"@smithy/util-stream@^3.1.3": version "3.1.3" resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-3.1.3.tgz#699ee2397cc1d474e46d2034039d5263812dca64" integrity sha512-FIv/bRhIlAxC0U7xM1BCnF2aDRPq0UaelqBHkM2lsCp26mcBbgI0tCVTv+jGdsQLUmAMybua/bjDsSu8RQHbmw== @@ -2486,6 +2689,20 @@ "@smithy/util-utf8" "^3.0.0" tslib "^2.6.2" +"@smithy/util-stream@^3.1.9": + version "3.1.9" + resolved "https://registry.yarnpkg.com/@smithy/util-stream/-/util-stream-3.1.9.tgz#d39656eae27696bdc5a3ec7c2f6b89c32dccd1ca" + integrity sha512-7YAR0Ub3MwTMjDfjnup4qa6W8gygZMxikBhFMPESi6ASsl/rZJhwLpF/0k9TuezScCojsM0FryGdz4LZtjKPPQ== + dependencies: + "@smithy/fetch-http-handler" "^3.2.9" + "@smithy/node-http-handler" "^3.2.4" + "@smithy/types" "^3.5.0" + "@smithy/util-base64" "^3.0.0" + "@smithy/util-buffer-from" "^3.0.0" + "@smithy/util-hex-encoding" "^3.0.0" + "@smithy/util-utf8" "^3.0.0" + tslib "^2.6.2" + "@smithy/util-uri-escape@^3.0.0": version "3.0.0" resolved "https://registry.yarnpkg.com/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz#e43358a78bf45d50bb736770077f0f09195b6f54" @@ -2509,13 +2726,13 @@ "@smithy/util-buffer-from" "^3.0.0" tslib "^2.6.2" -"@smithy/util-waiter@^3.1.2": - version "3.1.2" - resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-3.1.2.tgz#2d40c3312f3537feee763459a19acafab4c75cf3" - integrity sha512-4pP0EV3iTsexDx+8PPGAKCQpd/6hsQBaQhqWzU4hqKPHN5epPsxKbvUTIiYIHTxaKt6/kEaqPBpu/ufvfbrRzw== +"@smithy/util-waiter@^3.1.6": + version "3.1.6" + resolved "https://registry.yarnpkg.com/@smithy/util-waiter/-/util-waiter-3.1.6.tgz#c65870d0c802e33b96112fac5c4471b3bf2eeecb" + integrity sha512-xs/KAwWOeCklq8aMlnpk25LgxEYHKOEodfjfKclDMLcBJEVEKzDLxZxBQyztcuPJ7F54213NJS8PxoiHNMdItQ== dependencies: - "@smithy/abort-controller" "^3.1.1" - "@smithy/types" "^3.3.0" + "@smithy/abort-controller" "^3.1.5" + "@smithy/types" "^3.5.0" tslib "^2.6.2" "@stylelint/postcss-css-in-js@^0.37.2": @@ -6804,10 +7021,10 @@ fast-levenshtein@^2.0.6, fast-levenshtein@~2.0.6: resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" integrity sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= -fast-xml-parser@4.2.5: - version "4.2.5" - resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.2.5.tgz#a6747a09296a6cb34f2ae634019bf1738f3b421f" - integrity sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g== +fast-xml-parser@4.4.1: + version "4.4.1" + resolved "https://registry.yarnpkg.com/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz#86dbf3f18edf8739326447bcaac31b4ae7f6514f" + integrity sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw== dependencies: strnum "^1.0.5"