Skip to content
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

Remove callbacks part 1 #1541

Merged
merged 44 commits into from
Jan 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
44 commits
Select commit Hold shift + click to select a range
709f66a
Update recently-changed tests to use Promise-based API
lawrence-forooghian Dec 11, 2023
b647581
Update some missed tests to use Promise-based API
lawrence-forooghian Dec 11, 2023
16f3d38
Mark Rest.revokeTokens as async
lawrence-forooghian Jan 8, 2024
14ae7c9
Make Multicaster.call private
lawrence-forooghian Jan 15, 2024
1be691f
Be more explicit about a type
lawrence-forooghian Jan 15, 2024
d012125
Restrict Multicaster callback type
lawrence-forooghian Dec 11, 2023
dfaa6ba
Add a method for bridging Multicaster with promises
lawrence-forooghian Dec 7, 2023
cd6c2d8
Add whenPromiseSettles function
lawrence-forooghian Dec 11, 2023
4aa7494
Fix type of ChannelSubscriptions.removeWhere callback
lawrence-forooghian Dec 7, 2023
3e06ea9
Fix type of ChannelSubscriptions.save callback
lawrence-forooghian Dec 7, 2023
0eb0018
Fix return type of Connection.ping
lawrence-forooghian Dec 7, 2023
35970d6
Fix return type of RealtimePresence.get
lawrence-forooghian Dec 7, 2023
2c56030
Fix return type of Auth.authorize
lawrence-forooghian Dec 7, 2023
501dd74
Fix return type of Auth.requestToken
lawrence-forooghian Dec 7, 2023
66e025b
Fix return type of RealtimeChannel.subscribe
lawrence-forooghian Dec 7, 2023
602ceaf
Fix return type of RealtimeChannel.history
lawrence-forooghian Dec 8, 2023
336695a
Remove useless return
lawrence-forooghian Dec 7, 2023
5e95872
Add Promise overload signatures to some methods
lawrence-forooghian Dec 8, 2023
df28f8d
Use the promise-based version of callback/promise methods
lawrence-forooghian Dec 8, 2023
7c465d6
Remove dual callback/promise operation
lawrence-forooghian Dec 7, 2023
1ef2b2b
Convert Auth._forceNewToken to use promises
lawrence-forooghian Dec 8, 2023
ffea183
Convert Auth.getAuthParams to use promises
lawrence-forooghian Dec 8, 2023
c2f02a0
Convert Auth.getAuthHeaders to use promises
lawrence-forooghian Dec 8, 2023
9dd1515
Convert Auth.getTimestamp to use promises
lawrence-forooghian Dec 8, 2023
73b30af
Convert Auth._ensureValidAuthCredentials to use promises
lawrence-forooghian Dec 8, 2023
5b33381
Convert PaginatedResource.handlePage to use promises
lawrence-forooghian Dec 8, 2023
0d2d90c
Convert PaginatedResult.get to use promises
lawrence-forooghian Dec 8, 2023
96655af
Convert PaginatedResource request methods to use promises
lawrence-forooghian Dec 8, 2023
cd0a6c4
Convert RestChannelMixin.history to use promises
lawrence-forooghian Dec 8, 2023
9093f0d
Change RestChannel._publish to only pass error to callback
lawrence-forooghian Dec 11, 2023
564e4aa
Convert RestChannel._publish to use promises
lawrence-forooghian Dec 11, 2023
2001675
Convert Resource request methods to use promises
lawrence-forooghian Jan 5, 2024
4951ec1
Convert Resource.do to use promises
lawrence-forooghian Jan 5, 2024
da6d206
Convert message `encrypt` to use promises
lawrence-forooghian Jan 5, 2024
019c315
Convert message `encode` to use promises
lawrence-forooghian Jan 5, 2024
69b64dc
Convert message `encodeArray` to use promises
lawrence-forooghian Jan 5, 2024
499ca19
Remove leftover documentation comment
lawrence-forooghian Jan 5, 2024
1e15e53
Convert web crypto `generateRandom` to use promises
lawrence-forooghian Jan 5, 2024
ec45a10
Make ICipher.encrypt signature consistent with our other callbacks
lawrence-forooghian Jan 5, 2024
d87123d
Convert Node crypto `generateRandom` to use promises
lawrence-forooghian Jan 5, 2024
32d02a6
Convert web crypto `getIv` to use promises
lawrence-forooghian Jan 5, 2024
2f19925
Convert ICipher.encrypt to use promises
lawrence-forooghian Jan 5, 2024
509b5c4
Convert IPlatformConfig.getRandomValues to use promises
lawrence-forooghian Jan 5, 2024
b429c13
Convert IPlatformConfig.getRandomArrayBuffer to use promises
lawrence-forooghian Jan 5, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
548 changes: 238 additions & 310 deletions src/common/lib/client/auth.ts

Large diffs are not rendered by default.

21 changes: 8 additions & 13 deletions src/common/lib/client/baseclient.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import Auth from './auth';
import { HttpPaginatedResponse, PaginatedResult } from './paginatedresource';
import ErrorInfo from '../types/errorinfo';
import Stats from '../types/stats';
import { StandardCallback } from '../../types/utils';
import { Http, RequestParams } from '../../types/http';
import ClientOptions, { NormalisedClientOptions } from '../../types/ClientOptions';
import * as API from '../../../../ably';
Expand Down Expand Up @@ -129,27 +128,23 @@ class BaseClient {
return Defaults.getHttpScheme(this.options) + host + ':' + Defaults.getPort(this.options, false);
}

stats(
params: RequestParams,
callback: StandardCallback<PaginatedResult<Stats>>
): Promise<PaginatedResult<Stats>> | void {
return this.rest.stats(params, callback);
async stats(params: RequestParams): Promise<PaginatedResult<Stats>> {
return this.rest.stats(params);
}

time(params?: RequestParams | StandardCallback<number>, callback?: StandardCallback<number>): Promise<number> | void {
return this.rest.time(params, callback);
async time(params?: RequestParams): Promise<number> {
return this.rest.time(params);
}

request(
async request(
method: string,
path: string,
version: number,
params: RequestParams,
body: unknown,
customHeaders: Record<string, string>,
callback: StandardCallback<HttpPaginatedResponse<unknown>>
): Promise<HttpPaginatedResponse<unknown>> | void {
return this.rest.request(method, path, version, params, body, customHeaders, callback);
customHeaders: Record<string, string>
): Promise<HttpPaginatedResponse<unknown>> {
return this.rest.request(method, path, version, params, body, customHeaders);
}

batchPublish<T extends BatchPublishSpec | BatchPublishSpec[]>(
Expand Down
10 changes: 4 additions & 6 deletions src/common/lib/client/connection.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import * as Utils from '../util/utils';
import EventEmitter from '../util/eventemitter';
import ConnectionManager from '../transport/connectionmanager';
import Logger from '../util/logger';
Expand Down Expand Up @@ -53,12 +52,11 @@ class Connection extends EventEmitter {
this.connectionManager.requestState({ state: 'connecting' });
}

ping(callback: Function): Promise<void> | void {
async ping(): Promise<number> {
Logger.logAction(Logger.LOG_MINOR, 'Connection.ping()', '');
if (!callback) {
return Utils.promisify(this, 'ping', arguments);
}
this.connectionManager.ping(null, callback);
return new Promise((resolve, reject) => {
this.connectionManager.ping(null, (err: unknown, result: number) => (err ? reject(err) : resolve(result)));
});
}

close(): void {
Expand Down
188 changes: 57 additions & 131 deletions src/common/lib/client/paginatedresource.ts
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import * as Utils from '../util/utils';
import Logger from '../util/logger';
import Resource from './resource';
import Resource, { ResourceResult } from './resource';
import { IPartialErrorInfo } from '../types/errorinfo';
import { PaginatedResultCallback } from '../../types/utils';
import BaseClient from './baseclient';
import { RequestBody, RequestCallbackHeaders } from 'common/types/http';

Expand All @@ -29,7 +28,7 @@ function parseRelLinks(linkHeader: string | Array<string>) {

function returnErrOnly(err: IPartialErrorInfo, body: unknown, useHPR?: boolean) {
/* If using httpPaginatedResponse, errors from Ably are returned as part of
* the HPR, only do callback(err) for network errors etc. which don't
* the HPR, only throw `err` for network errors etc. which don't
* return a body and/or have no ably-originated error code (non-numeric
* error codes originate from node) */
return !(useHPR && (body || typeof err.code === 'number'));
Expand Down Expand Up @@ -59,132 +58,76 @@ class PaginatedResource {
this.useHttpPaginatedResponse = useHttpPaginatedResponse || false;
}

get<T1, T2>(params: Record<string, T2>, callback: PaginatedResultCallback<T1>): void {
Resource.get(
this.client,
this.path,
this.headers,
params,
this.envelope,
(err, body, headers, unpacked, statusCode) => {
this.handlePage(err, body, headers, unpacked, statusCode, callback);
}
);
async get<T1, T2>(params: Record<string, T2>): Promise<PaginatedResult<T1>> {
const result = await Resource.get<T1>(this.client, this.path, this.headers, params, this.envelope, false);
return this.handlePage(result);
}

delete<T1, T2>(params: Record<string, T2>, callback: PaginatedResultCallback<T1>): void {
Resource.delete(
this.client,
this.path,
this.headers,
params,
this.envelope,
(err, body, headers, unpacked, statusCode) => {
this.handlePage(err, body, headers, unpacked, statusCode, callback);
}
);
async delete<T1, T2>(params: Record<string, T2>): Promise<PaginatedResult<T1>> {
const result = await Resource.delete<T1>(this.client, this.path, this.headers, params, this.envelope, false);
return this.handlePage(result);
}

post<T1, T2>(params: Record<string, T2>, body: RequestBody | null, callback: PaginatedResultCallback<T1>): void {
Resource.post(
this.client,
this.path,
body,
this.headers,
params,
this.envelope,
(err, responseBody, headers, unpacked, statusCode) => {
if (callback) {
this.handlePage(err, responseBody, headers, unpacked, statusCode, callback);
}
}
);
async post<T1, T2>(params: Record<string, T2>, body: RequestBody | null): Promise<PaginatedResult<T1>> {
const result = await Resource.post<T1>(this.client, this.path, body, this.headers, params, this.envelope, false);
return this.handlePage(result);
}

put<T1, T2>(params: Record<string, T2>, body: RequestBody | null, callback: PaginatedResultCallback<T1>): void {
Resource.put(
this.client,
this.path,
body,
this.headers,
params,
this.envelope,
(err, responseBody, headers, unpacked, statusCode) => {
if (callback) {
this.handlePage(err, responseBody, headers, unpacked, statusCode, callback);
}
}
);
async put<T1, T2>(params: Record<string, T2>, body: RequestBody | null): Promise<PaginatedResult<T1>> {
const result = await Resource.put<T1>(this.client, this.path, body, this.headers, params, this.envelope, false);
return this.handlePage(result);
}

patch<T1, T2>(params: Record<string, T2>, body: RequestBody | null, callback: PaginatedResultCallback<T1>): void {
Resource.patch(
this.client,
this.path,
body,
this.headers,
params,
this.envelope,
(err, responseBody, headers, unpacked, statusCode) => {
if (callback) {
this.handlePage(err, responseBody, headers, unpacked, statusCode, callback);
}
}
);
async patch<T1, T2>(params: Record<string, T2>, body: RequestBody | null): Promise<PaginatedResult<T1>> {
const result = await Resource.patch<T1>(this.client, this.path, body, this.headers, params, this.envelope, false);
return this.handlePage(result);
}

handlePage<T>(
err: IPartialErrorInfo | null,
body: unknown,
headers: RequestCallbackHeaders | undefined,
unpacked: boolean | undefined,
statusCode: number | undefined,
callback: PaginatedResultCallback<T>
): void {
if (err && returnErrOnly(err, body, this.useHttpPaginatedResponse)) {
async handlePage<T>(result: ResourceResult<T>): Promise<PaginatedResult<T>> {
if (result.err && returnErrOnly(result.err, result.body, this.useHttpPaginatedResponse)) {
Logger.logAction(
Logger.LOG_ERROR,
'PaginatedResource.handlePage()',
'Unexpected error getting resource: err = ' + Utils.inspectError(err)
'Unexpected error getting resource: err = ' + Utils.inspectError(result.err)
);
callback?.(err);
return;
throw result.err;
}

const handleBody = async () => {
let items, linkHeader, relParams;

try {
items = await this.bodyHandler(body, headers || {}, unpacked);
} catch (e) {
/* If we got an error, the failure to parse the body is almost certainly
* due to that, so throw that in preference over the parse error */
throw err || e;
}
let items, linkHeader, relParams;

if (headers && (linkHeader = headers['Link'] || headers['link'])) {
relParams = parseRelLinks(linkHeader);
}
try {
items = await this.bodyHandler(result.body, result.headers || {}, result.unpacked);
} catch (e) {
/* If we got an error, the failure to parse the body is almost certainly
* due to that, so throw that in preference over the parse error */
throw result.err || e;
}

if (this.useHttpPaginatedResponse) {
return new HttpPaginatedResponse(this, items, headers || {}, statusCode as number, relParams, err);
} else {
return new PaginatedResult(this, items, relParams);
}
};
if (result.headers && (linkHeader = result.headers['Link'] || result.headers['link'])) {
relParams = parseRelLinks(linkHeader);
}

handleBody()
.then((result) => callback(null, result))
.catch((err) => callback(err, null));
if (this.useHttpPaginatedResponse) {
return new HttpPaginatedResponse(
this,
items,
result.headers || {},
result.statusCode as number,
relParams,
result.err
);
} else {
return new PaginatedResult(this, items, relParams);
}
}
}

export class PaginatedResult<T> {
resource: PaginatedResource;
items: T[];
first?: (results: PaginatedResultCallback<T>) => void;
next?: (results: PaginatedResultCallback<T>) => void;
current?: (results: PaginatedResultCallback<T>) => void;
first?: () => Promise<PaginatedResult<T>>;
next?: () => Promise<PaginatedResult<T> | null>;
current?: () => Promise<PaginatedResult<T>>;
hasNext?: () => boolean;
isLast?: () => boolean;

Expand All @@ -195,29 +138,20 @@ export class PaginatedResult<T> {
const self = this;
if (relParams) {
if ('first' in relParams) {
this.first = function (callback) {
if (!callback) {
return Utils.promisify(self, 'first', []);
}
self.get(relParams.first, callback);
this.first = async function () {
return self.get(relParams.first);
};
}
if ('current' in relParams) {
this.current = function (callback) {
if (!callback) {
return Utils.promisify(self, 'current', []);
}
self.get(relParams.current, callback);
this.current = async function () {
return self.get(relParams.current);
};
}
this.next = function (callback) {
if (!callback) {
return Utils.promisify(self, 'next', []);
}
this.next = async function () {
if ('next' in relParams) {
self.get(relParams.next, callback);
return self.get(relParams.next);
} else {
callback(null, null);
return null;
}
};

Expand All @@ -232,18 +166,10 @@ export class PaginatedResult<T> {

/* We assume that only the initial request can be a POST, and that accessing
* the rest of a multipage set of results can always be done with GET */
get(params: any, callback: PaginatedResultCallback<T>): void {
async get(params: any): Promise<PaginatedResult<T>> {
const res = this.resource;
Resource.get(
res.client,
res.path,
res.headers,
params,
res.envelope,
function (err, body, headers, unpacked, statusCode) {
res.handlePage(err, body, headers, unpacked, statusCode, callback);
}
);
const result = await Resource.get<T>(res.client, res.path, res.headers, params, res.envelope, false);
return res.handlePage(result);
}
}

Expand Down
Loading
Loading