Skip to content

Commit

Permalink
Add documentation for the modular version of the library
Browse files Browse the repository at this point in the history
I imagine there’s plenty of room for improvement here, but it’s a start.

Hopefully a tech writer will be able to have a look at it before we
release, too.

For handling TypeDoc documentation for the two different variants of the
library, I’ve resurrected the approach that we used when we had
callback-based and Promise-based variants of the library (removed in
2a2ed49).

Resolves #1443.
  • Loading branch information
lawrence-forooghian committed Nov 14, 2023
1 parent af86335 commit 3d152b9
Show file tree
Hide file tree
Showing 8 changed files with 291 additions and 8 deletions.
19 changes: 19 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,25 @@ WebPack will search your `node_modules` folder by default, so if you include `ab

If that doesn't work for some reason (e.g. you are using a custom webpack target), you can reference the `ably.js` static file directly: `require('ably/build/ably.js');` (or `import * as Ably from 'ably/build/ably.js'` for typescript / ES6 modules).

#### Modular (tree-shakable) variant

Aimed at those who are concerned about their app’s bundle size, the modular variant of the library allows you to create a client which has only the functionality that you choose. Unused functionality can then be tree-shaken by your module bundler.

To use this variant of the library, import `ably/modules`. It exposes a `BaseRealtime` export, as well as various modules that provide functionality, such as `Rest`, `RealtimePresence`, etc. To create a client, choose which modules you wish to use and pass them to the constructor:

```javascript
import { BaseRealtime, WebSocketTransport, FetchRequest, RealtimePresence } from 'ably/modules';

const options = { key: 'foo' /* Replace with a real key from the Ably dashboard */ };
const client = new BaseRealtime(options, {
WebSocketTransport,
FetchRequest,
RealtimePresence
});
```

For more information, see the [generated documentation](https://sdk.ably.com/builds/ably/ably-js/main/typedoc/modules/index.html) (this link points to the documentation for the `main` branch).

### TypeScript

The TypeScript typings are included in the package and so all you have to do is:
Expand Down
2 changes: 2 additions & 0 deletions ably.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2219,6 +2219,8 @@ declare namespace Types {
*/
subscribe(events: Array<string>, listener?: messageCallback<Message>): Promise<ChannelStateChange | null>;
/**
* {@label WITH_MESSAGE_FILTER}
*
* Registers a listener for messages on this channel that match the supplied filter.
*
* @param filter - A {@link MessageFilter}.
Expand Down
212 changes: 212 additions & 0 deletions modules.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,35 +10,247 @@ export declare const decodePresenceMessage: Types.PresenceMessageStatic['fromEnc
export declare const decodePresenceMessages: Types.PresenceMessageStatic['fromEncodedArray'];
export declare const constructPresenceMessage: Types.PresenceMessageStatic['fromValues'];

/**
* Provides REST-related functionality to a {@link BaseRealtime} client.
*
* To create a client that includes this module, include it in the `ModulesMap` that you pass to the {@link BaseRealtime.constructor}:
*
* ```javascript
* import { BaseRealtime, Rest } from 'ably/modules';
* const realtime = new BaseRealtime(options, { Rest });
* ```
*
* When provided, the following functionality becomes available:
*
* - { @link Types.Push | push admin }
* - { @link BaseRealtime.time | retrieving Ably service time }
* - { @link BaseRealtime.request | making arbitrary REST requests }
* - { @link BaseRealtime.batchPublish | batch publishing of messages }
* - { @link BaseRealtime.batchPresence | batch retrieval of channel presence state }
* - { @link Types.Auth.revokeTokens | requesting the revocation of tokens }
* - { @link Types.RealtimeChannel.history | retrieving the message history of a channel }
* - { @link Types.RealtimePresence.history | retrieving the presence history of a channel }
*
* If this module is not provided, then trying to use the above functionality will cause a runtime error.
*/
export declare const Rest: unknown;

/**
* Provides a {@link BaseRest} or {@link BaseRealtime} instance with the ability to encrypt and decrypt {@link Types.Message} payloads.
*
* To create a client that includes this module, include it in the `ModulesMap` that you pass to the {@link BaseRealtime.constructor}:
*
* ```javascript
* import { BaseRealtime, WebSocketTransport, FetchRequest, Crypto } from 'ably/modules';
* const realtime = new BaseRealtime(options, { WebSocketTransport, FetchRequest, Crypto });
* ```
*
* When provided, you can configure message encryption on a channel via the {@link Types.ChannelOptions.cipher} property of the `ChannelOptions` that you pass when {@link Types.Channels.get | fetching a channel}. If this module is not provided, then passing a `ChannelOptions` with a `cipher` property will cause a runtime error.
*/
export declare const Crypto: unknown;

/**
* Provides a {@link BaseRest} or {@link BaseRealtime} instance with the ability to communicate with the Ably service using the more space-efficient [MessagePack](https://msgpack.org/index.html) format.
*
* To create a client that includes this module, include it in the `ModulesMap` that you pass to the {@link BaseRealtime.constructor}:
*
* ```javascript
* import { BaseRealtime, WebSocketTransport, FetchRequest, MsgPack } from 'ably/modules';
* const realtime = new BaseRealtime(options, { WebSocketTransport, FetchRequest, MsgPack });
* ```
*
* When provided, you can control whether the client uses MessagePack via the {@link Types.ClientOptions.useBinaryProtocol} client option. If you do not provide this module, then the library will always JSON format for encoding messages.
*/
export declare const MsgPack: unknown;

/**
* Provides a {@link BaseRealtime} instance with the ability to interact with a channel’s presence set.
*
* To create a client that includes this module, include it in the `ModulesMap` that you pass to the {@link BaseRealtime.constructor}:
*
* ```javascript
* import { BaseRealtime, WebSocketTransport, FetchRequest, RealtimePresence } from 'ably/modules';
* const realtime = new BaseRealtime(options, { WebSocketTransport, FetchRequest, RealtimePresence });
* ```
*
* If you do not provide this module, then attempting to access a channel’s {@link Types.RealtimeChannel.presence} property will cause a runtime error.
*/
export declare const RealtimePresence: unknown;

/**
* Provides a {@link BaseRealtime} instance with the ability to establish a connection with the Ably realtime service using a [WebSocket](https://developer.mozilla.org/en-US/docs/Web/API/WebSockets_API) connection.
*
* To create a client that includes this module, include it in the `ModulesMap` that you pass to the {@link BaseRealtime.constructor}:
*
* ```javascript
* import { BaseRealtime, WebSocketTransport, FetchRequest } from 'ably/modules';
* const realtime = new BaseRealtime(options, { WebSocketTransport, FetchRequest });
* ```
*
* Note that network conditions, such as firewalls or proxies, might prevent the client from establishing a WebSocket connection. For this reason, you may wish to provide the `BaseRealtime` instance with the ability to alternatively establish a connection using a transport that is less susceptible to these external conditions. You do this by passing an alternative transport module, such as {@link XHRStreaming}, alongside `WebSocketTransport`:
*
* ```javascript
* import { BaseRealtime, WebSocketTransport, FetchRequest } from 'ably/modules';
* const realtime = new BaseRealtime(options, { WebSocketTransport, XHRStreaming, FetchRequest });
* ```
*/
export declare const WebSocketTransport: unknown;

/**
* Provides a {@link BaseRealtime} instance with the ability to establish a connection with the Ably realtime service using the browser’s [XMLHttpRequest API](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest).
*
* ```javascript
* import { BaseRealtime, WebSocketTransport, FetchRequest } from 'ably/modules';
* const realtime = new BaseRealtime(options, { XHRPolling, FetchRequest });
* ```
*
* Provide this module if you wish the client to have an alternative mechanism for connecting to Ably if it’s unable to establish a WebSocket connection.
*/
export declare const XHRPolling: unknown;

// TODO how is it different to XHRPolling? How should the user choose between the two?
/**
* Provides a {@link BaseRealtime} instance with the ability to establish a connection with the Ably realtime service using the browser’s [XMLHttpRequest API](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest).
*
* ```javascript
* import { BaseRealtime, WebSocketTransport, FetchRequest } from 'ably/modules';
* const realtime = new BaseRealtime(options, { XHRPolling, FetchRequest });
* ```
*
* Provide this module if you wish the client to have an alternative mechanism for connecting to Ably if it’s unable to establish a WebSocket connection.
*/
export declare const XHRStreaming: unknown;

// TODO what are the conditions in which somebody would do this? Is Fetch not always available in the browsers we’re targeting?
/**
* Provides a {@link BaseRest} or {@link BaseRealtime} instance with the ability to make HTTP requests using the browser’s [XMLHttpRequest API](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest).
*
* To create a client that includes this module, include it in the `ModulesMap` that you pass to the {@link BaseRealtime.constructor}:
*
* ```javascript
* import { BaseRealtime, WebSocketTransport, XHRRequest } from 'ably/modules';
* const realtime = new BaseRealtime(options, { WebSocketTransport, XHRRequest });
* ```
*/
export declare const XHRRequest: unknown;

/**
* Provides a {@link BaseRest} or {@link BaseRealtime} instance with the ability to make HTTP requests using the browser’s [Fetch API](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API).
*
* To create a client that includes this module, include it in the `ModulesMap` that you pass to the {@link BaseRealtime.constructor}:
*
* ```javascript
* import { BaseRealtime, WebSocketTransport, FetchRequest } from 'ably/modules';
* const realtime = new BaseRealtime(options, { WebSocketTransport, FetchRequest });
* ```
*/
export declare const FetchRequest: unknown;

/**
* Provides a {@link BaseRealtime} instance with the ability to filter channel subscriptions at runtime using { @link Types.RealtimeChannel.subscribe:WITH_MESSAGE_FILTER | the overload of `subscribe()` that accepts a `MessageFilter` }.
*
* To create a client that includes this module, include it in the `ModulesMap` that you pass to the {@link BaseRealtime.constructor}:
*
* ```javascript
* import { BaseRealtime, WebSocketTransport, FetchRequest, MessageInteractions } from 'ably/modules';
* const realtime = new BaseRealtime(options, { WebSocketTransport, FetchRequest, MessageInteractions });
* ```
*
* If you do not provide this module, then attempting to use this overload of `subscribe()` will cause a runtime error.
*/
export declare const MessageInteractions: unknown;

/**
* Pass a `ModulesMap` to { @link BaseRest.constructor | the constructor of BaseRest } or {@link BaseRealtime.constructor | that of BaseRealtime} to specify which functionality should be made available to that client.
*/
export interface ModulesMap {
/**
* See {@link Rest | documentation for the `Rest` module}.
*/
Rest?: typeof Rest;

/**
* See {@link Crypto | documentation for the `Crypto` module}.
*/
Crypto?: typeof Crypto;

/**
* See {@link MsgPack | documentation for the `MsgPack` module}.
*/
MsgPack?: typeof MsgPack;

/**
* See {@link RealtimePresence | documentation for the `RealtimePresence` module}.
*/
RealtimePresence?: typeof RealtimePresence;

/**
* See {@link WebSocketTransport | documentation for the `WebSocketTransport` module}.
*/
WebSocketTransport?: typeof WebSocketTransport;

/**
* See {@link XHRPolling | documentation for the `XHRPolling` module}.
*/
XHRPolling?: typeof XHRPolling;

/**
* See {@link XHRStreaming | documentation for the `XHRStreaming` module}.
*/
XHRStreaming?: typeof XHRStreaming;

/**
* See {@link XHRRequest | documentation for the `XHRRequest` module}.
*/
XHRRequest?: typeof XHRRequest;

/**
* See {@link FetchRequest | documentation for the `FetchRequest` module}.
*/
FetchRequest?: typeof FetchRequest;

/**
* See {@link MessageInteractions | documentation for the `MessageInteractions` module}.
*/
MessageInteractions?: typeof MessageInteractions;
}

/**
* A client that offers a simple stateless API to interact directly with Ably's REST API.
*
* `BaseRest` is the equivalent, in the modular variant of the Ably Client Library SDK, of the [`Rest`](../../default/classes/Rest.html) class in the default variant of the SDK. The difference is that its constructor allows you to decide exactly which functionality the client should include. This allows unused functionality to be tree-shaken, reducing bundle size.
*/
export declare class BaseRest extends Types.Rest {
/**
* Construct a client object using an Ably {@link Types.ClientOptions} object.
*
* @param options - A {@link Types.ClientOptions} object to configure the client connection to Ably.
* @param modules - An object which describes which functionality the client should offer. See the documentation for {@link ModulesMap}.
*
* You must at least provide one HTTP request implementation; that is, one of {@link FetchRequest} or {@link XHRRequest}. For minimum bundle size, favour `FetchRequest`.
*
* The {@link Rest} module is always implicitly included.
*/
constructor(options: Types.ClientOptions, modules: ModulesMap);
}

/**
* A client that extends the functionality of {@link BaseRest} and provides additional realtime-specific features.
*
* `BaseRealtime` is the equivalent, in the modular variant of the Ably Client Library SDK, of the [`Realtime`](../../default/classes/Realtime.html) class in the default variant of the SDK. The difference is that its constructor allows you to decide exactly which functionality the client should include. This allows unused functionality to be tree-shaken, reducing bundle size.
*/
export declare class BaseRealtime extends Types.Realtime {
/**
* Construct a client object using an Ably {@link Types.ClientOptions} object.
*
* @param options - A {@link Types.ClientOptions} object to configure the client connection to Ably.
* @param modules - An object which describes which functionality the client should offer. See the documentation for {@link ModulesMap}.
*
* You must at least provide:
*
* - one HTTP request implementation; that is, one of {@link FetchRequest} or {@link XHRRequest} — for minimum bundle size, favour `FetchRequest`;
* - one realtime transport implementation; that is, one of {@link WebSocketTransport}, {@link XHRStreaming}, or {@link XHRPolling} — for minimum bundle size, favour `WebSocketTransport`.
*/
constructor(options: Types.ClientOptions, modules: ModulesMap);
}

Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,6 @@
"sourcemap": "source-map-explorer build/ably.min.js",
"sourcemap:noencryption": "source-map-explorer build/ably.noencryption.min.js",
"modulereport": "node scripts/moduleReport.js",
"docs": "typedoc --entryPoints ably.d.ts --out typedoc/generated --readme typedoc/landing-page.md"
"docs": "typedoc --entryPoints ably.d.ts --out typedoc/generated/default --readme typedoc/landing-pages/default.md && typedoc --entryPoints modules.d.ts --out typedoc/generated/modules --name \"ably (modular version)\" --readme typedoc/landing-pages/modules.md && cp typedoc/landing-pages/choose-library.html typedoc/generated/index.html"
}
}
7 changes: 0 additions & 7 deletions typedoc/landing-page.md

This file was deleted.

31 changes: 31 additions & 0 deletions typedoc/landing-pages/choose-library.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html lang="en-US">
<head>
<meta charset="utf-8">
<title>Ably JavaScript Client Library SDK API Reference</title>
</head>
<body>
<h1>Ably JavaScript Client Library SDK API Reference</h1>

<p>
The JavaScript Client Library SDK supports a realtime and a REST interface. The JavaScript API references are generated from the <a href="https://github.com/ably/ably-js/">Ably JavaScript Client Library SDK source code</a> using <a href="https://typedoc.org">TypeDoc</a> and structured by classes.
</p>

<p>
The realtime interface enables a client to maintain a persistent connection to Ably and publish, subscribe and be present on channels. The REST interface is stateless and typically implemented server-side. It is used to make requests such as retrieving statistics, token authentication and publishing to a channel.
</p>

<p>
There are two variants of the Ably JavaScript Client Library SDK:

<ul>
<li><a href="default/index.html">Default variant</a>: This variant of the SDK always creates a fully-featured Ably client.</li>
<li><a href="modules/index.html">Modular (tree-shakable) variant</a>: Aimed at those who are concerned about their app’s bundle size, this allows you to create a client which has only the functionality that you choose.</li>
</ul>
</p>

<p>
View the <a href="https://ably.com/docs/">Ably docs</a> for conceptual information on using Ably, and for API references featuring all languages. The combined <a href="https://ably.com/docs/api/">API references</a> are organized by features and split between the <a href="https://ably.com/docs/api/realtime-sdk">realtime</a> and <a href="https://ably.com/docs/api/rest-sdk">REST</a> interfaces.
</p>
</body>
</html>
5 changes: 5 additions & 0 deletions typedoc/landing-pages/default.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Ably JavaScript Client Library SDK API Reference

You are currently viewing the default variant of the Ably JavaScript Client Library SDK. View the modular variant [here](../modules/index.html).

To get started with the Ably JavaScript Client Library SDK, follow the [Quickstart Guide](https://ably.com/docs/quick-start-guide) or view the introductions to the [realtime](https://ably.com/docs/realtime/usage) and [REST](https://ably.com/docs/rest/usage) interfaces.
Loading

0 comments on commit 3d152b9

Please sign in to comment.