@discomedia/utils 1.0.78 → 1.0.79

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.mjs CHANGED
@@ -2504,6 +2504,118 @@ var PerformanceTimer = class {
2504
2504
  }
2505
2505
  };
2506
2506
 
2507
+ // src/disco-mail.ts
2508
+ var DEFAULT_DISCO_MAIL_BASE_URL = "https://mail.discomedia.co/api/v1";
2509
+ var DiscoMailApiError = class extends Error {
2510
+ code;
2511
+ status;
2512
+ constructor(code, message, status) {
2513
+ super(`Disco Mail API error: ${code} ${message}`);
2514
+ this.name = "DiscoMailApiError";
2515
+ this.code = code;
2516
+ this.status = status;
2517
+ }
2518
+ };
2519
+ var DiscoMailAPI = class {
2520
+ constructor(clientOptions = {}) {
2521
+ this.clientOptions = clientOptions;
2522
+ }
2523
+ clientOptions;
2524
+ async send(payload, options = {}) {
2525
+ this.validateSendRequest(payload);
2526
+ const headers = new Headers();
2527
+ if (options.idempotencyKey) {
2528
+ headers.set("Idempotency-Key", options.idempotencyKey);
2529
+ }
2530
+ return this.request("/emails", "POST", options, payload, headers);
2531
+ }
2532
+ async listDomains(options = {}) {
2533
+ return this.request("/domains", "GET", options);
2534
+ }
2535
+ async getDomain(domainId, options = {}) {
2536
+ this.validateDomainId(domainId);
2537
+ return this.request(`/domains/${domainId}`, "GET", options);
2538
+ }
2539
+ async createDomain(payload, options = {}) {
2540
+ if (!payload.name.trim()) {
2541
+ throw new Error("Disco Mail domain name must be a non-empty string");
2542
+ }
2543
+ if (!payload.region.trim()) {
2544
+ throw new Error("Disco Mail domain region must be a non-empty string");
2545
+ }
2546
+ return this.request("/domains", "POST", options, payload);
2547
+ }
2548
+ async verifyDomain(domainId, options = {}) {
2549
+ this.validateDomainId(domainId);
2550
+ return this.request(`/domains/${domainId}/verify`, "PUT", options);
2551
+ }
2552
+ async request(path, method, options, body, additionalHeaders = new Headers()) {
2553
+ const apiKey = this.resolveApiKey(options);
2554
+ const headers = new Headers(additionalHeaders);
2555
+ headers.set("Authorization", `Bearer ${apiKey}`);
2556
+ headers.set("Content-Type", "application/json");
2557
+ const response = await fetch(`${this.resolveBaseUrl(options)}${path}`, {
2558
+ method,
2559
+ headers,
2560
+ ...body ? { body: JSON.stringify(body) } : {}
2561
+ });
2562
+ if (!response.ok) {
2563
+ throw await this.createApiError(response);
2564
+ }
2565
+ return await response.json();
2566
+ }
2567
+ resolveApiKey(options) {
2568
+ const apiKey = options.apiKey || this.clientOptions.apiKey || process.env.DISCO_MAIL_API_KEY || process.env.DISCOMAIL_API_KEY;
2569
+ if (!apiKey) {
2570
+ throw new Error(
2571
+ "Disco Mail API key is not provided. Pass options.apiKey or set DISCO_MAIL_API_KEY or DISCOMAIL_API_KEY."
2572
+ );
2573
+ }
2574
+ return apiKey;
2575
+ }
2576
+ resolveBaseUrl(options) {
2577
+ const baseUrl = options.baseUrl || this.clientOptions.baseUrl || DEFAULT_DISCO_MAIL_BASE_URL;
2578
+ return baseUrl.replace(/\/+$/, "");
2579
+ }
2580
+ validateSendRequest(payload) {
2581
+ const recipients = Array.isArray(payload.to) ? payload.to : [payload.to];
2582
+ if (recipients.length === 0 || recipients.some((recipient) => !recipient.trim())) {
2583
+ throw new Error("Disco Mail send requests require at least one non-empty recipient");
2584
+ }
2585
+ if (!payload.from.trim()) {
2586
+ throw new Error("Disco Mail send requests require a non-empty from address");
2587
+ }
2588
+ if (!payload.subject?.trim() && !payload.templateId?.trim()) {
2589
+ throw new Error("Disco Mail send requests require a non-empty subject or templateId");
2590
+ }
2591
+ if (!payload.html?.trim() && !payload.text?.trim()) {
2592
+ throw new Error("Disco Mail send requests require a non-empty html or text body");
2593
+ }
2594
+ if (payload.attachments && payload.attachments.length > 10) {
2595
+ throw new Error("Disco Mail send requests support a maximum of 10 attachments");
2596
+ }
2597
+ }
2598
+ validateDomainId(domainId) {
2599
+ if (!Number.isInteger(domainId) || domainId <= 0) {
2600
+ throw new Error("Disco Mail domainId must be a positive integer");
2601
+ }
2602
+ }
2603
+ async createApiError(response) {
2604
+ let body = null;
2605
+ try {
2606
+ body = await response.json();
2607
+ } catch {
2608
+ body = null;
2609
+ }
2610
+ const apiError = body?.error ?? body;
2611
+ return new DiscoMailApiError(
2612
+ apiError?.code || `HTTP_${response.status}`,
2613
+ apiError?.message || response.statusText || "Request failed",
2614
+ response.status
2615
+ );
2616
+ }
2617
+ };
2618
+
2507
2619
  // src/alpaca-trading-api.ts
2508
2620
  import WebSocket2 from "ws";
2509
2621
 
@@ -5437,6 +5549,7 @@ var disco = {
5437
5549
  images: makeImagesCall,
5438
5550
  open: makeOpenRouterCall
5439
5551
  },
5552
+ mail: new DiscoMailAPI(),
5440
5553
  time: {
5441
5554
  convertDateToMarketTimeZone,
5442
5555
  getStartAndEndDates,
@@ -5465,6 +5578,8 @@ var disco = {
5465
5578
  export {
5466
5579
  AlpacaMarketDataAPI,
5467
5580
  AlpacaTradingAPI,
5581
+ DiscoMailAPI,
5582
+ DiscoMailApiError,
5468
5583
  OPENAI_IMAGE_MODELS,
5469
5584
  OPENAI_MODELS,
5470
5585
  OPENROUTER_MODELS,