@narcisbodea/smstunnel-sdk 1.1.5 → 1.1.7

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.
@@ -3,8 +3,8 @@ import { InjectionToken } from '@angular/core';
3
3
  interface SmsTunnelAngularConfig {
4
4
  /** Your backend base URL (where SmsTunnelModule is mounted) */
5
5
  apiBaseUrl: string;
6
- /** Function that returns auth headers (e.g. JWT) */
7
- getAuthHeaders?: () => Record<string, string>;
6
+ /** Function that returns the current JWT/auth token. SDK adds Authorization: Bearer header automatically. */
7
+ getToken?: () => string | null;
8
8
  /** Poll interval in ms (default: 3000) */
9
9
  pollInterval?: number;
10
10
  }
@@ -79,9 +79,9 @@ interface PairingInfo {
79
79
  }
80
80
  declare class SmsTunnelService {
81
81
  private readonly config;
82
+ private readonly http;
82
83
  private get baseUrl();
83
84
  private readonly prefix;
84
- private authHeaders;
85
85
  /** Get current pairing status */
86
86
  getStatus(): Promise<SmsTunnelStatus>;
87
87
  /** Create a pairing token (generates QR) */
@@ -135,6 +135,7 @@ declare class SmsTunnelService {
135
135
  updateServerUrl(serverUrl: string): Promise<{
136
136
  success: boolean;
137
137
  }>;
138
+ private authHeaders;
138
139
  private get;
139
140
  private post;
140
141
  }
@@ -3,8 +3,8 @@ import { InjectionToken } from '@angular/core';
3
3
  interface SmsTunnelAngularConfig {
4
4
  /** Your backend base URL (where SmsTunnelModule is mounted) */
5
5
  apiBaseUrl: string;
6
- /** Function that returns auth headers (e.g. JWT) */
7
- getAuthHeaders?: () => Record<string, string>;
6
+ /** Function that returns the current JWT/auth token. SDK adds Authorization: Bearer header automatically. */
7
+ getToken?: () => string | null;
8
8
  /** Poll interval in ms (default: 3000) */
9
9
  pollInterval?: number;
10
10
  }
@@ -79,9 +79,9 @@ interface PairingInfo {
79
79
  }
80
80
  declare class SmsTunnelService {
81
81
  private readonly config;
82
+ private readonly http;
82
83
  private get baseUrl();
83
84
  private readonly prefix;
84
- private authHeaders;
85
85
  /** Get current pairing status */
86
86
  getStatus(): Promise<SmsTunnelStatus>;
87
87
  /** Create a pairing token (generates QR) */
@@ -135,6 +135,7 @@ declare class SmsTunnelService {
135
135
  updateServerUrl(serverUrl: string): Promise<{
136
136
  success: boolean;
137
137
  }>;
138
+ private authHeaders;
138
139
  private get;
139
140
  private post;
140
141
  }
@@ -36,6 +36,8 @@ module.exports = __toCommonJS(angular_exports);
36
36
 
37
37
  // src/angular/smstunnel.service.ts
38
38
  var import_core = require("@angular/core");
39
+ var import_http = require("@angular/common/http");
40
+ var import_rxjs = require("rxjs");
39
41
  var SMSTUNNEL_CONFIG = new import_core.InjectionToken("SMSTUNNEL_CONFIG");
40
42
  function provideSmsTunnel(config) {
41
43
  return { provide: SMSTUNNEL_CONFIG, useValue: config };
@@ -43,113 +45,104 @@ function provideSmsTunnel(config) {
43
45
  var SmsTunnelService = class {
44
46
  constructor() {
45
47
  this.config = (0, import_core.inject)(SMSTUNNEL_CONFIG);
48
+ this.http = (0, import_core.inject)(import_http.HttpClient);
46
49
  this.prefix = "smstunnel";
47
50
  }
48
51
  get baseUrl() {
49
52
  return this.config.apiBaseUrl.replace(/\/$/, "");
50
53
  }
51
- authHeaders() {
52
- return this.config.getAuthHeaders ? this.config.getAuthHeaders() : {};
53
- }
54
54
  // ─── Pairing ────────────────────────────────────────
55
55
  /** Get current pairing status */
56
- async getStatus() {
56
+ getStatus() {
57
57
  return this.get(`/${this.prefix}/status`);
58
58
  }
59
59
  /** Create a pairing token (generates QR) */
60
- async createToken() {
60
+ createToken() {
61
61
  return this.post(`/${this.prefix}/create-token`, {});
62
62
  }
63
63
  /** Check pairing status for a token (no auth needed) */
64
- async getPairingStatus(token) {
65
- const res = await fetch(`${this.baseUrl}/${this.prefix}/pairing-status/${token}`);
66
- return res.json();
64
+ getPairingStatus(token) {
65
+ return this.get(`/${this.prefix}/pairing-status/${token}`);
67
66
  }
68
67
  /** Unpair the connected device */
69
- async unpair() {
68
+ unpair() {
70
69
  return this.post(`/${this.prefix}/unpair`, {});
71
70
  }
72
71
  /** List active pairings */
73
- async getPairings() {
72
+ getPairings() {
74
73
  return this.get(`/${this.prefix}/pairings`);
75
74
  }
76
75
  // ─── SMS ────────────────────────────────────────────
77
76
  /** Send a single SMS */
78
- async sendSms(to, message) {
77
+ sendSms(to, message) {
79
78
  return this.post(`/${this.prefix}/send`, { to, message });
80
79
  }
81
80
  /** Send 2FA SMS */
82
- async send2fa(to, code, template) {
81
+ send2fa(to, code, template) {
83
82
  return this.post(`/${this.prefix}/send-2fa`, { to, code, template });
84
83
  }
85
84
  /** Send bulk SMS */
86
- async sendBulk(messages) {
85
+ sendBulk(messages) {
87
86
  return this.post(`/${this.prefix}/send-bulk`, { messages });
88
87
  }
89
88
  /** Get SMS delivery status */
90
- async getSmsStatus(messageId) {
89
+ getSmsStatus(messageId) {
91
90
  return this.get(`/${this.prefix}/sms-status/${messageId}`);
92
91
  }
93
92
  /** Get received SMS (inbox) */
94
- async getReceivedSms() {
93
+ getReceivedSms() {
95
94
  return this.get(`/${this.prefix}/received`);
96
95
  }
97
96
  // ─── Devices & Account ─────────────────────────────
98
97
  /** List paired devices */
99
- async getDevices() {
98
+ getDevices() {
100
99
  return this.get(`/${this.prefix}/devices`);
101
100
  }
102
101
  /** Get account usage stats */
103
- async getUsage() {
102
+ getUsage() {
104
103
  return this.get(`/${this.prefix}/usage`);
105
104
  }
106
105
  // ─── E2E Encryption ────────────────────────────────
107
106
  /** Get E2E encryption status for a device */
108
- async getDeviceE2EStatus(deviceId) {
107
+ getDeviceE2EStatus(deviceId) {
109
108
  return this.get(`/${this.prefix}/e2e-status/${deviceId}`);
110
109
  }
111
110
  /** Get device public key for E2E encryption */
112
- async getDevicePublicKey(deviceId) {
111
+ getDevicePublicKey(deviceId) {
113
112
  return this.get(`/${this.prefix}/public-key/${deviceId}`);
114
113
  }
115
114
  /** Verify device key fingerprint hasn't changed (detect reinstalls) */
116
- async verifyDeviceKey(deviceId, fingerprint) {
115
+ verifyDeviceKey(deviceId, fingerprint) {
117
116
  return this.post(`/${this.prefix}/verify-key`, { deviceId, fingerprint });
118
117
  }
119
118
  /** Send encrypted SMS (payload already encrypted with device's RSA public key) */
120
- async sendEncryptedSms(encryptedPayload, deviceId, is2FA = false) {
119
+ sendEncryptedSms(encryptedPayload, deviceId, is2FA = false) {
121
120
  return this.post(`/${this.prefix}/send-encrypted`, { encryptedPayload, deviceId, is2FA });
122
121
  }
123
122
  // ─── Config ─────────────────────────────────────────
124
123
  /** Update server URL configuration */
125
- async updateServerUrl(serverUrl) {
124
+ updateServerUrl(serverUrl) {
126
125
  return this.post(`/${this.prefix}/update-config`, { serverUrl });
127
126
  }
128
127
  // ─── Internal helpers ──────────────────────────────
129
- async get(path) {
130
- try {
131
- const res = await fetch(`${this.baseUrl}${path}`, {
132
- headers: this.authHeaders()
133
- });
134
- return await res.json();
135
- } catch (err) {
136
- return { success: false, error: err.message };
128
+ authHeaders() {
129
+ if (this.config.getToken) {
130
+ const token = this.config.getToken();
131
+ if (token) {
132
+ return { Authorization: `Bearer ${token}` };
133
+ }
137
134
  }
135
+ return {};
138
136
  }
139
- async post(path, body) {
140
- try {
141
- const res = await fetch(`${this.baseUrl}${path}`, {
142
- method: "POST",
143
- headers: {
144
- "Content-Type": "application/json",
145
- ...this.authHeaders()
146
- },
147
- body: JSON.stringify(body)
148
- });
149
- return await res.json();
150
- } catch (err) {
151
- return { success: false, error: err.message };
152
- }
137
+ get(path) {
138
+ return (0, import_rxjs.lastValueFrom)(
139
+ this.http.get(`${this.baseUrl}${path}`, { headers: this.authHeaders() })
140
+ );
141
+ }
142
+ post(path, body) {
143
+ return (0, import_rxjs.lastValueFrom)(
144
+ this.http.post(`${this.baseUrl}${path}`, body, { headers: this.authHeaders() })
145
+ );
153
146
  }
154
147
  };
155
148
  SmsTunnelService = __decorateClass([
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/angular/index.ts","../../src/angular/smstunnel.service.ts"],"sourcesContent":["export {\r\n SmsTunnelService,\r\n SMSTUNNEL_CONFIG,\r\n provideSmsTunnel,\r\n} from './smstunnel.service';\r\n\r\nexport type {\r\n SmsTunnelAngularConfig,\r\n SmsTunnelStatus,\r\n CreateTokenResult,\r\n PairingStatusResult,\r\n SendSmsResult,\r\n DeviceE2EStatus,\r\n DevicePublicKeyInfo,\r\n VerifyDeviceKeyResult,\r\n DevicesResult,\r\n PairingInfo,\r\n} from './smstunnel.service';\r\n","import { Injectable, InjectionToken, inject } from '@angular/core';\r\n\r\n// ─── Configuration ──────────────────────────────────\r\n\r\nexport interface SmsTunnelAngularConfig {\r\n /** Your backend base URL (where SmsTunnelModule is mounted) */\r\n apiBaseUrl: string;\r\n /** Function that returns auth headers (e.g. JWT) */\r\n getAuthHeaders?: () => Record<string, string>;\r\n /** Poll interval in ms (default: 3000) */\r\n pollInterval?: number;\r\n}\r\n\r\nexport const SMSTUNNEL_CONFIG = new InjectionToken<SmsTunnelAngularConfig>('SMSTUNNEL_CONFIG');\r\n\r\nexport function provideSmsTunnel(config: SmsTunnelAngularConfig) {\r\n return { provide: SMSTUNNEL_CONFIG, useValue: config };\r\n}\r\n\r\n// ─── Response types ─────────────────────────────────\r\n\r\nexport interface SmsTunnelStatus {\r\n paired: boolean;\r\n serverUrl?: string;\r\n deviceName?: string;\r\n}\r\n\r\nexport interface CreateTokenResult {\r\n success: boolean;\r\n token?: string;\r\n qrData?: string;\r\n expiresAt?: string;\r\n pollUrl?: string;\r\n error?: string;\r\n}\r\n\r\nexport interface PairingStatusResult {\r\n status: 'pending' | 'completed' | 'expired' | 'error';\r\n source?: string;\r\n displayName?: string;\r\n pairedDeviceId?: string;\r\n pairingId?: string;\r\n error?: string;\r\n}\r\n\r\nexport interface SendSmsResult {\r\n success: boolean;\r\n messageId?: string;\r\n error?: string;\r\n}\r\n\r\nexport interface DeviceE2EStatus {\r\n encryptionEnabled: boolean;\r\n hasPublicKey: boolean;\r\n publicKeyFingerprint?: string;\r\n keyCreatedAt?: string;\r\n}\r\n\r\nexport interface DevicePublicKeyInfo {\r\n deviceId: string;\r\n deviceName: string;\r\n publicKey: string;\r\n}\r\n\r\nexport interface VerifyDeviceKeyResult {\r\n valid: boolean;\r\n currentFingerprint?: string;\r\n needsRePairing: boolean;\r\n}\r\n\r\nexport interface DevicesResult {\r\n success: boolean;\r\n data?: Array<{\r\n id: string;\r\n clientId: string;\r\n name: string;\r\n brand?: string;\r\n model?: string;\r\n connected?: boolean;\r\n }>;\r\n error?: string;\r\n}\r\n\r\nexport interface PairingInfo {\r\n _id: string;\r\n deviceId: string;\r\n type: string;\r\n name: string;\r\n status: 'active' | 'paused' | 'revoked';\r\n messagesSent: number;\r\n createdAt: string;\r\n source: string;\r\n}\r\n\r\n// ─── Service ────────────────────────────────────────\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class SmsTunnelService {\r\n private readonly config = inject(SMSTUNNEL_CONFIG);\r\n\r\n private get baseUrl(): string {\r\n return this.config.apiBaseUrl.replace(/\\/$/, '');\r\n }\r\n\r\n private readonly prefix = 'smstunnel';\r\n\r\n private authHeaders(): Record<string, string> {\r\n return this.config.getAuthHeaders ? this.config.getAuthHeaders() : {};\r\n }\r\n\r\n // ─── Pairing ────────────────────────────────────────\r\n\r\n /** Get current pairing status */\r\n async getStatus(): Promise<SmsTunnelStatus> {\r\n return this.get(`/${this.prefix}/status`);\r\n }\r\n\r\n /** Create a pairing token (generates QR) */\r\n async createToken(): Promise<CreateTokenResult> {\r\n return this.post(`/${this.prefix}/create-token`, {});\r\n }\r\n\r\n /** Check pairing status for a token (no auth needed) */\r\n async getPairingStatus(token: string): Promise<PairingStatusResult> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/pairing-status/${token}`);\r\n return res.json();\r\n }\r\n\r\n /** Unpair the connected device */\r\n async unpair(): Promise<{ success: boolean }> {\r\n return this.post(`/${this.prefix}/unpair`, {});\r\n }\r\n\r\n /** List active pairings */\r\n async getPairings(): Promise<PairingInfo[]> {\r\n return this.get(`/${this.prefix}/pairings`);\r\n }\r\n\r\n // ─── SMS ────────────────────────────────────────────\r\n\r\n /** Send a single SMS */\r\n async sendSms(to: string, message: string): Promise<SendSmsResult> {\r\n return this.post(`/${this.prefix}/send`, { to, message });\r\n }\r\n\r\n /** Send 2FA SMS */\r\n async send2fa(to: string, code: string, template?: string): Promise<SendSmsResult> {\r\n return this.post(`/${this.prefix}/send-2fa`, { to, code, template });\r\n }\r\n\r\n /** Send bulk SMS */\r\n async sendBulk(messages: Array<{ to: string; message: string }>): Promise<{ success: boolean; results?: any[]; error?: string }> {\r\n return this.post(`/${this.prefix}/send-bulk`, { messages });\r\n }\r\n\r\n /** Get SMS delivery status */\r\n async getSmsStatus(messageId: string): Promise<any> {\r\n return this.get(`/${this.prefix}/sms-status/${messageId}`);\r\n }\r\n\r\n /** Get received SMS (inbox) */\r\n async getReceivedSms(): Promise<any> {\r\n return this.get(`/${this.prefix}/received`);\r\n }\r\n\r\n // ─── Devices & Account ─────────────────────────────\r\n\r\n /** List paired devices */\r\n async getDevices(): Promise<DevicesResult> {\r\n return this.get(`/${this.prefix}/devices`);\r\n }\r\n\r\n /** Get account usage stats */\r\n async getUsage(): Promise<any> {\r\n return this.get(`/${this.prefix}/usage`);\r\n }\r\n\r\n // ─── E2E Encryption ────────────────────────────────\r\n\r\n /** Get E2E encryption status for a device */\r\n async getDeviceE2EStatus(deviceId: string): Promise<{ success: boolean; data?: DeviceE2EStatus; error?: string }> {\r\n return this.get(`/${this.prefix}/e2e-status/${deviceId}`);\r\n }\r\n\r\n /** Get device public key for E2E encryption */\r\n async getDevicePublicKey(deviceId: string): Promise<{ success: boolean; data?: DevicePublicKeyInfo; error?: string }> {\r\n return this.get(`/${this.prefix}/public-key/${deviceId}`);\r\n }\r\n\r\n /** Verify device key fingerprint hasn't changed (detect reinstalls) */\r\n async verifyDeviceKey(deviceId: string, fingerprint: string): Promise<VerifyDeviceKeyResult> {\r\n return this.post(`/${this.prefix}/verify-key`, { deviceId, fingerprint });\r\n }\r\n\r\n /** Send encrypted SMS (payload already encrypted with device's RSA public key) */\r\n async sendEncryptedSms(\r\n encryptedPayload: string,\r\n deviceId: string,\r\n is2FA: boolean = false,\r\n ): Promise<SendSmsResult> {\r\n return this.post(`/${this.prefix}/send-encrypted`, { encryptedPayload, deviceId, is2FA });\r\n }\r\n\r\n // ─── Config ─────────────────────────────────────────\r\n\r\n /** Update server URL configuration */\r\n async updateServerUrl(serverUrl: string): Promise<{ success: boolean }> {\r\n return this.post(`/${this.prefix}/update-config`, { serverUrl });\r\n }\r\n\r\n // ─── Internal helpers ──────────────────────────────\r\n\r\n private async get<T = any>(path: string): Promise<T> {\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n headers: this.authHeaders(),\r\n });\r\n return await res.json();\r\n } catch (err: any) {\r\n return { success: false, error: err.message } as any;\r\n }\r\n }\r\n\r\n private async post<T = any>(path: string, body: any): Promise<T> {\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.authHeaders(),\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n return await res.json();\r\n } catch (err: any) {\r\n return { success: false, error: err.message } as any;\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/angular/index.ts","../../src/angular/smstunnel.service.ts"],"sourcesContent":["export {\r\n SmsTunnelService,\r\n SMSTUNNEL_CONFIG,\r\n provideSmsTunnel,\r\n} from './smstunnel.service';\r\n\r\nexport type {\r\n SmsTunnelAngularConfig,\r\n SmsTunnelStatus,\r\n CreateTokenResult,\r\n PairingStatusResult,\r\n SendSmsResult,\r\n DeviceE2EStatus,\r\n DevicePublicKeyInfo,\r\n VerifyDeviceKeyResult,\r\n DevicesResult,\r\n PairingInfo,\r\n} from './smstunnel.service';\r\n","import { Injectable, InjectionToken, inject } from '@angular/core';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { lastValueFrom } from 'rxjs';\r\n\r\n// ─── Configuration ──────────────────────────────────\r\n\r\nexport interface SmsTunnelAngularConfig {\r\n /** Your backend base URL (where SmsTunnelModule is mounted) */\r\n apiBaseUrl: string;\r\n /** Function that returns the current JWT/auth token. SDK adds Authorization: Bearer header automatically. */\r\n getToken?: () => string | null;\r\n /** Poll interval in ms (default: 3000) */\r\n pollInterval?: number;\r\n}\r\n\r\nexport const SMSTUNNEL_CONFIG = new InjectionToken<SmsTunnelAngularConfig>('SMSTUNNEL_CONFIG');\r\n\r\nexport function provideSmsTunnel(config: SmsTunnelAngularConfig) {\r\n return { provide: SMSTUNNEL_CONFIG, useValue: config };\r\n}\r\n\r\n// ─── Response types ─────────────────────────────────\r\n\r\nexport interface SmsTunnelStatus {\r\n paired: boolean;\r\n serverUrl?: string;\r\n deviceName?: string;\r\n}\r\n\r\nexport interface CreateTokenResult {\r\n success: boolean;\r\n token?: string;\r\n qrData?: string;\r\n expiresAt?: string;\r\n pollUrl?: string;\r\n error?: string;\r\n}\r\n\r\nexport interface PairingStatusResult {\r\n status: 'pending' | 'completed' | 'expired' | 'error';\r\n source?: string;\r\n displayName?: string;\r\n pairedDeviceId?: string;\r\n pairingId?: string;\r\n error?: string;\r\n}\r\n\r\nexport interface SendSmsResult {\r\n success: boolean;\r\n messageId?: string;\r\n error?: string;\r\n}\r\n\r\nexport interface DeviceE2EStatus {\r\n encryptionEnabled: boolean;\r\n hasPublicKey: boolean;\r\n publicKeyFingerprint?: string;\r\n keyCreatedAt?: string;\r\n}\r\n\r\nexport interface DevicePublicKeyInfo {\r\n deviceId: string;\r\n deviceName: string;\r\n publicKey: string;\r\n}\r\n\r\nexport interface VerifyDeviceKeyResult {\r\n valid: boolean;\r\n currentFingerprint?: string;\r\n needsRePairing: boolean;\r\n}\r\n\r\nexport interface DevicesResult {\r\n success: boolean;\r\n data?: Array<{\r\n id: string;\r\n clientId: string;\r\n name: string;\r\n brand?: string;\r\n model?: string;\r\n connected?: boolean;\r\n }>;\r\n error?: string;\r\n}\r\n\r\nexport interface PairingInfo {\r\n _id: string;\r\n deviceId: string;\r\n type: string;\r\n name: string;\r\n status: 'active' | 'paused' | 'revoked';\r\n messagesSent: number;\r\n createdAt: string;\r\n source: string;\r\n}\r\n\r\n// ─── Service ────────────────────────────────────────\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class SmsTunnelService {\r\n private readonly config = inject(SMSTUNNEL_CONFIG);\r\n private readonly http = inject(HttpClient);\r\n\r\n private get baseUrl(): string {\r\n return this.config.apiBaseUrl.replace(/\\/$/, '');\r\n }\r\n\r\n private readonly prefix = 'smstunnel';\r\n\r\n // ─── Pairing ────────────────────────────────────────\r\n\r\n /** Get current pairing status */\r\n getStatus(): Promise<SmsTunnelStatus> {\r\n return this.get(`/${this.prefix}/status`);\r\n }\r\n\r\n /** Create a pairing token (generates QR) */\r\n createToken(): Promise<CreateTokenResult> {\r\n return this.post(`/${this.prefix}/create-token`, {});\r\n }\r\n\r\n /** Check pairing status for a token (no auth needed) */\r\n getPairingStatus(token: string): Promise<PairingStatusResult> {\r\n return this.get(`/${this.prefix}/pairing-status/${token}`);\r\n }\r\n\r\n /** Unpair the connected device */\r\n unpair(): Promise<{ success: boolean }> {\r\n return this.post(`/${this.prefix}/unpair`, {});\r\n }\r\n\r\n /** List active pairings */\r\n getPairings(): Promise<PairingInfo[]> {\r\n return this.get(`/${this.prefix}/pairings`);\r\n }\r\n\r\n // ─── SMS ────────────────────────────────────────────\r\n\r\n /** Send a single SMS */\r\n sendSms(to: string, message: string): Promise<SendSmsResult> {\r\n return this.post(`/${this.prefix}/send`, { to, message });\r\n }\r\n\r\n /** Send 2FA SMS */\r\n send2fa(to: string, code: string, template?: string): Promise<SendSmsResult> {\r\n return this.post(`/${this.prefix}/send-2fa`, { to, code, template });\r\n }\r\n\r\n /** Send bulk SMS */\r\n sendBulk(messages: Array<{ to: string; message: string }>): Promise<{ success: boolean; results?: any[]; error?: string }> {\r\n return this.post(`/${this.prefix}/send-bulk`, { messages });\r\n }\r\n\r\n /** Get SMS delivery status */\r\n getSmsStatus(messageId: string): Promise<any> {\r\n return this.get(`/${this.prefix}/sms-status/${messageId}`);\r\n }\r\n\r\n /** Get received SMS (inbox) */\r\n getReceivedSms(): Promise<any> {\r\n return this.get(`/${this.prefix}/received`);\r\n }\r\n\r\n // ─── Devices & Account ─────────────────────────────\r\n\r\n /** List paired devices */\r\n getDevices(): Promise<DevicesResult> {\r\n return this.get(`/${this.prefix}/devices`);\r\n }\r\n\r\n /** Get account usage stats */\r\n getUsage(): Promise<any> {\r\n return this.get(`/${this.prefix}/usage`);\r\n }\r\n\r\n // ─── E2E Encryption ────────────────────────────────\r\n\r\n /** Get E2E encryption status for a device */\r\n getDeviceE2EStatus(deviceId: string): Promise<{ success: boolean; data?: DeviceE2EStatus; error?: string }> {\r\n return this.get(`/${this.prefix}/e2e-status/${deviceId}`);\r\n }\r\n\r\n /** Get device public key for E2E encryption */\r\n getDevicePublicKey(deviceId: string): Promise<{ success: boolean; data?: DevicePublicKeyInfo; error?: string }> {\r\n return this.get(`/${this.prefix}/public-key/${deviceId}`);\r\n }\r\n\r\n /** Verify device key fingerprint hasn't changed (detect reinstalls) */\r\n verifyDeviceKey(deviceId: string, fingerprint: string): Promise<VerifyDeviceKeyResult> {\r\n return this.post(`/${this.prefix}/verify-key`, { deviceId, fingerprint });\r\n }\r\n\r\n /** Send encrypted SMS (payload already encrypted with device's RSA public key) */\r\n sendEncryptedSms(\r\n encryptedPayload: string,\r\n deviceId: string,\r\n is2FA: boolean = false,\r\n ): Promise<SendSmsResult> {\r\n return this.post(`/${this.prefix}/send-encrypted`, { encryptedPayload, deviceId, is2FA });\r\n }\r\n\r\n // ─── Config ─────────────────────────────────────────\r\n\r\n /** Update server URL configuration */\r\n updateServerUrl(serverUrl: string): Promise<{ success: boolean }> {\r\n return this.post(`/${this.prefix}/update-config`, { serverUrl });\r\n }\r\n\r\n // ─── Internal helpers ──────────────────────────────\r\n\r\n private authHeaders(): Record<string, string> {\r\n if (this.config.getToken) {\r\n const token = this.config.getToken();\r\n if (token) {\r\n return { Authorization: `Bearer ${token}` };\r\n }\r\n }\r\n return {};\r\n }\r\n\r\n private get<T = any>(path: string): Promise<T> {\r\n return lastValueFrom(\r\n this.http.get<T>(`${this.baseUrl}${path}`, { headers: this.authHeaders() }),\r\n );\r\n }\r\n\r\n private post<T = any>(path: string, body: any): Promise<T> {\r\n return lastValueFrom(\r\n this.http.post<T>(`${this.baseUrl}${path}`, body, { headers: this.authHeaders() }),\r\n );\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
@@ -11,6 +11,8 @@ var __decorateClass = (decorators, target, key, kind) => {
11
11
 
12
12
  // src/angular/smstunnel.service.ts
13
13
  import { Injectable, InjectionToken, inject } from "@angular/core";
14
+ import { HttpClient } from "@angular/common/http";
15
+ import { lastValueFrom } from "rxjs";
14
16
  var SMSTUNNEL_CONFIG = new InjectionToken("SMSTUNNEL_CONFIG");
15
17
  function provideSmsTunnel(config) {
16
18
  return { provide: SMSTUNNEL_CONFIG, useValue: config };
@@ -18,113 +20,104 @@ function provideSmsTunnel(config) {
18
20
  var SmsTunnelService = class {
19
21
  constructor() {
20
22
  this.config = inject(SMSTUNNEL_CONFIG);
23
+ this.http = inject(HttpClient);
21
24
  this.prefix = "smstunnel";
22
25
  }
23
26
  get baseUrl() {
24
27
  return this.config.apiBaseUrl.replace(/\/$/, "");
25
28
  }
26
- authHeaders() {
27
- return this.config.getAuthHeaders ? this.config.getAuthHeaders() : {};
28
- }
29
29
  // ─── Pairing ────────────────────────────────────────
30
30
  /** Get current pairing status */
31
- async getStatus() {
31
+ getStatus() {
32
32
  return this.get(`/${this.prefix}/status`);
33
33
  }
34
34
  /** Create a pairing token (generates QR) */
35
- async createToken() {
35
+ createToken() {
36
36
  return this.post(`/${this.prefix}/create-token`, {});
37
37
  }
38
38
  /** Check pairing status for a token (no auth needed) */
39
- async getPairingStatus(token) {
40
- const res = await fetch(`${this.baseUrl}/${this.prefix}/pairing-status/${token}`);
41
- return res.json();
39
+ getPairingStatus(token) {
40
+ return this.get(`/${this.prefix}/pairing-status/${token}`);
42
41
  }
43
42
  /** Unpair the connected device */
44
- async unpair() {
43
+ unpair() {
45
44
  return this.post(`/${this.prefix}/unpair`, {});
46
45
  }
47
46
  /** List active pairings */
48
- async getPairings() {
47
+ getPairings() {
49
48
  return this.get(`/${this.prefix}/pairings`);
50
49
  }
51
50
  // ─── SMS ────────────────────────────────────────────
52
51
  /** Send a single SMS */
53
- async sendSms(to, message) {
52
+ sendSms(to, message) {
54
53
  return this.post(`/${this.prefix}/send`, { to, message });
55
54
  }
56
55
  /** Send 2FA SMS */
57
- async send2fa(to, code, template) {
56
+ send2fa(to, code, template) {
58
57
  return this.post(`/${this.prefix}/send-2fa`, { to, code, template });
59
58
  }
60
59
  /** Send bulk SMS */
61
- async sendBulk(messages) {
60
+ sendBulk(messages) {
62
61
  return this.post(`/${this.prefix}/send-bulk`, { messages });
63
62
  }
64
63
  /** Get SMS delivery status */
65
- async getSmsStatus(messageId) {
64
+ getSmsStatus(messageId) {
66
65
  return this.get(`/${this.prefix}/sms-status/${messageId}`);
67
66
  }
68
67
  /** Get received SMS (inbox) */
69
- async getReceivedSms() {
68
+ getReceivedSms() {
70
69
  return this.get(`/${this.prefix}/received`);
71
70
  }
72
71
  // ─── Devices & Account ─────────────────────────────
73
72
  /** List paired devices */
74
- async getDevices() {
73
+ getDevices() {
75
74
  return this.get(`/${this.prefix}/devices`);
76
75
  }
77
76
  /** Get account usage stats */
78
- async getUsage() {
77
+ getUsage() {
79
78
  return this.get(`/${this.prefix}/usage`);
80
79
  }
81
80
  // ─── E2E Encryption ────────────────────────────────
82
81
  /** Get E2E encryption status for a device */
83
- async getDeviceE2EStatus(deviceId) {
82
+ getDeviceE2EStatus(deviceId) {
84
83
  return this.get(`/${this.prefix}/e2e-status/${deviceId}`);
85
84
  }
86
85
  /** Get device public key for E2E encryption */
87
- async getDevicePublicKey(deviceId) {
86
+ getDevicePublicKey(deviceId) {
88
87
  return this.get(`/${this.prefix}/public-key/${deviceId}`);
89
88
  }
90
89
  /** Verify device key fingerprint hasn't changed (detect reinstalls) */
91
- async verifyDeviceKey(deviceId, fingerprint) {
90
+ verifyDeviceKey(deviceId, fingerprint) {
92
91
  return this.post(`/${this.prefix}/verify-key`, { deviceId, fingerprint });
93
92
  }
94
93
  /** Send encrypted SMS (payload already encrypted with device's RSA public key) */
95
- async sendEncryptedSms(encryptedPayload, deviceId, is2FA = false) {
94
+ sendEncryptedSms(encryptedPayload, deviceId, is2FA = false) {
96
95
  return this.post(`/${this.prefix}/send-encrypted`, { encryptedPayload, deviceId, is2FA });
97
96
  }
98
97
  // ─── Config ─────────────────────────────────────────
99
98
  /** Update server URL configuration */
100
- async updateServerUrl(serverUrl) {
99
+ updateServerUrl(serverUrl) {
101
100
  return this.post(`/${this.prefix}/update-config`, { serverUrl });
102
101
  }
103
102
  // ─── Internal helpers ──────────────────────────────
104
- async get(path) {
105
- try {
106
- const res = await fetch(`${this.baseUrl}${path}`, {
107
- headers: this.authHeaders()
108
- });
109
- return await res.json();
110
- } catch (err) {
111
- return { success: false, error: err.message };
103
+ authHeaders() {
104
+ if (this.config.getToken) {
105
+ const token = this.config.getToken();
106
+ if (token) {
107
+ return { Authorization: `Bearer ${token}` };
108
+ }
112
109
  }
110
+ return {};
113
111
  }
114
- async post(path, body) {
115
- try {
116
- const res = await fetch(`${this.baseUrl}${path}`, {
117
- method: "POST",
118
- headers: {
119
- "Content-Type": "application/json",
120
- ...this.authHeaders()
121
- },
122
- body: JSON.stringify(body)
123
- });
124
- return await res.json();
125
- } catch (err) {
126
- return { success: false, error: err.message };
127
- }
112
+ get(path) {
113
+ return lastValueFrom(
114
+ this.http.get(`${this.baseUrl}${path}`, { headers: this.authHeaders() })
115
+ );
116
+ }
117
+ post(path, body) {
118
+ return lastValueFrom(
119
+ this.http.post(`${this.baseUrl}${path}`, body, { headers: this.authHeaders() })
120
+ );
128
121
  }
129
122
  };
130
123
  SmsTunnelService = __decorateClass([
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/angular/smstunnel.service.ts"],"sourcesContent":["import { Injectable, InjectionToken, inject } from '@angular/core';\r\n\r\n// ─── Configuration ──────────────────────────────────\r\n\r\nexport interface SmsTunnelAngularConfig {\r\n /** Your backend base URL (where SmsTunnelModule is mounted) */\r\n apiBaseUrl: string;\r\n /** Function that returns auth headers (e.g. JWT) */\r\n getAuthHeaders?: () => Record<string, string>;\r\n /** Poll interval in ms (default: 3000) */\r\n pollInterval?: number;\r\n}\r\n\r\nexport const SMSTUNNEL_CONFIG = new InjectionToken<SmsTunnelAngularConfig>('SMSTUNNEL_CONFIG');\r\n\r\nexport function provideSmsTunnel(config: SmsTunnelAngularConfig) {\r\n return { provide: SMSTUNNEL_CONFIG, useValue: config };\r\n}\r\n\r\n// ─── Response types ─────────────────────────────────\r\n\r\nexport interface SmsTunnelStatus {\r\n paired: boolean;\r\n serverUrl?: string;\r\n deviceName?: string;\r\n}\r\n\r\nexport interface CreateTokenResult {\r\n success: boolean;\r\n token?: string;\r\n qrData?: string;\r\n expiresAt?: string;\r\n pollUrl?: string;\r\n error?: string;\r\n}\r\n\r\nexport interface PairingStatusResult {\r\n status: 'pending' | 'completed' | 'expired' | 'error';\r\n source?: string;\r\n displayName?: string;\r\n pairedDeviceId?: string;\r\n pairingId?: string;\r\n error?: string;\r\n}\r\n\r\nexport interface SendSmsResult {\r\n success: boolean;\r\n messageId?: string;\r\n error?: string;\r\n}\r\n\r\nexport interface DeviceE2EStatus {\r\n encryptionEnabled: boolean;\r\n hasPublicKey: boolean;\r\n publicKeyFingerprint?: string;\r\n keyCreatedAt?: string;\r\n}\r\n\r\nexport interface DevicePublicKeyInfo {\r\n deviceId: string;\r\n deviceName: string;\r\n publicKey: string;\r\n}\r\n\r\nexport interface VerifyDeviceKeyResult {\r\n valid: boolean;\r\n currentFingerprint?: string;\r\n needsRePairing: boolean;\r\n}\r\n\r\nexport interface DevicesResult {\r\n success: boolean;\r\n data?: Array<{\r\n id: string;\r\n clientId: string;\r\n name: string;\r\n brand?: string;\r\n model?: string;\r\n connected?: boolean;\r\n }>;\r\n error?: string;\r\n}\r\n\r\nexport interface PairingInfo {\r\n _id: string;\r\n deviceId: string;\r\n type: string;\r\n name: string;\r\n status: 'active' | 'paused' | 'revoked';\r\n messagesSent: number;\r\n createdAt: string;\r\n source: string;\r\n}\r\n\r\n// ─── Service ────────────────────────────────────────\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class SmsTunnelService {\r\n private readonly config = inject(SMSTUNNEL_CONFIG);\r\n\r\n private get baseUrl(): string {\r\n return this.config.apiBaseUrl.replace(/\\/$/, '');\r\n }\r\n\r\n private readonly prefix = 'smstunnel';\r\n\r\n private authHeaders(): Record<string, string> {\r\n return this.config.getAuthHeaders ? this.config.getAuthHeaders() : {};\r\n }\r\n\r\n // ─── Pairing ────────────────────────────────────────\r\n\r\n /** Get current pairing status */\r\n async getStatus(): Promise<SmsTunnelStatus> {\r\n return this.get(`/${this.prefix}/status`);\r\n }\r\n\r\n /** Create a pairing token (generates QR) */\r\n async createToken(): Promise<CreateTokenResult> {\r\n return this.post(`/${this.prefix}/create-token`, {});\r\n }\r\n\r\n /** Check pairing status for a token (no auth needed) */\r\n async getPairingStatus(token: string): Promise<PairingStatusResult> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/pairing-status/${token}`);\r\n return res.json();\r\n }\r\n\r\n /** Unpair the connected device */\r\n async unpair(): Promise<{ success: boolean }> {\r\n return this.post(`/${this.prefix}/unpair`, {});\r\n }\r\n\r\n /** List active pairings */\r\n async getPairings(): Promise<PairingInfo[]> {\r\n return this.get(`/${this.prefix}/pairings`);\r\n }\r\n\r\n // ─── SMS ────────────────────────────────────────────\r\n\r\n /** Send a single SMS */\r\n async sendSms(to: string, message: string): Promise<SendSmsResult> {\r\n return this.post(`/${this.prefix}/send`, { to, message });\r\n }\r\n\r\n /** Send 2FA SMS */\r\n async send2fa(to: string, code: string, template?: string): Promise<SendSmsResult> {\r\n return this.post(`/${this.prefix}/send-2fa`, { to, code, template });\r\n }\r\n\r\n /** Send bulk SMS */\r\n async sendBulk(messages: Array<{ to: string; message: string }>): Promise<{ success: boolean; results?: any[]; error?: string }> {\r\n return this.post(`/${this.prefix}/send-bulk`, { messages });\r\n }\r\n\r\n /** Get SMS delivery status */\r\n async getSmsStatus(messageId: string): Promise<any> {\r\n return this.get(`/${this.prefix}/sms-status/${messageId}`);\r\n }\r\n\r\n /** Get received SMS (inbox) */\r\n async getReceivedSms(): Promise<any> {\r\n return this.get(`/${this.prefix}/received`);\r\n }\r\n\r\n // ─── Devices & Account ─────────────────────────────\r\n\r\n /** List paired devices */\r\n async getDevices(): Promise<DevicesResult> {\r\n return this.get(`/${this.prefix}/devices`);\r\n }\r\n\r\n /** Get account usage stats */\r\n async getUsage(): Promise<any> {\r\n return this.get(`/${this.prefix}/usage`);\r\n }\r\n\r\n // ─── E2E Encryption ────────────────────────────────\r\n\r\n /** Get E2E encryption status for a device */\r\n async getDeviceE2EStatus(deviceId: string): Promise<{ success: boolean; data?: DeviceE2EStatus; error?: string }> {\r\n return this.get(`/${this.prefix}/e2e-status/${deviceId}`);\r\n }\r\n\r\n /** Get device public key for E2E encryption */\r\n async getDevicePublicKey(deviceId: string): Promise<{ success: boolean; data?: DevicePublicKeyInfo; error?: string }> {\r\n return this.get(`/${this.prefix}/public-key/${deviceId}`);\r\n }\r\n\r\n /** Verify device key fingerprint hasn't changed (detect reinstalls) */\r\n async verifyDeviceKey(deviceId: string, fingerprint: string): Promise<VerifyDeviceKeyResult> {\r\n return this.post(`/${this.prefix}/verify-key`, { deviceId, fingerprint });\r\n }\r\n\r\n /** Send encrypted SMS (payload already encrypted with device's RSA public key) */\r\n async sendEncryptedSms(\r\n encryptedPayload: string,\r\n deviceId: string,\r\n is2FA: boolean = false,\r\n ): Promise<SendSmsResult> {\r\n return this.post(`/${this.prefix}/send-encrypted`, { encryptedPayload, deviceId, is2FA });\r\n }\r\n\r\n // ─── Config ─────────────────────────────────────────\r\n\r\n /** Update server URL configuration */\r\n async updateServerUrl(serverUrl: string): Promise<{ success: boolean }> {\r\n return this.post(`/${this.prefix}/update-config`, { serverUrl });\r\n }\r\n\r\n // ─── Internal helpers ──────────────────────────────\r\n\r\n private async get<T = any>(path: string): Promise<T> {\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n headers: this.authHeaders(),\r\n });\r\n return await res.json();\r\n } catch (err: any) {\r\n return { success: false, error: err.message } as any;\r\n }\r\n }\r\n\r\n private async post<T = any>(path: string, body: any): Promise<T> {\r\n try {\r\n const res = await fetch(`${this.baseUrl}${path}`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.authHeaders(),\r\n },\r\n body: JSON.stringify(body),\r\n });\r\n return await res.json();\r\n } catch (err: any) {\r\n return { success: false, error: err.message } as any;\r\n }\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../../src/angular/smstunnel.service.ts"],"sourcesContent":["import { Injectable, InjectionToken, inject } from '@angular/core';\r\nimport { HttpClient } from '@angular/common/http';\r\nimport { lastValueFrom } from 'rxjs';\r\n\r\n// ─── Configuration ──────────────────────────────────\r\n\r\nexport interface SmsTunnelAngularConfig {\r\n /** Your backend base URL (where SmsTunnelModule is mounted) */\r\n apiBaseUrl: string;\r\n /** Function that returns the current JWT/auth token. SDK adds Authorization: Bearer header automatically. */\r\n getToken?: () => string | null;\r\n /** Poll interval in ms (default: 3000) */\r\n pollInterval?: number;\r\n}\r\n\r\nexport const SMSTUNNEL_CONFIG = new InjectionToken<SmsTunnelAngularConfig>('SMSTUNNEL_CONFIG');\r\n\r\nexport function provideSmsTunnel(config: SmsTunnelAngularConfig) {\r\n return { provide: SMSTUNNEL_CONFIG, useValue: config };\r\n}\r\n\r\n// ─── Response types ─────────────────────────────────\r\n\r\nexport interface SmsTunnelStatus {\r\n paired: boolean;\r\n serverUrl?: string;\r\n deviceName?: string;\r\n}\r\n\r\nexport interface CreateTokenResult {\r\n success: boolean;\r\n token?: string;\r\n qrData?: string;\r\n expiresAt?: string;\r\n pollUrl?: string;\r\n error?: string;\r\n}\r\n\r\nexport interface PairingStatusResult {\r\n status: 'pending' | 'completed' | 'expired' | 'error';\r\n source?: string;\r\n displayName?: string;\r\n pairedDeviceId?: string;\r\n pairingId?: string;\r\n error?: string;\r\n}\r\n\r\nexport interface SendSmsResult {\r\n success: boolean;\r\n messageId?: string;\r\n error?: string;\r\n}\r\n\r\nexport interface DeviceE2EStatus {\r\n encryptionEnabled: boolean;\r\n hasPublicKey: boolean;\r\n publicKeyFingerprint?: string;\r\n keyCreatedAt?: string;\r\n}\r\n\r\nexport interface DevicePublicKeyInfo {\r\n deviceId: string;\r\n deviceName: string;\r\n publicKey: string;\r\n}\r\n\r\nexport interface VerifyDeviceKeyResult {\r\n valid: boolean;\r\n currentFingerprint?: string;\r\n needsRePairing: boolean;\r\n}\r\n\r\nexport interface DevicesResult {\r\n success: boolean;\r\n data?: Array<{\r\n id: string;\r\n clientId: string;\r\n name: string;\r\n brand?: string;\r\n model?: string;\r\n connected?: boolean;\r\n }>;\r\n error?: string;\r\n}\r\n\r\nexport interface PairingInfo {\r\n _id: string;\r\n deviceId: string;\r\n type: string;\r\n name: string;\r\n status: 'active' | 'paused' | 'revoked';\r\n messagesSent: number;\r\n createdAt: string;\r\n source: string;\r\n}\r\n\r\n// ─── Service ────────────────────────────────────────\r\n\r\n@Injectable({ providedIn: 'root' })\r\nexport class SmsTunnelService {\r\n private readonly config = inject(SMSTUNNEL_CONFIG);\r\n private readonly http = inject(HttpClient);\r\n\r\n private get baseUrl(): string {\r\n return this.config.apiBaseUrl.replace(/\\/$/, '');\r\n }\r\n\r\n private readonly prefix = 'smstunnel';\r\n\r\n // ─── Pairing ────────────────────────────────────────\r\n\r\n /** Get current pairing status */\r\n getStatus(): Promise<SmsTunnelStatus> {\r\n return this.get(`/${this.prefix}/status`);\r\n }\r\n\r\n /** Create a pairing token (generates QR) */\r\n createToken(): Promise<CreateTokenResult> {\r\n return this.post(`/${this.prefix}/create-token`, {});\r\n }\r\n\r\n /** Check pairing status for a token (no auth needed) */\r\n getPairingStatus(token: string): Promise<PairingStatusResult> {\r\n return this.get(`/${this.prefix}/pairing-status/${token}`);\r\n }\r\n\r\n /** Unpair the connected device */\r\n unpair(): Promise<{ success: boolean }> {\r\n return this.post(`/${this.prefix}/unpair`, {});\r\n }\r\n\r\n /** List active pairings */\r\n getPairings(): Promise<PairingInfo[]> {\r\n return this.get(`/${this.prefix}/pairings`);\r\n }\r\n\r\n // ─── SMS ────────────────────────────────────────────\r\n\r\n /** Send a single SMS */\r\n sendSms(to: string, message: string): Promise<SendSmsResult> {\r\n return this.post(`/${this.prefix}/send`, { to, message });\r\n }\r\n\r\n /** Send 2FA SMS */\r\n send2fa(to: string, code: string, template?: string): Promise<SendSmsResult> {\r\n return this.post(`/${this.prefix}/send-2fa`, { to, code, template });\r\n }\r\n\r\n /** Send bulk SMS */\r\n sendBulk(messages: Array<{ to: string; message: string }>): Promise<{ success: boolean; results?: any[]; error?: string }> {\r\n return this.post(`/${this.prefix}/send-bulk`, { messages });\r\n }\r\n\r\n /** Get SMS delivery status */\r\n getSmsStatus(messageId: string): Promise<any> {\r\n return this.get(`/${this.prefix}/sms-status/${messageId}`);\r\n }\r\n\r\n /** Get received SMS (inbox) */\r\n getReceivedSms(): Promise<any> {\r\n return this.get(`/${this.prefix}/received`);\r\n }\r\n\r\n // ─── Devices & Account ─────────────────────────────\r\n\r\n /** List paired devices */\r\n getDevices(): Promise<DevicesResult> {\r\n return this.get(`/${this.prefix}/devices`);\r\n }\r\n\r\n /** Get account usage stats */\r\n getUsage(): Promise<any> {\r\n return this.get(`/${this.prefix}/usage`);\r\n }\r\n\r\n // ─── E2E Encryption ────────────────────────────────\r\n\r\n /** Get E2E encryption status for a device */\r\n getDeviceE2EStatus(deviceId: string): Promise<{ success: boolean; data?: DeviceE2EStatus; error?: string }> {\r\n return this.get(`/${this.prefix}/e2e-status/${deviceId}`);\r\n }\r\n\r\n /** Get device public key for E2E encryption */\r\n getDevicePublicKey(deviceId: string): Promise<{ success: boolean; data?: DevicePublicKeyInfo; error?: string }> {\r\n return this.get(`/${this.prefix}/public-key/${deviceId}`);\r\n }\r\n\r\n /** Verify device key fingerprint hasn't changed (detect reinstalls) */\r\n verifyDeviceKey(deviceId: string, fingerprint: string): Promise<VerifyDeviceKeyResult> {\r\n return this.post(`/${this.prefix}/verify-key`, { deviceId, fingerprint });\r\n }\r\n\r\n /** Send encrypted SMS (payload already encrypted with device's RSA public key) */\r\n sendEncryptedSms(\r\n encryptedPayload: string,\r\n deviceId: string,\r\n is2FA: boolean = false,\r\n ): Promise<SendSmsResult> {\r\n return this.post(`/${this.prefix}/send-encrypted`, { encryptedPayload, deviceId, is2FA });\r\n }\r\n\r\n // ─── Config ─────────────────────────────────────────\r\n\r\n /** Update server URL configuration */\r\n updateServerUrl(serverUrl: string): Promise<{ success: boolean }> {\r\n return this.post(`/${this.prefix}/update-config`, { serverUrl });\r\n }\r\n\r\n // ─── Internal helpers ──────────────────────────────\r\n\r\n private authHeaders(): Record<string, string> {\r\n if (this.config.getToken) {\r\n const token = this.config.getToken();\r\n if (token) {\r\n return { Authorization: `Bearer ${token}` };\r\n }\r\n }\r\n return {};\r\n }\r\n\r\n private get<T = any>(path: string): Promise<T> {\r\n return lastValueFrom(\r\n this.http.get<T>(`${this.baseUrl}${path}`, { headers: this.authHeaders() }),\r\n );\r\n }\r\n\r\n private post<T = any>(path: string, body: any): Promise<T> {\r\n return lastValueFrom(\r\n this.http.post<T>(`${this.baseUrl}${path}`, body, { headers: this.authHeaders() }),\r\n );\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
package/dist/index.d.mts CHANGED
@@ -76,6 +76,9 @@ declare const RO_LABELS: SmsTunnelLabels;
76
76
  */
77
77
  interface SmsTunnelClientOptions {
78
78
  apiBaseUrl: string;
79
+ /** Return the current JWT/auth token. SDK adds Authorization: Bearer header automatically. */
80
+ getToken?: () => string | null;
81
+ /** Full control over auth headers. Takes precedence over getToken. */
79
82
  getAuthHeaders?: () => Record<string, string>;
80
83
  pollInterval?: number;
81
84
  }
package/dist/index.d.ts CHANGED
@@ -76,6 +76,9 @@ declare const RO_LABELS: SmsTunnelLabels;
76
76
  */
77
77
  interface SmsTunnelClientOptions {
78
78
  apiBaseUrl: string;
79
+ /** Return the current JWT/auth token. SDK adds Authorization: Bearer header automatically. */
80
+ getToken?: () => string | null;
81
+ /** Full control over auth headers. Takes precedence over getToken. */
79
82
  getAuthHeaders?: () => Record<string, string>;
80
83
  pollInterval?: number;
81
84
  }
package/dist/index.js CHANGED
@@ -83,7 +83,18 @@ var SmsTunnelClient = class {
83
83
  this.pollTimer = null;
84
84
  this.baseUrl = options.apiBaseUrl.replace(/\/$/, "");
85
85
  this.pollInterval = options.pollInterval || 3e3;
86
- this.getAuthHeaders = options.getAuthHeaders || (() => ({}));
86
+ if (options.getAuthHeaders) {
87
+ this.getAuthHeaders = options.getAuthHeaders;
88
+ } else if (options.getToken) {
89
+ const getToken = options.getToken;
90
+ this.getAuthHeaders = () => {
91
+ const token = getToken();
92
+ if (token) return { Authorization: `Bearer ${token}` };
93
+ return {};
94
+ };
95
+ } else {
96
+ this.getAuthHeaders = () => ({});
97
+ }
87
98
  }
88
99
  // ─── Pairing ───────────────────────────────────────
89
100
  /** Get current pairing status */