diff --git a/examples/pnpm-lock.yaml b/examples/pnpm-lock.yaml index 7ee3ba0..ca6e10e 100644 --- a/examples/pnpm-lock.yaml +++ b/examples/pnpm-lock.yaml @@ -33,7 +33,7 @@ dependencies: devDependencies: '@stutzlab/eslint-config': specifier: ^3.1.1 - version: 3.1.1(@typescript-eslint/eslint-plugin@7.18.0)(@typescript-eslint/parser@7.18.0)(eslint-config-airbnb-base@15.0.0)(eslint-config-airbnb-typescript@18.0.0)(eslint-config-prettier@9.1.0)(eslint-import-resolver-typescript@3.6.3)(eslint-plugin-fp@2.3.0)(eslint-plugin-import@2.29.1)(eslint-plugin-jest@28.8.1)(eslint-plugin-prettier@5.2.1)(eslint-plugin-promise@6.6.0)(eslint@8.57.0)(prettier@3.3.3) + version: 3.1.1(@typescript-eslint/eslint-plugin@7.18.0)(@typescript-eslint/parser@7.18.0)(eslint-config-airbnb-base@15.0.0)(eslint-config-airbnb-typescript@18.0.0)(eslint-config-prettier@9.1.0)(eslint-import-resolver-typescript@3.6.3)(eslint-plugin-fp@2.3.0)(eslint-plugin-import@2.30.0)(eslint-plugin-jest@28.8.3)(eslint-plugin-prettier@5.2.1)(eslint-plugin-promise@6.6.0)(eslint@8.57.0)(prettier@3.3.3) '@tsconfig/node20': specifier: ^20.1.4 version: 20.1.4 @@ -1155,8 +1155,8 @@ packages: engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dev: true - /@eslint-community/regexpp@4.11.0: - resolution: {integrity: sha512-G/M/tIiMrTAxEWRfLfQJMmGNX28IxBg4PBz8XqQhqUHLFI6TL2htpIB1iQCj144V5ee/JaKyT9/WZ0MGZWfA7A==} + /@eslint-community/regexpp@4.11.1: + resolution: {integrity: sha512-m4DVN9ZqskZoLU5GlWZadwDnYo3vAEydiUayB9widCl9ffWx2IvPnp6n3on5rJmziJSw9Bv+Z3ChDVdMwXCY8Q==} engines: {node: ^12.0.0 || ^14.0.0 || >=16.0.0} dev: true @@ -1577,6 +1577,10 @@ packages: rollup: 2.79.1 dev: false + /@rtsao/scc@1.1.0: + resolution: {integrity: sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==} + dev: true + /@sinclair/typebox@0.27.8: resolution: {integrity: sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==} dev: true @@ -2029,7 +2033,7 @@ packages: resolution: {integrity: sha512-YNcWv3R3n3U6iQYBsFOiWSuRGE5su1tJSiX6pAPRVk7dP0L7lqCteXGzuVRQ0gMZqUl8v1P0+fAKxF6PLo9B5A==} engines: {node: '>=8.3.0'} dependencies: - '@stoplight/json': 3.21.6 + '@stoplight/json': 3.21.7 '@stoplight/path': 1.3.2 '@stoplight/types': 13.20.0 '@types/urijs': 1.19.25 @@ -2041,8 +2045,8 @@ packages: urijs: 1.19.11 dev: false - /@stoplight/json@3.21.6: - resolution: {integrity: sha512-KGisXfNigoYdWIj1jA4p3IAAIW5YFpU9BdoECdjyDLBbhWGGHzs77e0STSCBmXQ/K3ApxfED2R7mQ79ymjzlvQ==} + /@stoplight/json@3.21.7: + resolution: {integrity: sha512-xcJXgKFqv/uCEgtGlPxy3tPA+4I+ZI4vAuMJ885+ThkTHFVkC+0Fm58lA9NlsyjnkpxFh4YiQWpH+KefHdbA0A==} engines: {node: '>=8.3.0'} dependencies: '@stoplight/ordered-object-literal': 1.0.5 @@ -2063,20 +2067,20 @@ packages: engines: {node: '>=8'} dev: false - /@stoplight/spectral-cli@6.11.1: - resolution: {integrity: sha512-1zqsQ0TOuVSnxxZ9mHBfC0IygV6ex7nAY6Mp59mLmw5fW103U9yPVK5ZcX9ZngCmr3PdteAnMDUIIaoDGso6nA==} + /@stoplight/spectral-cli@6.13.1: + resolution: {integrity: sha512-v6ipX4w6wRhtbOotwdPL7RrEkP0m1OwHTIyqzVrAPi932F/zkee24jmf1CHNrTynonmfGoU6/XpeqUHtQdKDFw==} engines: {node: ^12.20 || >= 14.13} hasBin: true dependencies: - '@stoplight/json': 3.21.6 + '@stoplight/json': 3.21.7 '@stoplight/path': 1.3.2 - '@stoplight/spectral-core': 1.18.3 - '@stoplight/spectral-formatters': 1.3.0 + '@stoplight/spectral-core': 1.19.1 + '@stoplight/spectral-formatters': 1.4.0 '@stoplight/spectral-parsers': 1.0.4 '@stoplight/spectral-ref-resolver': 1.0.4 - '@stoplight/spectral-ruleset-bundler': 1.5.2 - '@stoplight/spectral-ruleset-migrator': 1.9.5 - '@stoplight/spectral-rulesets': 1.19.1 + '@stoplight/spectral-ruleset-bundler': 1.6.0 + '@stoplight/spectral-ruleset-migrator': 1.10.0 + '@stoplight/spectral-rulesets': 1.20.2 '@stoplight/spectral-runtime': 1.1.2 '@stoplight/types': 13.20.0 chalk: 4.1.2 @@ -2091,12 +2095,12 @@ packages: - encoding dev: false - /@stoplight/spectral-core@1.18.3: - resolution: {integrity: sha512-YY8x7X2SWJIhGTLPol+eFiQpWPz0D0mJdkK2i4A0QJG68KkNhypP6+JBC7/Kz3XWjqr0L/RqAd+N5cQLPOKZGQ==} + /@stoplight/spectral-core@1.19.1: + resolution: {integrity: sha512-YiWhXdjyjn4vCl3102ywzwCEJzncxapFcj4dxcj1YP/bZ62DFeGJ8cEaMP164vSw2kI3rX7EMMzI/c8XOUnTfQ==} engines: {node: ^12.20 || >= 14.13} dependencies: '@stoplight/better-ajv-errors': 1.0.3(ajv@8.17.1) - '@stoplight/json': 3.21.6 + '@stoplight/json': 3.21.7 '@stoplight/path': 1.3.2 '@stoplight/spectral-parsers': 1.0.4 '@stoplight/spectral-ref-resolver': 1.0.4 @@ -2120,29 +2124,31 @@ packages: - encoding dev: false - /@stoplight/spectral-formats@1.6.0: - resolution: {integrity: sha512-X27qhUfNluiduH0u/QwJqhOd8Wk5YKdxVmKM03Aijlx0AH1H5mYt3l9r7t2L4iyJrsBaFPnMGt7UYJDGxszbNA==} + /@stoplight/spectral-formats@1.7.0: + resolution: {integrity: sha512-vJ1vIkA2s96fdJp0d3AJBGuPAW3sj8yMamyzR+dquEFO6ZAoYBo/BVsKKQskYzZi/nwljlRqUmGVmcf2PncIaA==} engines: {node: '>=12'} dependencies: - '@stoplight/json': 3.21.6 - '@stoplight/spectral-core': 1.18.3 + '@stoplight/json': 3.21.7 + '@stoplight/spectral-core': 1.19.1 '@types/json-schema': 7.0.15 tslib: 2.7.0 transitivePeerDependencies: - encoding dev: false - /@stoplight/spectral-formatters@1.3.0: - resolution: {integrity: sha512-ryuMwlzbPUuyn7ybSEbFYsljYmvTaTyD51wyCQs4ROzgfm3Yo5QDD0IsiJUzUpKK/Ml61ZX8ebgiPiRFEJtBpg==} + /@stoplight/spectral-formatters@1.4.0: + resolution: {integrity: sha512-nxYQldDzVg32pxQ4cMX27eMtB1A39ea+GSf0wIJ20mqkSBfIgLnRZ+GKkBxhgF9JzSolc4YtweydsubGQGd7ag==} engines: {node: ^12.20 || >=14.13} dependencies: '@stoplight/path': 1.3.2 - '@stoplight/spectral-core': 1.18.3 + '@stoplight/spectral-core': 1.19.1 '@stoplight/spectral-runtime': 1.1.2 '@stoplight/types': 13.20.0 + '@types/markdown-escape': 1.1.3 chalk: 4.1.2 cliui: 7.0.4 lodash: 4.17.21 + markdown-escape: 2.0.0 node-sarif-builder: 2.0.3 strip-ansi: 6.0.1 text-table: 0.2.0 @@ -2151,14 +2157,14 @@ packages: - encoding dev: false - /@stoplight/spectral-functions@1.8.0: - resolution: {integrity: sha512-ZrAkYA/ZGbuQ6EyG1gisF4yQ5nWP/+glcqVoGmS6kH6ekaynz2Yp6FL0oIamWj3rWedFUN7ppwTRUdo+9f/uCw==} + /@stoplight/spectral-functions@1.9.0: + resolution: {integrity: sha512-T+xl93ji8bpus4wUsTq8Qr2DSu2X9PO727rbxW61tTCG0s17CbsXOLYI+Ezjg5P6aaQlgXszGX8khtc57xk8Yw==} engines: {node: '>=12'} dependencies: '@stoplight/better-ajv-errors': 1.0.3(ajv@8.17.1) - '@stoplight/json': 3.21.6 - '@stoplight/spectral-core': 1.18.3 - '@stoplight/spectral-formats': 1.6.0 + '@stoplight/json': 3.21.7 + '@stoplight/spectral-core': 1.19.1 + '@stoplight/spectral-formats': 1.7.0 '@stoplight/spectral-runtime': 1.1.2 ajv: 8.17.1 ajv-draft-04: 1.0.0(ajv@8.17.1) @@ -2174,7 +2180,7 @@ packages: resolution: {integrity: sha512-nCTVvtX6q71M8o5Uvv9kxU31Gk1TRmgD6/k8HBhdCmKG6FWcwgjiZouA/R3xHLn/VwTI/9k8SdG5Mkdy0RBqbQ==} engines: {node: ^12.20 || >=14.13} dependencies: - '@stoplight/json': 3.21.6 + '@stoplight/json': 3.21.7 '@stoplight/types': 14.1.1 '@stoplight/yaml': 4.3.0 tslib: 2.7.0 @@ -2193,19 +2199,19 @@ packages: - encoding dev: false - /@stoplight/spectral-ruleset-bundler@1.5.2: - resolution: {integrity: sha512-4QUVUFAU+S7IQ9XeCu+0TQMYxKFpKnkOAfa9unRQ1iPL2cviaipEN6witpbAptdHJD3UUjx4OnwlX8WwmXSq9w==} + /@stoplight/spectral-ruleset-bundler@1.6.0: + resolution: {integrity: sha512-8CU7e4aEGdfU9ncVDtlnJSawg/6epzAHrQTjuNu1QfKAOoiwyG7oUk2XUTHWcvq6Q67iUctb0vjOokR+MPVg0Q==} engines: {node: ^12.20 || >= 14.13} dependencies: '@rollup/plugin-commonjs': 22.0.2(rollup@2.79.1) '@stoplight/path': 1.3.2 - '@stoplight/spectral-core': 1.18.3 - '@stoplight/spectral-formats': 1.6.0 - '@stoplight/spectral-functions': 1.8.0 + '@stoplight/spectral-core': 1.19.1 + '@stoplight/spectral-formats': 1.7.0 + '@stoplight/spectral-functions': 1.9.0 '@stoplight/spectral-parsers': 1.0.4 '@stoplight/spectral-ref-resolver': 1.0.4 - '@stoplight/spectral-ruleset-migrator': 1.9.5 - '@stoplight/spectral-rulesets': 1.19.1 + '@stoplight/spectral-ruleset-migrator': 1.10.0 + '@stoplight/spectral-rulesets': 1.20.2 '@stoplight/spectral-runtime': 1.1.2 '@stoplight/types': 13.20.0 '@types/node': 20.16.2 @@ -2217,14 +2223,14 @@ packages: - encoding dev: false - /@stoplight/spectral-ruleset-migrator@1.9.5: - resolution: {integrity: sha512-76n/HETr3UinVl/xLNldrH9p0JNoD8Gz4K75J6E4OHp4xD0P+BA2e8+W30HjIvqm1LJdLU2BNma0ioy+q3B9RA==} + /@stoplight/spectral-ruleset-migrator@1.10.0: + resolution: {integrity: sha512-nDfkVfYeWWv0UvILC4TWZSnRqQ4rHgeOJO1/lHQ7XHeG5iONanQ639B1aK6ZS6vuUc8gwuyQsrPF67b4sHIyYw==} engines: {node: '>=12'} dependencies: - '@stoplight/json': 3.21.6 + '@stoplight/json': 3.21.7 '@stoplight/ordered-object-literal': 1.0.5 '@stoplight/path': 1.3.2 - '@stoplight/spectral-functions': 1.8.0 + '@stoplight/spectral-functions': 1.9.0 '@stoplight/spectral-runtime': 1.1.2 '@stoplight/types': 13.20.0 '@stoplight/yaml': 4.2.3 @@ -2239,16 +2245,16 @@ packages: - encoding dev: false - /@stoplight/spectral-rulesets@1.19.1: - resolution: {integrity: sha512-rfGK87Y1JJCEeLC8MVdLkjUkRH+Y6VnSF388D+UWihfU9xuq2eNB9phWpTFkG+AG4HLRyGx963BmO6PyM9dBag==} + /@stoplight/spectral-rulesets@1.20.2: + resolution: {integrity: sha512-7Y8orZuNyGyeHr9n50rMfysgUJ+/zzIEHMptt66jiy82GUWl+0nr865DkMuXdC5GryfDYhtjoRTUCVsXu80Nkg==} engines: {node: '>=12'} dependencies: '@asyncapi/specs': 4.3.1 '@stoplight/better-ajv-errors': 1.0.3(ajv@8.17.1) - '@stoplight/json': 3.21.6 - '@stoplight/spectral-core': 1.18.3 - '@stoplight/spectral-formats': 1.6.0 - '@stoplight/spectral-functions': 1.8.0 + '@stoplight/json': 3.21.7 + '@stoplight/spectral-core': 1.19.1 + '@stoplight/spectral-formats': 1.7.0 + '@stoplight/spectral-functions': 1.9.0 '@stoplight/spectral-runtime': 1.1.2 '@stoplight/types': 13.20.0 '@types/json-schema': 7.0.15 @@ -2266,7 +2272,7 @@ packages: resolution: {integrity: sha512-fr5zRceXI+hrl82yAVoME+4GvJie8v3wmOe9tU+ZLRRNonizthy8qDi0Z/z4olE+vGreSDcuDOZ7JjRxFW5kTw==} engines: {node: '>=12'} dependencies: - '@stoplight/json': 3.21.6 + '@stoplight/json': 3.21.7 '@stoplight/path': 1.3.2 '@stoplight/types': 12.5.0 abort-controller: 3.0.0 @@ -2337,7 +2343,7 @@ packages: tslib: 2.7.0 dev: false - /@stutzlab/eslint-config@3.1.1(@typescript-eslint/eslint-plugin@7.18.0)(@typescript-eslint/parser@7.18.0)(eslint-config-airbnb-base@15.0.0)(eslint-config-airbnb-typescript@18.0.0)(eslint-config-prettier@9.1.0)(eslint-import-resolver-typescript@3.6.3)(eslint-plugin-fp@2.3.0)(eslint-plugin-import@2.29.1)(eslint-plugin-jest@28.8.1)(eslint-plugin-prettier@5.2.1)(eslint-plugin-promise@6.6.0)(eslint@8.57.0)(prettier@3.3.3): + /@stutzlab/eslint-config@3.1.1(@typescript-eslint/eslint-plugin@7.18.0)(@typescript-eslint/parser@7.18.0)(eslint-config-airbnb-base@15.0.0)(eslint-config-airbnb-typescript@18.0.0)(eslint-config-prettier@9.1.0)(eslint-import-resolver-typescript@3.6.3)(eslint-plugin-fp@2.3.0)(eslint-plugin-import@2.30.0)(eslint-plugin-jest@28.8.3)(eslint-plugin-prettier@5.2.1)(eslint-plugin-promise@6.6.0)(eslint@8.57.0)(prettier@3.3.3): resolution: {integrity: sha512-XmwQJE6UkSBmr2ZFGOprxVO/8Yioxu0vTzoLDm/0dB9E2RwGp1r6N4cyRT0MI8PCyYSUOz2kBH1aL5qpJkfFwQ==} peerDependencies: '@typescript-eslint/eslint-plugin': ^7.15.0 @@ -2357,13 +2363,13 @@ packages: '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0)(eslint@8.57.0)(typescript@5.5.4) '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.5.4) eslint: 8.57.0 - eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.29.1)(eslint@8.57.0) - eslint-config-airbnb-typescript: 18.0.0(@typescript-eslint/eslint-plugin@7.18.0)(@typescript-eslint/parser@7.18.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.30.0)(eslint@8.57.0) + eslint-config-airbnb-typescript: 18.0.0(@typescript-eslint/eslint-plugin@7.18.0)(@typescript-eslint/parser@7.18.0)(eslint-plugin-import@2.30.0)(eslint@8.57.0) eslint-config-prettier: 9.1.0(eslint@8.57.0) - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.18.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.18.0)(eslint-plugin-import@2.30.0)(eslint@8.57.0) eslint-plugin-fp: 2.3.0(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) - eslint-plugin-jest: 28.8.1(@typescript-eslint/eslint-plugin@7.18.0)(eslint@8.57.0)(jest@29.7.0)(typescript@5.5.4) + eslint-plugin-import: 2.30.0(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) + eslint-plugin-jest: 28.8.3(@typescript-eslint/eslint-plugin@7.18.0)(eslint@8.57.0)(jest@29.7.0)(typescript@5.5.4) eslint-plugin-prettier: 5.2.1(eslint-config-prettier@9.1.0)(eslint@8.57.0)(prettier@3.3.3) eslint-plugin-promise: 6.6.0(eslint@8.57.0) prettier: 3.3.3 @@ -2432,8 +2438,8 @@ packages: resolution: {integrity: sha512-EYNwp3bU+98cpU4lAWYYL7Zz+2gryWH1qbdDTidVd6hkiR6weksdbMadyXKXNPEkQFhXM+hVO9ZygomHXp+AIw==} dev: false - /@types/estree@1.0.5: - resolution: {integrity: sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==} + /@types/estree@1.0.6: + resolution: {integrity: sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==} dev: false /@types/graceful-fs@4.1.9: @@ -2473,6 +2479,10 @@ packages: resolution: {integrity: sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==} dev: true + /@types/markdown-escape@1.1.3: + resolution: {integrity: sha512-JIc1+s3y5ujKnt/+N+wq6s/QdL2qZ11fP79MijrVXsAAnzSxCbT2j/3prHRouJdZ2yFLN3vkP0HytfnoCczjOw==} + dev: false + /@types/node@20.16.2: resolution: {integrity: sha512-91s/n4qUPV/wg8eE9KHYW1kouTfDk2FPGjXbBMfRWP/2vg1rCXNQL1OCabwGs0XSdukuK+MwCDXE30QpSeMUhQ==} dependencies: @@ -2527,7 +2537,7 @@ packages: typescript: optional: true dependencies: - '@eslint-community/regexpp': 4.11.0 + '@eslint-community/regexpp': 4.11.1 '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.5.4) '@typescript-eslint/scope-manager': 7.18.0 '@typescript-eslint/type-utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4) @@ -2557,7 +2567,7 @@ packages: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) '@typescript-eslint/visitor-keys': 7.18.0 - debug: 4.3.6 + debug: 4.3.7 eslint: 8.57.0 typescript: 5.5.4 transitivePeerDependencies: @@ -2572,12 +2582,12 @@ packages: '@typescript-eslint/visitor-keys': 7.18.0 dev: true - /@typescript-eslint/scope-manager@8.3.0: - resolution: {integrity: sha512-mz2X8WcN2nVu5Hodku+IR8GgCOl4C0G/Z1ruaWN4dgec64kDBabuXyPAr+/RgJtumv8EEkqIzf3X2U5DUKB2eg==} + /@typescript-eslint/scope-manager@8.7.0: + resolution: {integrity: sha512-87rC0k3ZlDOuz82zzXRtQ7Akv3GKhHs0ti4YcbAJtaomllXoSO8hi7Ix3ccEvCd824dy9aIX+j3d2UMAfCtVpg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: - '@typescript-eslint/types': 8.3.0 - '@typescript-eslint/visitor-keys': 8.3.0 + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/visitor-keys': 8.7.0 dev: true /@typescript-eslint/type-utils@7.18.0(eslint@8.57.0)(typescript@5.5.4): @@ -2592,7 +2602,7 @@ packages: dependencies: '@typescript-eslint/typescript-estree': 7.18.0(typescript@5.5.4) '@typescript-eslint/utils': 7.18.0(eslint@8.57.0)(typescript@5.5.4) - debug: 4.3.6 + debug: 4.3.7 eslint: 8.57.0 ts-api-utils: 1.3.0(typescript@5.5.4) typescript: 5.5.4 @@ -2605,8 +2615,8 @@ packages: engines: {node: ^18.18.0 || >=20.0.0} dev: true - /@typescript-eslint/types@8.3.0: - resolution: {integrity: sha512-y6sSEeK+facMaAyixM36dQ5NVXTnKWunfD1Ft4xraYqxP0lC0POJmIaL/mw72CUMqjY9qfyVfXafMeaUj0noWw==} + /@typescript-eslint/types@8.7.0: + resolution: {integrity: sha512-LLt4BLHFwSfASHSF2K29SZ+ZCsbQOM+LuarPjRUuHm+Qd09hSe3GCeaQbcCr+Mik+0QFRmep/FyZBO6fJ64U3w==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dev: true @@ -2621,7 +2631,7 @@ packages: dependencies: '@typescript-eslint/types': 7.18.0 '@typescript-eslint/visitor-keys': 7.18.0 - debug: 4.3.6 + debug: 4.3.7 globby: 11.1.0 is-glob: 4.0.3 minimatch: 9.0.5 @@ -2632,8 +2642,8 @@ packages: - supports-color dev: true - /@typescript-eslint/typescript-estree@8.3.0(typescript@5.5.4): - resolution: {integrity: sha512-Mq7FTHl0R36EmWlCJWojIC1qn/ZWo2YiWYc1XVtasJ7FIgjo0MVv9rZWXEE7IK2CGrtwe1dVOxWwqXUdNgfRCA==} + /@typescript-eslint/typescript-estree@8.7.0(typescript@5.5.4): + resolution: {integrity: sha512-MC8nmcGHsmfAKxwnluTQpNqceniT8SteVwd2voYlmiSWGOtjvGXdPl17dYu2797GVscK30Z04WRM28CrKS9WOg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: typescript: '*' @@ -2641,9 +2651,9 @@ packages: typescript: optional: true dependencies: - '@typescript-eslint/types': 8.3.0 - '@typescript-eslint/visitor-keys': 8.3.0 - debug: 4.3.6 + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/visitor-keys': 8.7.0 + debug: 4.3.7 fast-glob: 3.3.2 is-glob: 4.0.3 minimatch: 9.0.5 @@ -2670,16 +2680,16 @@ packages: - typescript dev: true - /@typescript-eslint/utils@8.3.0(eslint@8.57.0)(typescript@5.5.4): - resolution: {integrity: sha512-F77WwqxIi/qGkIGOGXNBLV7nykwfjLsdauRB/DOFPdv6LTF3BHHkBpq81/b5iMPSF055oO2BiivDJV4ChvNtXA==} + /@typescript-eslint/utils@8.7.0(eslint@8.57.0)(typescript@5.5.4): + resolution: {integrity: sha512-ZbdUdwsl2X/s3CiyAu3gOlfQzpbuG3nTWKPoIvAu1pu5r8viiJvv2NPN2AqArL35NCYtw/lrPPfM4gxrMLNLPw==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} peerDependencies: eslint: ^8.57.0 || ^9.0.0 dependencies: '@eslint-community/eslint-utils': 4.4.0(eslint@8.57.0) - '@typescript-eslint/scope-manager': 8.3.0 - '@typescript-eslint/types': 8.3.0 - '@typescript-eslint/typescript-estree': 8.3.0(typescript@5.5.4) + '@typescript-eslint/scope-manager': 8.7.0 + '@typescript-eslint/types': 8.7.0 + '@typescript-eslint/typescript-estree': 8.7.0(typescript@5.5.4) eslint: 8.57.0 transitivePeerDependencies: - supports-color @@ -2694,11 +2704,11 @@ packages: eslint-visitor-keys: 3.4.3 dev: true - /@typescript-eslint/visitor-keys@8.3.0: - resolution: {integrity: sha512-RmZwrTbQ9QveF15m/Cl28n0LXD6ea2CjkhH5rQ55ewz3H24w+AMCJHPVYaZ8/0HoG8Z3cLLFFycRXxeO2tz9FA==} + /@typescript-eslint/visitor-keys@8.7.0: + resolution: {integrity: sha512-b1tx0orFCCh/THWPQa2ZwWzvOeyzzp36vkJYOpVg0u8UVOIsfVrnuC9FqAw9gRKn+rG2VmWQ/zDJZzkxUnj/XQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} dependencies: - '@typescript-eslint/types': 8.3.0 + '@typescript-eslint/types': 8.7.0 eslint-visitor-keys: 3.4.3 dev: true @@ -3580,8 +3590,8 @@ packages: ms: 2.1.2 dev: true - /debug@4.3.6: - resolution: {integrity: sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==} + /debug@4.3.7: + resolution: {integrity: sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==} engines: {node: '>=6.0'} peerDependencies: supports-color: '*' @@ -3589,7 +3599,7 @@ packages: supports-color: optional: true dependencies: - ms: 2.1.2 + ms: 2.1.3 dev: true /decode-uri-component@0.2.2: @@ -3887,8 +3897,8 @@ packages: engines: {node: '>=6'} dev: true - /escalade@3.1.2: - resolution: {integrity: sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==} + /escalade@3.2.0: + resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==} engines: {node: '>=6'} dev: false @@ -3915,7 +3925,7 @@ packages: lodash.zip: 4.2.0 dev: true - /eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.29.1)(eslint@8.57.0): + /eslint-config-airbnb-base@15.0.0(eslint-plugin-import@2.30.0)(eslint@8.57.0): resolution: {integrity: sha512-xaX3z4ZZIcFLvh2oUNvcX5oEofXda7giYmuplVxoOg5A7EXJMrUyqRgR+mhDhPK8LZ4PttFOBvCYDbX3sUoUig==} engines: {node: ^10.12.0 || >=12.0.0} peerDependencies: @@ -3924,13 +3934,13 @@ packages: dependencies: confusing-browser-globals: 1.0.11 eslint: 8.57.0 - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) + eslint-plugin-import: 2.30.0(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) object.assign: 4.1.5 object.entries: 1.1.8 semver: 6.3.1 dev: true - /eslint-config-airbnb-typescript@18.0.0(@typescript-eslint/eslint-plugin@7.18.0)(@typescript-eslint/parser@7.18.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0): + /eslint-config-airbnb-typescript@18.0.0(@typescript-eslint/eslint-plugin@7.18.0)(@typescript-eslint/parser@7.18.0)(eslint-plugin-import@2.30.0)(eslint@8.57.0): resolution: {integrity: sha512-oc+Lxzgzsu8FQyFVa4QFaVKiitTYiiW3frB9KYW5OWdPrqFc7FzxgB20hP4cHMlr+MBzGcLl3jnCOVOydL9mIg==} peerDependencies: '@typescript-eslint/eslint-plugin': ^7.0.0 @@ -3940,7 +3950,7 @@ packages: '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0)(eslint@8.57.0)(typescript@5.5.4) '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.5.4) eslint: 8.57.0 - eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-config-airbnb-base: 15.0.0(eslint-plugin-import@2.30.0)(eslint@8.57.0) transitivePeerDependencies: - eslint-plugin-import dev: true @@ -3964,7 +3974,7 @@ packages: - supports-color dev: true - /eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0): + /eslint-import-resolver-typescript@3.6.3(@typescript-eslint/parser@7.18.0)(eslint-plugin-import@2.30.0)(eslint@8.57.0): resolution: {integrity: sha512-ud9aw4szY9cCT1EWWdGv1L1XR6hh2PaRWif0j2QjQ0pgTY/69iw+W0Z4qZv5wHahOl8isEr+k/JnyAqNQkLkIA==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -3978,14 +3988,14 @@ packages: optional: true dependencies: '@nolyfill/is-core-module': 1.0.39 - debug: 4.3.6 + debug: 4.3.7 enhanced-resolve: 5.17.1 eslint: 8.57.0 - eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) - eslint-plugin-import: 2.29.1(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) + eslint-module-utils: 2.11.1(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) + eslint-plugin-import: 2.30.0(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) fast-glob: 3.3.2 - get-tsconfig: 4.8.0 - is-bun-module: 1.1.0 + get-tsconfig: 4.8.1 + is-bun-module: 1.2.1 is-glob: 4.0.3 transitivePeerDependencies: - '@typescript-eslint/parser' @@ -3994,8 +4004,8 @@ packages: - supports-color dev: true - /eslint-module-utils@2.8.2(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0): - resolution: {integrity: sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg==} + /eslint-module-utils@2.11.1(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0): + resolution: {integrity: sha512-EwcbfLOhwVMAfatfqLecR2yv3dE5+kQ8kx+Rrt0DvDXEVwW86KQ/xbMDQhtp5l42VXukD5SOF8mQQHbaNtO0CQ==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -4019,13 +4029,13 @@ packages: debug: 3.2.7 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.18.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.18.0)(eslint-plugin-import@2.30.0)(eslint@8.57.0) transitivePeerDependencies: - supports-color dev: true - /eslint-module-utils@2.8.2(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0): - resolution: {integrity: sha512-3XnC5fDyc8M4J2E8pt8pmSVRX2M+5yWMCfI/kDZwauQeFgzQOuhcRBFKjTeJagqgk4sFKxe1mvNVnaWwImx/Tg==} + /eslint-module-utils@2.11.1(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0): + resolution: {integrity: sha512-EwcbfLOhwVMAfatfqLecR2yv3dE5+kQ8kx+Rrt0DvDXEVwW86KQ/xbMDQhtp5l42VXukD5SOF8mQQHbaNtO0CQ==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -4048,7 +4058,7 @@ packages: '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.5.4) debug: 3.2.7 eslint: 8.57.0 - eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.18.0)(eslint-plugin-import@2.29.1)(eslint@8.57.0) + eslint-import-resolver-typescript: 3.6.3(@typescript-eslint/parser@7.18.0)(eslint-plugin-import@2.30.0)(eslint@8.57.0) transitivePeerDependencies: - supports-color dev: true @@ -4066,8 +4076,8 @@ packages: req-all: 0.1.0 dev: true - /eslint-plugin-import@2.29.1(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0): - resolution: {integrity: sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw==} + /eslint-plugin-import@2.30.0(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0): + resolution: {integrity: sha512-/mHNE9jINJfiD2EKkg1BKyPyUk4zdnT54YgbOgfjSakWT5oyX/qQLVNTkehyfpcMxZXMy1zyonZ2v7hZTX43Yw==} engines: {node: '>=4'} peerDependencies: '@typescript-eslint/parser': '*' @@ -4076,6 +4086,7 @@ packages: '@typescript-eslint/parser': optional: true dependencies: + '@rtsao/scc': 1.1.0 '@typescript-eslint/parser': 7.18.0(eslint@8.57.0)(typescript@5.5.4) array-includes: 3.1.8 array.prototype.findlastindex: 1.2.5 @@ -4085,7 +4096,7 @@ packages: doctrine: 2.1.0 eslint: 8.57.0 eslint-import-resolver-node: 0.3.9 - eslint-module-utils: 2.8.2(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) + eslint-module-utils: 2.11.1(@typescript-eslint/parser@7.18.0)(eslint-import-resolver-node@0.3.9)(eslint-import-resolver-typescript@3.6.3)(eslint@8.57.0) hasown: 2.0.2 is-core-module: 2.15.1 is-glob: 4.0.3 @@ -4101,8 +4112,8 @@ packages: - supports-color dev: true - /eslint-plugin-jest@28.8.1(@typescript-eslint/eslint-plugin@7.18.0)(eslint@8.57.0)(jest@29.7.0)(typescript@5.5.4): - resolution: {integrity: sha512-G46XMyYu6PtSNJUkQ0hsPjzXYpzq/O4vpCciMizTKRJG8kNsRreGoMRDG6H9FIB/xVgfFuclVnuX4XRvFUzrZQ==} + /eslint-plugin-jest@28.8.3(@typescript-eslint/eslint-plugin@7.18.0)(eslint@8.57.0)(jest@29.7.0)(typescript@5.5.4): + resolution: {integrity: sha512-HIQ3t9hASLKm2IhIOqnu+ifw7uLZkIlR7RYNv7fMcEi/p0CIiJmfriStQS2LDkgtY4nyLbIZAD+JL347Yc2ETQ==} engines: {node: ^16.10.0 || ^18.12.0 || >=20.0.0} peerDependencies: '@typescript-eslint/eslint-plugin': ^6.0.0 || ^7.0.0 || ^8.0.0 @@ -4115,7 +4126,7 @@ packages: optional: true dependencies: '@typescript-eslint/eslint-plugin': 7.18.0(@typescript-eslint/parser@7.18.0)(eslint@8.57.0)(typescript@5.5.4) - '@typescript-eslint/utils': 8.3.0(eslint@8.57.0)(typescript@5.5.4) + '@typescript-eslint/utils': 8.7.0(eslint@8.57.0)(typescript@5.5.4) eslint: 8.57.0 jest: 29.7.0(@types/node@20.16.2)(ts-node@10.9.2) transitivePeerDependencies: @@ -4630,8 +4641,8 @@ packages: es-errors: 1.3.0 get-intrinsic: 1.2.4 - /get-tsconfig@4.8.0: - resolution: {integrity: sha512-Pgba6TExTZ0FJAn1qkJAjIeKoDJ3CsI2ChuLohJnZl/tTU8MVrq3b+2t5UOPfRa4RMsorClBjJALkJUMjG1PAw==} + /get-tsconfig@4.8.1: + resolution: {integrity: sha512-k9PN+cFBmaLWtVz29SkUoqU5O0slLuHJXt/2P+tMVFT+phsSGXGkp9t3rQIqdz0e+06EHNGs3oM6ZX1s2zHxRg==} dependencies: resolve-pkg-maps: 1.0.0 dev: true @@ -4909,8 +4920,8 @@ packages: resolution: {integrity: sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==} dev: true - /is-bun-module@1.1.0: - resolution: {integrity: sha512-4mTAVPlrXpaN3jtF0lsnPCMGnq4+qZjVIKq0HCpfcqf8OC1SM5oATCIAPM5V5FN05qp2NNnFndphmdZS9CV3hA==} + /is-bun-module@1.2.1: + resolution: {integrity: sha512-AmidtEM6D6NmUiLOvvU7+IePxjEjOzra2h0pSrsfSAcXwl/83zLLXDByafUJy9k/rKK0pvXMLdwKwGHlX2Ke6Q==} dependencies: semver: 7.6.3 dev: true @@ -5047,7 +5058,7 @@ packages: /is-reference@1.2.1: resolution: {integrity: sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==} dependencies: - '@types/estree': 1.0.5 + '@types/estree': 1.0.6 dev: false /is-regex@1.1.4: @@ -5897,6 +5908,10 @@ packages: object-visit: 1.0.1 dev: true + /markdown-escape@2.0.0: + resolution: {integrity: sha512-Trz4v0+XWlwy68LJIyw3bLbsJiC8XAbRCKF9DbEtZjyndKOGVx6n+wNB0VfoRmY2LKboQLeniap3xrb6LGSJ8A==} + dev: false + /merge-stream@2.0.0: resolution: {integrity: sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==} dev: true @@ -7435,7 +7450,7 @@ packages: engines: {node: '>=12'} dependencies: cliui: 8.0.1 - escalade: 3.1.2 + escalade: 3.2.0 get-caller-file: 2.0.5 require-directory: 2.1.1 string-width: 4.2.3 @@ -7458,7 +7473,7 @@ packages: dev: false file:../lib/dist/cdk-practical-constructs-0.0.1.tgz(@asteasolutions/zod-to-openapi@7.0.0)(aws-cdk-lib@2.155.0)(zod@3.23.8): - resolution: {integrity: sha512-ZKTk0nCY2DMvvSi0dPxlUXITsd2ahY6cN4GIXyRs+EB65HSmAQj/ftDJtOyy26zJ3MeVW/fzrGo2/5e5xROuNA==, tarball: file:../lib/dist/cdk-practical-constructs-0.0.1.tgz} + resolution: {integrity: sha512-jkisyPDSbCIaaqO4z1PtlrxVvO74UDQQ7lf5PhU+eLwkzxPppEYK0KHQOy4pJ7uNhcRdNJ76K7zyuOOB3HiCxw==, tarball: file:../lib/dist/cdk-practical-constructs-0.0.1.tgz} id: file:../lib/dist/cdk-practical-constructs-0.0.1.tgz name: cdk-practical-constructs version: 0.0.1 @@ -7470,7 +7485,7 @@ packages: '@apiture/openapi-down-convert': 0.9.0 '@asteasolutions/zod-to-openapi': 7.0.0(zod@3.23.8) '@aws-sdk/client-secrets-manager': 3.624.0 - '@stoplight/spectral-cli': 6.11.1 + '@stoplight/spectral-cli': 6.13.1 aws-cdk-lib: 2.155.0(constructs@10.3.0) aws-lambda: 1.0.7 axios: 1.7.5 diff --git a/lib/src/wso2/wso2-api/handler/index.test.ts b/lib/src/wso2/wso2-api/handler/index.test.ts index 438a4ff..eef8c70 100644 --- a/lib/src/wso2/wso2-api/handler/index.test.ts +++ b/lib/src/wso2/wso2-api/handler/index.test.ts @@ -3,12 +3,11 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import nock from 'nock'; -import { mockClient } from 'aws-sdk-client-mock'; -import { GetSecretValueCommand, SecretsManagerClient } from '@aws-sdk/client-secrets-manager'; import { petstoreOpenapi } from '../__tests__/petstore'; import { ApiFromListV1, PublisherPortalAPIv1, Wso2ApiDefinitionV1 } from '../v1/types'; import { Wso2ApiCustomResourceProperties } from '../types'; +import { nockBasicWso2SDK } from '../../wso2-utils.test'; import { Wso2ApiCustomResourceEvent, handler } from './index'; @@ -44,7 +43,7 @@ describe('wso2 custom resource lambda', () => { }); it('basic wso2 api create', async () => { - nockBasicWso2SDK(); + nockBasicWso2SDK(baseWso2Url); // api list mock nock(baseWso2Url) @@ -88,7 +87,7 @@ describe('wso2 custom resource lambda', () => { }); it('basic wso2 api update', async () => { - nockBasicWso2SDK(); + nockBasicWso2SDK(baseWso2Url); // api list mock const testDefs: Wso2ApiDefinitionV1 = { @@ -136,7 +135,7 @@ describe('wso2 custom resource lambda', () => { }); it('basic wso2 api change on UPDATE operation', async () => { - nockBasicWso2SDK(); + nockBasicWso2SDK(baseWso2Url); // api list mock const testDefs: Wso2ApiDefinitionV1 = { @@ -181,7 +180,7 @@ describe('wso2 custom resource lambda', () => { }); it('should pass with success if wso2 answers properly after a few retries', async () => { - nockBasicWso2SDK(); + nockBasicWso2SDK(baseWso2Url); // api list mock const testDefs: Wso2ApiDefinitionV1 = { @@ -257,7 +256,7 @@ describe('wso2 custom resource lambda', () => { }); it('should fail after retrying checking WSO2 api for a few times', async () => { - nockBasicWso2SDK(); + nockBasicWso2SDK(baseWso2Url); // api list mock const testDefs: Wso2ApiDefinitionV1 = { @@ -317,7 +316,7 @@ describe('wso2 custom resource lambda', () => { }); it('basic wso2 api delete on DELETE operation', async () => { - nockBasicWso2SDK(); + nockBasicWso2SDK(baseWso2Url); // api update mock nock(baseWso2Url) @@ -415,32 +414,6 @@ describe('wso2 custom resource lambda', () => { retryOptions: testRetryOptions, }; - const nockBasicWso2SDK = (): void => { - const secretMock = mockClient(SecretsManagerClient); - secretMock.on(GetSecretValueCommand).resolves({ - SecretBinary: Buffer.from(JSON.stringify({ user: 'user1', pwd: 'pwd1' })), - }); - - // register client mock - nock(baseWso2Url).post('/client-registration/v0.17/register').reply(200, { - clientId: 'clientId1', - clientSecret: 'clientSecret1', - }); - - // get token mock - nock(baseWso2Url).post('/oauth2/token').reply(200, { - access_token: '1111-1111-1111', - }); - - // mock server check - nock(baseWso2Url) - .get('/services/Version') - .reply( - 200, - 'WSO2 API Manager-3.2.0', - ); - }; - const nockAfterUpdateCreate = (testDefs: Wso2ApiDefinitionV1): void => { // api openapi update mock nock(baseWso2Url) diff --git a/lib/src/wso2/wso2-application/handler/index.test.ts b/lib/src/wso2/wso2-application/handler/index.test.ts index 4096e1d..1d50e34 100644 --- a/lib/src/wso2/wso2-application/handler/index.test.ts +++ b/lib/src/wso2/wso2-application/handler/index.test.ts @@ -3,11 +3,10 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ import nock from 'nock'; -import { mockClient } from 'aws-sdk-client-mock'; -import { GetSecretValueCommand, SecretsManagerClient } from '@aws-sdk/client-secrets-manager'; import { Wso2ApplicationDefinition } from '../v1/types'; import { Wso2ApplicationCustomResourceProperties } from '../types'; +import { nockBasicWso2SDK } from '../../wso2-utils.test'; import { Wso2ApplicationCustomResourceEvent, handler } from './index'; @@ -43,7 +42,7 @@ describe('wso2 application custom resource lambda', () => { }); it('wso2 application delete', async () => { - nockBasicWso2SDK(); + nockBasicWso2SDK(baseWso2Url); // application get mock nock(baseWso2Url) @@ -56,7 +55,7 @@ describe('wso2 application custom resource lambda', () => { }); it('basic wso2 application update', async () => { - nockBasicWso2SDK(); + nockBasicWso2SDK(baseWso2Url); const testDefs: Wso2ApplicationDefinition = testApplicationDefs(); @@ -89,7 +88,7 @@ describe('wso2 application custom resource lambda', () => { }); it('basic wso2 application create', async () => { - nockBasicWso2SDK(); + nockBasicWso2SDK(baseWso2Url); // api list mock nock(baseWso2Url) @@ -183,30 +182,4 @@ describe('wso2 application custom resource lambda', () => { applicationDefinition: testApplicationDefs(), retryOptions: testRetryOptions, }; - - const nockBasicWso2SDK = (): void => { - const secretMock = mockClient(SecretsManagerClient); - secretMock.on(GetSecretValueCommand).resolves({ - SecretBinary: Buffer.from(JSON.stringify({ user: 'user1', pwd: 'pwd1' })), - }); - - // register client mock - nock(baseWso2Url).post('/client-registration/v0.17/register').reply(200, { - clientId: 'clientId1', - clientSecret: 'clientSecret1', - }); - - // get token mock - nock(baseWso2Url).post('/oauth2/token').reply(200, { - access_token: '1111-1111-1111', - }); - - // mock server check - nock(baseWso2Url) - .get('/services/Version') - .reply( - 200, - 'WSO2 API Manager-3.2.0', - ); - }; }); diff --git a/lib/src/wso2/wso2-subscription/handler/index.test.ts b/lib/src/wso2/wso2-subscription/handler/index.test.ts new file mode 100644 index 0000000..56682dd --- /dev/null +++ b/lib/src/wso2/wso2-subscription/handler/index.test.ts @@ -0,0 +1,182 @@ +/* eslint-disable no-console */ +/* eslint-disable camelcase */ +/* eslint-disable @typescript-eslint/no-explicit-any */ + +import nock from 'nock'; + +import { Wso2SubscriptionDefinition } from '../v1/types'; +import { Wso2SubscriptionCustomResourceProperties } from '../types'; +import { nockBasicWso2SDK } from '../../wso2-utils.test'; + +import { handler, Wso2SubscriptionCustomResourceEvent } from './index'; + +const baseWso2Url = 'https://mywso2.com'; + +const testRetryOptions = { + checkRetries: { + startingDelay: 100, + delayFirstAttempt: true, + maxDelay: 100, + numOfAttempts: 0, + timeMultiple: 1.1, + }, + mutationRetries: { + startingDelay: 100, + delayFirstAttempt: true, + maxDelay: 100, + numOfAttempts: 0, + timeMultiple: 1.1, + }, +}; + +const originalConsoleLog = console.log; + +describe('wso2 subscription custom resource lambda', () => { + beforeEach(() => { + nock.cleanAll(); + // silence verbose console logs. comment this for debugging + // console.log = (): void => {}; + }); + afterEach(() => { + console.log = originalConsoleLog; + }); + + it('wso2 subscription delete', async () => { + nockBasicWso2SDK(baseWso2Url); + + // application get mock + nock(baseWso2Url) + .delete(/.*\/store\/v1\/subscriptions\/[^\\/]+$/) + .times(1) // check if was created + .reply(200); + + const eres = await handler(testCFNEventDelete(testEvent, '123-456')); + expect(eres.Status).toBe('SUCCESS'); + }); + + it('basic wso2 subscription update', async () => { + nockBasicWso2SDK(baseWso2Url); + + const testDefs: Wso2SubscriptionDefinition = testSubscriptionDefs(); + + // subscriptions list mock + nock(baseWso2Url) + .get(/.*\/store\/v1\/subscriptions.*/) + .query(true) + .times(1) // check create or update + .reply(200, { list: [{ ...testDefs, subscriptionId: '123-456' }] }); + + // subscription update mock + nock(baseWso2Url) + .put(/.*\/store\/v1\/subscriptions\/[^\\/]+$/) + .times(1) + .reply(200); + + // subscription get mock + nock(baseWso2Url) + .get(/.*\/store\/v1\/subscriptions\/[^\\/]+$/) + .times(1) // check if was created + .reply(200, { ...testDefs }); + + const eres = await handler( + testCFNEventCreate({ + ...testEvent, + }), + ); + expect(eres.PhysicalResourceId).toBe('123-456'); + expect(eres.Status).toBe('SUCCESS'); + }); + + it('basic wso2 subscription create', async () => { + nockBasicWso2SDK(baseWso2Url); + + // subscriptions list mock + nock(baseWso2Url) + .get(/.*\/store\/v1\/subscriptions.*/) + .query(true) + .times(1) // check create or update + .reply(200, { list: [] }); + + const testDefs: Wso2SubscriptionDefinition = testSubscriptionDefs(); + + // subscription create mock + nock(baseWso2Url) + .post(/.*\/store\/v1\/subscriptions$/) + .reply(201, { ...testDefs, subscriptionId: '123-456' }); + + // subscription get mock + nock(baseWso2Url) + .get(/.*\/store\/v1\/subscriptions\/[^\\/]+$/) + .times(1) // check if was created + .reply(200, { ...testDefs }); + + const eres = await handler( + testCFNEventCreate({ + ...testEvent, + }), + ); + expect(eres.PhysicalResourceId).toBe('123-456'); + expect(eres.Status).toBe('SUCCESS'); + }); + + const testSubscriptionDefs = (): Wso2SubscriptionDefinition => { + return { + apiId: '111-222', + applicationId: '333-444', + throttlingPolicy: 'Unlimited', + }; + }; + + const commonEvt = { + StackId: 'test-stack', + RequestId: '123-123123', + LogicalResourceId: 'abc abc', + ServiceToken: 'arn:somelambdatest', + ResponseURL: 's3bucketxxx', + ResourceType: 'wso2subscription', + }; + + const testCFNEventCreate = ( + baseProperties: Wso2SubscriptionCustomResourceProperties, + ): Wso2SubscriptionCustomResourceEvent => { + return { + ...commonEvt, + RequestType: 'Create', + ResourceProperties: { ...baseProperties, ServiceToken: 'arn:somelambdatest' }, + }; + }; + const testCFNEventDelete = ( + baseProperties: Wso2SubscriptionCustomResourceProperties, + PhysicalResourceId: string, + ): Wso2SubscriptionCustomResourceEvent => { + return { + ...commonEvt, + RequestType: 'Delete', + ResourceProperties: { ...baseProperties, ServiceToken: 'arn:somelambdatest' }, + PhysicalResourceId, + }; + }; + // const testCFNEventUpdate = ( + // baseProperties: Wso2SubscriptionCustomResourceProperties, + // PhysicalResourceId: string, + // oldResourceProperties: Record, + // ): Wso2SubscriptionCustomResourceEvent => { + // return { + // ...commonEvt, + // RequestType: 'Update', + // ResourceProperties: { ...baseProperties, ServiceToken: 'arn:somelambdatest' }, + // PhysicalResourceId, + // OldResourceProperties: oldResourceProperties, + // }; + // }; + + const testEvent: Wso2SubscriptionCustomResourceProperties = { + wso2Config: { + baseApiUrl: baseWso2Url, + credentialsSecretId: 'arn:aws:secretsmanager:us-east-1:123123123:secret:MySecret', + apiVersion: 'v1', + }, + subscriptionDefinition: testSubscriptionDefs(), + retryOptions: testRetryOptions, + }; +}); diff --git a/lib/src/wso2/wso2-subscription/handler/index.ts b/lib/src/wso2/wso2-subscription/handler/index.ts new file mode 100644 index 0000000..24c9148 --- /dev/null +++ b/lib/src/wso2/wso2-subscription/handler/index.ts @@ -0,0 +1,143 @@ +/* eslint-disable no-console */ + +import type { CdkCustomResourceEvent, CdkCustomResourceResponse } from 'aws-lambda'; +import type { AxiosInstance } from 'axios'; + +import { prepareAxiosForWso2Calls } from '../../wso2-utils'; +import { applyRetryDefaults, truncateStr } from '../../utils'; +import type { Wso2SubscriptionInfo } from '../v1/types'; +import type { Wso2SubscriptionCustomResourceProperties } from '../types'; + +import { createUpdateSubscriptionInWso2, removeSubscriptionInWso2 } from './wso2-v1'; + +export type Wso2SubscriptionCustomResourceEvent = CdkCustomResourceEvent & { + ResourceProperties: Wso2SubscriptionCustomResourceProperties; +}; + +export type Wso2SubscriptionCustomResourceResponse = CdkCustomResourceResponse & { + Data?: { + ApiEndpointUrl?: string; + Error?: unknown; + }; + Status?: 'SUCCESS' | 'FAILED'; + Reason?: string; +}; + +export const handler = async ( + event: Wso2SubscriptionCustomResourceEvent, +): Promise => { + console.log(`WSO2 API Custom Resource invoked with: ${JSON.stringify(event)}`); + + if (!event.ResourceProperties.subscriptionDefinition) { + throw new Error('event.subscriptionDefinition should be defined'); + } + if (!event.ResourceProperties.wso2Config) { + throw new Error('event.wso2Config should be defined'); + } + + const response: Wso2SubscriptionCustomResourceResponse = { + StackId: event.StackId, + RequestId: event.RequestId, + LogicalResourceId: event.LogicalResourceId, + }; + + try { + console.log('>>> Prepare WSO2 API client...'); + const wso2Axios = await prepareAxiosForWso2Calls(event.ResourceProperties.wso2Config); + + if (event.RequestType === 'Create' || event.RequestType === 'Update') { + if (event.RequestType === 'Update') { + response.PhysicalResourceId = event.PhysicalResourceId; + } + console.log('>>> Creating or Updating WSO2 Subscription...'); + const wso2SubscriptionId = await createOrUpdateWso2Subscription(event, wso2Axios); + response.PhysicalResourceId = wso2SubscriptionId; + response.Data = { + Wso2SubscriptionId: wso2SubscriptionId, + }; + response.Status = 'SUCCESS'; + return response; + } + if (event.RequestType === 'Delete') { + console.log('>>> Deleting WSO2 Subscription...'); + response.PhysicalResourceId = event.PhysicalResourceId; + await removeSubscriptionInWso2({ + wso2Axios, + wso2SubscriptionId: event.PhysicalResourceId, + }); + response.Status = 'SUCCESS'; + return response; + } + throw new Error('Unrecognized RequestType'); + } catch (error) { + console.log(`An error has occurred. err=${error}`); + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const err = error as any; + if (err.stack) { + console.log(err.stack); + } + throw new Error(truncateStr(`${error}`, 1000)); + } +}; + +const createOrUpdateWso2Subscription = async ( + event: Wso2SubscriptionCustomResourceEvent, + wso2Axios: AxiosInstance, +): Promise => { + if (!event.ResourceProperties.subscriptionDefinition?.apiId) { + throw new Error('subscriptionDefinition.apiId should be defined'); + } + if (!event.ResourceProperties.subscriptionDefinition?.applicationId) { + throw new Error('subscriptionDefinition.applicationId should be defined'); + } + + // find existing WSO2 subscription to the same apiId by the same applicationId + console.log('Searching if Subscription already exists in WSO2...'); + let existingSubscription: Wso2SubscriptionInfo | undefined; + const apil = await wso2Axios.get(`/api/am/store/v1/subscriptions`, { + params: { + applicationId: event.ResourceProperties.subscriptionDefinition.applicationId, + apiId: event.ResourceProperties.subscriptionDefinition.apiId, + }, + }); + const apiRes = apil.data.list as Wso2SubscriptionInfo[]; + if (apiRes.length > 1) { + throw new Error( + `More than one Subscription for apiId='${event.ResourceProperties.subscriptionDefinition.apiId}' and applicationId='${event.ResourceProperties.subscriptionDefinition.applicationId}' was found in WSO2 so we cannot determine which subscription to manage automatically`, + ); + } + if (apiRes.length === 1) { + existingSubscription = apiRes[0]; + console.log( + `Found existing WSO2 Subscription. subscriptionId=${existingSubscription.subscriptionId}; apiId=${existingSubscription.apiId}; applicationId=${existingSubscription.applicationId}`, + ); + } + + if ( + event.RequestType === 'Create' && + existingSubscription && + event.ResourceProperties.failIfExists + ) { + throw new Error( + `WSO2 Subscription '${existingSubscription.subscriptionId}' already exists but cannot be managed by this resource. Change 'failIfExists' to change this behavior`, + ); + } + + if (event.RequestType === 'Update' && !existingSubscription) { + console.log( + `WARNING: This is an Update operation but the Subscription couldn't be found in WSO2. It will be created again`, + ); + } + + if (event.RequestType === 'Create' || event.RequestType === 'Update') { + return createUpdateSubscriptionInWso2({ + wso2Axios, + wso2Tenant: event.ResourceProperties.wso2Config.tenant ?? '', + subscriptionDefinition: event.ResourceProperties.subscriptionDefinition, + existingSubscription, + retryOptions: applyRetryDefaults(event.ResourceProperties.retryOptions), + }); + } + + throw new Error(`Invalid requestType found. requestType=${event.ResourceType}`); +}; diff --git a/lib/src/wso2/wso2-subscription/handler/wso2-v1.ts b/lib/src/wso2/wso2-subscription/handler/wso2-v1.ts new file mode 100644 index 0000000..4ffee7f --- /dev/null +++ b/lib/src/wso2/wso2-subscription/handler/wso2-v1.ts @@ -0,0 +1,96 @@ +/* eslint-disable no-console */ +import { backOff } from 'exponential-backoff'; +import { AxiosInstance } from 'axios'; + +import type { Wso2SubscriptionDefinition, Wso2SubscriptionInfo } from '../v1/types'; +import type { RetryOptions } from '../../types'; + +export type UpsertWso2Args = { + wso2Axios: AxiosInstance; + wso2Tenant: string; + existingSubscription?: Wso2SubscriptionInfo; + subscriptionDefinition: Wso2SubscriptionDefinition; + retryOptions: RetryOptions; +}; + +/** + * Delete Subscription in WSO2 server + */ +export const removeSubscriptionInWso2 = async (args: { + wso2Axios: AxiosInstance; + wso2SubscriptionId: string; +}): Promise => { + if (!args.wso2SubscriptionId) { + throw new Error('wso2SubscriptionId is required for deleting Application'); + } + await args.wso2Axios.delete(`/api/am/store/v1/subscriptions/${args.wso2SubscriptionId}`); +}; + +/** + * Perform calls in WSO2 API to create or update an Application + * @returns {string} Id of the Application in WSO2 + */ +export const createUpdateSubscriptionInWso2 = async (args: UpsertWso2Args): Promise => { + console.log(''); + console.log(`>>> Create or update subscription in WSO2...`); + // will retry create/update api operation if fails + const wso2SubscriptionId = await backOff( + async () => createUpdateSubscriptionInWso2AndCheck(args), + args.retryOptions.mutationRetries, + ); + + console.log('Subscription created/updated on WSO2 server successfuly'); + + return wso2SubscriptionId; +}; + +export const createUpdateSubscriptionInWso2AndCheck = async ( + args: UpsertWso2Args, +): Promise => { + // create new Subscription in WSO2 + if (!args.existingSubscription) { + console.log(`Creating new Subscription in WSO2...`); + const apir = await args.wso2Axios.post( + `/api/am/store/v1/subscriptions`, + args.subscriptionDefinition, + ); + + const dataRes = apir.data as Wso2SubscriptionInfo; + if (!dataRes.subscriptionId) { + throw new Error( + `'subscriptionId' wasn't returned as part of the Subscription creation response`, + ); + } + console.log(`Subscription "${dataRes.subscriptionId}" created in WSO2`); + + console.log(`Checking if the Subscription was created in WSO2 by retrying checks`); + await backOff(async () => { + await args.wso2Axios.get(`/api/am/store/v1/subscriptions/${dataRes.subscriptionId}`); + // TODO check if returned contents match desired state + }, args.retryOptions.checkRetries); + + return dataRes.subscriptionId; + } + + // update existing Subscription in WSO2 + console.log(`Updating Subscription definitions in WSO2`); + + if (!args.existingSubscription.subscriptionId) { + throw new Error('Existing subscriptionId should be defined'); + } + + await args.wso2Axios.put( + `/api/am/store/v1/subscriptions/${args.existingSubscription.subscriptionId}`, + args.subscriptionDefinition, + ); + + console.log(`Checking if the Subscription exists in WSO2 by retrying checks`); + await backOff(async () => { + await args.wso2Axios.get( + `/api/am/store/v1/subscriptions/${args.existingSubscription?.subscriptionId}`, + ); + // TODO check if returned contents match desired state + }, args.retryOptions.checkRetries); + + return args.existingSubscription.subscriptionId; +}; diff --git a/lib/src/wso2/wso2-subscription/types.ts b/lib/src/wso2/wso2-subscription/types.ts new file mode 100644 index 0000000..cad0eca --- /dev/null +++ b/lib/src/wso2/wso2-subscription/types.ts @@ -0,0 +1,12 @@ +import { Wso2BaseProperties } from '../types'; + +import { Wso2SubscriptionDefinition } from './v1/types'; + +export type Wso2SubscriptionCustomResourceProperties = Wso2SubscriptionProps; + +/** + * WSO2 Subscription construct parameters + */ +export type Wso2SubscriptionProps = Wso2BaseProperties & { + subscriptionDefinition: Wso2SubscriptionDefinition; +}; diff --git a/lib/src/wso2/wso2-subscription/v1/types.ts b/lib/src/wso2/wso2-subscription/v1/types.ts new file mode 100644 index 0000000..c950dfe --- /dev/null +++ b/lib/src/wso2/wso2-subscription/v1/types.ts @@ -0,0 +1,41 @@ +export type Wso2SubscriptionInfo = Wso2SubscriptionDefinition & { + /** + * Subscription Id + * @example 123-456-789 + */ + subscriptionId: string; +}; + +export type Wso2SubscriptionDefinition = { + /** + * Api Id that will be subscribed by an application + * @example 123-456-789 + */ + apiId: string; + /** + * Application Id that will subscribe to the API + * @example 123-456-789 + */ + applicationId: string; + // /** + // * Subscription Id of the subscription. If not defined a new Subscription might be created during createOrUpdate operations. + // * @example 123-456-789 + // */ + // subscriptionId?: string; + /** + * Throttling policy applied to the calls from this Application + * @example Unlimited + * */ + throttlingPolicy: 'Unlimited' | 'Bronze' | 'Silver' | 'Gold' | string; + /** + * Status of the subscription + * @example Unlimited + * */ + status?: + | 'BLOCKED' + | 'PROD_ONLY_BLOCKED' + | 'UNBLOCKED' + | 'ON_HOLD' + | 'REJECTED' + | 'TIER_UPDATE_PENDING'; +}; diff --git a/lib/src/wso2/wso2-subscription/wso2-subscription.test.ts b/lib/src/wso2/wso2-subscription/wso2-subscription.test.ts new file mode 100644 index 0000000..2a775eb --- /dev/null +++ b/lib/src/wso2/wso2-subscription/wso2-subscription.test.ts @@ -0,0 +1,44 @@ +/* eslint-disable camelcase */ +/* eslint-disable @typescript-eslint/ban-ts-comment */ +/* eslint-disable fp/no-mutating-methods */ + +import { App, Stack } from 'aws-cdk-lib/core'; +import { Template } from 'aws-cdk-lib/assertions'; + +import { Wso2SubscriptionProps } from './types'; +import { Wso2Subscription } from './wso2-subscription'; + +describe('wso2-subscription-construct', () => { + it('minimal wso2 api', async () => { + const app = new App(); + const stack = new Stack(app); + + const testProps1 = testProps(); + const wso2Subscription = new Wso2Subscription(stack, 'wso2', testProps1); + + expect(wso2Subscription.customResourceFunction).toBeDefined(); + + const template = Template.fromStack(stack); + // eslint-disable-next-line no-console + // console.log(JSON.stringify(template.toJSON(), null, 2)); + + template.hasResourceProperties('Custom::Wso2Subscription', { + wso2Config: testProps1.wso2Config, + subscriptionDefinition: testProps1.subscriptionDefinition, + }); + }); +}); + +const testProps = (): Wso2SubscriptionProps => { + return { + wso2Config: { + baseApiUrl: 'http://localhost:8080/wso2', + credentialsSecretId: 'arn::creds', + }, + subscriptionDefinition: { + apiId: '1111-2222', + applicationId: '3333-4444', + throttlingPolicy: 'Unlimited', + }, + }; +}; diff --git a/lib/src/wso2/wso2-subscription/wso2-subscription.ts b/lib/src/wso2/wso2-subscription/wso2-subscription.ts new file mode 100644 index 0000000..5d1dd2e --- /dev/null +++ b/lib/src/wso2/wso2-subscription/wso2-subscription.ts @@ -0,0 +1,75 @@ +import { Construct } from 'constructs'; +import { CustomResource, RemovalPolicy } from 'aws-cdk-lib/core'; +import { IFunction } from 'aws-cdk-lib/aws-lambda'; + +import { addLambdaAndProviderForWso2Operations } from '../utils-cdk'; + +import { Wso2SubscriptionCustomResourceProperties, Wso2SubscriptionProps } from './types'; + +/** + * WSO2 API CDK construct for creating a WSO2 subscription from one application to an API + * This construct is related to one "physical" subscription in WSO2. + * + * The internal implementation tries to protect itself from various scenarios where larger or more complex + * WSO2 clusters might lead to out-of-order or delays in operations that happen assynchronously after the API + * accepts the requests, so for every mutation, there is a check to verify sanity. + */ +export class Wso2Subscription extends Construct { + readonly customResourceFunction: IFunction; + + constructor(scope: Construct, id: string, props: Wso2SubscriptionProps) { + super(scope, id); + + // Do as much of the logic in the construct as possible and leave only + // the minimal complexity to the Lambda Custom Resource as it's harder + // to debug and eventual errors will rollback the entire stack and will + // make the feedback cycle much longer. + + // Keep this construct stateless (don't access WSO2 apis) and + // leave the stateful part to the Lambda Custom Resource (accessing WSO2 apis etc) + + validateProps(props); + + const { customResourceProvider, customResourceFunction } = + addLambdaAndProviderForWso2Operations({ + scope: this, + id: `${id}-wso2sub`, + props, + baseDir: __dirname, + }); + + // eslint-disable-next-line no-new + new CustomResource(this, `${id}-wso2sub-custom-resource`, { + serviceToken: customResourceProvider.serviceToken, + properties: { + wso2Config: props.wso2Config, + subscriptionDefinition: props.subscriptionDefinition, + retryOptions: props.retryOptions, + } as Wso2SubscriptionCustomResourceProperties, + resourceType: 'Custom::Wso2Subscription', + removalPolicy: props.removalPolicy ?? RemovalPolicy.RETAIN, + }); + + this.customResourceFunction = customResourceFunction.nodeJsFunction; + } +} + +export const validateProps = (props: Wso2SubscriptionProps): void => { + if (!props.wso2Config) throw new Error('wso2Config is required'); + if (!props.wso2Config.baseApiUrl) throw new Error('wso2Config.baseApiUrl is required'); + if (!props.wso2Config.credentialsSecretId) { + throw new Error('wso2Config.credentialsSecretManagerPath is required'); + } + if (!props.subscriptionDefinition) { + throw new Error('subscriptionDefinition is required'); + } + if (!props.subscriptionDefinition.apiId) { + throw new Error('subscriptionDefinition.apiId is required'); + } + if (!props.subscriptionDefinition.applicationId) { + throw new Error('subscriptionDefinition.applicationId is required'); + } + if (!props.subscriptionDefinition.throttlingPolicy) { + throw new Error('subscriptionDefinition.throttlingPolicy is required'); + } +}; diff --git a/lib/src/wso2/wso2-utils.test.ts b/lib/src/wso2/wso2-utils.test.ts new file mode 100644 index 0000000..96b50fb --- /dev/null +++ b/lib/src/wso2/wso2-utils.test.ts @@ -0,0 +1,30 @@ +import { GetSecretValueCommand, SecretsManagerClient } from '@aws-sdk/client-secrets-manager'; +import { mockClient } from 'aws-sdk-client-mock'; +import nock from 'nock'; + +export const nockBasicWso2SDK = (baseWso2Url: string): void => { + const secretMock = mockClient(SecretsManagerClient); + secretMock.on(GetSecretValueCommand).resolves({ + SecretBinary: Buffer.from(JSON.stringify({ user: 'user1', pwd: 'pwd1' })), + }); + + // register client mock + nock(baseWso2Url).post('/client-registration/v0.17/register').reply(200, { + clientId: 'clientId1', + clientSecret: 'clientSecret1', + }); + + // get token mock + nock(baseWso2Url).post('/oauth2/token').reply(200, { + // eslint-disable-next-line camelcase + access_token: '1111-1111-1111', + }); + + // mock server check + nock(baseWso2Url) + .get('/services/Version') + .reply( + 200, + 'WSO2 API Manager-3.2.0', + ); +};