Skip to content

V3 docs #319

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 13 commits into from
Mar 31, 2024
48 changes: 48 additions & 0 deletions BREAKING.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,53 @@
# Breaking changes

## 3.0.0

In the last few years, the library has been growing and changing, and
with that, not only new functionalities are added, but also new bugs
are created, which sometimes require breaking changes to be fixed. This
version is one of those cases.

### Removed default exports

Due to interoperability issues between ESM and CJS, all the default
exports were removed to assure a consistent behavior across all
runtimes. The list of affected imports by this change is:

- `whatsapp-api-js`
- `whatsapp-api-js/messages/location`
- `whatsapp-api-js/messages/reaction`
- `whatsapp-api-js/messages/text`
- `whatsapp-api-js/middleware/*` (yeah, all of them, issue [#306](https://github.com/Secreto31126/whatsapp-api-js/issues/306))
- `whatsapp-api-js/setup/bun`
- `whatsapp-api-js/setup/deno`
- `whatsapp-api-js/setup/web`

ESM example:

```js
import { WhatsAppAPI } from "whatsapp-api-js";
```

CJS example:

```js
const { WhatsAppAPI } = require("whatsapp-api-js");
```

### Once again, classes splitted and renamed

In order to improve the typing in Interactive's constructor, the
`ActionProduct` class was splitted into `ActionProduct` and
`ActionProductList`. If you are using the former to send multi product
messages, updating is as simple as renaming the class to the new one.

### Version pinning warning

Although not a breaking change, it's worth mentioning that the library
will now show a warning if the API version is not pinned. This is to
encourage good practices and avoid unexpected changes in the API
at production.

## 2.0.0

### Classes renamed, splitted and moved
Expand Down
25 changes: 12 additions & 13 deletions ENVIRONMENTS.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,13 @@ helpers for the most popular choices.
If using ESM, you can import the module like this:

```js
import WhatsAppAPI from "whatsapp-api-js";
import { WhatsAppAPI } from "whatsapp-api-js";
```

If using CommonJS, you can require the package, although you will need to use
the default export:
If using CommonJS, you can require the package:

```js
const WhatsAppAPI = require("whatsapp-api-js").default;
const { WhatsAppAPI } = require("whatsapp-api-js");
```

For each version of Node, you can use the `setup` function to simplify the
Expand All @@ -25,7 +24,7 @@ process.
- Node 19 and above (using Express and it's middleware):

```js
import WhatsAppAPI from "whatsapp-api-js/middleware/express";
import { WhatsAppAPI } from "whatsapp-api-js/middleware/express";
import { NodeNext } from "whatsapp-api-js/setup/node";

import express from "express";
Expand All @@ -47,7 +46,7 @@ app.post("/message", async (req, res) => {
- Node 18:

```js
import WhatsAppAPI from "whatsapp-api-js";
import { WhatsAppAPI } from "whatsapp-api-js";
import { Node18 } from "whatsapp-api-js/setup/node";

const Whatsapp = new WhatsAppAPI(
Expand All @@ -61,7 +60,7 @@ const Whatsapp = new WhatsAppAPI(
- Node 15 to 17 (deprecated):

```js
import WhatsAppAPI from "whatsapp-api-js";
import { WhatsAppAPI } from "whatsapp-api-js";
import { Node15 } from "whatsapp-api-js/setup/node";

// As fetch isn't available until Node 18, you will need to pass a ponyfill as a parameter
Expand All @@ -84,7 +83,7 @@ With the release of Deno 1.25.0, now you can import npm modules directly to
Deno. It's really simple to use:

```js
import WhatsAppAPI from "npm:whatsapp-api-js";
import { WhatsAppAPI } from "npm:whatsapp-api-js";
```

If you want to use prior versions of Deno, use
Expand All @@ -94,8 +93,8 @@ code.
Deno also counts with setup and middleware helpers:

```js
import WhatsAppAPI from "npm:whatsapp-api-js/middleware/deno";
import Deno from "whatsapp-api-js/setup/deno";
import { WhatsAppAPI } from "npm:whatsapp-api-js/middleware/deno";
import { Deno } from "whatsapp-api-js/setup/deno";

const Whatsapp = new WhatsAppAPI(
Deno({
Expand All @@ -122,8 +121,8 @@ bun install whatsapp-api-js
```

```js
import WhatsAppAPI from "whatsapp-api-js/middleware/bun";
import Bun from "whatsapp-api-js/setup/bun";
import { WhatsAppAPI } from "whatsapp-api-js/middleware/bun";
import { Bun } from "whatsapp-api-js/setup/bun";

const Whatsapp = new WhatsAppAPI(
Bun({
Expand All @@ -147,7 +146,7 @@ HTML module example:

```html
<script type="module">
import WhatsAppAPI from "https://esm.sh/whatsapp-api-js";
import { WhatsAppAPI } from "https://esm.sh/whatsapp-api-js";
<!-- Please, never use your API tokens in a website, use this method wisely -->
</script>
```
Expand Down
7 changes: 4 additions & 3 deletions EXAMPLES/interactive.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,13 +52,13 @@ const interactive_single_product_message = new Interactive(
```ts
import {
Interactive,
ActionProduct,
ActionProductList,
ProductSection,
Product
} from "whatsapp-api-js/messages";

const interactive_multi_product_message = new Interactive(
new ActionProduct(
new ActionProductList(
"catalog_id",
new ProductSection(
"Product section title",
Expand Down Expand Up @@ -148,7 +148,7 @@ import { Interactive, ActionLocation, Body } from "whatsapp-api-js/messages";

const interactive_catalog_message = new Interactive(
new ActionLocation(),
new Body("You should google it")
new Body("Show me where you live")
);
```

Expand All @@ -162,6 +162,7 @@ https://whatsappapijs.web.app/classes/messages.Interactive.html
https://whatsappapijs.web.app/classes/messages.ActionButtons.html
https://whatsappapijs.web.app/classes/messages.ActionList.html
https://whatsappapijs.web.app/classes/messages.ActionProduct.html
https://whatsappapijs.web.app/classes/messages.ActionProductList.html
https://whatsappapijs.web.app/classes/messages.ActionCatalog.html
https://whatsappapijs.web.app/classes/messages.ActionCTA.html
https://whatsappapijs.web.app/classes/messages.ActionNavigateFlow.html
Expand Down
8 changes: 4 additions & 4 deletions EXAMPLES/main.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
## Simple Whatsapp creation

```ts
import WhatsAppAPI from "whatsapp-api-js";
import { WhatsAppAPI } from "whatsapp-api-js";

const Whatsapp = new WhatsAppAPI({
token: "",
Expand All @@ -14,7 +14,7 @@ const Whatsapp = new WhatsAppAPI({
## Using the setup helpers

```ts
import WhatsAppAPI from "whatsapp-api-js";
import { WhatsAppAPI } from "whatsapp-api-js";
import { Node18 } from "whatsapp-api-js/setup/node";

const Whatsapp = new WhatsAppAPI(
Expand All @@ -29,7 +29,7 @@ const Whatsapp = new WhatsAppAPI(

```ts
import express from "express";
import WhatsAppAPI from "whatsapp-api-js/middleware/express";
import { WhatsAppAPI } from "whatsapp-api-js/middleware/express";

const Whatsapp = new WhatsAppAPI({
token: "",
Expand Down Expand Up @@ -60,6 +60,6 @@ Whatsapp.sendMessage(

## Documentation

https://whatsappapijs.web.app/classes/WhatsAppAPI.default.html
https://whatsappapijs.web.app/classes/WhatsAppAPI.WhatsAppAPI.html
https://whatsappapijs.web.app/modules/setup.html
https://whatsappapijs.web.app/modules/middleware.html
8 changes: 4 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# whatsapp-api-js v2
# whatsapp-api-js v3

[![npm](https://img.shields.io/npm/v/whatsapp-api-js?color=4ccc1c)](https://www.npmjs.com/package/whatsapp-api-js)
[![Contributors](https://img.shields.io/github/all-contributors/Secreto31126/whatsapp-api-js)](#contributors)
Expand All @@ -7,7 +7,7 @@ A TypeScript server agnostic Whatsapp's Official API framework.

## List of contents

- [whatsapp-api-js v2](#whatsapp-api-js-v2)
- [whatsapp-api-js v3](#whatsapp-api-js-v3)
- [List of contents](#list-of-contents)
- [Set up](#set-up)
- [Examples and Tutorials](#examples-and-tutorials)
Expand All @@ -34,7 +34,7 @@ npm install whatsapp-api-js
Now you can write code like this:

```js
import WhatsAppAPI from "whatsapp-api-js";
import { WhatsAppAPI } from "whatsapp-api-js";
import { Text, Image, Document } from "whatsapp-api-js/messages";
import * as Contacts from "whatsapp-api-js/messages/contacts";

Expand Down Expand Up @@ -121,7 +121,7 @@ While setting it up, you will be asked for a Verify Token. This can be any strin
The package also has a GET wizard for the webhook authentication:

```js
import WhatsAppAPI from "whatsapp-api-js";
import { WhatsAppAPI } from "whatsapp-api-js";

const TOKEN = "YOUR_TOKEN";
const APP_SECRET = "YOUR_SECRET";
Expand Down
4 changes: 2 additions & 2 deletions SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@

| Version | Supported |
| ------- | ------------------ |
| 2 | :white_check_mark: |
| < 2 | :x: |
| 3 | :white_check_mark: |
| < 3 | :x: |

## Reporting a Vulnerability

Expand Down
76 changes: 61 additions & 15 deletions src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ export class WhatsAppAPI {
*/
private offload_functions: boolean;
/**
* If false, the API will be used in a less secure way, reducing the need for appSecret. Defaults to true.
* If false, the API will be used in a less secure way, removing the need for appSecret. Defaults to true.
*/
private secure: boolean;
/**
Expand All @@ -83,8 +83,8 @@ export class WhatsAppAPI {
* // Set the callback
* Whatsapp.on.message = ({ from, phoneID }) => console.log(`Message from ${from} to bot ${phoneID}`);
*
* // Remove the callback
* Whatsapp.on.message = undefined;
* // If you need to disable the callback:
* // Whatsapp.on.message = undefined;
* ```
*/
public on: {
Expand All @@ -106,6 +106,16 @@ export class WhatsAppAPI {
* such as `ponyfill`, which allows the code to execute on platforms
* that are missing standard APIs such as fetch and crypto.
*
* @example
* ```ts
* import { WhatsAppAPI } from "whatsapp-api-js";
*
* const Whatsapp = new WhatsAppAPI({
* token: "YOUR_TOKEN",
* appSecret: "YOUR_APP_SECRET"
* });
* ```
*
* @throws If fetch is not defined in the enviroment and the provided ponyfill isn't a function
* @throws If secure is true, crypto.subtle is not defined in the enviroment and the provided ponyfill isn't an object
*/
Expand Down Expand Up @@ -295,7 +305,7 @@ export class WhatsAppAPI {
* @param message - A Whatsapp message, built using the corresponding module for each type of message.
* @param batch_size - The number of messages to send per batch
* @param delay - The delay between each batch of messages in milliseconds
* @returns The server response
* @returns The server's responses
* @throws if batch_size is lower than 1
* @throws if delay is lower than 0
*/
Expand Down Expand Up @@ -471,6 +481,8 @@ export class WhatsAppAPI {
/**
* Get a Media object data with an ID
*
* @see {@link fetchMedia}
*
* @param id - The Media's ID
* @param phoneID - Business phone number ID. If included, the operation will only be processed if the ID matches the ID of the business phone number that the media was uploaded on.
* @returns The server response
Expand All @@ -493,15 +505,8 @@ export class WhatsAppAPI {
}

/**
* Upload a Media to the server
* Upload a Media to the API server
*
* @param phoneID - The bot's phone ID
* @param form - The Media's FormData. Must have a 'file' property with the file to upload as a blob and a valid mime-type in the 'type' field of the blob. Example for Node ^18: new FormData().set("file", new Blob([stringOrFileBuffer], "image/png")); Previous versions of Node will need an external FormData, such as undici's. To use non spec complaints versions of FormData (eg: form-data) or Blob set the 'check' parameter to false.
* @param check - If the FormData should be checked before uploading. The FormData must have the method .get("name") to work with the checks. If it doesn't (for example, using the module "form-data"), set this to false.
* @returns The server response
* @throws If check is set to true and form is not a FormData
* @throws If check is set to true and the form doesn't have valid required properties (file, type)
* @throws If check is set to true and the form file is too big for the file type
* @example
* ```ts
* import { WhatsAppAPI } from "whatsapp-api-js";
Expand All @@ -528,6 +533,14 @@ export class WhatsAppAPI {
* console.log(await Whatsapp.uploadMedia("phoneID", form));
* // Expected output: { id: "mediaID" }
* ```
*
* @param phoneID - The bot's phone ID
* @param form - The Media's FormData. Must have a 'file' property with the file to upload as a blob and a valid mime-type in the 'type' field of the blob. Example for Node ^18: new FormData().set("file", new Blob([stringOrFileBuffer], "image/png")); Previous versions of Node will need an external FormData, such as undici's. To use non spec complaints versions of FormData (eg: form-data) or Blob set the 'check' parameter to false.
* @param check - If the FormData should be checked before uploading. The FormData must have the method .get("name") to work with the checks. If it doesn't (for example, using the module "form-data"), set this to false.
* @returns The server response
* @throws If check is set to true and form is not a FormData
* @throws If check is set to true and the form doesn't have valid required properties (file, type)
* @throws If check is set to true and the form file is too big for the file type
*/
async uploadMedia(
phoneID: string,
Expand Down Expand Up @@ -613,9 +626,6 @@ export class WhatsAppAPI {
* Get a Media fetch from an url.
* When using this method, be sure to pass a trusted url, since the request will be authenticated with the token.
*
* @param url - The Media's url
* @returns The fetch raw response
* @throws If url is not a valid url
* @example
* ```ts
* import { WhatsAppAPI } from "whatsapp-api-js";
Expand All @@ -629,6 +639,10 @@ export class WhatsAppAPI {
* const { url } = await Whatsapp.retrieveMedia(id);
* const response = Whatsapp.fetchMedia(url);
* ```
*
* @param url - The Media's url
* @returns The fetch raw response
* @throws If url is not a valid url
*/
fetchMedia(url: string): Promise<Response> {
// Hacky way to check if the url is valid and throw if invalid
Expand Down Expand Up @@ -826,6 +840,38 @@ export class WhatsAppAPI {
* GET helper, must be called inside the get function of your code.
* Used once at the first webhook setup.
*
* @example
* ```ts
* // Simple http example implementation with Whatsapp.get() on Node@^19
* import { WhatsAppAPI } from "whatsapp-api-js";
* import { NodeNext } from "whatsapp-api-js/setup/node";
*
* import { createServer } from "http";
*
* const token = "token";
* const appSecret = "appSecret";
* const Whatsapp = new WhatsAppAPI(NodeNext({ token, appSecret }));
*
* function handler(req, res) {
* if (req.method == "GET") {
* const params = new URLSearchParams(req.url.split("?")[1]);
*
* const response = Whatsapp.get(Object.fromEntries(params));
*
* res.writeHead(200, {"Content-Type": "text/html"});
* res.write(response)
* res.end();
* } else res.writeHead(501).end();
* };
*
* Whatsapp.on.message = ({ phoneID, from, message, name }) => {
* console.log(`User ${name} (${from}) sent to bot ${phoneID} a(n) ${message.type}`);
* };
*
* const server = createServer(handler);
* server.listen(3000);
* ```
*
* @param params - The request object sent by Whatsapp
* @returns The challenge string, it must be the http response body
* @throws 500 if webhookVerifyToken is not specified
Expand Down
Loading