@electrolux-oss/plugin-infrawallet 1.1.0 → 1.2.0-20260522070332-40cf881
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.
- package/README.md +2 -2
- package/dist/api/InfraWalletApiClient.esm.js.map +1 -1
- package/dist/api/functions.esm.js.map +1 -1
- package/dist/components/Budgets/Budgets.esm.js +272 -151
- package/dist/components/Budgets/Budgets.esm.js.map +1 -1
- package/dist/components/ColumnsChartComponent/ColumnsChartComponent.esm.js +97 -82
- package/dist/components/ColumnsChartComponent/ColumnsChartComponent.esm.js.map +1 -1
- package/dist/components/CostReportsTableComponent/CostReportsTableComponent.esm.js +23 -18
- package/dist/components/CostReportsTableComponent/CostReportsTableComponent.esm.js.map +1 -1
- package/dist/components/CustomCostsComponent/BulkInsertButton.esm.js +159 -107
- package/dist/components/CustomCostsComponent/BulkInsertButton.esm.js.map +1 -1
- package/dist/components/CustomCostsComponent/CustomCostsComponent.esm.js +43 -39
- package/dist/components/CustomCostsComponent/CustomCostsComponent.esm.js.map +1 -1
- package/dist/components/EntityInfraWalletCard/EntityInfraWalletCard.esm.js +126 -83
- package/dist/components/EntityInfraWalletCard/EntityInfraWalletCard.esm.js.map +1 -1
- package/dist/components/EntityInfraWalletCard/index.esm.js +5 -1
- package/dist/components/EntityInfraWalletCard/index.esm.js.map +1 -1
- package/dist/components/ErrorsAlertComponent/ErrorsAlertComponent.esm.js +24 -12
- package/dist/components/ErrorsAlertComponent/ErrorsAlertComponent.esm.js.map +1 -1
- package/dist/components/FiltersComponent/FiltersComponent.esm.js +155 -117
- package/dist/components/FiltersComponent/FiltersComponent.esm.js.map +1 -1
- package/dist/components/HomePage/HomePage.esm.js +21 -21
- package/dist/components/HomePage/HomePage.esm.js.map +1 -1
- package/dist/components/InfraWalletIcon.esm.js +69 -54
- package/dist/components/InfraWalletIcon.esm.js.map +1 -1
- package/dist/components/MetricConfigurationComponent/MetricConfigurationComponent.esm.js +35 -30
- package/dist/components/MetricConfigurationComponent/MetricConfigurationComponent.esm.js.map +1 -1
- package/dist/components/Overview/Overview.esm.js +67 -53
- package/dist/components/Overview/Overview.esm.js.map +1 -1
- package/dist/components/PieChartComponent/PieChartComponent.esm.js +14 -7
- package/dist/components/PieChartComponent/PieChartComponent.esm.js.map +1 -1
- package/dist/components/ProviderIcon/ProviderIcon.esm.js +4 -3
- package/dist/components/ProviderIcon/ProviderIcon.esm.js.map +1 -1
- package/dist/components/Router.esm.js +9 -3
- package/dist/components/Router.esm.js.map +1 -1
- package/dist/components/SettingsComponent/SettingsComponent.esm.js +3 -2
- package/dist/components/SettingsComponent/SettingsComponent.esm.js.map +1 -1
- package/dist/components/TopbarComponent/TopbarComponent.esm.js +53 -32
- package/dist/components/TopbarComponent/TopbarComponent.esm.js.map +1 -1
- package/dist/components/index.esm.js +2 -1
- package/dist/components/index.esm.js.map +1 -1
- package/dist/components/utils.esm.js.map +1 -1
- package/dist/hooks/useInfraWalletLuceneParams.esm.js.map +1 -1
- package/dist/index.d.ts +72 -9
- package/dist/index.esm.js +1 -1
- package/dist/plugin.esm.js +53 -6
- package/dist/plugin.esm.js.map +1 -1
- package/dist/routes.esm.js +3 -9
- package/dist/routes.esm.js.map +1 -1
- package/package.json +18 -13
package/README.md
CHANGED
|
@@ -101,7 +101,7 @@ InfraWallet's AWS client is built using the AWS SDK for JavaScript. If both `acc
|
|
|
101
101
|
|
|
102
102
|
To manage Azure costs with InfraWallet, you need to register an application in Azure. Note that InfraWallet has been tested with subscription-level cost data only.
|
|
103
103
|
|
|
104
|
-
##### Steps
|
|
104
|
+
##### Steps
|
|
105
105
|
|
|
106
106
|
1. After registering the application, navigate to the `Subscriptions` page and select the target subscription.
|
|
107
107
|
2. Go to the `Access control (IAM)` section and assign the `Cost Management Reader` role to the newly created application.
|
|
@@ -308,7 +308,7 @@ async function main() {
|
|
|
308
308
|
|
|
309
309
|
## Local Development
|
|
310
310
|
|
|
311
|
-
First of all, make sure you are using either Node 18 or Node 20 for this project. Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn install && yarn
|
|
311
|
+
First of all, make sure you are using either Node 18 or Node 20 for this project. Your plugin has been added to the example app in this repository, meaning you'll be able to access it by running `yarn install && yarn start` in the root directory, and then navigating to [/infrawallet](http://localhost:3000/infrawallet).
|
|
312
312
|
|
|
313
313
|
You can also serve the plugin in isolation by running `yarn install && yarn start` in the plugin directory.
|
|
314
314
|
This method of serving the plugin provides quicker iteration speed and a faster startup and hot reloads.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"InfraWalletApiClient.esm.js","sources":["../../src/api/InfraWalletApiClient.ts"],"sourcesContent":["import { ConfigApi, IdentityApi } from '@backstage/core-plugin-api';\nimport fetch from 'node-fetch';\nimport { InfraWalletApi } from './InfraWalletApi';\nimport { tagsToString } from './functions';\nimport {\n Budget,\n BudgetsResponse,\n CostReportsResponse,\n CustomCost,\n CustomCostsResponse,\n GetWalletResponse,\n MetricConfigsResponse,\n MetricSetting,\n MetricsResponse,\n MetricsSettingResponse,\n Tag,\n TagResponse,\n} from './types';\n\n/** @public */\nexport class InfraWalletApiClient implements InfraWalletApi {\n private readonly identityApi: IdentityApi;\n private readonly backendUrl: string;\n\n constructor(options: { identityApi: IdentityApi; configApi: ConfigApi }) {\n this.identityApi = options.identityApi;\n this.backendUrl = options.configApi.getString('backend.baseUrl');\n }\n\n async request(path: string, method?: string, payload?: Record<string, any>) {\n const url = `${this.backendUrl}/${path}`;\n const { token: idToken } = await this.identityApi.getCredentials();\n const headers: Record<string, string> = idToken ? { Authorization: `Bearer ${idToken}` } : {};\n\n if (method !== undefined && method !== 'GET') {\n headers['Content-Type'] = 'application/json';\n }\n\n const request: any = {\n headers: headers,\n method: method ?? 'GET',\n };\n\n if (payload) {\n request.body = JSON.stringify(payload);\n }\n\n const response = await fetch(url, request);\n\n if (!response.ok) {\n const res = await response.text();\n const message = `Request failed with ${response.status} ${response.statusText}, ${res}`;\n throw new Error(message);\n }\n\n return await response.json();\n }\n\n async getCostReports(\n filters: string,\n tags: Tag[],\n groups: string,\n granularity: string,\n startTime: Date,\n endTime: Date,\n entityName?: string,\n ): Promise<CostReportsResponse> {\n const tagsString = tagsToString(tags);\n const entityNameParam = entityName ? `&entityName=${entityName}` : '';\n const url = `api/infrawallet/reports?granularity=${granularity}&groups=${groups}&filters=${filters}&tags=${tagsString}&startTime=${startTime.getTime()}&endTime=${endTime.getTime()}${entityNameParam}`;\n\n return await this.request(url);\n }\n\n async getTagKeys(provider: string, startTime: Date, endTime: Date): Promise<TagResponse> {\n const url = `api/infrawallet/tag-keys?provider=${provider}&startTime=${startTime.getTime()}&endTime=${endTime.getTime()}`;\n return await this.request(url);\n }\n\n async getTagValues(tag: Tag, startTime: Date, endTime: Date): Promise<TagResponse> {\n const provider = tag.provider;\n const tagKey = tag.key;\n const url = `api/infrawallet/tag-values?provider=${provider}&tag=${tagKey}&startTime=${startTime.getTime()}&endTime=${endTime.getTime()}`;\n return await this.request(url);\n }\n\n async getBudgets(walletName: string): Promise<BudgetsResponse> {\n const url = `api/infrawallet/${walletName}/budgets`;\n return await this.request(url);\n }\n\n async getBudget(walletName: string, provider: string): Promise<BudgetsResponse> {\n const url = `api/infrawallet/${walletName}/budgets?provider=${provider}`;\n return await this.request(url);\n }\n\n async updateBudget(walletName: string, budget: Budget): Promise<{ updated: boolean; status: number }> {\n const url = `api/infrawallet/${walletName}/budgets`;\n return await this.request(url, 'PUT', budget);\n }\n\n async getWalletByName(walletName: string): Promise<GetWalletResponse> {\n const url = `api/infrawallet/${walletName}`;\n return await this.request(url);\n }\n\n async getMetrics(walletName: string, granularity: string, startTime: Date, endTime: Date): Promise<MetricsResponse> {\n const url = `api/infrawallet/${walletName}/metrics?&granularity=${granularity}&startTime=${startTime.getTime()}&endTime=${endTime.getTime()}`;\n return await this.request(url);\n }\n\n async getMetricConfigs(): Promise<MetricConfigsResponse> {\n const url = 'api/infrawallet/metric/metric-configs';\n return await this.request(url);\n }\n\n async getWalletMetricsSetting(walletName: string): Promise<MetricsSettingResponse> {\n const url = `api/infrawallet/${walletName}/metrics-setting`;\n return await this.request(url);\n }\n\n async updateWalletMetricSetting(\n walletName: string,\n metricSetting: MetricSetting,\n ): Promise<{ updated: boolean; status: number }> {\n const url = `api/infrawallet/${walletName}/metrics-setting`;\n return await this.request(url, 'PUT', metricSetting);\n }\n\n async deleteWalletMetricSetting(\n walletName: string,\n metricSetting: MetricSetting,\n ): Promise<{ deleted: boolean; status: number }> {\n const url = `api/infrawallet/${walletName}/metrics-setting`;\n return await this.request(url, 'DELETE', metricSetting);\n }\n\n async getCustomCosts(): Promise<CustomCostsResponse> {\n const url = `api/infrawallet/custom-costs`;\n return await this.request(url);\n }\n\n async createCustomCosts(customCosts: CustomCost[]): Promise<{ created: number; status: number }> {\n const url = `api/infrawallet/custom-costs`;\n return await this.request(url, 'POST', customCosts);\n }\n\n async updateCustomCost(customCost: CustomCost): Promise<{ updated: boolean; status: number }> {\n const url = `api/infrawallet/custom-cost`;\n return await this.request(url, 'PUT', customCost);\n }\n\n async deleteCustomCost(customCost: CustomCost): Promise<{ deleted: boolean; status: number }> {\n const url = `api/infrawallet/custom-cost`;\n return await this.request(url, 'DELETE', customCost);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"InfraWalletApiClient.esm.js","sources":["../../src/api/InfraWalletApiClient.ts"],"sourcesContent":["import { ConfigApi, IdentityApi } from '@backstage/core-plugin-api';\nimport fetch from 'node-fetch';\nimport { InfraWalletApi } from './InfraWalletApi';\nimport { tagsToString } from './functions';\nimport {\n Budget,\n BudgetsResponse,\n CostReportsResponse,\n CustomCost,\n CustomCostsResponse,\n GetWalletResponse,\n MetricConfigsResponse,\n MetricSetting,\n MetricsResponse,\n MetricsSettingResponse,\n Tag,\n TagResponse,\n} from './types';\n\n/** @public */\nexport class InfraWalletApiClient implements InfraWalletApi {\n private readonly identityApi: IdentityApi;\n private readonly backendUrl: string;\n\n constructor(options: { identityApi: IdentityApi; configApi: ConfigApi }) {\n this.identityApi = options.identityApi;\n this.backendUrl = options.configApi.getString('backend.baseUrl');\n }\n\n async request(path: string, method?: string, payload?: Record<string, any>) {\n const url = `${this.backendUrl}/${path}`;\n const { token: idToken } = await this.identityApi.getCredentials();\n const headers: Record<string, string> = idToken ? { Authorization: `Bearer ${idToken}` } : {};\n\n if (method !== undefined && method !== 'GET') {\n headers['Content-Type'] = 'application/json';\n }\n\n const request: any = {\n headers: headers,\n method: method ?? 'GET',\n };\n\n if (payload) {\n request.body = JSON.stringify(payload);\n }\n\n const response = await fetch(url, request);\n\n if (!response.ok) {\n const res = await response.text();\n const message = `Request failed with ${response.status} ${response.statusText}, ${res}`;\n throw new Error(message);\n }\n\n return await response.json();\n }\n\n async getCostReports(\n filters: string,\n tags: Tag[],\n groups: string,\n granularity: string,\n startTime: Date,\n endTime: Date,\n entityName?: string,\n ): Promise<CostReportsResponse> {\n const tagsString = tagsToString(tags);\n const entityNameParam = entityName ? `&entityName=${entityName}` : '';\n const url = `api/infrawallet/reports?granularity=${granularity}&groups=${groups}&filters=${filters}&tags=${tagsString}&startTime=${startTime.getTime()}&endTime=${endTime.getTime()}${entityNameParam}`;\n\n return await this.request(url);\n }\n\n async getTagKeys(provider: string, startTime: Date, endTime: Date): Promise<TagResponse> {\n const url = `api/infrawallet/tag-keys?provider=${provider}&startTime=${startTime.getTime()}&endTime=${endTime.getTime()}`;\n return await this.request(url);\n }\n\n async getTagValues(tag: Tag, startTime: Date, endTime: Date): Promise<TagResponse> {\n const provider = tag.provider;\n const tagKey = tag.key;\n const url = `api/infrawallet/tag-values?provider=${provider}&tag=${tagKey}&startTime=${startTime.getTime()}&endTime=${endTime.getTime()}`;\n return await this.request(url);\n }\n\n async getBudgets(walletName: string): Promise<BudgetsResponse> {\n const url = `api/infrawallet/${walletName}/budgets`;\n return await this.request(url);\n }\n\n async getBudget(walletName: string, provider: string): Promise<BudgetsResponse> {\n const url = `api/infrawallet/${walletName}/budgets?provider=${provider}`;\n return await this.request(url);\n }\n\n async updateBudget(walletName: string, budget: Budget): Promise<{ updated: boolean; status: number }> {\n const url = `api/infrawallet/${walletName}/budgets`;\n return await this.request(url, 'PUT', budget);\n }\n\n async getWalletByName(walletName: string): Promise<GetWalletResponse> {\n const url = `api/infrawallet/${walletName}`;\n return await this.request(url);\n }\n\n async getMetrics(walletName: string, granularity: string, startTime: Date, endTime: Date): Promise<MetricsResponse> {\n const url = `api/infrawallet/${walletName}/metrics?&granularity=${granularity}&startTime=${startTime.getTime()}&endTime=${endTime.getTime()}`;\n return await this.request(url);\n }\n\n async getMetricConfigs(): Promise<MetricConfigsResponse> {\n const url = 'api/infrawallet/metric/metric-configs';\n return await this.request(url);\n }\n\n async getWalletMetricsSetting(walletName: string): Promise<MetricsSettingResponse> {\n const url = `api/infrawallet/${walletName}/metrics-setting`;\n return await this.request(url);\n }\n\n async updateWalletMetricSetting(\n walletName: string,\n metricSetting: MetricSetting,\n ): Promise<{ updated: boolean; status: number }> {\n const url = `api/infrawallet/${walletName}/metrics-setting`;\n return await this.request(url, 'PUT', metricSetting);\n }\n\n async deleteWalletMetricSetting(\n walletName: string,\n metricSetting: MetricSetting,\n ): Promise<{ deleted: boolean; status: number }> {\n const url = `api/infrawallet/${walletName}/metrics-setting`;\n return await this.request(url, 'DELETE', metricSetting);\n }\n\n async getCustomCosts(): Promise<CustomCostsResponse> {\n const url = `api/infrawallet/custom-costs`;\n return await this.request(url);\n }\n\n async createCustomCosts(customCosts: CustomCost[]): Promise<{ created: number; status: number }> {\n const url = `api/infrawallet/custom-costs`;\n return await this.request(url, 'POST', customCosts);\n }\n\n async updateCustomCost(customCost: CustomCost): Promise<{ updated: boolean; status: number }> {\n const url = `api/infrawallet/custom-cost`;\n return await this.request(url, 'PUT', customCost);\n }\n\n async deleteCustomCost(customCost: CustomCost): Promise<{ deleted: boolean; status: number }> {\n const url = `api/infrawallet/custom-cost`;\n return await this.request(url, 'DELETE', customCost);\n }\n}\n"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"functions.esm.js","sources":["../../src/api/functions.ts"],"sourcesContent":["import { format, parse, subDays, subMonths } from 'date-fns';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport { Filters, Report, Tag } from './types';\n\nconst aggregateReportsAndForecasts = (\n accumulator: { [key: string]: Report },\n report: Report,\n keyName: string,\n): void => {\n Object.keys(report.reports).forEach(key => {\n if (accumulator[keyName].reports[key]) {\n accumulator[keyName].reports[key] += report.reports[key];\n } else {\n accumulator[keyName].reports[key] = report.reports[key];\n }\n });\n\n // Aggregate forecast values\n if (report.forecast) {\n if (!accumulator[keyName].forecast) {\n accumulator[keyName].forecast = {};\n }\n Object.keys(report.forecast).forEach(key => {\n const accForecast = accumulator[keyName].forecast as { [key: string]: number };\n const repForecast = report.forecast as { [key: string]: number };\n if (accForecast[key]) {\n accForecast[key] += repForecast[key];\n } else {\n accForecast[key] = repForecast[key];\n }\n });\n }\n};\n\nexport const mergeCostReports = (reports: Report[], threshold?: number): Report[] => {\n const totalCosts: { id: string; total: number }[] = [];\n reports.forEach(report => {\n let total = 0;\n Object.values(report.reports).forEach(v => {\n total += v as number;\n });\n totalCosts.push({ id: report.id, total: total });\n });\n totalCosts.sort((a, b) => b.total - a.total);\n const idsToBeKept = totalCosts.slice(0, threshold).map(v => v.id);\n\n const mergedReports = reduce(\n reports,\n (accumulator: { [key: string]: Report }, report) => {\n let keyName = 'Others';\n if (idsToBeKept.includes(report.id)) {\n keyName = report.id;\n }\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n reports: {},\n forecast: {},\n };\n }\n\n aggregateReportsAndForecasts(accumulator, report, keyName);\n\n return accumulator;\n },\n {},\n );\n\n return Object.values(mergedReports).sort((a, b) => a.id.localeCompare(b.id));\n};\n\nexport const filterCostReports = (reports: Report[], filters: Filters): Report[] => {\n const filteredReports = reports.filter(report => {\n let match = true;\n Object.keys(filters).forEach(key => {\n if (filters[key].length > 0) {\n const reportValue = report[key] as string | undefined;\n\n // If the report doesn't have this field at all, it doesn't match\n if (reportValue === undefined) {\n match = false;\n return;\n }\n\n // Check if the report value matches any of the filter values\n const valueMatches = filters[key].some(filterValue => {\n // For exact matches\n if (reportValue === filterValue) {\n return true;\n }\n\n // For account field: match with or without account ID suffix\n // e.g., \"AWS/aws-staging-mock\" should match \"AWS/aws-staging-mock (012345678901)\"\n if (key === 'account') {\n // Extract the base account name (everything before the parentheses)\n const baseAccountName = reportValue.split(' (')[0];\n const filterAccountName = filterValue.split(' (')[0];\n if (baseAccountName === filterAccountName) {\n return true;\n }\n }\n\n // For service field: handle provider prefix matching\n // e.g., \"AWS/Lambda\" in filter should match \"AWS/Lambda\" in report\n if (key === 'service' && reportValue.includes('/') && filterValue.includes('/')) {\n return reportValue === filterValue;\n }\n\n return false;\n });\n\n if (!valueMatches) {\n match = false;\n }\n }\n });\n return match;\n });\n\n return filteredReports;\n};\n\nexport const aggregateCostReports = (reports: Report[], aggregatedBy?: string): Report[] => {\n const aggregatedReports: { [key: string]: Report } = reduce(\n reports,\n (accumulator, report) => {\n let keyName: string = 'no value';\n if (aggregatedBy && aggregatedBy in report) {\n keyName = report[aggregatedBy] as string;\n } else if (aggregatedBy === 'none') {\n keyName = 'Total';\n }\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n provider: report.provider,\n reports: {},\n forecast: {},\n } as {\n id: string;\n reports: { [key: string]: number };\n forecast?: { [key: string]: number };\n [key: string]: any;\n };\n\n if (aggregatedBy !== undefined) {\n accumulator[keyName][aggregatedBy] = keyName;\n }\n }\n\n aggregateReportsAndForecasts(accumulator, report, keyName);\n\n return accumulator;\n },\n {} as { [key: string]: Report },\n );\n return Object.values(aggregatedReports);\n};\n\nexport const getReportKeyAndValues = (reports: Report[] | undefined): { [key: string]: string[] } => {\n const excludedKeys = new Set(['id', 'reports', 'forecast']);\n const keyValueSets: { [key: string]: Set<string> } = {};\n reports?.forEach(report => {\n Object.keys(report).forEach(key => {\n if (!excludedKeys.has(key)) {\n if (keyValueSets[key] === undefined) {\n keyValueSets[key] = new Set<string>();\n }\n\n keyValueSets[key].add(report[key] as string);\n }\n });\n });\n\n const keyValues: { [key: string]: string[] } = {};\n Object.keys(keyValueSets).forEach((key: string) => {\n keyValues[key] = Array.from(keyValueSets[key]);\n keyValues[key].sort((a, b) => a.localeCompare(b));\n });\n return keyValues;\n};\n\nexport const extractProvider = (input: string): string | undefined => {\n let provider = undefined;\n if (input && input.indexOf('/') !== -1) {\n provider = input.split('/')[0];\n }\n\n return provider;\n};\n\nexport const extractAccountInfo = (input: string): { accountName: string; accountId?: string } => {\n // try to match format: accountName (accountId), e.g. aws-dev (123456789012)\n const regex = /^(.*?)\\s*\\(([^)]+)\\)$/;\n const match = input.match(regex);\n\n if (match) {\n const accountName = match[1];\n const accountId = match[2];\n return { accountName: accountName, accountId: accountId };\n }\n\n return { accountName: input };\n};\n\n// check if targetTag exists in tags\nexport function tagExists(tags: Tag[], targetTag: Tag): boolean {\n return tags.some(\n tag => tag.provider === targetTag.provider && tag.key === targetTag.key && tag.value === targetTag.value,\n );\n}\n\n// convert Tag array to (provider1:key1=value1 OR provider2:key2=value2) format\nexport const tagsToString = (tags: Tag[]): string => {\n if (tags.length === 0) {\n return '()';\n }\n\n const keyValuePairs = tags.map(tag => `${tag.provider}:${tag.key}=${tag.value}`);\n return `(${keyValuePairs.join(' OR ')})`;\n};\n\nexport const getAllReportTags = (reports: Report[]): string[] => {\n const tags = new Set<string>();\n const reservedKeys = new Set(['id', 'account', 'service', 'category', 'provider', 'reports', 'forecast']);\n reports.forEach(report => {\n Object.keys(report).forEach(key => {\n if (!reservedKeys.has(key)) {\n tags.add(key);\n }\n });\n });\n return Array.from(tags);\n};\n\nexport const getPreviousMonth = (month: string): string => {\n const date = parse(month, 'yyyy-MM', new Date());\n const previousMonth = subMonths(date, 1);\n return format(previousMonth, 'yyyy-MM');\n};\n\nexport const getPreviousDay = (day: string): string => {\n const date = parse(day, 'yyyy-MM-dd', new Date());\n const previousDay = subDays(date, 1);\n return format(previousDay, 'yyyy-MM-dd');\n};\n\nexport const getPeriodStrings = (granularity: string, startTime: Date, endTime: Date): string[] => {\n const result: string[] = [];\n const current = moment(startTime);\n\n while (current.isSameOrBefore(endTime) && current.isSameOrBefore(moment())) {\n if (granularity === 'monthly') {\n result.push(current.format('YYYY-MM'));\n current.add(1, 'months');\n } else {\n result.push(current.format('YYYY-MM-DD'));\n current.add(1, 'days');\n }\n }\n\n return result;\n};\n\nexport const formatCurrency = (number: number, currency?: string): string => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n notation: 'compact',\n }).format(number);\n};\n\nexport interface BudgetAnalytics {\n yearToDateSpent: number;\n monthlyRunRate: number;\n projectedAnnualSpending: number;\n projectedCurrentMonthCost: number;\n budgetHealthStatus: 'healthy' | 'warning' | 'critical';\n budgetUtilizationPercent: number;\n targetMonthlySpending: number;\n monthsRemaining: number;\n averageMonthlySpending: number;\n spendingVelocity: number;\n confidenceRange: {\n low: number;\n high: number;\n };\n}\n\nexport const calculateBudgetAnalytics = (\n monthlyCosts: Record<string, number>,\n annualBudget: number,\n forecast?: number,\n): BudgetAnalytics => {\n const currentMonth = moment().month() + 1;\n const currentYear = moment().year();\n const daysIntoCurrentMonth = moment().date();\n const daysInCurrentMonth = moment().daysInMonth();\n let yearToDateSpent = 0;\n let projectedCurrentMonthCost = 0;\n const monthlySpending: number[] = [];\n for (let month = 1; month <= currentMonth; month++) {\n const monthKey = `${currentYear}-${month.toString().padStart(2, '0')}`;\n const monthCost = monthlyCosts[monthKey] || 0;\n\n if (month < currentMonth) {\n yearToDateSpent += monthCost;\n monthlySpending.push(monthCost);\n } else if (month === currentMonth) {\n projectedCurrentMonthCost = forecast ?? (monthCost / daysIntoCurrentMonth) * daysInCurrentMonth;\n yearToDateSpent += monthCost;\n monthlySpending.push(projectedCurrentMonthCost);\n }\n }\n\n const monthsRemaining = 12 - currentMonth + (1 - daysIntoCurrentMonth / daysInCurrentMonth);\n const averageMonthlySpending =\n monthlySpending.length > 0 ? monthlySpending.reduce((sum, cost) => sum + cost, 0) / monthlySpending.length : 0;\n\n const monthlyRunRate = monthlySpending.length > 0 ? monthlySpending[monthlySpending.length - 1] || 0 : 0;\n\n const projectedAnnualSpending = yearToDateSpent + averageMonthlySpending * monthsRemaining;\n\n const budgetUtilizationPercent = annualBudget > 0 ? (yearToDateSpent / annualBudget) * 100 : 0;\n const expectedUtilizationPercent = ((currentMonth - 1 + daysIntoCurrentMonth / daysInCurrentMonth) / 12) * 100;\n\n let budgetHealthStatus: 'healthy' | 'warning' | 'critical' = 'healthy';\n if (budgetUtilizationPercent > expectedUtilizationPercent + 20) {\n budgetHealthStatus = 'critical';\n } else if (budgetUtilizationPercent > expectedUtilizationPercent + 10) {\n budgetHealthStatus = 'warning';\n }\n\n const targetMonthlySpending = monthsRemaining > 0 ? (annualBudget - yearToDateSpent) / monthsRemaining : 0;\n\n const spendingVariance =\n monthlySpending.length > 1\n ? Math.sqrt(\n monthlySpending.reduce((sum, cost) => sum + Math.pow(cost - averageMonthlySpending, 2), 0) /\n (monthlySpending.length - 1),\n )\n : 0;\n\n const spendingVelocity =\n monthlySpending.length >= 2\n ? ((monthlySpending[monthlySpending.length - 1] - monthlySpending[monthlySpending.length - 2]) /\n monthlySpending[monthlySpending.length - 2]) *\n 100\n : 0;\n\n const confidenceRange = {\n low: Math.max(0, projectedAnnualSpending - spendingVariance * 2 * Math.sqrt(monthsRemaining)),\n high: projectedAnnualSpending + spendingVariance * 2 * Math.sqrt(monthsRemaining),\n };\n\n return {\n yearToDateSpent,\n monthlyRunRate,\n projectedAnnualSpending,\n projectedCurrentMonthCost,\n budgetHealthStatus,\n budgetUtilizationPercent,\n targetMonthlySpending,\n monthsRemaining,\n averageMonthlySpending,\n spendingVelocity,\n confidenceRange,\n };\n};\n"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"functions.esm.js","sources":["../../src/api/functions.ts"],"sourcesContent":["import { format, parse, subDays, subMonths } from 'date-fns';\nimport { reduce } from 'lodash';\nimport moment from 'moment';\nimport { Filters, Report, Tag } from './types';\n\nconst aggregateReportsAndForecasts = (\n accumulator: { [key: string]: Report },\n report: Report,\n keyName: string,\n): void => {\n Object.keys(report.reports).forEach(key => {\n if (accumulator[keyName].reports[key]) {\n accumulator[keyName].reports[key] += report.reports[key];\n } else {\n accumulator[keyName].reports[key] = report.reports[key];\n }\n });\n\n // Aggregate forecast values\n if (report.forecast) {\n if (!accumulator[keyName].forecast) {\n accumulator[keyName].forecast = {};\n }\n Object.keys(report.forecast).forEach(key => {\n const accForecast = accumulator[keyName].forecast as { [key: string]: number };\n const repForecast = report.forecast as { [key: string]: number };\n if (accForecast[key]) {\n accForecast[key] += repForecast[key];\n } else {\n accForecast[key] = repForecast[key];\n }\n });\n }\n};\n\nexport const mergeCostReports = (reports: Report[], threshold?: number): Report[] => {\n const totalCosts: { id: string; total: number }[] = [];\n reports.forEach(report => {\n let total = 0;\n Object.values(report.reports).forEach(v => {\n total += v as number;\n });\n totalCosts.push({ id: report.id, total: total });\n });\n totalCosts.sort((a, b) => b.total - a.total);\n const idsToBeKept = totalCosts.slice(0, threshold).map(v => v.id);\n\n const mergedReports = reduce(\n reports,\n (accumulator: { [key: string]: Report }, report) => {\n let keyName = 'Others';\n if (idsToBeKept.includes(report.id)) {\n keyName = report.id;\n }\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n reports: {},\n forecast: {},\n };\n }\n\n aggregateReportsAndForecasts(accumulator, report, keyName);\n\n return accumulator;\n },\n {},\n );\n\n return Object.values(mergedReports).sort((a, b) => a.id.localeCompare(b.id));\n};\n\nexport const filterCostReports = (reports: Report[], filters: Filters): Report[] => {\n const filteredReports = reports.filter(report => {\n let match = true;\n Object.keys(filters).forEach(key => {\n if (filters[key].length > 0) {\n const reportValue = report[key] as string | undefined;\n\n // If the report doesn't have this field at all, it doesn't match\n if (reportValue === undefined) {\n match = false;\n return;\n }\n\n // Check if the report value matches any of the filter values\n const valueMatches = filters[key].some(filterValue => {\n // For exact matches\n if (reportValue === filterValue) {\n return true;\n }\n\n // For account field: match with or without account ID suffix\n // e.g., \"AWS/aws-staging-mock\" should match \"AWS/aws-staging-mock (012345678901)\"\n if (key === 'account') {\n // Extract the base account name (everything before the parentheses)\n const baseAccountName = reportValue.split(' (')[0];\n const filterAccountName = filterValue.split(' (')[0];\n if (baseAccountName === filterAccountName) {\n return true;\n }\n }\n\n // For service field: handle provider prefix matching\n // e.g., \"AWS/Lambda\" in filter should match \"AWS/Lambda\" in report\n if (key === 'service' && reportValue.includes('/') && filterValue.includes('/')) {\n return reportValue === filterValue;\n }\n\n return false;\n });\n\n if (!valueMatches) {\n match = false;\n }\n }\n });\n return match;\n });\n\n return filteredReports;\n};\n\nexport const aggregateCostReports = (reports: Report[], aggregatedBy?: string): Report[] => {\n const aggregatedReports: { [key: string]: Report } = reduce(\n reports,\n (accumulator, report) => {\n let keyName: string = 'no value';\n if (aggregatedBy && aggregatedBy in report) {\n keyName = report[aggregatedBy] as string;\n } else if (aggregatedBy === 'none') {\n keyName = 'Total';\n }\n\n if (!accumulator[keyName]) {\n accumulator[keyName] = {\n id: keyName,\n provider: report.provider,\n reports: {},\n forecast: {},\n } as {\n id: string;\n reports: { [key: string]: number };\n forecast?: { [key: string]: number };\n [key: string]: any;\n };\n\n if (aggregatedBy !== undefined) {\n accumulator[keyName][aggregatedBy] = keyName;\n }\n }\n\n aggregateReportsAndForecasts(accumulator, report, keyName);\n\n return accumulator;\n },\n {} as { [key: string]: Report },\n );\n return Object.values(aggregatedReports);\n};\n\nexport const getReportKeyAndValues = (reports: Report[] | undefined): { [key: string]: string[] } => {\n const excludedKeys = new Set(['id', 'reports', 'forecast']);\n const keyValueSets: { [key: string]: Set<string> } = {};\n reports?.forEach(report => {\n Object.keys(report).forEach(key => {\n if (!excludedKeys.has(key)) {\n if (keyValueSets[key] === undefined) {\n keyValueSets[key] = new Set<string>();\n }\n\n keyValueSets[key].add(report[key] as string);\n }\n });\n });\n\n const keyValues: { [key: string]: string[] } = {};\n Object.keys(keyValueSets).forEach((key: string) => {\n keyValues[key] = Array.from(keyValueSets[key]);\n keyValues[key].sort((a, b) => a.localeCompare(b));\n });\n return keyValues;\n};\n\nexport const extractProvider = (input: string): string | undefined => {\n let provider = undefined;\n if (input && input.indexOf('/') !== -1) {\n provider = input.split('/')[0];\n }\n\n return provider;\n};\n\nexport const extractAccountInfo = (input: string): { accountName: string; accountId?: string } => {\n // try to match format: accountName (accountId), e.g. aws-dev (123456789012)\n const regex = /^(.*?)\\s*\\(([^)]+)\\)$/;\n const match = input.match(regex);\n\n if (match) {\n const accountName = match[1];\n const accountId = match[2];\n return { accountName: accountName, accountId: accountId };\n }\n\n return { accountName: input };\n};\n\n// check if targetTag exists in tags\nexport function tagExists(tags: Tag[], targetTag: Tag): boolean {\n return tags.some(\n tag => tag.provider === targetTag.provider && tag.key === targetTag.key && tag.value === targetTag.value,\n );\n}\n\n// convert Tag array to (provider1:key1=value1 OR provider2:key2=value2) format\nexport const tagsToString = (tags: Tag[]): string => {\n if (tags.length === 0) {\n return '()';\n }\n\n const keyValuePairs = tags.map(tag => `${tag.provider}:${tag.key}=${tag.value}`);\n return `(${keyValuePairs.join(' OR ')})`;\n};\n\nexport const getAllReportTags = (reports: Report[]): string[] => {\n const tags = new Set<string>();\n const reservedKeys = new Set(['id', 'account', 'service', 'category', 'provider', 'reports', 'forecast']);\n reports.forEach(report => {\n Object.keys(report).forEach(key => {\n if (!reservedKeys.has(key)) {\n tags.add(key);\n }\n });\n });\n return Array.from(tags);\n};\n\nexport const getPreviousMonth = (month: string): string => {\n const date = parse(month, 'yyyy-MM', new Date());\n const previousMonth = subMonths(date, 1);\n return format(previousMonth, 'yyyy-MM');\n};\n\nexport const getPreviousDay = (day: string): string => {\n const date = parse(day, 'yyyy-MM-dd', new Date());\n const previousDay = subDays(date, 1);\n return format(previousDay, 'yyyy-MM-dd');\n};\n\nexport const getPeriodStrings = (granularity: string, startTime: Date, endTime: Date): string[] => {\n const result: string[] = [];\n const current = moment(startTime);\n\n while (current.isSameOrBefore(endTime) && current.isSameOrBefore(moment())) {\n if (granularity === 'monthly') {\n result.push(current.format('YYYY-MM'));\n current.add(1, 'months');\n } else {\n result.push(current.format('YYYY-MM-DD'));\n current.add(1, 'days');\n }\n }\n\n return result;\n};\n\nexport const formatCurrency = (number: number, currency?: string): string => {\n return new Intl.NumberFormat('en-US', {\n style: 'currency',\n currency: currency || 'USD',\n notation: 'compact',\n }).format(number);\n};\n\nexport interface BudgetAnalytics {\n yearToDateSpent: number;\n monthlyRunRate: number;\n projectedAnnualSpending: number;\n projectedCurrentMonthCost: number;\n budgetHealthStatus: 'healthy' | 'warning' | 'critical';\n budgetUtilizationPercent: number;\n targetMonthlySpending: number;\n monthsRemaining: number;\n averageMonthlySpending: number;\n spendingVelocity: number;\n confidenceRange: {\n low: number;\n high: number;\n };\n}\n\nexport const calculateBudgetAnalytics = (\n monthlyCosts: Record<string, number>,\n annualBudget: number,\n forecast?: number,\n): BudgetAnalytics => {\n const currentMonth = moment().month() + 1;\n const currentYear = moment().year();\n const daysIntoCurrentMonth = moment().date();\n const daysInCurrentMonth = moment().daysInMonth();\n let yearToDateSpent = 0;\n let projectedCurrentMonthCost = 0;\n const monthlySpending: number[] = [];\n for (let month = 1; month <= currentMonth; month++) {\n const monthKey = `${currentYear}-${month.toString().padStart(2, '0')}`;\n const monthCost = monthlyCosts[monthKey] || 0;\n\n if (month < currentMonth) {\n yearToDateSpent += monthCost;\n monthlySpending.push(monthCost);\n } else if (month === currentMonth) {\n projectedCurrentMonthCost = forecast ?? (monthCost / daysIntoCurrentMonth) * daysInCurrentMonth;\n yearToDateSpent += monthCost;\n monthlySpending.push(projectedCurrentMonthCost);\n }\n }\n\n const monthsRemaining = 12 - currentMonth + (1 - daysIntoCurrentMonth / daysInCurrentMonth);\n const averageMonthlySpending =\n monthlySpending.length > 0 ? monthlySpending.reduce((sum, cost) => sum + cost, 0) / monthlySpending.length : 0;\n\n const monthlyRunRate = monthlySpending.length > 0 ? monthlySpending[monthlySpending.length - 1] || 0 : 0;\n\n const projectedAnnualSpending = yearToDateSpent + averageMonthlySpending * monthsRemaining;\n\n const budgetUtilizationPercent = annualBudget > 0 ? (yearToDateSpent / annualBudget) * 100 : 0;\n const expectedUtilizationPercent = ((currentMonth - 1 + daysIntoCurrentMonth / daysInCurrentMonth) / 12) * 100;\n\n let budgetHealthStatus: 'healthy' | 'warning' | 'critical' = 'healthy';\n if (budgetUtilizationPercent > expectedUtilizationPercent + 20) {\n budgetHealthStatus = 'critical';\n } else if (budgetUtilizationPercent > expectedUtilizationPercent + 10) {\n budgetHealthStatus = 'warning';\n }\n\n const targetMonthlySpending = monthsRemaining > 0 ? (annualBudget - yearToDateSpent) / monthsRemaining : 0;\n\n const spendingVariance =\n monthlySpending.length > 1\n ? Math.sqrt(\n monthlySpending.reduce((sum, cost) => sum + Math.pow(cost - averageMonthlySpending, 2), 0) /\n (monthlySpending.length - 1),\n )\n : 0;\n\n const spendingVelocity =\n monthlySpending.length >= 2\n ? ((monthlySpending[monthlySpending.length - 1] - monthlySpending[monthlySpending.length - 2]) /\n monthlySpending[monthlySpending.length - 2]) *\n 100\n : 0;\n\n const confidenceRange = {\n low: Math.max(0, projectedAnnualSpending - spendingVariance * 2 * Math.sqrt(monthsRemaining)),\n high: projectedAnnualSpending + spendingVariance * 2 * Math.sqrt(monthsRemaining),\n };\n\n return {\n yearToDateSpent,\n monthlyRunRate,\n projectedAnnualSpending,\n projectedCurrentMonthCost,\n budgetHealthStatus,\n budgetUtilizationPercent,\n targetMonthlySpending,\n monthsRemaining,\n averageMonthlySpending,\n spendingVelocity,\n confidenceRange,\n };\n};\n"],"names":[],"mappings":"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"}
|