@composurecdk/budgets 0.7.0 → 0.8.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 (102) hide show
  1. package/dist/commonjs/alarm-config.d.ts.map +1 -0
  2. package/dist/commonjs/alarm-config.js +3 -0
  3. package/dist/{alarm-config.js.map → commonjs/alarm-config.js.map} +1 -1
  4. package/dist/commonjs/budget-alarm-builder.d.ts.map +1 -0
  5. package/dist/commonjs/budget-alarm-builder.js +149 -0
  6. package/dist/commonjs/budget-alarm-builder.js.map +1 -0
  7. package/dist/commonjs/budget-alarms.d.ts.map +1 -0
  8. package/dist/commonjs/budget-alarms.js +53 -0
  9. package/dist/commonjs/budget-alarms.js.map +1 -0
  10. package/dist/commonjs/budget-builder.d.ts.map +1 -0
  11. package/dist/commonjs/budget-builder.js +170 -0
  12. package/dist/commonjs/budget-builder.js.map +1 -0
  13. package/dist/commonjs/currency.d.ts.map +1 -0
  14. package/dist/commonjs/currency.js +39 -0
  15. package/dist/commonjs/currency.js.map +1 -0
  16. package/dist/commonjs/defaults.d.ts.map +1 -0
  17. package/dist/commonjs/defaults.js +94 -0
  18. package/dist/commonjs/defaults.js.map +1 -0
  19. package/dist/commonjs/email.d.ts.map +1 -0
  20. package/dist/commonjs/email.js +33 -0
  21. package/dist/commonjs/email.js.map +1 -0
  22. package/dist/commonjs/index.d.ts.map +1 -0
  23. package/dist/commonjs/index.js +18 -0
  24. package/dist/commonjs/index.js.map +1 -0
  25. package/dist/commonjs/notifications.d.ts.map +1 -0
  26. package/dist/commonjs/notifications.js +43 -0
  27. package/dist/commonjs/notifications.js.map +1 -0
  28. package/dist/commonjs/package.json +3 -0
  29. package/dist/commonjs/topic-policy.d.ts.map +1 -0
  30. package/dist/commonjs/topic-policy.js +45 -0
  31. package/dist/commonjs/topic-policy.js.map +1 -0
  32. package/dist/esm/alarm-config.d.ts +61 -0
  33. package/dist/esm/alarm-config.d.ts.map +1 -0
  34. package/dist/esm/alarm-config.js.map +1 -0
  35. package/dist/esm/budget-alarm-builder.d.ts +150 -0
  36. package/dist/esm/budget-alarm-builder.d.ts.map +1 -0
  37. package/dist/esm/budget-alarm-builder.js.map +1 -0
  38. package/dist/esm/budget-alarms.d.ts +22 -0
  39. package/dist/esm/budget-alarms.d.ts.map +1 -0
  40. package/dist/esm/budget-alarms.js.map +1 -0
  41. package/dist/esm/budget-builder.d.ts +192 -0
  42. package/dist/esm/budget-builder.d.ts.map +1 -0
  43. package/dist/esm/budget-builder.js.map +1 -0
  44. package/dist/esm/currency.d.ts +21 -0
  45. package/dist/esm/currency.d.ts.map +1 -0
  46. package/dist/esm/currency.js.map +1 -0
  47. package/dist/esm/defaults.d.ts +57 -0
  48. package/dist/esm/defaults.d.ts.map +1 -0
  49. package/dist/esm/defaults.js.map +1 -0
  50. package/dist/esm/email.d.ts +28 -0
  51. package/dist/esm/email.d.ts.map +1 -0
  52. package/dist/esm/email.js.map +1 -0
  53. package/dist/esm/index.d.ts +8 -0
  54. package/dist/esm/index.d.ts.map +1 -0
  55. package/dist/esm/index.js.map +1 -0
  56. package/dist/esm/notifications.d.ts +88 -0
  57. package/dist/esm/notifications.d.ts.map +1 -0
  58. package/dist/esm/notifications.js.map +1 -0
  59. package/dist/esm/package.json +3 -0
  60. package/dist/esm/topic-policy.d.ts +20 -0
  61. package/dist/esm/topic-policy.d.ts.map +1 -0
  62. package/dist/esm/topic-policy.js.map +1 -0
  63. package/package.json +36 -18
  64. package/dist/alarm-config.d.ts.map +0 -1
  65. package/dist/budget-alarm-builder.d.ts.map +0 -1
  66. package/dist/budget-alarm-builder.js.map +0 -1
  67. package/dist/budget-alarms.d.ts.map +0 -1
  68. package/dist/budget-alarms.js.map +0 -1
  69. package/dist/budget-builder.d.ts.map +0 -1
  70. package/dist/budget-builder.js.map +0 -1
  71. package/dist/currency.d.ts.map +0 -1
  72. package/dist/currency.js.map +0 -1
  73. package/dist/defaults.d.ts.map +0 -1
  74. package/dist/defaults.js.map +0 -1
  75. package/dist/email.d.ts.map +0 -1
  76. package/dist/email.js.map +0 -1
  77. package/dist/index.d.ts.map +0 -1
  78. package/dist/index.js.map +0 -1
  79. package/dist/notifications.d.ts.map +0 -1
  80. package/dist/notifications.js.map +0 -1
  81. package/dist/topic-policy.d.ts.map +0 -1
  82. package/dist/topic-policy.js.map +0 -1
  83. /package/dist/{alarm-config.d.ts → commonjs/alarm-config.d.ts} +0 -0
  84. /package/dist/{budget-alarm-builder.d.ts → commonjs/budget-alarm-builder.d.ts} +0 -0
  85. /package/dist/{budget-alarms.d.ts → commonjs/budget-alarms.d.ts} +0 -0
  86. /package/dist/{budget-builder.d.ts → commonjs/budget-builder.d.ts} +0 -0
  87. /package/dist/{currency.d.ts → commonjs/currency.d.ts} +0 -0
  88. /package/dist/{defaults.d.ts → commonjs/defaults.d.ts} +0 -0
  89. /package/dist/{email.d.ts → commonjs/email.d.ts} +0 -0
  90. /package/dist/{index.d.ts → commonjs/index.d.ts} +0 -0
  91. /package/dist/{notifications.d.ts → commonjs/notifications.d.ts} +0 -0
  92. /package/dist/{topic-policy.d.ts → commonjs/topic-policy.d.ts} +0 -0
  93. /package/dist/{alarm-config.js → esm/alarm-config.js} +0 -0
  94. /package/dist/{budget-alarm-builder.js → esm/budget-alarm-builder.js} +0 -0
  95. /package/dist/{budget-alarms.js → esm/budget-alarms.js} +0 -0
  96. /package/dist/{budget-builder.js → esm/budget-builder.js} +0 -0
  97. /package/dist/{currency.js → esm/currency.js} +0 -0
  98. /package/dist/{defaults.js → esm/defaults.js} +0 -0
  99. /package/dist/{email.js → esm/email.js} +0 -0
  100. /package/dist/{index.js → esm/index.js} +0 -0
  101. /package/dist/{notifications.js → esm/notifications.js} +0 -0
  102. /package/dist/{topic-policy.js → esm/topic-policy.js} +0 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"alarm-config.d.ts","sourceRoot":"","sources":["../../src/alarm-config.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AAE5D;;;;;;;;;;;;;GAaG;AACH,MAAM,WAAW,2BAA4B,SAAQ,WAAW;IAC9D;;;OAGG;IACH,SAAS,EAAE,MAAM,CAAC;IAElB;;;;;;OAMG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;;;;;;;;;;;;;GAcG;AACH,MAAM,WAAW,iBAAiB;IAChC;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;IAElB;;;;;;OAMG;IACH,gBAAgB,CAAC,EAAE,2BAA2B,GAAG,KAAK,CAAC;CACxD"}
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=alarm-config.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"alarm-config.js","sourceRoot":"","sources":["../src/alarm-config.ts"],"names":[],"mappings":""}
1
+ {"version":3,"file":"alarm-config.js","sourceRoot":"","sources":["../../src/alarm-config.ts"],"names":[],"mappings":""}
@@ -0,0 +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,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"}
@@ -0,0 +1,149 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildBudgetAlarms = buildBudgetAlarms;
4
+ exports.createBudgetAlarmBuilder = createBudgetAlarmBuilder;
5
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
6
+ const core_1 = require("@composurecdk/core");
7
+ const cloudformation_1 = require("@composurecdk/cloudformation");
8
+ const cloudwatch_1 = require("@composurecdk/cloudwatch");
9
+ const budget_alarms_js_1 = require("./budget-alarms.js");
10
+ /**
11
+ * The `AWS/Billing EstimatedCharges` metric is emitted in `us-east-1`
12
+ * only. CloudWatch alarms are regional, so alarms created in any other
13
+ * region will never receive data. Warn (don't error) when alarms are
14
+ * being created outside `us-east-1`, unless the region is an unresolved
15
+ * token (env-agnostic stack — user knows best).
16
+ */
17
+ function warnIfNotUsEast1(scope) {
18
+ const region = aws_cdk_lib_1.Stack.of(scope).region;
19
+ if (aws_cdk_lib_1.Token.isUnresolved(region))
20
+ return;
21
+ if (region === "us-east-1")
22
+ return;
23
+ aws_cdk_lib_1.Annotations.of(scope).addWarningV2("@composurecdk/budgets:alarm-region", `AWS/Billing EstimatedCharges is emitted in us-east-1 only, but this stack is ` +
24
+ `deployed in "${region}". CloudWatch alarms created here will not fire. Deploy the ` +
25
+ `stack in us-east-1, or use createBudgetAlarmBuilder() routed to a ` +
26
+ `us-east-1 stack via compose().withStacks().`);
27
+ }
28
+ /**
29
+ * Shared alarm-assembly used by both {@link createBudgetBuilder} (in its
30
+ * own stack) and {@link createBudgetAlarmBuilder} (typically in a separate
31
+ * `us-east-1` stack). Materialises the recommended billing alarm and any
32
+ * user-supplied custom alarms, emits the region warning if the resulting
33
+ * scope is not in `us-east-1`, and creates the alarm constructs.
34
+ *
35
+ * The `target.budget` reference is only needed for custom alarms added
36
+ * via `addAlarm()` — the recommended `EstimatedCharges` alarm is
37
+ * account-level and does not key off the budget itself, so `target` may
38
+ * be omitted when only the recommended alarm is being created.
39
+ *
40
+ * @internal
41
+ */
42
+ function buildBudgetAlarms(scope, id, target, options = {}) {
43
+ const recommended = options.recommendedAlarms;
44
+ const recommendedDefs = recommended === false ? [] : (0, budget_alarms_js_1.resolveBudgetAlarmDefinitions)(recommended);
45
+ const customAlarms = options.customAlarms ?? [];
46
+ if (customAlarms.length > 0 && !target) {
47
+ throw new Error(`BudgetAlarmBuilder "${id}" was given addAlarm() definitions but no budget. ` +
48
+ `Call .budget() with a BudgetBuilderResult or a Ref to one before adding custom alarms.`);
49
+ }
50
+ const customAlarmDefs = target ? customAlarms.map((b) => b.resolve(target.budget)) : [];
51
+ const allAlarmDefs = [...recommendedDefs, ...customAlarmDefs];
52
+ if (allAlarmDefs.length > 0) {
53
+ warnIfNotUsEast1(scope);
54
+ }
55
+ return (0, cloudwatch_1.createAlarms)(scope, id, allAlarmDefs);
56
+ }
57
+ class BudgetAlarmBuilder {
58
+ props = {};
59
+ #budget;
60
+ #customAlarms = [];
61
+ /**
62
+ * Sets the budget to alarm on. Pass the result of
63
+ * {@link createBudgetBuilder} (or a {@link Ref} to it). The builder
64
+ * reads the underlying `CfnBudget` from the result so custom alarms
65
+ * added via {@link addAlarm} can reference it.
66
+ *
67
+ * Optional when only the recommended `EstimatedCharges` alarm is being
68
+ * created — that alarm is account-level and does not reference any
69
+ * specific budget. Required as soon as you call {@link addAlarm}.
70
+ *
71
+ * Pair with `compose().withStacks()` to route this component into a
72
+ * `us-east-1` stack while the budget itself lives elsewhere — set
73
+ * `crossRegionReferences: true` on both stacks so CDK can wire any
74
+ * cross-stack references automatically.
75
+ */
76
+ budget(budget) {
77
+ this.#budget = budget;
78
+ return this;
79
+ }
80
+ /**
81
+ * Adds a custom alarm against the budget. The configure callback
82
+ * receives a fresh {@link AlarmDefinitionBuilder} pre-set with the
83
+ * alarm's key; configure metric, threshold, comparison and any other
84
+ * options.
85
+ *
86
+ * The created alarm is materialised in this builder's stack — useful
87
+ * for cross-region setups where you want all billing-related alarms to
88
+ * live with the recommended one.
89
+ */
90
+ addAlarm(key, configure) {
91
+ this.#customAlarms.push(configure(new cloudwatch_1.AlarmDefinitionBuilder(key)));
92
+ return this;
93
+ }
94
+ /** @internal — see ADR-0005. */
95
+ [core_1.COPY_STATE](target) {
96
+ target.#budget = this.#budget;
97
+ target.#customAlarms.push(...this.#customAlarms);
98
+ }
99
+ build(scope, id, context) {
100
+ const target = this.#budget ? (0, core_1.resolve)(this.#budget, context ?? {}) : undefined;
101
+ return {
102
+ alarms: buildBudgetAlarms(scope, id, target, {
103
+ recommendedAlarms: this.props.recommendedAlarms,
104
+ customAlarms: this.#customAlarms,
105
+ }),
106
+ };
107
+ }
108
+ }
109
+ /**
110
+ * Creates a new {@link IBudgetAlarmBuilder} for materialising AWS Budget
111
+ * alarms in a stack separate from the budget itself.
112
+ *
113
+ * The recommended use is multi-region deployments: the budget lives in
114
+ * the application's stack (in any region — `AWS::Budgets::Budget` is a
115
+ * global resource), and the alarms must live in a `us-east-1` stack so
116
+ * they can read the `AWS/Billing EstimatedCharges` metric AWS emits
117
+ * there.
118
+ *
119
+ * @example
120
+ * ```ts
121
+ * compose(
122
+ * {
123
+ * account: createBudgetBuilder()
124
+ * .budgetName("Account")
125
+ * .limit({ amount: 1000 })
126
+ * .recommendedAlarms(false), // suppress alarms in the budget's own stack
127
+ *
128
+ * accountAlarms: createBudgetAlarmBuilder()
129
+ * .budget(ref<BudgetBuilderResult>("account"))
130
+ * .recommendedAlarms({
131
+ * estimatedCharges: { threshold: 1000, currency: "USD" },
132
+ * }),
133
+ * },
134
+ * { account: [], accountAlarms: ["account"] },
135
+ * )
136
+ * .withStacks({
137
+ * account: appStack, // any region — Budgets is a global service
138
+ * accountAlarms: monitoringStack, // us-east-1 — where AWS/Billing metrics live
139
+ * })
140
+ * .build(app, "App");
141
+ * ```
142
+ *
143
+ * Set `crossRegionReferences: true` on both stacks if you reference the
144
+ * budget from custom alarms via `.addAlarm()`.
145
+ */
146
+ function createBudgetAlarmBuilder() {
147
+ return (0, cloudformation_1.taggedBuilder)(BudgetAlarmBuilder);
148
+ }
149
+ //# sourceMappingURL=budget-alarm-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget-alarm-builder.js","sourceRoot":"","sources":["../../src/budget-alarm-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +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;AAK3D;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,6BAA6B,CAC3C,MAAM,EAAE,iBAAiB,GAAG,SAAS,GACpC,eAAe,EAAE,CA0BnB"}
@@ -0,0 +1,53 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.resolveBudgetAlarmDefinitions = resolveBudgetAlarmDefinitions;
4
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
5
+ const aws_cloudwatch_1 = require("aws-cdk-lib/aws-cloudwatch");
6
+ const currency_js_1 = require("./currency.js");
7
+ const BILLING_METRIC_PERIOD = aws_cdk_lib_1.Duration.hours(6);
8
+ /**
9
+ * Resolves the recommended alarm configuration into fully-resolved
10
+ * {@link AlarmDefinition}s for an AWS Budget.
11
+ *
12
+ * AWS Budgets does not publish per-budget CloudWatch metrics — the only
13
+ * recommended alarm is the account-level `AWS/Billing EstimatedCharges`
14
+ * billing alarm. Off by default: callers must pass an
15
+ * {@link BudgetAlarmConfig.estimatedCharges} config to opt in.
16
+ *
17
+ * Period and statistic are fixed at the AWS-recommended values
18
+ * (6 hours, Maximum) and not exposed as configuration knobs — billing
19
+ * metrics only update every ~6 hours, so a shorter period would
20
+ * oversample. Threshold, currency, evaluation periods, datapoints and
21
+ * missing-data behaviour remain user-configurable via
22
+ * {@link EstimatedChargesAlarmConfig}.
23
+ *
24
+ * @see https://docs.aws.amazon.com/AmazonCloudWatch/latest/monitoring/monitor_estimated_charges_with_cloudwatch.html
25
+ */
26
+ function resolveBudgetAlarmDefinitions(config) {
27
+ if (config?.enabled === false)
28
+ return [];
29
+ if (!config?.estimatedCharges)
30
+ return [];
31
+ const cfg = config.estimatedCharges;
32
+ const currency = cfg.currency ?? "USD";
33
+ (0, currency_js_1.assertValidBudgetCurrency)(currency, `EstimatedChargesAlarmConfig: currency`);
34
+ return [
35
+ {
36
+ key: "estimatedCharges",
37
+ metric: new aws_cloudwatch_1.Metric({
38
+ namespace: "AWS/Billing",
39
+ metricName: "EstimatedCharges",
40
+ dimensionsMap: { Currency: currency },
41
+ statistic: "Maximum",
42
+ period: BILLING_METRIC_PERIOD,
43
+ }),
44
+ threshold: cfg.threshold,
45
+ comparisonOperator: aws_cloudwatch_1.ComparisonOperator.GREATER_THAN_THRESHOLD,
46
+ evaluationPeriods: cfg.evaluationPeriods ?? 1,
47
+ datapointsToAlarm: cfg.datapointsToAlarm ?? 1,
48
+ treatMissingData: cfg.treatMissingData ?? aws_cloudwatch_1.TreatMissingData.NOT_BREACHING,
49
+ description: `Account-level estimated charges exceeded ${String(cfg.threshold)} ${currency}. Billing metrics are only emitted in us-east-1.`,
50
+ },
51
+ ];
52
+ }
53
+ //# sourceMappingURL=budget-alarms.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget-alarms.js","sourceRoot":"","sources":["../../src/budget-alarms.ts"],"names":[],"mappings":";;AA0BA,sEA4BC;AAtDD,6CAAuC;AACvC,+DAA0F;AAG1F,+CAA0D;AAE1D,MAAM,qBAAqB,GAAG,sBAAQ,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;AAEhD;;;;;;;;;;;;;;;;;GAiBG;AACH,SAAgB,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,IAAA,uCAAyB,EAAC,QAAQ,EAAE,uCAAuC,CAAC,CAAC;IAE7E,OAAO;QACL;YACE,GAAG,EAAE,kBAAkB;YACvB,MAAM,EAAE,IAAI,uBAAM,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,mCAAkB,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,iCAAgB,CAAC,aAAa;YACxE,WAAW,EAAE,4CAA4C,MAAM,CAAC,GAAG,CAAC,SAAS,CAAC,IAAI,QAAQ,kDAAkD;SAC7I;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget-builder.d.ts","sourceRoot":"","sources":["../../src/budget-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,170 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createBudgetBuilder = createBudgetBuilder;
4
+ const aws_budgets_1 = require("aws-cdk-lib/aws-budgets");
5
+ const core_1 = require("@composurecdk/core");
6
+ const cloudwatch_1 = require("@composurecdk/cloudwatch");
7
+ const budget_alarm_builder_js_1 = require("./budget-alarm-builder.js");
8
+ const currency_js_1 = require("./currency.js");
9
+ const defaults_js_1 = require("./defaults.js");
10
+ const notifications_js_1 = require("./notifications.js");
11
+ const topic_policy_js_1 = require("./topic-policy.js");
12
+ const MAX_EMAILS_PER_NOTIFICATION = 10;
13
+ class BudgetBuilder {
14
+ props = {};
15
+ #notifications = [];
16
+ #customAlarms = [];
17
+ /**
18
+ * Add a notification that fires when ACTUAL spend crosses the given
19
+ * percentage of the budget limit.
20
+ *
21
+ * @param thresholdPercent - Percentage of the budget limit (e.g. `80`).
22
+ * For absolute-value thresholds, use {@link addNotification} directly.
23
+ * @param subscribers - Up to one SNS topic plus up to ten validated
24
+ * email addresses. AWS Budgets caps each notification at 1 SNS + up
25
+ * to 10 EMAIL subscribers.
26
+ */
27
+ notifyOnActual(thresholdPercent, subscribers) {
28
+ return this.#addPercentageNotification("ACTUAL", thresholdPercent, subscribers);
29
+ }
30
+ /**
31
+ * Add a notification that fires when FORECASTED spend crosses the
32
+ * given percentage of the budget limit.
33
+ *
34
+ * @param thresholdPercent - Percentage of the budget limit (e.g. `100`).
35
+ * For absolute-value thresholds, use {@link addNotification} directly.
36
+ * @param subscribers - Up to one SNS topic plus up to ten validated
37
+ * email addresses.
38
+ */
39
+ notifyOnForecasted(thresholdPercent, subscribers) {
40
+ return this.#addPercentageNotification("FORECASTED", thresholdPercent, subscribers);
41
+ }
42
+ /**
43
+ * Raw notification passthrough for callers that need the full
44
+ * CloudFormation surface (e.g. absolute-value thresholds).
45
+ */
46
+ addNotification(entry) {
47
+ this.#notifications.push(entry);
48
+ return this;
49
+ }
50
+ /**
51
+ * Apply the well-architected recommended notification thresholds:
52
+ *
53
+ * - `ACTUAL` at 80% — early warning before breach.
54
+ * - `FORECASTED` at 100% — trending-over-budget alert.
55
+ *
56
+ * Must be called with at least one subscriber; the same subscriber
57
+ * set is used for both thresholds.
58
+ *
59
+ * @see https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-best-practices.html
60
+ */
61
+ withRecommendedThresholds(subscribers) {
62
+ if (!hasAnySubscriber(subscribers)) {
63
+ throw new Error(`BudgetBuilder: withRecommendedThresholds(...) must be called with at least one subscriber.`);
64
+ }
65
+ const { actualPercent, forecastedPercent } = defaults_js_1.BUDGET_DEFAULTS.recommendedThresholds;
66
+ this.#notifications.push({ notificationType: "ACTUAL", threshold: actualPercent, subscribers }, { notificationType: "FORECASTED", threshold: forecastedPercent, subscribers });
67
+ return this;
68
+ }
69
+ /**
70
+ * Adds a custom CloudWatch alarm against the budget. The configure
71
+ * callback receives a fresh {@link AlarmDefinitionBuilder} pre-set with
72
+ * the alarm's key; configure metric, threshold, comparison and any
73
+ * other options.
74
+ *
75
+ * Custom alarms are materialised in this builder's stack alongside any
76
+ * recommended alarms. Like the recommended `EstimatedCharges` alarm,
77
+ * custom alarms on `AWS/Billing` metrics will only fire when this
78
+ * stack is in `us-east-1` — the builder emits the same synth-time
79
+ * warning (`@composurecdk/budgets:alarm-region`) when used elsewhere.
80
+ * For non-`us-east-1` stacks, route alarms via
81
+ * {@link createBudgetAlarmBuilder} into a `us-east-1` stack.
82
+ */
83
+ addAlarm(key, configure) {
84
+ this.#customAlarms.push(configure(new cloudwatch_1.AlarmDefinitionBuilder(key)));
85
+ return this;
86
+ }
87
+ /** @internal — see ADR-0005. */
88
+ [core_1.COPY_STATE](target) {
89
+ target.#notifications.push(...this.#notifications);
90
+ target.#customAlarms.push(...this.#customAlarms);
91
+ }
92
+ build(scope, id, context = {}) {
93
+ const { recommendedAlarms: alarmConfig, ...budgetProps } = this.props;
94
+ const budgetType = budgetProps.budgetType ?? defaults_js_1.BUDGET_DEFAULTS.budgetType;
95
+ const timeUnit = budgetProps.timeUnit ?? defaults_js_1.BUDGET_DEFAULTS.timeUnit;
96
+ const requiresLimit = budgetType === "COST" || budgetType === "USAGE";
97
+ if (requiresLimit && !budgetProps.limit) {
98
+ throw new Error(`BudgetBuilder "${id}": limit({ amount, unit }) must be set for ${budgetType} budgets.`);
99
+ }
100
+ const limitUnit = budgetProps.limit?.unit ?? defaults_js_1.BUDGET_DEFAULTS.limitUnit;
101
+ if (budgetType === "COST" && budgetProps.limit) {
102
+ (0, currency_js_1.assertValidBudgetCurrency)(limitUnit, `BudgetBuilder "${id}": limit unit`);
103
+ (0, currency_js_1.warnIfNonUsdCurrency)(scope, limitUnit, `BudgetBuilder "${id}": limit unit`);
104
+ }
105
+ const { notificationsWithSubscribers, snsTopics } = this.#buildNotifications(id, context);
106
+ const budgetData = {
107
+ budgetName: budgetProps.budgetName,
108
+ budgetType,
109
+ timeUnit,
110
+ ...(budgetProps.limit
111
+ ? {
112
+ budgetLimit: {
113
+ amount: budgetProps.limit.amount,
114
+ unit: limitUnit,
115
+ },
116
+ }
117
+ : {}),
118
+ ...(budgetProps.costFilters ? { costFilters: budgetProps.costFilters } : {}),
119
+ ...(budgetProps.costTypes ? { costTypes: budgetProps.costTypes } : {}),
120
+ };
121
+ const cfnProps = {
122
+ budget: budgetData,
123
+ ...(notificationsWithSubscribers.length > 0 ? { notificationsWithSubscribers } : {}),
124
+ };
125
+ const budget = new aws_budgets_1.CfnBudget(scope, id, cfnProps);
126
+ const topicPolicies = (0, topic_policy_js_1.createBudgetsTopicPolicies)(scope, id, snsTopics);
127
+ const alarms = (0, budget_alarm_builder_js_1.buildBudgetAlarms)(scope, id, { budget }, {
128
+ recommendedAlarms: alarmConfig,
129
+ customAlarms: this.#customAlarms,
130
+ });
131
+ return { budget, topicPolicies, alarms };
132
+ }
133
+ #addPercentageNotification(notificationType, thresholdPercent, subscribers) {
134
+ if (!hasAnySubscriber(subscribers)) {
135
+ throw new Error(`BudgetBuilder: ${notificationType} notification at ${String(thresholdPercent)}% requires at least one subscriber.`);
136
+ }
137
+ this.#notifications.push({ notificationType, threshold: thresholdPercent, subscribers });
138
+ return this;
139
+ }
140
+ #buildNotifications(id, context) {
141
+ const notificationsWithSubscribers = [];
142
+ const allSnsTopics = [];
143
+ for (const entry of this.#notifications) {
144
+ const emailCount = entry.subscribers.emails?.length ?? 0;
145
+ if (emailCount > MAX_EMAILS_PER_NOTIFICATION) {
146
+ throw new Error(`BudgetBuilder "${id}": ${describeNotification(entry)} has ${String(emailCount)} email subscribers; ` +
147
+ `AWS Budgets allows at most ${String(MAX_EMAILS_PER_NOTIFICATION)} email subscribers per notification (plus up to 1 SNS topic).`);
148
+ }
149
+ const resolved = (0, notifications_js_1.resolveSubscribers)(entry.subscribers, context);
150
+ notificationsWithSubscribers.push((0, notifications_js_1.toCfnNotificationWithSubscribers)(entry, resolved.cfn));
151
+ allSnsTopics.push(...resolved.snsTopics);
152
+ }
153
+ return { notificationsWithSubscribers, snsTopics: allSnsTopics };
154
+ }
155
+ }
156
+ function hasAnySubscriber(subscribers) {
157
+ return subscribers.sns !== undefined || (subscribers.emails?.length ?? 0) > 0;
158
+ }
159
+ function describeNotification(entry) {
160
+ const unit = (entry.thresholdType ?? "PERCENTAGE") === "PERCENTAGE" ? "%" : "";
161
+ return `notification ${entry.notificationType} @ ${String(entry.threshold)}${unit}`;
162
+ }
163
+ /**
164
+ * Creates a new {@link IBudgetBuilder} for configuring an AWS Budget.
165
+ */
166
+ function createBudgetBuilder() {
167
+ // eslint-disable-next-line composurecdk/builder-must-be-tagged -- AWS::Budgets::Budget has no Tags property
168
+ return (0, core_1.Builder)(BudgetBuilder);
169
+ }
170
+ //# sourceMappingURL=budget-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"budget-builder.js","sourceRoot":"","sources":["../../src/budget-builder.ts"],"names":[],"mappings":"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"}
@@ -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"}
@@ -0,0 +1,39 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertValidBudgetCurrency = assertValidBudgetCurrency;
4
+ exports.warnIfNonUsdCurrency = warnIfNonUsdCurrency;
5
+ const aws_cdk_lib_1 = require("aws-cdk-lib");
6
+ const defaults_js_1 = require("./defaults.js");
7
+ /**
8
+ * Throws if `unit` is not in {@link DEFAULT_BUDGET_CURRENCIES}.
9
+ *
10
+ * `context` is woven into the message (e.g. `BudgetBuilder "X": limit
11
+ * unit ...`) so callers can blame the right field. Catches typos like
12
+ * `"USDD"` or `"ZZZ"` at synth instead of mid-deploy.
13
+ */
14
+ function assertValidBudgetCurrency(unit, context) {
15
+ if (defaults_js_1.DEFAULT_BUDGET_CURRENCIES.includes(unit))
16
+ return;
17
+ throw new Error(`${context}: "${unit}" is not a recognised AWS Budgets currency code. ` +
18
+ `Expected one of: ${defaults_js_1.DEFAULT_BUDGET_CURRENCIES.join(", ")}.`);
19
+ }
20
+ /**
21
+ * Annotates `scope` with a non-fatal warning when `unit` is anything
22
+ * other than `USD`. The synth context cannot see an account's billing
23
+ * currency, and AWS Budgets rejects `BudgetLimit.Unit` values that
24
+ * don't match it — so a non-USD configuration deserves a "make sure
25
+ * this matches your billing currency" nudge.
26
+ *
27
+ * Short-circuits on unresolved tokens so env-agnostic stacks aren't
28
+ * spammed.
29
+ */
30
+ function warnIfNonUsdCurrency(scope, unit, context) {
31
+ if (aws_cdk_lib_1.Token.isUnresolved(unit))
32
+ return;
33
+ if (unit === "USD")
34
+ return;
35
+ aws_cdk_lib_1.Annotations.of(scope).addWarningV2("@composurecdk/budgets:limit-currency", `${context}: currency "${unit}" must match the account's billing currency or AWS Budgets ` +
36
+ `will reject the request at deploy time. Most accounts default to USD; verify yours and ` +
37
+ `suppress this warning if intentional.`);
38
+ }
39
+ //# sourceMappingURL=currency.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"currency.js","sourceRoot":"","sources":["../../src/currency.ts"],"names":[],"mappings":";;AAWA,8DAMC;AAYD,oDASC;AAtCD,6CAAiD;AAEjD,+CAA0D;AAE1D;;;;;;GAMG;AACH,SAAgB,yBAAyB,CAAC,IAAY,EAAE,OAAe;IACrE,IAAI,uCAAyB,CAAC,QAAQ,CAAC,IAAI,CAAC;QAAE,OAAO;IACrD,MAAM,IAAI,KAAK,CACb,GAAG,OAAO,MAAM,IAAI,mDAAmD;QACrE,oBAAoB,uCAAyB,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAC9D,CAAC;AACJ,CAAC;AAED;;;;;;;;;GASG;AACH,SAAgB,oBAAoB,CAAC,KAAiB,EAAE,IAAY,EAAE,OAAe;IACnF,IAAI,mBAAK,CAAC,YAAY,CAAC,IAAI,CAAC;QAAE,OAAO;IACrC,IAAI,IAAI,KAAK,KAAK;QAAE,OAAO;IAC3B,yBAAW,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,YAAY,CAChC,sCAAsC,EACtC,GAAG,OAAO,eAAe,IAAI,6DAA6D;QACxF,yFAAyF;QACzF,uCAAuC,CAC1C,CAAC;AACJ,CAAC"}
@@ -0,0 +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;AAEF;;;;;;;;;;;;GAYG;AACH,eAAO,MAAM,yBAAyB,EAAE,SAAS,MAAM,EAkCtD,CAAC"}
@@ -0,0 +1,94 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_BUDGET_CURRENCIES = exports.BUDGET_DEFAULTS = void 0;
4
+ /**
5
+ * Well-architected defaults for {@link createBudgetBuilder}. Each can be
6
+ * overridden via the builder's fluent API.
7
+ *
8
+ * @see https://docs.aws.amazon.com/wellarchitected/latest/cost-optimization-pillar/welcome.html
9
+ */
10
+ exports.BUDGET_DEFAULTS = {
11
+ /**
12
+ * Default budget type — most budgets are cost budgets.
13
+ *
14
+ * @see https://docs.aws.amazon.com/aws-cost-management/latest/APIReference/API_budgets_Budget.html
15
+ */
16
+ budgetType: "COST",
17
+ /**
18
+ * Default tracking period — monthly is the most common granularity and
19
+ * aligns with AWS billing cycles.
20
+ *
21
+ * @see https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-create.html
22
+ */
23
+ timeUnit: "MONTHLY",
24
+ /**
25
+ * Default spend currency — most customers need to set this; the builder
26
+ * defaults to USD to align with the AWS Billing reporting default.
27
+ *
28
+ * @see https://docs.aws.amazon.com/aws-cost-management/latest/APIReference/API_budgets_Spend.html
29
+ */
30
+ limitUnit: "USD",
31
+ /**
32
+ * Recommended percentage thresholds applied by
33
+ * {@link IBudgetBuilder.withRecommendedThresholds}.
34
+ *
35
+ * - `ACTUAL` at 80% — early warning before you breach the budget.
36
+ * - `FORECASTED` at 100% — notifies when forecasted spend trends over
37
+ * budget for the period.
38
+ *
39
+ * @see https://docs.aws.amazon.com/cost-management/latest/userguide/budgets-best-practices.html
40
+ */
41
+ recommendedThresholds: {
42
+ actualPercent: 80,
43
+ forecastedPercent: 100,
44
+ },
45
+ };
46
+ /**
47
+ * ISO 4217 currency codes accepted by AWS Budgets for `COST` budgets'
48
+ * `BudgetLimit.Unit` and the `EstimatedCharges` alarm's `Currency`
49
+ * dimension. Sourced from the AWS Billing supported-currencies list.
50
+ *
51
+ * The synth context cannot see an account's billing currency, so the
52
+ * builder uses this set for shape validation only — a hard error on
53
+ * anything outside it (catches typos like `"ZZZ"`/`"USDD"`) — and emits
54
+ * a soft warning when the configured unit is anything other than `USD`,
55
+ * since most accounts default to USD billing.
56
+ *
57
+ * @see https://docs.aws.amazon.com/awsaccountbilling/latest/aboutv2/manage-account-payment.html
58
+ */
59
+ exports.DEFAULT_BUDGET_CURRENCIES = [
60
+ "AED",
61
+ "ARS",
62
+ "AUD",
63
+ "BRL",
64
+ "CAD",
65
+ "CHF",
66
+ "CLP",
67
+ "CNY",
68
+ "COP",
69
+ "CZK",
70
+ "DKK",
71
+ "EUR",
72
+ "GBP",
73
+ "HKD",
74
+ "IDR",
75
+ "ILS",
76
+ "INR",
77
+ "JPY",
78
+ "KRW",
79
+ "MXN",
80
+ "MYR",
81
+ "NOK",
82
+ "NZD",
83
+ "PLN",
84
+ "RUB",
85
+ "SAR",
86
+ "SEK",
87
+ "SGD",
88
+ "THB",
89
+ "TRY",
90
+ "TWD",
91
+ "USD",
92
+ "ZAR",
93
+ ];
94
+ //# sourceMappingURL=defaults.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"defaults.js","sourceRoot":"","sources":["../../src/defaults.ts"],"names":[],"mappings":";;;AAAA;;;;;GAKG;AACU,QAAA,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;AACU,QAAA,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"}
@@ -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"}
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.email = email;
4
+ const MAX_LEN = 50;
5
+ const EMAIL_REGEX = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
6
+ /**
7
+ * Validates and brands a string as an {@link Email}.
8
+ *
9
+ * The pattern intentionally errs on the side of acceptance — anything
10
+ * obviously not an email (whitespace, missing `@`, missing TLD) is
11
+ * rejected, but any address AWS Budgets will plausibly accept passes.
12
+ * The 50-char cap matches the Budgets API's documented per-subscriber
13
+ * limit.
14
+ *
15
+ * @throws If the input is empty, exceeds 50 characters, or doesn't
16
+ * contain `local@domain.tld`.
17
+ *
18
+ * @see https://docs.aws.amazon.com/aws-cost-management/latest/APIReference/API_budgets_Subscriber.html
19
+ */
20
+ function email(input) {
21
+ const trimmed = input.trim();
22
+ if (trimmed.length === 0) {
23
+ throw new Error("email cannot be empty");
24
+ }
25
+ if (trimmed.length > MAX_LEN) {
26
+ throw new Error(`email exceeds ${String(MAX_LEN)} chars (AWS Budgets per-subscriber limit): "${trimmed}"`);
27
+ }
28
+ if (!EMAIL_REGEX.test(trimmed)) {
29
+ throw new Error(`invalid email address: "${trimmed}"`);
30
+ }
31
+ return trimmed;
32
+ }
33
+ //# sourceMappingURL=email.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"email.js","sourceRoot":"","sources":["../../src/email.ts"],"names":[],"mappings":";;AA4BA,sBAcC;AA/BD,MAAM,OAAO,GAAG,EAAE,CAAC;AACnB,MAAM,WAAW,GAAG,4BAA4B,CAAC;AAEjD;;;;;;;;;;;;;GAaG;AACH,SAAgB,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"}
@@ -0,0 +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,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"}
@@ -0,0 +1,18 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.toCfnNotificationWithSubscribers = exports.resolveSubscribers = exports.email = exports.createBudgetsTopicPolicies = exports.DEFAULT_BUDGET_CURRENCIES = exports.BUDGET_DEFAULTS = exports.createBudgetAlarmBuilder = exports.createBudgetBuilder = void 0;
4
+ var budget_builder_js_1 = require("./budget-builder.js");
5
+ Object.defineProperty(exports, "createBudgetBuilder", { enumerable: true, get: function () { return budget_builder_js_1.createBudgetBuilder; } });
6
+ var budget_alarm_builder_js_1 = require("./budget-alarm-builder.js");
7
+ Object.defineProperty(exports, "createBudgetAlarmBuilder", { enumerable: true, get: function () { return budget_alarm_builder_js_1.createBudgetAlarmBuilder; } });
8
+ var defaults_js_1 = require("./defaults.js");
9
+ Object.defineProperty(exports, "BUDGET_DEFAULTS", { enumerable: true, get: function () { return defaults_js_1.BUDGET_DEFAULTS; } });
10
+ Object.defineProperty(exports, "DEFAULT_BUDGET_CURRENCIES", { enumerable: true, get: function () { return defaults_js_1.DEFAULT_BUDGET_CURRENCIES; } });
11
+ var topic_policy_js_1 = require("./topic-policy.js");
12
+ Object.defineProperty(exports, "createBudgetsTopicPolicies", { enumerable: true, get: function () { return topic_policy_js_1.createBudgetsTopicPolicies; } });
13
+ var email_js_1 = require("./email.js");
14
+ Object.defineProperty(exports, "email", { enumerable: true, get: function () { return email_js_1.email; } });
15
+ var notifications_js_1 = require("./notifications.js");
16
+ Object.defineProperty(exports, "resolveSubscribers", { enumerable: true, get: function () { return notifications_js_1.resolveSubscribers; } });
17
+ Object.defineProperty(exports, "toCfnNotificationWithSubscribers", { enumerable: true, get: function () { return notifications_js_1.toCfnNotificationWithSubscribers; } });
18
+ //# sourceMappingURL=index.js.map