@narcisbodea/smstunnel-sdk 1.1.0 → 1.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/angular/index.d.mts +144 -0
- package/dist/angular/index.d.ts +144 -0
- package/dist/angular/index.js +166 -0
- package/dist/angular/index.js.map +1 -0
- package/dist/angular/index.mjs +140 -0
- package/dist/angular/index.mjs.map +1 -0
- package/dist/index.d.mts +33 -1
- package/dist/index.d.ts +33 -1
- package/dist/index.js +41 -0
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +41 -0
- package/dist/index.mjs.map +1 -1
- package/dist/node/index.d.mts +228 -0
- package/dist/node/index.d.ts +228 -0
- package/dist/node/index.js +208 -0
- package/dist/node/index.js.map +1 -0
- package/dist/node/index.mjs +183 -0
- package/dist/node/index.mjs.map +1 -0
- package/dist/react/index.d.mts +4 -0
- package/dist/react/index.d.ts +4 -0
- package/dist/react/index.js +64 -1
- package/dist/react/index.js.map +1 -1
- package/dist/react/index.mjs +64 -1
- package/dist/react/index.mjs.map +1 -1
- package/dist/server/index.d.mts +86 -1
- package/dist/server/index.d.ts +86 -1
- package/dist/server/index.js +88 -0
- package/dist/server/index.js.map +1 -1
- package/dist/server/index.mjs +88 -0
- package/dist/server/index.mjs.map +1 -1
- package/dist/vue/index.d.mts +4 -0
- package/dist/vue/index.d.ts +4 -0
- package/dist/vue/index.js +52 -1
- package/dist/vue/index.js.map +1 -1
- package/dist/vue/index.mjs +52 -1
- package/dist/vue/index.mjs.map +1 -1
- package/package.json +19 -4
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
interface SmsTunnelAngularConfig {
|
|
4
|
+
/** Your backend base URL (where SmsTunnelModule is mounted) */
|
|
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
|
+
/** Poll interval in ms (default: 3000) */
|
|
11
|
+
pollInterval?: number;
|
|
12
|
+
}
|
|
13
|
+
declare const SMSTUNNEL_CONFIG: InjectionToken<SmsTunnelAngularConfig>;
|
|
14
|
+
declare function provideSmsTunnel(config: SmsTunnelAngularConfig): {
|
|
15
|
+
provide: InjectionToken<SmsTunnelAngularConfig>;
|
|
16
|
+
useValue: SmsTunnelAngularConfig;
|
|
17
|
+
};
|
|
18
|
+
interface SmsTunnelStatus {
|
|
19
|
+
paired: boolean;
|
|
20
|
+
serverUrl?: string;
|
|
21
|
+
deviceName?: string;
|
|
22
|
+
}
|
|
23
|
+
interface CreateTokenResult {
|
|
24
|
+
success: boolean;
|
|
25
|
+
token?: string;
|
|
26
|
+
qrData?: string;
|
|
27
|
+
expiresAt?: string;
|
|
28
|
+
pollUrl?: string;
|
|
29
|
+
error?: string;
|
|
30
|
+
}
|
|
31
|
+
interface PairingStatusResult {
|
|
32
|
+
status: 'pending' | 'completed' | 'expired' | 'error';
|
|
33
|
+
source?: string;
|
|
34
|
+
displayName?: string;
|
|
35
|
+
pairedDeviceId?: string;
|
|
36
|
+
pairingId?: string;
|
|
37
|
+
error?: string;
|
|
38
|
+
}
|
|
39
|
+
interface SendSmsResult {
|
|
40
|
+
success: boolean;
|
|
41
|
+
messageId?: string;
|
|
42
|
+
error?: string;
|
|
43
|
+
}
|
|
44
|
+
interface DeviceE2EStatus {
|
|
45
|
+
encryptionEnabled: boolean;
|
|
46
|
+
hasPublicKey: boolean;
|
|
47
|
+
publicKeyFingerprint?: string;
|
|
48
|
+
keyCreatedAt?: string;
|
|
49
|
+
}
|
|
50
|
+
interface DevicePublicKeyInfo {
|
|
51
|
+
deviceId: string;
|
|
52
|
+
deviceName: string;
|
|
53
|
+
publicKey: string;
|
|
54
|
+
}
|
|
55
|
+
interface VerifyDeviceKeyResult {
|
|
56
|
+
valid: boolean;
|
|
57
|
+
currentFingerprint?: string;
|
|
58
|
+
needsRePairing: boolean;
|
|
59
|
+
}
|
|
60
|
+
interface DevicesResult {
|
|
61
|
+
success: boolean;
|
|
62
|
+
data?: Array<{
|
|
63
|
+
id: string;
|
|
64
|
+
clientId: string;
|
|
65
|
+
name: string;
|
|
66
|
+
brand?: string;
|
|
67
|
+
model?: string;
|
|
68
|
+
connected?: boolean;
|
|
69
|
+
}>;
|
|
70
|
+
error?: string;
|
|
71
|
+
}
|
|
72
|
+
interface PairingInfo {
|
|
73
|
+
_id: string;
|
|
74
|
+
deviceId: string;
|
|
75
|
+
type: string;
|
|
76
|
+
name: string;
|
|
77
|
+
status: 'active' | 'paused' | 'revoked';
|
|
78
|
+
messagesSent: number;
|
|
79
|
+
createdAt: string;
|
|
80
|
+
source: string;
|
|
81
|
+
}
|
|
82
|
+
declare class SmsTunnelService {
|
|
83
|
+
private readonly config;
|
|
84
|
+
private get baseUrl();
|
|
85
|
+
private get prefix();
|
|
86
|
+
private authHeaders;
|
|
87
|
+
/** Get current pairing status */
|
|
88
|
+
getStatus(): Promise<SmsTunnelStatus>;
|
|
89
|
+
/** Create a pairing token (generates QR) */
|
|
90
|
+
createToken(): Promise<CreateTokenResult>;
|
|
91
|
+
/** Check pairing status for a token (no auth needed) */
|
|
92
|
+
getPairingStatus(token: string): Promise<PairingStatusResult>;
|
|
93
|
+
/** Unpair the connected device */
|
|
94
|
+
unpair(): Promise<{
|
|
95
|
+
success: boolean;
|
|
96
|
+
}>;
|
|
97
|
+
/** List active pairings */
|
|
98
|
+
getPairings(): Promise<PairingInfo[]>;
|
|
99
|
+
/** Send a single SMS */
|
|
100
|
+
sendSms(to: string, message: string): Promise<SendSmsResult>;
|
|
101
|
+
/** Send 2FA SMS */
|
|
102
|
+
send2fa(to: string, code: string, template?: string): Promise<SendSmsResult>;
|
|
103
|
+
/** Send bulk SMS */
|
|
104
|
+
sendBulk(messages: Array<{
|
|
105
|
+
to: string;
|
|
106
|
+
message: string;
|
|
107
|
+
}>): Promise<{
|
|
108
|
+
success: boolean;
|
|
109
|
+
results?: any[];
|
|
110
|
+
error?: string;
|
|
111
|
+
}>;
|
|
112
|
+
/** Get SMS delivery status */
|
|
113
|
+
getSmsStatus(messageId: string): Promise<any>;
|
|
114
|
+
/** Get received SMS (inbox) */
|
|
115
|
+
getReceivedSms(): Promise<any>;
|
|
116
|
+
/** List paired devices */
|
|
117
|
+
getDevices(): Promise<DevicesResult>;
|
|
118
|
+
/** Get account usage stats */
|
|
119
|
+
getUsage(): Promise<any>;
|
|
120
|
+
/** Get E2E encryption status for a device */
|
|
121
|
+
getDeviceE2EStatus(deviceId: string): Promise<{
|
|
122
|
+
success: boolean;
|
|
123
|
+
data?: DeviceE2EStatus;
|
|
124
|
+
error?: string;
|
|
125
|
+
}>;
|
|
126
|
+
/** Get device public key for E2E encryption */
|
|
127
|
+
getDevicePublicKey(deviceId: string): Promise<{
|
|
128
|
+
success: boolean;
|
|
129
|
+
data?: DevicePublicKeyInfo;
|
|
130
|
+
error?: string;
|
|
131
|
+
}>;
|
|
132
|
+
/** Verify device key fingerprint hasn't changed (detect reinstalls) */
|
|
133
|
+
verifyDeviceKey(deviceId: string, fingerprint: string): Promise<VerifyDeviceKeyResult>;
|
|
134
|
+
/** Send encrypted SMS (payload already encrypted with device's RSA public key) */
|
|
135
|
+
sendEncryptedSms(encryptedPayload: string, deviceId: string, is2FA?: boolean): Promise<SendSmsResult>;
|
|
136
|
+
/** Update server URL configuration */
|
|
137
|
+
updateServerUrl(serverUrl: string): Promise<{
|
|
138
|
+
success: boolean;
|
|
139
|
+
}>;
|
|
140
|
+
private get;
|
|
141
|
+
private post;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export { type CreateTokenResult, type DeviceE2EStatus, type DevicePublicKeyInfo, type DevicesResult, type PairingInfo, type PairingStatusResult, SMSTUNNEL_CONFIG, type SendSmsResult, type SmsTunnelAngularConfig, SmsTunnelService, type SmsTunnelStatus, type VerifyDeviceKeyResult, provideSmsTunnel };
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import { InjectionToken } from '@angular/core';
|
|
2
|
+
|
|
3
|
+
interface SmsTunnelAngularConfig {
|
|
4
|
+
/** Your backend base URL (where SmsTunnelModule is mounted) */
|
|
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
|
+
/** Poll interval in ms (default: 3000) */
|
|
11
|
+
pollInterval?: number;
|
|
12
|
+
}
|
|
13
|
+
declare const SMSTUNNEL_CONFIG: InjectionToken<SmsTunnelAngularConfig>;
|
|
14
|
+
declare function provideSmsTunnel(config: SmsTunnelAngularConfig): {
|
|
15
|
+
provide: InjectionToken<SmsTunnelAngularConfig>;
|
|
16
|
+
useValue: SmsTunnelAngularConfig;
|
|
17
|
+
};
|
|
18
|
+
interface SmsTunnelStatus {
|
|
19
|
+
paired: boolean;
|
|
20
|
+
serverUrl?: string;
|
|
21
|
+
deviceName?: string;
|
|
22
|
+
}
|
|
23
|
+
interface CreateTokenResult {
|
|
24
|
+
success: boolean;
|
|
25
|
+
token?: string;
|
|
26
|
+
qrData?: string;
|
|
27
|
+
expiresAt?: string;
|
|
28
|
+
pollUrl?: string;
|
|
29
|
+
error?: string;
|
|
30
|
+
}
|
|
31
|
+
interface PairingStatusResult {
|
|
32
|
+
status: 'pending' | 'completed' | 'expired' | 'error';
|
|
33
|
+
source?: string;
|
|
34
|
+
displayName?: string;
|
|
35
|
+
pairedDeviceId?: string;
|
|
36
|
+
pairingId?: string;
|
|
37
|
+
error?: string;
|
|
38
|
+
}
|
|
39
|
+
interface SendSmsResult {
|
|
40
|
+
success: boolean;
|
|
41
|
+
messageId?: string;
|
|
42
|
+
error?: string;
|
|
43
|
+
}
|
|
44
|
+
interface DeviceE2EStatus {
|
|
45
|
+
encryptionEnabled: boolean;
|
|
46
|
+
hasPublicKey: boolean;
|
|
47
|
+
publicKeyFingerprint?: string;
|
|
48
|
+
keyCreatedAt?: string;
|
|
49
|
+
}
|
|
50
|
+
interface DevicePublicKeyInfo {
|
|
51
|
+
deviceId: string;
|
|
52
|
+
deviceName: string;
|
|
53
|
+
publicKey: string;
|
|
54
|
+
}
|
|
55
|
+
interface VerifyDeviceKeyResult {
|
|
56
|
+
valid: boolean;
|
|
57
|
+
currentFingerprint?: string;
|
|
58
|
+
needsRePairing: boolean;
|
|
59
|
+
}
|
|
60
|
+
interface DevicesResult {
|
|
61
|
+
success: boolean;
|
|
62
|
+
data?: Array<{
|
|
63
|
+
id: string;
|
|
64
|
+
clientId: string;
|
|
65
|
+
name: string;
|
|
66
|
+
brand?: string;
|
|
67
|
+
model?: string;
|
|
68
|
+
connected?: boolean;
|
|
69
|
+
}>;
|
|
70
|
+
error?: string;
|
|
71
|
+
}
|
|
72
|
+
interface PairingInfo {
|
|
73
|
+
_id: string;
|
|
74
|
+
deviceId: string;
|
|
75
|
+
type: string;
|
|
76
|
+
name: string;
|
|
77
|
+
status: 'active' | 'paused' | 'revoked';
|
|
78
|
+
messagesSent: number;
|
|
79
|
+
createdAt: string;
|
|
80
|
+
source: string;
|
|
81
|
+
}
|
|
82
|
+
declare class SmsTunnelService {
|
|
83
|
+
private readonly config;
|
|
84
|
+
private get baseUrl();
|
|
85
|
+
private get prefix();
|
|
86
|
+
private authHeaders;
|
|
87
|
+
/** Get current pairing status */
|
|
88
|
+
getStatus(): Promise<SmsTunnelStatus>;
|
|
89
|
+
/** Create a pairing token (generates QR) */
|
|
90
|
+
createToken(): Promise<CreateTokenResult>;
|
|
91
|
+
/** Check pairing status for a token (no auth needed) */
|
|
92
|
+
getPairingStatus(token: string): Promise<PairingStatusResult>;
|
|
93
|
+
/** Unpair the connected device */
|
|
94
|
+
unpair(): Promise<{
|
|
95
|
+
success: boolean;
|
|
96
|
+
}>;
|
|
97
|
+
/** List active pairings */
|
|
98
|
+
getPairings(): Promise<PairingInfo[]>;
|
|
99
|
+
/** Send a single SMS */
|
|
100
|
+
sendSms(to: string, message: string): Promise<SendSmsResult>;
|
|
101
|
+
/** Send 2FA SMS */
|
|
102
|
+
send2fa(to: string, code: string, template?: string): Promise<SendSmsResult>;
|
|
103
|
+
/** Send bulk SMS */
|
|
104
|
+
sendBulk(messages: Array<{
|
|
105
|
+
to: string;
|
|
106
|
+
message: string;
|
|
107
|
+
}>): Promise<{
|
|
108
|
+
success: boolean;
|
|
109
|
+
results?: any[];
|
|
110
|
+
error?: string;
|
|
111
|
+
}>;
|
|
112
|
+
/** Get SMS delivery status */
|
|
113
|
+
getSmsStatus(messageId: string): Promise<any>;
|
|
114
|
+
/** Get received SMS (inbox) */
|
|
115
|
+
getReceivedSms(): Promise<any>;
|
|
116
|
+
/** List paired devices */
|
|
117
|
+
getDevices(): Promise<DevicesResult>;
|
|
118
|
+
/** Get account usage stats */
|
|
119
|
+
getUsage(): Promise<any>;
|
|
120
|
+
/** Get E2E encryption status for a device */
|
|
121
|
+
getDeviceE2EStatus(deviceId: string): Promise<{
|
|
122
|
+
success: boolean;
|
|
123
|
+
data?: DeviceE2EStatus;
|
|
124
|
+
error?: string;
|
|
125
|
+
}>;
|
|
126
|
+
/** Get device public key for E2E encryption */
|
|
127
|
+
getDevicePublicKey(deviceId: string): Promise<{
|
|
128
|
+
success: boolean;
|
|
129
|
+
data?: DevicePublicKeyInfo;
|
|
130
|
+
error?: string;
|
|
131
|
+
}>;
|
|
132
|
+
/** Verify device key fingerprint hasn't changed (detect reinstalls) */
|
|
133
|
+
verifyDeviceKey(deviceId: string, fingerprint: string): Promise<VerifyDeviceKeyResult>;
|
|
134
|
+
/** Send encrypted SMS (payload already encrypted with device's RSA public key) */
|
|
135
|
+
sendEncryptedSms(encryptedPayload: string, deviceId: string, is2FA?: boolean): Promise<SendSmsResult>;
|
|
136
|
+
/** Update server URL configuration */
|
|
137
|
+
updateServerUrl(serverUrl: string): Promise<{
|
|
138
|
+
success: boolean;
|
|
139
|
+
}>;
|
|
140
|
+
private get;
|
|
141
|
+
private post;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export { type CreateTokenResult, type DeviceE2EStatus, type DevicePublicKeyInfo, type DevicesResult, type PairingInfo, type PairingStatusResult, SMSTUNNEL_CONFIG, type SendSmsResult, type SmsTunnelAngularConfig, SmsTunnelService, type SmsTunnelStatus, type VerifyDeviceKeyResult, provideSmsTunnel };
|
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
20
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
21
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
22
|
+
if (decorator = decorators[i])
|
|
23
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
24
|
+
if (kind && result) __defProp(target, key, result);
|
|
25
|
+
return result;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
// src/angular/index.ts
|
|
29
|
+
var angular_exports = {};
|
|
30
|
+
__export(angular_exports, {
|
|
31
|
+
SMSTUNNEL_CONFIG: () => SMSTUNNEL_CONFIG,
|
|
32
|
+
SmsTunnelService: () => SmsTunnelService,
|
|
33
|
+
provideSmsTunnel: () => provideSmsTunnel
|
|
34
|
+
});
|
|
35
|
+
module.exports = __toCommonJS(angular_exports);
|
|
36
|
+
|
|
37
|
+
// src/angular/smstunnel.service.ts
|
|
38
|
+
var import_core = require("@angular/core");
|
|
39
|
+
var SMSTUNNEL_CONFIG = new import_core.InjectionToken("SMSTUNNEL_CONFIG");
|
|
40
|
+
function provideSmsTunnel(config) {
|
|
41
|
+
return { provide: SMSTUNNEL_CONFIG, useValue: config };
|
|
42
|
+
}
|
|
43
|
+
var SmsTunnelService = class {
|
|
44
|
+
constructor() {
|
|
45
|
+
this.config = (0, import_core.inject)(SMSTUNNEL_CONFIG);
|
|
46
|
+
}
|
|
47
|
+
get baseUrl() {
|
|
48
|
+
return this.config.apiBaseUrl.replace(/\/$/, "");
|
|
49
|
+
}
|
|
50
|
+
get prefix() {
|
|
51
|
+
return this.config.routePrefix || "smstunnel";
|
|
52
|
+
}
|
|
53
|
+
authHeaders() {
|
|
54
|
+
return this.config.getAuthHeaders ? this.config.getAuthHeaders() : {};
|
|
55
|
+
}
|
|
56
|
+
// ─── Pairing ────────────────────────────────────────
|
|
57
|
+
/** Get current pairing status */
|
|
58
|
+
async getStatus() {
|
|
59
|
+
return this.get(`/${this.prefix}/status`);
|
|
60
|
+
}
|
|
61
|
+
/** Create a pairing token (generates QR) */
|
|
62
|
+
async createToken() {
|
|
63
|
+
return this.post(`/${this.prefix}/create-token`, {});
|
|
64
|
+
}
|
|
65
|
+
/** 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();
|
|
69
|
+
}
|
|
70
|
+
/** Unpair the connected device */
|
|
71
|
+
async unpair() {
|
|
72
|
+
return this.post(`/${this.prefix}/unpair`, {});
|
|
73
|
+
}
|
|
74
|
+
/** List active pairings */
|
|
75
|
+
async getPairings() {
|
|
76
|
+
return this.get(`/${this.prefix}/pairings`);
|
|
77
|
+
}
|
|
78
|
+
// ─── SMS ────────────────────────────────────────────
|
|
79
|
+
/** Send a single SMS */
|
|
80
|
+
async sendSms(to, message) {
|
|
81
|
+
return this.post(`/${this.prefix}/send`, { to, message });
|
|
82
|
+
}
|
|
83
|
+
/** Send 2FA SMS */
|
|
84
|
+
async send2fa(to, code, template) {
|
|
85
|
+
return this.post(`/${this.prefix}/send-2fa`, { to, code, template });
|
|
86
|
+
}
|
|
87
|
+
/** Send bulk SMS */
|
|
88
|
+
async sendBulk(messages) {
|
|
89
|
+
return this.post(`/${this.prefix}/send-bulk`, { messages });
|
|
90
|
+
}
|
|
91
|
+
/** Get SMS delivery status */
|
|
92
|
+
async getSmsStatus(messageId) {
|
|
93
|
+
return this.get(`/${this.prefix}/sms-status/${messageId}`);
|
|
94
|
+
}
|
|
95
|
+
/** Get received SMS (inbox) */
|
|
96
|
+
async getReceivedSms() {
|
|
97
|
+
return this.get(`/${this.prefix}/received`);
|
|
98
|
+
}
|
|
99
|
+
// ─── Devices & Account ─────────────────────────────
|
|
100
|
+
/** List paired devices */
|
|
101
|
+
async getDevices() {
|
|
102
|
+
return this.get(`/${this.prefix}/devices`);
|
|
103
|
+
}
|
|
104
|
+
/** Get account usage stats */
|
|
105
|
+
async getUsage() {
|
|
106
|
+
return this.get(`/${this.prefix}/usage`);
|
|
107
|
+
}
|
|
108
|
+
// ─── E2E Encryption ────────────────────────────────
|
|
109
|
+
/** Get E2E encryption status for a device */
|
|
110
|
+
async getDeviceE2EStatus(deviceId) {
|
|
111
|
+
return this.get(`/${this.prefix}/e2e-status/${deviceId}`);
|
|
112
|
+
}
|
|
113
|
+
/** Get device public key for E2E encryption */
|
|
114
|
+
async getDevicePublicKey(deviceId) {
|
|
115
|
+
return this.get(`/${this.prefix}/public-key/${deviceId}`);
|
|
116
|
+
}
|
|
117
|
+
/** Verify device key fingerprint hasn't changed (detect reinstalls) */
|
|
118
|
+
async verifyDeviceKey(deviceId, fingerprint) {
|
|
119
|
+
return this.post(`/${this.prefix}/verify-key`, { deviceId, fingerprint });
|
|
120
|
+
}
|
|
121
|
+
/** Send encrypted SMS (payload already encrypted with device's RSA public key) */
|
|
122
|
+
async sendEncryptedSms(encryptedPayload, deviceId, is2FA = false) {
|
|
123
|
+
return this.post(`/${this.prefix}/send-encrypted`, { encryptedPayload, deviceId, is2FA });
|
|
124
|
+
}
|
|
125
|
+
// ─── Config ─────────────────────────────────────────
|
|
126
|
+
/** Update server URL configuration */
|
|
127
|
+
async updateServerUrl(serverUrl) {
|
|
128
|
+
return this.post(`/${this.prefix}/update-config`, { serverUrl });
|
|
129
|
+
}
|
|
130
|
+
// ─── 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
|
+
}
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
SmsTunnelService = __decorateClass([
|
|
158
|
+
(0, import_core.Injectable)({ providedIn: "root" })
|
|
159
|
+
], SmsTunnelService);
|
|
160
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
161
|
+
0 && (module.exports = {
|
|
162
|
+
SMSTUNNEL_CONFIG,
|
|
163
|
+
SmsTunnelService,
|
|
164
|
+
provideSmsTunnel
|
|
165
|
+
});
|
|
166
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +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":[]}
|
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
var __defProp = Object.defineProperty;
|
|
2
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
3
|
+
var __decorateClass = (decorators, target, key, kind) => {
|
|
4
|
+
var result = kind > 1 ? void 0 : kind ? __getOwnPropDesc(target, key) : target;
|
|
5
|
+
for (var i = decorators.length - 1, decorator; i >= 0; i--)
|
|
6
|
+
if (decorator = decorators[i])
|
|
7
|
+
result = (kind ? decorator(target, key, result) : decorator(result)) || result;
|
|
8
|
+
if (kind && result) __defProp(target, key, result);
|
|
9
|
+
return result;
|
|
10
|
+
};
|
|
11
|
+
|
|
12
|
+
// src/angular/smstunnel.service.ts
|
|
13
|
+
import { Injectable, InjectionToken, inject } from "@angular/core";
|
|
14
|
+
var SMSTUNNEL_CONFIG = new InjectionToken("SMSTUNNEL_CONFIG");
|
|
15
|
+
function provideSmsTunnel(config) {
|
|
16
|
+
return { provide: SMSTUNNEL_CONFIG, useValue: config };
|
|
17
|
+
}
|
|
18
|
+
var SmsTunnelService = class {
|
|
19
|
+
constructor() {
|
|
20
|
+
this.config = inject(SMSTUNNEL_CONFIG);
|
|
21
|
+
}
|
|
22
|
+
get baseUrl() {
|
|
23
|
+
return this.config.apiBaseUrl.replace(/\/$/, "");
|
|
24
|
+
}
|
|
25
|
+
get prefix() {
|
|
26
|
+
return this.config.routePrefix || "smstunnel";
|
|
27
|
+
}
|
|
28
|
+
authHeaders() {
|
|
29
|
+
return this.config.getAuthHeaders ? this.config.getAuthHeaders() : {};
|
|
30
|
+
}
|
|
31
|
+
// ─── Pairing ────────────────────────────────────────
|
|
32
|
+
/** Get current pairing status */
|
|
33
|
+
async getStatus() {
|
|
34
|
+
return this.get(`/${this.prefix}/status`);
|
|
35
|
+
}
|
|
36
|
+
/** Create a pairing token (generates QR) */
|
|
37
|
+
async createToken() {
|
|
38
|
+
return this.post(`/${this.prefix}/create-token`, {});
|
|
39
|
+
}
|
|
40
|
+
/** 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();
|
|
44
|
+
}
|
|
45
|
+
/** Unpair the connected device */
|
|
46
|
+
async unpair() {
|
|
47
|
+
return this.post(`/${this.prefix}/unpair`, {});
|
|
48
|
+
}
|
|
49
|
+
/** List active pairings */
|
|
50
|
+
async getPairings() {
|
|
51
|
+
return this.get(`/${this.prefix}/pairings`);
|
|
52
|
+
}
|
|
53
|
+
// ─── SMS ────────────────────────────────────────────
|
|
54
|
+
/** Send a single SMS */
|
|
55
|
+
async sendSms(to, message) {
|
|
56
|
+
return this.post(`/${this.prefix}/send`, { to, message });
|
|
57
|
+
}
|
|
58
|
+
/** Send 2FA SMS */
|
|
59
|
+
async send2fa(to, code, template) {
|
|
60
|
+
return this.post(`/${this.prefix}/send-2fa`, { to, code, template });
|
|
61
|
+
}
|
|
62
|
+
/** Send bulk SMS */
|
|
63
|
+
async sendBulk(messages) {
|
|
64
|
+
return this.post(`/${this.prefix}/send-bulk`, { messages });
|
|
65
|
+
}
|
|
66
|
+
/** Get SMS delivery status */
|
|
67
|
+
async getSmsStatus(messageId) {
|
|
68
|
+
return this.get(`/${this.prefix}/sms-status/${messageId}`);
|
|
69
|
+
}
|
|
70
|
+
/** Get received SMS (inbox) */
|
|
71
|
+
async getReceivedSms() {
|
|
72
|
+
return this.get(`/${this.prefix}/received`);
|
|
73
|
+
}
|
|
74
|
+
// ─── Devices & Account ─────────────────────────────
|
|
75
|
+
/** List paired devices */
|
|
76
|
+
async getDevices() {
|
|
77
|
+
return this.get(`/${this.prefix}/devices`);
|
|
78
|
+
}
|
|
79
|
+
/** Get account usage stats */
|
|
80
|
+
async getUsage() {
|
|
81
|
+
return this.get(`/${this.prefix}/usage`);
|
|
82
|
+
}
|
|
83
|
+
// ─── E2E Encryption ────────────────────────────────
|
|
84
|
+
/** Get E2E encryption status for a device */
|
|
85
|
+
async getDeviceE2EStatus(deviceId) {
|
|
86
|
+
return this.get(`/${this.prefix}/e2e-status/${deviceId}`);
|
|
87
|
+
}
|
|
88
|
+
/** Get device public key for E2E encryption */
|
|
89
|
+
async getDevicePublicKey(deviceId) {
|
|
90
|
+
return this.get(`/${this.prefix}/public-key/${deviceId}`);
|
|
91
|
+
}
|
|
92
|
+
/** Verify device key fingerprint hasn't changed (detect reinstalls) */
|
|
93
|
+
async verifyDeviceKey(deviceId, fingerprint) {
|
|
94
|
+
return this.post(`/${this.prefix}/verify-key`, { deviceId, fingerprint });
|
|
95
|
+
}
|
|
96
|
+
/** Send encrypted SMS (payload already encrypted with device's RSA public key) */
|
|
97
|
+
async sendEncryptedSms(encryptedPayload, deviceId, is2FA = false) {
|
|
98
|
+
return this.post(`/${this.prefix}/send-encrypted`, { encryptedPayload, deviceId, is2FA });
|
|
99
|
+
}
|
|
100
|
+
// ─── Config ─────────────────────────────────────────
|
|
101
|
+
/** Update server URL configuration */
|
|
102
|
+
async updateServerUrl(serverUrl) {
|
|
103
|
+
return this.post(`/${this.prefix}/update-config`, { serverUrl });
|
|
104
|
+
}
|
|
105
|
+
// ─── 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
|
+
}
|
|
130
|
+
}
|
|
131
|
+
};
|
|
132
|
+
SmsTunnelService = __decorateClass([
|
|
133
|
+
Injectable({ providedIn: "root" })
|
|
134
|
+
], SmsTunnelService);
|
|
135
|
+
export {
|
|
136
|
+
SMSTUNNEL_CONFIG,
|
|
137
|
+
SmsTunnelService,
|
|
138
|
+
provideSmsTunnel
|
|
139
|
+
};
|
|
140
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +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":[]}
|