Skip to content

Commit

Permalink
chore(solace-message-client): remove deprecated APIs
Browse files Browse the repository at this point in the history
BREAKING CHANGE: Removing the deprecated APIs introduced breaking changes.

The following APIs have been removed:
 - `SolaceMessageClientModule.forRoot` => register Angular Solace Message Client using `provideSolaceMessageClient` function instead;
 - `SolaceMessageClientModule.forChild` => register Angular Solace Message Client using `provideSolaceMessageClient` function instead;
 - `OAuthAccessTokenProvider` => use `OAuthAccessTokenFn` instead;
 - `BrowseOptions.emitOutsideAngularZone` => messages are received in the zone in which subscribed to the Observable. To receive messages outside the Angular zone, subscribe to the Observable outside the Angular zone, otherwise inside the Angular zone;
 - `ConsumeOptions.emitOutsideAngularZone` => messages are received in the zone in which subscribed to the Observable. To receive messages outside the Angular zone, subscribe to the Observable outside the Angular zone, otherwise inside the Angular zone;
 - `ObserveOptions.emitOutsideAngularZone` => messages are received in the zone in which subscribed to the Observable. To receive messages outside the Angular zone, subscribe to the Observable outside the Angular zone, otherwise inside the Angular zone;
 - `RequestOptions.emitOutsideAngularZone` => replies are received in the zone in which subscribed to the Observable. To receive replies outside the Angular zone, subscribe to the Observable outside the Angular zone, otherwise inside the Angular zone;
  • Loading branch information
k-genov committed Dec 5, 2024
1 parent 43743f8 commit 51c9102
Show file tree
Hide file tree
Showing 11 changed files with 17 additions and 484 deletions.
Original file line number Diff line number Diff line change
@@ -1,59 +1,5 @@
import {Observable} from 'rxjs';

/**
* Provides "solclientjs" continuously with a valid "OAuth 2.0 Access Token".
*
* OAuth 2.0 enables secure login to the broker while protecting user credentials.
*
* This class provides an Observable that emits the user's access token upon subscription, and then continuously emits it when the token is renewed.
* The Observable should never complete, enabling the connection to the broker to be re-established in the event of a network interruption.
*
* Register this class in {@link SolaceMessageClientConfig#accessToken} and enable OAuth 2.0 authentication scheme in {@link SolaceMessageClientConfig#authenticationScheme}.
*
* **Example of an `OAuthAccessTokenProvider`**
*
* ```ts
* @Injectable({providedIn: 'root'})
* export class YourAccessTokenProvider implements OAuthAccessTokenProvider {
*
* constructor(private authService: YourAuthService) {
* }
*
* public provide$(): Observable<string> {
* return this.authService.accessToken$;
* }
* }
* ```
*
* **Example for configuring Solace Message Client**
*
* ```ts
* import {bootstrapApplication} from '@angular/platform-browser';
* import {provideSolaceMessageClient} from '@solace-community/angular-solace-message-client';
* import {AuthenticationScheme} from 'solclientjs';
*
* bootstrapApplication(AppComponent, {
* providers: [
* provideSolaceMessageClient({
* url: 'wss://YOUR-SOLACE-BROKER-URL:443',
* vpnName: 'YOUR VPN',
* authenticationScheme: AuthenticationScheme.OAUTH2, // enables OAUTH
* accessToken: YourAccessTokenProvider, sets your access token provider
* }),
* ],
* });
* ```
* @deprecated since version 17.1.0; Use `OAuthAccessTokenFn` instead; API will be removed in a future release.
* @see {@link OAuthAccessTokenFn}
*/
export interface OAuthAccessTokenProvider {

/**
* Provides an Observable that emits the user's access token upon subscription, and then continuously emits it when the token is renewed. It never completes.
*/
provide$(): Observable<string>;
}

/**
* Signature of a function to provide "solclientjs" continuously with a valid "OAuth 2.0 Access Token".
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,8 @@ import {AuthenticationScheme, SessionEventCode} from 'solclientjs';
import {SessionFixture} from './testing/session.fixture';
import {provideSession} from './testing/session-provider';
import {TestBed} from '@angular/core/testing';
import {BehaviorSubject, EMPTY, NEVER, Observable, of, Subject} from 'rxjs';
import {inject, Injectable, InjectionToken, NgZone} from '@angular/core';
import {OAuthAccessTokenProvider} from './oauth-access-token-provider';
import {BehaviorSubject, EMPTY, Observable, of, Subject} from 'rxjs';
import {inject, InjectionToken, NgZone} from '@angular/core';
import {drainMicrotaskQueue, initSolclientFactory} from './testing/testing.utils';
import {SolaceSessionProvider} from './solace-session-provider';

Expand All @@ -19,49 +18,6 @@ describe('OAuth 2.0', () => {
spyOn(console, 'error');
});

it('should invoke `OAuthAccessTokenProvider$provide$` in Angular zone', async () => {
const sessionFixture = new SessionFixture();

@Injectable({providedIn: 'root'})
class TestAccessTokenProvider implements OAuthAccessTokenProvider {

public constructedInAngularZone: boolean | undefined;
public invokedInAngularZone: boolean | undefined;
public subscribedInAngularZone: boolean | undefined;

constructor() {
this.constructedInAngularZone = NgZone.isInAngularZone();
}

public provide$(): Observable<string> {
this.invokedInAngularZone = NgZone.isInAngularZone();
return new Observable(observer => {
this.subscribedInAngularZone = NgZone.isInAngularZone();
observer.next('access-token');
});
}
}

TestBed.configureTestingModule({
providers: [
provideSolaceMessageClient({
url: 'url',
vpnName: 'vpn',
authenticationScheme: AuthenticationScheme.OAUTH2,
accessToken: TestAccessTokenProvider,
}),
provideSession(sessionFixture),
],
});

TestBed.inject(SolaceMessageClient);
await drainMicrotaskQueue();

expect(TestBed.inject(TestAccessTokenProvider).constructedInAngularZone).toBeTrue();
expect(TestBed.inject(TestAccessTokenProvider).invokedInAngularZone).toBeTrue();
expect(TestBed.inject(TestAccessTokenProvider).subscribedInAngularZone).toBeTrue();
});

it('should invoke access token function in Angular zone', async () => {
const sessionFixture = new SessionFixture();

Expand Down Expand Up @@ -278,36 +234,6 @@ describe('OAuth 2.0', () => {
expect(sessionFixture.session.updateAuthenticationOnReconnect).toHaveBeenCalledTimes(0);
});

it('should error if forgotten to register `OAuthAccessTokenProvider` as Angular provider [NullAccessTokenProviderError]', async () => {
// Create a provider, but forget to register it as Angular provider
@Injectable()
class TestAccessTokenProvider implements OAuthAccessTokenProvider {
public provide$(): Observable<string> {
return NEVER;
}
}

const sessionFixture = new SessionFixture();
TestBed.configureTestingModule({
providers: [
provideSolaceMessageClient({
url: 'url',
vpnName: 'vpn',
authenticationScheme: AuthenticationScheme.OAUTH2,
accessToken: TestAccessTokenProvider,
}),
provideSession(sessionFixture),
],
});

TestBed.inject(SolaceMessageClient);
await drainMicrotaskQueue();

expect(console.error).toHaveBeenCalledWith(jasmine.stringMatching(/\[SolaceMessageClient]/), jasmine.stringMatching(/\[NullAccessTokenProviderError]/));
expect(sessionFixture.sessionProvider.provide).toHaveBeenCalledTimes(0);
expect(sessionFixture.session.updateAuthenticationOnReconnect).toHaveBeenCalledTimes(0);
});

it('should error when emitting `null` as the initial access token [NullAccessTokenError]', async () => {
const sessionFixture = new SessionFixture();
TestBed.configureTestingModule({
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -109,66 +109,6 @@ describe('SolaceMessageClient - Browse', () => {
]);
});

// @deprecated since version 17.1.0; Remove when dropping support to configure whether to emit inside or outside the Angular zone.
it('should receive messages inside the Angular zone', async () => {
const sessionFixture = new SessionFixture();
const queueBrowserFixture = sessionFixture.queueBrowserFixture;
const observeCaptor = new ObserveCaptor(() => NgZone.isInAngularZone());
TestBed.configureTestingModule({
providers: [
provideSolaceMessageClient({url: 'url', vpnName: 'vpn'}),
provideSession(sessionFixture),
],
});
const solaceMessageClient = TestBed.inject(SolaceMessageClient);
await sessionFixture.simulateEvent(SessionEventCode.UP_NOTICE);

// Connect to the queue browser
solaceMessageClient.browse$({
queueDescriptor: new QueueDescriptor({type: QueueType.QUEUE, name: 'queue'}),
emitOutsideAngularZone: false,
}).subscribe(observeCaptor);

// Simulate the queue browser to be connected to the broker
await queueBrowserFixture.simulateEvent(QueueBrowserEventName.UP);

// Simulate to receive a message
await queueBrowserFixture.simulateMessage(createQueueMessage('queue'));

// Expect message to be received inside the Angular zone
expect(observeCaptor.getValues()).toEqual([true]);
});

// @deprecated since version 17.1.0; Remove when dropping support to configure whether to emit inside or outside the Angular zone.
it('should receive messages outside the Angular zone', async () => {
const sessionFixture = new SessionFixture();
const queueBrowserFixture = sessionFixture.queueBrowserFixture;
const observeCaptor = new ObserveCaptor(() => NgZone.isInAngularZone());
TestBed.configureTestingModule({
providers: [
provideSolaceMessageClient({url: 'url', vpnName: 'vpn'}),
provideSession(sessionFixture),
],
});
const solaceMessageClient = TestBed.inject(SolaceMessageClient);
await sessionFixture.simulateEvent(SessionEventCode.UP_NOTICE);

// Connect to the queue browser
solaceMessageClient.browse$({
queueDescriptor: new QueueDescriptor({type: QueueType.QUEUE, name: 'queue'}),
emitOutsideAngularZone: true,
}).subscribe(observeCaptor);

// Simulate the queue browser to be connected to the broker
await queueBrowserFixture.simulateEvent(QueueBrowserEventName.UP);

// Simulate to receive a message
await queueBrowserFixture.simulateMessage(createQueueMessage('queue'));

// Expect message to be received outside the Angular zone
expect(observeCaptor.getValues()).toEqual([false]);
});

it('should receive messages in the zone subscribed (inside Angular)', async () => {
const sessionFixture = new SessionFixture();
const queueBrowserFixture = sessionFixture.queueBrowserFixture;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,68 +145,6 @@ describe('SolaceMessageClient - Consume', () => {
]);
});

// @deprecated since version 17.1.0; Remove when dropping support to configure whether to emit inside or outside the Angular zone.
it('should receive messages inside the Angular zone', async () => {
const sessionFixture = new SessionFixture();
const messageConsumerFixture = sessionFixture.messageConsumerFixture;
const observeCaptor = new ObserveCaptor(() => NgZone.isInAngularZone());
TestBed.configureTestingModule({
providers: [
provideSolaceMessageClient({url: 'url', vpnName: 'vpn'}),
provideSession(sessionFixture),
],
});
const solaceMessageClient = TestBed.inject(SolaceMessageClient);
await sessionFixture.simulateEvent(SessionEventCode.UP_NOTICE);

// Subscribe to a topic endpoint
solaceMessageClient.consume$({
topicEndpointSubscription: SolclientFactory.createTopicDestination('topic'),
queueDescriptor: new QueueDescriptor({type: QueueType.TOPIC_ENDPOINT, durable: false}),
emitOutsideAngularZone: false,
}).subscribe(observeCaptor);

// Simulate the message consumer to be connected to the broker
await messageConsumerFixture.simulateEvent(MessageConsumerEventName.UP);

// Simulate to receive a message
await messageConsumerFixture.simulateMessage(createTopicMessage('topic'));

// Expect message to be received inside the Angular zone
expect(observeCaptor.getValues()).toEqual([true]);
});

// @deprecated since version 17.1.0; Remove when dropping support to configure whether to emit inside or outside the Angular zone.
it('should receive messages outside the Angular zone', async () => {
const sessionFixture = new SessionFixture();
const messageConsumerFixture = sessionFixture.messageConsumerFixture;
const observeCaptor = new ObserveCaptor(() => NgZone.isInAngularZone());
TestBed.configureTestingModule({
providers: [
provideSolaceMessageClient({url: 'url', vpnName: 'vpn'}),
provideSession(sessionFixture),
],
});
const solaceMessageClient = TestBed.inject(SolaceMessageClient);
await sessionFixture.simulateEvent(SessionEventCode.UP_NOTICE);

// Subscribe to a topic endpoint
solaceMessageClient.consume$({
topicEndpointSubscription: SolclientFactory.createTopicDestination('topic'),
queueDescriptor: new QueueDescriptor({type: QueueType.TOPIC_ENDPOINT, durable: false}),
emitOutsideAngularZone: true,
}).subscribe(observeCaptor);

// Simulate the message consumer to be connected to the broker
await messageConsumerFixture.simulateEvent(MessageConsumerEventName.UP);

// Simulate to receive a message
await messageConsumerFixture.simulateMessage(createTopicMessage('topic'));

// Expect message to be received outside the Angular zone
expect(observeCaptor.getValues()).toEqual([false]);
});

it('should receive messages in the zone subscribed (inside Angular)', async () => {
const sessionFixture = new SessionFixture();
const messageConsumerFixture = sessionFixture.messageConsumerFixture;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,54 +95,6 @@ describe('SolaceMessageClient - Request Reply', () => {
expect(replyCaptor.hasErrored()).toBeTrue();
});

// @deprecated since version 17.1.0; Remove when dropping support to configure whether to emit inside or outside the Angular zone.
it('should emit inside Angular', async () => {
const sessionFixture = new SessionFixture();
const sendRequestFixture = sessionFixture.sendRequestFixture;
const zoneCaptor = new ObserveCaptor<MessageEnvelope, boolean>(() => NgZone.isInAngularZone());
TestBed.configureTestingModule({
providers: [
provideSolaceMessageClient({url: 'url', vpnName: 'vpn'}),
provideSession(sessionFixture),
],
});
const solaceMessageClient = TestBed.inject(SolaceMessageClient);
await sessionFixture.simulateEvent(SessionEventCode.UP_NOTICE);

// Send a request
solaceMessageClient.request$('topic', undefined, {emitOutsideAngularZone: false}).subscribe(zoneCaptor);
await drainMicrotaskQueue();

// Simulate to receive a reply
await sendRequestFixture.simulateReply(createTopicMessage('reply'));

expect(zoneCaptor.getValues()).toEqual([true]);
});

// @deprecated since version 17.1.0; Remove when dropping support to configure whether to emit inside or outside the Angular zone.
it('should emit outside Angular', async () => {
const sessionFixture = new SessionFixture();
const sendRequestFixture = sessionFixture.sendRequestFixture;
const zoneCaptor = new ObserveCaptor<MessageEnvelope, boolean>(() => NgZone.isInAngularZone());
TestBed.configureTestingModule({
providers: [
provideSolaceMessageClient({url: 'url', vpnName: 'vpn'}),
provideSession(sessionFixture),
],
});
const solaceMessageClient = TestBed.inject(SolaceMessageClient);
await sessionFixture.simulateEvent(SessionEventCode.UP_NOTICE);

// Send a request
solaceMessageClient.request$('topic', undefined, {emitOutsideAngularZone: true}).subscribe(zoneCaptor);
await drainMicrotaskQueue();

// Simulate to receive a reply
await sendRequestFixture.simulateReply(createTopicMessage('reply'));

expect(zoneCaptor.getValues()).toEqual([false]);
});

it('should receive reply in the zone subscribed (inside Angular)', async () => {
const sessionFixture = new SessionFixture();
const sendRequestFixture = sessionFixture.sendRequestFixture;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
import {SessionProperties} from 'solclientjs';
import {InjectionToken, Type} from '@angular/core';
import {OAuthAccessTokenFn, OAuthAccessTokenProvider} from './oauth-access-token-provider';
import {InjectionToken} from '@angular/core';
import {OAuthAccessTokenFn} from './oauth-access-token-provider';
import {Observable} from 'rxjs';

/**
Expand All @@ -19,7 +19,7 @@ export interface SolaceMessageClientConfig extends Omit<SessionProperties, 'acce
*
* @see {@link OAuthAccessTokenFn}
*/
accessToken?: string | Type<OAuthAccessTokenProvider> | OAuthAccessTokenFn;
accessToken?: string | OAuthAccessTokenFn;
}

/**
Expand Down
Loading

0 comments on commit 51c9102

Please sign in to comment.