sermon-js 0.2.0 → 0.3.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.
Files changed (52) hide show
  1. package/README.md +2 -1
  2. package/dist/api/index.d.cts +4 -4
  3. package/dist/api/index.d.ts +4 -4
  4. package/dist/{chunk-PARE6EUZ.cjs → chunk-NZTKXXW2.cjs} +7 -3
  5. package/dist/chunk-NZTKXXW2.cjs.map +1 -0
  6. package/dist/{chunk-2M4UBCDM.js → chunk-R7BDAQOM.js} +7 -3
  7. package/dist/chunk-R7BDAQOM.js.map +1 -0
  8. package/dist/{config-BEbP-uLf.d.cts → config-gro29syt.d.cts} +1 -1
  9. package/dist/{config-w1tm1bdu.d.ts → config-iY18j9IA.d.ts} +1 -1
  10. package/dist/{generic-lmrGxMDC.d.cts → generic-BUiaKpNp.d.cts} +2 -2
  11. package/dist/{generic-BJmlgtUM.d.ts → generic-CV2O4aNH.d.ts} +2 -2
  12. package/dist/index.cjs +6 -6
  13. package/dist/index.d.cts +8 -8
  14. package/dist/index.d.ts +8 -8
  15. package/dist/index.js +2 -2
  16. package/dist/presets/index.cjs +407 -47
  17. package/dist/presets/index.cjs.map +1 -1
  18. package/dist/presets/index.d.cts +173 -14
  19. package/dist/presets/index.d.ts +173 -14
  20. package/dist/presets/index.js +402 -48
  21. package/dist/presets/index.js.map +1 -1
  22. package/dist/react/heroui/index.cjs +27 -18
  23. package/dist/react/heroui/index.cjs.map +1 -1
  24. package/dist/react/heroui/index.d.cts +7 -2
  25. package/dist/react/heroui/index.d.ts +7 -2
  26. package/dist/react/heroui/index.js +13 -4
  27. package/dist/react/heroui/index.js.map +1 -1
  28. package/dist/react/index.d.cts +2 -2
  29. package/dist/react/index.d.ts +2 -2
  30. package/dist/{status-DsWzgb9Q.d.cts → status-BExBb08T.d.cts} +3 -3
  31. package/dist/{status-zd04ZQ98.d.ts → status-DmRhwvVC.d.ts} +3 -3
  32. package/dist/{store-_GuzSP0z.d.ts → store-BfKP7CjW.d.ts} +1 -1
  33. package/dist/{store-DybhDphS.d.cts → store-CAIB7Esp.d.cts} +1 -1
  34. package/dist/stores/mongodb.d.cts +2 -2
  35. package/dist/stores/mongodb.d.ts +2 -2
  36. package/dist/stores/redis.d.cts +2 -2
  37. package/dist/stores/redis.d.ts +2 -2
  38. package/dist/stores/sql.d.cts +2 -2
  39. package/dist/stores/sql.d.ts +2 -2
  40. package/dist/stores/upstash.d.cts +2 -2
  41. package/dist/stores/upstash.d.ts +2 -2
  42. package/dist/testing/index.cjs +3 -3
  43. package/dist/testing/index.d.cts +3 -3
  44. package/dist/testing/index.d.ts +3 -3
  45. package/dist/testing/index.js +1 -1
  46. package/dist/{tree-BXbXfjF1.d.cts → tree-J3riUyI9.d.cts} +9 -0
  47. package/dist/{tree-BXbXfjF1.d.ts → tree-J3riUyI9.d.ts} +9 -0
  48. package/dist/{types-CctvUAs2.d.cts → types-BVa6vIKk.d.cts} +9 -0
  49. package/dist/{types-CctvUAs2.d.ts → types-BVa6vIKk.d.ts} +9 -0
  50. package/package.json +1 -1
  51. package/dist/chunk-2M4UBCDM.js.map +0 -1
  52. package/dist/chunk-PARE6EUZ.cjs.map +0 -1
@@ -19,9 +19,9 @@ function withKeys(machines) {
19
19
  const seen = /* @__PURE__ */ new Map();
20
20
  return [...machines].sort((a, b) => (a.region ?? "").localeCompare(b.region ?? "") || a.id.localeCompare(b.id)).map((machine) => {
21
21
  const region = machine.region ?? "unknown";
22
- const count = (seen.get(region) ?? 0) + 1;
23
- seen.set(region, count);
24
- return { machine, region, key: count === 1 ? region : `${region}#${count}` };
22
+ const count2 = (seen.get(region) ?? 0) + 1;
23
+ seen.set(region, count2);
24
+ return { machine, region, key: count2 === 1 ? region : `${region}#${count2}` };
25
25
  });
26
26
  }
27
27
  function median(values) {
@@ -223,8 +223,8 @@ var instance = chunkXHXEKB3Q_cjs.definePreset()({
223
223
  }),
224
224
  check: async ({ options, secrets, http, now }) => {
225
225
  const account = parseServiceAccount(secrets.serviceAccount);
226
- const project = options.project ?? account?.project_id;
227
- if (!account || !project) {
226
+ const project2 = options.project ?? account?.project_id;
227
+ if (!account || !project2) {
228
228
  return { status: "down", probed: false, error: "The service account secret is not a service-account JSON key" };
229
229
  }
230
230
  let token;
@@ -239,7 +239,7 @@ var instance = chunkXHXEKB3Q_cjs.definePreset()({
239
239
  return { status: "down", probed: false, error: error instanceof Error ? error.message : String(error) };
240
240
  }
241
241
  const info = await http(
242
- `https://compute.googleapis.com/compute/v1/projects/${project}/zones/${options.zone}/instances/${options.instance}`,
242
+ `https://compute.googleapis.com/compute/v1/projects/${project2}/zones/${options.zone}/instances/${options.instance}`,
243
243
  { headers: { Authorization: `Bearer ${token}` } }
244
244
  );
245
245
  const state = info.json?.status;
@@ -262,6 +262,68 @@ var instance = chunkXHXEKB3Q_cjs.definePreset()({
262
262
  }
263
263
  });
264
264
  var gcp = { instance };
265
+
266
+ // src/presets/providers/shared.ts
267
+ var bearer = (token) => ({ Authorization: `Bearer ${token}` });
268
+ var round = (value, digits = 1) => Math.round(value * 10 ** digits) / 10 ** digits;
269
+ function base64(text) {
270
+ const bytes = new TextEncoder().encode(text);
271
+ let binary = "";
272
+ for (const byte of bytes) binary += String.fromCharCode(byte);
273
+ return btoa(binary);
274
+ }
275
+ async function call(http, url, init, refine) {
276
+ const response = await http(url, init);
277
+ if (!response.ok || !refine) return response.outcome;
278
+ return { ...response.outcome, ...chunkXHXEKB3Q_cjs.normalizeReturn(refine(response)) };
279
+ }
280
+ function quota({
281
+ label,
282
+ used,
283
+ limit,
284
+ unit,
285
+ resetsAt,
286
+ warnAbovePct,
287
+ warning
288
+ }) {
289
+ const pct = limit > 0 ? used / limit * 100 : 0;
290
+ const over = pct >= warnAbovePct;
291
+ return {
292
+ status: over ? "degraded" : "up",
293
+ error: over ? warning : void 0,
294
+ usage: [{ label, used, limit, unit, resetsAt }]
295
+ };
296
+ }
297
+ function summarize(instances, noun) {
298
+ const down = instances.filter((instance2) => instance2.status === "down");
299
+ const degraded = instances.filter((instance2) => instance2.status === "degraded");
300
+ const awake = instances.filter((instance2) => instance2.status === "up" || instance2.status === "degraded");
301
+ const keysOf = (items) => items.map((instance2) => instance2.key).join(", ");
302
+ const latencies = instances.map((instance2) => instance2.latencyMs).filter((l) => l !== void 0);
303
+ const latencyMs = latencies.length ? Math.max(...latencies) : void 0;
304
+ if (instances.length > 0 && down.length === instances.length) {
305
+ return { status: "down", latencyMs, error: `All ${instances.length} ${noun}(s) failing` };
306
+ }
307
+ if (down.length > 0) {
308
+ return { status: "degraded", latencyMs, error: `${down.length}/${instances.length} ${noun}(s) failing: ${keysOf(down)}` };
309
+ }
310
+ if (degraded.length > 0) return { status: "degraded", latencyMs, error: `Degraded: ${keysOf(degraded)}` };
311
+ return { status: awake.length || instances.length === 0 ? "up" : "sleeping", latencyMs };
312
+ }
313
+ function keyAccepted(res) {
314
+ if (res.status === 400 || res.status === 422) return { status: "up", latencyMs: res.latencyMs, httpStatus: res.status };
315
+ if (res.status === 402) {
316
+ return { status: "degraded", latencyMs: res.latencyMs, httpStatus: 402, error: "Out of credits, or payment required" };
317
+ }
318
+ return res.outcome;
319
+ }
320
+ var emptyPost = (headers) => ({
321
+ method: "POST",
322
+ headers: { "content-type": "application/json", ...headers },
323
+ body: "{}"
324
+ });
325
+
326
+ // src/presets/aws.ts
265
327
  async function signedCall({
266
328
  http,
267
329
  secrets,
@@ -321,7 +383,170 @@ var s3Bucket = chunkXHXEKB3Q_cjs.definePreset()({
321
383
  return response.outcome;
322
384
  }
323
385
  });
324
- var aws = { credentials, s3Bucket };
386
+ function pingBody(model) {
387
+ if (/(^|\.)cohere\.embed/.test(model)) return { texts: ["ping"], input_type: "search_query" };
388
+ return { anthropic_version: "bedrock-2023-05-31", max_tokens: 1, messages: [{ role: "user", content: "ping" }] };
389
+ }
390
+ var bedrockPreset = chunkXHXEKB3Q_cjs.definePreset()({
391
+ kind: "aws.bedrock",
392
+ requiredFields: ["region"],
393
+ requiredSecrets: "all",
394
+ defaults: { slowMs: 5e3, timeoutMs: 2e4 },
395
+ derive: () => ({
396
+ name: "Amazon Bedrock",
397
+ identity: "aws.bedrock",
398
+ description: "Invokes each monitored model with one token"
399
+ }),
400
+ check: async ({ options, secrets, http }) => {
401
+ const signer = secrets.accessKeyId && secrets.secretAccessKey ? new aws4fetch.AwsClient({
402
+ accessKeyId: secrets.accessKeyId,
403
+ secretAccessKey: secrets.secretAccessKey,
404
+ service: "bedrock",
405
+ region: options.region
406
+ }) : void 0;
407
+ const invoke = async (model) => {
408
+ const url = `https://bedrock-runtime.${options.region}.amazonaws.com/model/${encodeURIComponent(model)}/invoke`;
409
+ const init = {
410
+ method: "POST",
411
+ headers: { "content-type": "application/json", accept: "application/json" },
412
+ body: JSON.stringify(pingBody(model))
413
+ };
414
+ if (!signer) return http(url, { ...init, headers: { ...init.headers, ...bearer(secrets.bearerToken ?? "") } });
415
+ const signed = await signer.sign(url, init);
416
+ return http(signed.url, { ...init, headers: Object.fromEntries(signed.headers.entries()) });
417
+ };
418
+ const instances = await Promise.all(
419
+ [...new Set(options.models)].map(async (model) => {
420
+ const res = await invoke(model);
421
+ return {
422
+ key: model,
423
+ status: res.outcome.status,
424
+ latencyMs: res.status === void 0 ? void 0 : res.latencyMs,
425
+ httpStatus: res.status,
426
+ error: res.outcome.error
427
+ };
428
+ })
429
+ );
430
+ return { ...summarize(instances, "model"), instances, instanceLabels: { key: "Model" } };
431
+ }
432
+ });
433
+ function bedrock(options) {
434
+ const { bearerToken, accessKeyId, secretAccessKey } = options.secrets;
435
+ return bedrockPreset({ ...options, secrets: bearerToken ? { bearerToken } : { accessKeyId, secretAccessKey } });
436
+ }
437
+ var aws = { credentials, s3Bucket, bedrock };
438
+
439
+ // src/presets/neon.ts
440
+ var API = "https://console.neon.tech/api/v2";
441
+ var GB = 1024 ** 3;
442
+ function withKeys2(endpoints, branches) {
443
+ const seen = /* @__PURE__ */ new Map();
444
+ return endpoints.map((endpoint) => {
445
+ const name = branches.get(endpoint.branch_id)?.name ?? endpoint.branch_id;
446
+ const count2 = (seen.get(name) ?? 0) + 1;
447
+ seen.set(name, count2);
448
+ return { endpoint, key: count2 === 1 ? name : `${name}#${count2}` };
449
+ });
450
+ }
451
+ var project = chunkXHXEKB3Q_cjs.definePreset()({
452
+ kind: "neon.project",
453
+ requiredFields: ["projectId"],
454
+ requiredSecrets: ["apiKey"],
455
+ defaults: { slowMs: 1e3 },
456
+ derive: (options) => ({
457
+ name: "Neon",
458
+ identity: `neon.project:${options.projectId ?? ""}`,
459
+ description: "Compute states from the Neon API, then `select 1` on an active compute only"
460
+ }),
461
+ check: async ({ options, secrets, http, measure }) => {
462
+ const base = `${API}/projects/${encodeURIComponent(options.projectId)}`;
463
+ const headers = { ...bearer(secrets.apiKey), accept: "application/json" };
464
+ const [list, info, branchList] = await Promise.all([
465
+ http(`${base}/endpoints`, { headers }),
466
+ http(base, { headers }),
467
+ http(`${base}/branches`, { headers })
468
+ ]);
469
+ if (list.status === 404) {
470
+ return { status: "down", probed: false, httpStatus: 404, error: `Project "${options.projectId}" not found on Neon` };
471
+ }
472
+ const endpoints = list.json?.endpoints;
473
+ if (!list.ok || !Array.isArray(endpoints)) {
474
+ return {
475
+ status: "degraded",
476
+ probed: false,
477
+ httpStatus: list.status,
478
+ error: list.status ? `Neon API HTTP ${list.status}` : `Neon API unreachable: ${list.outcome.error ?? "no response"}`
479
+ };
480
+ }
481
+ if (endpoints.length === 0) return { status: "down", probed: false, error: "No compute: nothing can connect" };
482
+ const branches = branchList.json?.branches ?? [];
483
+ const details = info.json?.project;
484
+ const byId = new Map(branches.map((branch) => [branch.id, branch]));
485
+ const defaultBranch = branches.find((branch) => branch.default)?.id;
486
+ const keyed = withKeys2(endpoints, byId);
487
+ const target = keyed.find(({ endpoint }) => endpoint.id === options.endpoint) ?? (options.endpoint ? void 0 : keyed.find(({ endpoint }) => endpoint.type === "read_write" && endpoint.branch_id === defaultBranch) ?? keyed.find(({ endpoint }) => endpoint.type === "read_write"));
488
+ const ping = options.query && target?.endpoint.current_state === "active" && !target.endpoint.disabled ? await measure(async () => void await options.query("select 1")) : void 0;
489
+ const instances = keyed.map(({ endpoint, key }) => {
490
+ const row = { key, region: endpoint.region_id, id: endpoint.id };
491
+ if (endpoint.disabled) return { ...row, state: "disabled", status: "sleeping" };
492
+ if (endpoint.current_state === "idle") return { ...row, state: "idle", status: "sleeping" };
493
+ if (endpoint.current_state !== "active") return { ...row, state: endpoint.current_state, status: "degraded" };
494
+ if (ping && endpoint.id === target?.endpoint.id) {
495
+ return { ...row, state: "active", status: ping.status, latencyMs: ping.latencyMs, error: ping.error };
496
+ }
497
+ return { ...row, state: "active", status: "up" };
498
+ });
499
+ const usage = [];
500
+ const warnings = [];
501
+ const bar = (entry, warnAbovePct = 90) => {
502
+ usage.push(entry);
503
+ if (entry.limit > 0 && entry.used / entry.limit * 100 >= warnAbovePct) warnings.push(`${entry.label} close to the plan limit`);
504
+ };
505
+ const compute = options.track?.compute;
506
+ if (compute && typeof details?.compute_time_seconds === "number") {
507
+ bar(
508
+ {
509
+ label: "Compute this period",
510
+ used: round(details.compute_time_seconds / 3600),
511
+ limit: compute.maxHours,
512
+ unit: "CU-hours",
513
+ resetsAt: details.consumption_period_end ? Date.parse(details.consumption_period_end) || void 0 : void 0
514
+ },
515
+ compute.warnAbovePct
516
+ );
517
+ }
518
+ const storage = options.track?.storage;
519
+ if (storage && branches.length > 0) {
520
+ const bytes = branches.reduce((sum, branch) => sum + (branch.logical_size ?? 0), 0);
521
+ bar({ label: "Storage", used: round(bytes / GB, 2), limit: storage.maxGb, unit: "GB" }, storage.warnAbovePct);
522
+ }
523
+ const main = instances.find((instance2) => instance2.id === target?.endpoint.id) ?? instances[0];
524
+ const active = instances.filter((instance2) => instance2.state === "active").length;
525
+ let status = main.status;
526
+ let error = main.error;
527
+ if (status === "degraded" && !error) error = `Compute is ${main.state}`;
528
+ if ((status === "up" || status === "sleeping") && warnings.length) {
529
+ status = "degraded";
530
+ error = warnings.join("; ");
531
+ }
532
+ return {
533
+ status,
534
+ probed: !!ping,
535
+ latencyMs: ping?.latencyMs ?? list.latencyMs,
536
+ error,
537
+ metrics: {
538
+ ...details?.pg_version ? { postgres: details.pg_version } : {},
539
+ ...details?.region_id ? { region: details.region_id } : {},
540
+ ...branches.length ? { branches: branches.length } : {},
541
+ computes: `${active}/${instances.length} active`
542
+ },
543
+ usage: usage.length ? usage : void 0,
544
+ instances,
545
+ instanceLabels: { key: "Compute", detail: "Endpoint" }
546
+ };
547
+ }
548
+ });
549
+ var neon = { project };
325
550
 
326
551
  // src/presets/databases.ts
327
552
  var mongoPing = chunkXHXEKB3Q_cjs.definePreset()({
@@ -359,38 +584,6 @@ var postgresPing = chunkXHXEKB3Q_cjs.definePreset()({
359
584
  });
360
585
  var postgres = { ping: postgresPing };
361
586
 
362
- // src/presets/providers/shared.ts
363
- var bearer = (token) => ({ Authorization: `Bearer ${token}` });
364
- var round = (value, digits = 1) => Math.round(value * 10 ** digits) / 10 ** digits;
365
- function base64(text) {
366
- const bytes = new TextEncoder().encode(text);
367
- let binary = "";
368
- for (const byte of bytes) binary += String.fromCharCode(byte);
369
- return btoa(binary);
370
- }
371
- async function call(http, url, init, refine) {
372
- const response = await http(url, init);
373
- if (!response.ok || !refine) return response.outcome;
374
- return { ...response.outcome, ...chunkXHXEKB3Q_cjs.normalizeReturn(refine(response)) };
375
- }
376
- function quota({
377
- label,
378
- used,
379
- limit,
380
- unit,
381
- resetsAt,
382
- warnAbovePct,
383
- warning
384
- }) {
385
- const pct = limit > 0 ? used / limit * 100 : 0;
386
- const over = pct >= warnAbovePct;
387
- return {
388
- status: over ? "degraded" : "up",
389
- error: over ? warning : void 0,
390
- usage: [{ label, used, limit, unit, resetsAt }]
391
- };
392
- }
393
-
394
587
  // src/presets/providers/ai.ts
395
588
  var deepgram = chunkXHXEKB3Q_cjs.definePreset()({
396
589
  kind: "deepgram",
@@ -454,13 +647,33 @@ var openai = chunkXHXEKB3Q_cjs.definePreset()({
454
647
  }
455
648
  )
456
649
  });
650
+ var API2 = "https://api.anthropic.com/v1/models";
457
651
  var anthropic = chunkXHXEKB3Q_cjs.definePreset()({
458
652
  kind: "anthropic",
459
653
  requiredSecrets: ["apiKey"],
460
- derive: () => ({ name: "Anthropic", identity: "anthropic", description: "Lists models" }),
461
- check: ({ secrets, http }) => call(http, "https://api.anthropic.com/v1/models?limit=1", {
462
- headers: { "x-api-key": secrets.apiKey, "anthropic-version": "2023-06-01" }
463
- })
654
+ derive: (options) => ({
655
+ name: "Anthropic",
656
+ identity: "anthropic",
657
+ description: options.track?.models?.length ? "Reads each monitored model" : "Lists models"
658
+ }),
659
+ check: async ({ options, secrets, http }) => {
660
+ const headers = { "x-api-key": secrets.apiKey, "anthropic-version": "2023-06-01" };
661
+ const models = [...new Set(options.track?.models ?? [])];
662
+ if (models.length === 0) return (await http(`${API2}?limit=1`, { headers })).outcome;
663
+ const responses = await Promise.all(
664
+ models.map(async (model) => ({ model, res: await http(`${API2}/${encodeURIComponent(model)}`, { headers }) }))
665
+ );
666
+ const rejected = responses.find(({ res }) => res.status === 401 || res.status === 403);
667
+ if (rejected) return rejected.res.outcome;
668
+ const instances = responses.map(({ model, res }) => {
669
+ const base = { key: model, latencyMs: res.status === void 0 ? void 0 : res.latencyMs, httpStatus: res.status };
670
+ if (res.ok) return { ...base, status: "up" };
671
+ if (res.status === 404) return { ...base, status: "down", error: "Model not found: retired, or not available to this key" };
672
+ if (res.status === 529) return { ...base, status: "degraded", error: "Overloaded" };
673
+ return { ...base, status: res.outcome.status, error: res.outcome.error };
674
+ });
675
+ return { ...summarize(instances, "model"), instances, instanceLabels: { key: "Model" } };
676
+ }
464
677
  });
465
678
  var gemini = chunkXHXEKB3Q_cjs.definePreset()({
466
679
  kind: "gemini",
@@ -880,12 +1093,12 @@ var pusher = chunkXHXEKB3Q_cjs.definePreset()({
880
1093
  let countingDisabled = false;
881
1094
  const counts = await mapLimit(queried, CONCURRENCY, async (name) => {
882
1095
  const res = await get(`/channels/${encodeURIComponent(name)}`, { info: "subscription_count" });
883
- const count = res.json?.subscription_count;
1096
+ const count2 = res.json?.subscription_count;
884
1097
  if (!res.ok) failed += 1;
885
- else if (typeof count !== "number") countingDisabled = true;
886
- return typeof count === "number" ? count : 0;
1098
+ else if (typeof count2 !== "number") countingDisabled = true;
1099
+ return typeof count2 === "number" ? count2 : 0;
887
1100
  });
888
- const connections = counts.reduce((sum, count) => sum + count, 0);
1101
+ const connections = counts.reduce((sum, count2) => sum + count2, 0);
889
1102
  const signedInUsers = queried.reduce(
890
1103
  (sum, name, index) => name.startsWith("#server-to-user-") ? sum + (counts[index] ?? 0) : sum,
891
1104
  0
@@ -968,6 +1181,147 @@ var blob = chunkXHXEKB3Q_cjs.definePreset()({
968
1181
  });
969
1182
  var vercel = { aiGateway, blob };
970
1183
 
1184
+ // src/presets/providers/stripe.ts
1185
+ var API3 = "https://api.stripe.com/v1";
1186
+ var DAY_S = 24 * 60 * 60;
1187
+ var ZERO_DECIMAL = /* @__PURE__ */ new Set(["bif", "clp", "djf", "gnf", "jpy", "kmf", "krw", "mga", "pyg", "rwf", "ugx", "vnd", "vuv", "xaf", "xof", "xpf"]);
1188
+ function money(amounts) {
1189
+ return (amounts ?? []).slice(0, 3).map(({ amount, currency }) => {
1190
+ const value = ZERO_DECIMAL.has(currency) ? String(amount) : (amount / 100).toFixed(2);
1191
+ return `${value} ${currency.toUpperCase()}`;
1192
+ }).join(", ");
1193
+ }
1194
+ function endpointKey(url) {
1195
+ try {
1196
+ const { host, pathname } = new URL(url);
1197
+ return `${host}${pathname}`;
1198
+ } catch {
1199
+ return "endpoint";
1200
+ }
1201
+ }
1202
+ var count = (list) => `${list.data?.length ?? 0}${list.has_more ? "+" : ""}`;
1203
+ var stripe = chunkXHXEKB3Q_cjs.definePreset()({
1204
+ kind: "stripe",
1205
+ requiredSecrets: ["apiKey"],
1206
+ derive: () => ({ name: "Stripe", identity: "stripe", description: "Reads the balance, account and webhook endpoints" }),
1207
+ check: async ({ options, secrets, http, now }) => {
1208
+ const { account = true, webhooks = true, disputes = true } = options.track ?? {};
1209
+ const get = (path) => http(`${API3}${path}`, { headers: bearer(secrets.apiKey) });
1210
+ const skip = Promise.resolve(void 0);
1211
+ const [balance, accountRes, endpoints, undelivered, disputeList] = await Promise.all([
1212
+ get("/balance"),
1213
+ account ? get("/account") : skip,
1214
+ webhooks ? get("/webhook_endpoints?limit=100") : skip,
1215
+ webhooks ? get(`/events?delivery_success=false&limit=100&created[gte]=${Math.floor(now / 1e3) - DAY_S}`) : skip,
1216
+ disputes ? get("/disputes?limit=100") : skip
1217
+ ]);
1218
+ if (!balance.ok && balance.status !== 403) return balance.outcome;
1219
+ const metrics = {};
1220
+ const warnings = [];
1221
+ const funds = balance.ok ? balance.json : void 0;
1222
+ if (funds) {
1223
+ metrics.mode = funds.livemode ? "live" : "test";
1224
+ if (funds.available?.length) metrics.available = money(funds.available);
1225
+ if (funds.pending?.length) metrics.pending = money(funds.pending);
1226
+ } else {
1227
+ metrics.key = "restricted";
1228
+ }
1229
+ if (accountRes?.ok && funds?.livemode) {
1230
+ const body = accountRes.json;
1231
+ if (body.charges_enabled === false) warnings.push("Charges are disabled");
1232
+ if (body.payouts_enabled === false) warnings.push("Payouts are disabled");
1233
+ const overdue = body.requirements?.past_due?.length ?? 0;
1234
+ if (overdue > 0) warnings.push(`${overdue} account requirement(s) past due`);
1235
+ }
1236
+ let instances;
1237
+ if (endpoints?.ok) {
1238
+ const list = endpoints.json.data ?? [];
1239
+ const seen = /* @__PURE__ */ new Set();
1240
+ instances = list.map((endpoint) => {
1241
+ let key = endpointKey(endpoint.url);
1242
+ for (let n = 2; seen.has(key); n++) key = `${endpointKey(endpoint.url)}#${n}`;
1243
+ seen.add(key);
1244
+ const enabled = endpoint.status === "enabled";
1245
+ return { key, id: endpoint.id, state: endpoint.status, status: enabled ? "up" : "down", error: enabled ? void 0 : "Endpoint disabled" };
1246
+ });
1247
+ metrics.webhookEndpoints = list.length;
1248
+ const disabled = instances.filter((instance2) => instance2.status === "down").length;
1249
+ if (disabled > 0) warnings.push(`${disabled} webhook endpoint(s) disabled`);
1250
+ }
1251
+ if (undelivered?.ok) {
1252
+ const list = undelivered.json;
1253
+ metrics.undelivered24h = count(list);
1254
+ if (list.data?.length) warnings.push(`${count(list)} event(s) not delivered in the last 24 h`);
1255
+ }
1256
+ if (disputeList?.ok) {
1257
+ const open = (disputeList.json.data ?? []).filter(
1258
+ (dispute) => dispute.status.endsWith("needs_response")
1259
+ );
1260
+ metrics.openDisputes = open.length;
1261
+ }
1262
+ return {
1263
+ status: warnings.length ? "degraded" : "up",
1264
+ latencyMs: balance.latencyMs,
1265
+ httpStatus: balance.status,
1266
+ error: warnings.join("; ") || void 0,
1267
+ metrics,
1268
+ instances: instances?.length ? instances : void 0,
1269
+ instanceLabels: { key: "Webhook endpoint", detail: "ID" }
1270
+ };
1271
+ }
1272
+ });
1273
+
1274
+ // src/presets/providers/search.ts
1275
+ var exa = chunkXHXEKB3Q_cjs.definePreset()({
1276
+ kind: "exa",
1277
+ requiredSecrets: ["apiKey"],
1278
+ derive: () => ({ name: "Exa", identity: "exa", description: "Validates the API key (no search is run)" }),
1279
+ check: async ({ secrets, http }) => keyAccepted(await http("https://api.exa.ai/search", emptyPost({ "x-api-key": secrets.apiKey })))
1280
+ });
1281
+ var nimble = chunkXHXEKB3Q_cjs.definePreset()({
1282
+ kind: "nimble",
1283
+ requiredSecrets: ["apiKey"],
1284
+ derive: () => ({ name: "Nimble", identity: "nimble", description: "Validates the API key (no search is run)" }),
1285
+ check: async ({ secrets, http }) => keyAccepted(await http("https://sdk.nimbleway.com/v1/search", emptyPost(bearer(secrets.apiKey))))
1286
+ });
1287
+ var tavily = chunkXHXEKB3Q_cjs.definePreset()({
1288
+ kind: "tavily",
1289
+ requiredSecrets: ["apiKey"],
1290
+ derive: () => ({ name: "Tavily", identity: "tavily", description: "Reads the credits used this period" }),
1291
+ check: async ({ options, secrets, http }) => {
1292
+ const res = await http("https://api.tavily.com/usage", { headers: bearer(secrets.apiKey) });
1293
+ if (!res.ok) return res.outcome;
1294
+ const { key, account } = res.json ?? {};
1295
+ const metrics = account?.current_plan ? { plan: account.current_plan } : void 0;
1296
+ const [used, limit] = key?.limit ? [key.usage, key.limit] : [account?.plan_usage, account?.plan_limit];
1297
+ if (typeof used !== "number" || !limit) return { ...res.outcome, metrics };
1298
+ return {
1299
+ ...res.outcome,
1300
+ ...quota({
1301
+ label: "Credits",
1302
+ used,
1303
+ limit,
1304
+ unit: "credits",
1305
+ warnAbovePct: options.track?.quota?.warnAbovePct ?? 90,
1306
+ warning: "Credits almost exhausted"
1307
+ }),
1308
+ metrics
1309
+ };
1310
+ }
1311
+ });
1312
+ var emelia = chunkXHXEKB3Q_cjs.definePreset()({
1313
+ kind: "emelia",
1314
+ requiredSecrets: ["apiKey"],
1315
+ derive: () => ({ name: "Emelia", identity: "emelia", description: "Validates the API key (no lookup is run)" }),
1316
+ check: async ({ options, secrets, http }) => keyAccepted(
1317
+ await http(
1318
+ `${(options.baseUrl ?? "https://api.emelia.io").replace(/\/+$/, "")}/tools/find/email`,
1319
+ // Emelia takes the bare key, without a scheme
1320
+ emptyPost({ Authorization: secrets.apiKey })
1321
+ )
1322
+ )
1323
+ });
1324
+
971
1325
  Object.defineProperty(exports, "generic", {
972
1326
  enumerable: true,
973
1327
  get: function () { return chunkELV4ZU6G_cjs.generic; }
@@ -984,6 +1338,8 @@ exports.crashReason = crashReason;
984
1338
  exports.deepgram = deepgram;
985
1339
  exports.deepl = deepl;
986
1340
  exports.elevenlabs = elevenlabs;
1341
+ exports.emelia = emelia;
1342
+ exports.exa = exa;
987
1343
  exports.fly = fly;
988
1344
  exports.gcp = gcp;
989
1345
  exports.gemini = gemini;
@@ -995,6 +1351,8 @@ exports.mailersend = mailersend;
995
1351
  exports.meilisearch = meilisearch;
996
1352
  exports.mongodb = mongodb;
997
1353
  exports.mux = mux;
1354
+ exports.neon = neon;
1355
+ exports.nimble = nimble;
998
1356
  exports.openai = openai;
999
1357
  exports.parseServiceAccount = parseServiceAccount;
1000
1358
  exports.postgres = postgres;
@@ -1006,6 +1364,8 @@ exports.signGoogleAssertion = signGoogleAssertion;
1006
1364
  exports.signPusherRequest = signPusherRequest;
1007
1365
  exports.speechmatics = speechmatics;
1008
1366
  exports.statuspage = statuspage;
1367
+ exports.stripe = stripe;
1368
+ exports.tavily = tavily;
1009
1369
  exports.upstashRedis = upstashRedis;
1010
1370
  exports.vercel = vercel;
1011
1371
  //# sourceMappingURL=index.cjs.map