@composurecdk/budgets 0.5.1 → 0.7.0
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 +21 -12
- package/dist/budget-alarm-builder.d.ts +5 -2
- package/dist/budget-alarm-builder.d.ts.map +1 -1
- package/dist/budget-alarm-builder.js +8 -2
- package/dist/budget-alarm-builder.js.map +1 -1
- package/dist/budget-alarms.d.ts.map +1 -1
- package/dist/budget-alarms.js +2 -0
- package/dist/budget-alarms.js.map +1 -1
- package/dist/budget-builder.d.ts +25 -11
- package/dist/budget-builder.d.ts.map +1 -1
- package/dist/budget-builder.js +40 -12
- package/dist/budget-builder.js.map +1 -1
- package/dist/currency.d.ts +21 -0
- package/dist/currency.d.ts.map +1 -0
- package/dist/currency.js +35 -0
- package/dist/currency.js.map +1 -0
- package/dist/defaults.d.ts +14 -0
- package/dist/defaults.d.ts.map +1 -1
- package/dist/defaults.js +48 -0
- package/dist/defaults.js.map +1 -1
- package/dist/email.d.ts +28 -0
- package/dist/email.d.ts.map +1 -0
- package/dist/email.js +30 -0
- package/dist/email.js.map +1 -0
- package/dist/index.d.ts +3 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +2 -1
- package/dist/index.js.map +1 -1
- package/dist/notifications.d.ts +41 -13
- package/dist/notifications.d.ts.map +1 -1
- package/dist/notifications.js +12 -9
- package/dist/notifications.js.map +1 -1
- package/package.json +4 -3
package/README.md
CHANGED
|
@@ -7,12 +7,12 @@ This package provides a fluent builder for `AWS::Budgets::Budget` with well-arch
|
|
|
7
7
|
## Budget Builder
|
|
8
8
|
|
|
9
9
|
```ts
|
|
10
|
-
import { createBudgetBuilder } from "@composurecdk/budgets";
|
|
10
|
+
import { createBudgetBuilder, email } from "@composurecdk/budgets";
|
|
11
11
|
|
|
12
12
|
const budget = createBudgetBuilder()
|
|
13
13
|
.budgetName("AgentBudget")
|
|
14
|
-
.limit({ amount: 50
|
|
15
|
-
.notifyOnActual(100, "ops@example.com")
|
|
14
|
+
.limit({ amount: 50 })
|
|
15
|
+
.notifyOnActual(100, { emails: [email("ops@example.com")] })
|
|
16
16
|
.build(stack, "AgentBudget");
|
|
17
17
|
```
|
|
18
18
|
|
|
@@ -31,34 +31,43 @@ Every field on [CfnBudget.BudgetDataProperty](https://docs.aws.amazon.com/cdk/ap
|
|
|
31
31
|
|
|
32
32
|
### Notifications
|
|
33
33
|
|
|
34
|
-
|
|
34
|
+
Each notification takes a `NotifySubscribers` object with **at most one** `sns` topic and a list of validated `emails` — AWS Budgets caps every notification at 1 SNS subscriber plus up to 10 EMAIL subscribers. The shape encodes that constraint in the type system: passing two SNS topics is unrepresentable.
|
|
35
35
|
|
|
36
36
|
```ts
|
|
37
|
+
import { email } from "@composurecdk/budgets";
|
|
38
|
+
|
|
37
39
|
createBudgetBuilder()
|
|
38
40
|
.limit({ amount: 100 })
|
|
39
|
-
.notifyOnActual(80, "ops@example.com") // 80% ACTUAL → email
|
|
40
|
-
.notifyOnForecasted(
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
41
|
+
.notifyOnActual(80, { emails: [email("ops@example.com")] }) // 80% ACTUAL → email
|
|
42
|
+
.notifyOnForecasted(100, { sns: ref("alerts", (r) => r.topic) }) // 100% FORECASTED → SNS topic
|
|
43
|
+
.notifyOnActual(100, {
|
|
44
|
+
sns: killSwitchTopic,
|
|
45
|
+
emails: [email("oncall@example.com")],
|
|
46
|
+
}) // hard breach → automation + human
|
|
44
47
|
.addNotification({
|
|
45
48
|
notificationType: "ACTUAL",
|
|
46
49
|
threshold: 120,
|
|
47
50
|
thresholdType: "ABSOLUTE_VALUE",
|
|
48
|
-
subscribers: ["oncall@example.com"],
|
|
51
|
+
subscribers: { emails: [email("oncall@example.com")] },
|
|
49
52
|
});
|
|
50
53
|
```
|
|
51
54
|
|
|
52
|
-
|
|
55
|
+
Email addresses must be constructed via `email(string)`, which validates and brands the value — bare strings are rejected at compile time. The `sns` slot accepts an `ITopic` instance or a `Resolvable<ITopic>` reference to a topic owned by a sibling component.
|
|
53
56
|
|
|
54
57
|
### Recommended Thresholds
|
|
55
58
|
|
|
56
59
|
```ts
|
|
57
|
-
createBudgetBuilder()
|
|
60
|
+
createBudgetBuilder()
|
|
61
|
+
.limit({ amount: 50 })
|
|
62
|
+
.withRecommendedThresholds({ emails: [email("ops@example.com")] });
|
|
58
63
|
```
|
|
59
64
|
|
|
60
65
|
Applies the AWS Cost Optimization pillar defaults: `ACTUAL` at 80% and `FORECASTED` at 100%.
|
|
61
66
|
|
|
67
|
+
### Currency
|
|
68
|
+
|
|
69
|
+
`limit({ amount, unit })` validates `unit` against the AWS-Budgets-supported ISO 4217 set (`DEFAULT_BUDGET_CURRENCIES`). Typos like `"ZZZ"` throw at synth instead of mid-deploy. Because the synth context cannot see an account's billing currency, anything other than `"USD"` also emits a non-fatal warning (`@composurecdk/budgets:limit-currency`) — verify the configured unit matches your billing currency before deploying.
|
|
70
|
+
|
|
62
71
|
## Defaults
|
|
63
72
|
|
|
64
73
|
| Property | Default | Rationale |
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { type CfnBudget } from "aws-cdk-lib/aws-budgets";
|
|
2
2
|
import { type Alarm } from "aws-cdk-lib/aws-cloudwatch";
|
|
3
3
|
import { type IConstruct } from "constructs";
|
|
4
|
-
import {
|
|
4
|
+
import { COPY_STATE, type Lifecycle, type Resolvable } from "@composurecdk/core";
|
|
5
|
+
import { type ITaggedBuilder } from "@composurecdk/cloudformation";
|
|
5
6
|
import { AlarmDefinitionBuilder } from "@composurecdk/cloudwatch";
|
|
6
7
|
import type { BudgetAlarmConfig } from "./alarm-config.js";
|
|
7
8
|
import type { BudgetBuilderResult } from "./budget-builder.js";
|
|
@@ -54,7 +55,7 @@ export interface BudgetAlarmBuilderResult {
|
|
|
54
55
|
*
|
|
55
56
|
* @see {@link createBudgetAlarmBuilder}
|
|
56
57
|
*/
|
|
57
|
-
export type IBudgetAlarmBuilder =
|
|
58
|
+
export type IBudgetAlarmBuilder = ITaggedBuilder<BudgetAlarmBuilderProps, BudgetAlarmBuilder>;
|
|
58
59
|
/**
|
|
59
60
|
* Shared alarm-assembly used by both {@link createBudgetBuilder} (in its
|
|
60
61
|
* own stack) and {@link createBudgetAlarmBuilder} (typically in a separate
|
|
@@ -103,6 +104,8 @@ declare class BudgetAlarmBuilder implements Lifecycle<BudgetAlarmBuilderResult>
|
|
|
103
104
|
* live with the recommended one.
|
|
104
105
|
*/
|
|
105
106
|
addAlarm(key: string, configure: (alarm: AlarmDefinitionBuilder<CfnBudget>) => AlarmDefinitionBuilder<CfnBudget>): this;
|
|
107
|
+
/** @internal — see ADR-0005. */
|
|
108
|
+
[COPY_STATE](target: BudgetAlarmBuilder): void;
|
|
106
109
|
build(scope: IConstruct, id: string, context?: Record<string, object>): BudgetAlarmBuilderResult;
|
|
107
110
|
}
|
|
108
111
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budget-alarm-builder.d.ts","sourceRoot":"","sources":["../src/budget-alarm-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAExD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,
|
|
1
|
+
{"version":3,"file":"budget-alarm-builder.d.ts","sourceRoot":"","sources":["../src/budget-alarm-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,KAAK,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACzD,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,4BAA4B,CAAC;AAExD,OAAO,EAAE,KAAK,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAE,UAAU,EAAE,KAAK,SAAS,EAAW,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC1F,OAAO,EAAE,KAAK,cAAc,EAAiB,MAAM,8BAA8B,CAAC;AAElF,OAAO,EAAE,sBAAsB,EAAgB,MAAM,0BAA0B,CAAC;AAChF,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAE3D,OAAO,KAAK,EAAE,mBAAmB,EAAE,MAAM,qBAAqB,CAAC;AAE/D;;;;;;;;;;;GAWG;AACH,MAAM,WAAW,uBAAuB;IACtC;;;;;;;;;;;;;;OAcG;IACH,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAC;CAC/C;AAED;;GAEG;AACH,MAAM,WAAW,wBAAwB;IACvC;;;OAGG;IACH,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;CAC/B;AAED;;;;;;;;GAQG;AACH,MAAM,MAAM,mBAAmB,GAAG,cAAc,CAAC,uBAAuB,EAAE,kBAAkB,CAAC,CAAC;AAsB9F;;;;;;;;;;;;;GAaG;AACH,wBAAgB,iBAAiB,CAC/B,KAAK,EAAE,UAAU,EACjB,EAAE,EAAE,MAAM,EACV,MAAM,EAAE,IAAI,CAAC,mBAAmB,EAAE,QAAQ,CAAC,GAAG,SAAS,EACvD,OAAO,GAAE;IACP,iBAAiB,CAAC,EAAE,iBAAiB,GAAG,KAAK,CAAC;IAC9C,YAAY,CAAC,EAAE,sBAAsB,CAAC,SAAS,CAAC,EAAE,CAAC;CAC/C,GACL,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,CAoBvB;AAED,cAAM,kBAAmB,YAAW,SAAS,CAAC,wBAAwB,CAAC;;IACrE,KAAK,EAAE,OAAO,CAAC,uBAAuB,CAAC,CAAM;IAI7C;;;;;;;;;;;;;;OAcG;IACH,MAAM,CAAC,MAAM,EAAE,UAAU,CAAC,mBAAmB,CAAC,GAAG,IAAI;IAKrD;;;;;;;;;OASG;IACH,QAAQ,CACN,GAAG,EAAE,MAAM,EACX,SAAS,EAAE,CAAC,KAAK,EAAE,sBAAsB,CAAC,SAAS,CAAC,KAAK,sBAAsB,CAAC,SAAS,CAAC,GACzF,IAAI;IAKP,gCAAgC;IAChC,CAAC,UAAU,CAAC,CAAC,MAAM,EAAE,kBAAkB,GAAG,IAAI;IAK9C,KAAK,CAAC,KAAK,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAAG,wBAAwB;CASjG;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,wBAAgB,wBAAwB,IAAI,mBAAmB,CAE9D"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Annotations, Stack, Token } from "aws-cdk-lib";
|
|
2
|
-
import {
|
|
2
|
+
import { COPY_STATE, resolve } from "@composurecdk/core";
|
|
3
|
+
import { taggedBuilder } from "@composurecdk/cloudformation";
|
|
3
4
|
import { AlarmDefinitionBuilder, createAlarms } from "@composurecdk/cloudwatch";
|
|
4
5
|
import { resolveBudgetAlarmDefinitions } from "./budget-alarms.js";
|
|
5
6
|
/**
|
|
@@ -86,6 +87,11 @@ class BudgetAlarmBuilder {
|
|
|
86
87
|
this.#customAlarms.push(configure(new AlarmDefinitionBuilder(key)));
|
|
87
88
|
return this;
|
|
88
89
|
}
|
|
90
|
+
/** @internal — see ADR-0005. */
|
|
91
|
+
[COPY_STATE](target) {
|
|
92
|
+
target.#budget = this.#budget;
|
|
93
|
+
target.#customAlarms.push(...this.#customAlarms);
|
|
94
|
+
}
|
|
89
95
|
build(scope, id, context) {
|
|
90
96
|
const target = this.#budget ? resolve(this.#budget, context ?? {}) : undefined;
|
|
91
97
|
return {
|
|
@@ -134,6 +140,6 @@ class BudgetAlarmBuilder {
|
|
|
134
140
|
* budget from custom alarms via `.addAlarm()`.
|
|
135
141
|
*/
|
|
136
142
|
export function createBudgetAlarmBuilder() {
|
|
137
|
-
return
|
|
143
|
+
return taggedBuilder(BudgetAlarmBuilder);
|
|
138
144
|
}
|
|
139
145
|
//# sourceMappingURL=budget-alarm-builder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budget-alarm-builder.js","sourceRoot":"","sources":["../src/budget-alarm-builder.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAExD,OAAO,
|
|
1
|
+
{"version":3,"file":"budget-alarm-builder.js","sourceRoot":"","sources":["../src/budget-alarm-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budget-alarms.d.ts","sourceRoot":"","sources":["../src/budget-alarms.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;
|
|
1
|
+
{"version":3,"file":"budget-alarms.d.ts","sourceRoot":"","sources":["../src/budget-alarms.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,0BAA0B,CAAC;AAChE,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAK3D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,iBAAiB,GAAG,SAAS,GACpC,eAAe,EAAE,CA0BnB"}
|
package/dist/budget-alarms.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Duration } from "aws-cdk-lib";
|
|
2
2
|
import { ComparisonOperator, Metric, TreatMissingData } from "aws-cdk-lib/aws-cloudwatch";
|
|
3
|
+
import { assertValidBudgetCurrency } from "./currency.js";
|
|
3
4
|
const BILLING_METRIC_PERIOD = Duration.hours(6);
|
|
4
5
|
/**
|
|
5
6
|
* Resolves the recommended alarm configuration into fully-resolved
|
|
@@ -26,6 +27,7 @@ export function resolveBudgetAlarmDefinitions(config) {
|
|
|
26
27
|
return [];
|
|
27
28
|
const cfg = config.estimatedCharges;
|
|
28
29
|
const currency = cfg.currency ?? "USD";
|
|
30
|
+
assertValidBudgetCurrency(currency, `EstimatedChargesAlarmConfig: currency`);
|
|
29
31
|
return [
|
|
30
32
|
{
|
|
31
33
|
key: "estimatedCharges",
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budget-alarms.js","sourceRoot":"","sources":["../src/budget-alarms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;
|
|
1
|
+
{"version":3,"file":"budget-alarms.js","sourceRoot":"","sources":["../src/budget-alarms.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,EAAE,gBAAgB,EAAE,MAAM,4BAA4B,CAAC;AAG1F,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAE1D,MAAM,qBAAqB,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEhD;;;;;;;;;;;;;;;;;GAiBG;AACH,MAAM,UAAU,6BAA6B,CAC3C,MAAqC;IAErC,IAAI,MAAM,EAAE,OAAO,KAAK,KAAK;QAAE,OAAO,EAAE,CAAC;IACzC,IAAI,CAAC,MAAM,EAAE,gBAAgB;QAAE,OAAO,EAAE,CAAC;IAEzC,MAAM,GAAG,GAAG,MAAM,CAAC,gBAAgB,CAAC;IACpC,MAAM,QAAQ,GAAG,GAAG,CAAC,QAAQ,IAAI,KAAK,CAAC;IACvC,yBAAyB,CAAC,QAAQ,EAAE,uCAAuC,CAAC,CAAC;IAE7E,OAAO;QACL;YACE,GAAG,EAAE,kBAAkB;YACvB,MAAM,EAAE,IAAI,MAAM,CAAC;gBACjB,SAAS,EAAE,aAAa;gBACxB,UAAU,EAAE,kBAAkB;gBAC9B,aAAa,EAAE,EAAE,QAAQ,EAAE,QAAQ,EAAE;gBACrC,SAAS,EAAE,SAAS;gBACpB,MAAM,EAAE,qBAAqB;aAC9B,CAAC;YACF,SAAS,EAAE,GAAG,CAAC,SAAS;YACxB,kBAAkB,EAAE,kBAAkB,CAAC,sBAAsB;YAC7D,iBAAiB,EAAE,GAAG,CAAC,iBAAiB,IAAI,CAAC;YAC7C,iBAAiB,EAAE,GAAG,CAAC,iBAAiB,IAAI,CAAC;YAC7C,gBAAgB,EAAE,GAAG,CAAC,gBAAgB,IAAI,gBAAgB,CAAC,aAAa;YACxE,WAAW,EAAE,4CAA4C,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,QAAQ,kDAAkD;SAC7I;KACF,CAAC;AACJ,CAAC"}
|
package/dist/budget-builder.d.ts
CHANGED
|
@@ -2,10 +2,10 @@ import { CfnBudget } from "aws-cdk-lib/aws-budgets";
|
|
|
2
2
|
import { type Alarm } from "aws-cdk-lib/aws-cloudwatch";
|
|
3
3
|
import type { TopicPolicy } from "aws-cdk-lib/aws-sns";
|
|
4
4
|
import type { IConstruct } from "constructs";
|
|
5
|
-
import { type IBuilder, type Lifecycle } from "@composurecdk/core";
|
|
5
|
+
import { COPY_STATE, type IBuilder, type Lifecycle } from "@composurecdk/core";
|
|
6
6
|
import { AlarmDefinitionBuilder } from "@composurecdk/cloudwatch";
|
|
7
7
|
import type { BudgetAlarmConfig } from "./alarm-config.js";
|
|
8
|
-
import { type
|
|
8
|
+
import { type NotificationEntry, type NotifySubscribers } from "./notifications.js";
|
|
9
9
|
/**
|
|
10
10
|
* Spend limit for a cost or usage budget.
|
|
11
11
|
*/
|
|
@@ -15,6 +15,12 @@ export interface BudgetLimit {
|
|
|
15
15
|
/**
|
|
16
16
|
* Currency or usage unit. Defaults to
|
|
17
17
|
* {@link BUDGET_DEFAULTS.limitUnit} when omitted.
|
|
18
|
+
*
|
|
19
|
+
* For `COST` budgets, must be a recognised AWS Budgets currency
|
|
20
|
+
* (validated at synth — see {@link DEFAULT_BUDGET_CURRENCIES}). The
|
|
21
|
+
* builder also emits a non-fatal warning when this is anything other
|
|
22
|
+
* than `"USD"`, since the account's billing currency isn't visible
|
|
23
|
+
* at synth and a mismatch is rejected at deploy time.
|
|
18
24
|
*/
|
|
19
25
|
unit?: string;
|
|
20
26
|
}
|
|
@@ -108,9 +114,12 @@ export interface BudgetBuilderResult {
|
|
|
108
114
|
* ```ts
|
|
109
115
|
* createBudgetBuilder()
|
|
110
116
|
* .budgetName("AgentBudget")
|
|
111
|
-
* .limit({ amount: 50
|
|
112
|
-
* .notifyOnActual(100,
|
|
113
|
-
*
|
|
117
|
+
* .limit({ amount: 50 })
|
|
118
|
+
* .notifyOnActual(100, {
|
|
119
|
+
* emails: [email("ops@example.com")],
|
|
120
|
+
* sns: ref("alerts", r => r.topic),
|
|
121
|
+
* })
|
|
122
|
+
* .withRecommendedThresholds({ emails: [email("ops@example.com")] })
|
|
114
123
|
* .build(stack, "AgentBudget");
|
|
115
124
|
* ```
|
|
116
125
|
*/
|
|
@@ -124,18 +133,21 @@ declare class BudgetBuilder implements Lifecycle<BudgetBuilderResult> {
|
|
|
124
133
|
*
|
|
125
134
|
* @param thresholdPercent - Percentage of the budget limit (e.g. `80`).
|
|
126
135
|
* For absolute-value thresholds, use {@link addNotification} directly.
|
|
127
|
-
* @param subscribers -
|
|
128
|
-
*
|
|
136
|
+
* @param subscribers - Up to one SNS topic plus up to ten validated
|
|
137
|
+
* email addresses. AWS Budgets caps each notification at 1 SNS + up
|
|
138
|
+
* to 10 EMAIL subscribers.
|
|
129
139
|
*/
|
|
130
|
-
notifyOnActual(thresholdPercent: number,
|
|
140
|
+
notifyOnActual(thresholdPercent: number, subscribers: NotifySubscribers): this;
|
|
131
141
|
/**
|
|
132
142
|
* Add a notification that fires when FORECASTED spend crosses the
|
|
133
143
|
* given percentage of the budget limit.
|
|
134
144
|
*
|
|
135
145
|
* @param thresholdPercent - Percentage of the budget limit (e.g. `100`).
|
|
136
146
|
* For absolute-value thresholds, use {@link addNotification} directly.
|
|
147
|
+
* @param subscribers - Up to one SNS topic plus up to ten validated
|
|
148
|
+
* email addresses.
|
|
137
149
|
*/
|
|
138
|
-
notifyOnForecasted(thresholdPercent: number,
|
|
150
|
+
notifyOnForecasted(thresholdPercent: number, subscribers: NotifySubscribers): this;
|
|
139
151
|
/**
|
|
140
152
|
* Raw notification passthrough for callers that need the full
|
|
141
153
|
* CloudFormation surface (e.g. absolute-value thresholds).
|
|
@@ -148,11 +160,11 @@ declare class BudgetBuilder implements Lifecycle<BudgetBuilderResult> {
|
|
|
148
160
|
* - `FORECASTED` at 100% — trending-over-budget alert.
|
|
149
161
|
*
|
|
150
162
|
* Must be called with at least one subscriber; the same subscriber
|
|
151
|
-
*
|
|
163
|
+
* set is used for both thresholds.
|
|
152
164
|
*
|
|
153
165
|
* @see https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-best-practices.html
|
|
154
166
|
*/
|
|
155
|
-
withRecommendedThresholds(
|
|
167
|
+
withRecommendedThresholds(subscribers: NotifySubscribers): this;
|
|
156
168
|
/**
|
|
157
169
|
* Adds a custom CloudWatch alarm against the budget. The configure
|
|
158
170
|
* callback receives a fresh {@link AlarmDefinitionBuilder} pre-set with
|
|
@@ -168,6 +180,8 @@ declare class BudgetBuilder implements Lifecycle<BudgetBuilderResult> {
|
|
|
168
180
|
* {@link createBudgetAlarmBuilder} into a `us-east-1` stack.
|
|
169
181
|
*/
|
|
170
182
|
addAlarm(key: string, configure: (alarm: AlarmDefinitionBuilder<CfnBudget>) => AlarmDefinitionBuilder<CfnBudget>): this;
|
|
183
|
+
/** @internal — see ADR-0005. */
|
|
184
|
+
[COPY_STATE](target: BudgetBuilder): void;
|
|
171
185
|
build(scope: IConstruct, id: string, context?: Record<string, object>): BudgetBuilderResult;
|
|
172
186
|
}
|
|
173
187
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budget-builder.d.ts","sourceRoot":"","sources":["../src/budget-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAuB,MAAM,yBAAyB,CAAC;AACzE,OAAO,EAAE,KAAK,KAAK,EAAE,MAAM,4BAA4B,CAAC;AACxD,OAAO,KAAK,EAAU,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAC/D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAC7C,OAAO,EAAW,KAAK,QAAQ,EAAE,KAAK,SAAS,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"budget-builder.d.ts","sourceRoot":"","sources":["../src/budget-builder.ts"],"names":[],"mappings":"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"}
|
package/dist/budget-builder.js
CHANGED
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import { CfnBudget } from "aws-cdk-lib/aws-budgets";
|
|
2
|
-
import { Builder } from "@composurecdk/core";
|
|
2
|
+
import { Builder, COPY_STATE } from "@composurecdk/core";
|
|
3
3
|
import { AlarmDefinitionBuilder } from "@composurecdk/cloudwatch";
|
|
4
4
|
import { buildBudgetAlarms } from "./budget-alarm-builder.js";
|
|
5
|
+
import { assertValidBudgetCurrency, warnIfNonUsdCurrency } from "./currency.js";
|
|
5
6
|
import { BUDGET_DEFAULTS } from "./defaults.js";
|
|
6
7
|
import { resolveSubscribers, toCfnNotificationWithSubscribers, } from "./notifications.js";
|
|
7
8
|
import { createBudgetsTopicPolicies } from "./topic-policy.js";
|
|
9
|
+
const MAX_EMAILS_PER_NOTIFICATION = 10;
|
|
8
10
|
class BudgetBuilder {
|
|
9
11
|
props = {};
|
|
10
12
|
#notifications = [];
|
|
@@ -15,10 +17,11 @@ class BudgetBuilder {
|
|
|
15
17
|
*
|
|
16
18
|
* @param thresholdPercent - Percentage of the budget limit (e.g. `80`).
|
|
17
19
|
* For absolute-value thresholds, use {@link addNotification} directly.
|
|
18
|
-
* @param subscribers -
|
|
19
|
-
*
|
|
20
|
+
* @param subscribers - Up to one SNS topic plus up to ten validated
|
|
21
|
+
* email addresses. AWS Budgets caps each notification at 1 SNS + up
|
|
22
|
+
* to 10 EMAIL subscribers.
|
|
20
23
|
*/
|
|
21
|
-
notifyOnActual(thresholdPercent,
|
|
24
|
+
notifyOnActual(thresholdPercent, subscribers) {
|
|
22
25
|
return this.#addPercentageNotification("ACTUAL", thresholdPercent, subscribers);
|
|
23
26
|
}
|
|
24
27
|
/**
|
|
@@ -27,8 +30,10 @@ class BudgetBuilder {
|
|
|
27
30
|
*
|
|
28
31
|
* @param thresholdPercent - Percentage of the budget limit (e.g. `100`).
|
|
29
32
|
* For absolute-value thresholds, use {@link addNotification} directly.
|
|
33
|
+
* @param subscribers - Up to one SNS topic plus up to ten validated
|
|
34
|
+
* email addresses.
|
|
30
35
|
*/
|
|
31
|
-
notifyOnForecasted(thresholdPercent,
|
|
36
|
+
notifyOnForecasted(thresholdPercent, subscribers) {
|
|
32
37
|
return this.#addPercentageNotification("FORECASTED", thresholdPercent, subscribers);
|
|
33
38
|
}
|
|
34
39
|
/**
|
|
@@ -46,12 +51,12 @@ class BudgetBuilder {
|
|
|
46
51
|
* - `FORECASTED` at 100% — trending-over-budget alert.
|
|
47
52
|
*
|
|
48
53
|
* Must be called with at least one subscriber; the same subscriber
|
|
49
|
-
*
|
|
54
|
+
* set is used for both thresholds.
|
|
50
55
|
*
|
|
51
56
|
* @see https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-best-practices.html
|
|
52
57
|
*/
|
|
53
|
-
withRecommendedThresholds(
|
|
54
|
-
if (subscribers
|
|
58
|
+
withRecommendedThresholds(subscribers) {
|
|
59
|
+
if (!hasAnySubscriber(subscribers)) {
|
|
55
60
|
throw new Error(`BudgetBuilder: withRecommendedThresholds(...) must be called with at least one subscriber.`);
|
|
56
61
|
}
|
|
57
62
|
const { actualPercent, forecastedPercent } = BUDGET_DEFAULTS.recommendedThresholds;
|
|
@@ -76,6 +81,11 @@ class BudgetBuilder {
|
|
|
76
81
|
this.#customAlarms.push(configure(new AlarmDefinitionBuilder(key)));
|
|
77
82
|
return this;
|
|
78
83
|
}
|
|
84
|
+
/** @internal — see ADR-0005. */
|
|
85
|
+
[COPY_STATE](target) {
|
|
86
|
+
target.#notifications.push(...this.#notifications);
|
|
87
|
+
target.#customAlarms.push(...this.#customAlarms);
|
|
88
|
+
}
|
|
79
89
|
build(scope, id, context = {}) {
|
|
80
90
|
const { recommendedAlarms: alarmConfig, ...budgetProps } = this.props;
|
|
81
91
|
const budgetType = budgetProps.budgetType ?? BUDGET_DEFAULTS.budgetType;
|
|
@@ -84,7 +94,12 @@ class BudgetBuilder {
|
|
|
84
94
|
if (requiresLimit && !budgetProps.limit) {
|
|
85
95
|
throw new Error(`BudgetBuilder "${id}": limit({ amount, unit }) must be set for ${budgetType} budgets.`);
|
|
86
96
|
}
|
|
87
|
-
const
|
|
97
|
+
const limitUnit = budgetProps.limit?.unit ?? BUDGET_DEFAULTS.limitUnit;
|
|
98
|
+
if (budgetType === "COST" && budgetProps.limit) {
|
|
99
|
+
assertValidBudgetCurrency(limitUnit, `BudgetBuilder "${id}": limit unit`);
|
|
100
|
+
warnIfNonUsdCurrency(scope, limitUnit, `BudgetBuilder "${id}": limit unit`);
|
|
101
|
+
}
|
|
102
|
+
const { notificationsWithSubscribers, snsTopics } = this.#buildNotifications(id, context);
|
|
88
103
|
const budgetData = {
|
|
89
104
|
budgetName: budgetProps.budgetName,
|
|
90
105
|
budgetType,
|
|
@@ -93,7 +108,7 @@ class BudgetBuilder {
|
|
|
93
108
|
? {
|
|
94
109
|
budgetLimit: {
|
|
95
110
|
amount: budgetProps.limit.amount,
|
|
96
|
-
unit:
|
|
111
|
+
unit: limitUnit,
|
|
97
112
|
},
|
|
98
113
|
}
|
|
99
114
|
: {}),
|
|
@@ -113,16 +128,21 @@ class BudgetBuilder {
|
|
|
113
128
|
return { budget, topicPolicies, alarms };
|
|
114
129
|
}
|
|
115
130
|
#addPercentageNotification(notificationType, thresholdPercent, subscribers) {
|
|
116
|
-
if (subscribers
|
|
131
|
+
if (!hasAnySubscriber(subscribers)) {
|
|
117
132
|
throw new Error(`BudgetBuilder: ${notificationType} notification at ${String(thresholdPercent)}% requires at least one subscriber.`);
|
|
118
133
|
}
|
|
119
134
|
this.#notifications.push({ notificationType, threshold: thresholdPercent, subscribers });
|
|
120
135
|
return this;
|
|
121
136
|
}
|
|
122
|
-
#buildNotifications(context) {
|
|
137
|
+
#buildNotifications(id, context) {
|
|
123
138
|
const notificationsWithSubscribers = [];
|
|
124
139
|
const allSnsTopics = [];
|
|
125
140
|
for (const entry of this.#notifications) {
|
|
141
|
+
const emailCount = entry.subscribers.emails?.length ?? 0;
|
|
142
|
+
if (emailCount > MAX_EMAILS_PER_NOTIFICATION) {
|
|
143
|
+
throw new Error(`BudgetBuilder "${id}": ${describeNotification(entry)} has ${String(emailCount)} email subscribers; ` +
|
|
144
|
+
`AWS Budgets allows at most ${String(MAX_EMAILS_PER_NOTIFICATION)} email subscribers per notification (plus up to 1 SNS topic).`);
|
|
145
|
+
}
|
|
126
146
|
const resolved = resolveSubscribers(entry.subscribers, context);
|
|
127
147
|
notificationsWithSubscribers.push(toCfnNotificationWithSubscribers(entry, resolved.cfn));
|
|
128
148
|
allSnsTopics.push(...resolved.snsTopics);
|
|
@@ -130,10 +150,18 @@ class BudgetBuilder {
|
|
|
130
150
|
return { notificationsWithSubscribers, snsTopics: allSnsTopics };
|
|
131
151
|
}
|
|
132
152
|
}
|
|
153
|
+
function hasAnySubscriber(subscribers) {
|
|
154
|
+
return subscribers.sns !== undefined || (subscribers.emails?.length ?? 0) > 0;
|
|
155
|
+
}
|
|
156
|
+
function describeNotification(entry) {
|
|
157
|
+
const unit = (entry.thresholdType ?? "PERCENTAGE") === "PERCENTAGE" ? "%" : "";
|
|
158
|
+
return `notification ${entry.notificationType} @ ${String(entry.threshold)}${unit}`;
|
|
159
|
+
}
|
|
133
160
|
/**
|
|
134
161
|
* Creates a new {@link IBudgetBuilder} for configuring an AWS Budget.
|
|
135
162
|
*/
|
|
136
163
|
export function createBudgetBuilder() {
|
|
164
|
+
// eslint-disable-next-line composurecdk/builder-must-be-tagged -- AWS::Budgets::Budget has no Tags property
|
|
137
165
|
return Builder(BudgetBuilder);
|
|
138
166
|
}
|
|
139
167
|
//# sourceMappingURL=budget-builder.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"budget-builder.js","sourceRoot":"","sources":["../src/budget-builder.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAuB,MAAM,yBAAyB,CAAC;AAIzE,OAAO,EAAE,OAAO,EAAiC,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"budget-builder.js","sourceRoot":"","sources":["../src/budget-builder.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { IConstruct } from "constructs";
|
|
2
|
+
/**
|
|
3
|
+
* Throws if `unit` is not in {@link DEFAULT_BUDGET_CURRENCIES}.
|
|
4
|
+
*
|
|
5
|
+
* `context` is woven into the message (e.g. `BudgetBuilder "X": limit
|
|
6
|
+
* unit ...`) so callers can blame the right field. Catches typos like
|
|
7
|
+
* `"USDD"` or `"ZZZ"` at synth instead of mid-deploy.
|
|
8
|
+
*/
|
|
9
|
+
export declare function assertValidBudgetCurrency(unit: string, context: string): void;
|
|
10
|
+
/**
|
|
11
|
+
* Annotates `scope` with a non-fatal warning when `unit` is anything
|
|
12
|
+
* other than `USD`. The synth context cannot see an account's billing
|
|
13
|
+
* currency, and AWS Budgets rejects `BudgetLimit.Unit` values that
|
|
14
|
+
* don't match it — so a non-USD configuration deserves a "make sure
|
|
15
|
+
* this matches your billing currency" nudge.
|
|
16
|
+
*
|
|
17
|
+
* Short-circuits on unresolved tokens so env-agnostic stacks aren't
|
|
18
|
+
* spammed.
|
|
19
|
+
*/
|
|
20
|
+
export declare function warnIfNonUsdCurrency(scope: IConstruct, unit: string, context: string): void;
|
|
21
|
+
//# sourceMappingURL=currency.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"currency.d.ts","sourceRoot":"","sources":["../src/currency.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAG7C;;;;;;GAMG;AACH,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAM7E;AAED;;;;;;;;;GASG;AACH,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,UAAU,EAAE,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,IAAI,CAS3F"}
|
package/dist/currency.js
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { Annotations, Token } from "aws-cdk-lib";
|
|
2
|
+
import { DEFAULT_BUDGET_CURRENCIES } from "./defaults.js";
|
|
3
|
+
/**
|
|
4
|
+
* Throws if `unit` is not in {@link DEFAULT_BUDGET_CURRENCIES}.
|
|
5
|
+
*
|
|
6
|
+
* `context` is woven into the message (e.g. `BudgetBuilder "X": limit
|
|
7
|
+
* unit ...`) so callers can blame the right field. Catches typos like
|
|
8
|
+
* `"USDD"` or `"ZZZ"` at synth instead of mid-deploy.
|
|
9
|
+
*/
|
|
10
|
+
export function assertValidBudgetCurrency(unit, context) {
|
|
11
|
+
if (DEFAULT_BUDGET_CURRENCIES.includes(unit))
|
|
12
|
+
return;
|
|
13
|
+
throw new Error(`${context}: "${unit}" is not a recognised AWS Budgets currency code. ` +
|
|
14
|
+
`Expected one of: ${DEFAULT_BUDGET_CURRENCIES.join(", ")}.`);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* Annotates `scope` with a non-fatal warning when `unit` is anything
|
|
18
|
+
* other than `USD`. The synth context cannot see an account's billing
|
|
19
|
+
* currency, and AWS Budgets rejects `BudgetLimit.Unit` values that
|
|
20
|
+
* don't match it — so a non-USD configuration deserves a "make sure
|
|
21
|
+
* this matches your billing currency" nudge.
|
|
22
|
+
*
|
|
23
|
+
* Short-circuits on unresolved tokens so env-agnostic stacks aren't
|
|
24
|
+
* spammed.
|
|
25
|
+
*/
|
|
26
|
+
export function warnIfNonUsdCurrency(scope, unit, context) {
|
|
27
|
+
if (Token.isUnresolved(unit))
|
|
28
|
+
return;
|
|
29
|
+
if (unit === "USD")
|
|
30
|
+
return;
|
|
31
|
+
Annotations.of(scope).addWarningV2("@composurecdk/budgets:limit-currency", `${context}: currency "${unit}" must match the account's billing currency or AWS Budgets ` +
|
|
32
|
+
`will reject the request at deploy time. Most accounts default to USD; verify yours and ` +
|
|
33
|
+
`suppress this warning if intentional.`);
|
|
34
|
+
}
|
|
35
|
+
//# sourceMappingURL=currency.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"currency.js","sourceRoot":"","sources":["../src/currency.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,KAAK,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAE1D;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CAAC,IAAY,EAAE,OAAe;IACrE,IAAI,yBAAyB,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO;IACrD,MAAM,IAAI,KAAK,CACb,GAAG,OAAO,MAAM,IAAI,mDAAmD;QACrE,oBAAoB,yBAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC9D,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,MAAM,UAAU,oBAAoB,CAAC,KAAiB,EAAE,IAAY,EAAE,OAAe;IACnF,IAAI,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC;QAAE,OAAO;IACrC,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO;IAC3B,WAAW,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,YAAY,CAChC,sCAAsC,EACtC,GAAG,OAAO,eAAe,IAAI,6DAA6D;QACxF,yFAAyF;QACzF,uCAAuC,CAC1C,CAAC;AACJ,CAAC"}
|
package/dist/defaults.d.ts
CHANGED
|
@@ -40,4 +40,18 @@ export declare const BUDGET_DEFAULTS: {
|
|
|
40
40
|
forecastedPercent: number;
|
|
41
41
|
};
|
|
42
42
|
};
|
|
43
|
+
/**
|
|
44
|
+
* ISO 4217 currency codes accepted by AWS Budgets for `COST` budgets'
|
|
45
|
+
* `BudgetLimit.Unit` and the `EstimatedCharges` alarm's `Currency`
|
|
46
|
+
* dimension. Sourced from the AWS Billing supported-currencies list.
|
|
47
|
+
*
|
|
48
|
+
* The synth context cannot see an account's billing currency, so the
|
|
49
|
+
* builder uses this set for shape validation only — a hard error on
|
|
50
|
+
* anything outside it (catches typos like `"ZZZ"`/`"USDD"`) — and emits
|
|
51
|
+
* a soft warning when the configured unit is anything other than `USD`,
|
|
52
|
+
* since most accounts default to USD billing.
|
|
53
|
+
*
|
|
54
|
+
* @see https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/manage-account-payment.html
|
|
55
|
+
*/
|
|
56
|
+
export declare const DEFAULT_BUDGET_CURRENCIES: readonly string[];
|
|
43
57
|
//# sourceMappingURL=defaults.d.ts.map
|
package/dist/defaults.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,eAAe;IAC1B;;;;OAIG;;IAGH;;;;;OAKG;;IAGH;;;;;OAKG;;IAGH;;;;;;;;;OASG;;;;;CAKJ,CAAC"}
|
|
1
|
+
{"version":3,"file":"defaults.d.ts","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,eAAO,MAAM,eAAe;IAC1B;;;;OAIG;;IAGH;;;;;OAKG;;IAGH;;;;;OAKG;;IAGH;;;;;;;;;OASG;;;;;CAKJ,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAkCtD,CAAC"}
|
package/dist/defaults.js
CHANGED
|
@@ -40,4 +40,52 @@ export const BUDGET_DEFAULTS = {
|
|
|
40
40
|
forecastedPercent: 100,
|
|
41
41
|
},
|
|
42
42
|
};
|
|
43
|
+
/**
|
|
44
|
+
* ISO 4217 currency codes accepted by AWS Budgets for `COST` budgets'
|
|
45
|
+
* `BudgetLimit.Unit` and the `EstimatedCharges` alarm's `Currency`
|
|
46
|
+
* dimension. Sourced from the AWS Billing supported-currencies list.
|
|
47
|
+
*
|
|
48
|
+
* The synth context cannot see an account's billing currency, so the
|
|
49
|
+
* builder uses this set for shape validation only — a hard error on
|
|
50
|
+
* anything outside it (catches typos like `"ZZZ"`/`"USDD"`) — and emits
|
|
51
|
+
* a soft warning when the configured unit is anything other than `USD`,
|
|
52
|
+
* since most accounts default to USD billing.
|
|
53
|
+
*
|
|
54
|
+
* @see https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/manage-account-payment.html
|
|
55
|
+
*/
|
|
56
|
+
export const DEFAULT_BUDGET_CURRENCIES = [
|
|
57
|
+
"AED",
|
|
58
|
+
"ARS",
|
|
59
|
+
"AUD",
|
|
60
|
+
"BRL",
|
|
61
|
+
"CAD",
|
|
62
|
+
"CHF",
|
|
63
|
+
"CLP",
|
|
64
|
+
"CNY",
|
|
65
|
+
"COP",
|
|
66
|
+
"CZK",
|
|
67
|
+
"DKK",
|
|
68
|
+
"EUR",
|
|
69
|
+
"GBP",
|
|
70
|
+
"HKD",
|
|
71
|
+
"IDR",
|
|
72
|
+
"ILS",
|
|
73
|
+
"INR",
|
|
74
|
+
"JPY",
|
|
75
|
+
"KRW",
|
|
76
|
+
"MXN",
|
|
77
|
+
"MYR",
|
|
78
|
+
"NOK",
|
|
79
|
+
"NZD",
|
|
80
|
+
"PLN",
|
|
81
|
+
"RUB",
|
|
82
|
+
"SAR",
|
|
83
|
+
"SEK",
|
|
84
|
+
"SGD",
|
|
85
|
+
"THB",
|
|
86
|
+
"TRY",
|
|
87
|
+
"TWD",
|
|
88
|
+
"USD",
|
|
89
|
+
"ZAR",
|
|
90
|
+
];
|
|
43
91
|
//# sourceMappingURL=defaults.js.map
|
package/dist/defaults.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B;;;;OAIG;IACH,UAAU,EAAE,MAAe;IAE3B;;;;;OAKG;IACH,QAAQ,EAAE,SAAkB;IAE5B;;;;;OAKG;IACH,SAAS,EAAE,KAAK;IAEhB;;;;;;;;;OASG;IACH,qBAAqB,EAAE;QACrB,aAAa,EAAE,EAAE;QACjB,iBAAiB,EAAE,GAAG;KACvB;CACF,CAAC"}
|
|
1
|
+
{"version":3,"file":"defaults.js","sourceRoot":"","sources":["../src/defaults.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AACH,MAAM,CAAC,MAAM,eAAe,GAAG;IAC7B;;;;OAIG;IACH,UAAU,EAAE,MAAe;IAE3B;;;;;OAKG;IACH,QAAQ,EAAE,SAAkB;IAE5B;;;;;OAKG;IACH,SAAS,EAAE,KAAK;IAEhB;;;;;;;;;OASG;IACH,qBAAqB,EAAE;QACrB,aAAa,EAAE,EAAE;QACjB,iBAAiB,EAAE,GAAG;KACvB;CACF,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,MAAM,CAAC,MAAM,yBAAyB,GAAsB;IAC1D,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;IACL,KAAK;CACN,CAAC"}
|
package/dist/email.d.ts
ADDED
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
declare const emailBrand: unique symbol;
|
|
2
|
+
/**
|
|
3
|
+
* A validated email address suitable for use as a budget notification
|
|
4
|
+
* subscriber. Construct via {@link email}; the brand prevents bare
|
|
5
|
+
* strings from being passed where an `Email` is required, ensuring the
|
|
6
|
+
* value has been syntactically validated and length-checked against
|
|
7
|
+
* AWS Budgets' per-subscriber limit.
|
|
8
|
+
*/
|
|
9
|
+
export type Email = string & {
|
|
10
|
+
readonly [emailBrand]: true;
|
|
11
|
+
};
|
|
12
|
+
/**
|
|
13
|
+
* Validates and brands a string as an {@link Email}.
|
|
14
|
+
*
|
|
15
|
+
* The pattern intentionally errs on the side of acceptance — anything
|
|
16
|
+
* obviously not an email (whitespace, missing `@`, missing TLD) is
|
|
17
|
+
* rejected, but any address AWS Budgets will plausibly accept passes.
|
|
18
|
+
* The 50-char cap matches the Budgets API's documented per-subscriber
|
|
19
|
+
* limit.
|
|
20
|
+
*
|
|
21
|
+
* @throws If the input is empty, exceeds 50 characters, or doesn't
|
|
22
|
+
* contain `local@domain.tld`.
|
|
23
|
+
*
|
|
24
|
+
* @see https://docs.aws.amazon.com/aws-cost-management/latest/APIReference/API_budgets_Subscriber.html
|
|
25
|
+
*/
|
|
26
|
+
export declare function email(input: string): Email;
|
|
27
|
+
export {};
|
|
28
|
+
//# sourceMappingURL=email.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email.d.ts","sourceRoot":"","sources":["../src/email.ts"],"names":[],"mappings":"AAAA,OAAO,CAAC,MAAM,UAAU,EAAE,OAAO,MAAM,CAAC;AAExC;;;;;;GAMG;AACH,MAAM,MAAM,KAAK,GAAG,MAAM,GAAG;IAAE,QAAQ,CAAC,CAAC,UAAU,CAAC,EAAE,IAAI,CAAA;CAAE,CAAC;AAK7D;;;;;;;;;;;;;GAaG;AACH,wBAAgB,KAAK,CAAC,KAAK,EAAE,MAAM,GAAG,KAAK,CAc1C"}
|
package/dist/email.js
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
const MAX_LEN = 50;
|
|
2
|
+
const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
3
|
+
/**
|
|
4
|
+
* Validates and brands a string as an {@link Email}.
|
|
5
|
+
*
|
|
6
|
+
* The pattern intentionally errs on the side of acceptance — anything
|
|
7
|
+
* obviously not an email (whitespace, missing `@`, missing TLD) is
|
|
8
|
+
* rejected, but any address AWS Budgets will plausibly accept passes.
|
|
9
|
+
* The 50-char cap matches the Budgets API's documented per-subscriber
|
|
10
|
+
* limit.
|
|
11
|
+
*
|
|
12
|
+
* @throws If the input is empty, exceeds 50 characters, or doesn't
|
|
13
|
+
* contain `local@domain.tld`.
|
|
14
|
+
*
|
|
15
|
+
* @see https://docs.aws.amazon.com/aws-cost-management/latest/APIReference/API_budgets_Subscriber.html
|
|
16
|
+
*/
|
|
17
|
+
export function email(input) {
|
|
18
|
+
const trimmed = input.trim();
|
|
19
|
+
if (trimmed.length === 0) {
|
|
20
|
+
throw new Error("email cannot be empty");
|
|
21
|
+
}
|
|
22
|
+
if (trimmed.length > MAX_LEN) {
|
|
23
|
+
throw new Error(`email exceeds ${String(MAX_LEN)} chars (AWS Budgets per-subscriber limit): "${trimmed}"`);
|
|
24
|
+
}
|
|
25
|
+
if (!EMAIL_REGEX.test(trimmed)) {
|
|
26
|
+
throw new Error(`invalid email address: "${trimmed}"`);
|
|
27
|
+
}
|
|
28
|
+
return trimmed;
|
|
29
|
+
}
|
|
30
|
+
//# sourceMappingURL=email.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"email.js","sourceRoot":"","sources":["../src/email.ts"],"names":[],"mappings":"AAWA,MAAM,OAAO,GAAG,EAAE,CAAC;AACnB,MAAM,WAAW,GAAG,4BAA4B,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,KAAK,CAAC,KAAa;IACjC,MAAM,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,CAAC;IAC7B,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACzB,MAAM,IAAI,KAAK,CAAC,uBAAuB,CAAC,CAAC;IAC3C,CAAC;IACD,IAAI,OAAO,CAAC,MAAM,GAAG,OAAO,EAAE,CAAC;QAC7B,MAAM,IAAI,KAAK,CACb,iBAAiB,MAAM,CAAC,OAAO,CAAC,+CAA+C,OAAO,GAAG,CAC1F,CAAC;IACJ,CAAC;IACD,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,2BAA2B,OAAO,GAAG,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,OAAgB,CAAC;AAC1B,CAAC"}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
export { createBudgetBuilder, type IBudgetBuilder, type BudgetBuilderProps, type BudgetBuilderResult, type BudgetLimit, } from "./budget-builder.js";
|
|
2
2
|
export { createBudgetAlarmBuilder, type IBudgetAlarmBuilder, type BudgetAlarmBuilderProps, type BudgetAlarmBuilderResult, } from "./budget-alarm-builder.js";
|
|
3
|
-
export { BUDGET_DEFAULTS } from "./defaults.js";
|
|
3
|
+
export { BUDGET_DEFAULTS, DEFAULT_BUDGET_CURRENCIES } from "./defaults.js";
|
|
4
4
|
export { type BudgetAlarmConfig, type EstimatedChargesAlarmConfig } from "./alarm-config.js";
|
|
5
5
|
export { createBudgetsTopicPolicies } from "./topic-policy.js";
|
|
6
|
-
export {
|
|
6
|
+
export { email, type Email } from "./email.js";
|
|
7
|
+
export { resolveSubscribers, toCfnNotificationWithSubscribers, type NotificationEntry, type NotificationType, type NotifySubscribers, type ResolvedSubscribers, } from "./notifications.js";
|
|
7
8
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,WAAW,GACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,GAC9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,kBAAkB,EACvB,KAAK,mBAAmB,EACxB,KAAK,WAAW,GACjB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,wBAAwB,EACxB,KAAK,mBAAmB,EACxB,KAAK,uBAAuB,EAC5B,KAAK,wBAAwB,GAC9B,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAC3E,OAAO,EAAE,KAAK,iBAAiB,EAAE,KAAK,2BAA2B,EAAE,MAAM,mBAAmB,CAAC;AAC7F,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAE,KAAK,KAAK,EAAE,MAAM,YAAY,CAAC;AAC/C,OAAO,EACL,kBAAkB,EAClB,gCAAgC,EAChC,KAAK,iBAAiB,EACtB,KAAK,gBAAgB,EACrB,KAAK,iBAAiB,EACtB,KAAK,mBAAmB,GACzB,MAAM,oBAAoB,CAAC"}
|
package/dist/index.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export { createBudgetBuilder, } from "./budget-builder.js";
|
|
2
2
|
export { createBudgetAlarmBuilder, } from "./budget-alarm-builder.js";
|
|
3
|
-
export { BUDGET_DEFAULTS } from "./defaults.js";
|
|
3
|
+
export { BUDGET_DEFAULTS, DEFAULT_BUDGET_CURRENCIES } from "./defaults.js";
|
|
4
4
|
export { createBudgetsTopicPolicies } from "./topic-policy.js";
|
|
5
|
+
export { email } from "./email.js";
|
|
5
6
|
export { resolveSubscribers, toCfnNotificationWithSubscribers, } from "./notifications.js";
|
|
6
7
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,GAKpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,wBAAwB,GAIzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,eAAe,CAAC;
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,mBAAmB,GAKpB,MAAM,qBAAqB,CAAC;AAC7B,OAAO,EACL,wBAAwB,GAIzB,MAAM,2BAA2B,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,yBAAyB,EAAE,MAAM,eAAe,CAAC;AAE3E,OAAO,EAAE,0BAA0B,EAAE,MAAM,mBAAmB,CAAC;AAC/D,OAAO,EAAE,KAAK,EAAc,MAAM,YAAY,CAAC;AAC/C,OAAO,EACL,kBAAkB,EAClB,gCAAgC,GAKjC,MAAM,oBAAoB,CAAC"}
|
package/dist/notifications.d.ts
CHANGED
|
@@ -1,11 +1,37 @@
|
|
|
1
1
|
import { CfnBudget } from "aws-cdk-lib/aws-budgets";
|
|
2
2
|
import type { ITopic } from "aws-cdk-lib/aws-sns";
|
|
3
3
|
import { type Resolvable } from "@composurecdk/core";
|
|
4
|
+
import type { Email } from "./email.js";
|
|
4
5
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
6
|
+
* Subscribers attached to a budget notification.
|
|
7
|
+
*
|
|
8
|
+
* AWS Budgets enforces an asymmetric per-notification subscriber rule
|
|
9
|
+
* that CloudFormation does not model:
|
|
10
|
+
*
|
|
11
|
+
* - up to 10 subscribers per notification
|
|
12
|
+
* - **at most one** with `SubscriptionType=SNS`
|
|
13
|
+
* - the remainder must be `EMAIL`
|
|
14
|
+
*
|
|
15
|
+
* This shape encodes that constraint in the type system: `sns` is
|
|
16
|
+
* singular, so passing two SNS topics is unrepresentable. The
|
|
17
|
+
* combined-count cap is enforced at synth time.
|
|
18
|
+
*
|
|
19
|
+
* @see https://docs.aws.amazon.com/aws-cost-management/latest/APIReference/API_budgets_NotificationWithSubscribers.html
|
|
7
20
|
*/
|
|
8
|
-
export
|
|
21
|
+
export interface NotifySubscribers {
|
|
22
|
+
/**
|
|
23
|
+
* Optional SNS topic to publish notifications to. AWS Budgets allows
|
|
24
|
+
* at most one SNS subscriber per notification; route fan-out by
|
|
25
|
+
* adding additional subscriptions to this single topic.
|
|
26
|
+
*/
|
|
27
|
+
sns?: ITopic | Resolvable<ITopic>;
|
|
28
|
+
/**
|
|
29
|
+
* Optional list of validated email addresses. Construct each value
|
|
30
|
+
* via {@link email}; bare strings are rejected at compile time. The
|
|
31
|
+
* combined `sns` + `emails` count must be ≤ 10.
|
|
32
|
+
*/
|
|
33
|
+
emails?: Email[];
|
|
34
|
+
}
|
|
9
35
|
/**
|
|
10
36
|
* Which side of spend a notification triggers on.
|
|
11
37
|
*
|
|
@@ -31,27 +57,29 @@ export interface NotificationEntry {
|
|
|
31
57
|
* absolute amount when `thresholdType` is `ABSOLUTE_VALUE`.
|
|
32
58
|
*/
|
|
33
59
|
threshold: number;
|
|
34
|
-
subscribers:
|
|
60
|
+
subscribers: NotifySubscribers;
|
|
35
61
|
comparisonOperator?: "GREATER_THAN" | "LESS_THAN" | "EQUAL_TO";
|
|
36
62
|
thresholdType?: "PERCENTAGE" | "ABSOLUTE_VALUE";
|
|
37
63
|
}
|
|
38
64
|
/**
|
|
39
|
-
* Resolved
|
|
40
|
-
*
|
|
41
|
-
*
|
|
42
|
-
* `AWS::SNS::TopicPolicy` entries granting `budgets.amazonaws.com`
|
|
43
|
-
* permission to publish.
|
|
65
|
+
* Resolved subscribers in the CloudFormation shape required by
|
|
66
|
+
* `AWS::Budgets::Budget`, plus any SNS topic referenced (so the caller
|
|
67
|
+
* can create matching `AWS::SNS::TopicPolicy` grants).
|
|
44
68
|
*/
|
|
45
69
|
export interface ResolvedSubscribers {
|
|
46
70
|
cfn: CfnBudget.SubscriberProperty[];
|
|
47
71
|
snsTopics: ITopic[];
|
|
48
72
|
}
|
|
49
73
|
/**
|
|
50
|
-
* Resolve a
|
|
51
|
-
*
|
|
52
|
-
*
|
|
74
|
+
* Resolve a {@link NotifySubscribers} into the CloudFormation shape for
|
|
75
|
+
* `AWS::Budgets::Budget`'s `Subscribers` array, plus any SNS topic
|
|
76
|
+
* referenced so the caller can create a matching topic policy.
|
|
77
|
+
*
|
|
78
|
+
* The SNS subscriber (if any) is emitted first, followed by emails in
|
|
79
|
+
* declaration order — the order is not load-bearing, but stable output
|
|
80
|
+
* keeps test snapshots steady.
|
|
53
81
|
*/
|
|
54
|
-
export declare function resolveSubscribers(subscribers:
|
|
82
|
+
export declare function resolveSubscribers(subscribers: NotifySubscribers, context: Record<string, object>): ResolvedSubscribers;
|
|
55
83
|
/**
|
|
56
84
|
* Convert a {@link NotificationEntry} plus resolved subscribers into the
|
|
57
85
|
* CloudFormation `NotificationWithSubscribersProperty` shape.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAW,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"notifications.d.ts","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,yBAAyB,CAAC;AACpD,OAAO,KAAK,EAAE,MAAM,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,EAAW,KAAK,UAAU,EAAE,MAAM,oBAAoB,CAAC;AAC9D,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,YAAY,CAAC;AAExC;;;;;;;;;;;;;;;GAeG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;;OAIG;IACH,GAAG,CAAC,EAAE,MAAM,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC;IAClC;;;;OAIG;IACH,MAAM,CAAC,EAAE,KAAK,EAAE,CAAC;CAClB;AAED;;;;;;GAMG;AACH,MAAM,MAAM,gBAAgB,GAAG,QAAQ,GAAG,YAAY,CAAC;AAEvD;;;;;;;;GAQG;AACH,MAAM,WAAW,iBAAiB;IAChC,gBAAgB,EAAE,gBAAgB,CAAC;IACnC;;;;OAIG;IACH,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,iBAAiB,CAAC;IAC/B,kBAAkB,CAAC,EAAE,cAAc,GAAG,WAAW,GAAG,UAAU,CAAC;IAC/D,aAAa,CAAC,EAAE,YAAY,GAAG,gBAAgB,CAAC;CACjD;AAED;;;;GAIG;AACH,MAAM,WAAW,mBAAmB;IAClC,GAAG,EAAE,SAAS,CAAC,kBAAkB,EAAE,CAAC;IACpC,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB;AAED;;;;;;;;GAQG;AACH,wBAAgB,kBAAkB,CAChC,WAAW,EAAE,iBAAiB,EAC9B,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,GAC9B,mBAAmB,CAerB;AAED;;;GAGG;AACH,wBAAgB,gCAAgC,CAC9C,KAAK,EAAE,iBAAiB,EACxB,mBAAmB,EAAE,SAAS,CAAC,kBAAkB,EAAE,GAClD,SAAS,CAAC,mCAAmC,CAU/C"}
|
package/dist/notifications.js
CHANGED
|
@@ -1,21 +1,24 @@
|
|
|
1
1
|
import { resolve } from "@composurecdk/core";
|
|
2
2
|
/**
|
|
3
|
-
* Resolve a
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Resolve a {@link NotifySubscribers} into the CloudFormation shape for
|
|
4
|
+
* `AWS::Budgets::Budget`'s `Subscribers` array, plus any SNS topic
|
|
5
|
+
* referenced so the caller can create a matching topic policy.
|
|
6
|
+
*
|
|
7
|
+
* The SNS subscriber (if any) is emitted first, followed by emails in
|
|
8
|
+
* declaration order — the order is not load-bearing, but stable output
|
|
9
|
+
* keeps test snapshots steady.
|
|
6
10
|
*/
|
|
7
11
|
export function resolveSubscribers(subscribers, context) {
|
|
8
12
|
const cfn = [];
|
|
9
13
|
const snsTopics = [];
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
cfn.push({ address: subscriber, subscriptionType: "EMAIL" });
|
|
13
|
-
continue;
|
|
14
|
-
}
|
|
15
|
-
const topic = resolve(subscriber, context);
|
|
14
|
+
if (subscribers.sns !== undefined) {
|
|
15
|
+
const topic = resolve(subscribers.sns, context);
|
|
16
16
|
cfn.push({ address: topic.topicArn, subscriptionType: "SNS" });
|
|
17
17
|
snsTopics.push(topic);
|
|
18
18
|
}
|
|
19
|
+
for (const address of subscribers.emails ?? []) {
|
|
20
|
+
cfn.push({ address, subscriptionType: "EMAIL" });
|
|
21
|
+
}
|
|
19
22
|
return { cfn, snsTopics };
|
|
20
23
|
}
|
|
21
24
|
/**
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAmB,MAAM,oBAAoB,CAAC;
|
|
1
|
+
{"version":3,"file":"notifications.js","sourceRoot":"","sources":["../src/notifications.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,OAAO,EAAmB,MAAM,oBAAoB,CAAC;AA2E9D;;;;;;;;GAQG;AACH,MAAM,UAAU,kBAAkB,CAChC,WAA8B,EAC9B,OAA+B;IAE/B,MAAM,GAAG,GAAmC,EAAE,CAAC;IAC/C,MAAM,SAAS,GAAa,EAAE,CAAC;IAE/B,IAAI,WAAW,CAAC,GAAG,KAAK,SAAS,EAAE,CAAC;QAClC,MAAM,KAAK,GAAG,OAAO,CAAC,WAAW,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC;QAChD,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,KAAK,CAAC,QAAQ,EAAE,gBAAgB,EAAE,KAAK,EAAE,CAAC,CAAC;QAC/D,SAAS,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;IACxB,CAAC;IAED,KAAK,MAAM,OAAO,IAAI,WAAW,CAAC,MAAM,IAAI,EAAE,EAAE,CAAC;QAC/C,GAAG,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,gBAAgB,EAAE,OAAO,EAAE,CAAC,CAAC;IACnD,CAAC;IAED,OAAO,EAAE,GAAG,EAAE,SAAS,EAAE,CAAC;AAC5B,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gCAAgC,CAC9C,KAAwB,EACxB,mBAAmD;IAEnD,OAAO;QACL,YAAY,EAAE;YACZ,gBAAgB,EAAE,KAAK,CAAC,gBAAgB;YACxC,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,kBAAkB,EAAE,KAAK,CAAC,kBAAkB,IAAI,cAAc;YAC9D,aAAa,EAAE,KAAK,CAAC,aAAa,IAAI,YAAY;SACnD;QACD,WAAW,EAAE,mBAAmB;KACjC,CAAC;AACJ,CAAC"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@composurecdk/budgets",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.7.0",
|
|
4
4
|
"description": "Composable AWS Budgets builder with well-architected defaults and automatic SNS topic policies",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -35,8 +35,9 @@
|
|
|
35
35
|
},
|
|
36
36
|
"type": "module",
|
|
37
37
|
"peerDependencies": {
|
|
38
|
-
"@composurecdk/
|
|
39
|
-
"@composurecdk/
|
|
38
|
+
"@composurecdk/cloudformation": "^0.7.0",
|
|
39
|
+
"@composurecdk/cloudwatch": "^0.7.0",
|
|
40
|
+
"@composurecdk/core": "^0.7.0",
|
|
40
41
|
"aws-cdk-lib": "^2.0.0",
|
|
41
42
|
"constructs": "^10.0.0"
|
|
42
43
|
},
|