@great-detail/whatsapp
Advanced tools
Comparing version 6.6.3 to 6.7.0
@@ -1,2 +0,1 @@ | ||
export{default,default as CloudAPI}from"./CloudAPI/index.js";export{default as IncomingMessageType}from"./Message/MessageType/IncomingMessageType.js";export{default as OutgoingMessageType}from"./Message/MessageType/OutgoingMessageType.js"; | ||
//# sourceMappingURL=index.js.map | ||
import{a,b,c}from"./chunk-ZDDVDR34.js";export{b as CloudAPI,c as IncomingMessageType,a as OutgoingMessageType,b as default}; |
{ | ||
"name": "@great-detail/whatsapp", | ||
"version": "6.6.3", | ||
"version": "6.7.0", | ||
"type": "module", | ||
@@ -24,4 +24,25 @@ "description": "SDK for interfacing with WhatsApp Business Platform in Typescript or Node.js using the Cloud API, hosted by Meta.", | ||
}, | ||
"exports": "./dist/index.js", | ||
"types": "./dist/index.d.ts", | ||
"bin": "./dist/cli.js", | ||
"exports": { | ||
".": { | ||
"import": { | ||
"types": "./dist/index.d.ts", | ||
"default": "./dist/index.js" | ||
}, | ||
"require": { | ||
"types": "./dist/index.d.cts", | ||
"default": "./dist/index.cjs" | ||
} | ||
}, | ||
"./cli": { | ||
"import": { | ||
"types": "./dist/cli.d.ts", | ||
"default": "./dist/cli.js" | ||
}, | ||
"require": { | ||
"types": "./dist/cli.d.cts", | ||
"default": "./dist/cli.cjs" | ||
} | ||
} | ||
}, | ||
"files": [ | ||
@@ -42,3 +63,3 @@ "dist", | ||
"scripts": { | ||
"build": "npm-run-all swc tsc", | ||
"build": "npm-run-all tsup", | ||
"changeset": "changeset", | ||
@@ -55,6 +76,4 @@ "cspell": "cspell .", | ||
"release": "changeset publish", | ||
"start": "ts-node ./src/index.ts", | ||
"swc": "swc ./src/ -d ./dist/ --ignore ./src/__tests__/", | ||
"test": "npm-run-all jest", | ||
"tsc": "tsc --emitDeclarationOnly", | ||
"tsup": "tsup --entry src/index.ts --entry src/cli.ts --format cjs,esm --minify --dts", | ||
"typecheck": "tsc --noEmit" | ||
@@ -70,10 +89,11 @@ }, | ||
}, | ||
"dependencies": { | ||
"commander": "^11.1.0", | ||
"get-stdin": "^9.0.0", | ||
"ora": "^8.0.1" | ||
}, | ||
"devDependencies": { | ||
"@changesets/cli": "^2.27.1", | ||
"@eslint/eslintrc": "^3.0.0", | ||
"@great-detail/prettier-config": "^0.1.1", | ||
"@great-detail/prettier-config": "latest", | ||
"@jest/globals": "^29.7.0", | ||
"@swc/cli": "^0.1.63", | ||
"@swc/core": "^1.3.101", | ||
"@swc/jest": "^0.2.29", | ||
"@types/jest": "^29.5.5", | ||
@@ -84,3 +104,2 @@ "@types/node": "^20.7.1", | ||
"cspell": "^8.1.0", | ||
"dotenv": "^16.3.1", | ||
"eslint": "^8.50.0", | ||
@@ -92,7 +111,6 @@ "eslint-config-prettier": "^9.0.0", | ||
"jest": "^29.7.0", | ||
"nock": "^13.3.3", | ||
"npm-run-all": "^4.1.5", | ||
"prettier": "^3.0.3", | ||
"ts-jest": "^29.1.1", | ||
"ts-node": "^10.9.1", | ||
"tsup": "^8.0.1", | ||
"typescript": "^5.2.2", | ||
@@ -99,0 +117,0 @@ "winston": "^3.10.0" |
@@ -26,4 +26,8 @@ <!-- Copyright (c) Meta Platforms, Inc. and affiliates. | ||
```typescript | ||
// ESM | ||
import CloudAPI from "@great-detail/whatsapp"; | ||
// CJS | ||
const CloudAPI = require("@great-detail/whatsapp").default; | ||
// const businessID = "123...etc..."; | ||
@@ -42,16 +46,32 @@ const sdk = new CloudAPI({ businessID }); | ||
```bash | ||
# NPM: | ||
npm install @great-detail/whatsapp | ||
# Yarn: | ||
yarn add @great-detail/WhatsApp-Nodejs-SDK | ||
yarn add @great-detail/whatsapp | ||
# NPM: | ||
npm install @great-detail/WhatsApp-Nodejs-SDK | ||
# PNPM: | ||
pnpm add @great-detail/WhatsApp-Nodejs-SDK | ||
pnpm add @great-detail/whatsapp | ||
``` | ||
## Configuration | ||
## CLI Usage | ||
<!-- TODO --> | ||
```bash | ||
export WHATSAPP_ACCESS_TOKEN="" | ||
export WHATSAPP_PHONE_NUMBER_ID="" | ||
# Send a Text Message | ||
npx @great-detail/whatsapp message send text "<RECIPIENT>" --body="Hello, World!" | ||
# Note: <RECIPIENT> may be a Phone Number ID - it may not always be the phone number itself. | ||
# Upload a Media File | ||
npx @great-detail/whatsapp media upload --mime-type="<MIME_TYPE>" < "<FILE_FROM_STDIN>" | ||
# Get a Media File's URL | ||
npx @great-detail/whatsapp media get-url "<MEDIA_ID>" | ||
# Note: With WHATSAPP_PHONE_NUMBER_ID set, the request will check if the media | ||
# is available for that phone number. To prevent this check, unset the env var | ||
# or add --phone-number-id="" to the command. | ||
``` | ||
## Compatibility | ||
@@ -58,0 +78,0 @@ |
@@ -19,3 +19,3 @@ /** | ||
// Act | ||
const graphRequest = new GraphRequest(endpoint); | ||
const graphRequest = GraphRequest.create(endpoint); | ||
@@ -33,3 +33,3 @@ // Assert | ||
// Act | ||
const graphRequest = new GraphRequest(endpoint); | ||
const graphRequest = GraphRequest.create(endpoint); | ||
@@ -48,3 +48,3 @@ // Assert | ||
// Act | ||
const graphRequest = new GraphRequest(endpoint, { version }); | ||
const graphRequest = GraphRequest.create(endpoint, { version }); | ||
@@ -63,3 +63,3 @@ // Assert | ||
// Act | ||
const graphRequest = new GraphRequest(endpoint, { baseUrl }); | ||
const graphRequest = GraphRequest.create(endpoint, { baseUrl }); | ||
@@ -70,3 +70,3 @@ // Assert | ||
test("When setting a header via the constructor, the header should be accessible as a parameter as expected", () => { | ||
test("When setting a header, the header should be accessible as a parameter as expected", () => { | ||
// Arrange | ||
@@ -78,3 +78,3 @@ const endpoint = "/path/to/something"; | ||
// Act | ||
const graphRequest = new GraphRequest(endpoint, { | ||
const graphRequest = GraphRequest.create(endpoint, { | ||
headers: { [headerName]: headerValue }, | ||
@@ -92,3 +92,3 @@ }); | ||
const endpoint = "/path/to/something"; | ||
const graphRequest = new GraphRequest(endpoint); | ||
const graphRequest = GraphRequest.create(endpoint); | ||
const mockFetch = jest.fn<typeof fetch>(); | ||
@@ -114,3 +114,3 @@ const body = "exampleBody"; | ||
const endpoint = "/path/to/something"; | ||
const graphRequest = new GraphRequest(endpoint, { | ||
const graphRequest = GraphRequest.create(endpoint, { | ||
headers: { | ||
@@ -117,0 +117,0 @@ "x-will-merge": "willMerge", |
@@ -9,35 +9,6 @@ /** | ||
*/ | ||
import { AccountID } from "../ID.js"; | ||
import APIInterface from "./APIInterface.js"; | ||
import { randomBytes } from "node:crypto"; | ||
import type { Logger } from "winston"; | ||
export interface WhatsAppAPICreateVerifyTokenParameters { | ||
/** | ||
* The length of the verify token. | ||
* | ||
* @since 5.1.0 | ||
* @default 16 | ||
*/ | ||
length?: number; | ||
/** | ||
* The encoding of the verify token. | ||
* | ||
* @since 5.1.0 | ||
* @default hex | ||
*/ | ||
encoding?: BufferEncoding; | ||
/** | ||
* Random Bytes Generation. | ||
* | ||
* @since 5.1.0 | ||
* @default crypto.randomBytes | ||
*/ | ||
random?: (length: number) => Buffer; | ||
} | ||
export interface AbstractAPIParameters { | ||
businessID?: AccountID; | ||
logger?: Logger; | ||
@@ -55,44 +26,7 @@ } | ||
export default abstract class AbstractAPI implements APIInterface { | ||
/** | ||
* Default Verify Token Length. | ||
* | ||
* @since 5.6.0 | ||
*/ | ||
public static DEFAULT_VERIFY_TOKEN_LENGTH = 16; | ||
/** | ||
* Default Verify Token Encoding. | ||
* | ||
* @since 5.6.0 | ||
*/ | ||
public static DEFAULT_VERIFY_TOKEN_ENCODING: BufferEncoding = "hex"; | ||
/** | ||
* Business ID. | ||
* | ||
* @since 2.0.0 | ||
*/ | ||
protected _businessID?: AccountID; | ||
protected _logger?: Logger; | ||
constructor({ logger, businessID }: AbstractAPIParameters) { | ||
constructor({ logger }: AbstractAPIParameters) { | ||
this._logger = logger; | ||
this._businessID = businessID; | ||
} | ||
/** | ||
* Create a new Verify Token. | ||
* This is a random string that is used to verify that the request is coming | ||
* from WhatsApp. This method **only** creates the value, it's usage is up to | ||
* the implementer. | ||
* | ||
* @since 5.6.0 | ||
*/ | ||
public static createVerifyToken({ | ||
length = this.DEFAULT_VERIFY_TOKEN_LENGTH, | ||
encoding = this.DEFAULT_VERIFY_TOKEN_ENCODING, | ||
random = randomBytes, | ||
}: WhatsAppAPICreateVerifyTokenParameters = {}): string { | ||
return random(length).toString(encoding); | ||
} | ||
} |
@@ -29,2 +29,6 @@ /** | ||
export interface CloudAPIMessageParameters extends AbstractAPIParameters { | ||
businessID: string; | ||
} | ||
type CreateMessagePayload = | ||
@@ -38,2 +42,6 @@ | CloudOutgoingMessageMedia | ||
export interface CreateStatusOptionsType { | ||
requestOptions?: GraphRequestCreateParameters; | ||
} | ||
type CreateMessageOptionsType = { | ||
@@ -45,15 +53,13 @@ toNumber: string; | ||
export interface CloudAPIMessageParameters extends AbstractAPIParameters { | ||
businessID: string; | ||
} | ||
/** | ||
* WhatsApp Message API. | ||
* | ||
* @since 2.0.0 | ||
* @author Dom Webber <dom.webber@hotmail.com> | ||
*/ | ||
export default class CloudAPIMessage extends AbstractAPI { | ||
constructor(parameters: CloudAPIMessageParameters) { | ||
protected _businessID: string; | ||
constructor({ businessID, ...parameters }: CloudAPIMessageParameters) { | ||
super(parameters); | ||
this._businessID = businessID; | ||
} | ||
@@ -68,3 +74,2 @@ | ||
* | ||
* @since 2.0.0 | ||
* @author Dom Webber <dom.webber@hotmail.com> | ||
@@ -74,3 +79,3 @@ */ | ||
payload: CloudOutgoingMessageStatus, | ||
requestOptions: GraphRequestCreateParameters = {}, | ||
{ requestOptions = {} }: CreateStatusOptionsType = {}, | ||
) { | ||
@@ -82,3 +87,3 @@ const body: CloudOutgoingStatusMessage = { | ||
return new GraphRequest<CloudOutgoingMessageStatusResponse>( | ||
return GraphRequest.create<CloudOutgoingMessageStatusResponse>( | ||
this.getEndpoint(), | ||
@@ -101,3 +106,2 @@ { | ||
* | ||
* @since 2.0.0 | ||
* @author Dom Webber <dom.webber@hotmail.com> | ||
@@ -120,12 +124,15 @@ */ | ||
return new GraphRequest<CloudOutgoingMessageResponse>(this.getEndpoint(), { | ||
logger: this._logger, | ||
...requestOptions, | ||
method: "POST", | ||
body: JSON.stringify(body), | ||
headers: { | ||
...requestOptions.headers, | ||
"Content-Type": "application/json", | ||
return GraphRequest.create<CloudOutgoingMessageResponse>( | ||
this.getEndpoint(), | ||
{ | ||
logger: this._logger, | ||
...requestOptions, | ||
method: "POST", | ||
body: JSON.stringify(body), | ||
headers: { | ||
...requestOptions.headers, | ||
"Content-Type": "application/json", | ||
}, | ||
}, | ||
}); | ||
); | ||
} | ||
@@ -137,11 +144,10 @@ | ||
>(type: T) { | ||
const shorthandAliasFunction = function ( | ||
this: CloudAPIMessage, | ||
const shorthandAliasFunction = ( | ||
payload: P, | ||
options: CreateMessageOptionsType, | ||
) { | ||
) => { | ||
return this.createMessage(type, payload, options); | ||
}; | ||
return shorthandAliasFunction.bind(this); | ||
return shorthandAliasFunction; | ||
} | ||
@@ -148,0 +154,0 @@ |
@@ -10,13 +10,37 @@ /** | ||
import AbstractAPI, { AbstractAPIParameters } from "../API/AbstractAPI.js"; | ||
import CloudAPIInvalidParameterError from "./CloudAPIInvalidParameterError.js"; | ||
import CloudAPIMedia from "./CloudAPIMedia/index.js"; | ||
import CloudAPIMessage, { | ||
CloudAPIMessageParameters as BaseCloudAPIMessageParameters, | ||
CloudAPIMessageParameters, | ||
} from "./CloudAPIMessage/index.js"; | ||
import CloudAPIWebhook from "./CloudAPIWebhook/index.js"; | ||
import { randomBytes } from "node:crypto"; | ||
export interface WhatsAppAPIParameters extends AbstractAPIParameters {} | ||
export interface CloudAPIMessageParameters | ||
extends Partial<BaseCloudAPIMessageParameters> {} | ||
export interface WhatsAppAPICreateVerifyTokenParameters { | ||
/** | ||
* The length of the verify token. | ||
* | ||
* @since 5.1.0 | ||
* @default 16 | ||
*/ | ||
length?: number; | ||
/** | ||
* The encoding of the verify token. | ||
* | ||
* @since 5.1.0 | ||
* @default hex | ||
*/ | ||
encoding?: BufferEncoding; | ||
/** | ||
* Random Bytes Generation. | ||
* | ||
* @since 5.1.0 | ||
* @default crypto.randomBytes | ||
*/ | ||
random?: (length: number) => Buffer; | ||
} | ||
/** | ||
@@ -33,2 +57,16 @@ * WhatsApp Cloud API SDK. | ||
/** | ||
* Default Verify Token Length. | ||
* | ||
* @since 5.6.0 | ||
*/ | ||
public static DEFAULT_VERIFY_TOKEN_LENGTH = 16; | ||
/** | ||
* Default Verify Token Encoding. | ||
* | ||
* @since 5.6.0 | ||
*/ | ||
public static DEFAULT_VERIFY_TOKEN_ENCODING: BufferEncoding = "hex"; | ||
/** | ||
* Webhook API. | ||
@@ -41,5 +79,18 @@ * Receive and handle messages from WhatsApp via WebHook. | ||
constructor(parameters: WhatsAppAPIParameters) { | ||
/** | ||
* Media API. | ||
* | ||
* @example | ||
* // Upload Media | ||
* const upload = sdk.media({ businessID: "123456" }) | ||
* .upload(file); | ||
* const uploadReceipt = await upload.send(); | ||
* console.log(uploadReceipt); | ||
*/ | ||
public media; | ||
constructor(parameters: WhatsAppAPIParameters = {}) { | ||
super(parameters); | ||
this.webhook = new CloudAPIWebhook(parameters); | ||
this.media = new CloudAPIMedia(parameters); | ||
} | ||
@@ -50,3 +101,2 @@ | ||
* | ||
* @since 6.0.0 | ||
* @example | ||
@@ -59,18 +109,21 @@ * // Send a Text Message | ||
*/ | ||
public message({ | ||
businessID: overrideBusinessID, | ||
logger, | ||
...parameters | ||
}: CloudAPIMessageParameters = {}) { | ||
const businessID = overrideBusinessID ?? this._businessID; | ||
if (!businessID) { | ||
throw new CloudAPIInvalidParameterError("Business ID is required"); | ||
} | ||
public message(parameters: CloudAPIMessageParameters) { | ||
return new CloudAPIMessage({ ...parameters }); | ||
} | ||
return new CloudAPIMessage({ | ||
logger: logger ?? this._logger, | ||
businessID, | ||
...parameters, | ||
}); | ||
/** | ||
* Create a new Verify Token. | ||
* This is a random string that is used to verify that the request is coming | ||
* from WhatsApp. This method **only** creates the value, it's usage is up to | ||
* the implementer. | ||
* | ||
* @since 5.6.0 | ||
*/ | ||
public static createVerifyToken({ | ||
length = this.DEFAULT_VERIFY_TOKEN_LENGTH, | ||
encoding = this.DEFAULT_VERIFY_TOKEN_ENCODING, | ||
random = randomBytes, | ||
}: WhatsAppAPICreateVerifyTokenParameters = {}): string { | ||
return random(length).toString(encoding); | ||
} | ||
} |
@@ -15,7 +15,8 @@ /** | ||
version?: string; | ||
baseUrl?: string; | ||
logger?: Logger; | ||
} | ||
export interface GraphRequestCreateParameters extends GraphRequestParameters {} | ||
export interface GraphRequestCreateParameters extends GraphRequestParameters { | ||
baseUrl?: string; | ||
} | ||
@@ -70,38 +71,29 @@ export interface GraphRequestSendParameters { | ||
*/ | ||
public readonly version: string; | ||
public readonly version?: string; | ||
/** | ||
* Graph API endpoint. | ||
* | ||
* @since 6.5.0 | ||
*/ | ||
public readonly endpoint: string; | ||
public constructor( | ||
url: string | URL, | ||
{ logger, version, ...requestInit }: GraphRequestParameters = {}, | ||
) { | ||
super(url, requestInit); | ||
this.version = version; | ||
logger?.http(`${url.toString()} ${JSON.stringify(requestInit)}`); | ||
} | ||
/** | ||
* Graph API base URL. | ||
* | ||
* @since 6.5.0 | ||
* Create Graph Request. | ||
*/ | ||
public readonly baseUrl: string; | ||
public constructor( | ||
public static create<T = unknown>( | ||
endpoint: EndpointType, | ||
{ | ||
logger, | ||
version = GraphRequest.DEFAULT_GRAPH_VERSION, | ||
baseUrl = GraphRequest.DEFAULT_GRAPH_API_BASE_URL, | ||
...requestInit | ||
}: GraphRequestParameters = {}, | ||
...options | ||
}: GraphRequestCreateParameters = {}, | ||
) { | ||
const url = new URL( | ||
[version ? "/" : "", version, endpoint].join(""), | ||
baseUrl, | ||
); | ||
const path = [version ? "/" : "", version, endpoint].join(""); | ||
const url = new URL(path, baseUrl); | ||
super(url, requestInit); | ||
this.version = version; | ||
this.endpoint = endpoint; | ||
this.baseUrl = baseUrl; | ||
logger?.http(`${url.toString()} ${JSON.stringify(requestInit)}`); | ||
return new GraphRequest<T>(url, { version, ...options }); | ||
} | ||
@@ -113,3 +105,2 @@ | ||
* @since 2.0.0 | ||
* @author Dom Webber <dom.webber@hotmail.com> | ||
*/ | ||
@@ -116,0 +107,0 @@ public async send({ |
@@ -39,1 +39,8 @@ /** | ||
export type MessageID = string; | ||
/** | ||
* WhatsApp Media ID. | ||
* | ||
* @since 6.7.0 | ||
*/ | ||
export type MediaID = string; |
Sorry, the diff of this file is too big to display
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Environment variable access
Supply chain riskPackage accesses environment variables, which may be a sign of credential stuffing or data theft.
Found 2 instances in 1 package
Minified code
QualityThis package contains minified code. This may be harmless in some cases where minified code is included in packaged libraries, however packages on npm should not minify code.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
20
104
297680
4
118
6661
2
4
3
+ Addedcommander@^11.1.0
+ Addedget-stdin@^9.0.0
+ Addedora@^8.0.1
+ Addedansi-regex@6.1.0(transitive)
+ Addedchalk@5.4.1(transitive)
+ Addedcli-cursor@5.0.0(transitive)
+ Addedcli-spinners@2.9.2(transitive)
+ Addedcommander@11.1.0(transitive)
+ Addedemoji-regex@10.4.0(transitive)
+ Addedget-east-asian-width@1.3.0(transitive)
+ Addedget-stdin@9.0.0(transitive)
+ Addedis-interactive@2.0.0(transitive)
+ Addedis-unicode-supported@1.3.02.1.0(transitive)
+ Addedlog-symbols@6.0.0(transitive)
+ Addedmimic-function@5.0.1(transitive)
+ Addedonetime@7.0.0(transitive)
+ Addedora@8.1.1(transitive)
+ Addedrestore-cursor@5.1.0(transitive)
+ Addedsignal-exit@4.1.0(transitive)
+ Addedstdin-discarder@0.2.2(transitive)
+ Addedstring-width@7.2.0(transitive)
+ Addedstrip-ansi@7.1.0(transitive)