@thisispamela/sdk 1.0.0

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/README.md ADDED
@@ -0,0 +1,65 @@
1
+ # Pamela SDK for JavaScript/TypeScript
2
+
3
+ Official SDK for the Pamela Voice API.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @pamela/sdk
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ### Basic Example
14
+
15
+ ```typescript
16
+ import { PamelaClient } from '@pamela/sdk';
17
+
18
+ const client = new PamelaClient({
19
+ apiKey: 'pk_live_your_api_key_here',
20
+ baseUrl: 'https://api.thisispamela.com', // Optional
21
+ });
22
+
23
+ // Create a call
24
+ const call = await client.createCall({
25
+ to: '+1234567890',
26
+ task: 'Order a large pizza for delivery',
27
+ locale: 'en-US',
28
+ });
29
+
30
+ console.log('Call created:', call.id);
31
+
32
+ // Get call status
33
+ const status = await client.getCall(call.id);
34
+ console.log('Call status:', status.status);
35
+ ```
36
+
37
+ ### Webhook Verification
38
+
39
+ ```typescript
40
+ import { PamelaClient } from '@pamela/b2b-sdk';
41
+ import express from 'express';
42
+
43
+ const app = express();
44
+ const WEBHOOK_SECRET = 'your_webhook_secret';
45
+
46
+ app.post('/webhooks/pamela', express.json(), (req, res) => {
47
+ const signature = req.headers['x-pamela-signature'] as string;
48
+ const payload = req.body;
49
+
50
+ if (!PamelaClient.verifyWebhookSignature(payload, signature, WEBHOOK_SECRET)) {
51
+ return res.status(401).send('Invalid signature');
52
+ }
53
+
54
+ // Handle webhook event
55
+ console.log('Webhook event:', payload.event);
56
+ console.log('Call ID:', payload.call_id);
57
+
58
+ res.status(200).send('OK');
59
+ });
60
+ ```
61
+
62
+ ## API Reference
63
+
64
+ See the [Pamela B2B API Documentation](https://docs.thisispamela.com/b2b) for full API reference.
65
+
@@ -0,0 +1,130 @@
1
+ /**
2
+ * Pamela B2B Voice API SDK for JavaScript/TypeScript
3
+ */
4
+ export interface PamelaClientConfig {
5
+ apiKey: string;
6
+ baseUrl?: string;
7
+ }
8
+ export interface CreateCallRequest {
9
+ to: string;
10
+ country?: string;
11
+ locale?: string;
12
+ task: string;
13
+ instructions?: string;
14
+ end_user_id?: string;
15
+ metadata?: Record<string, any>;
16
+ tools?: Array<Record<string, any>>;
17
+ webhooks?: {
18
+ webhook_url?: string;
19
+ tool_webhook_url?: string;
20
+ };
21
+ }
22
+ export interface CallResponse {
23
+ id: string;
24
+ status: string;
25
+ call_session_id: string;
26
+ created_at: string;
27
+ }
28
+ export interface CallStatus {
29
+ id: string;
30
+ status: string;
31
+ to: string;
32
+ from_: string;
33
+ country: string;
34
+ created_at: string;
35
+ started_at?: string;
36
+ completed_at?: string;
37
+ duration_seconds?: number;
38
+ transcript?: Array<Record<string, any>>;
39
+ summary?: string;
40
+ metadata: Record<string, any>;
41
+ end_user_id?: string;
42
+ }
43
+ export interface ToolDefinition {
44
+ name: string;
45
+ description: string;
46
+ input_schema: Record<string, any>;
47
+ output_schema?: Record<string, any>;
48
+ timeout_ms?: number;
49
+ }
50
+ export interface WebhookPayload {
51
+ event: string;
52
+ call_id: string;
53
+ call_session_id: string;
54
+ timestamp: string;
55
+ data: Record<string, any>;
56
+ }
57
+ export declare class PamelaClient {
58
+ private client;
59
+ private apiKey;
60
+ constructor(config: PamelaClientConfig);
61
+ /**
62
+ * Create a new call.
63
+ */
64
+ createCall(request: CreateCallRequest): Promise<CallResponse>;
65
+ /**
66
+ * Get call status and details.
67
+ */
68
+ getCall(callId: string): Promise<CallStatus>;
69
+ /**
70
+ * List calls for the authenticated partner/project.
71
+ */
72
+ listCalls(params?: {
73
+ status?: string;
74
+ limit?: number;
75
+ offset?: number;
76
+ start_date?: string;
77
+ end_date?: string;
78
+ }): Promise<{
79
+ items: CallStatus[];
80
+ total: number;
81
+ limit: number;
82
+ offset: number;
83
+ }>;
84
+ /**
85
+ * Cancel an in-progress call.
86
+ */
87
+ cancelCall(callId: string): Promise<{
88
+ success: boolean;
89
+ call_id: string;
90
+ status: string;
91
+ }>;
92
+ /**
93
+ * Register a tool.
94
+ */
95
+ registerTool(tool: ToolDefinition): Promise<{
96
+ id: string;
97
+ project_id: string;
98
+ name: string;
99
+ description: string;
100
+ input_schema: Record<string, any>;
101
+ output_schema: Record<string, any>;
102
+ timeout_ms: number;
103
+ created_at: string;
104
+ }>;
105
+ /**
106
+ * List all tools for the project.
107
+ */
108
+ listTools(): Promise<Array<{
109
+ id: string;
110
+ project_id: string;
111
+ name: string;
112
+ description: string;
113
+ input_schema: Record<string, any>;
114
+ output_schema: Record<string, any>;
115
+ timeout_ms: number;
116
+ created_at: string;
117
+ }>>;
118
+ /**
119
+ * Delete a tool.
120
+ */
121
+ deleteTool(toolId: string): Promise<{
122
+ success: boolean;
123
+ tool_id: string;
124
+ }>;
125
+ /**
126
+ * Verify webhook signature.
127
+ */
128
+ static verifyWebhookSignature(payload: string | object, signature: string, secret: string): boolean;
129
+ }
130
+ export default PamelaClient;
package/dist/index.js ADDED
@@ -0,0 +1,134 @@
1
+ "use strict";
2
+ /**
3
+ * Pamela B2B Voice API SDK for JavaScript/TypeScript
4
+ */
5
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ var desc = Object.getOwnPropertyDescriptor(m, k);
8
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
9
+ desc = { enumerable: true, get: function() { return m[k]; } };
10
+ }
11
+ Object.defineProperty(o, k2, desc);
12
+ }) : (function(o, m, k, k2) {
13
+ if (k2 === undefined) k2 = k;
14
+ o[k2] = m[k];
15
+ }));
16
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
17
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
18
+ }) : function(o, v) {
19
+ o["default"] = v;
20
+ });
21
+ var __importStar = (this && this.__importStar) || (function () {
22
+ var ownKeys = function(o) {
23
+ ownKeys = Object.getOwnPropertyNames || function (o) {
24
+ var ar = [];
25
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
26
+ return ar;
27
+ };
28
+ return ownKeys(o);
29
+ };
30
+ return function (mod) {
31
+ if (mod && mod.__esModule) return mod;
32
+ var result = {};
33
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
34
+ __setModuleDefault(result, mod);
35
+ return result;
36
+ };
37
+ })();
38
+ var __importDefault = (this && this.__importDefault) || function (mod) {
39
+ return (mod && mod.__esModule) ? mod : { "default": mod };
40
+ };
41
+ Object.defineProperty(exports, "__esModule", { value: true });
42
+ exports.PamelaClient = void 0;
43
+ const axios_1 = __importDefault(require("axios"));
44
+ const crypto = __importStar(require("crypto"));
45
+ class PamelaClient {
46
+ constructor(config) {
47
+ this.apiKey = config.apiKey;
48
+ const baseURL = config.baseUrl || 'https://api.thisispamela.com';
49
+ this.client = axios_1.default.create({
50
+ baseURL: `${baseURL}/api/b2b/v1`,
51
+ headers: {
52
+ 'Authorization': `Bearer ${this.apiKey}`,
53
+ 'Content-Type': 'application/json',
54
+ },
55
+ timeout: 30000,
56
+ });
57
+ // Add retry logic
58
+ this.client.interceptors.response.use((response) => response, async (error) => {
59
+ const config = error.config;
60
+ if (!config || !config.retry) {
61
+ config.retry = 0;
62
+ }
63
+ config.retry += 1;
64
+ if (config.retry <= 3 && error.response?.status && error.response.status >= 500) {
65
+ await new Promise(resolve => setTimeout(resolve, 1000 * config.retry));
66
+ return this.client.request(config);
67
+ }
68
+ return Promise.reject(error);
69
+ });
70
+ }
71
+ /**
72
+ * Create a new call.
73
+ */
74
+ async createCall(request) {
75
+ const response = await this.client.post('/calls', request);
76
+ return response.data;
77
+ }
78
+ /**
79
+ * Get call status and details.
80
+ */
81
+ async getCall(callId) {
82
+ const response = await this.client.get(`/calls/${callId}`);
83
+ return response.data;
84
+ }
85
+ /**
86
+ * List calls for the authenticated partner/project.
87
+ */
88
+ async listCalls(params) {
89
+ const response = await this.client.get('/calls', { params });
90
+ // Backend returns { items: [...], total, limit, offset }
91
+ return response.data;
92
+ }
93
+ /**
94
+ * Cancel an in-progress call.
95
+ */
96
+ async cancelCall(callId) {
97
+ const response = await this.client.post(`/calls/${callId}/cancel`);
98
+ return response.data;
99
+ }
100
+ /**
101
+ * Register a tool.
102
+ */
103
+ async registerTool(tool) {
104
+ const response = await this.client.post('/tools', { tool });
105
+ return response.data;
106
+ }
107
+ /**
108
+ * List all tools for the project.
109
+ */
110
+ async listTools() {
111
+ const response = await this.client.get('/tools');
112
+ return response.data;
113
+ }
114
+ /**
115
+ * Delete a tool.
116
+ */
117
+ async deleteTool(toolId) {
118
+ const response = await this.client.delete(`/tools/${toolId}`);
119
+ return response.data;
120
+ }
121
+ /**
122
+ * Verify webhook signature.
123
+ */
124
+ static verifyWebhookSignature(payload, signature, secret) {
125
+ const payloadString = typeof payload === 'string' ? payload : JSON.stringify(payload);
126
+ const expectedSignature = crypto
127
+ .createHmac('sha256', secret)
128
+ .update(payloadString)
129
+ .digest('hex');
130
+ return crypto.timingSafeEqual(Buffer.from(signature), Buffer.from(expectedSignature));
131
+ }
132
+ }
133
+ exports.PamelaClient = PamelaClient;
134
+ exports.default = PamelaClient;
package/jest.config.js ADDED
@@ -0,0 +1,13 @@
1
+ module.exports = {
2
+ preset: 'ts-jest',
3
+ testEnvironment: 'node',
4
+ roots: ['<rootDir>/tests'],
5
+ testMatch: ['**/*.test.ts'],
6
+ collectCoverageFrom: [
7
+ 'src/**/*.ts',
8
+ '!src/**/*.d.ts',
9
+ ],
10
+ coverageDirectory: 'coverage',
11
+ coverageReporters: ['text', 'lcov', 'html'],
12
+ };
13
+
package/package.json ADDED
@@ -0,0 +1,33 @@
1
+ {
2
+ "name": "@thisispamela/sdk",
3
+ "version": "1.0.0",
4
+ "description": "Pamela B2B Voice API SDK for JavaScript/TypeScript",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc",
9
+ "test": "jest",
10
+ "test:watch": "jest --watch",
11
+ "prepublishOnly": "npm run build"
12
+ },
13
+ "keywords": [
14
+ "pamela",
15
+ "voice",
16
+ "api",
17
+ "b2b",
18
+ "phone",
19
+ "calling"
20
+ ],
21
+ "author": "Pamela",
22
+ "license": "MIT",
23
+ "dependencies": {
24
+ "axios": "^1.6.0"
25
+ },
26
+ "devDependencies": {
27
+ "@types/node": "^20.0.0",
28
+ "@types/jest": "^29.5.0",
29
+ "typescript": "^5.0.0",
30
+ "jest": "^29.7.0",
31
+ "ts-jest": "^29.1.0"
32
+ }
33
+ }
package/src/index.ts ADDED
@@ -0,0 +1,189 @@
1
+ /**
2
+ * Pamela B2B Voice API SDK for JavaScript/TypeScript
3
+ */
4
+
5
+ import axios, { AxiosInstance, AxiosError } from 'axios';
6
+ import * as crypto from 'crypto';
7
+
8
+ export interface PamelaClientConfig {
9
+ apiKey: string;
10
+ baseUrl?: string;
11
+ }
12
+
13
+ export interface CreateCallRequest {
14
+ to: string;
15
+ country?: string;
16
+ locale?: string;
17
+ task: string;
18
+ instructions?: string;
19
+ end_user_id?: string;
20
+ metadata?: Record<string, any>;
21
+ tools?: Array<Record<string, any>>;
22
+ webhooks?: {
23
+ webhook_url?: string;
24
+ tool_webhook_url?: string;
25
+ };
26
+ }
27
+
28
+ export interface CallResponse {
29
+ id: string;
30
+ status: string;
31
+ call_session_id: string;
32
+ created_at: string;
33
+ }
34
+
35
+ export interface CallStatus {
36
+ id: string;
37
+ status: string;
38
+ to: string;
39
+ from_: string; // Backend uses from_ (Python keyword)
40
+ country: string;
41
+ created_at: string;
42
+ started_at?: string;
43
+ completed_at?: string;
44
+ duration_seconds?: number;
45
+ transcript?: Array<Record<string, any>>;
46
+ summary?: string;
47
+ metadata: Record<string, any>;
48
+ end_user_id?: string; // Marketplace end-user ID for privacy isolation
49
+ }
50
+
51
+ export interface ToolDefinition {
52
+ name: string;
53
+ description: string;
54
+ input_schema: Record<string, any>;
55
+ output_schema?: Record<string, any>;
56
+ timeout_ms?: number;
57
+ }
58
+
59
+ export interface WebhookPayload {
60
+ event: string;
61
+ call_id: string;
62
+ call_session_id: string;
63
+ timestamp: string;
64
+ data: Record<string, any>;
65
+ }
66
+
67
+ export class PamelaClient {
68
+ private client: AxiosInstance;
69
+ private apiKey: string;
70
+
71
+ constructor(config: PamelaClientConfig) {
72
+ this.apiKey = config.apiKey;
73
+ const baseURL = config.baseUrl || 'https://api.thisispamela.com';
74
+
75
+ this.client = axios.create({
76
+ baseURL: `${baseURL}/api/b2b/v1`,
77
+ headers: {
78
+ 'Authorization': `Bearer ${this.apiKey}`,
79
+ 'Content-Type': 'application/json',
80
+ },
81
+ timeout: 30000,
82
+ });
83
+
84
+ // Add retry logic
85
+ this.client.interceptors.response.use(
86
+ (response) => response,
87
+ async (error: AxiosError) => {
88
+ const config = error.config as any;
89
+ if (!config || !config.retry) {
90
+ config.retry = 0;
91
+ }
92
+ config.retry += 1;
93
+
94
+ if (config.retry <= 3 && error.response?.status && error.response.status >= 500) {
95
+ await new Promise(resolve => setTimeout(resolve, 1000 * config.retry));
96
+ return this.client.request(config);
97
+ }
98
+
99
+ return Promise.reject(error);
100
+ }
101
+ );
102
+ }
103
+
104
+ /**
105
+ * Create a new call.
106
+ */
107
+ async createCall(request: CreateCallRequest): Promise<CallResponse> {
108
+ const response = await this.client.post<CallResponse>('/calls', request);
109
+ return response.data;
110
+ }
111
+
112
+ /**
113
+ * Get call status and details.
114
+ */
115
+ async getCall(callId: string): Promise<CallStatus> {
116
+ const response = await this.client.get<CallStatus>(`/calls/${callId}`);
117
+ return response.data;
118
+ }
119
+
120
+ /**
121
+ * List calls for the authenticated partner/project.
122
+ */
123
+ async listCalls(params?: {
124
+ status?: string;
125
+ limit?: number;
126
+ offset?: number;
127
+ start_date?: string;
128
+ end_date?: string;
129
+ }): Promise<{ items: CallStatus[]; total: number; limit: number; offset: number }> {
130
+ const response = await this.client.get('/calls', { params });
131
+ // Backend returns { items: [...], total, limit, offset }
132
+ return response.data;
133
+ }
134
+
135
+ /**
136
+ * Cancel an in-progress call.
137
+ */
138
+ async cancelCall(callId: string): Promise<{ success: boolean; call_id: string; status: string }> {
139
+ const response = await this.client.post(`/calls/${callId}/cancel`);
140
+ return response.data;
141
+ }
142
+
143
+ /**
144
+ * Register a tool.
145
+ */
146
+ async registerTool(tool: ToolDefinition): Promise<{ id: string; project_id: string; name: string; description: string; input_schema: Record<string, any>; output_schema: Record<string, any>; timeout_ms: number; created_at: string }> {
147
+ const response = await this.client.post('/tools', { tool });
148
+ return response.data;
149
+ }
150
+
151
+ /**
152
+ * List all tools for the project.
153
+ */
154
+ async listTools(): Promise<Array<{ id: string; project_id: string; name: string; description: string; input_schema: Record<string, any>; output_schema: Record<string, any>; timeout_ms: number; created_at: string }>> {
155
+ const response = await this.client.get('/tools');
156
+ return response.data;
157
+ }
158
+
159
+ /**
160
+ * Delete a tool.
161
+ */
162
+ async deleteTool(toolId: string): Promise<{ success: boolean; tool_id: string }> {
163
+ const response = await this.client.delete(`/tools/${toolId}`);
164
+ return response.data;
165
+ }
166
+
167
+ /**
168
+ * Verify webhook signature.
169
+ */
170
+ static verifyWebhookSignature(
171
+ payload: string | object,
172
+ signature: string,
173
+ secret: string
174
+ ): boolean {
175
+ const payloadString = typeof payload === 'string' ? payload : JSON.stringify(payload);
176
+ const expectedSignature = crypto
177
+ .createHmac('sha256', secret)
178
+ .update(payloadString)
179
+ .digest('hex');
180
+
181
+ return crypto.timingSafeEqual(
182
+ Buffer.from(signature),
183
+ Buffer.from(expectedSignature)
184
+ );
185
+ }
186
+ }
187
+
188
+ export default PamelaClient;
189
+
@@ -0,0 +1,136 @@
1
+ /**
2
+ * Integration tests for Pamela JavaScript SDK.
3
+ *
4
+ * Tests against staging API or mocked responses.
5
+ */
6
+
7
+ import { Pamela } from "../src/index";
8
+
9
+ const TEST_API_URL = process.env.TEST_API_URL || "https://pamela-dev.up.railway.app";
10
+ const TEST_API_KEY = process.env.TEST_API_KEY || "pk_test_placeholder";
11
+
12
+ describe("Pamela SDK", () => {
13
+ let sdk: Pamela;
14
+
15
+ beforeEach(() => {
16
+ sdk = new Pamela({
17
+ apiKey: TEST_API_KEY,
18
+ apiUrl: TEST_API_URL,
19
+ });
20
+ });
21
+
22
+ describe("Initialization", () => {
23
+ it("should initialize with API key", () => {
24
+ expect(sdk).toBeDefined();
25
+ });
26
+
27
+ it("should throw error without API key", () => {
28
+ expect(() => {
29
+ new Pamela({ apiKey: "" });
30
+ }).toThrow();
31
+ });
32
+ });
33
+
34
+ describe("Call Creation", () => {
35
+ it("should create a call with required parameters", async () => {
36
+ // Mock or use staging API
37
+ const call = await sdk.calls.create({
38
+ to: "+1234567890",
39
+ from_: "+1987654321",
40
+ country: "US",
41
+ });
42
+
43
+ expect(call).toBeDefined();
44
+ expect(call.id).toBeDefined();
45
+ expect(call.status).toBeDefined();
46
+ });
47
+
48
+ it("should handle invalid phone numbers", async () => {
49
+ await expect(
50
+ sdk.calls.create({
51
+ to: "invalid",
52
+ from_: "+1987654321",
53
+ country: "US",
54
+ })
55
+ ).rejects.toThrow();
56
+ });
57
+ });
58
+
59
+ describe("Call Status", () => {
60
+ it("should get call status by ID", async () => {
61
+ const callId = "test_call_id";
62
+ const status = await sdk.calls.getStatus(callId);
63
+
64
+ expect(status).toBeDefined();
65
+ expect(status.id).toBe(callId);
66
+ expect(status.status).toBeDefined();
67
+ });
68
+
69
+ it("should handle non-existent call ID", async () => {
70
+ await expect(sdk.calls.getStatus("nonexistent")).rejects.toThrow();
71
+ });
72
+ });
73
+
74
+ describe("Call Cancellation", () => {
75
+ it("should cancel an in-progress call", async () => {
76
+ const callId = "test_call_id";
77
+ const result = await sdk.calls.cancel(callId);
78
+
79
+ expect(result).toBeDefined();
80
+ expect(result.success).toBe(true);
81
+ });
82
+
83
+ it("should handle cancelling already completed call", async () => {
84
+ await expect(sdk.calls.cancel("completed_call")).rejects.toThrow();
85
+ });
86
+ });
87
+
88
+ describe("Usage", () => {
89
+ it("should get usage statistics", async () => {
90
+ const usage = await sdk.usage.get("2024-01");
91
+
92
+ expect(usage).toBeDefined();
93
+ expect(usage.call_count).toBeDefined();
94
+ expect(usage.quota).toBeDefined();
95
+ });
96
+
97
+ it("should handle invalid period format", async () => {
98
+ await expect(sdk.usage.get("invalid")).rejects.toThrow();
99
+ });
100
+ });
101
+
102
+ describe("Error Handling", () => {
103
+ it("should handle network errors", async () => {
104
+ // Test with invalid API URL
105
+ const badSdk = new Pamela({
106
+ apiKey: TEST_API_KEY,
107
+ apiUrl: "https://invalid-url.example.com",
108
+ });
109
+
110
+ await expect(
111
+ badSdk.calls.create({
112
+ to: "+1234567890",
113
+ from_: "+1987654321",
114
+ country: "US",
115
+ })
116
+ ).rejects.toThrow();
117
+ });
118
+
119
+ it("should handle API errors (400, 401, 403, 500)", async () => {
120
+ // Test with invalid API key
121
+ const badSdk = new Pamela({
122
+ apiKey: "invalid_key",
123
+ apiUrl: TEST_API_URL,
124
+ });
125
+
126
+ await expect(
127
+ badSdk.calls.create({
128
+ to: "+1234567890",
129
+ from_: "+1987654321",
130
+ country: "US",
131
+ })
132
+ ).rejects.toThrow();
133
+ });
134
+ });
135
+ });
136
+
package/tests/setup.ts ADDED
@@ -0,0 +1,31 @@
1
+ /**
2
+ * Test setup for JavaScript SDK tests.
3
+ *
4
+ * Configure test environment, mock API responses, etc.
5
+ */
6
+
7
+ // Set test API URL (use staging or mock server)
8
+ export const TEST_API_URL = process.env.TEST_API_URL || "https://pamela-dev.up.railway.app";
9
+
10
+ // Test API key (use test keys from staging environment)
11
+ export const TEST_API_KEY = process.env.TEST_API_KEY || "pk_test_placeholder";
12
+
13
+ // Mock data helpers
14
+ export const mockCallResponse = {
15
+ id: "call_test_123",
16
+ status: "queued",
17
+ to: "+1234567890",
18
+ from_: "+1987654321",
19
+ created_at: new Date().toISOString(),
20
+ };
21
+
22
+ export const mockCallStatusResponse = {
23
+ id: "call_test_123",
24
+ status: "completed",
25
+ to: "+1234567890",
26
+ from_: "+1987654321",
27
+ duration_seconds: 120,
28
+ created_at: new Date().toISOString(),
29
+ completed_at: new Date().toISOString(),
30
+ };
31
+
package/tsconfig.json ADDED
@@ -0,0 +1,18 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "commonjs",
5
+ "lib": ["ES2020"],
6
+ "declaration": true,
7
+ "outDir": "./dist",
8
+ "rootDir": "./src",
9
+ "strict": true,
10
+ "esModuleInterop": true,
11
+ "skipLibCheck": true,
12
+ "forceConsistentCasingInFileNames": true,
13
+ "resolveJsonModule": true
14
+ },
15
+ "include": ["src/**/*"],
16
+ "exclude": ["node_modules", "dist"]
17
+ }
18
+