tsp-scale-sdk 1.0.0 ā 1.2.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 +37 -9
- package/bin/tsp-scale.js +137 -0
- package/dist/index.d.ts +39 -6
- package/dist/index.js +1 -1
- package/package.json +8 -4
package/README.md
CHANGED
|
@@ -2,28 +2,56 @@
|
|
|
2
2
|
|
|
3
3
|
Official Node.js SDK for TSP Scale.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## š Quick Start (Zero-Config)
|
|
6
6
|
|
|
7
|
+
Initialize your project in seconds. This will link your project, create a secure hidden config, and add it to your `.gitignore` automatically.
|
|
8
|
+
|
|
9
|
+
```bash
|
|
10
|
+
npx tsp-scale init
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
### Manual Installation
|
|
14
|
+
If you prefer manual setup:
|
|
7
15
|
```bash
|
|
8
16
|
npm install tsp-scale-sdk
|
|
9
17
|
```
|
|
10
18
|
|
|
11
|
-
## Usage
|
|
19
|
+
## š ļø Usage
|
|
20
|
+
|
|
21
|
+
```javascript
|
|
22
|
+
const { TspScaleClient } = require('tsp-scale-sdk');
|
|
23
|
+
|
|
24
|
+
// Authenticates automatically from local config or environment variables
|
|
25
|
+
const client = new TspScaleClient();
|
|
26
|
+
|
|
27
|
+
async function sendTest() {
|
|
28
|
+
const res = await client.sendEmail({
|
|
29
|
+
to: "recipient@example.com",
|
|
30
|
+
subject: "Hello from TSP Scale",
|
|
31
|
+
html: "<h1>It works!</h1>"
|
|
32
|
+
});
|
|
33
|
+
console.log(res);
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
run().catch(console.error);
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
> **Note**: The `from` field is optional if your API Key is locked to a specific sender identity.
|
|
40
|
+
|
|
41
|
+
### WhatsApp Messaging
|
|
12
42
|
|
|
13
43
|
```js
|
|
14
44
|
const { TspScaleClient } = require("tsp-scale-sdk");
|
|
15
45
|
|
|
16
46
|
const client = new TspScaleClient({
|
|
17
|
-
apiKey: process.env.TSP_API_KEY
|
|
18
|
-
baseUrl: "https://api.tspscale.in/api/v1",
|
|
47
|
+
apiKey: process.env.TSP_API_KEY
|
|
19
48
|
});
|
|
20
49
|
|
|
21
50
|
async function run() {
|
|
22
|
-
const result = await client.
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
html: "<h1>It works</h1>",
|
|
51
|
+
const result = await client.sendWhatsApp({
|
|
52
|
+
to: "919988776655",
|
|
53
|
+
text: "Hello from TSP Scale!",
|
|
54
|
+
// mediaUrl: "https://example.com/image.jpg" // Optional
|
|
27
55
|
});
|
|
28
56
|
|
|
29
57
|
console.log(result);
|
package/bin/tsp-scale.js
ADDED
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const { execSync } = require('child_process');
|
|
4
|
+
const path = require('path');
|
|
5
|
+
|
|
6
|
+
try {
|
|
7
|
+
// We reuse the curl CLI logic if available, or implement a lightweight version here
|
|
8
|
+
// For simplicity, we'll just implement the init logic here for the SDK
|
|
9
|
+
const readline = require('readline');
|
|
10
|
+
const fs = require('fs');
|
|
11
|
+
const crypto = require('crypto');
|
|
12
|
+
const https = require('https');
|
|
13
|
+
|
|
14
|
+
function ask(question) {
|
|
15
|
+
const rl = readline.createInterface({ input: process.stdin, output: process.stdout });
|
|
16
|
+
return new Promise(resolve => rl.question(question, ans => { rl.close(); resolve(ans); }));
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
async function post(url, data) {
|
|
20
|
+
return new Promise((resolve, reject) => {
|
|
21
|
+
const req = https.request(url, {
|
|
22
|
+
method: 'POST',
|
|
23
|
+
headers: { 'Content-Type': 'application/json' }
|
|
24
|
+
}, res => {
|
|
25
|
+
let body = '';
|
|
26
|
+
res.on('data', chunk => body += chunk);
|
|
27
|
+
res.on('end', () => resolve({ ok: res.statusCode < 300, json: () => JSON.parse(body) }));
|
|
28
|
+
});
|
|
29
|
+
req.on('error', reject);
|
|
30
|
+
req.write(JSON.stringify(data));
|
|
31
|
+
req.end();
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
async function init() {
|
|
36
|
+
console.log("\nš TSP Scale SDK - Initializing Project\n");
|
|
37
|
+
const apiKey = await ask("š Enter your API Key: ");
|
|
38
|
+
if (!apiKey) return console.error("Error: API Key is required.");
|
|
39
|
+
|
|
40
|
+
const projectIdentifier = await ask("š Enter Project Name: ");
|
|
41
|
+
const projectId = crypto.createHash('md5').update(process.cwd()).digest('hex');
|
|
42
|
+
|
|
43
|
+
console.log("ā³ Verifying with server...");
|
|
44
|
+
|
|
45
|
+
try {
|
|
46
|
+
const res = await post("https://api.tspscale.in/api/v1/apikeys/verify", {
|
|
47
|
+
key: apiKey,
|
|
48
|
+
projectId,
|
|
49
|
+
projectIdentifier: projectIdentifier || "NodeJS Project"
|
|
50
|
+
});
|
|
51
|
+
const result = await res.json();
|
|
52
|
+
if (!res.ok) throw new Error(result.message || "Verification failed");
|
|
53
|
+
|
|
54
|
+
// 1. Save to Global Vault (Fallback)
|
|
55
|
+
const configDir = path.join(os.homedir(), '.tsp-scale');
|
|
56
|
+
if (!fs.existsSync(configDir)) fs.mkdirSync(configDir, { recursive: true });
|
|
57
|
+
fs.writeFileSync(path.join(configDir, 'config.json'), JSON.stringify({ apiKey }, null, 2));
|
|
58
|
+
|
|
59
|
+
// 2. Save to Local Hidden Config (.tspscale) - Primary
|
|
60
|
+
fs.writeFileSync(path.join(process.cwd(), '.tspscale'), JSON.stringify({ apiKey, projectId }, null, 2));
|
|
61
|
+
|
|
62
|
+
// 3. Auto-GitIgnore
|
|
63
|
+
const gitignorePath = path.join(process.cwd(), '.gitignore');
|
|
64
|
+
const ignoreLine = '\n# TSP Scale Config\n.tspscale\n';
|
|
65
|
+
if (fs.existsSync(gitignorePath)) {
|
|
66
|
+
const content = fs.readFileSync(gitignorePath, 'utf8');
|
|
67
|
+
if (!content.includes('.tspscale')) fs.appendFileSync(gitignorePath, ignoreLine);
|
|
68
|
+
} else {
|
|
69
|
+
fs.writeFileSync(gitignorePath, ignoreLine);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
console.log("\nā
Success! Project linked and .tspscale config created.");
|
|
73
|
+
console.log(`š” Status: ${result.status}\n`);
|
|
74
|
+
console.log(`š Note: Added .tspscale to your .gitignore for security.\n`);
|
|
75
|
+
|
|
76
|
+
console.log("-------------------------------------------");
|
|
77
|
+
console.log("š PRODUCTION DEPLOYMENT GUIDE");
|
|
78
|
+
console.log("-------------------------------------------");
|
|
79
|
+
console.log("When you deploy to Railway, Vercel, or a VPS,");
|
|
80
|
+
console.log("add these two Environment Variables:");
|
|
81
|
+
console.log("");
|
|
82
|
+
console.log(` TSP_API_KEY = ${apiKey}`);
|
|
83
|
+
console.log(` TSP_PROJECT_ID = ${projectId}`);
|
|
84
|
+
console.log("-------------------------------------------\n");
|
|
85
|
+
|
|
86
|
+
const install = await ask("š¦ Would you like to install the 'tsp-scale-sdk' in this project? (y/n): ");
|
|
87
|
+
if (install.toLowerCase() === 'y') {
|
|
88
|
+
console.log("ā³ Installing...");
|
|
89
|
+
try {
|
|
90
|
+
execSync('npm install tsp-scale-sdk', { stdio: 'inherit' });
|
|
91
|
+
console.log("\nā
SDK installed successfully!");
|
|
92
|
+
} catch (e) {
|
|
93
|
+
console.error("\nā Installation failed. Please run 'npm install tsp-scale-sdk' manually.");
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
const example = await ask("š Would you like to generate a sample 'tsp-test.js' script? (y/n): ");
|
|
98
|
+
if (example.toLowerCase() === 'y') {
|
|
99
|
+
const sampleCode = `const { TspScaleClient } = require('tsp-scale-sdk');
|
|
100
|
+
require('dotenv').config();
|
|
101
|
+
|
|
102
|
+
const client = new TspScaleClient(process.env.TSP_API_KEY);
|
|
103
|
+
|
|
104
|
+
async function main() {
|
|
105
|
+
console.log("Sending test email...");
|
|
106
|
+
try {
|
|
107
|
+
const res = await client.sendEmail({
|
|
108
|
+
from: "support@yourdomain.com", // Replace with your verified sender
|
|
109
|
+
to: "recipient@example.com",
|
|
110
|
+
subject: "TSP Scale Test",
|
|
111
|
+
html: "<h1>It works!</h1>"
|
|
112
|
+
});
|
|
113
|
+
console.log("Response:", res);
|
|
114
|
+
} catch (err) {
|
|
115
|
+
console.error("Error:", err.message);
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
main();`;
|
|
120
|
+
fs.writeFileSync(path.join(process.cwd(), "tsp-test.js"), sampleCode);
|
|
121
|
+
console.log("\nā
'tsp-test.js' created. Run it with: node tsp-test.js");
|
|
122
|
+
}
|
|
123
|
+
} catch (err) {
|
|
124
|
+
console.error(`\nā Error: ${err.message}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
const command = process.argv[2];
|
|
129
|
+
if (command === 'init') {
|
|
130
|
+
init();
|
|
131
|
+
} else {
|
|
132
|
+
console.log("Usage: npx tsp-scale init");
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
} catch (err) {
|
|
136
|
+
console.error("Initialization failed:", err.message);
|
|
137
|
+
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,3 +1,9 @@
|
|
|
1
|
+
export type EmailAttachment = {
|
|
2
|
+
filename: string;
|
|
3
|
+
contentType: string;
|
|
4
|
+
content: string;
|
|
5
|
+
};
|
|
6
|
+
|
|
1
7
|
export type SendEmailPayload = {
|
|
2
8
|
to: string;
|
|
3
9
|
from: string;
|
|
@@ -6,11 +12,37 @@ export type SendEmailPayload = {
|
|
|
6
12
|
html?: string;
|
|
7
13
|
bodyText?: string;
|
|
8
14
|
bodyHtml?: string;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
15
|
+
priority?: number;
|
|
16
|
+
region?: string;
|
|
17
|
+
category?: string;
|
|
18
|
+
attachments?: EmailAttachment[];
|
|
19
|
+
expiresIn?: number;
|
|
20
|
+
useGhost?: boolean;
|
|
21
|
+
runForensics?: boolean;
|
|
22
|
+
isLocked?: boolean;
|
|
23
|
+
scheduledAt?: string;
|
|
24
|
+
templateId?: string;
|
|
25
|
+
viewPassword?: string;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
export type SendEmailStatus = "QUEUED" | "SANDBOX_DELIVERED";
|
|
29
|
+
|
|
30
|
+
export type SendEmailResponse = {
|
|
31
|
+
id: string;
|
|
32
|
+
status: SendEmailStatus;
|
|
33
|
+
message?: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
36
|
+
export type SendWhatsAppPayload = {
|
|
37
|
+
to: string;
|
|
38
|
+
text: string;
|
|
39
|
+
mediaUrl?: string;
|
|
40
|
+
configId?: string;
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
export type SendWhatsAppResponse = {
|
|
44
|
+
success: true;
|
|
45
|
+
message: string;
|
|
14
46
|
};
|
|
15
47
|
|
|
16
48
|
export type TspScaleClientOptions = {
|
|
@@ -23,5 +55,6 @@ export type TspScaleClientOptions = {
|
|
|
23
55
|
|
|
24
56
|
export declare class TspScaleClient {
|
|
25
57
|
constructor(options: TspScaleClientOptions);
|
|
26
|
-
sendEmail(payload: SendEmailPayload): Promise<
|
|
58
|
+
sendEmail(payload: SendEmailPayload): Promise<SendEmailResponse>;
|
|
59
|
+
sendWhatsApp(payload: SendWhatsAppPayload): Promise<SendWhatsAppResponse>;
|
|
27
60
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
var
|
|
1
|
+
var d=require("crypto"),m="1.2.0",y={prod:"https://api.tspscale.in/api/v1",staging:"https://staging-api.tspscale.in/api/v1",local:"http://localhost:4000/api/v1"};function g(l){if(l.baseUrl)return l.baseUrl;let t=(l.env||"prod").toLowerCase();return y[t]||y.prod}var f=class{constructor(t){let s={};typeof t=="string"?s={apiKey:t}:s=t||{};let e=require("fs"),o=require("path"),a=require("os"),n=this._loadLocalConfig();if(this.apiKey=s.apiKey||process.env.TSP_API_KEY||n.apiKey||this._loadGlobalKey(),this.projectId=s.projectId||process.env.TSP_PROJECT_ID||n.projectId,this.apiKey||console.warn("\u26A0\uFE0F TSP Scale: No API Key found. Run 'npx tsp-scale init'."),this.baseUrl=g(s).replace(/\/+$/,""),this.timeoutMs=s.timeoutMs||15e3,this.fetchImpl=s.fetchImpl||globalThis.fetch,typeof this.fetchImpl!="function")throw new Error("Fetch implementation is not available. Use Node 18+ or pass fetchImpl.")}_loadLocalConfig(){try{let t=require("fs"),e=require("path").join(process.cwd(),".tspscale");if(t.existsSync(e))return JSON.parse(t.readFileSync(e,"utf8"))}catch{}return{}}_loadGlobalKey(){try{let t=require("fs"),s=require("path"),e=require("os"),o=s.join(e.homedir(),".tsp-scale","config.json");if(t.existsSync(o))return JSON.parse(t.readFileSync(o,"utf8")).apiKey}catch{}return null}async sendEmail(t){let s="/emails/send",e=`${this.baseUrl}${s}`,o=JSON.stringify(t||{}),a=Date.now().toString(),n=d.randomBytes(16).toString("hex"),h=this._sign({timestamp:a,nonce:n,method:"POST",path:s,body:o}),p=new AbortController,u=setTimeout(()=>p.abort(),this.timeoutMs);try{let i=await this.fetchImpl(e,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":this.apiKey,"x-tsp-client":`tsp-scale-sdk/${m}`,"x-tsp-timestamp":a,"x-tsp-nonce":n,"x-tsp-signature":h,...this.projectId?{"x-tsp-project-id":this.projectId}:{}},body:o,signal:p.signal}),r=await i.json().catch(()=>({}));if(!i.ok){let c=new Error(r?.error||`Request failed with status ${i.status}`);throw c.status=i.status,c.response=r,c}return r}finally{clearTimeout(u)}}async sendWhatsApp(t){let s="/whatsapp/messages/send",e=`${this.baseUrl}${s}`,o=JSON.stringify(t||{}),a=Date.now().toString(),n=d.randomBytes(16).toString("hex"),h=this._sign({timestamp:a,nonce:n,method:"POST",path:s,body:o}),p=new AbortController,u=setTimeout(()=>p.abort(),this.timeoutMs);try{let i=await this.fetchImpl(e,{method:"POST",headers:{"Content-Type":"application/json","x-api-key":this.apiKey,"x-tsp-client":`tsp-scale-sdk/${m}`,"x-tsp-timestamp":a,"x-tsp-nonce":n,"x-tsp-signature":h},body:o,signal:p.signal}),r=await i.json().catch(()=>({}));if(!i.ok){let c=new Error(r?.error||`Request failed with status ${i.status}`);throw c.status=i.status,c.response=r,c}return r}finally{clearTimeout(u)}}_sign({timestamp:t,nonce:s,method:e,path:o,body:a}){let n=`${t}.${s}.${e}.${o}.${a}`;return d.createHmac("sha256",this.apiKey).update(n).digest("hex")}};module.exports={TspScaleClient:f};
|
|
2
2
|
//# sourceMappingURL=index.js.map
|
package/package.json
CHANGED
|
@@ -1,19 +1,23 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "tsp-scale-sdk",
|
|
3
|
-
"version": "1.
|
|
4
|
-
"description": "Official Node.js client for TSP Scale
|
|
3
|
+
"version": "1.2.0",
|
|
4
|
+
"description": "Official Node.js client for TSP Scale Email and WhatsApp API",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"author": "TSP Scale",
|
|
8
8
|
"license": "MIT",
|
|
9
9
|
"homepage": "https://tspscale.in",
|
|
10
|
+
"bin": {
|
|
11
|
+
"tsp-scale": "./bin/tsp-scale.js"
|
|
12
|
+
},
|
|
10
13
|
"keywords": [
|
|
11
14
|
"tsp",
|
|
12
15
|
"smtp",
|
|
13
16
|
"email",
|
|
17
|
+
"whatsapp",
|
|
18
|
+
"automation",
|
|
14
19
|
"api-client",
|
|
15
|
-
"transactional-email"
|
|
16
|
-
"developer-tools"
|
|
20
|
+
"transactional-email"
|
|
17
21
|
],
|
|
18
22
|
"files": [
|
|
19
23
|
"dist/index.js",
|