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

[#169] Improve JS client error responses #196

Merged
merged 2 commits into from
Sep 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
11 changes: 11 additions & 0 deletions javascript/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,17 @@
# Changelog
All notable changes to the Ditto JavaScript client will be documented in this file.

## [3.0.0] - 2022-09-xx

### Updated dependencies
TODO text

### \#169 Improved error handling for HTTP rejections
TODO text

### \#193 Preserve headers when responding to messages
TODO text

## [2.4.0] - 2022-04-14

### No changes
Expand Down
2 changes: 1 addition & 1 deletion javascript/lerna.json
Original file line number Diff line number Diff line change
Expand Up @@ -16,5 +16,5 @@
]
}
},
"version": "2.4.0"
"version": "3.0.0"
}
445 changes: 244 additions & 201 deletions javascript/lib/api/package-lock.json

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions javascript/lib/api/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@eclipse-ditto/ditto-javascript-client-api",
"version": "2.4.0",
"version": "3.0.0",
"description": "API interfaces for implementing TypeScript clients for Eclipse Ditto",
"author": "Eclipse Ditto committers <[email protected]>",
"repository": "https://github.com/eclipse/ditto-clients",
Expand All @@ -25,7 +25,7 @@
"tslint": "^5.18.x",
"tslint-config-airbnb": "^5.11.1",
"tslint-sonarts": "^1.8.0",
"typescript": "^3.4.3"
"typescript": "^3.9.10"
},
"scripts": {
"build": "npm run build:tsc && npm run build:barrels",
Expand Down
3 changes: 2 additions & 1 deletion javascript/lib/api/src/client/handles/events.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,9 @@
* SPDX-License-Identifier: EPL-2.0
*/

import { ProtocolResponseValue } from '../request-factory/websocket-request-handler';
/* tslint:disable:bool-param-default no-identical-functions */
import { SubscribeRequest } from '../request-factory/websocket-request-sender';
import { ProtocolResponseValue } from '../request-factory/websocket-request-handler';

/**
* Handle to receive Events. To be able to subscribe to Events requestEvents() needs to be called first
Expand Down Expand Up @@ -136,6 +136,7 @@ export interface EventsHandle {
*
* @param thingId - The ID of the Thing the Feature belongs to.
* @param featureId - The ID of the Feature the Property belongs to.
* @param propertyPath - The path of the Feature Property.
* @param callback - The function that gets called for every Event.
* @param action - The action to listen for (eg. modify).
* @param subResources - Whether or not sub-resources of the Property should also trigger the callback.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,18 +11,18 @@
* SPDX-License-Identifier: EPL-2.0
*/

import { AuthProvider, DittoURL } from '../../auth/auth-provider';
import { DefaultDittoProtocolEnvelope, DittoProtocolEnvelope, DittoProtocolResponse } from '../../model/ditto-protocol';
import { GenericResponse } from '../../model/response';
/* tslint:disable:no-duplicate-string */
import {
PromiseResponse,
RequestHandler,
ResilienceHandler,
ResilienceHandlerFactoryBuildStep,
WebSocketImplementationBuilderHandler,
WebSocketBindingMessage
WebSocketBindingMessage,
WebSocketImplementationBuilderHandler
} from './resilience/websocket-resilience-interfaces';
import { AuthProvider, DittoURL } from '../../auth/auth-provider';
import { DefaultDittoProtocolEnvelope, DittoProtocolEnvelope, DittoProtocolResponse } from '../../model/ditto-protocol';
import { GenericResponse } from '../../model/response';

/**
* A Factory for a WebSocketRequestSender.
Expand Down Expand Up @@ -245,6 +245,7 @@ abstract class Subscription {
action,
topic: message.topic,
path: message.path,
headers: message.headers,
value: message.value
});
}
Expand Down Expand Up @@ -314,6 +315,6 @@ export interface ProtocolResponseValue {
topic: string;
path: string;
action: string;
headers?: string;
headers?: { [key: string]: any };
value?: any;
}
4 changes: 2 additions & 2 deletions javascript/lib/api/src/model/ditto-protocol.ts
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ interface DittoProtocolResponse {
path: string;
status: number;
headers: { [key: string]: any };
value: object;
value: any;

correlationId(): string | undefined;
}
Expand All @@ -86,7 +86,7 @@ class DefaultDittoProtocolResponse implements DittoProtocolResponse {
value: object;
status: number;

constructor(topic: string, headers: object, path: string, value: object, status: number) {
constructor(topic: string, headers: object, path: string, value: any, status: number) {
this.topic = topic;
this.headers = headers;
this.path = path;
Expand Down
31 changes: 31 additions & 0 deletions javascript/lib/api/src/model/response.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,18 @@ export interface GenericResponse {
headers: Map<string, string>;
}

/**
* A generic server response to a request.
*/
export interface ErrorResponse {
/** The status code of the error response. */
status: number;
/** The body of the error response. */
body: any;
/** The headers of the error response inside a map. */
headers: Map<string, string>;
}

export class PutResponse<T> implements GenericResponse {
public constructor(private readonly _value: T | null,
private readonly _status: number,
Expand Down Expand Up @@ -53,6 +65,25 @@ export class PutResponse<T> implements GenericResponse {
}
}

export class BasicErrorResponse<T> implements ErrorResponse {
public constructor(private readonly _value: T | null,
private readonly _status: number,
private readonly _headers: Map<string, string>) {
}

get body(): T | null {
return this._value;
}

get status(): number {
return this._status;
}

get headers(): Map<string, string> {
return this._headers;
}
}


/**
* Representation of a response ot a search request
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
* SPDX-License-Identifier: EPL-2.0
*/

import { jest } from '@jest/globals';
import { ProtocolResponseValue } from '../../../src/client/request-factory/websocket-request-handler';
import { EventsHelper as H } from './events.helper';
import { Features } from '../../../src/model/things.model';
import { jest } from '@jest/globals';
import { EventsHelper as H } from './events.helper';

describe('WebSocket Commands Handle', () => {
jest.setTimeout(5000); // we need to tell jest, that it should also wait on promises ... default is 0 ms
Expand All @@ -35,6 +35,7 @@ describe('WebSocket Commands Handle', () => {
topic,
action,
path: '/',
headers: {},
value: H.thing.toObject()
}
});
Expand All @@ -49,6 +50,7 @@ describe('WebSocket Commands Handle', () => {
topic,
action,
path: '/',
headers: {},
value: H.thing.toObject()
}
});
Expand All @@ -63,6 +65,7 @@ describe('WebSocket Commands Handle', () => {
topic,
action,
path: `/attributes`,
headers: {},
value: H.attributes
}
});
Expand All @@ -77,6 +80,7 @@ describe('WebSocket Commands Handle', () => {
topic,
action,
path: `/attributes/${H.attributePath}`,
headers: {},
value: H.attribute
}
});
Expand All @@ -91,6 +95,7 @@ describe('WebSocket Commands Handle', () => {
topic,
action,
path: '/features',
headers: {},
value: Features.toObject(H.features)
}
});
Expand All @@ -105,6 +110,7 @@ describe('WebSocket Commands Handle', () => {
topic,
action,
path: `/features/${H.feature.id}`,
headers: {},
value: H.feature.toObject()
}
});
Expand All @@ -119,6 +125,7 @@ describe('WebSocket Commands Handle', () => {
topic,
action,
path: `/features/${H.feature.id}/definition`,
headers: {},
value: H.definition
}
});
Expand All @@ -133,6 +140,7 @@ describe('WebSocket Commands Handle', () => {
topic,
action,
path: `/features/${H.feature.id}/properties`,
headers: {},
value: H.properties
}
});
Expand All @@ -147,6 +155,7 @@ describe('WebSocket Commands Handle', () => {
topic,
action,
path: `/features/${H.feature.id}/properties/${H.propertyPath}`,
headers: {},
value: H.property
}
});
Expand Down
13 changes: 11 additions & 2 deletions javascript/lib/api/tests/client/websocket/events.websocket.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,10 @@
* SPDX-License-Identifier: EPL-2.0
*/

import { jest } from '@jest/globals';
import { ProtocolResponseValue } from '../../../src/client/request-factory/websocket-request-handler';
import { EventsHelper as H } from './events.helper';
import { Features } from '../../../src/model/things.model';
import { jest } from '@jest/globals';
import { EventsHelper as H } from './events.helper';

describe('WebSocket Events Handle', () => {
jest.setTimeout(5000); // we need to tell jest, that it should also wait on promises ... default is 0 ms
Expand All @@ -35,6 +35,7 @@ describe('WebSocket Events Handle', () => {
topic,
action,
path: '/',
headers: {},
value: H.thing.toObject()
}
});
Expand All @@ -49,6 +50,7 @@ describe('WebSocket Events Handle', () => {
topic,
action,
path: '/',
headers: {},
value: H.thing.toObject()
}
});
Expand All @@ -63,6 +65,7 @@ describe('WebSocket Events Handle', () => {
topic,
action,
path: `/attributes`,
headers: {},
value: H.attributes
}
});
Expand All @@ -77,6 +80,7 @@ describe('WebSocket Events Handle', () => {
topic,
action,
path: `/attributes/${H.attributePath}`,
headers: {},
value: H.attribute
}
});
Expand All @@ -91,6 +95,7 @@ describe('WebSocket Events Handle', () => {
topic,
action,
path: '/features',
headers: {},
value: Features.toObject(H.features)
}
});
Expand All @@ -105,6 +110,7 @@ describe('WebSocket Events Handle', () => {
topic,
action,
path: `/features/${H.feature.id}`,
headers: {},
value: H.feature.toObject()
}
});
Expand All @@ -119,6 +125,7 @@ describe('WebSocket Events Handle', () => {
topic,
action,
path: `/features/${H.feature.id}/definition`,
headers: {},
value: H.definition
}
});
Expand All @@ -133,6 +140,7 @@ describe('WebSocket Events Handle', () => {
topic,
action,
path: `/features/${H.feature.id}/properties`,
headers: {},
value: H.properties
}
});
Expand All @@ -147,6 +155,7 @@ describe('WebSocket Events Handle', () => {
topic,
action,
path: `/features/${H.feature.id}/properties/${H.propertyPath}`,
headers: {},
value: H.property
}
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,11 +11,11 @@
* SPDX-License-Identifier: EPL-2.0
*/

import { jest } from '@jest/globals';
/* tslint:disable:no-duplicate-string */
import { ProtocolResponseValue } from '../../../src/client/request-factory/websocket-request-handler';
import { EventsHelper as H } from './events.helper';
import { GenericResponse } from '../../../src/model/response';
import { jest } from '@jest/globals';
import { EventsHelper as H } from './events.helper';

const testWithoutResponse: (method: () => void, request: Request) => Promise<void> = (method: () => void, request: Request) => {
return new Promise<void>(resolve => {
Expand Down Expand Up @@ -171,6 +171,7 @@ describe('WebSocket Messages Handle', () => {
topic: standardTopic,
action: subject,
path: '/',
headers: {},
value: H.thing.toObject()
}
});
Expand All @@ -186,6 +187,7 @@ describe('WebSocket Messages Handle', () => {
topic: standardTopic,
action: subject,
path: `/features/${H.feature.id}/outbox`,
headers: {},
value: H.thing.toObject()
}
});
Expand All @@ -201,6 +203,7 @@ describe('WebSocket Messages Handle', () => {
topic: standardTopic,
action: subject,
path: '/',
headers: {},
value: H.thing.toObject()
}
});
Expand Down
Loading