@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.cjs CHANGED
@@ -32,6 +32,8 @@ var index_exports = {};
32
32
  __export(index_exports, {
33
33
  AlpacaMarketDataAPI: () => AlpacaMarketDataAPI,
34
34
  AlpacaTradingAPI: () => AlpacaTradingAPI,
35
+ DiscoMailAPI: () => DiscoMailAPI,
36
+ DiscoMailApiError: () => DiscoMailApiError,
35
37
  OPENAI_IMAGE_MODELS: () => OPENAI_IMAGE_MODELS,
36
38
  OPENAI_MODELS: () => OPENAI_MODELS,
37
39
  OPENROUTER_MODELS: () => OPENROUTER_MODELS,
@@ -2544,6 +2546,118 @@ var PerformanceTimer = class {
2544
2546
  }
2545
2547
  };
2546
2548
 
2549
+ // src/disco-mail.ts
2550
+ var DEFAULT_DISCO_MAIL_BASE_URL = "https://mail.discomedia.co/api/v1";
2551
+ var DiscoMailApiError = class extends Error {
2552
+ code;
2553
+ status;
2554
+ constructor(code, message, status) {
2555
+ super(`Disco Mail API error: ${code} ${message}`);
2556
+ this.name = "DiscoMailApiError";
2557
+ this.code = code;
2558
+ this.status = status;
2559
+ }
2560
+ };
2561
+ var DiscoMailAPI = class {
2562
+ constructor(clientOptions = {}) {
2563
+ this.clientOptions = clientOptions;
2564
+ }
2565
+ clientOptions;
2566
+ async send(payload, options = {}) {
2567
+ this.validateSendRequest(payload);
2568
+ const headers = new Headers();
2569
+ if (options.idempotencyKey) {
2570
+ headers.set("Idempotency-Key", options.idempotencyKey);
2571
+ }
2572
+ return this.request("/emails", "POST", options, payload, headers);
2573
+ }
2574
+ async listDomains(options = {}) {
2575
+ return this.request("/domains", "GET", options);
2576
+ }
2577
+ async getDomain(domainId, options = {}) {
2578
+ this.validateDomainId(domainId);
2579
+ return this.request(`/domains/${domainId}`, "GET", options);
2580
+ }
2581
+ async createDomain(payload, options = {}) {
2582
+ if (!payload.name.trim()) {
2583
+ throw new Error("Disco Mail domain name must be a non-empty string");
2584
+ }
2585
+ if (!payload.region.trim()) {
2586
+ throw new Error("Disco Mail domain region must be a non-empty string");
2587
+ }
2588
+ return this.request("/domains", "POST", options, payload);
2589
+ }
2590
+ async verifyDomain(domainId, options = {}) {
2591
+ this.validateDomainId(domainId);
2592
+ return this.request(`/domains/${domainId}/verify`, "PUT", options);
2593
+ }
2594
+ async request(path, method, options, body, additionalHeaders = new Headers()) {
2595
+ const apiKey = this.resolveApiKey(options);
2596
+ const headers = new Headers(additionalHeaders);
2597
+ headers.set("Authorization", `Bearer ${apiKey}`);
2598
+ headers.set("Content-Type", "application/json");
2599
+ const response = await fetch(`${this.resolveBaseUrl(options)}${path}`, {
2600
+ method,
2601
+ headers,
2602
+ ...body ? { body: JSON.stringify(body) } : {}
2603
+ });
2604
+ if (!response.ok) {
2605
+ throw await this.createApiError(response);
2606
+ }
2607
+ return await response.json();
2608
+ }
2609
+ resolveApiKey(options) {
2610
+ const apiKey = options.apiKey || this.clientOptions.apiKey || process.env.DISCO_MAIL_API_KEY || process.env.DISCOMAIL_API_KEY;
2611
+ if (!apiKey) {
2612
+ throw new Error(
2613
+ "Disco Mail API key is not provided. Pass options.apiKey or set DISCO_MAIL_API_KEY or DISCOMAIL_API_KEY."
2614
+ );
2615
+ }
2616
+ return apiKey;
2617
+ }
2618
+ resolveBaseUrl(options) {
2619
+ const baseUrl = options.baseUrl || this.clientOptions.baseUrl || DEFAULT_DISCO_MAIL_BASE_URL;
2620
+ return baseUrl.replace(/\/+$/, "");
2621
+ }
2622
+ validateSendRequest(payload) {
2623
+ const recipients = Array.isArray(payload.to) ? payload.to : [payload.to];
2624
+ if (recipients.length === 0 || recipients.some((recipient) => !recipient.trim())) {
2625
+ throw new Error("Disco Mail send requests require at least one non-empty recipient");
2626
+ }
2627
+ if (!payload.from.trim()) {
2628
+ throw new Error("Disco Mail send requests require a non-empty from address");
2629
+ }
2630
+ if (!payload.subject?.trim() && !payload.templateId?.trim()) {
2631
+ throw new Error("Disco Mail send requests require a non-empty subject or templateId");
2632
+ }
2633
+ if (!payload.html?.trim() && !payload.text?.trim()) {
2634
+ throw new Error("Disco Mail send requests require a non-empty html or text body");
2635
+ }
2636
+ if (payload.attachments && payload.attachments.length > 10) {
2637
+ throw new Error("Disco Mail send requests support a maximum of 10 attachments");
2638
+ }
2639
+ }
2640
+ validateDomainId(domainId) {
2641
+ if (!Number.isInteger(domainId) || domainId <= 0) {
2642
+ throw new Error("Disco Mail domainId must be a positive integer");
2643
+ }
2644
+ }
2645
+ async createApiError(response) {
2646
+ let body = null;
2647
+ try {
2648
+ body = await response.json();
2649
+ } catch {
2650
+ body = null;
2651
+ }
2652
+ const apiError = body?.error ?? body;
2653
+ return new DiscoMailApiError(
2654
+ apiError?.code || `HTTP_${response.status}`,
2655
+ apiError?.message || response.statusText || "Request failed",
2656
+ response.status
2657
+ );
2658
+ }
2659
+ };
2660
+
2547
2661
  // src/alpaca-trading-api.ts
2548
2662
  var import_ws2 = __toESM(require("ws"), 1);
2549
2663
 
@@ -5477,6 +5591,7 @@ var disco = {
5477
5591
  images: makeImagesCall,
5478
5592
  open: makeOpenRouterCall
5479
5593
  },
5594
+ mail: new DiscoMailAPI(),
5480
5595
  time: {
5481
5596
  convertDateToMarketTimeZone,
5482
5597
  getStartAndEndDates,
@@ -5506,6 +5621,8 @@ var disco = {
5506
5621
  0 && (module.exports = {
5507
5622
  AlpacaMarketDataAPI,
5508
5623
  AlpacaTradingAPI,
5624
+ DiscoMailAPI,
5625
+ DiscoMailApiError,
5509
5626
  OPENAI_IMAGE_MODELS,
5510
5627
  OPENAI_MODELS,
5511
5628
  OPENROUTER_MODELS,