Skip to content

Commit

Permalink
Remove Message-related static things in tree-shakable library
Browse files Browse the repository at this point in the history
This removes the static BaseClient.Message property and the static
Message.{fromEncoded, fromEncodedArray} methods.

The motivation, and the approach taken for the tree-shakable and non
tree-shakable versions of the library, are as in c859b90.

Note that instead of fromEncoded and fromEncodedArray, the standalone
functions are named decodeMessage and decodeMessages — after some
discussion we decided that this naming was more consistent with the kind
of naming used for standalone functions in JavaScript libraries.
  • Loading branch information
lawrence-forooghian committed Nov 6, 2023
1 parent 5cc2c13 commit 601b46b
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 12 deletions.
2 changes: 1 addition & 1 deletion scripts/moduleReport.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ const esbuild = require('esbuild');
const moduleNames = ['Rest'];

// List of all free-standing functions exported by the library
const functionNames = ['generateRandomKey', 'getDefaultCryptoParams'];
const functionNames = ['generateRandomKey', 'getDefaultCryptoParams', 'decodeMessage', 'decodeMessages'];

function formatBytes(bytes) {
const kibibytes = bytes / 1024;
Expand Down
2 changes: 0 additions & 2 deletions src/common/lib/client/baseclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,6 @@ import ClientOptions, { NormalisedClientOptions } from '../../types/ClientOption
import * as API from '../../../../ably';

import Platform from '../../platform';
import Message from '../types/message';
import PresenceMessage from '../types/presencemessage';
import { ModulesMap } from './modulesmap';
import { Rest } from './rest';
Expand Down Expand Up @@ -147,7 +146,6 @@ class BaseClient {
}

static Platform = Platform;
static Message = Message;
static PresenceMessage = PresenceMessage;
}

Expand Down
3 changes: 3 additions & 0 deletions src/common/lib/client/defaultrealtime.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import * as Utils from '../util/utils';
import ConnectionManager from '../transport/connectionmanager';
import ProtocolMessage from '../types/protocolmessage';
import Platform from 'common/platform';
import { DefaultMessage } from '../types/defaultmessage';

/**
`DefaultRealtime` is the class that the non tree-shakable version of the SDK exports as `Realtime`. It ensures that this version of the SDK includes all of the functionality which is optionally available in the tree-shakable version.
Expand All @@ -29,4 +30,6 @@ export class DefaultRealtime extends BaseRealtime {
static set Crypto(newValue: typeof Platform.Crypto) {
this._Crypto = newValue;
}

static Message = DefaultMessage;
}
3 changes: 3 additions & 0 deletions src/common/lib/client/defaultrest.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { BaseRest } from './baserest';
import ClientOptions from '../../types/ClientOptions';
import { allCommonModules } from './modulesmap';
import Platform from 'common/platform';
import { DefaultMessage } from '../types/defaultmessage';

/**
`DefaultRest` is the class that the non tree-shakable version of the SDK exports as `Rest`. It ensures that this version of the SDK includes all of the functionality which is optionally available in the tree-shakable version.
Expand All @@ -22,4 +23,6 @@ export class DefaultRest extends BaseRest {
static set Crypto(newValue: typeof Platform.Crypto) {
this._Crypto = newValue;
}

static Message = DefaultMessage;
}
16 changes: 16 additions & 0 deletions src/common/lib/types/defaultmessage.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import Message, { fromEncoded, fromEncodedArray } from './message';
import * as API from '../../../../ably';
import Platform from 'common/platform';

/**
`DefaultMessage` is the class returned by `DefaultRest` and `DefaultRealtime`’s `Message` static property. It introduces the static methods described in the `MessageStatic` interface of the public API of the non tree-shakable version of the library.
*/
export class DefaultMessage extends Message {
static async fromEncoded(encoded: unknown, inputOptions?: API.Types.ChannelOptions): Promise<Message> {
return fromEncoded(Platform.Crypto, encoded, inputOptions);
}

static async fromEncodedArray(encodedArray: Array<unknown>, options?: API.Types.ChannelOptions): Promise<Message[]> {
return fromEncodedArray(Platform.Crypto, encodedArray, options);
}
}
8 changes: 0 additions & 8 deletions src/common/lib/types/message.ts
Original file line number Diff line number Diff line change
Expand Up @@ -363,14 +363,6 @@ class Message {
return result;
}

static async fromEncoded(encoded: unknown, inputOptions?: API.Types.ChannelOptions): Promise<Message> {
return fromEncoded(Platform.Crypto, encoded, inputOptions);
}

static async fromEncodedArray(encodedArray: Array<unknown>, options?: API.Types.ChannelOptions): Promise<Message[]> {
return fromEncodedArray(Platform.Crypto, encodedArray, options);
}

/* This should be called on encode()d (and encrypt()d) Messages (as it
* assumes the data is a string or buffer) */
static getMessagesSize(messages: Message[]): number {
Expand Down
1 change: 1 addition & 0 deletions src/platform/web/modules.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,5 +44,6 @@ if (Platform.Config.noUpgrade) {
}

export * from './modules/crypto';
export * from './modules/message';
export { Rest } from '../../common/lib/client/rest';
export { BaseRest, BaseRealtime, ErrorInfo };
13 changes: 13 additions & 0 deletions src/platform/web/modules/message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import * as API from '../../../../ably';
import Platform from 'common/platform';
import { fromEncoded, fromEncodedArray } from '../../../common/lib/types/message';

// The type assertions for the decode* functions below are due to https://github.com/ably/ably-js/issues/1421

export const decodeMessage = ((obj, options) => {
return fromEncoded(Platform.Crypto, obj, options);
}) as API.Types.MessageStatic['fromEncoded'];

export const decodeMessages = ((obj, options) => {
return fromEncodedArray(Platform.Crypto, obj, options);
}) as API.Types.MessageStatic['fromEncodedArray'];
83 changes: 82 additions & 1 deletion test/browser/modules.test.js
Original file line number Diff line number Diff line change
@@ -1,12 +1,33 @@
import { BaseRest, BaseRealtime, Rest, generateRandomKey, getDefaultCryptoParams } from '../../build/modules/index.js';
import {
BaseRest,
BaseRealtime,
Rest,
generateRandomKey,
getDefaultCryptoParams,
decodeMessage,
decodeMessages,
} from '../../build/modules/index.js';

describe('browser/modules', function () {
this.timeout(10 * 1000);
const expect = chai.expect;
const BufferUtils = BaseRest.Platform.BufferUtils;
let ablyClientOptions;
let testResourcesPath;
let loadTestData;
let testMessageEquality;

before((done) => {
ablyClientOptions = window.ablyHelpers.ablyClientOptions;
testResourcesPath = window.ablyHelpers.testResourcesPath;
testMessageEquality = window.ablyHelpers.testMessageEquality;

loadTestData = async (dataPath) => {
return new Promise((resolve, reject) => {
window.ablyHelpers.loadTestData(dataPath, (err, testData) => (err ? reject(err) : resolve(testData)));
});
};

window.ablyHelpers.setupApp(done);
});

Expand Down Expand Up @@ -57,4 +78,64 @@ describe('browser/modules', function () {
expect(params).to.be.an('object');
});
});

describe('Message standalone functions', () => {
describe('decodeMessage', () => {
it('decodes a message’s data', async () => {
const testData = await loadTestData(testResourcesPath + 'crypto-data-128.json');

const item = testData.items[1];
const decoded = await decodeMessage(item.encoded);

expect(decoded.data).to.be.an('ArrayBuffer');
});

it('decrypts a message', async () => {
const testData = await loadTestData(testResourcesPath + 'crypto-data-128.json');

const key = BufferUtils.base64Decode(testData.key);
const iv = BufferUtils.base64Decode(testData.iv);

for (const item of testData.items) {
const [decodedFromEncoded, decodedFromEncrypted] = await Promise.all([
decodeMessage(item.encoded),
decodeMessage(item.encrypted, { cipher: { key, iv } }),
]);

testMessageEquality(decodedFromEncoded, decodedFromEncrypted);
}
});
});

describe('decodeMessages', () => {
it('decodes messages’ data', async () => {
const testData = await loadTestData(testResourcesPath + 'crypto-data-128.json');

const items = [testData.items[1], testData.items[3]];
const decoded = await decodeMessages(items.map((item) => item.encoded));

expect(decoded[0].data).to.be.an('ArrayBuffer');
expect(decoded[1].data).to.be.an('array');
});

it('decrypts messages', async () => {
const testData = await loadTestData(testResourcesPath + 'crypto-data-128.json');

const key = BufferUtils.base64Decode(testData.key);
const iv = BufferUtils.base64Decode(testData.iv);

const [decodedFromEncoded, decodedFromEncrypted] = await Promise.all([
decodeMessages(testData.items.map((item) => item.encoded)),
decodeMessages(
testData.items.map((item) => item.encrypted),
{ cipher: { key, iv } }
),
]);

for (let i = 0; i < decodedFromEncoded.length; i++) {
testMessageEquality(decodedFromEncoded[i], decodedFromEncrypted[i]);
}
});
});
});
});

0 comments on commit 601b46b

Please sign in to comment.