File size: 4,918 Bytes
46252cd
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
/**
 * OpenWA JavaScript/TypeScript SDK β€” client core.
 *
 * The {@link OpenWAClient} is the single entry point. It holds configuration
 * (base URL, API key, timeout, injectable transport) and exposes domain
 * resources as properties:
 *
 * ```typescript
 * import { OpenWAClient } from '@rmyndharis/openwa';
 *
 * const client = new OpenWAClient({
 *   baseUrl: 'http://localhost:2785',
 *   apiKey: 'owa_k1_…',
 * });
 *
 * await client.sessions.start('my-session');
 * await client.messages.sendText('my-session', {
 *   chatId: '628123456789@c.us',
 *   text: 'Hello from the OpenWA SDK!',
 * });
 * ```
 *
 * @packageDocumentation
 */

import { request, encodeSegment, warnIfInsecureHttpUrl, type ClientConfig, type FetchLike, type RequestOptions } from './http.js';
import { CallsResource } from './resources/calls.js';
import { CatalogResource } from './resources/catalog.js';
import { ChannelsResource } from './resources/channels.js';
import { ChatsResource } from './resources/chats.js';
import { ContactsResource } from './resources/contacts.js';
import { GroupsResource } from './resources/groups.js';
import { HealthResource } from './resources/health.js';
import { LabelsResource } from './resources/labels.js';
import { MessagesResource } from './resources/messages.js';
import { ProfileResource } from './resources/profile.js';
import { SearchResource } from './resources/search.js';
import { SessionsResource } from './resources/sessions.js';
import { StatusResource } from './resources/status.js';
import { TemplatesResource } from './resources/templates.js';
import { WebhooksResource } from './resources/webhooks.js';
import type { AuthValidateResponse, MessageResponse, SendMediaRequest } from './types.js';

export interface OpenWAClientOptions {
  /** Base URL of the OpenWA API, e.g. `http://localhost:2785`. */
  baseUrl: string;
  /** API key sent as `X-API-Key`. */
  apiKey: string;
  /** Per-request timeout in milliseconds (default 30000). */
  timeoutMs?: number;
  /** Default headers applied to every request. */
  defaultHeaders?: Record<string, string>;
  /** Injectable transport; defaults to the global `fetch`. */
  fetch?: FetchLike;
}

export class OpenWAClient {
  private readonly config: Required<Omit<ClientConfig, 'fetch'>> & { fetch: FetchLike };

  constructor(options: OpenWAClientOptions) {
    if (!options.baseUrl) throw new Error('OpenWAClient: baseUrl is required');
    if (!options.apiKey) throw new Error('OpenWAClient: apiKey is required');

    this.config = {
      baseUrl: options.baseUrl,
      apiKey: options.apiKey,
      timeoutMs: options.timeoutMs ?? 30000,
      defaultHeaders: options.defaultHeaders ?? {},
      fetch: options.fetch ?? globalThis.fetch,
    };

    warnIfInsecureHttpUrl(options.baseUrl);
  }

  // ── Resources ────────────────────────────────────────────────────

  readonly sessions = new SessionsResource(this);
  readonly messages = new MessagesResource(this);
  readonly contacts = new ContactsResource(this);
  readonly groups = new GroupsResource(this);
  readonly webhooks = new WebhooksResource(this);
  readonly chats = new ChatsResource(this);
  readonly status = new StatusResource(this);
  readonly health = new HealthResource(this);
  readonly labels = new LabelsResource(this);
  readonly channels = new ChannelsResource(this);
  readonly catalog = new CatalogResource(this);
  readonly templates = new TemplatesResource(this);
  readonly search = new SearchResource(this);
  readonly profile = new ProfileResource(this);
  readonly calls = new CallsResource(this);

  // ── Auth ─────────────────────────────────────────────────────────

  /** Validate the configured API key and resolve its role. */
  auth(): Promise<AuthValidateResponse> {
    return this.request<AuthValidateResponse>({ method: 'POST', path: '/api/auth/validate' });
  }

  // ── Internal API ─────────────────────────────────────────────────

  /** Issue a raw request against the API. (Public for advanced use.) */
  request<T>(options: RequestOptions): Promise<T> {
    return request<T>(this.config, options);
  }

  /**
   * Shared transport helper for image/video/audio/document/sticker sends. Public resource methods
   * expose the narrower per-route request types (including audio-only `ptt`).
   */
  sendMedia(sessionId: string, segment: string, body: SendMediaRequest): Promise<MessageResponse> {
    return this.request<MessageResponse>({
      method: 'POST',
      path: `/api/sessions/${encodeSegment(sessionId)}/messages/${segment}`,
      body,
    });
  }
}

export default OpenWAClient;