cdk-cost-analyzer 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (228) hide show
  1. package/.cdk-cost-analyzer-cache/metadata.json +12 -0
  2. package/.gitlab-ci.yml +214 -0
  3. package/.husky/pre-commit +12 -0
  4. package/.kiro/hooks/accessibility-audit.kiro.hook +18 -0
  5. package/.kiro/hooks/api-schema-validation.kiro.hook +21 -0
  6. package/.kiro/hooks/auto-test-on-save.kiro.hook +19 -0
  7. package/.kiro/hooks/cdk-synth-on-change.kiro.hook +20 -0
  8. package/.kiro/hooks/code-coverage-check.kiro.hook +14 -0
  9. package/.kiro/hooks/commit-message-helper.kiro.hook +14 -0
  10. package/.kiro/hooks/dependency-update-check.kiro.hook +14 -0
  11. package/.kiro/hooks/env-file-validation.kiro.hook +18 -0
  12. package/.kiro/hooks/lint-and-format-on-save.kiro.hook +21 -0
  13. package/.kiro/hooks/mcp-config-validation.kiro.hook +17 -0
  14. package/.kiro/hooks/mcp-server-test.kiro.hook +14 -0
  15. package/.kiro/hooks/performance-analysis.kiro.hook +14 -0
  16. package/.kiro/hooks/readme-spell-check.kiro.hook +14 -0
  17. package/.kiro/hooks/security-scan-on-dependency-change.kiro.hook +21 -0
  18. package/.kiro/hooks/translation-update.kiro.hook +18 -0
  19. package/.kiro/hooks/update-documentation.kiro.hook +18 -0
  20. package/.kiro/settings/mcp.json +20 -0
  21. package/.kiro/specs/cdk-cost-analyzer/design.md +620 -0
  22. package/.kiro/specs/cdk-cost-analyzer/requirements.md +183 -0
  23. package/.kiro/specs/cdk-cost-analyzer/tasks.md +357 -0
  24. package/.kiro/specs/github-actions-ci/design.md +281 -0
  25. package/.kiro/specs/github-actions-ci/requirements.md +86 -0
  26. package/.kiro/specs/github-actions-ci/tasks.md +115 -0
  27. package/.kiro/specs/nlb-calculator-test-coverage/design.md +190 -0
  28. package/.kiro/specs/nlb-calculator-test-coverage/requirements.md +84 -0
  29. package/.kiro/specs/nlb-calculator-test-coverage/tasks.md +150 -0
  30. package/.kiro/specs/production-readiness/design.md +1213 -0
  31. package/.kiro/specs/production-readiness/requirements.md +312 -0
  32. package/.kiro/specs/production-readiness/tasks.md +269 -0
  33. package/.kiro/specs/repository-cleanup/design.md +283 -0
  34. package/.kiro/specs/repository-cleanup/requirements.md +74 -0
  35. package/.kiro/specs/repository-cleanup/tasks.md +64 -0
  36. package/.kiro/steering/aws-cli-best-practices.md +41 -0
  37. package/.kiro/steering/cdk-best-practices.md +49 -0
  38. package/.kiro/steering/development-standards.md +54 -0
  39. package/.kiro/steering/docker-best-practices.md +34 -0
  40. package/.kiro/steering/documentation-style.md +151 -0
  41. package/.kiro/steering/git-best-practices.md +37 -0
  42. package/.kiro/steering/mcp-best-practices.md +95 -0
  43. package/.kiro/steering/python-best-practices.md +48 -0
  44. package/.kiro/steering/react-best-practices.md +44 -0
  45. package/.kiro/steering/security-best-practices.md +41 -0
  46. package/.kiro/steering/testing-best-practices.md +59 -0
  47. package/.kiro/steering/typescript-best-practices.md +40 -0
  48. package/CHANGELOG.md +49 -0
  49. package/CONTRIBUTING.md +258 -0
  50. package/LICENSE +19 -0
  51. package/README.md +480 -0
  52. package/SECURITY.md +117 -0
  53. package/dist/api/index.d.ts +11 -0
  54. package/dist/api/index.js +65 -0
  55. package/dist/api/types.d.ts +15 -0
  56. package/dist/api/types.js +3 -0
  57. package/dist/cli/index.d.ts +2 -0
  58. package/dist/cli/index.js +262 -0
  59. package/dist/config/ConfigManager.d.ts +40 -0
  60. package/dist/config/ConfigManager.js +238 -0
  61. package/dist/config/index.d.ts +2 -0
  62. package/dist/config/index.js +19 -0
  63. package/dist/config/types.d.ts +72 -0
  64. package/dist/config/types.js +15 -0
  65. package/dist/diff/DiffEngine.d.ts +7 -0
  66. package/dist/diff/DiffEngine.js +73 -0
  67. package/dist/diff/index.d.ts +2 -0
  68. package/dist/diff/index.js +21 -0
  69. package/dist/diff/types.d.ts +20 -0
  70. package/dist/diff/types.js +3 -0
  71. package/dist/integrations/GitLabIntegration.d.ts +7 -0
  72. package/dist/integrations/GitLabIntegration.js +45 -0
  73. package/dist/integrations/index.d.ts +2 -0
  74. package/dist/integrations/index.js +21 -0
  75. package/dist/integrations/types.d.ts +11 -0
  76. package/dist/integrations/types.js +13 -0
  77. package/dist/parser/TemplateParser.d.ts +8 -0
  78. package/dist/parser/TemplateParser.js +75 -0
  79. package/dist/parser/index.d.ts +2 -0
  80. package/dist/parser/index.js +22 -0
  81. package/dist/parser/types.d.ts +30 -0
  82. package/dist/parser/types.js +3 -0
  83. package/dist/pipeline/PipelineOrchestrator.d.ts +23 -0
  84. package/dist/pipeline/PipelineOrchestrator.js +191 -0
  85. package/dist/pipeline/index.d.ts +2 -0
  86. package/dist/pipeline/index.js +19 -0
  87. package/dist/pipeline/types.d.ts +41 -0
  88. package/dist/pipeline/types.js +13 -0
  89. package/dist/pricing/CacheManager.d.ts +75 -0
  90. package/dist/pricing/CacheManager.js +195 -0
  91. package/dist/pricing/PricingClient.d.ts +17 -0
  92. package/dist/pricing/PricingClient.js +122 -0
  93. package/dist/pricing/PricingService.d.ts +16 -0
  94. package/dist/pricing/PricingService.js +149 -0
  95. package/dist/pricing/calculators/ALBCalculator.d.ts +16 -0
  96. package/dist/pricing/calculators/ALBCalculator.js +163 -0
  97. package/dist/pricing/calculators/APIGatewayCalculator.d.ts +10 -0
  98. package/dist/pricing/calculators/APIGatewayCalculator.js +177 -0
  99. package/dist/pricing/calculators/CloudFrontCalculator.d.ts +59 -0
  100. package/dist/pricing/calculators/CloudFrontCalculator.js +151 -0
  101. package/dist/pricing/calculators/DynamoDBCalculator.d.ts +9 -0
  102. package/dist/pricing/calculators/DynamoDBCalculator.js +146 -0
  103. package/dist/pricing/calculators/EC2Calculator.d.ts +7 -0
  104. package/dist/pricing/calculators/EC2Calculator.js +80 -0
  105. package/dist/pricing/calculators/ECSCalculator.d.ts +9 -0
  106. package/dist/pricing/calculators/ECSCalculator.js +116 -0
  107. package/dist/pricing/calculators/ElastiCacheCalculator.d.ts +8 -0
  108. package/dist/pricing/calculators/ElastiCacheCalculator.js +106 -0
  109. package/dist/pricing/calculators/LambdaCalculator.d.ts +13 -0
  110. package/dist/pricing/calculators/LambdaCalculator.js +111 -0
  111. package/dist/pricing/calculators/NLBCalculator.d.ts +16 -0
  112. package/dist/pricing/calculators/NLBCalculator.js +138 -0
  113. package/dist/pricing/calculators/NatGatewayCalculator.d.ts +12 -0
  114. package/dist/pricing/calculators/NatGatewayCalculator.js +116 -0
  115. package/dist/pricing/calculators/RDSCalculator.d.ts +9 -0
  116. package/dist/pricing/calculators/RDSCalculator.js +103 -0
  117. package/dist/pricing/calculators/S3Calculator.d.ts +8 -0
  118. package/dist/pricing/calculators/S3Calculator.js +68 -0
  119. package/dist/pricing/calculators/VPCEndpointCalculator.d.ts +12 -0
  120. package/dist/pricing/calculators/VPCEndpointCalculator.js +129 -0
  121. package/dist/pricing/index.d.ts +10 -0
  122. package/dist/pricing/index.js +37 -0
  123. package/dist/pricing/types.d.ts +53 -0
  124. package/dist/pricing/types.js +22 -0
  125. package/dist/releasetag.txt +1 -0
  126. package/dist/reporter/Reporter.d.ts +18 -0
  127. package/dist/reporter/Reporter.js +412 -0
  128. package/dist/reporter/index.d.ts +2 -0
  129. package/dist/reporter/index.js +21 -0
  130. package/dist/reporter/types.d.ts +72 -0
  131. package/dist/reporter/types.js +3 -0
  132. package/dist/synthesis/SynthesisOrchestrator.d.ts +26 -0
  133. package/dist/synthesis/SynthesisOrchestrator.js +243 -0
  134. package/dist/synthesis/index.d.ts +2 -0
  135. package/dist/synthesis/index.js +19 -0
  136. package/dist/synthesis/types.d.ts +17 -0
  137. package/dist/synthesis/types.js +13 -0
  138. package/dist/threshold/ThresholdEnforcer.d.ts +29 -0
  139. package/dist/threshold/ThresholdEnforcer.js +143 -0
  140. package/dist/threshold/index.d.ts +2 -0
  141. package/dist/threshold/index.js +19 -0
  142. package/dist/threshold/types.d.ts +15 -0
  143. package/dist/threshold/types.js +17 -0
  144. package/docs/CALCULATORS.md +820 -0
  145. package/docs/CI_CD.md +608 -0
  146. package/docs/CONFIGURATION.md +407 -0
  147. package/docs/DEVELOPMENT.md +387 -0
  148. package/docs/RELEASE.md +223 -0
  149. package/docs/TROUBLESHOOTING.md +847 -0
  150. package/examples/.cdk-cost-analyzer.yml +85 -0
  151. package/examples/.gitlab-ci.yml +125 -0
  152. package/examples/api-usage.js +26 -0
  153. package/examples/complex/base.json +16 -0
  154. package/examples/complex/target.json +29 -0
  155. package/examples/monorepo/.gitlab-ci.yml +251 -0
  156. package/examples/monorepo/README.md +341 -0
  157. package/examples/monorepo/package.json +27 -0
  158. package/examples/monorepo/packages/backend-infra/.cdk-cost-analyzer.yml +34 -0
  159. package/examples/monorepo/packages/backend-infra/bin/app.ts +16 -0
  160. package/examples/monorepo/packages/backend-infra/cdk.json +7 -0
  161. package/examples/monorepo/packages/backend-infra/lib/backend-stack.ts +128 -0
  162. package/examples/monorepo/packages/backend-infra/package.json +30 -0
  163. package/examples/monorepo/packages/backend-infra/tsconfig.json +11 -0
  164. package/examples/monorepo/packages/data-infra/.cdk-cost-analyzer.yml +38 -0
  165. package/examples/monorepo/packages/data-infra/bin/app.ts +16 -0
  166. package/examples/monorepo/packages/data-infra/cdk.json +7 -0
  167. package/examples/monorepo/packages/data-infra/lib/data-stack.ts +121 -0
  168. package/examples/monorepo/packages/data-infra/package.json +30 -0
  169. package/examples/monorepo/packages/data-infra/tsconfig.json +11 -0
  170. package/examples/monorepo/packages/frontend-infra/.cdk-cost-analyzer.yml +31 -0
  171. package/examples/monorepo/packages/frontend-infra/bin/app.ts +16 -0
  172. package/examples/monorepo/packages/frontend-infra/cdk.json +7 -0
  173. package/examples/monorepo/packages/frontend-infra/lib/frontend-stack.ts +60 -0
  174. package/examples/monorepo/packages/frontend-infra/package.json +30 -0
  175. package/examples/monorepo/packages/frontend-infra/tsconfig.json +11 -0
  176. package/examples/monorepo/tsconfig.json +35 -0
  177. package/examples/multi-stack/.cdk-cost-analyzer.yml +72 -0
  178. package/examples/multi-stack/.gitlab-ci.yml +184 -0
  179. package/examples/multi-stack/README.md +279 -0
  180. package/examples/multi-stack/bin/app.ts +36 -0
  181. package/examples/multi-stack/cdk.json +72 -0
  182. package/examples/multi-stack/lib/compute-stack.ts +128 -0
  183. package/examples/multi-stack/lib/networking-stack.ts +69 -0
  184. package/examples/multi-stack/lib/storage-stack.ts +141 -0
  185. package/examples/multi-stack/package-lock.json +4437 -0
  186. package/examples/multi-stack/package.json +42 -0
  187. package/examples/multi-stack/tsconfig.json +34 -0
  188. package/examples/simple/base.json +8 -0
  189. package/examples/simple/target.json +14 -0
  190. package/examples/single-stack/.NVP +0 -0
  191. package/examples/single-stack/.cdk-cost-analyzer.yml +52 -0
  192. package/examples/single-stack/.gitlab-ci.yml +126 -0
  193. package/examples/single-stack/README.md +184 -0
  194. package/examples/single-stack/UeK +0 -0
  195. package/examples/single-stack/bin/app.ts +16 -0
  196. package/examples/single-stack/cdk.json +72 -0
  197. package/examples/single-stack/lib/infrastructure-stack.ts +119 -0
  198. package/examples/single-stack/package-lock.json +4443 -0
  199. package/examples/single-stack/package.json +38 -0
  200. package/examples/single-stack/tsconfig.json +34 -0
  201. package/package.json +139 -0
  202. package/test-cdk-project/README-COMPUTE.md +141 -0
  203. package/test-cdk-project/README.md +95 -0
  204. package/test-cdk-project/app-with-compute.js +102 -0
  205. package/test-cdk-project/app.js +81 -0
  206. package/test-cdk-project/cdk-compute.json +3 -0
  207. package/test-cdk-project/cdk.context.json +7 -0
  208. package/test-cdk-project/cdk.json +3 -0
  209. package/test-cdk-project/cdk.out/TestStack.assets.json +21 -0
  210. package/test-cdk-project/cdk.out/TestStack.template.json +115 -0
  211. package/test-cdk-project/cdk.out/cdk.out +1 -0
  212. package/test-cdk-project/cdk.out/manifest.json +503 -0
  213. package/test-cdk-project/cdk.out/tree.json +1 -0
  214. package/test-cdk-project/cdk.out.base/TestStack.assets.json +21 -0
  215. package/test-cdk-project/cdk.out.base/TestStack.template.json +115 -0
  216. package/test-cdk-project/cdk.out.base/cdk.out +1 -0
  217. package/test-cdk-project/cdk.out.base/manifest.json +503 -0
  218. package/test-cdk-project/cdk.out.base/tree.json +1 -0
  219. package/test-cdk-project/cdk.out.target/TestStack.assets.json +21 -0
  220. package/test-cdk-project/cdk.out.target/TestStack.template.json +183 -0
  221. package/test-cdk-project/cdk.out.target/cdk.out +1 -0
  222. package/test-cdk-project/cdk.out.target/manifest.json +521 -0
  223. package/test-cdk-project/cdk.out.target/tree.json +1 -0
  224. package/test-cdk-project/package-lock.json +422 -0
  225. package/test-cdk-project/package.json +17 -0
  226. package/tools/workflows/README.md +102 -0
  227. package/tools/workflows/validate-workflows.js +109 -0
  228. package/tools/workflows/workflow-utils.ts +181 -0
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PricingClient = void 0;
4
+ const client_pricing_1 = require("@aws-sdk/client-pricing");
5
+ const types_1 = require("./types");
6
+ class PricingClient {
7
+ cache = new Map();
8
+ client;
9
+ cacheManager;
10
+ constructor(region = 'us-east-1', cacheManager, awsClient) {
11
+ this.client = awsClient || new client_pricing_1.PricingClient({ region });
12
+ this.cacheManager = cacheManager;
13
+ }
14
+ /**
15
+ * Clean up resources and connections
16
+ */
17
+ destroy() {
18
+ this.cache.clear();
19
+ // AWS SDK v3 clients automatically clean up their connections
20
+ // but we can help by clearing references
21
+ if (this.client && typeof this.client.destroy === 'function') {
22
+ this.client.destroy();
23
+ }
24
+ }
25
+ async getPrice(params) {
26
+ const cacheKey = this.getCacheKey(params);
27
+ // Check in-memory cache first
28
+ if (this.cache.has(cacheKey)) {
29
+ return this.cache.get(cacheKey);
30
+ }
31
+ // Check persistent cache if cache manager is available
32
+ if (this.cacheManager) {
33
+ const cachedPrice = this.cacheManager.getCachedPrice(params);
34
+ if (cachedPrice !== null) {
35
+ // Store in memory cache for faster subsequent access
36
+ this.cache.set(cacheKey, cachedPrice);
37
+ return cachedPrice;
38
+ }
39
+ }
40
+ try {
41
+ const price = await this.fetchPriceWithRetry(params);
42
+ if (price !== null) {
43
+ // Store in both memory and persistent cache
44
+ this.cache.set(cacheKey, price);
45
+ if (this.cacheManager) {
46
+ this.cacheManager.setCachedPrice(params, price);
47
+ }
48
+ }
49
+ return price;
50
+ }
51
+ catch (error) {
52
+ // On API failure, try to use cached data even if stale
53
+ if (this.cache.has(cacheKey)) {
54
+ return this.cache.get(cacheKey);
55
+ }
56
+ if (this.cacheManager) {
57
+ const cachedPrice = this.cacheManager.getCachedPrice(params);
58
+ if (cachedPrice !== null) {
59
+ return cachedPrice;
60
+ }
61
+ }
62
+ return null;
63
+ }
64
+ }
65
+ async fetchPriceWithRetry(params, maxRetries = 3) {
66
+ let lastError = null;
67
+ for (let attempt = 0; attempt < maxRetries; attempt++) {
68
+ try {
69
+ return await this.fetchPrice(params);
70
+ }
71
+ catch (error) {
72
+ lastError = error;
73
+ if (attempt < maxRetries - 1) {
74
+ const delay = Math.pow(2, attempt) * 1000;
75
+ await new Promise(resolve => setTimeout(resolve, delay));
76
+ }
77
+ }
78
+ }
79
+ throw new types_1.PricingAPIError(`Failed to fetch pricing after ${maxRetries} attempts: ${lastError?.message}`, false);
80
+ }
81
+ async fetchPrice(params) {
82
+ const filters = params.filters.map(f => ({
83
+ Type: f.type || 'TERM_MATCH',
84
+ Field: f.field,
85
+ Value: f.value,
86
+ }));
87
+ const command = new client_pricing_1.GetProductsCommand({
88
+ ServiceCode: params.serviceCode,
89
+ Filters: filters,
90
+ MaxResults: 1,
91
+ });
92
+ const response = await this.client.send(command);
93
+ if (!response.PriceList || response.PriceList.length === 0) {
94
+ return null;
95
+ }
96
+ const priceItem = JSON.parse(response.PriceList[0]);
97
+ const onDemand = priceItem?.terms?.OnDemand;
98
+ if (!onDemand) {
99
+ return null;
100
+ }
101
+ const termKey = Object.keys(onDemand)[0];
102
+ const priceDimensions = onDemand[termKey]?.priceDimensions;
103
+ if (!priceDimensions) {
104
+ return null;
105
+ }
106
+ const dimensionKey = Object.keys(priceDimensions)[0];
107
+ const pricePerUnit = priceDimensions[dimensionKey]?.pricePerUnit?.USD;
108
+ if (!pricePerUnit) {
109
+ return null;
110
+ }
111
+ return parseFloat(pricePerUnit);
112
+ }
113
+ getCacheKey(params) {
114
+ const filterStr = params.filters
115
+ .map(f => `${f.field}:${f.value}`)
116
+ .sort()
117
+ .join('|');
118
+ return `${params.serviceCode}:${params.region}:${filterStr}`;
119
+ }
120
+ }
121
+ exports.PricingClient = PricingClient;
122
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHJpY2luZ0NsaWVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uL3NyYy9wcmljaW5nL1ByaWNpbmdDbGllbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBQUEsNERBQWdHO0FBRWhHLG1DQUE2RjtBQUU3RixNQUFhLGFBQWE7SUFDaEIsS0FBSyxHQUF3QixJQUFJLEdBQUcsRUFBRSxDQUFDO0lBQ3ZDLE1BQU0sQ0FBbUI7SUFDekIsWUFBWSxDQUFnQjtJQUVwQyxZQUNFLFNBQWlCLFdBQVcsRUFDNUIsWUFBMkIsRUFDM0IsU0FBNEI7UUFFNUIsSUFBSSxDQUFDLE1BQU0sR0FBRyxTQUFTLElBQUksSUFBSSw4QkFBZ0IsQ0FBQyxFQUFFLE1BQU0sRUFBRSxDQUFDLENBQUM7UUFDNUQsSUFBSSxDQUFDLFlBQVksR0FBRyxZQUFZLENBQUM7SUFDbkMsQ0FBQztJQUVEOztPQUVHO0lBQ0gsT0FBTztRQUNMLElBQUksQ0FBQyxLQUFLLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDbkIsOERBQThEO1FBQzlELHlDQUF5QztRQUN6QyxJQUFJLElBQUksQ0FBQyxNQUFNLElBQUksT0FBUSxJQUFJLENBQUMsTUFBYyxDQUFDLE9BQU8sS0FBSyxVQUFVLEVBQUUsQ0FBQztZQUNyRSxJQUFJLENBQUMsTUFBYyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2pDLENBQUM7SUFDSCxDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQVEsQ0FBQyxNQUF3QjtRQUNyQyxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1FBRTFDLDhCQUE4QjtRQUM5QixJQUFJLElBQUksQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLFFBQVEsQ0FBQyxFQUFFLENBQUM7WUFDN0IsT0FBTyxJQUFJLENBQUMsS0FBSyxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUUsQ0FBQztRQUNuQyxDQUFDO1FBRUQsdURBQXVEO1FBQ3ZELElBQUksSUFBSSxD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ZCxDQUFDO1FBRUQsT0FBTyxVQUFVLENBQUMsWUFBWSxDQUFDLENBQUM7SUFDbEMsQ0FBQztJQUVPLFdBQVcsQ0FBQyxNQUF3QjtRQUMxQyxNQUFNLFNBQVMsR0FBRyxNQUFNLENBQUMsT0FBTzthQUM3QixHQUFHLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQyxLQUFLLElBQUksQ0FBQyxDQUFDLEtBQUssRUFBRSxDQUFDO2FBQ2pDLElBQUksRUFBRTthQUNOLElBQUksQ0FBQyxHQUFHLENBQUMsQ0FBQztRQUNiLE9BQU8sR0FBRyxNQUFNLENBQUMsV0FBVyxJQUFJLE1BQU0sQ0FBQyxNQUFNLElBQUksU0FBUyxFQUFFLENBQUM7SUFDL0QsQ0FBQztDQUNGO0FBNUlELHNDQTRJQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IFByaWNpbmdDbGllbnQgYXMgQVdTUHJpY2luZ0NsaWVudCwgR2V0UHJvZHVjdHNDb21tYW5kIH0gZnJvbSAnQGF3cy1zZGsvY2xpZW50LXByaWNpbmcnO1xuaW1wb3J0IHsgQ2FjaGVNYW5hZ2VyIH0gZnJvbSAnLi9DYWNoZU1hbmFnZXInO1xuaW1wb3J0IHsgUHJpY2luZ0NsaWVudCBhcyBJUHJpY2luZ0NsaWVudCwgUHJpY2VRdWVyeVBhcmFtcywgUHJpY2luZ0FQSUVycm9yIH0gZnJvbSAnLi90eXBlcyc7XG5cbmV4cG9ydCBjbGFzcyBQcmljaW5nQ2xpZW50IGltcGxlbWVudHMgSVByaWNpbmdDbGllbnQge1xuICBwcml2YXRlIGNhY2hlOiBNYXA8c3RyaW5nLCBudW1iZXI+ID0gbmV3IE1hcCgpO1xuICBwcml2YXRlIGNsaWVudDogQVdTUHJpY2luZ0NsaWVudDtcbiAgcHJpdmF0ZSBjYWNoZU1hbmFnZXI/OiBDYWNoZU1hbmFnZXI7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcmVnaW9uOiBzdHJpbmcgPSAndXMtZWFzdC0xJyxcbiAgICBjYWNoZU1hbmFnZXI/OiBDYWNoZU1hbmFnZXIsXG4gICAgYXdzQ2xpZW50PzogQVdTUHJpY2luZ0NsaWVudCxcbiAgKSB7XG4gICAgdGhpcy5jbGllbnQgPSBhd3NDbGllbnQgfHwgbmV3IEFXU1ByaWNpbmdDbGllbnQoeyByZWdpb24gfSk7XG4gICAgdGhpcy5jYWNoZU1hbmFnZXIgPSBjYWNoZU1hbmFnZXI7XG4gIH1cblxuICAvKipcbiAgICogQ2xlYW4gdXAgcmVzb3VyY2VzIGFuZCBjb25uZWN0aW9uc1xuICAgKi9cbiAgZGVzdHJveSgpOiB2b2lkIHtcbiAgICB0aGlzLmNhY2hlLmNsZWFyKCk7XG4gICAgLy8gQVdTIFNESyB2MyBjbGllbnRzIGF1dG9tYXRpY2FsbHkgY2xlYW4gdXAgdGhlaXIgY29ubmVjdGlvbnNcbiAgICAvLyBidXQgd2UgY2FuIGhlbHAgYnkgY2xlYXJpbmcgcmVmZXJlbmNlc1xuICAgIGlmICh0aGlzLmNsaWVudCAmJiB0eXBlb2YgKHRoaXMuY2xpZW50IGFzIGFueSkuZGVzdHJveSA9PT0gJ2Z1bmN0aW9uJykge1xuICAgICAgKHRoaXMuY2xpZW50IGFzIGFueSkuZGVzdHJveSgpO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIGdldFByaWNlKHBhcmFtczogUHJpY2VRdWVyeVBhcmFtcyk6IFByb21pc2U8bnVtYmVyIHwgbnVsbD4ge1xuICAgIGNvbnN0IGNhY2hlS2V5ID0gdGhpcy5nZXRDYWNoZUtleShwYXJhbXMpO1xuXG4gICAgLy8gQ2hlY2sgaW4tbWVtb3J5IGNhY2hlIGZpcnN0XG4gICAgaWYgKHRoaXMuY2FjaGUuaGFzKGNhY2hlS2V5KSkge1xuICAgICAgcmV0dXJuIHRoaXMuY2FjaGUuZ2V0KGNhY2hlS2V5KSE7XG4gICAgfVxuXG4gICAgLy8gQ2hlY2sgcGVyc2lzdGVudCBjYWNoZSBpZiBjYWNoZSBtYW5hZ2VyIGlzIGF2YWlsYWJsZVxuICAgIGlmICh0aGlzLmNhY2hlTWFuYWdlcikge1xuICAgICAgY29uc3QgY2FjaGVkUHJpY2UgPSB0aGlzLmNhY2hlTWFuYWdlci5nZXRDYWNoZWRQcmljZShwYXJhbXMpO1xuICAgICAgaWYgKGNhY2hlZFByaWNlICE9PSBudWxsKSB7XG4gICAgICAgIC8vIFN0b3JlIGluIG1lbW9yeSBjYWNoZSBmb3IgZmFzdGVyIHN1YnNlcXVlbnQgYWNjZXNzXG4gICAgICAgIHRoaXMuY2FjaGUuc2V0KGNhY2hlS2V5LCBjYWNoZWRQcmljZSk7XG4gICAgICAgIHJldHVybiBjYWNoZWRQcmljZTtcbiAgICAgIH1cbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgcHJpY2UgPSBhd2FpdCB0aGlzLmZldGNoUHJpY2VXaXRoUmV0cnkocGFyYW1zKTtcbiAgICAgIGlmIChwcmljZSAhPT0gbnVsbCkge1xuICAgICAgICAvLyBTdG9yZSBpbiBib3RoIG1lbW9yeSBhbmQgcGVyc2lzdGVudCBjYWNoZVxuICAgICAgICB0aGlzLmNhY2hlLnNldChjYWNoZUtleSwgcHJpY2UpO1xuICAgICAgICBpZiAodGhpcy5jYWNoZU1hbmFnZXIpIHtcbiAgICAgICAgICB0aGlzLmNhY2hlTWFuYWdlci5zZXRDYWNoZWRQcmljZShwYXJhbXMsIHByaWNlKTtcbiAgICAgICAgfVxuICAgICAgfVxuICAgICAgcmV0dXJuIHByaWNlO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICAvLyBPbiBBUEkgZmFpbHVyZSwgdHJ5IHRvIHVzZSBjYWNoZWQgZGF0YSBldmVuIGlmIHN0YWxlXG4gICAgICBpZiAodGhpcy5jYWNoZS5oYXMoY2FjaGVLZXkpKSB7XG4gICAgICAgIHJldHVybiB0aGlzLmNhY2hlLmdldChjYWNoZUtleSkhO1xuICAgICAgfVxuICAgICAgaWYgKHRoaXMuY2FjaGVNYW5hZ2VyKSB7XG4gICAgICAgIGNvbnN0IGNhY2hlZFByaWNlID0gdGhpcy5jYWNoZU1hbmFnZXIuZ2V0Q2FjaGVkUHJpY2UocGFyYW1zKTtcbiAgICAgICAgaWYgKGNhY2hlZFByaWNlICE9PSBudWxsKSB7XG4gICAgICAgICAgcmV0dXJuIGNhY2hlZFByaWNlO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgICByZXR1cm4gbnVsbDtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIGFzeW5jIGZldGNoUHJpY2VXaXRoUmV0cnkocGFyYW1zOiBQcmljZVF1ZXJ5UGFyYW1zLCBtYXhSZXRyaWVzOiBudW1iZXIgPSAzKTogUHJvbWlzZTxudW1iZXIgfCBudWxsPiB7XG4gICAgbGV0IGxhc3RFcnJvcjogRXJyb3IgfCBudWxsID0gbnVsbDtcblxuICAgIGZvciAobGV0IGF0dGVtcHQgPSAwOyBhdHRlbXB0IDwgbWF4UmV0cmllczsgYXR0ZW1wdCsrKSB7XG4gICAgICB0cnkge1xuICAgICAgICByZXR1cm4gYXdhaXQgdGhpcy5mZXRjaFByaWNlKHBhcmFtcyk7XG4gICAgICB9IGNhdGNoIChlcnJvcikge1xuICAgICAgICBsYXN0RXJyb3IgPSBlcnJvciBhcyBFcnJvcjtcbiAgICAgICAgaWYgKGF0dGVtcHQgPCBtYXhSZXRyaWVzIC0gMSkge1xuICAgICAgICAgIGNvbnN0IGRlbGF5ID0gTWF0aC5wb3coMiwgYXR0ZW1wdCkgKiAxMDAwO1xuICAgICAgICAgIGF3YWl0IG5ldyBQcm9taXNlKHJlc29sdmUgPT4gc2V0VGltZW91dChyZXNvbHZlLCBkZWxheSkpO1xuICAgICAgICB9XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhyb3cgbmV3IFByaWNpbmdBUElFcnJvcihcbiAgICAgIGBGYWlsZWQgdG8gZmV0Y2ggcHJpY2luZyBhZnRlciAke21heFJldHJpZXN9IGF0dGVtcHRzOiAke2xhc3RFcnJvcj8ubWVzc2FnZX1gLFxuICAgICAgZmFsc2UsXG4gICAgKTtcbiAgfVxuXG4gIHByaXZhdGUgYXN5bmMgZmV0Y2hQcmljZShwYXJhbXM6IFByaWNlUXVlcnlQYXJhbXMpOiBQcm9taXNlPG51bWJlciB8IG51bGw+IHtcbiAgICBjb25zdCBmaWx0ZXJzID0gcGFyYW1zLmZpbHRlcnMubWFwKGYgPT4gKHtcbiAgICAgIFR5cGU6IGYudHlwZSB8fCAnVEVSTV9NQVRDSCcsXG4gICAgICBGaWVsZDogZi5maWVsZCxcbiAgICAgIFZhbHVlOiBmLnZhbHVlLFxuICAgIH0pKTtcblxuICAgIGNvbnN0IGNvbW1hbmQgPSBuZXcgR2V0UHJvZHVjdHNDb21tYW5kKHtcbiAgICAgIFNlcnZpY2VDb2RlOiBwYXJhbXMuc2VydmljZUNvZGUsXG4gICAgICBGaWx0ZXJzOiBmaWx0ZXJzLFxuICAgICAgTWF4UmVzdWx0czogMSxcbiAgICB9KTtcblxuICAgIGNvbnN0IHJlc3BvbnNlID0gYXdhaXQgdGhpcy5jbGllbnQuc2VuZChjb21tYW5kKTtcblxuICAgIGlmICghcmVzcG9uc2UuUHJpY2VMaXN0IHx8IHJlc3BvbnNlLlByaWNlTGlzdC5sZW5ndGggPT09IDApIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IHByaWNlSXRlbSA9IEpTT04ucGFyc2UocmVzcG9uc2UuUHJpY2VMaXN0WzBdKTtcbiAgICBjb25zdCBvbkRlbWFuZCA9IHByaWNlSXRlbT8udGVybXM/Lk9uRGVtYW5kO1xuXG4gICAgaWYgKCFvbkRlbWFuZCkge1xuICAgICAgcmV0dXJuIG51bGw7XG4gICAgfVxuXG4gICAgY29uc3QgdGVybUtleSA9IE9iamVjdC5rZXlzKG9uRGVtYW5kKVswXTtcbiAgICBjb25zdCBwcmljZURpbWVuc2lvbnMgPSBvbkRlbWFuZFt0ZXJtS2V5XT8ucHJpY2VEaW1lbnNpb25zO1xuXG4gICAgaWYgKCFwcmljZURpbWVuc2lvbnMpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIGNvbnN0IGRpbWVuc2lvbktleSA9IE9iamVjdC5rZXlzKHByaWNlRGltZW5zaW9ucylbMF07XG4gICAgY29uc3QgcHJpY2VQZXJVbml0ID0gcHJpY2VEaW1lbnNpb25zW2RpbWVuc2lvbktleV0/LnByaWNlUGVyVW5pdD8uVVNEO1xuXG4gICAgaWYgKCFwcmljZVBlclVuaXQpIHtcbiAgICAgIHJldHVybiBudWxsO1xuICAgIH1cblxuICAgIHJldHVybiBwYXJzZUZsb2F0KHByaWNlUGVyVW5pdCk7XG4gIH1cblxuICBwcml2YXRlIGdldENhY2hlS2V5KHBhcmFtczogUHJpY2VRdWVyeVBhcmFtcyk6IHN0cmluZyB7XG4gICAgY29uc3QgZmlsdGVyU3RyID0gcGFyYW1zLmZpbHRlcnNcbiAgICAgIC5tYXAoZiA9PiBgJHtmLmZpZWxkfToke2YudmFsdWV9YClcbiAgICAgIC5zb3J0KClcbiAgICAgIC5qb2luKCd8Jyk7XG4gICAgcmV0dXJuIGAke3BhcmFtcy5zZXJ2aWNlQ29kZX06JHtwYXJhbXMucmVnaW9ufToke2ZpbHRlclN0cn1gO1xuICB9XG59XG4iXX0=
@@ -0,0 +1,16 @@
1
+ import { PricingClient } from './PricingClient';
2
+ import { PricingService as IPricingService, MonthlyCost, CostDelta } from './types';
3
+ import { UsageAssumptionsConfig, CacheConfig } from '../config/types';
4
+ import { ResourceWithId, ResourceDiff } from '../diff/types';
5
+ export declare class PricingService implements IPricingService {
6
+ private calculators;
7
+ private pricingClient;
8
+ private excludedResourceTypes;
9
+ constructor(region?: string, usageAssumptions?: UsageAssumptionsConfig, excludedResourceTypes?: string[], cacheConfig?: CacheConfig, pricingClient?: PricingClient);
10
+ getResourceCost(resource: ResourceWithId, region: string): Promise<MonthlyCost>;
11
+ getCostDelta(diff: ResourceDiff, region: string): Promise<CostDelta>;
12
+ /**
13
+ * Clean up resources and connections
14
+ */
15
+ destroy(): void;
16
+ }
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.PricingService = void 0;
4
+ const CacheManager_1 = require("./CacheManager");
5
+ const ALBCalculator_1 = require("./calculators/ALBCalculator");
6
+ const APIGatewayCalculator_1 = require("./calculators/APIGatewayCalculator");
7
+ const CloudFrontCalculator_1 = require("./calculators/CloudFrontCalculator");
8
+ const DynamoDBCalculator_1 = require("./calculators/DynamoDBCalculator");
9
+ const EC2Calculator_1 = require("./calculators/EC2Calculator");
10
+ const ECSCalculator_1 = require("./calculators/ECSCalculator");
11
+ const ElastiCacheCalculator_1 = require("./calculators/ElastiCacheCalculator");
12
+ const LambdaCalculator_1 = require("./calculators/LambdaCalculator");
13
+ const NatGatewayCalculator_1 = require("./calculators/NatGatewayCalculator");
14
+ const NLBCalculator_1 = require("./calculators/NLBCalculator");
15
+ const RDSCalculator_1 = require("./calculators/RDSCalculator");
16
+ const S3Calculator_1 = require("./calculators/S3Calculator");
17
+ const VPCEndpointCalculator_1 = require("./calculators/VPCEndpointCalculator");
18
+ const PricingClient_1 = require("./PricingClient");
19
+ class PricingService {
20
+ calculators;
21
+ pricingClient;
22
+ excludedResourceTypes;
23
+ constructor(region = 'us-east-1', usageAssumptions, excludedResourceTypes, cacheConfig, pricingClient) {
24
+ // Use provided pricing client or create a new one
25
+ if (pricingClient) {
26
+ this.pricingClient = pricingClient;
27
+ }
28
+ else {
29
+ // Initialize cache manager if caching is enabled
30
+ let cacheManager;
31
+ if (cacheConfig?.enabled !== false) {
32
+ const cacheDuration = cacheConfig?.durationHours ?? 24;
33
+ cacheManager = new CacheManager_1.CacheManager('.cdk-cost-analyzer-cache', cacheDuration);
34
+ }
35
+ this.pricingClient = new PricingClient_1.PricingClient(region, cacheManager);
36
+ }
37
+ this.excludedResourceTypes = new Set(excludedResourceTypes || []);
38
+ this.calculators = [
39
+ new EC2Calculator_1.EC2Calculator(),
40
+ new S3Calculator_1.S3Calculator(),
41
+ new LambdaCalculator_1.LambdaCalculator(usageAssumptions?.lambda?.invocationsPerMonth, usageAssumptions?.lambda?.averageDurationMs),
42
+ new RDSCalculator_1.RDSCalculator(),
43
+ new DynamoDBCalculator_1.DynamoDBCalculator(),
44
+ new ECSCalculator_1.ECSCalculator(),
45
+ new APIGatewayCalculator_1.APIGatewayCalculator(),
46
+ new NatGatewayCalculator_1.NatGatewayCalculator(usageAssumptions?.natGateway?.dataProcessedGB),
47
+ new ALBCalculator_1.ALBCalculator(usageAssumptions?.alb?.newConnectionsPerSecond, usageAssumptions?.alb?.activeConnectionsPerMinute, usageAssumptions?.alb?.processedBytesGB),
48
+ new NLBCalculator_1.NLBCalculator(usageAssumptions?.nlb?.newConnectionsPerSecond, usageAssumptions?.nlb?.activeConnectionsPerMinute, usageAssumptions?.nlb?.processedBytesGB),
49
+ new VPCEndpointCalculator_1.VPCEndpointCalculator(usageAssumptions?.vpcEndpoint?.dataProcessedGB),
50
+ new CloudFrontCalculator_1.CloudFrontCalculator(usageAssumptions?.cloudfront?.dataTransferGB, usageAssumptions?.cloudfront?.requests),
51
+ new ElastiCacheCalculator_1.ElastiCacheCalculator(),
52
+ ];
53
+ }
54
+ async getResourceCost(resource, region) {
55
+ // Check if resource type is excluded
56
+ if (this.excludedResourceTypes.has(resource.type)) {
57
+ return {
58
+ amount: 0,
59
+ currency: 'USD',
60
+ confidence: 'high',
61
+ assumptions: [`Resource type ${resource.type} is excluded from cost analysis`],
62
+ };
63
+ }
64
+ const calculator = this.calculators.find(calc => calc.supports(resource.type));
65
+ if (!calculator) {
66
+ return {
67
+ amount: 0,
68
+ currency: 'USD',
69
+ confidence: 'unknown',
70
+ assumptions: [`Resource type ${resource.type} is not supported`],
71
+ };
72
+ }
73
+ try {
74
+ return await calculator.calculateCost(resource, region, this.pricingClient);
75
+ }
76
+ catch (error) {
77
+ return {
78
+ amount: 0,
79
+ currency: 'USD',
80
+ confidence: 'unknown',
81
+ assumptions: [`Failed to calculate cost: ${error instanceof Error ? error.message : String(error)}`],
82
+ };
83
+ }
84
+ }
85
+ async getCostDelta(diff, region) {
86
+ // Filter out excluded resources before processing
87
+ const filteredAdded = diff.added.filter(r => !this.excludedResourceTypes.has(r.type));
88
+ const filteredRemoved = diff.removed.filter(r => !this.excludedResourceTypes.has(r.type));
89
+ const filteredModified = diff.modified.filter(r => !this.excludedResourceTypes.has(r.type));
90
+ const addedCosts = await Promise.all(filteredAdded.map(async (resource) => {
91
+ const monthlyCost = await this.getResourceCost(resource, region);
92
+ return {
93
+ logicalId: resource.logicalId,
94
+ type: resource.type,
95
+ monthlyCost,
96
+ };
97
+ }));
98
+ const removedCosts = await Promise.all(filteredRemoved.map(async (resource) => {
99
+ const monthlyCost = await this.getResourceCost(resource, region);
100
+ return {
101
+ logicalId: resource.logicalId,
102
+ type: resource.type,
103
+ monthlyCost,
104
+ };
105
+ }));
106
+ const modifiedCosts = await Promise.all(filteredModified.map(async (resource) => {
107
+ const oldResource = {
108
+ logicalId: resource.logicalId,
109
+ type: resource.type,
110
+ properties: resource.oldProperties,
111
+ };
112
+ const newResource = {
113
+ logicalId: resource.logicalId,
114
+ type: resource.type,
115
+ properties: resource.newProperties,
116
+ };
117
+ const oldMonthlyCost = await this.getResourceCost(oldResource, region);
118
+ const newMonthlyCost = await this.getResourceCost(newResource, region);
119
+ const costDelta = newMonthlyCost.amount - oldMonthlyCost.amount;
120
+ return {
121
+ logicalId: resource.logicalId,
122
+ type: resource.type,
123
+ monthlyCost: newMonthlyCost,
124
+ oldMonthlyCost,
125
+ newMonthlyCost,
126
+ costDelta,
127
+ };
128
+ }));
129
+ const totalAddedCost = addedCosts.reduce((sum, r) => sum + r.monthlyCost.amount, 0);
130
+ const totalRemovedCost = removedCosts.reduce((sum, r) => sum + r.monthlyCost.amount, 0);
131
+ const totalModifiedDelta = modifiedCosts.reduce((sum, r) => sum + r.costDelta, 0);
132
+ const totalDelta = totalAddedCost - totalRemovedCost + totalModifiedDelta;
133
+ return {
134
+ totalDelta,
135
+ currency: 'USD',
136
+ addedCosts,
137
+ removedCosts,
138
+ modifiedCosts,
139
+ };
140
+ }
141
+ /**
142
+ * Clean up resources and connections
143
+ */
144
+ destroy() {
145
+ this.pricingClient.destroy();
146
+ }
147
+ }
148
+ exports.PricingService = PricingService;
149
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiUHJpY2luZ1NlcnZpY2UuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi9zcmMvcHJpY2luZy9QcmljaW5nU2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiOzs7QUFBQSxpREFBOEM7QUFDOUMsK0RBQTREO0FBQzVELDZFQUEwRTtBQUMxRSw2RUFBMEU7QUFDMUUseUVBQXNFO0FBQ3RFLCtEQUE0RDtBQUM1RCwrREFBNEQ7QUFDNUQsK0VBQTRFO0FBQzVFLHFFQUFrRTtBQUNsRSw2RUFBMEU7QUFDMUUsK0RBQTREO0FBQzVELCtEQUE0RDtBQUM1RCw2REFBMEQ7QUFDMUQsK0VBQTRFO0FBQzVFLG1EQUFnRDtBQVVoRCxNQUFhLGNBQWM7SUFDakIsV0FBVyxDQUEyQjtJQUN0QyxhQUFhLENBQWdCO0lBQzdCLHFCQUFxQixDQUFjO0lBRTNDLFlBQ0UsU0FBaUIsV0FBVyxFQUM1QixnQkFBeUMsRUFDekMscUJBQWdDLEVBQ2hDLFdBQXlCLEVBQ3pCLGFBQTZCO1FBRTdCLGtEQUFrRDtRQUNsRCxJQUFJLGFBQWEsRUFBRSxDQUFDO1lBQ2xCLElBQUksQ0FBQyxhQUFhLEdBQUcsYUFBYSxDQUFDO1FBQ3JDLENBQUM7YUFBTSxDQUFDO1lBQ04saURBQWlEO1lBQ2pELElBQUksWUFBc0MsQ0FBQztZQUMzQyxJQUFJLFdBQVcsRUFBRSxPQUFPLEtBQUssS0FBSyxFQUFFLENBQUM7Z0JBQ25DLE1BQU0sYUFBYSxHQUFHLFdBQVcsRUFBRSxhQUFhLElBQUksRUFBRSxDQUFDO2dCQUN2RCxZQUFZLEdBQUcsSUFBSSwyQkFBWSxDQUFDLDBCQUEwQixFQUFFLGFBQWEsQ0FBQyxDQUFDO1lBQzdFLENBQUM7WUFFRCxJQUFJLENBQUMsYUFBYSxHQUFHLElBQUksNkJBQWEsQ0FBQyxNQUFNLEVBQUUsWUFBWSxDQUFDLENBQUM7UUFDL0QsQ0FBQztRQUNELElBQUksQ0FBQyxxQkFBcUIsR0FBRyxJQUFJLEdBQUcsQ0FBQyxxQkFBcUIsSUFBSSxFQUFF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WUFBWSxDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxDQUFDLEVBQUUsRUFBRSxDQUFDLEdBQUcsR0FBRyxDQUFDLENBQUMsV0FBVyxDQUFDLE1BQU0sRUFBRSxDQUFDLENBQUMsQ0FBQztRQUN4RixNQUFNLGtCQUFrQixHQUFHLGFBQWEsQ0FBQyxNQUFNLENBQUMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxHQUFHLEdBQUcsQ0FBQyxDQUFDLFNBQVMsRUFBRSxDQUFDLENBQUMsQ0FBQztRQUVsRixNQUFNLFVBQVUsR0FBRyxjQUFjLEdBQUcsZ0JBQWdCLEdBQUcsa0JBQWtCLENBQUM7UUFFMUUsT0FBTztZQUNMLFVBQVU7WUFDVixRQUFRLEVBQUUsS0FBSztZQUNmLFVBQVU7WUFDVixZQUFZO1lBQ1osYUFBYTtTQUNkLENBQUM7SUFDSixDQUFDO0lBRUQ7O09BRUc7SUFDSCxPQUFPO1FBQ0wsSUFBSSxDQUFDLGFBQWEsQ0FBQyxPQUFPLEVBQUUsQ0FBQztJQUMvQixDQUFDO0NBQ0Y7QUF4S0Qsd0NBd0tDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ2FjaGVNYW5hZ2VyIH0gZnJvbSAnLi9DYWNoZU1hbmFnZXInO1xuaW1wb3J0IHsgQUxCQ2FsY3VsYXRvciB9IGZyb20gJy4vY2FsY3VsYXRvcnMvQUxCQ2FsY3VsYXRvcic7XG5pbXBvcnQgeyBBUElHYXRld2F5Q2FsY3VsYXRvciB9IGZyb20gJy4vY2FsY3VsYXRvcnMvQVBJR2F0ZXdheUNhbGN1bGF0b3InO1xuaW1wb3J0IHsgQ2xvdWRGcm9udENhbGN1bGF0b3IgfSBmcm9tICcuL2NhbGN1bGF0b3JzL0Nsb3VkRnJvbnRDYWxjdWxhdG9yJztcbmltcG9ydCB7IER5bmFtb0RCQ2FsY3VsYXRvciB9IGZyb20gJy4vY2FsY3VsYXRvcnMvRHluYW1vREJDYWxjdWxhdG9yJztcbmltcG9ydCB7IEVDMkNhbGN1bGF0b3IgfSBmcm9tICcuL2NhbGN1bGF0b3JzL0VDMkNhbGN1bGF0b3InO1xuaW1wb3J0IHsgRUNTQ2FsY3VsYXRvciB9IGZyb20gJy4vY2FsY3VsYXRvcnMvRUNTQ2FsY3VsYXRvcic7XG5pbXBvcnQgeyBFbGFzdGlDYWNoZUNhbGN1bGF0b3IgfSBmcm9tICcuL2NhbGN1bGF0b3JzL0VsYXN0aUNhY2hlQ2FsY3VsYXRvcic7XG5pbXBvcnQgeyBMYW1iZGFDYWxjdWxhdG9yIH0gZnJvbSAnLi9jYWxjdWxhdG9ycy9MYW1iZGFDYWxjdWxhdG9yJztcbmltcG9ydCB7IE5hdEdhdGV3YXlDYWxjdWxhdG9yIH0gZnJvbSAnLi9jYWxjdWxhdG9ycy9OYXRHYXRld2F5Q2FsY3VsYXRvcic7XG5pbXBvcnQgeyBOTEJDYWxjdWxhdG9yIH0gZnJvbSAnLi9jYWxjdWxhdG9ycy9OTEJDYWxjdWxhdG9yJztcbmltcG9ydCB7IFJEU0NhbGN1bGF0b3IgfSBmcm9tICcuL2NhbGN1bGF0b3JzL1JEU0NhbGN1bGF0b3InO1xuaW1wb3J0IHsgUzNDYWxjdWxhdG9yIH0gZnJvbSAnLi9jYWxjdWxhdG9ycy9TM0NhbGN1bGF0b3InO1xuaW1wb3J0IHsgVlBDRW5kcG9pbnRDYWxjdWxhdG9yIH0gZnJvbSAnLi9jYWxjdWxhdG9ycy9WUENFbmRwb2ludENhbGN1bGF0b3InO1xuaW1wb3J0IHsgUHJpY2luZ0NsaWVudCB9IGZyb20gJy4vUHJpY2luZ0NsaWVudCc7XG5pbXBvcnQge1xuICBQcmljaW5nU2VydmljZSBhcyBJUHJpY2luZ1NlcnZpY2UsXG4gIE1vbnRobHlDb3N0LFxuICBDb3N0RGVsdGEsXG4gIFJlc291cmNlQ29zdENhbGN1bGF0b3IsXG59IGZyb20gJy4vdHlwZXMnO1xuaW1wb3J0IHsgVXNhZ2VBc3N1bXB0aW9uc0NvbmZpZywgQ2FjaGVDb25maWcgfSBmcm9tICcuLi9jb25maWcvdHlwZXMnO1xuaW1wb3J0IHsgUmVzb3VyY2VXaXRoSWQsIFJlc291cmNlRGlmZiB9IGZyb20gJy4uL2RpZmYvdHlwZXMnO1xuXG5leHBvcnQgY2xhc3MgUHJpY2luZ1NlcnZpY2UgaW1wbGVtZW50cyBJUHJpY2luZ1NlcnZpY2Uge1xuICBwcml2YXRlIGNhbGN1bGF0b3JzOiBSZXNvdXJjZUNvc3RDYWxjdWxhdG9yW107XG4gIHByaXZhdGUgcHJpY2luZ0NsaWVudDogUHJpY2luZ0NsaWVudDtcbiAgcHJpdmF0ZSBleGNsdWRlZFJlc291cmNlVHlwZXM6IFNldDxzdHJpbmc+O1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHJlZ2lvbjogc3RyaW5nID0gJ3VzLWVhc3QtMScsXG4gICAgdXNhZ2VBc3N1bXB0aW9ucz86IFVzYWdlQXNzdW1wdGlvbnNDb25maWcsXG4gICAgZXhjbHVkZWRSZXNvdXJjZVR5cGVzPzogc3RyaW5nW10sXG4gICAgY2FjaGVDb25maWc/OiBDYWNoZUNvbmZpZyxcbiAgICBwcmljaW5nQ2xpZW50PzogUHJpY2luZ0NsaWVudCxcbiAgKSB7XG4gICAgLy8gVXNlIHByb3ZpZGVkIHByaWNpbmcgY2xpZW50IG9yIGNyZWF0ZSBhIG5ldyBvbmVcbiAgICBpZiAocHJpY2luZ0NsaWVudCkge1xuICAgICAgdGhpcy5wcmljaW5nQ2xpZW50ID0gcHJpY2luZ0NsaWVudDtcbiAgICB9IGVsc2Uge1xuICAgICAgLy8gSW5pdGlhbGl6ZSBjYWNoZSBtYW5hZ2VyIGlmIGNhY2hpbmcgaXMgZW5hYmxlZFxuICAgICAgbGV0IGNhY2hlTWFuYWdlcjogQ2FjaGVNYW5hZ2VyIHwgdW5kZWZpbmVkO1xuICAgICAgaWYgKGNhY2hlQ29uZmlnPy5lbmFibGVkICE9PSBmYWxzZSkge1xuICAgICAgICBjb25zdCBjYWNoZUR1cmF0aW9uID0gY2FjaGVDb25maWc/LmR1cmF0aW9uSG91cnMgPz8gMjQ7XG4gICAgICAgIGNhY2hlTWFuYWdlciA9IG5ldyBDYWNoZU1hbmFnZXIoJy5jZGstY29zdC1hbmFseXplci1jYWNoZScsIGNhY2hlRHVyYXRpb24pO1xuICAgICAgfVxuXG4gICAgICB0aGlzLnByaWNpbmdDbGllbnQgPSBuZXcgUHJpY2luZ0NsaWVudChyZWdpb24sIGNhY2hlTWFuYWdlcik7XG4gICAgfVxuICAgIHRoaXMuZXhjbHVkZWRSZXNvdXJjZVR5cGVzID0gbmV3IFNldChleGNsdWRlZFJlc291cmNlVHlwZXMgfHwgW10pO1xuICAgIHRoaXMuY2FsY3VsYXRvcnMgPSBbXG4gICAgICBuZXcgRUMyQ2FsY3VsYXRvcigpLFxuICAgICAgbmV3IFMzQ2FsY3VsYXRvcigpLFxuICAgICAgbmV3IExhbWJkYUNhbGN1bGF0b3IoXG4gICAgICAgIHVzYWdlQXNzdW1wdGlvbnM/LmxhbWJkYT8uaW52b2NhdGlvbnNQZXJNb250aCxcbiAgICAgICAgdXNhZ2VBc3N1bXB0aW9ucz8ubGFtYmRhPy5hdmVyYWdlRHVyYXRpb25NcyxcbiAgICAgICksXG4gICAgICBuZXcgUkRTQ2FsY3VsYXRvcigpLFxuICAgICAgbmV3IER5bmFtb0RCQ2FsY3VsYXRvcigpLFxuICAgICAgbmV3IEVDU0NhbGN1bGF0b3IoKSxcbiAgICAgIG5ldyBBUElHYXRld2F5Q2FsY3VsYXRvcigpLFxuICAgICAgbmV3IE5hdEdhdGV3YXlDYWxjdWxhdG9yKHVzYWdlQXNzdW1wdGlvbnM/Lm5hdEdhdGV3YXk/LmRhdGFQcm9jZXNzZWRHQiksXG4gICAgICBuZXcgQUxCQ2FsY3VsYXRvcihcbiAgICAgICAgdXNhZ2VBc3N1bXB0aW9ucz8uYWxiPy5uZXdDb25uZWN0aW9uc1BlclNlY29uZCxcbiAgICAgICAgdXNhZ2VBc3N1bXB0aW9ucz8uYWxiPy5hY3RpdmVDb25uZWN0aW9uc1Blck1pbnV0ZSxcbiAgICAgICAgdXNhZ2VBc3N1bXB0aW9ucz8uYWxiPy5wcm9jZXNzZWRCeXRlc0dCLFxuICAgICAgKSxcbiAgICAgIG5ldyBOTEJDYWxjdWxhdG9yKFxuICAgICAgICB1c2FnZUFzc3VtcHRpb25zPy5ubGI/Lm5ld0Nvbm5lY3Rpb25zUGVyU2Vjb25kLFxuICAgICAgICB1c2FnZUFzc3VtcHRpb25zPy5ubGI/LmFjdGl2ZUNvbm5lY3Rpb25zUGVyTWludXRlLFxuICAgICAgICB1c2FnZUFzc3VtcHRpb25zPy5ubGI/LnByb2Nlc3NlZEJ5dGVzR0IsXG4gICAgICApLFxuICAgICAgbmV3IFZQQ0VuZHBvaW50Q2FsY3VsYXRvcih1c2FnZUFzc3VtcHRpb25zPy52cGNFbmRwb2ludD8uZGF0YVByb2Nlc3NlZEdCKSxcbiAgICAgIG5ldyBDbG91ZEZyb250Q2FsY3VsYXRvcihcbiAgICAgICAgdXNhZ2VBc3N1bXB0aW9ucz8uY2xvdWRmcm9udD8uZGF0YVRyYW5zZmVyR0IsXG4gICAgICAgIHVzYWdlQXNzdW1wdGlvbnM/LmNsb3VkZnJvbnQ/LnJlcXVlc3RzLFxuICAgICAgKSxcbiAgICAgIG5ldyBFbGFzdGlDYWNoZUNhbGN1bGF0b3IoKSxcbiAgICBdO1xuICB9XG5cbiAgYXN5bmMgZ2V0UmVzb3VyY2VDb3N0KHJlc291cmNlOiBSZXNvdXJjZVdpdGhJZCwgcmVnaW9uOiBzdHJpbmcpOiBQcm9taXNlPE1vbnRobHlDb3N0PiB7XG4gICAgLy8gQ2hlY2sgaWYgcmVzb3VyY2UgdHlwZSBpcyBleGNsdWRlZFxuICAgIGlmICh0aGlzLmV4Y2x1ZGVkUmVzb3VyY2VUeXBlcy5oYXMocmVzb3VyY2UudHlwZSkpIHtcbiAgICAgIHJldHVybiB7XG4gICAgICAgIGFtb3VudDogMCxcbiAgICAgICAgY3VycmVuY3k6ICdVU0QnLFxuICAgICAgICBjb25maWRlbmNlOiAnaGlnaCcsXG4gICAgICAgIGFzc3VtcHRpb25zOiBbYFJlc291cmNlIHR5cGUgJHtyZXNvdXJjZS50eXBlfSBpcyBleGNsdWRlZCBmcm9tIGNvc3QgYW5hbHlzaXNgXSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgY29uc3QgY2FsY3VsYXRvciA9IHRoaXMuY2FsY3VsYXRvcnMuZmluZChjYWxjID0+IGNhbGMuc3VwcG9ydHMocmVzb3VyY2UudHlwZSkpO1xuXG4gICAgaWYgKCFjYWxjdWxhdG9yKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBhbW91bnQ6IDAsXG4gICAgICAgIGN1cnJlbmN5OiAnVVNEJyxcbiAgICAgICAgY29uZmlkZW5jZTogJ3Vua25vd24nLFxuICAgICAgICBhc3N1bXB0aW9uczogW2BSZXNvdXJjZSB0eXBlICR7cmVzb3VyY2UudHlwZX0gaXMgbm90IHN1cHBvcnRlZGBdLFxuICAgICAgfTtcbiAgICB9XG5cbiAgICB0cnkge1xuICAgICAgcmV0dXJuIGF3YWl0IGNhbGN1bGF0b3IuY2FsY3VsYXRlQ29zdChyZXNvdXJjZSwgcmVnaW9uLCB0aGlzLnByaWNpbmdDbGllbnQpO1xuICAgIH0gY2F0Y2ggKGVycm9yKSB7XG4gICAgICByZXR1cm4ge1xuICAgICAgICBhbW91bnQ6IDAsXG4gICAgICAgIGN1cnJlbmN5OiAnVVNEJyxcbiAgICAgICAgY29uZmlkZW5jZTogJ3Vua25vd24nLFxuICAgICAgICBhc3N1bXB0aW9uczogW2BGYWlsZWQgdG8gY2FsY3VsYXRlIGNvc3Q6ICR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpfWBdLFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBhc3luYyBnZXRDb3N0RGVsdGEoZGlmZjogUmVzb3VyY2VEaWZmLCByZWdpb246IHN0cmluZyk6IFByb21pc2U8Q29zdERlbHRhPiB7XG4gICAgLy8gRmlsdGVyIG91dCBleGNsdWRlZCByZXNvdXJjZXMgYmVmb3JlIHByb2Nlc3NpbmdcbiAgICBjb25zdCBmaWx0ZXJlZEFkZGVkID0gZGlmZi5hZGRlZC5maWx0ZXIociA9PiAhdGhpcy5leGNsdWRlZFJlc291cmNlVHlwZXMuaGFzKHIudHlwZSkpO1xuICAgIGNvbnN0IGZpbHRlcmVkUmVtb3ZlZCA9IGRpZmYucmVtb3ZlZC5maWx0ZXIociA9PiAhdGhpcy5leGNsdWRlZFJlc291cmNlVHlwZXMuaGFzKHIudHlwZSkpO1xuICAgIGNvbnN0IGZpbHRlcmVkTW9kaWZpZWQgPSBkaWZmLm1vZGlmaWVkLmZpbHRlcihyID0+ICF0aGlzLmV4Y2x1ZGVkUmVzb3VyY2VUeXBlcy5oYXMoci50eXBlKSk7XG5cbiAgICBjb25zdCBhZGRlZENvc3RzID0gYXdhaXQgUHJvbWlzZS5hbGwoXG4gICAgICBmaWx0ZXJlZEFkZGVkLm1hcChhc3luYyAocmVzb3VyY2UpID0+IHtcbiAgICAgICAgY29uc3QgbW9udGhseUNvc3QgPSBhd2FpdCB0aGlzLmdldFJlc291cmNlQ29zdChyZXNvdXJjZSwgcmVnaW9uKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBsb2dpY2FsSWQ6IHJlc291cmNlLmxvZ2ljYWxJZCxcbiAgICAgICAgICB0eXBlOiByZXNvdXJjZS50eXBlLFxuICAgICAgICAgIG1vbnRobHlDb3N0LFxuICAgICAgICB9O1xuICAgICAgfSksXG4gICAgKTtcblxuICAgIGNvbnN0IHJlbW92ZWRDb3N0cyA9IGF3YWl0IFByb21pc2UuYWxsKFxuICAgICAgZmlsdGVyZWRSZW1vdmVkLm1hcChhc3luYyAocmVzb3VyY2UpID0+IHtcbiAgICAgICAgY29uc3QgbW9udGhseUNvc3QgPSBhd2FpdCB0aGlzLmdldFJlc291cmNlQ29zdChyZXNvdXJjZSwgcmVnaW9uKTtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBsb2dpY2FsSWQ6IHJlc291cmNlLmxvZ2ljYWxJZCxcbiAgICAgICAgICB0eXBlOiByZXNvdXJjZS50eXBlLFxuICAgICAgICAgIG1vbnRobHlDb3N0LFxuICAgICAgICB9O1xuICAgICAgfSksXG4gICAgKTtcblxuICAgIGNvbnN0IG1vZGlmaWVkQ29zdHMgPSBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgIGZpbHRlcmVkTW9kaWZpZWQubWFwKGFzeW5jIChyZXNvdXJjZSkgPT4ge1xuICAgICAgICBjb25zdCBvbGRSZXNvdXJjZTogUmVzb3VyY2VXaXRoSWQgPSB7XG4gICAgICAgICAgbG9naWNhbElkOiByZXNvdXJjZS5sb2dpY2FsSWQsXG4gICAgICAgICAgdHlwZTogcmVzb3VyY2UudHlwZSxcbiAgICAgICAgICBwcm9wZXJ0aWVzOiByZXNvdXJjZS5vbGRQcm9wZXJ0aWVzLFxuICAgICAgICB9O1xuICAgICAgICBjb25zdCBuZXdSZXNvdXJjZTogUmVzb3VyY2VXaXRoSWQgPSB7XG4gICAgICAgICAgbG9naWNhbElkOiByZXNvdXJjZS5sb2dpY2FsSWQsXG4gICAgICAgICAgdHlwZTogcmVzb3VyY2UudHlwZSxcbiAgICAgICAgICBwcm9wZXJ0aWVzOiByZXNvdXJjZS5uZXdQcm9wZXJ0aWVzLFxuICAgICAgICB9O1xuXG4gICAgICAgIGNvbnN0IG9sZE1vbnRobHlDb3N0ID0gYXdhaXQgdGhpcy5nZXRSZXNvdXJjZUNvc3Qob2xkUmVzb3VyY2UsIHJlZ2lvbik7XG4gICAgICAgIGNvbnN0IG5ld01vbnRobHlDb3N0ID0gYXdhaXQgdGhpcy5nZXRSZXNvdXJjZUNvc3QobmV3UmVzb3VyY2UsIHJlZ2lvbik7XG4gICAgICAgIGNvbnN0IGNvc3REZWx0YSA9IG5ld01vbnRobHlDb3N0LmFtb3VudCAtIG9sZE1vbnRobHlDb3N0LmFtb3VudDtcblxuICAgICAgICByZXR1cm4ge1xuICAgICAgICAgIGxvZ2ljYWxJZDogcmVzb3VyY2UubG9naWNhbElkLFxuICAgICAgICAgIHR5cGU6IHJlc291cmNlLnR5cGUsXG4gICAgICAgICAgbW9udGhseUNvc3Q6IG5ld01vbnRobHlDb3N0LFxuICAgICAgICAgIG9sZE1vbnRobHlDb3N0LFxuICAgICAgICAgIG5ld01vbnRobHlDb3N0LFxuICAgICAgICAgIGNvc3REZWx0YSxcbiAgICAgICAgfTtcbiAgICAgIH0pLFxuICAgICk7XG5cbiAgICBjb25zdCB0b3RhbEFkZGVkQ29zdCA9IGFkZGVkQ29zdHMucmVkdWNlKChzdW0sIHIpID0+IHN1bSArIHIubW9udGhseUNvc3QuYW1vdW50LCAwKTtcbiAgICBjb25zdCB0b3RhbFJlbW92ZWRDb3N0ID0gcmVtb3ZlZENvc3RzLnJlZHVjZSgoc3VtLCByKSA9PiBzdW0gKyByLm1vbnRobHlDb3N0LmFtb3VudCwgMCk7XG4gICAgY29uc3QgdG90YWxNb2RpZmllZERlbHRhID0gbW9kaWZpZWRDb3N0cy5yZWR1Y2UoKHN1bSwgcikgPT4gc3VtICsgci5jb3N0RGVsdGEsIDApO1xuXG4gICAgY29uc3QgdG90YWxEZWx0YSA9IHRvdGFsQWRkZWRDb3N0IC0gdG90YWxSZW1vdmVkQ29zdCArIHRvdGFsTW9kaWZpZWREZWx0YTtcblxuICAgIHJldHVybiB7XG4gICAgICB0b3RhbERlbHRhLFxuICAgICAgY3VycmVuY3k6ICdVU0QnLFxuICAgICAgYWRkZWRDb3N0cyxcbiAgICAgIHJlbW92ZWRDb3N0cyxcbiAgICAgIG1vZGlmaWVkQ29zdHMsXG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhbiB1cCByZXNvdXJjZXMgYW5kIGNvbm5lY3Rpb25zXG4gICAqL1xuICBkZXN0cm95KCk6IHZvaWQge1xuICAgIHRoaXMucHJpY2luZ0NsaWVudC5kZXN0cm95KCk7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,16 @@
1
+ import { ResourceWithId } from '../../diff/types';
2
+ import { ResourceCostCalculator, MonthlyCost, PricingClient } from '../types';
3
+ export declare class ALBCalculator implements ResourceCostCalculator {
4
+ private customNewConnectionsPerSecond?;
5
+ private customActiveConnectionsPerMinute?;
6
+ private customProcessedBytesGB?;
7
+ private readonly DEFAULT_NEW_CONNECTIONS_PER_SECOND;
8
+ private readonly DEFAULT_ACTIVE_CONNECTIONS_PER_MINUTE;
9
+ private readonly DEFAULT_PROCESSED_BYTES_GB;
10
+ private readonly HOURS_PER_MONTH;
11
+ constructor(customNewConnectionsPerSecond?: number | undefined, customActiveConnectionsPerMinute?: number | undefined, customProcessedBytesGB?: number | undefined);
12
+ supports(resourceType: string): boolean;
13
+ calculateCost(resource: ResourceWithId, region: string, pricingClient: PricingClient): Promise<MonthlyCost>;
14
+ private normalizeRegion;
15
+ private getRegionPrefix;
16
+ }
@@ -0,0 +1,163 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ALBCalculator = void 0;
4
+ class ALBCalculator {
5
+ customNewConnectionsPerSecond;
6
+ customActiveConnectionsPerMinute;
7
+ customProcessedBytesGB;
8
+ DEFAULT_NEW_CONNECTIONS_PER_SECOND = 25;
9
+ DEFAULT_ACTIVE_CONNECTIONS_PER_MINUTE = 3000;
10
+ DEFAULT_PROCESSED_BYTES_GB = 100;
11
+ HOURS_PER_MONTH = 730;
12
+ constructor(customNewConnectionsPerSecond, customActiveConnectionsPerMinute, customProcessedBytesGB) {
13
+ this.customNewConnectionsPerSecond = customNewConnectionsPerSecond;
14
+ this.customActiveConnectionsPerMinute = customActiveConnectionsPerMinute;
15
+ this.customProcessedBytesGB = customProcessedBytesGB;
16
+ }
17
+ supports(resourceType) {
18
+ return resourceType === 'AWS::ElasticLoadBalancingV2::LoadBalancer';
19
+ }
20
+ async calculateCost(resource, region, pricingClient) {
21
+ // Check if this is an Application Load Balancer (not Network Load Balancer)
22
+ const loadBalancerType = resource.properties?.Type;
23
+ if (loadBalancerType && loadBalancerType !== 'application') {
24
+ return {
25
+ amount: 0,
26
+ currency: 'USD',
27
+ confidence: 'unknown',
28
+ assumptions: ['This calculator only supports Application Load Balancers'],
29
+ };
30
+ }
31
+ try {
32
+ // Get hourly rate
33
+ const hourlyRate = await pricingClient.getPrice({
34
+ serviceCode: 'AWSELB',
35
+ region: this.normalizeRegion(region),
36
+ filters: [
37
+ { field: 'productFamily', value: 'Load Balancer-Application' },
38
+ { field: 'usagetype', value: `${this.getRegionPrefix(region)}LoadBalancerUsage` },
39
+ ],
40
+ });
41
+ // Get LCU rate
42
+ const lcuRate = await pricingClient.getPrice({
43
+ serviceCode: 'AWSELB',
44
+ region: this.normalizeRegion(region),
45
+ filters: [
46
+ { field: 'productFamily', value: 'Load Balancer-Application' },
47
+ { field: 'usagetype', value: `${this.getRegionPrefix(region)}LCUUsage` },
48
+ ],
49
+ });
50
+ const newConnectionsPerSecond = this.customNewConnectionsPerSecond || this.DEFAULT_NEW_CONNECTIONS_PER_SECOND;
51
+ const activeConnectionsPerMinute = this.customActiveConnectionsPerMinute || this.DEFAULT_ACTIVE_CONNECTIONS_PER_MINUTE;
52
+ const processedBytesGB = this.customProcessedBytesGB || this.DEFAULT_PROCESSED_BYTES_GB;
53
+ if (hourlyRate === null || lcuRate === null) {
54
+ // Calculate LCU consumption for assumptions even when pricing fails
55
+ const lcuFromNewConnections = newConnectionsPerSecond / 25;
56
+ const lcuFromActiveConnections = activeConnectionsPerMinute / 3000;
57
+ const gbPerHour = processedBytesGB / this.HOURS_PER_MONTH;
58
+ const lcuFromProcessedBytes = gbPerHour;
59
+ const lcuPerHour = Math.max(lcuFromNewConnections, lcuFromActiveConnections, lcuFromProcessedBytes);
60
+ return {
61
+ amount: 0,
62
+ currency: 'USD',
63
+ confidence: 'unknown',
64
+ assumptions: [
65
+ `Pricing data not available for Application Load Balancer in region ${region}`,
66
+ `Would use LCU consumption: ${lcuPerHour.toFixed(2)} LCU/hour based on:`,
67
+ ` - New connections: ${newConnectionsPerSecond}/sec → ${lcuFromNewConnections.toFixed(2)} LCU`,
68
+ ` - Active connections: ${activeConnectionsPerMinute}/min → ${lcuFromActiveConnections.toFixed(2)} LCU`,
69
+ ` - Processed data: ${processedBytesGB} GB/month → ${lcuFromProcessedBytes.toFixed(2)} LCU`,
70
+ ],
71
+ };
72
+ }
73
+ // Calculate LCU consumption
74
+ // 1 LCU provides: 25 new connections/sec, 3000 active connections/min, 1 GB processed/hour, 1000 rule evaluations/sec
75
+ const lcuFromNewConnections = newConnectionsPerSecond / 25;
76
+ const lcuFromActiveConnections = activeConnectionsPerMinute / 3000;
77
+ const gbPerHour = processedBytesGB / this.HOURS_PER_MONTH;
78
+ const lcuFromProcessedBytes = gbPerHour;
79
+ // Use the highest LCU consumption
80
+ const lcuPerHour = Math.max(lcuFromNewConnections, lcuFromActiveConnections, lcuFromProcessedBytes);
81
+ const hourlyCost = hourlyRate * this.HOURS_PER_MONTH;
82
+ const lcuCost = lcuRate * lcuPerHour * this.HOURS_PER_MONTH;
83
+ const totalCost = hourlyCost + lcuCost;
84
+ return {
85
+ amount: totalCost,
86
+ currency: 'USD',
87
+ confidence: 'medium',
88
+ assumptions: [
89
+ `Hourly rate: $${hourlyRate.toFixed(4)}/hour × ${this.HOURS_PER_MONTH} hours = $${hourlyCost.toFixed(2)}/month`,
90
+ `LCU consumption: ${lcuPerHour.toFixed(2)} LCU/hour based on:`,
91
+ ` - New connections: ${newConnectionsPerSecond}/sec → ${lcuFromNewConnections.toFixed(2)} LCU`,
92
+ ` - Active connections: ${activeConnectionsPerMinute}/min → ${lcuFromActiveConnections.toFixed(2)} LCU`,
93
+ ` - Processed data: ${processedBytesGB} GB/month → ${lcuFromProcessedBytes.toFixed(2)} LCU`,
94
+ `LCU cost: $${lcuRate.toFixed(4)}/LCU/hour × ${lcuPerHour.toFixed(2)} LCU × ${this.HOURS_PER_MONTH} hours = $${lcuCost.toFixed(2)}/month`,
95
+ `Total: $${totalCost.toFixed(2)}/month`,
96
+ ],
97
+ };
98
+ }
99
+ catch (error) {
100
+ const newConnectionsPerSecond = this.customNewConnectionsPerSecond || this.DEFAULT_NEW_CONNECTIONS_PER_SECOND;
101
+ const activeConnectionsPerMinute = this.customActiveConnectionsPerMinute || this.DEFAULT_ACTIVE_CONNECTIONS_PER_MINUTE;
102
+ const processedBytesGB = this.customProcessedBytesGB || this.DEFAULT_PROCESSED_BYTES_GB;
103
+ // Calculate LCU consumption for assumptions even when error occurs
104
+ const lcuFromNewConnections = newConnectionsPerSecond / 25;
105
+ const lcuFromActiveConnections = activeConnectionsPerMinute / 3000;
106
+ const gbPerHour = processedBytesGB / this.HOURS_PER_MONTH;
107
+ const lcuFromProcessedBytes = gbPerHour;
108
+ const lcuPerHour = Math.max(lcuFromNewConnections, lcuFromActiveConnections, lcuFromProcessedBytes);
109
+ return {
110
+ amount: 0,
111
+ currency: 'USD',
112
+ confidence: 'unknown',
113
+ assumptions: [
114
+ `Failed to fetch pricing: ${error instanceof Error ? error.message : String(error)}`,
115
+ `Would use LCU consumption: ${lcuPerHour.toFixed(2)} LCU/hour based on:`,
116
+ ` - New connections: ${newConnectionsPerSecond}/sec → ${lcuFromNewConnections.toFixed(2)} LCU`,
117
+ ` - Active connections: ${activeConnectionsPerMinute}/min → ${lcuFromActiveConnections.toFixed(2)} LCU`,
118
+ ` - Processed data: ${processedBytesGB} GB/month → ${lcuFromProcessedBytes.toFixed(2)} LCU`,
119
+ ],
120
+ };
121
+ }
122
+ }
123
+ normalizeRegion(region) {
124
+ const regionMap = {
125
+ 'us-east-1': 'US East (N. Virginia)',
126
+ 'us-east-2': 'US East (Ohio)',
127
+ 'us-west-1': 'US West (N. California)',
128
+ 'us-west-2': 'US West (Oregon)',
129
+ 'eu-west-1': 'EU (Ireland)',
130
+ 'eu-west-2': 'EU (London)',
131
+ 'eu-west-3': 'EU (Paris)',
132
+ 'eu-central-1': 'EU (Frankfurt)',
133
+ 'eu-north-1': 'EU (Stockholm)',
134
+ 'ap-south-1': 'Asia Pacific (Mumbai)',
135
+ 'ap-southeast-1': 'Asia Pacific (Singapore)',
136
+ 'ap-southeast-2': 'Asia Pacific (Sydney)',
137
+ 'ap-northeast-1': 'Asia Pacific (Tokyo)',
138
+ 'ap-northeast-2': 'Asia Pacific (Seoul)',
139
+ };
140
+ return regionMap[region] || region;
141
+ }
142
+ getRegionPrefix(region) {
143
+ const prefixMap = {
144
+ 'us-east-1': 'USE1',
145
+ 'us-east-2': 'USE2',
146
+ 'us-west-1': 'USW1',
147
+ 'us-west-2': 'USW2',
148
+ 'eu-west-1': 'EUW1',
149
+ 'eu-west-2': 'EUW2',
150
+ 'eu-west-3': 'EUW3',
151
+ 'eu-central-1': 'EUC1',
152
+ 'eu-north-1': 'EUN1',
153
+ 'ap-south-1': 'APS1',
154
+ 'ap-southeast-1': 'APS2',
155
+ 'ap-southeast-2': 'APS3',
156
+ 'ap-northeast-1': 'APN1',
157
+ 'ap-northeast-2': 'APN2',
158
+ };
159
+ return prefixMap[region] || '';
160
+ }
161
+ }
162
+ exports.ALBCalculator = ALBCalculator;
163
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiQUxCQ2FsY3VsYXRvci5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uL3NyYy9wcmljaW5nL2NhbGN1bGF0b3JzL0FMQkNhbGN1bGF0b3IudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6Ijs7O0FBR0EsTUFBYSxhQUFhO0lBT2Q7SUFDQTtJQUNBO0lBUk8sa0NBQWtDLEdBQUcsRUFBRSxDQUFDO0lBQ3hDLHFDQUFxQyxHQUFHLElBQUksQ0FBQztJQUM3QywwQkFBMEIsR0FBRyxHQUFHLENBQUM7SUFDakMsZUFBZSxHQUFHLEdBQUcsQ0FBQztJQUV2QyxZQUNVLDZCQUFzQyxFQUN0QyxnQ0FBeUMsRUFDekMsc0JBQStCO1FBRi9CLGtDQUE2QixHQUE3Qiw2QkFBNkIsQ0FBUztRQUN0QyxxQ0FBZ0MsR0FBaEMsZ0NBQWdDLENBQVM7UUFDekMsMkJBQXNCLEdBQXRCLHNCQUFzQixDQUFTO0lBQ3RDLENBQUM7SUFFSixRQUFRLENBQUMsWUFBb0I7UUFDM0IsT0FBTyxZQUFZLEtBQUssMkNBQTJDLENBQUM7SUFDdEUsQ0FBQztJQUVELEtBQUssQ0FBQyxhQUFhLENBQ2pCLFFBQXdCLEVBQ3hCLE1BQWMsRUFDZCxhQUE0QjtRQUU1Qiw0RUFBNEU7UUFDNUUsTUFBTSxnQkFBZ0IsR0FBRyxRQUFRLENBQUMsVUFBVSxFQUFFLElBQUksQ0FBQztRQUNuRCxJQUFJLGdCQUFnQixJQUFJLGdCQUFnQixLQUFLLGFBQWEsRUFBRSxDQUFDO1lBQzNELE9BQU87Z0JBQ0wsTUFBTSxFQUFFLENBQUM7Z0JBQ1QsUUFBUSxFQUFFLEtBQUs7Z0JBQ2YsVUFBVSxFQUFFLFNBQVM7Z0JBQ3JCLFdBQVcsRUFBRSxDQUFDLDBEQUEwRCxDQUFDO2FBQzFFLENBQUM7UUFDSixDQUFDO1FBRUQsSUFBSSxDQUFDO1lBQ0gsa0JBQWtCO1lBQ2xCLE1BQU0sVUFBVSxHQUFHLE1BQU0sYUFBYSxDQUFDLFFBQVEsQ0FBQztnQkFDOUMsV0FBVyxFQUFFLFFBQVE7Z0JBQ3JCLE1B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QzdCLFdBQVcsRUFBRSx5QkFBeUI7WUFDdEMsV0FBVyxFQUFFLGtCQUFrQjtZQUMvQixXQUFXLEVBQUUsY0FBYztZQUMzQixXQUFXLEVBQUUsYUFBYTtZQUMxQixXQUFXLEVBQUUsWUFBWTtZQUN6QixjQUFjLEVBQUUsZ0JBQWdCO1lBQ2hDLFlBQVksRUFBRSxnQkFBZ0I7WUFDOUIsWUFBWSxFQUFFLHVCQUF1QjtZQUNyQyxnQkFBZ0IsRUFBRSwwQkFBMEI7WUFDNUMsZ0JBQWdCLEVBQUUsdUJBQXVCO1lBQ3pDLGdCQUFnQixFQUFFLHNCQUFzQjtZQUN4QyxnQkFBZ0IsRUFBRSxzQkFBc0I7U0FDekMsQ0FBQztRQUVGLE9BQU8sU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLE1BQU0sQ0FBQztJQUNyQyxDQUFDO0lBRU8sZUFBZSxDQUFDLE1BQWM7UUFDcEMsTUFBTSxTQUFTLEdBQTJCO1lBQ3hDLFdBQVcsRUFBRSxNQUFNO1lBQ25CLFdBQVcsRUFBRSxNQUFNO1lBQ25CLFdBQVcsRUFBRSxNQUFNO1lBQ25CLFdBQVcsRUFBRSxNQUFNO1lBQ25CLFdBQVcsRUFBRSxNQUFNO1lBQ25CLFdBQVcsRUFBRSxNQUFNO1lBQ25CLFdBQVcsRUFBRSxNQUFNO1lBQ25CLGNBQWMsRUFBRSxNQUFNO1lBQ3RCLFlBQVksRUFBRSxNQUFNO1lBQ3BCLFlBQVksRUFBRSxNQUFNO1lBQ3BCLGdCQUFnQixFQUFFLE1BQU07WUFDeEIsZ0JBQWdCLEVBQUUsTUFBTTtZQUN4QixnQkFBZ0IsRUFBRSxNQUFNO1lBQ3hCLGdCQUFnQixFQUFFLE1BQU07U0FDekIsQ0FBQztRQUVGLE9BQU8sU0FBUyxDQUFDLE1BQU0sQ0FBQyxJQUFJLEVBQUUsQ0FBQztJQUNqQyxDQUFDO0NBQ0Y7QUFqTUQsc0NBaU1DIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgUmVzb3VyY2VXaXRoSWQgfSBmcm9tICcuLi8uLi9kaWZmL3R5cGVzJztcbmltcG9ydCB7IFJlc291cmNlQ29zdENhbGN1bGF0b3IsIE1vbnRobHlDb3N0LCBQcmljaW5nQ2xpZW50IH0gZnJvbSAnLi4vdHlwZXMnO1xuXG5leHBvcnQgY2xhc3MgQUxCQ2FsY3VsYXRvciBpbXBsZW1lbnRzIFJlc291cmNlQ29zdENhbGN1bGF0b3Ige1xuICBwcml2YXRlIHJlYWRvbmx5IERFRkFVTFRfTkVXX0NPTk5FQ1RJT05TX1BFUl9TRUNPTkQgPSAyNTtcbiAgcHJpdmF0ZSByZWFkb25seSBERUZBVUxUX0FDVElWRV9DT05ORUNUSU9OU19QRVJfTUlOVVRFID0gMzAwMDtcbiAgcHJpdmF0ZSByZWFkb25seSBERUZBVUxUX1BST0NFU1NFRF9CWVRFU19HQiA9IDEwMDtcbiAgcHJpdmF0ZSByZWFkb25seSBIT1VSU19QRVJfTU9OVEggPSA3MzA7XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBjdXN0b21OZXdDb25uZWN0aW9uc1BlclNlY29uZD86IG51bWJlcixcbiAgICBwcml2YXRlIGN1c3RvbUFjdGl2ZUNvbm5lY3Rpb25zUGVyTWludXRlPzogbnVtYmVyLFxuICAgIHByaXZhdGUgY3VzdG9tUHJvY2Vzc2VkQnl0ZXNHQj86IG51bWJlcixcbiAgKSB7fVxuXG4gIHN1cHBvcnRzKHJlc291cmNlVHlwZTogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHJlc291cmNlVHlwZSA9PT0gJ0FXUzo6RWxhc3RpY0xvYWRCYWxhbmNpbmdWMjo6TG9hZEJhbGFuY2VyJztcbiAgfVxuXG4gIGFzeW5jIGNhbGN1bGF0ZUNvc3QoXG4gICAgcmVzb3VyY2U6IFJlc291cmNlV2l0aElkLFxuICAgIHJlZ2lvbjogc3RyaW5nLFxuICAgIHByaWNpbmdDbGllbnQ6IFByaWNpbmdDbGllbnQsXG4gICk6IFByb21pc2U8TW9udGhseUNvc3Q+IHtcbiAgICAvLyBDaGVjayBpZiB0aGlzIGlzIGFuIEFwcGxpY2F0aW9uIExvYWQgQmFsYW5jZXIgKG5vdCBOZXR3b3JrIExvYWQgQmFsYW5jZXIpXG4gICAgY29uc3QgbG9hZEJhbGFuY2VyVHlwZSA9IHJlc291cmNlLnByb3BlcnRpZXM/LlR5cGU7XG4gICAgaWYgKGxvYWRCYWxhbmNlclR5cGUgJiYgbG9hZEJhbGFuY2VyVHlwZSAhPT0gJ2FwcGxpY2F0aW9uJykge1xuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICBjdXJyZW5jeTogJ1VTRCcsXG4gICAgICAgIGNvbmZpZGVuY2U6ICd1bmtub3duJyxcbiAgICAgICAgYXNzdW1wdGlvbnM6IFsnVGhpcyBjYWxjdWxhdG9yIG9ubHkgc3VwcG9ydHMgQXBwbGljYXRpb24gTG9hZCBCYWxhbmNlcnMnXSxcbiAgICAgIH07XG4gICAgfVxuXG4gICAgdHJ5IHtcbiAgICAgIC8vIEdldCBob3VybHkgcmF0ZVxuICAgICAgY29uc3QgaG91cmx5UmF0ZSA9IGF3YWl0IHByaWNpbmdDbGllbnQuZ2V0UHJpY2Uoe1xuICAgICAgICBzZXJ2aWNlQ29kZTogJ0FXU0VMQicsXG4gICAgICAgIHJlZ2lvbjogdGhpcy5ub3JtYWxpemVSZWdpb24ocmVnaW9uKSxcbiAgICAgICAgZmlsdGVyczogW1xuICAgICAgICAgIHsgZmllbGQ6ICdwcm9kdWN0RmFtaWx5JywgdmFsdWU6ICdMb2FkIEJhbGFuY2VyLUFwcGxpY2F0aW9uJyB9LFxuICAgICAgICAgIHsgZmllbGQ6ICd1c2FnZXR5cGUnLCB2YWx1ZTogYCR7dGhpcy5nZXRSZWdpb25QcmVmaXgocmVnaW9uKX1Mb2FkQmFsYW5jZXJVc2FnZWAgfSxcbiAgICAgICAgXSxcbiAgICAgIH0pO1xuXG4gICAgICAvLyBHZXQgTENVIHJhdGVcbiAgICAgIGNvbnN0IGxjdVJhdGUgPSBhd2FpdCBwcmljaW5nQ2xpZW50LmdldFByaWNlKHtcbiAgICAgICAgc2VydmljZUNvZGU6ICdBV1NFTEInLFxuICAgICAgICByZWdpb246IHRoaXMubm9ybWFsaXplUmVnaW9uKHJlZ2lvbiksXG4gICAgICAgIGZpbHRlcnM6IFtcbiAgICAgICAgICB7IGZpZWxkOiAncHJvZHVjdEZhbWlseScsIHZhbHVlOiAnTG9hZCBCYWxhbmNlci1BcHBsaWNhdGlvbicgfSxcbiAgICAgICAgICB7IGZpZWxkOiAndXNhZ2V0eXBlJywgdmFsdWU6IGAke3RoaXMuZ2V0UmVnaW9uUHJlZml4KHJlZ2lvbil9TENVVXNhZ2VgIH0sXG4gICAgICAgIF0sXG4gICAgICB9KTtcblxuICAgICAgY29uc3QgbmV3Q29ubmVjdGlvbnNQZXJTZWNvbmQgPVxuICAgICAgICB0aGlzLmN1c3RvbU5ld0Nvbm5lY3Rpb25zUGVyU2Vjb25kIHx8IHRoaXMuREVGQVVMVF9ORVdfQ09OTkVDVElPTlNfUEVSX1NFQ09ORDtcbiAgICAgIGNvbnN0IGFjdGl2ZUNvbm5lY3Rpb25zUGVyTWludXRlID1cbiAgICAgICAgdGhpcy5jdXN0b21BY3RpdmVDb25uZWN0aW9uc1Blck1pbnV0ZSB8fCB0aGlzLkRFRkFVTFRfQUNUSVZFX0NPTk5FQ1RJT05TX1BFUl9NSU5VVEU7XG4gICAgICBjb25zdCBwcm9jZXNzZWRCeXRlc0dCID1cbiAgICAgICAgdGhpcy5jdXN0b21Qcm9jZXNzZWRCeXRlc0dCIHx8IHRoaXMuREVGQVVMVF9QUk9DRVNTRURfQllURVNfR0I7XG5cbiAgICAgIGlmIChob3VybHlSYXRlID09PSBudWxsIHx8IGxjdVJhdGUgPT09IG51bGwpIHtcbiAgICAgICAgLy8gQ2FsY3VsYXRlIExDVSBjb25zdW1wdGlvbiBmb3IgYXNzdW1wdGlvbnMgZXZlbiB3aGVuIHByaWNpbmcgZmFpbHNcbiAgICAgICAgY29uc3QgbGN1RnJvbU5ld0Nvbm5lY3Rpb25zID0gbmV3Q29ubmVjdGlvbnNQZXJTZWNvbmQgLyAyNTtcbiAgICAgICAgY29uc3QgbGN1RnJvbUFjdGl2ZUNvbm5lY3Rpb25zID0gYWN0aXZlQ29ubmVjdGlvbnNQZXJNaW51dGUgLyAzMDAwO1xuICAgICAgICBjb25zdCBnYlBlckhvdXIgPSBwcm9jZXNzZWRCeXRlc0dCIC8gdGhpcy5IT1VSU19QRVJfTU9OVEg7XG4gICAgICAgIGNvbnN0IGxjdUZyb21Qcm9jZXNzZWRCeXRlcyA9IGdiUGVySG91cjtcbiAgICAgICAgY29uc3QgbGN1UGVySG91ciA9IE1hdGgubWF4KFxuICAgICAgICAgIGxjdUZyb21OZXdDb25uZWN0aW9ucyxcbiAgICAgICAgICBsY3VGcm9tQWN0aXZlQ29ubmVjdGlvbnMsXG4gICAgICAgICAgbGN1RnJvbVByb2Nlc3NlZEJ5dGVzLFxuICAgICAgICApO1xuXG4gICAgICAgIHJldHVybiB7XG4gICAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICAgIGN1cnJlbmN5OiAnVVNEJyxcbiAgICAgICAgICBjb25maWRlbmNlOiAndW5rbm93bicsXG4gICAgICAgICAgYXNzdW1wdGlvbnM6IFtcbiAgICAgICAgICAgIGBQcmljaW5nIGRhdGEgbm90IGF2YWlsYWJsZSBmb3IgQXBwbGljYXRpb24gTG9hZCBCYWxhbmNlciBpbiByZWdpb24gJHtyZWdpb259YCxcbiAgICAgICAgICAgIGBXb3VsZCB1c2UgTENVIGNvbnN1bXB0aW9uOiAke2xjdVBlckhvdXIudG9GaXhlZCgyKX0gTENVL2hvdXIgYmFzZWQgb246YCxcbiAgICAgICAgICAgIGAgIC0gTmV3IGNvbm5lY3Rpb25zOiAke25ld0Nvbm5lY3Rpb25zUGVyU2Vjb25kfS9zZWMg4oaSICR7bGN1RnJvbU5ld0Nvbm5lY3Rpb25zLnRvRml4ZWQoMil9IExDVWAsXG4gICAgICAgICAgICBgICAtIEFjdGl2ZSBjb25uZWN0aW9uczogJHthY3RpdmVDb25uZWN0aW9uc1Blck1pbnV0ZX0vbWluIOKGkiAke2xjdUZyb21BY3RpdmVDb25uZWN0aW9ucy50b0ZpeGVkKDIpfSBMQ1VgLFxuICAgICAgICAgICAgYCAgLSBQcm9jZXNzZWQgZGF0YTogJHtwcm9jZXNzZWRCeXRlc0dCfSBHQi9tb250aCDihpIgJHtsY3VGcm9tUHJvY2Vzc2VkQnl0ZXMudG9GaXhlZCgyKX0gTENVYCxcbiAgICAgICAgICBdLFxuICAgICAgICB9O1xuICAgICAgfVxuXG4gICAgICAvLyBDYWxjdWxhdGUgTENVIGNvbnN1bXB0aW9uXG4gICAgICAvLyAxIExDVSBwcm92aWRlczogMjUgbmV3IGNvbm5lY3Rpb25zL3NlYywgMzAwMCBhY3RpdmUgY29ubmVjdGlvbnMvbWluLCAxIEdCIHByb2Nlc3NlZC9ob3VyLCAxMDAwIHJ1bGUgZXZhbHVhdGlvbnMvc2VjXG4gICAgICBjb25zdCBsY3VGcm9tTmV3Q29ubmVjdGlvbnMgPSBuZXdDb25uZWN0aW9uc1BlclNlY29uZCAvIDI1O1xuICAgICAgY29uc3QgbGN1RnJvbUFjdGl2ZUNvbm5lY3Rpb25zID0gYWN0aXZlQ29ubmVjdGlvbnNQZXJNaW51dGUgLyAzMDAwO1xuICAgICAgY29uc3QgZ2JQZXJIb3VyID0gcHJvY2Vzc2VkQnl0ZXNHQiAvIHRoaXMuSE9VUlNfUEVSX01PTlRIO1xuICAgICAgY29uc3QgbGN1RnJvbVByb2Nlc3NlZEJ5dGVzID0gZ2JQZXJIb3VyO1xuXG4gICAgICAvLyBVc2UgdGhlIGhpZ2hlc3QgTENVIGNvbnN1bXB0aW9uXG4gICAgICBjb25zdCBsY3VQZXJIb3VyID0gTWF0aC5tYXgoXG4gICAgICAgIGxjdUZyb21OZXdDb25uZWN0aW9ucyxcbiAgICAgICAgbGN1RnJvbUFjdGl2ZUNvbm5lY3Rpb25zLFxuICAgICAgICBsY3VGcm9tUHJvY2Vzc2VkQnl0ZXMsXG4gICAgICApO1xuXG4gICAgICBjb25zdCBob3VybHlDb3N0ID0gaG91cmx5UmF0ZSAqIHRoaXMuSE9VUlNfUEVSX01PTlRIO1xuICAgICAgY29uc3QgbGN1Q29zdCA9IGxjdVJhdGUgKiBsY3VQZXJIb3VyICogdGhpcy5IT1VSU19QRVJfTU9OVEg7XG4gICAgICBjb25zdCB0b3RhbENvc3QgPSBob3VybHlDb3N0ICsgbGN1Q29zdDtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYW1vdW50OiB0b3RhbENvc3QsXG4gICAgICAgIGN1cnJlbmN5OiAnVVNEJyxcbiAgICAgICAgY29uZmlkZW5jZTogJ21lZGl1bScsXG4gICAgICAgIGFzc3VtcHRpb25zOiBbXG4gICAgICAgICAgYEhvdXJseSByYXRlOiAkJHtob3VybHlSYXRlLnRvRml4ZWQoNCl9L2hvdXIgw5cgJHt0aGlzLkhPVVJTX1BFUl9NT05USH0gaG91cnMgPSAkJHtob3VybHlDb3N0LnRvRml4ZWQoMil9L21vbnRoYCxcbiAgICAgICAgICBgTENVIGNvbnN1bXB0aW9uOiAke2xjdVBlckhvdXIudG9GaXhlZCgyKX0gTENVL2hvdXIgYmFzZWQgb246YCxcbiAgICAgICAgICBgICAtIE5ldyBjb25uZWN0aW9uczogJHtuZXdDb25uZWN0aW9uc1BlclNlY29uZH0vc2VjIOKGkiAke2xjdUZyb21OZXdDb25uZWN0aW9ucy50b0ZpeGVkKDIpfSBMQ1VgLFxuICAgICAgICAgIGAgIC0gQWN0aXZlIGNvbm5lY3Rpb25zOiAke2FjdGl2ZUNvbm5lY3Rpb25zUGVyTWludXRlfS9taW4g4oaSICR7bGN1RnJvbUFjdGl2ZUNvbm5lY3Rpb25zLnRvRml4ZWQoMil9IExDVWAsXG4gICAgICAgICAgYCAgLSBQcm9jZXNzZWQgZGF0YTogJHtwcm9jZXNzZWRCeXRlc0dCfSBHQi9tb250aCDihpIgJHtsY3VGcm9tUHJvY2Vzc2VkQnl0ZXMudG9GaXhlZCgyKX0gTENVYCxcbiAgICAgICAgICBgTENVIGNvc3Q6ICQke2xjdVJhdGUudG9GaXhlZCg0KX0vTENVL2hvdXIgw5cgJHtsY3VQZXJIb3VyLnRvRml4ZWQoMil9IExDVSDDlyAke3RoaXMuSE9VUlNfUEVSX01PTlRIfSBob3VycyA9ICQke2xjdUNvc3QudG9GaXhlZCgyKX0vbW9udGhgLFxuICAgICAgICAgIGBUb3RhbDogJCR7dG90YWxDb3N0LnRvRml4ZWQoMil9L21vbnRoYCxcbiAgICAgICAgXSxcbiAgICAgIH07XG4gICAgfSBjYXRjaCAoZXJyb3IpIHtcbiAgICAgIGNvbnN0IG5ld0Nvbm5lY3Rpb25zUGVyU2Vjb25kID1cbiAgICAgICAgdGhpcy5jdXN0b21OZXdDb25uZWN0aW9uc1BlclNlY29uZCB8fCB0aGlzLkRFRkFVTFRfTkVXX0NPTk5FQ1RJT05TX1BFUl9TRUNPTkQ7XG4gICAgICBjb25zdCBhY3RpdmVDb25uZWN0aW9uc1Blck1pbnV0ZSA9XG4gICAgICAgIHRoaXMuY3VzdG9tQWN0aXZlQ29ubmVjdGlvbnNQZXJNaW51dGUgfHwgdGhpcy5ERUZBVUxUX0FDVElWRV9DT05ORUNUSU9OU19QRVJfTUlOVVRFO1xuICAgICAgY29uc3QgcHJvY2Vzc2VkQnl0ZXNHQiA9XG4gICAgICAgIHRoaXMuY3VzdG9tUHJvY2Vzc2VkQnl0ZXNHQiB8fCB0aGlzLkRFRkFVTFRfUFJPQ0VTU0VEX0JZVEVTX0dCO1xuXG4gICAgICAvLyBDYWxjdWxhdGUgTENVIGNvbnN1bXB0aW9uIGZvciBhc3N1bXB0aW9ucyBldmVuIHdoZW4gZXJyb3Igb2NjdXJzXG4gICAgICBjb25zdCBsY3VGcm9tTmV3Q29ubmVjdGlvbnMgPSBuZXdDb25uZWN0aW9uc1BlclNlY29uZCAvIDI1O1xuICAgICAgY29uc3QgbGN1RnJvbUFjdGl2ZUNvbm5lY3Rpb25zID0gYWN0aXZlQ29ubmVjdGlvbnNQZXJNaW51dGUgLyAzMDAwO1xuICAgICAgY29uc3QgZ2JQZXJIb3VyID0gcHJvY2Vzc2VkQnl0ZXNHQiAvIHRoaXMuSE9VUlNfUEVSX01PTlRIO1xuICAgICAgY29uc3QgbGN1RnJvbVByb2Nlc3NlZEJ5dGVzID0gZ2JQZXJIb3VyO1xuICAgICAgY29uc3QgbGN1UGVySG91ciA9IE1hdGgubWF4KFxuICAgICAgICBsY3VGcm9tTmV3Q29ubmVjdGlvbnMsXG4gICAgICAgIGxjdUZyb21BY3RpdmVDb25uZWN0aW9ucyxcbiAgICAgICAgbGN1RnJvbVByb2Nlc3NlZEJ5dGVzLFxuICAgICAgKTtcblxuICAgICAgcmV0dXJuIHtcbiAgICAgICAgYW1vdW50OiAwLFxuICAgICAgICBjdXJyZW5jeTogJ1VTRCcsXG4gICAgICAgIGNvbmZpZGVuY2U6ICd1bmtub3duJyxcbiAgICAgICAgYXNzdW1wdGlvbnM6IFtcbiAgICAgICAgICBgRmFpbGVkIHRvIGZldGNoIHByaWNpbmc6ICR7ZXJyb3IgaW5zdGFuY2VvZiBFcnJvciA/IGVycm9yLm1lc3NhZ2UgOiBTdHJpbmcoZXJyb3IpfWAsXG4gICAgICAgICAgYFdvdWxkIHVzZSBMQ1UgY29uc3VtcHRpb246ICR7bGN1UGVySG91ci50b0ZpeGVkKDIpfSBMQ1UvaG91ciBiYXNlZCBvbjpgLFxuICAgICAgICAgIGAgIC0gTmV3IGNvbm5lY3Rpb25zOiAke25ld0Nvbm5lY3Rpb25zUGVyU2Vjb25kfS9zZWMg4oaSICR7bGN1RnJvbU5ld0Nvbm5lY3Rpb25zLnRvRml4ZWQoMil9IExDVWAsXG4gICAgICAgICAgYCAgLSBBY3RpdmUgY29ubmVjdGlvbnM6ICR7YWN0aXZlQ29ubmVjdGlvbnNQZXJNaW51dGV9L21pbiDihpIgJHtsY3VGcm9tQWN0aXZlQ29ubmVjdGlvbnMudG9GaXhlZCgyKX0gTENVYCxcbiAgICAgICAgICBgICAtIFByb2Nlc3NlZCBkYXRhOiAke3Byb2Nlc3NlZEJ5dGVzR0J9IEdCL21vbnRoIOKGkiAke2xjdUZyb21Qcm9jZXNzZWRCeXRlcy50b0ZpeGVkKDIpfSBMQ1VgLFxuICAgICAgICBdLFxuICAgICAgfTtcbiAgICB9XG4gIH1cblxuICBwcml2YXRlIG5vcm1hbGl6ZVJlZ2lvbihyZWdpb246IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgcmVnaW9uTWFwOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgICAgJ3VzLWVhc3QtMSc6ICdVUyBFYXN0IChOLiBWaXJnaW5pYSknLFxuICAgICAgJ3VzLWVhc3QtMic6ICdVUyBFYXN0IChPaGlvKScsXG4gICAgICAndXMtd2VzdC0xJzogJ1VTIFdlc3QgKE4uIENhbGlmb3JuaWEpJyxcbiAgICAgICd1cy13ZXN0LTInOiAnVVMgV2VzdCAoT3JlZ29uKScsXG4gICAgICAnZXUtd2VzdC0xJzogJ0VVIChJcmVsYW5kKScsXG4gICAgICAnZXUtd2VzdC0yJzogJ0VVIChMb25kb24pJyxcbiAgICAgICdldS13ZXN0LTMnOiAnRVUgKFBhcmlzKScsXG4gICAgICAnZXUtY2VudHJhbC0xJzogJ0VVIChGcmFua2Z1cnQpJyxcbiAgICAgICdldS1ub3J0aC0xJzogJ0VVIChTdG9ja2hvbG0pJyxcbiAgICAgICdhcC1zb3V0aC0xJzogJ0FzaWEgUGFjaWZpYyAoTXVtYmFpKScsXG4gICAgICAnYXAtc291dGhlYXN0LTEnOiAnQXNpYSBQYWNpZmljIChTaW5nYXBvcmUpJyxcbiAgICAgICdhcC1zb3V0aGVhc3QtMic6ICdBc2lhIFBhY2lmaWMgKFN5ZG5leSknLFxuICAgICAgJ2FwLW5vcnRoZWFzdC0xJzogJ0FzaWEgUGFjaWZpYyAoVG9reW8pJyxcbiAgICAgICdhcC1ub3J0aGVhc3QtMic6ICdBc2lhIFBhY2lmaWMgKFNlb3VsKScsXG4gICAgfTtcblxuICAgIHJldHVybiByZWdpb25NYXBbcmVnaW9uXSB8fCByZWdpb247XG4gIH1cblxuICBwcml2YXRlIGdldFJlZ2lvblByZWZpeChyZWdpb246IHN0cmluZyk6IHN0cmluZyB7XG4gICAgY29uc3QgcHJlZml4TWFwOiBSZWNvcmQ8c3RyaW5nLCBzdHJpbmc+ID0ge1xuICAgICAgJ3VzLWVhc3QtMSc6ICdVU0UxJyxcbiAgICAgICd1cy1lYXN0LTInOiAnVVNFMicsXG4gICAgICAndXMtd2VzdC0xJzogJ1VTVzEnLFxuICAgICAgJ3VzLXdlc3QtMic6ICdVU1cyJyxcbiAgICAgICdldS13ZXN0LTEnOiAnRVVXMScsXG4gICAgICAnZXUtd2VzdC0yJzogJ0VVVzInLFxuICAgICAgJ2V1LXdlc3QtMyc6ICdFVVczJyxcbiAgICAgICdldS1jZW50cmFsLTEnOiAnRVVDMScsXG4gICAgICAnZXUtbm9ydGgtMSc6ICdFVU4xJyxcbiAgICAgICdhcC1zb3V0aC0xJzogJ0FQUzEnLFxuICAgICAgJ2FwLXNvdXRoZWFzdC0xJzogJ0FQUzInLFxuICAgICAgJ2FwLXNvdXRoZWFzdC0yJzogJ0FQUzMnLFxuICAgICAgJ2FwLW5vcnRoZWFzdC0xJzogJ0FQTjEnLFxuICAgICAgJ2FwLW5vcnRoZWFzdC0yJzogJ0FQTjInLFxuICAgIH07XG5cbiAgICByZXR1cm4gcHJlZml4TWFwW3JlZ2lvbl0gfHwgJyc7XG4gIH1cbn1cbiJdfQ==
@@ -0,0 +1,10 @@
1
+ import { ResourceWithId } from '../../diff/types';
2
+ import { ResourceCostCalculator, MonthlyCost, PricingClient } from '../types';
3
+ export declare class APIGatewayCalculator implements ResourceCostCalculator {
4
+ supports(resourceType: string): boolean;
5
+ calculateCost(resource: ResourceWithId, region: string, pricingClient: PricingClient): Promise<MonthlyCost>;
6
+ private calculateRestApiCost;
7
+ private calculateHttpApiCost;
8
+ private calculateWebSocketCost;
9
+ private normalizeRegion;
10
+ }