@narcisbodea/smstunnel-sdk 1.1.4 → 1.1.6

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,10 +3,6 @@ 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>;
8
- /** Route prefix (default: 'smstunnel') */
9
- routePrefix?: string;
10
6
  /** Poll interval in ms (default: 3000) */
11
7
  pollInterval?: number;
12
8
  }
@@ -81,9 +77,9 @@ interface PairingInfo {
81
77
  }
82
78
  declare class SmsTunnelService {
83
79
  private readonly config;
80
+ private readonly http;
84
81
  private get baseUrl();
85
- private get prefix();
86
- private authHeaders;
82
+ private readonly prefix;
87
83
  /** Get current pairing status */
88
84
  getStatus(): Promise<SmsTunnelStatus>;
89
85
  /** Create a pairing token (generates QR) */
@@ -3,10 +3,6 @@ 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>;
8
- /** Route prefix (default: 'smstunnel') */
9
- routePrefix?: string;
10
6
  /** Poll interval in ms (default: 3000) */
11
7
  pollInterval?: number;
12
8
  }
@@ -81,9 +77,9 @@ interface PairingInfo {
81
77
  }
82
78
  declare class SmsTunnelService {
83
79
  private readonly config;
80
+ private readonly http;
84
81
  private get baseUrl();
85
- private get prefix();
86
- private authHeaders;
82
+ private readonly prefix;
87
83
  /** Get current pairing status */
88
84
  getStatus(): Promise<SmsTunnelStatus>;
89
85
  /** Create a pairing token (generates QR) */
@@ -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,115 +45,91 @@ 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);
49
+ this.prefix = "smstunnel";
46
50
  }
47
51
  get baseUrl() {
48
52
  return this.config.apiBaseUrl.replace(/\/$/, "");
49
53
  }
50
- get prefix() {
51
- return this.config.routePrefix || "smstunnel";
52
- }
53
- authHeaders() {
54
- return this.config.getAuthHeaders ? this.config.getAuthHeaders() : {};
55
- }
56
54
  // ─── Pairing ────────────────────────────────────────
57
55
  /** Get current pairing status */
58
- async getStatus() {
56
+ getStatus() {
59
57
  return this.get(`/${this.prefix}/status`);
60
58
  }
61
59
  /** Create a pairing token (generates QR) */
62
- async createToken() {
60
+ createToken() {
63
61
  return this.post(`/${this.prefix}/create-token`, {});
64
62
  }
65
63
  /** Check pairing status for a token (no auth needed) */
66
- async getPairingStatus(token) {
67
- const res = await fetch(`${this.baseUrl}/${this.prefix}/pairing-status/${token}`);
68
- return res.json();
64
+ getPairingStatus(token) {
65
+ return this.get(`/${this.prefix}/pairing-status/${token}`);
69
66
  }
70
67
  /** Unpair the connected device */
71
- async unpair() {
68
+ unpair() {
72
69
  return this.post(`/${this.prefix}/unpair`, {});
73
70
  }
74
71
  /** List active pairings */
75
- async getPairings() {
72
+ getPairings() {
76
73
  return this.get(`/${this.prefix}/pairings`);
77
74
  }
78
75
  // ─── SMS ────────────────────────────────────────────
79
76
  /** Send a single SMS */
80
- async sendSms(to, message) {
77
+ sendSms(to, message) {
81
78
  return this.post(`/${this.prefix}/send`, { to, message });
82
79
  }
83
80
  /** Send 2FA SMS */
84
- async send2fa(to, code, template) {
81
+ send2fa(to, code, template) {
85
82
  return this.post(`/${this.prefix}/send-2fa`, { to, code, template });
86
83
  }
87
84
  /** Send bulk SMS */
88
- async sendBulk(messages) {
85
+ sendBulk(messages) {
89
86
  return this.post(`/${this.prefix}/send-bulk`, { messages });
90
87
  }
91
88
  /** Get SMS delivery status */
92
- async getSmsStatus(messageId) {
89
+ getSmsStatus(messageId) {
93
90
  return this.get(`/${this.prefix}/sms-status/${messageId}`);
94
91
  }
95
92
  /** Get received SMS (inbox) */
96
- async getReceivedSms() {
93
+ getReceivedSms() {
97
94
  return this.get(`/${this.prefix}/received`);
98
95
  }
99
96
  // ─── Devices & Account ─────────────────────────────
100
97
  /** List paired devices */
101
- async getDevices() {
98
+ getDevices() {
102
99
  return this.get(`/${this.prefix}/devices`);
103
100
  }
104
101
  /** Get account usage stats */
105
- async getUsage() {
102
+ getUsage() {
106
103
  return this.get(`/${this.prefix}/usage`);
107
104
  }
108
105
  // ─── E2E Encryption ────────────────────────────────
109
106
  /** Get E2E encryption status for a device */
110
- async getDeviceE2EStatus(deviceId) {
107
+ getDeviceE2EStatus(deviceId) {
111
108
  return this.get(`/${this.prefix}/e2e-status/${deviceId}`);
112
109
  }
113
110
  /** Get device public key for E2E encryption */
114
- async getDevicePublicKey(deviceId) {
111
+ getDevicePublicKey(deviceId) {
115
112
  return this.get(`/${this.prefix}/public-key/${deviceId}`);
116
113
  }
117
114
  /** Verify device key fingerprint hasn't changed (detect reinstalls) */
118
- async verifyDeviceKey(deviceId, fingerprint) {
115
+ verifyDeviceKey(deviceId, fingerprint) {
119
116
  return this.post(`/${this.prefix}/verify-key`, { deviceId, fingerprint });
120
117
  }
121
118
  /** Send encrypted SMS (payload already encrypted with device's RSA public key) */
122
- async sendEncryptedSms(encryptedPayload, deviceId, is2FA = false) {
119
+ sendEncryptedSms(encryptedPayload, deviceId, is2FA = false) {
123
120
  return this.post(`/${this.prefix}/send-encrypted`, { encryptedPayload, deviceId, is2FA });
124
121
  }
125
122
  // ─── Config ─────────────────────────────────────────
126
123
  /** Update server URL configuration */
127
- async updateServerUrl(serverUrl) {
124
+ updateServerUrl(serverUrl) {
128
125
  return this.post(`/${this.prefix}/update-config`, { serverUrl });
129
126
  }
130
127
  // ─── Internal helpers ──────────────────────────────
131
- async get(path) {
132
- try {
133
- const res = await fetch(`${this.baseUrl}${path}`, {
134
- headers: this.authHeaders()
135
- });
136
- return await res.json();
137
- } catch (err) {
138
- return { success: false, error: err.message };
139
- }
140
- }
141
- async post(path, body) {
142
- try {
143
- const res = await fetch(`${this.baseUrl}${path}`, {
144
- method: "POST",
145
- headers: {
146
- "Content-Type": "application/json",
147
- ...this.authHeaders()
148
- },
149
- body: JSON.stringify(body)
150
- });
151
- return await res.json();
152
- } catch (err) {
153
- return { success: false, error: err.message };
154
- }
128
+ get(path) {
129
+ return (0, import_rxjs.lastValueFrom)(this.http.get(`${this.baseUrl}${path}`));
130
+ }
131
+ post(path, body) {
132
+ return (0, import_rxjs.lastValueFrom)(this.http.post(`${this.baseUrl}${path}`, body));
155
133
  }
156
134
  };
157
135
  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 /** Route prefix (default: 'smstunnel') */\r\n routePrefix?: 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 get prefix(): string {\r\n return this.config.routePrefix || 'smstunnel';\r\n }\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 /** 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 get<T = any>(path: string): Promise<T> {\r\n return lastValueFrom(this.http.get<T>(`${this.baseUrl}${path}`));\r\n }\r\n\r\n private post<T = any>(path: string, body: any): Promise<T> {\r\n return lastValueFrom(this.http.post<T>(`${this.baseUrl}${path}`, body));\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,115 +20,91 @@ function provideSmsTunnel(config) {
18
20
  var SmsTunnelService = class {
19
21
  constructor() {
20
22
  this.config = inject(SMSTUNNEL_CONFIG);
23
+ this.http = inject(HttpClient);
24
+ this.prefix = "smstunnel";
21
25
  }
22
26
  get baseUrl() {
23
27
  return this.config.apiBaseUrl.replace(/\/$/, "");
24
28
  }
25
- get prefix() {
26
- return this.config.routePrefix || "smstunnel";
27
- }
28
- authHeaders() {
29
- return this.config.getAuthHeaders ? this.config.getAuthHeaders() : {};
30
- }
31
29
  // ─── Pairing ────────────────────────────────────────
32
30
  /** Get current pairing status */
33
- async getStatus() {
31
+ getStatus() {
34
32
  return this.get(`/${this.prefix}/status`);
35
33
  }
36
34
  /** Create a pairing token (generates QR) */
37
- async createToken() {
35
+ createToken() {
38
36
  return this.post(`/${this.prefix}/create-token`, {});
39
37
  }
40
38
  /** Check pairing status for a token (no auth needed) */
41
- async getPairingStatus(token) {
42
- const res = await fetch(`${this.baseUrl}/${this.prefix}/pairing-status/${token}`);
43
- return res.json();
39
+ getPairingStatus(token) {
40
+ return this.get(`/${this.prefix}/pairing-status/${token}`);
44
41
  }
45
42
  /** Unpair the connected device */
46
- async unpair() {
43
+ unpair() {
47
44
  return this.post(`/${this.prefix}/unpair`, {});
48
45
  }
49
46
  /** List active pairings */
50
- async getPairings() {
47
+ getPairings() {
51
48
  return this.get(`/${this.prefix}/pairings`);
52
49
  }
53
50
  // ─── SMS ────────────────────────────────────────────
54
51
  /** Send a single SMS */
55
- async sendSms(to, message) {
52
+ sendSms(to, message) {
56
53
  return this.post(`/${this.prefix}/send`, { to, message });
57
54
  }
58
55
  /** Send 2FA SMS */
59
- async send2fa(to, code, template) {
56
+ send2fa(to, code, template) {
60
57
  return this.post(`/${this.prefix}/send-2fa`, { to, code, template });
61
58
  }
62
59
  /** Send bulk SMS */
63
- async sendBulk(messages) {
60
+ sendBulk(messages) {
64
61
  return this.post(`/${this.prefix}/send-bulk`, { messages });
65
62
  }
66
63
  /** Get SMS delivery status */
67
- async getSmsStatus(messageId) {
64
+ getSmsStatus(messageId) {
68
65
  return this.get(`/${this.prefix}/sms-status/${messageId}`);
69
66
  }
70
67
  /** Get received SMS (inbox) */
71
- async getReceivedSms() {
68
+ getReceivedSms() {
72
69
  return this.get(`/${this.prefix}/received`);
73
70
  }
74
71
  // ─── Devices & Account ─────────────────────────────
75
72
  /** List paired devices */
76
- async getDevices() {
73
+ getDevices() {
77
74
  return this.get(`/${this.prefix}/devices`);
78
75
  }
79
76
  /** Get account usage stats */
80
- async getUsage() {
77
+ getUsage() {
81
78
  return this.get(`/${this.prefix}/usage`);
82
79
  }
83
80
  // ─── E2E Encryption ────────────────────────────────
84
81
  /** Get E2E encryption status for a device */
85
- async getDeviceE2EStatus(deviceId) {
82
+ getDeviceE2EStatus(deviceId) {
86
83
  return this.get(`/${this.prefix}/e2e-status/${deviceId}`);
87
84
  }
88
85
  /** Get device public key for E2E encryption */
89
- async getDevicePublicKey(deviceId) {
86
+ getDevicePublicKey(deviceId) {
90
87
  return this.get(`/${this.prefix}/public-key/${deviceId}`);
91
88
  }
92
89
  /** Verify device key fingerprint hasn't changed (detect reinstalls) */
93
- async verifyDeviceKey(deviceId, fingerprint) {
90
+ verifyDeviceKey(deviceId, fingerprint) {
94
91
  return this.post(`/${this.prefix}/verify-key`, { deviceId, fingerprint });
95
92
  }
96
93
  /** Send encrypted SMS (payload already encrypted with device's RSA public key) */
97
- async sendEncryptedSms(encryptedPayload, deviceId, is2FA = false) {
94
+ sendEncryptedSms(encryptedPayload, deviceId, is2FA = false) {
98
95
  return this.post(`/${this.prefix}/send-encrypted`, { encryptedPayload, deviceId, is2FA });
99
96
  }
100
97
  // ─── Config ─────────────────────────────────────────
101
98
  /** Update server URL configuration */
102
- async updateServerUrl(serverUrl) {
99
+ updateServerUrl(serverUrl) {
103
100
  return this.post(`/${this.prefix}/update-config`, { serverUrl });
104
101
  }
105
102
  // ─── Internal helpers ──────────────────────────────
106
- async get(path) {
107
- try {
108
- const res = await fetch(`${this.baseUrl}${path}`, {
109
- headers: this.authHeaders()
110
- });
111
- return await res.json();
112
- } catch (err) {
113
- return { success: false, error: err.message };
114
- }
115
- }
116
- async post(path, body) {
117
- try {
118
- const res = await fetch(`${this.baseUrl}${path}`, {
119
- method: "POST",
120
- headers: {
121
- "Content-Type": "application/json",
122
- ...this.authHeaders()
123
- },
124
- body: JSON.stringify(body)
125
- });
126
- return await res.json();
127
- } catch (err) {
128
- return { success: false, error: err.message };
129
- }
103
+ get(path) {
104
+ return lastValueFrom(this.http.get(`${this.baseUrl}${path}`));
105
+ }
106
+ post(path, body) {
107
+ return lastValueFrom(this.http.post(`${this.baseUrl}${path}`, body));
130
108
  }
131
109
  };
132
110
  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 /** Route prefix (default: 'smstunnel') */\r\n routePrefix?: 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 get prefix(): string {\r\n return this.config.routePrefix || 'smstunnel';\r\n }\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 /** 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 get<T = any>(path: string): Promise<T> {\r\n return lastValueFrom(this.http.get<T>(`${this.baseUrl}${path}`));\r\n }\r\n\r\n private post<T = any>(path: string, body: any): Promise<T> {\r\n return lastValueFrom(this.http.post<T>(`${this.baseUrl}${path}`, body));\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
package/dist/index.d.mts CHANGED
@@ -77,7 +77,6 @@ declare const RO_LABELS: SmsTunnelLabels;
77
77
  interface SmsTunnelClientOptions {
78
78
  apiBaseUrl: string;
79
79
  getAuthHeaders?: () => Record<string, string>;
80
- routePrefix?: string;
81
80
  pollInterval?: number;
82
81
  }
83
82
  interface SmsTunnelStatusResponse {
package/dist/index.d.ts CHANGED
@@ -77,7 +77,6 @@ declare const RO_LABELS: SmsTunnelLabels;
77
77
  interface SmsTunnelClientOptions {
78
78
  apiBaseUrl: string;
79
79
  getAuthHeaders?: () => Record<string, string>;
80
- routePrefix?: string;
81
80
  pollInterval?: number;
82
81
  }
83
82
  interface SmsTunnelStatusResponse {
package/dist/index.js CHANGED
@@ -79,9 +79,9 @@ var RO_LABELS = {
79
79
  // src/client.ts
80
80
  var SmsTunnelClient = class {
81
81
  constructor(options) {
82
+ this.prefix = "smstunnel";
82
83
  this.pollTimer = null;
83
84
  this.baseUrl = options.apiBaseUrl.replace(/\/$/, "");
84
- this.prefix = options.routePrefix || "smstunnel";
85
85
  this.pollInterval = options.pollInterval || 3e3;
86
86
  this.getAuthHeaders = options.getAuthHeaders || (() => ({}));
87
87
  }
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/shared/labels.ts","../src/client.ts"],"sourcesContent":["// Common types shared between server and all frontends\r\nexport type {\r\n SmsTunnelConfig,\r\n SmsTunnelStorageAdapter,\r\n SmsTunnelStatus,\r\n SendSmsResult,\r\n CreateTokenResult,\r\n PairingStatusResult,\r\n PairingCallbackBody,\r\n} from './server/smstunnel.interfaces';\r\n\r\n// Shared labels (i18n)\r\nexport type { SmsTunnelLabels } from './shared/labels';\r\nexport { EN_LABELS, RO_LABELS } from './shared/labels';\r\n\r\n// Framework-agnostic client (Angular, Svelte, Astro, Solid, Vanilla JS)\r\nexport { SmsTunnelClient } from './client';\r\nexport type {\r\n SmsTunnelClientOptions,\r\n SmsTunnelStatusResponse,\r\n CreateTokenResponse,\r\n PairingStatusResponse,\r\n SendSmsResponse,\r\n SmsStatusResponse,\r\n SendBulkSmsRequest,\r\n SendBulkSmsResponse,\r\n Send2faRequest,\r\n ReceivedSmsResponse,\r\n DevicesResponse,\r\n AccountUsageResponse,\r\n PairingInfo,\r\n PairingEventCallback,\r\n DeviceE2EStatusResponse,\r\n DevicePublicKeyResponse,\r\n VerifyDeviceKeyResponse,\r\n} from './client';\r\n","export interface SmsTunnelLabels {\r\n title: string;\r\n description: string;\r\n serverUrlLabel: string;\r\n serverUrlPlaceholder: string;\r\n saveButton: string;\r\n pairedStatus: string;\r\n deviceLabel: string;\r\n unpairButton: string;\r\n unpairConfirm: string;\r\n notPairedStatus: string;\r\n notPairedDescription: string;\r\n connectButton: string;\r\n scanQrPrompt: string;\r\n waitingForPairing: string;\r\n cancelButton: string;\r\n qrExpired: string;\r\n testSmsTitle: string;\r\n testPhonePlaceholder: string;\r\n testMessagePlaceholder: string;\r\n sendTestButton: string;\r\n smsSentSuccess: string;\r\n smsError: string;\r\n}\r\n\r\nexport const EN_LABELS: SmsTunnelLabels = {\r\n title: 'SMS Configuration (SMSTunnel)',\r\n description: 'Connect an Android phone with the SMSTunnel app to send SMS directly from the application.',\r\n serverUrlLabel: 'SMSTunnel Server',\r\n serverUrlPlaceholder: 'https://smstunnel.io',\r\n saveButton: 'Save',\r\n pairedStatus: 'Connected',\r\n deviceLabel: 'Device',\r\n unpairButton: 'Disconnect',\r\n unpairConfirm: 'Are you sure you want to disconnect the SMS device?',\r\n notPairedStatus: 'Not connected',\r\n notPairedDescription: 'Scan the QR code with the SMSTunnel app on your Android phone.',\r\n connectButton: 'Connect phone',\r\n scanQrPrompt: 'Scan this QR code with the SMSTunnel app on your phone:',\r\n waitingForPairing: 'Waiting for connection...',\r\n cancelButton: 'Cancel',\r\n qrExpired: 'QR code has expired. Generate a new one.',\r\n testSmsTitle: 'Send test SMS',\r\n testPhonePlaceholder: 'Phone number (e.g., +1234567890)',\r\n testMessagePlaceholder: 'Message',\r\n sendTestButton: 'Send',\r\n smsSentSuccess: 'SMS sent successfully!',\r\n smsError: 'Error',\r\n};\r\n\r\nexport const RO_LABELS: SmsTunnelLabels = {\r\n title: 'Configurare SMS (SMSTunnel)',\r\n description: 'Conecteaza un telefon Android cu aplicatia SMSTunnel pentru a trimite SMS-uri direct din aplicatie.',\r\n serverUrlLabel: 'Server SMSTunnel',\r\n serverUrlPlaceholder: 'https://smstunnel.io',\r\n saveButton: 'Salveaza',\r\n pairedStatus: 'Conectat',\r\n deviceLabel: 'Dispozitiv',\r\n unpairButton: 'Deconecteaza',\r\n unpairConfirm: 'Sigur doresti sa deconectezi dispozitivul SMS?',\r\n notPairedStatus: 'Neconectat',\r\n notPairedDescription: 'Scaneaza codul QR cu aplicatia SMSTunnel de pe telefonul Android.',\r\n connectButton: 'Conecteaza telefon',\r\n scanQrPrompt: 'Scaneaza acest cod QR cu aplicatia SMSTunnel de pe telefon:',\r\n waitingForPairing: 'Se asteapta conectarea...',\r\n cancelButton: 'Anuleaza',\r\n qrExpired: 'Codul QR a expirat. Genereaza unul nou.',\r\n testSmsTitle: 'Trimite SMS de test',\r\n testPhonePlaceholder: 'Nr. telefon (ex: 0741234567)',\r\n testMessagePlaceholder: 'Mesaj',\r\n sendTestButton: 'Trimite',\r\n smsSentSuccess: 'SMS trimis cu succes!',\r\n smsError: 'Eroare',\r\n};\r\n","/**\r\n * Framework-agnostic SMSTunnel client.\r\n *\r\n * Works with Angular, Svelte, Astro, Solid, Vanilla JS, or any framework.\r\n * For React use `smstunnel-sdk/react`, for Vue use `smstunnel-sdk/vue`.\r\n */\r\nexport interface SmsTunnelClientOptions {\r\n apiBaseUrl: string;\r\n getAuthHeaders?: () => Record<string, string>;\r\n routePrefix?: string;\r\n pollInterval?: number;\r\n}\r\n\r\n// --- Status ---\r\n\r\nexport interface SmsTunnelStatusResponse {\r\n paired: boolean;\r\n serverUrl?: string;\r\n deviceName?: string;\r\n}\r\n\r\n// --- Pairing ---\r\n\r\nexport interface CreateTokenResponse {\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 PairingStatusResponse {\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\n// --- SMS ---\r\n\r\nexport interface SendSmsResponse {\r\n success: boolean;\r\n messageId?: string;\r\n queued?: boolean;\r\n data?: {\r\n messageId: string;\r\n branded: boolean;\r\n queued: boolean;\r\n remaining: number;\r\n };\r\n error?: string;\r\n}\r\n\r\nexport interface SmsStatusResponse {\r\n success: boolean;\r\n data?: {\r\n messageId: string;\r\n status: 'sent' | 'pending' | 'failed' | 'delivered';\r\n recipient: string;\r\n sentAt?: string;\r\n };\r\n error?: string;\r\n}\r\n\r\nexport interface SendBulkSmsRequest {\r\n messages: Array<{ to: string; message: string }>;\r\n}\r\n\r\nexport interface SendBulkSmsResponse {\r\n success: boolean;\r\n results?: Array<{ to: string; messageId?: string; error?: string }>;\r\n error?: string;\r\n}\r\n\r\nexport interface Send2faRequest {\r\n to: string;\r\n code: string;\r\n template?: string;\r\n}\r\n\r\nexport interface ReceivedSmsResponse {\r\n success: boolean;\r\n data?: Array<{\r\n from: string;\r\n message: string;\r\n receivedAt: string;\r\n }>;\r\n error?: string;\r\n}\r\n\r\n// --- Devices ---\r\n\r\nexport interface DevicesResponse {\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\n// --- Account ---\r\n\r\nexport interface AccountUsageResponse {\r\n success: boolean;\r\n data?: {\r\n messagesSent: number;\r\n messagesReceived: number;\r\n messagesSentToday: number;\r\n messagesSentMonth: number;\r\n dailyLimit?: number;\r\n monthlyLimit?: number;\r\n };\r\n error?: string;\r\n}\r\n\r\n// --- E2E Encryption ---\r\n\r\nexport interface DeviceE2EStatusResponse {\r\n success: boolean;\r\n data?: {\r\n encryptionEnabled: boolean;\r\n hasPublicKey: boolean;\r\n publicKeyFingerprint?: string;\r\n keyCreatedAt?: string;\r\n };\r\n error?: string;\r\n}\r\n\r\nexport interface DevicePublicKeyResponse {\r\n success: boolean;\r\n data?: {\r\n deviceId: string;\r\n deviceName: string;\r\n publicKey: string;\r\n };\r\n error?: string;\r\n}\r\n\r\nexport interface VerifyDeviceKeyResponse {\r\n valid: boolean;\r\n currentFingerprint?: string;\r\n needsRePairing: boolean;\r\n}\r\n\r\n// --- Pairings list ---\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// --- Callback ---\r\n\r\nexport type PairingEventCallback = (event: 'completed' | 'expired' | 'error', data?: any) => void;\r\n\r\nexport class SmsTunnelClient {\r\n private readonly baseUrl: string;\r\n private readonly prefix: string;\r\n private readonly pollInterval: number;\r\n private readonly getAuthHeaders: () => Record<string, string>;\r\n private pollTimer: ReturnType<typeof setInterval> | null = null;\r\n\r\n constructor(options: SmsTunnelClientOptions) {\r\n this.baseUrl = options.apiBaseUrl.replace(/\\/$/, '');\r\n this.prefix = options.routePrefix || 'smstunnel';\r\n this.pollInterval = options.pollInterval || 3000;\r\n this.getAuthHeaders = options.getAuthHeaders || (() => ({}));\r\n }\r\n\r\n // ─── Pairing ───────────────────────────────────────\r\n\r\n /** Get current pairing status */\r\n async getStatus(): Promise<SmsTunnelStatusResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/status`, {\r\n headers: this.getAuthHeaders(),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Create a pairing token (generates QR data) */\r\n async createToken(): Promise<CreateTokenResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/create-token`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.getAuthHeaders(),\r\n },\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Check pairing status for a token (no auth needed) */\r\n async getPairingStatus(token: string): Promise<PairingStatusResponse> {\r\n const res = await fetch(\r\n `${this.baseUrl}/${this.prefix}/pairing-status/${token}`,\r\n );\r\n return res.json();\r\n }\r\n\r\n /**\r\n * Start polling for pairing completion.\r\n * Returns a cleanup function to stop polling.\r\n */\r\n startPolling(token: string, callback: PairingEventCallback): () => void {\r\n this.stopPolling();\r\n\r\n this.pollTimer = setInterval(async () => {\r\n try {\r\n const data = await this.getPairingStatus(token);\r\n if (data.status === 'completed') {\r\n this.stopPolling();\r\n callback('completed', data);\r\n } else if (data.status === 'expired') {\r\n this.stopPolling();\r\n callback('expired', data);\r\n }\r\n } catch (err) {\r\n // ignore polling errors\r\n }\r\n }, this.pollInterval);\r\n\r\n return () => this.stopPolling();\r\n }\r\n\r\n /** Stop polling */\r\n stopPolling(): void {\r\n if (this.pollTimer) {\r\n clearInterval(this.pollTimer);\r\n this.pollTimer = null;\r\n }\r\n }\r\n\r\n /** Unpair the connected device */\r\n async unpair(): Promise<{ success: boolean }> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/unpair`, {\r\n method: 'POST',\r\n headers: this.getAuthHeaders(),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** List active pairings (proxied through backend) */\r\n async getPairings(): Promise<PairingInfo[]> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/pairings`, {\r\n headers: this.getAuthHeaders(),\r\n });\r\n return res.json();\r\n }\r\n\r\n // ─── SMS ───────────────────────────────────────────\r\n\r\n /** Send a single SMS */\r\n async sendSms(to: string, message: string): Promise<SendSmsResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/send`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.getAuthHeaders(),\r\n },\r\n body: JSON.stringify({ to, message }),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Send a 2FA SMS */\r\n async send2fa(to: string, code: string, template?: string): Promise<SendSmsResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/send-2fa`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.getAuthHeaders(),\r\n },\r\n body: JSON.stringify({ to, code, template }),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Send bulk SMS */\r\n async sendBulk(messages: Array<{ to: string; message: string }>): Promise<SendBulkSmsResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/send-bulk`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.getAuthHeaders(),\r\n },\r\n body: JSON.stringify({ messages }),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Get SMS delivery status */\r\n async getSmsStatus(messageId: string): Promise<SmsStatusResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/sms-status/${messageId}`, {\r\n headers: this.getAuthHeaders(),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Get received SMS (inbox) */\r\n async getReceivedSms(): Promise<ReceivedSmsResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/received`, {\r\n headers: this.getAuthHeaders(),\r\n });\r\n return res.json();\r\n }\r\n\r\n // ─── Devices & Account ─────────────────────────────\r\n\r\n /** List paired devices */\r\n async getDevices(): Promise<DevicesResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/devices`, {\r\n headers: this.getAuthHeaders(),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Get account usage stats */\r\n async getUsage(): Promise<AccountUsageResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/usage`, {\r\n headers: this.getAuthHeaders(),\r\n });\r\n return res.json();\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<DeviceE2EStatusResponse> {\r\n const res = await fetch(\r\n `${this.baseUrl}/${this.prefix}/e2e-status/${deviceId}`,\r\n { headers: this.getAuthHeaders() },\r\n );\r\n return res.json();\r\n }\r\n\r\n /** Get device public key for E2E encryption */\r\n async getDevicePublicKey(deviceId: string): Promise<DevicePublicKeyResponse> {\r\n const res = await fetch(\r\n `${this.baseUrl}/${this.prefix}/public-key/${deviceId}`,\r\n { headers: this.getAuthHeaders() },\r\n );\r\n return res.json();\r\n }\r\n\r\n /** Verify that a stored fingerprint matches the current device key */\r\n async verifyDeviceKey(\r\n deviceId: string,\r\n fingerprint: string,\r\n ): Promise<VerifyDeviceKeyResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/verify-key`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.getAuthHeaders(),\r\n },\r\n body: JSON.stringify({ deviceId, fingerprint }),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Send an encrypted SMS (payload already encrypted with device public key) */\r\n async sendEncryptedSms(\r\n encryptedPayload: string,\r\n deviceId: string,\r\n is2FA: boolean = false,\r\n ): Promise<SendSmsResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/send-encrypted`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.getAuthHeaders(),\r\n },\r\n body: JSON.stringify({ encryptedPayload, deviceId, is2FA }),\r\n });\r\n return res.json();\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 const res = await fetch(`${this.baseUrl}/${this.prefix}/update-config`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.getAuthHeaders(),\r\n },\r\n body: JSON.stringify({ serverUrl }),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Destroy - cleanup polling */\r\n destroy(): void {\r\n this.stopPolling();\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
1
+ {"version":3,"sources":["../src/index.ts","../src/shared/labels.ts","../src/client.ts"],"sourcesContent":["// Common types shared between server and all frontends\r\nexport type {\r\n SmsTunnelConfig,\r\n SmsTunnelStorageAdapter,\r\n SmsTunnelStatus,\r\n SendSmsResult,\r\n CreateTokenResult,\r\n PairingStatusResult,\r\n PairingCallbackBody,\r\n} from './server/smstunnel.interfaces';\r\n\r\n// Shared labels (i18n)\r\nexport type { SmsTunnelLabels } from './shared/labels';\r\nexport { EN_LABELS, RO_LABELS } from './shared/labels';\r\n\r\n// Framework-agnostic client (Angular, Svelte, Astro, Solid, Vanilla JS)\r\nexport { SmsTunnelClient } from './client';\r\nexport type {\r\n SmsTunnelClientOptions,\r\n SmsTunnelStatusResponse,\r\n CreateTokenResponse,\r\n PairingStatusResponse,\r\n SendSmsResponse,\r\n SmsStatusResponse,\r\n SendBulkSmsRequest,\r\n SendBulkSmsResponse,\r\n Send2faRequest,\r\n ReceivedSmsResponse,\r\n DevicesResponse,\r\n AccountUsageResponse,\r\n PairingInfo,\r\n PairingEventCallback,\r\n DeviceE2EStatusResponse,\r\n DevicePublicKeyResponse,\r\n VerifyDeviceKeyResponse,\r\n} from './client';\r\n","export interface SmsTunnelLabels {\r\n title: string;\r\n description: string;\r\n serverUrlLabel: string;\r\n serverUrlPlaceholder: string;\r\n saveButton: string;\r\n pairedStatus: string;\r\n deviceLabel: string;\r\n unpairButton: string;\r\n unpairConfirm: string;\r\n notPairedStatus: string;\r\n notPairedDescription: string;\r\n connectButton: string;\r\n scanQrPrompt: string;\r\n waitingForPairing: string;\r\n cancelButton: string;\r\n qrExpired: string;\r\n testSmsTitle: string;\r\n testPhonePlaceholder: string;\r\n testMessagePlaceholder: string;\r\n sendTestButton: string;\r\n smsSentSuccess: string;\r\n smsError: string;\r\n}\r\n\r\nexport const EN_LABELS: SmsTunnelLabels = {\r\n title: 'SMS Configuration (SMSTunnel)',\r\n description: 'Connect an Android phone with the SMSTunnel app to send SMS directly from the application.',\r\n serverUrlLabel: 'SMSTunnel Server',\r\n serverUrlPlaceholder: 'https://smstunnel.io',\r\n saveButton: 'Save',\r\n pairedStatus: 'Connected',\r\n deviceLabel: 'Device',\r\n unpairButton: 'Disconnect',\r\n unpairConfirm: 'Are you sure you want to disconnect the SMS device?',\r\n notPairedStatus: 'Not connected',\r\n notPairedDescription: 'Scan the QR code with the SMSTunnel app on your Android phone.',\r\n connectButton: 'Connect phone',\r\n scanQrPrompt: 'Scan this QR code with the SMSTunnel app on your phone:',\r\n waitingForPairing: 'Waiting for connection...',\r\n cancelButton: 'Cancel',\r\n qrExpired: 'QR code has expired. Generate a new one.',\r\n testSmsTitle: 'Send test SMS',\r\n testPhonePlaceholder: 'Phone number (e.g., +1234567890)',\r\n testMessagePlaceholder: 'Message',\r\n sendTestButton: 'Send',\r\n smsSentSuccess: 'SMS sent successfully!',\r\n smsError: 'Error',\r\n};\r\n\r\nexport const RO_LABELS: SmsTunnelLabels = {\r\n title: 'Configurare SMS (SMSTunnel)',\r\n description: 'Conecteaza un telefon Android cu aplicatia SMSTunnel pentru a trimite SMS-uri direct din aplicatie.',\r\n serverUrlLabel: 'Server SMSTunnel',\r\n serverUrlPlaceholder: 'https://smstunnel.io',\r\n saveButton: 'Salveaza',\r\n pairedStatus: 'Conectat',\r\n deviceLabel: 'Dispozitiv',\r\n unpairButton: 'Deconecteaza',\r\n unpairConfirm: 'Sigur doresti sa deconectezi dispozitivul SMS?',\r\n notPairedStatus: 'Neconectat',\r\n notPairedDescription: 'Scaneaza codul QR cu aplicatia SMSTunnel de pe telefonul Android.',\r\n connectButton: 'Conecteaza telefon',\r\n scanQrPrompt: 'Scaneaza acest cod QR cu aplicatia SMSTunnel de pe telefon:',\r\n waitingForPairing: 'Se asteapta conectarea...',\r\n cancelButton: 'Anuleaza',\r\n qrExpired: 'Codul QR a expirat. Genereaza unul nou.',\r\n testSmsTitle: 'Trimite SMS de test',\r\n testPhonePlaceholder: 'Nr. telefon (ex: 0741234567)',\r\n testMessagePlaceholder: 'Mesaj',\r\n sendTestButton: 'Trimite',\r\n smsSentSuccess: 'SMS trimis cu succes!',\r\n smsError: 'Eroare',\r\n};\r\n","/**\r\n * Framework-agnostic SMSTunnel client.\r\n *\r\n * Works with Angular, Svelte, Astro, Solid, Vanilla JS, or any framework.\r\n * For React use `smstunnel-sdk/react`, for Vue use `smstunnel-sdk/vue`.\r\n */\r\nexport interface SmsTunnelClientOptions {\r\n apiBaseUrl: string;\r\n getAuthHeaders?: () => Record<string, string>;\r\n pollInterval?: number;\r\n}\r\n\r\n// --- Status ---\r\n\r\nexport interface SmsTunnelStatusResponse {\r\n paired: boolean;\r\n serverUrl?: string;\r\n deviceName?: string;\r\n}\r\n\r\n// --- Pairing ---\r\n\r\nexport interface CreateTokenResponse {\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 PairingStatusResponse {\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\n// --- SMS ---\r\n\r\nexport interface SendSmsResponse {\r\n success: boolean;\r\n messageId?: string;\r\n queued?: boolean;\r\n data?: {\r\n messageId: string;\r\n branded: boolean;\r\n queued: boolean;\r\n remaining: number;\r\n };\r\n error?: string;\r\n}\r\n\r\nexport interface SmsStatusResponse {\r\n success: boolean;\r\n data?: {\r\n messageId: string;\r\n status: 'sent' | 'pending' | 'failed' | 'delivered';\r\n recipient: string;\r\n sentAt?: string;\r\n };\r\n error?: string;\r\n}\r\n\r\nexport interface SendBulkSmsRequest {\r\n messages: Array<{ to: string; message: string }>;\r\n}\r\n\r\nexport interface SendBulkSmsResponse {\r\n success: boolean;\r\n results?: Array<{ to: string; messageId?: string; error?: string }>;\r\n error?: string;\r\n}\r\n\r\nexport interface Send2faRequest {\r\n to: string;\r\n code: string;\r\n template?: string;\r\n}\r\n\r\nexport interface ReceivedSmsResponse {\r\n success: boolean;\r\n data?: Array<{\r\n from: string;\r\n message: string;\r\n receivedAt: string;\r\n }>;\r\n error?: string;\r\n}\r\n\r\n// --- Devices ---\r\n\r\nexport interface DevicesResponse {\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\n// --- Account ---\r\n\r\nexport interface AccountUsageResponse {\r\n success: boolean;\r\n data?: {\r\n messagesSent: number;\r\n messagesReceived: number;\r\n messagesSentToday: number;\r\n messagesSentMonth: number;\r\n dailyLimit?: number;\r\n monthlyLimit?: number;\r\n };\r\n error?: string;\r\n}\r\n\r\n// --- E2E Encryption ---\r\n\r\nexport interface DeviceE2EStatusResponse {\r\n success: boolean;\r\n data?: {\r\n encryptionEnabled: boolean;\r\n hasPublicKey: boolean;\r\n publicKeyFingerprint?: string;\r\n keyCreatedAt?: string;\r\n };\r\n error?: string;\r\n}\r\n\r\nexport interface DevicePublicKeyResponse {\r\n success: boolean;\r\n data?: {\r\n deviceId: string;\r\n deviceName: string;\r\n publicKey: string;\r\n };\r\n error?: string;\r\n}\r\n\r\nexport interface VerifyDeviceKeyResponse {\r\n valid: boolean;\r\n currentFingerprint?: string;\r\n needsRePairing: boolean;\r\n}\r\n\r\n// --- Pairings list ---\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// --- Callback ---\r\n\r\nexport type PairingEventCallback = (event: 'completed' | 'expired' | 'error', data?: any) => void;\r\n\r\nexport class SmsTunnelClient {\r\n private readonly baseUrl: string;\r\n private readonly prefix = 'smstunnel';\r\n private readonly pollInterval: number;\r\n private readonly getAuthHeaders: () => Record<string, string>;\r\n private pollTimer: ReturnType<typeof setInterval> | null = null;\r\n\r\n constructor(options: SmsTunnelClientOptions) {\r\n this.baseUrl = options.apiBaseUrl.replace(/\\/$/, '');\r\n this.pollInterval = options.pollInterval || 3000;\r\n this.getAuthHeaders = options.getAuthHeaders || (() => ({}));\r\n }\r\n\r\n // ─── Pairing ───────────────────────────────────────\r\n\r\n /** Get current pairing status */\r\n async getStatus(): Promise<SmsTunnelStatusResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/status`, {\r\n headers: this.getAuthHeaders(),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Create a pairing token (generates QR data) */\r\n async createToken(): Promise<CreateTokenResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/create-token`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.getAuthHeaders(),\r\n },\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Check pairing status for a token (no auth needed) */\r\n async getPairingStatus(token: string): Promise<PairingStatusResponse> {\r\n const res = await fetch(\r\n `${this.baseUrl}/${this.prefix}/pairing-status/${token}`,\r\n );\r\n return res.json();\r\n }\r\n\r\n /**\r\n * Start polling for pairing completion.\r\n * Returns a cleanup function to stop polling.\r\n */\r\n startPolling(token: string, callback: PairingEventCallback): () => void {\r\n this.stopPolling();\r\n\r\n this.pollTimer = setInterval(async () => {\r\n try {\r\n const data = await this.getPairingStatus(token);\r\n if (data.status === 'completed') {\r\n this.stopPolling();\r\n callback('completed', data);\r\n } else if (data.status === 'expired') {\r\n this.stopPolling();\r\n callback('expired', data);\r\n }\r\n } catch (err) {\r\n // ignore polling errors\r\n }\r\n }, this.pollInterval);\r\n\r\n return () => this.stopPolling();\r\n }\r\n\r\n /** Stop polling */\r\n stopPolling(): void {\r\n if (this.pollTimer) {\r\n clearInterval(this.pollTimer);\r\n this.pollTimer = null;\r\n }\r\n }\r\n\r\n /** Unpair the connected device */\r\n async unpair(): Promise<{ success: boolean }> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/unpair`, {\r\n method: 'POST',\r\n headers: this.getAuthHeaders(),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** List active pairings (proxied through backend) */\r\n async getPairings(): Promise<PairingInfo[]> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/pairings`, {\r\n headers: this.getAuthHeaders(),\r\n });\r\n return res.json();\r\n }\r\n\r\n // ─── SMS ───────────────────────────────────────────\r\n\r\n /** Send a single SMS */\r\n async sendSms(to: string, message: string): Promise<SendSmsResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/send`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.getAuthHeaders(),\r\n },\r\n body: JSON.stringify({ to, message }),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Send a 2FA SMS */\r\n async send2fa(to: string, code: string, template?: string): Promise<SendSmsResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/send-2fa`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.getAuthHeaders(),\r\n },\r\n body: JSON.stringify({ to, code, template }),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Send bulk SMS */\r\n async sendBulk(messages: Array<{ to: string; message: string }>): Promise<SendBulkSmsResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/send-bulk`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.getAuthHeaders(),\r\n },\r\n body: JSON.stringify({ messages }),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Get SMS delivery status */\r\n async getSmsStatus(messageId: string): Promise<SmsStatusResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/sms-status/${messageId}`, {\r\n headers: this.getAuthHeaders(),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Get received SMS (inbox) */\r\n async getReceivedSms(): Promise<ReceivedSmsResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/received`, {\r\n headers: this.getAuthHeaders(),\r\n });\r\n return res.json();\r\n }\r\n\r\n // ─── Devices & Account ─────────────────────────────\r\n\r\n /** List paired devices */\r\n async getDevices(): Promise<DevicesResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/devices`, {\r\n headers: this.getAuthHeaders(),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Get account usage stats */\r\n async getUsage(): Promise<AccountUsageResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/usage`, {\r\n headers: this.getAuthHeaders(),\r\n });\r\n return res.json();\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<DeviceE2EStatusResponse> {\r\n const res = await fetch(\r\n `${this.baseUrl}/${this.prefix}/e2e-status/${deviceId}`,\r\n { headers: this.getAuthHeaders() },\r\n );\r\n return res.json();\r\n }\r\n\r\n /** Get device public key for E2E encryption */\r\n async getDevicePublicKey(deviceId: string): Promise<DevicePublicKeyResponse> {\r\n const res = await fetch(\r\n `${this.baseUrl}/${this.prefix}/public-key/${deviceId}`,\r\n { headers: this.getAuthHeaders() },\r\n );\r\n return res.json();\r\n }\r\n\r\n /** Verify that a stored fingerprint matches the current device key */\r\n async verifyDeviceKey(\r\n deviceId: string,\r\n fingerprint: string,\r\n ): Promise<VerifyDeviceKeyResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/verify-key`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.getAuthHeaders(),\r\n },\r\n body: JSON.stringify({ deviceId, fingerprint }),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Send an encrypted SMS (payload already encrypted with device public key) */\r\n async sendEncryptedSms(\r\n encryptedPayload: string,\r\n deviceId: string,\r\n is2FA: boolean = false,\r\n ): Promise<SendSmsResponse> {\r\n const res = await fetch(`${this.baseUrl}/${this.prefix}/send-encrypted`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.getAuthHeaders(),\r\n },\r\n body: JSON.stringify({ encryptedPayload, deviceId, is2FA }),\r\n });\r\n return res.json();\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 const res = await fetch(`${this.baseUrl}/${this.prefix}/update-config`, {\r\n method: 'POST',\r\n headers: {\r\n 'Content-Type': 'application/json',\r\n ...this.getAuthHeaders(),\r\n },\r\n body: JSON.stringify({ serverUrl }),\r\n });\r\n return res.json();\r\n }\r\n\r\n /** Destroy - cleanup polling */\r\n destroy(): void {\r\n this.stopPolling();\r\n }\r\n}\r\n"],"mappings":"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","names":[]}
package/dist/index.mjs CHANGED
@@ -51,9 +51,9 @@ var RO_LABELS = {
51
51
  // src/client.ts
52
52
  var SmsTunnelClient = class {
53
53
  constructor(options) {
54
+ this.prefix = "smstunnel";
54
55
  this.pollTimer = null;
55
56
  this.baseUrl = options.apiBaseUrl.replace(/\/$/, "");
56
- this.prefix = options.routePrefix || "smstunnel";
57
57
  this.pollInterval = options.pollInterval || 3e3;
58
58
  this.getAuthHeaders = options.getAuthHeaders || (() => ({}));
59
59
  }