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