@daemonitor/plugins 1.1.53 → 1.1.54

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.
@@ -76,6 +76,7 @@ export async function collectCost(p, today = todayUtc()) {
76
76
  ...summarizeCost(f, today),
77
77
  breakdown: (f.breakdown || []).filter((b) => b.amount).sort((a, b) => b.amount - a.amount).slice(0, 12)
78
78
  .map((b) => ({ name: b.name, amount: round2(b.amount) })),
79
+ ...(f.limits?.length ? { limits: f.limits } : {}),
79
80
  };
80
81
  }
81
82
  export function createCostPlugin() {
@@ -203,15 +203,47 @@ const vultr = async (cfg, _range, timeout) => {
203
203
  const cloudflare = async (cfg, { end }, timeout) => {
204
204
  need(cfg, "token", "accountId");
205
205
  const t = tally(end.slice(0, 7));
206
- const body = await json(`https://api.cloudflare.com/client/v4/accounts/${cfg.accountId}/billable-usage`, { headers: { Authorization: `Bearer ${cfg.token}` } }, timeout);
206
+ const acct = `https://api.cloudflare.com/client/v4/accounts/${cfg.accountId}`;
207
+ const init = { headers: { Authorization: `Bearer ${cfg.token}` } };
208
+ const [body, limits] = await Promise.all([
209
+ json(`${acct}/billable-usage`, init, timeout),
210
+ cloudflareLimits(acct, init, timeout),
211
+ ]);
207
212
  let currency = "USD";
208
213
  for (const r of body.result || []) {
209
214
  if (r.BillingCurrency)
210
215
  currency = r.BillingCurrency;
211
216
  t.add(String(r.ChargePeriodStart || "").slice(0, 10), Number(r.BilledCost) || 0, r.ServiceName || r.ChargeDescription || undefined);
212
217
  }
213
- return { currency, days: t.days(), breakdown: t.breakdown() };
218
+ return { currency, days: t.days(), breakdown: t.breakdown(), ...(limits.length ? { limits } : {}) };
214
219
  };
220
+ // Spend policies (beta, PayGo, Workers and Durable Objects only, 2026-11-13):
221
+ // per-product limits that email (`notification`) or stop the product
222
+ // (`usage_block`). Optional: a token without Billing access or an account with
223
+ // no policies leaves the spend row as it was. Cents converted to dollars here.
224
+ async function cloudflareLimits(acct, init, timeout) {
225
+ try {
226
+ const body = await json(`${acct}/billing/spend-policies`, init, timeout);
227
+ return (body.result || []).filter((p) => p.enabled).map((p) => cfLimit(p));
228
+ }
229
+ catch (e) {
230
+ if (e instanceof HttpError && [403, 404].includes(e.status))
231
+ return [];
232
+ throw e;
233
+ }
234
+ }
235
+ export function cfLimit(p) {
236
+ const st = p.current_state || {};
237
+ return {
238
+ name: p.name || p.product_id,
239
+ product: String(p.product_id || ""),
240
+ blocks: p.action === "usage_block",
241
+ threshold: (Number(p.threshold_cents) || 0) / 100,
242
+ ...(st.balance_cents != null ? { spent: (Number(st.balance_cents) || 0) / 100 } : {}),
243
+ status: String(st.status || "unavailable"),
244
+ ...(st.billing_period_end ? { periodEnd: st.billing_period_end } : {}),
245
+ };
246
+ }
215
247
  // PostHog: daily spend series, personal API key with billing:read. End is INCLUSIVE.
216
248
  const posthog = async (cfg, { start, end }, timeout) => {
217
249
  need(cfg, "apiKey");
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@daemonitor/plugins",
3
- "version": "1.1.53",
3
+ "version": "1.1.54",
4
4
  "description": "daemonitor plugins",
5
5
  "types": "types/index.d.ts",
6
6
  "main": "dist/index.js",