Skip to content

Commit fef5940

Browse files
authored
Merge pull request #5 from Devotel/feat/tests
Make the tests coverage both esm and commonjs modules.
2 parents f66f2f0 + 7ced201 commit fef5940

17 files changed

+937
-21
lines changed

.github/workflows/test.yml

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
name: Test Module Compatibility
2+
3+
on:
4+
push:
5+
branches: [ main, develop ]
6+
pull_request:
7+
branches: [ main ]
8+
9+
jobs:
10+
test:
11+
runs-on: ubuntu-latest
12+
strategy:
13+
matrix:
14+
node-version: [18, 20, 22]
15+
16+
steps:
17+
- uses: actions/checkout@v4
18+
19+
- name: Use Node.js ${{ matrix.node-version }}
20+
uses: actions/setup-node@v4
21+
with:
22+
node-version: ${{ matrix.node-version }}
23+
cache: 'npm'
24+
25+
- run: npm ci
26+
- run: npm run build
27+
- run: npm run test:modules
28+
- run: npm test

README.md

Lines changed: 180 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,53 @@
1-
# DevHub Node.js SDK
1+
# DevHub Node.js SDK 📡
2+
3+
[![npm version](https://badge.fury.io/js/@devotel%2Fdevhub.svg)](https://badge.fury.io/js/@devotel%2Fdevhub)
4+
[![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/)
5+
[![Node.js](https://img.shields.io/badge/Node.js-18%2B-green.svg)](https://nodejs.org/)
6+
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7+
[![ESM](https://img.shields.io/badge/ESM-Ready-brightgreen.svg)](https://nodejs.org/api/esm.html)
8+
[![CommonJS](https://img.shields.io/badge/CommonJS-Ready-brightgreen.svg)](https://nodejs.org/api/modules.html)
29

310
Official Node.js SDK for the DevHub Communication API.
411

5-
## Installation
12+
## 📦 Installation
613

714
```bash
8-
npm install @devotel/devhub
15+
npm i @devotel/devhub
16+
```
17+
18+
## 🔧 Module Compatibility
19+
20+
This SDK supports both **ESM** (ES Modules) and **CommonJS** module systems:
21+
22+
### ESM (ES Modules)
23+
24+
```javascript
25+
// Default import (recommended)
26+
import DevHubSDK from "@devotel/devhub";
27+
28+
// Named import
29+
import { DevHubSDK } from "@devotel/devhub";
30+
31+
const devhub = new DevHubSDK({
32+
apiKey: "<your-api-key>",
33+
});
34+
```
35+
36+
### CommonJS
37+
38+
```javascript
39+
// Default import (recommended)
40+
const DevHubSDK = require("@devotel/devhub").default;
41+
42+
// Named import
43+
const { DevHubSDK } = require("@devotel/devhub");
44+
45+
const devhub = new DevHubSDK({
46+
apiKey: "<your-api-key>",
47+
});
948
```
1049

11-
## Quick Start
50+
## 🚀 Quick Start
1251

1352
```javascript
1453
import DevHubSDK from "@devotel/devhub";
@@ -19,35 +58,38 @@ const devhub = new DevHubSDK({
1958

2059
// Send SMS
2160
await devhub.sms.send({
22-
to: "+1234567890",
61+
recipient: "+1234567890",
2362
message: "Hello from DevHub!",
63+
sender: "<sender>",
2464
});
2565

2666
// Send Email
2767
await devhub.email.send({
28-
to: "user@example.com",
68+
recipient: "user@example.com",
2969
subject: "Hello",
30-
html: "<h1>Hello from DevHub!</h1>",
70+
body: "<h1>Hello from DevHub!</h1>",
71+
sender: "sender@example.com",
3172
});
3273

3374
// Send WhatsApp message
3475
await devhub.whatsapp.sendNormalMessage({
76+
account_id: "your-account-id",
3577
to: "+1234567890",
3678
type: "text",
3779
text: { body: "Hello from DevHub!" },
3880
});
3981
```
4082

41-
## API Reference
83+
## 📚 API Reference
4284

4385
### SMS Service
4486

4587
```javascript
4688
// Send SMS
4789
await devhub.sms.send({
48-
to: "+1234567890",
90+
recipient: "+1234567890",
4991
message: "Your message",
50-
from: "optional-sender-id",
92+
sender: "optional-sender-id",
5193
});
5294

5395
// Get available senders
@@ -68,10 +110,10 @@ await devhub.sms.getNumbers();
68110
```javascript
69111
// Send email
70112
await devhub.email.send({
71-
to: "recipient@example.com",
113+
recipient: "recipient@example.com",
72114
subject: "Subject",
73-
html: "<p>HTML content</p>",
74-
text: "Plain text content",
115+
body: "<p>HTML content</p>",
116+
sender: "sender@example.com",
75117
});
76118
```
77119

@@ -92,6 +134,7 @@ await devhub.whatsapp.sendTemplateMessage("account-id", {
92134

93135
// Send normal message
94136
await devhub.whatsapp.sendNormalMessage({
137+
account_id: "your-account-id",
95138
to: "+1234567890",
96139
type: "text",
97140
text: { body: "Hello!" },
@@ -122,8 +165,8 @@ await devhub.contacts.updateContact("contact-id", {
122165

123166
// Create custom field
124167
await devhub.contacts.createCustomField({
125-
name: "Company",
126-
type: "text",
168+
label: "Company",
169+
component: "Input",
127170
required: false,
128171
});
129172
```
@@ -136,8 +179,11 @@ await devhub.rcs.getAccounts();
136179

137180
// Send RCS message
138181
await devhub.rcs.send({
139-
to: "+1234567890",
140-
content: { text: "Hello from RCS!" },
182+
account_id: "your-account-id",
183+
number: "+1234567890",
184+
contentMessage: {
185+
text: "Hello from RCS!",
186+
},
141187
});
142188

143189
// Create RCS template
@@ -172,13 +218,14 @@ await devhub.contactGroups.updateContactGroup("group-id", {
172218
await devhub.messages.send({
173219
channel: "SMS",
174220
sms: {
175-
to: "+1234567890",
221+
sender: "DevHub",
222+
recipient: "+1234567890",
176223
message: "Hello!",
177224
},
178225
});
179226
```
180227

181-
## Error Handling
228+
## ⚠️ Error Handling
182229

183230
All methods return a response object with the following structure:
184231

@@ -194,7 +241,7 @@ Example:
194241

195242
```javascript
196243
const result = await devhub.sms.send({
197-
to: "+1234567890",
244+
recipient: "+1234567890",
198245
message: "Hello!",
199246
});
200247

@@ -205,6 +252,118 @@ if (result.success) {
205252
}
206253
```
207254

208-
## License
255+
## 🔷 TypeScript Support
256+
257+
The SDK is written in TypeScript and provides full type definitions. Available types:
258+
259+
### Core Types
260+
261+
```typescript
262+
import { DevHubConfig, ApiResponse, ChannelType } from "@devotel/devhub";
263+
```
264+
265+
### SMS Types
266+
267+
```typescript
268+
import { SmsMessage, BuyNumberRequest } from "@devotel/devhub";
269+
270+
// Usage
271+
const smsData: SmsMessage = {
272+
recipient: "+1234567890",
273+
message: "Hello!",
274+
sender: "DevHub",
275+
};
276+
```
277+
278+
### Email Types
279+
280+
```typescript
281+
import { EmailMessage } from "@devotel/devhub";
282+
283+
// Usage
284+
const emailData: EmailMessage = {
285+
recipient: "user@example.com",
286+
subject: "Hello",
287+
body: "<h1>Hello!</h1>",
288+
sender: "sender@example.com",
289+
};
290+
```
291+
292+
### WhatsApp Types
293+
294+
```typescript
295+
import { WhatsAppTemplate, WhatsAppNormalMessage } from "@devotel/devhub";
296+
297+
// Template message
298+
const templateData: WhatsAppTemplate = {
299+
to: "+1234567890",
300+
template: {
301+
name: "hello_world",
302+
language: { code: "en" },
303+
},
304+
};
305+
306+
// Normal message
307+
const normalData: WhatsAppNormalMessage = {
308+
account_id: "your-account-id",
309+
to: "+1234567890",
310+
type: "text",
311+
text: { body: "Hello!" },
312+
};
313+
```
314+
315+
### Contact Types
316+
317+
```typescript
318+
import { Contact, CustomField } from "@devotel/devhub";
319+
320+
// Contact
321+
const contactData: Contact = {
322+
firstName: "John",
323+
lastName: "Doe",
324+
email: "john@example.com",
325+
phoneNumber: "+1234567890",
326+
};
327+
328+
// Custom field
329+
const fieldData: CustomField = {
330+
label: "Company",
331+
component: "Input",
332+
required: false,
333+
};
334+
```
335+
336+
### RCS Types
337+
338+
```typescript
339+
import { RcsMessage } from "@devotel/devhub";
340+
341+
// Usage
342+
const rcsData: RcsMessage = {
343+
account_id: "your-account-id",
344+
number: "+1234567890",
345+
contentMessage: {
346+
text: "Hello from RCS!",
347+
},
348+
};
349+
```
350+
351+
### Unified Messages
352+
353+
```typescript
354+
import { UnifiedMessage } from "@devotel/devhub";
355+
356+
// Usage
357+
const unifiedData: UnifiedMessage = {
358+
channel: "SMS",
359+
sms: {
360+
sender: "DevHub",
361+
recipient: "+1234567890",
362+
message: "Hello!",
363+
},
364+
};
365+
```
366+
367+
## 📄 License
209368

210369
MIT

jest.config.cjs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
module.exports = {
2+
preset: 'ts-jest',
3+
testEnvironment: 'node',
4+
roots: ['<rootDir>/src', '<rootDir>/tests'],
5+
testMatch: ['**/__tests__/**/*.ts', '**/?(*.)+(spec|test).ts'],
6+
setupFilesAfterEnv: ['<rootDir>/tests/setup.ts'],
7+
collectCoverageFrom: [
8+
'src/**/*.ts',
9+
'!src/**/*.d.ts',
10+
'!src/index.ts'
11+
],
12+
coverageDirectory: 'coverage',
13+
coverageReporters: ['text', 'lcov', 'html'],
14+
moduleNameMapper: {
15+
'^(\\.{1,2}/.*)\\.js$': '$1'
16+
}
17+
};

package.json

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,12 @@
2525
"build:package": "echo '{\"type\": \"commonjs\"}' > dist/cjs/package.json",
2626
"clean": "rm -rf dist",
2727
"test": "jest",
28+
"test:watch": "jest --watch",
29+
"test:coverage": "jest --coverage",
30+
"test:modules": "npm run test:esm && npm run test:cjs",
31+
"test:esm": "node tests/module-compatibility.test.js",
32+
"test:cjs": "node tests/module-compatibility.cjs",
33+
"validate:build": "node scripts/validate-build.cjs",
2834
"prepublishOnly": "npm run clean && npm run build && npm run validate:build && npm run test:modules"
2935
},
3036
"keywords": [

scripts/validate-build.cjs

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
#!/usr/bin/env node
2+
3+
const fs = require('fs');
4+
const path = require('path');
5+
6+
// Check required files exist
7+
const requiredFiles = [
8+
'dist/esm/index.js',
9+
'dist/esm/index.d.ts',
10+
'dist/cjs/index.js',
11+
'dist/cjs/index.d.ts',
12+
'dist/cjs/package.json'
13+
];
14+
15+
let allFilesExist = true;
16+
17+
requiredFiles.forEach(file => {
18+
if (!fs.existsSync(file)) {
19+
console.error(`❌ Missing: ${file}`);
20+
allFilesExist = false;
21+
} else {
22+
console.log(`✅ Found: ${file}`);
23+
}
24+
});
25+
26+
// Check CJS package.json has correct type
27+
const cjsPackage = JSON.parse(fs.readFileSync('dist/cjs/package.json', 'utf8'));
28+
if (cjsPackage.type !== 'commonjs') {
29+
console.error('❌ CJS package.json missing type: commonjs');
30+
allFilesExist = false;
31+
} else {
32+
console.log('✅ CJS package.json has correct type');
33+
}
34+
35+
if (!allFilesExist) {
36+
process.exit(1);
37+
}
38+
39+
console.log('✅ Build validation passed');

0 commit comments

Comments
 (0)