@cratis/arc 22.125.3 → 22.126.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/cjs/queries/ServerSentEventHubConnection.d.ts +1 -0
- package/dist/cjs/queries/ServerSentEventHubConnection.d.ts.map +1 -1
- package/dist/cjs/queries/ServerSentEventHubConnection.js +23 -0
- package/dist/cjs/queries/ServerSentEventHubConnection.js.map +1 -1
- package/dist/cjs/queries/WebSocketHubConnection.d.ts +1 -0
- package/dist/cjs/queries/WebSocketHubConnection.d.ts.map +1 -1
- package/dist/cjs/queries/WebSocketHubConnection.js +26 -0
- package/dist/cjs/queries/WebSocketHubConnection.js.map +1 -1
- package/dist/esm/queries/ServerSentEventHubConnection.d.ts +1 -0
- package/dist/esm/queries/ServerSentEventHubConnection.d.ts.map +1 -1
- package/dist/esm/queries/ServerSentEventHubConnection.js +23 -0
- package/dist/esm/queries/ServerSentEventHubConnection.js.map +1 -1
- package/dist/esm/queries/WebSocketHubConnection.d.ts +1 -0
- package/dist/esm/queries/WebSocketHubConnection.d.ts.map +1 -1
- package/dist/esm/queries/WebSocketHubConnection.js +26 -0
- package/dist/esm/queries/WebSocketHubConnection.js.map +1 -1
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_an_error_message/and_the_query_is_subscribed.d.ts +2 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_an_error_message/and_the_query_is_subscribed.d.ts.map +1 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_an_error_message/and_the_query_is_subscribed.js +69 -0
- package/dist/esm/queries/for_ServerSentEventHubConnection/when_receiving_an_error_message/and_the_query_is_subscribed.js.map +1 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_an_error_message/and_the_query_is_subscribed.d.ts +2 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_an_error_message/and_the_query_is_subscribed.d.ts.map +1 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_an_error_message/and_the_query_is_subscribed.js +68 -0
- package/dist/esm/queries/for_WebSocketHubConnection/when_receiving_an_error_message/and_the_query_is_subscribed.js.map +1 -0
- package/dist/esm/tsconfig.tsbuildinfo +1 -1
- package/package.json +1 -1
- package/queries/ServerSentEventHubConnection.ts +21 -0
- package/queries/WebSocketHubConnection.ts +21 -0
- package/queries/for_ServerSentEventHubConnection/when_receiving_an_error_message/and_the_query_is_subscribed.ts +80 -0
- package/queries/for_WebSocketHubConnection/when_receiving_an_error_message/and_the_query_is_subscribed.ts +79 -0
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"type": "module",
|
|
3
3
|
"name": "@cratis/arc",
|
|
4
|
-
"version": "22.
|
|
4
|
+
"version": "22.126.0",
|
|
5
5
|
"description": "TypeScript command, query, validation, identity, and messaging runtime for Cratis Arc — the CQRS application framework for ASP.NET Core — used by generated proxies.",
|
|
6
6
|
"keywords": [
|
|
7
7
|
"cratis",
|
|
@@ -333,6 +333,7 @@ export class ServerSentEventHubConnection implements IObservableQueryHubConnecti
|
|
|
333
333
|
message.queryId,
|
|
334
334
|
message.payload,
|
|
335
335
|
);
|
|
336
|
+
this.handleError(message);
|
|
336
337
|
}
|
|
337
338
|
break;
|
|
338
339
|
}
|
|
@@ -394,6 +395,26 @@ export class ServerSentEventHubConnection implements IObservableQueryHubConnecti
|
|
|
394
395
|
this.deliverResult(message, result, result?.isValid === false);
|
|
395
396
|
}
|
|
396
397
|
|
|
398
|
+
private handleError(message: HubMessage): void {
|
|
399
|
+
const result = new QueryResult(
|
|
400
|
+
{
|
|
401
|
+
data: undefined,
|
|
402
|
+
isSuccess: false,
|
|
403
|
+
isReady: true,
|
|
404
|
+
isAuthorized: true,
|
|
405
|
+
isValid: true,
|
|
406
|
+
hasExceptions: true,
|
|
407
|
+
validationResults: [],
|
|
408
|
+
exceptionMessages: [message.payload as string],
|
|
409
|
+
exceptionStackTrace: '',
|
|
410
|
+
paging: { totalItems: 0, totalPages: 0, page: 0, size: 0 },
|
|
411
|
+
},
|
|
412
|
+
Object,
|
|
413
|
+
false,
|
|
414
|
+
);
|
|
415
|
+
this.deliverResult(message, result, false);
|
|
416
|
+
}
|
|
417
|
+
|
|
397
418
|
private handleUnauthorized(message: HubMessage): void {
|
|
398
419
|
this.deliverResult(message, QueryResult.unauthorized(), true);
|
|
399
420
|
}
|
|
@@ -372,6 +372,7 @@ export class WebSocketHubConnection {
|
|
|
372
372
|
message.queryId,
|
|
373
373
|
message.payload,
|
|
374
374
|
);
|
|
375
|
+
this.handleError(message);
|
|
375
376
|
}
|
|
376
377
|
break;
|
|
377
378
|
}
|
|
@@ -408,6 +409,26 @@ export class WebSocketHubConnection {
|
|
|
408
409
|
sub.callback(result);
|
|
409
410
|
}
|
|
410
411
|
|
|
412
|
+
private handleError(message: HubMessage): void {
|
|
413
|
+
const result = new QueryResult(
|
|
414
|
+
{
|
|
415
|
+
data: undefined,
|
|
416
|
+
isSuccess: false,
|
|
417
|
+
isReady: true,
|
|
418
|
+
isAuthorized: true,
|
|
419
|
+
isValid: true,
|
|
420
|
+
hasExceptions: true,
|
|
421
|
+
validationResults: [],
|
|
422
|
+
exceptionMessages: [message.payload as string],
|
|
423
|
+
exceptionStackTrace: '',
|
|
424
|
+
paging: { totalItems: 0, totalPages: 0, page: 0, size: 0 },
|
|
425
|
+
},
|
|
426
|
+
Object,
|
|
427
|
+
false,
|
|
428
|
+
);
|
|
429
|
+
this.handleQueryResult({ ...message, payload: result });
|
|
430
|
+
}
|
|
431
|
+
|
|
411
432
|
private handleUnauthorized(message: HubMessage): void {
|
|
412
433
|
if (!message.queryId) return;
|
|
413
434
|
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import sinon from 'sinon';
|
|
5
|
+
import { a_server_sent_event_hub_connection } from '../given/a_server_sent_event_hub_connection.js';
|
|
6
|
+
import { given } from '../../../given.js';
|
|
7
|
+
import { HubMessageType } from '../../WebSocketHubConnection.js';
|
|
8
|
+
import { QueryResult } from '../../QueryResult.js';
|
|
9
|
+
|
|
10
|
+
for (const supportsRevisions of [false, true]) {
|
|
11
|
+
describe(
|
|
12
|
+
`when receiving an SSE query error with revision support ${supportsRevisions}`,
|
|
13
|
+
given(a_server_sent_event_hub_connection, (context) => {
|
|
14
|
+
const queryId = 'query-failed';
|
|
15
|
+
const failure = 'MongoDB is unreachable.';
|
|
16
|
+
let callback: sinon.SinonStub;
|
|
17
|
+
let otherCallback: sinon.SinonStub;
|
|
18
|
+
let result: QueryResult<unknown>;
|
|
19
|
+
let revision: number | undefined;
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
context.setup();
|
|
23
|
+
sinon.stub(console, 'error');
|
|
24
|
+
callback = sinon.stub();
|
|
25
|
+
otherCallback = sinon.stub();
|
|
26
|
+
context.connection.subscribe(queryId, { queryName: 'Authors' }, callback);
|
|
27
|
+
context.simulateOpen();
|
|
28
|
+
context.simulateMessage({
|
|
29
|
+
type: HubMessageType.Connected,
|
|
30
|
+
payload: 'connection-a',
|
|
31
|
+
supportsSubscriptionRevisions: supportsRevisions,
|
|
32
|
+
});
|
|
33
|
+
try {
|
|
34
|
+
revision = (JSON.parse(context.fetchStub.firstCall.args[1].body as string) as { revision?: number }).revision;
|
|
35
|
+
} catch (error) {
|
|
36
|
+
throw new Error('Expected a valid subscribe body', { cause: error });
|
|
37
|
+
}
|
|
38
|
+
context.connection.subscribe('other-query', { queryName: 'Other' }, otherCallback);
|
|
39
|
+
|
|
40
|
+
context.simulateMessage({ type: HubMessageType.Error, queryId, revision, payload: failure });
|
|
41
|
+
|
|
42
|
+
result = callback.firstCall?.args[0] as QueryResult<unknown>;
|
|
43
|
+
});
|
|
44
|
+
|
|
45
|
+
afterEach(() => {
|
|
46
|
+
context.connection.dispose();
|
|
47
|
+
sinon.restore();
|
|
48
|
+
});
|
|
49
|
+
|
|
50
|
+
it('should deliver one QueryResult to the subscriber', () => {
|
|
51
|
+
callback.calledOnce.should.be.true;
|
|
52
|
+
result.should.be.instanceOf(QueryResult);
|
|
53
|
+
});
|
|
54
|
+
it('should report a ready failed result', () => {
|
|
55
|
+
result.isReady.should.be.true;
|
|
56
|
+
result.isSuccess.should.be.false;
|
|
57
|
+
result.hasExceptions.should.be.true;
|
|
58
|
+
});
|
|
59
|
+
it('should carry the server error message', () =>
|
|
60
|
+
result.exceptionMessages.should.deep.equal([failure]));
|
|
61
|
+
it('should not report a validation or authorization rejection', () => {
|
|
62
|
+
result.isValid.should.be.true;
|
|
63
|
+
result.isAuthorized.should.be.true;
|
|
64
|
+
});
|
|
65
|
+
it('should have no result data', () => result.hasData.should.be.false);
|
|
66
|
+
it('should not notify another query', () => otherCallback.called.should.be.false);
|
|
67
|
+
it('should retain subscriptions for later results', () => {
|
|
68
|
+
context.connection.queryCount.should.equal(2);
|
|
69
|
+
context.simulateMessage({
|
|
70
|
+
type: HubMessageType.QueryResult,
|
|
71
|
+
queryId,
|
|
72
|
+
revision,
|
|
73
|
+
payload: { isSuccess: true, data: ['recovered'] },
|
|
74
|
+
});
|
|
75
|
+
callback.calledTwice.should.be.true;
|
|
76
|
+
callback.secondCall.args[0].isSuccess.should.be.true;
|
|
77
|
+
});
|
|
78
|
+
}),
|
|
79
|
+
);
|
|
80
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
// Copyright (c) Cratis. All rights reserved.
|
|
2
|
+
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
|
|
3
|
+
|
|
4
|
+
import sinon from 'sinon';
|
|
5
|
+
import { a_web_socket_hub_connection } from '../given/a_web_socket_hub_connection.js';
|
|
6
|
+
import { given } from '../../../given.js';
|
|
7
|
+
import { HubMessageType } from '../../WebSocketHubConnection.js';
|
|
8
|
+
import { QueryResult } from '../../QueryResult.js';
|
|
9
|
+
|
|
10
|
+
for (const supportsRevisions of [false, true]) {
|
|
11
|
+
describe(
|
|
12
|
+
`when receiving a WebSocket query error with revision support ${supportsRevisions}`,
|
|
13
|
+
given(a_web_socket_hub_connection, (context) => {
|
|
14
|
+
const queryId = 'query-failed';
|
|
15
|
+
const failure = 'MongoDB is unreachable.';
|
|
16
|
+
let callback: sinon.SinonStub;
|
|
17
|
+
let otherCallback: sinon.SinonStub;
|
|
18
|
+
let result: QueryResult<unknown>;
|
|
19
|
+
let revision: number | undefined;
|
|
20
|
+
|
|
21
|
+
beforeEach(() => {
|
|
22
|
+
context.setup();
|
|
23
|
+
sinon.stub(console, 'error');
|
|
24
|
+
callback = sinon.stub();
|
|
25
|
+
otherCallback = sinon.stub();
|
|
26
|
+
context.connection.subscribe(queryId, { queryName: 'Authors' }, callback);
|
|
27
|
+
context.simulateOpen();
|
|
28
|
+
context.simulateMessage({
|
|
29
|
+
type: HubMessageType.Connected,
|
|
30
|
+
supportsSubscriptionRevisions: supportsRevisions,
|
|
31
|
+
});
|
|
32
|
+
try {
|
|
33
|
+
revision = (JSON.parse(context.fakeSocket.send.lastCall.args[0] as string) as { revision?: number }).revision;
|
|
34
|
+
} catch (error) {
|
|
35
|
+
throw new Error('Expected a valid subscribe message', { cause: error });
|
|
36
|
+
}
|
|
37
|
+
context.connection.subscribe('other-query', { queryName: 'Other' }, otherCallback);
|
|
38
|
+
|
|
39
|
+
context.simulateMessage({ type: HubMessageType.Error, queryId, revision, payload: failure });
|
|
40
|
+
|
|
41
|
+
result = callback.firstCall?.args[0] as QueryResult<unknown>;
|
|
42
|
+
});
|
|
43
|
+
|
|
44
|
+
afterEach(() => {
|
|
45
|
+
context.connection.dispose();
|
|
46
|
+
sinon.restore();
|
|
47
|
+
});
|
|
48
|
+
|
|
49
|
+
it('should deliver one QueryResult to the subscriber', () => {
|
|
50
|
+
callback.calledOnce.should.be.true;
|
|
51
|
+
result.should.be.instanceOf(QueryResult);
|
|
52
|
+
});
|
|
53
|
+
it('should report a ready failed result', () => {
|
|
54
|
+
result.isReady.should.be.true;
|
|
55
|
+
result.isSuccess.should.be.false;
|
|
56
|
+
result.hasExceptions.should.be.true;
|
|
57
|
+
});
|
|
58
|
+
it('should carry the server error message', () =>
|
|
59
|
+
result.exceptionMessages.should.deep.equal([failure]));
|
|
60
|
+
it('should not report a validation or authorization rejection', () => {
|
|
61
|
+
result.isValid.should.be.true;
|
|
62
|
+
result.isAuthorized.should.be.true;
|
|
63
|
+
});
|
|
64
|
+
it('should have no result data', () => result.hasData.should.be.false);
|
|
65
|
+
it('should not notify another query', () => otherCallback.called.should.be.false);
|
|
66
|
+
it('should retain subscriptions for later results', () => {
|
|
67
|
+
context.connection.queryCount.should.equal(2);
|
|
68
|
+
context.simulateMessage({
|
|
69
|
+
type: HubMessageType.QueryResult,
|
|
70
|
+
queryId,
|
|
71
|
+
revision,
|
|
72
|
+
payload: { isSuccess: true, data: ['recovered'] },
|
|
73
|
+
});
|
|
74
|
+
callback.calledTwice.should.be.true;
|
|
75
|
+
callback.secondCall.args[0].isSuccess.should.be.true;
|
|
76
|
+
});
|
|
77
|
+
}),
|
|
78
|
+
);
|
|
79
|
+
}
|