diff --git a/lib/process-services-cloud/ng-package.json b/lib/process-services-cloud/ng-package.json index 04735461d9..11740e7e1c 100644 --- a/lib/process-services-cloud/ng-package.json +++ b/lib/process-services-cloud/ng-package.json @@ -29,7 +29,6 @@ "allowedNonPeerDependencies": [ "@apollo/client", "apollo-angular", - "subscriptions-transport-ws", "@editorjs/editorjs", "@editorjs/code", "@editorjs/header", diff --git a/lib/process-services-cloud/package.json b/lib/process-services-cloud/package.json index a2fceec738..2f1a82f098 100644 --- a/lib/process-services-cloud/package.json +++ b/lib/process-services-cloud/package.json @@ -41,8 +41,7 @@ "@alfresco/adf-content-services": ">=8.0.0", "@apollo/client": ">=3.7.2", "@ngx-translate/core": ">=14.0.0", - "apollo-angular": ">=4.0.1", - "subscriptions-transport-ws": ">=0.11.0" + "apollo-angular": ">=4.0.1" }, "keywords": [ "process-services-cloud", diff --git a/lib/process-services-cloud/src/lib/services/notification-cloud.service.spec.ts b/lib/process-services-cloud/src/lib/services/notification-cloud.service.spec.ts index 6df3c974af..8327037fa7 100644 --- a/lib/process-services-cloud/src/lib/services/notification-cloud.service.spec.ts +++ b/lib/process-services-cloud/src/lib/services/notification-cloud.service.spec.ts @@ -17,12 +17,11 @@ import { TestBed } from '@angular/core/testing'; import { NotificationCloudService } from './notification-cloud.service'; -import { provideMockFeatureFlags } from '@alfresco/adf-core/feature-flags'; import { WebSocketService } from './web-socket.service'; import { Apollo } from 'apollo-angular'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { AuthenticationService } from '@alfresco/adf-core'; -import { Subject } from 'rxjs'; +import { of, Subject } from 'rxjs'; describe('NotificationCloudService', () => { let service: NotificationCloudService; @@ -46,7 +45,6 @@ describe('NotificationCloudService', () => { imports: [HttpClientTestingModule], providers: [ WebSocketService, - provideMockFeatureFlags({ ['studio-ws-graphql-subprotocol']: false }), { provide: Apollo, useValue: apolloMock @@ -62,6 +60,7 @@ describe('NotificationCloudService', () => { }); service = TestBed.inject(NotificationCloudService); wsService = TestBed.inject(WebSocketService); + apolloMock.use.and.returnValue(of({})); }); it('should call getSubscription with the correct parameters', () => { @@ -72,7 +71,7 @@ describe('NotificationCloudService', () => { expect(getSubscriptionSpy).toHaveBeenCalledWith({ apolloClientName: 'myAppName', wsUrl: 'myAppName/notifications', - httpUrl: 'myAppName/notifications/graphql', + httpUrl: 'myAppName/notifications/v2/ws/graphql', subscriptionOptions: { query: jasmine.any(Object) } diff --git a/lib/process-services-cloud/src/lib/services/notification-cloud.service.ts b/lib/process-services-cloud/src/lib/services/notification-cloud.service.ts index 9777b973a8..6794848744 100644 --- a/lib/process-services-cloud/src/lib/services/notification-cloud.service.ts +++ b/lib/process-services-cloud/src/lib/services/notification-cloud.service.ts @@ -28,7 +28,7 @@ export class NotificationCloudService { return this.webSocketService.getSubscription({ apolloClientName: appName, wsUrl: `${appName}/notifications`, - httpUrl: `${appName}/notifications/graphql`, + httpUrl: `${appName}/notifications/v2/ws/graphql`, subscriptionOptions: { query: gql(gqlQuery) } diff --git a/lib/process-services-cloud/src/lib/services/web-socket.service.spec.ts b/lib/process-services-cloud/src/lib/services/web-socket.service.spec.ts index ad4183bb6f..b89a0f629a 100644 --- a/lib/process-services-cloud/src/lib/services/web-socket.service.spec.ts +++ b/lib/process-services-cloud/src/lib/services/web-socket.service.spec.ts @@ -22,14 +22,12 @@ import { WebSocketService } from './web-socket.service'; import { SubscriptionOptions } from '@apollo/client/core'; import { HttpClientTestingModule } from '@angular/common/http/testing'; import { AuthenticationService, AppConfigService } from '@alfresco/adf-core'; -import { FeaturesServiceToken } from '@alfresco/adf-core/feature-flags'; describe('WebSocketService', () => { let service: WebSocketService; const onLogoutSubject: Subject = new Subject(); const apolloMock = jasmine.createSpyObj('Apollo', ['use', 'createNamed']); - const isOnSpy = jasmine.createSpy('isOn$'); beforeEach(() => { TestBed.configureTestingModule({ @@ -51,19 +49,11 @@ describe('WebSocketService', () => { getToken: () => 'testToken', onLogout: onLogoutSubject.asObservable() } - }, - { - provide: FeaturesServiceToken, - useValue: { - isOn$: isOnSpy - } } ] }); service = TestBed.inject(WebSocketService); - TestBed.inject(FeaturesServiceToken); apolloMock.use.and.returnValues(undefined, { subscribe: () => of({}) }); - isOnSpy.and.returnValues(of(true)); }); afterEach(() => { @@ -115,22 +105,4 @@ describe('WebSocketService', () => { expect(apolloMock.createNamed).toHaveBeenCalled(); expect(headers).toEqual(expectedHeaders); }); - - it('should create named client with the right authentication token when FF is off', async () => { - isOnSpy.and.returnValues(of(false)); - let headers = {}; - const expectedHeaders = { 'X-Authorization': 'Bearer testToken' }; - const apolloClientName = 'testClient'; - const subscriptionOptions: SubscriptionOptions = { query: gql(`subscription {testQuery}`) }; - const wsOptions = { apolloClientName, wsUrl: 'testUrl', subscriptionOptions }; - apolloMock.createNamed.and.callFake((_, options) => { - headers = options.headers; - }); - - await lastValueFrom(service.getSubscription(wsOptions)); - - expect(apolloMock.use).toHaveBeenCalledTimes(2); - expect(apolloMock.createNamed).toHaveBeenCalled(); - expect(headers).toEqual(expectedHeaders); - }); }); diff --git a/lib/process-services-cloud/src/lib/services/web-socket.service.ts b/lib/process-services-cloud/src/lib/services/web-socket.service.ts index 99913001b4..f84ac9ef5f 100644 --- a/lib/process-services-cloud/src/lib/services/web-socket.service.ts +++ b/lib/process-services-cloud/src/lib/services/web-socket.service.ts @@ -16,7 +16,7 @@ */ import { createClient } from 'graphql-ws'; -import { inject, Inject, Injectable, Optional } from '@angular/core'; +import { inject, Injectable } from '@angular/core'; import { GraphQLWsLink } from '@apollo/client/link/subscriptions'; import { WebSocketLink } from '@apollo/client/link/ws'; import { @@ -37,9 +37,8 @@ import { Kind, OperationTypeNode } from 'graphql'; import { onError } from '@apollo/client/link/error'; import { RetryLink } from '@apollo/client/link/retry'; import { getMainDefinition } from '@apollo/client/utilities'; -import { switchMap, take, tap } from 'rxjs/operators'; +import { take } from 'rxjs/operators'; import { AppConfigService, AuthenticationService } from '@alfresco/adf-core'; -import { FeaturesServiceToken, IFeaturesService } from '@alfresco/adf-core/feature-flags'; interface serviceOptions { apolloClientName: string; @@ -53,16 +52,11 @@ interface serviceOptions { }) export class WebSocketService { private appConfigService = inject(AppConfigService); - private subscriptionProtocol: 'graphql-ws' | 'transport-ws' = 'transport-ws'; + private subscriptionProtocol = 'graphql-ws'; private wsLink: GraphQLWsLink | WebSocketLink; private httpLinkHandler: HttpLinkHandler; - constructor( - private readonly apollo: Apollo, - private readonly httpLink: HttpLink, - private readonly authService: AuthenticationService, - @Optional() @Inject(FeaturesServiceToken) private featuresService: IFeaturesService - ) {} + constructor(private readonly apollo: Apollo, private readonly httpLink: HttpLink, private readonly authService: AuthenticationService) {} public getSubscription(options: serviceOptions): Observable> { const { apolloClientName, subscriptionOptions } = options; @@ -72,19 +66,10 @@ export class WebSocketService { } }); - return this.featuresService.isOn$('studio-ws-graphql-subprotocol').pipe( - tap((isOn) => { - if (isOn) { - this.subscriptionProtocol = 'graphql-ws'; - } - }), - switchMap(() => { - if (this.apollo.use(apolloClientName) === undefined) { - this.initSubscriptions(options); - } - return this.apollo.use(apolloClientName).subscribe({ errorPolicy: 'all', ...subscriptionOptions }); - }) - ); + if (this.apollo.use(apolloClientName) === undefined) { + this.initSubscriptions(options); + } + return this.apollo.use(apolloClientName).subscribe({ errorPolicy: 'all', ...subscriptionOptions }); } private get contextRoot() { @@ -106,16 +91,7 @@ export class WebSocketService { } private initSubscriptions(options: serviceOptions): void { - switch (this.subscriptionProtocol) { - case 'graphql-ws': - this.createGraphQLWsLink(options); - break; - case 'transport-ws': - this.createTransportWsLink(options); - break; - default: - throw new Error('Unknown subscription protocol'); - } + this.createGraphQLWsLink(options); this.createHttpLinkHandler(options); @@ -175,20 +151,6 @@ export class WebSocketService { }); } - private createTransportWsLink(options: serviceOptions): void { - this.wsLink = new WebSocketLink({ - uri: this.createWsUrl(options.wsUrl) + '/ws/graphql', - options: { - reconnect: true, - lazy: true, - connectionParams: { - kaInterval: 2000, - 'X-Authorization': 'Bearer ' + this.authService.getToken() - } - } - }); - } - private createGraphQLWsLink(options: serviceOptions): void { this.wsLink = new GraphQLWsLink( createClient({ diff --git a/package-lock.json b/package-lock.json index 662e2c362b..4cc8a56aab 100644 --- a/package-lock.json +++ b/package-lock.json @@ -20,7 +20,7 @@ "@angular/platform-browser": "17.1.3", "@angular/platform-browser-dynamic": "17.1.3", "@angular/router": "17.1.3", - "@apollo/client": "3.11.4", + "@apollo/client": "^3.13.4", "@cspell/eslint-plugin": "8.16.1", "@mat-datetimepicker/core": "13.0.2", "@ngx-translate/core": "^14.0.0", @@ -41,7 +41,6 @@ "pdfjs-dist": "3.3.122", "raphael": "2.3.0", "rxjs": "7.8.1", - "subscriptions-transport-ws": "^0.11.0", "superagent": "^9.0.1", "ts-morph": "^20.0.0", "tslib": "2.8.1", @@ -1416,9 +1415,9 @@ } }, "node_modules/@apollo/client": { - "version": "3.11.4", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.11.4.tgz", - "integrity": "sha512-bmgYKkULpym8wt8aXlAZ1heaYo0skLJ5ru0qJ+JCRoo03Pe+yIDbBCnqlDw6Mjj76hFkDw3HwFMgZC2Hxp30Mg==", + "version": "3.13.4", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.13.4.tgz", + "integrity": "sha512-Ot3RaN2M/rhIKDqXBdOVlN0dQbHydUrYJ9lTxkvd6x7W1pAjwduUccfoz2gsO4U9by7oWtRj/ySF0MFNUp+9Aw==", "license": "MIT", "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", @@ -1430,7 +1429,6 @@ "optimism": "^0.18.0", "prop-types": "^15.7.2", "rehackt": "^0.1.0", - "response-iterator": "^0.2.6", "symbol-observable": "^4.0.0", "ts-invariant": "^0.10.3", "tslib": "^2.3.0", @@ -1438,9 +1436,9 @@ }, "peerDependencies": { "graphql": "^15.0.0 || ^16.0.0", - "graphql-ws": "^5.5.5", - "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0", - "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc <19.0.0", + "graphql-ws": "^5.5.5 || ^6.0.3", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || >=19.0.0-rc", "subscriptions-transport-ws": "^0.9.0 || ^0.11.0" }, "peerDependenciesMeta": { @@ -20273,7 +20271,9 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz", "integrity": "sha512-zj6Z6M7Eq+PBZ7PQxl5NT665MvJdAkzp0f60nAJ+sLaSCBPMwVak5ZegFbgVCzFcCJTKFoMizvM5Ld7+JrRJHA==", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/balanced-match": { "version": "1.0.2", @@ -27414,7 +27414,9 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/iterall/-/iterall-1.3.0.tgz", "integrity": "sha512-QZ9qOMdF+QLHxy1QIpUHUU1D5pS2CG2P69LF6L6CPjPYA/XMOmKV3PZpawHoAjHNyB0swdVTRxdYT4tbBbxqwg==", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/jackspeak": { "version": "3.4.3", @@ -35599,15 +35601,6 @@ "node": ">=10" } }, - "node_modules/response-iterator": { - "version": "0.2.20", - "resolved": "https://registry.npmjs.org/response-iterator/-/response-iterator-0.2.20.tgz", - "integrity": "sha512-RfNi9saiJ9VKznrRZEGZtlfeiQI7NWMUlXvmkvO60xaHfW1y+36EOibZkV59LuKNak8VIqL6IyxYxhMOGTurIQ==", - "license": "MIT", - "engines": { - "node": ">=0.8" - } - }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", @@ -37865,6 +37858,8 @@ "integrity": "sha512-8D4C6DIH5tGiAIpp5I0wD/xRlNiZAPGHygzCe7VzyzUoxHtawzjNAY9SUTXU05/EY2NMY9/9GF0ycizkXr1CWQ==", "deprecated": "The `subscriptions-transport-ws` package is no longer maintained. We recommend you use `graphql-ws` instead. For help migrating Apollo software to `graphql-ws`, see https://www.apollographql.com/docs/apollo-server/data/subscriptions/#switching-from-subscriptions-transport-ws For general help using `graphql-ws`, see https://github.com/enisdenjo/graphql-ws/blob/master/README.md", "license": "MIT", + "optional": true, + "peer": true, "dependencies": { "backo2": "^1.0.2", "eventemitter3": "^3.1.0", @@ -37880,13 +37875,17 @@ "version": "3.1.2", "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-3.1.2.tgz", "integrity": "sha512-tvtQIeLVHjDkJYnzf2dgVMxfuSGJeM/7UCG17TT4EumTfNtF+0nebF/4zWOIkCreAbtNqhGEboB6BWrwqNaw4Q==", - "license": "MIT" + "license": "MIT", + "optional": true, + "peer": true }, "node_modules/subscriptions-transport-ws/node_modules/symbol-observable": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz", "integrity": "sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ==", "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=0.10.0" } @@ -37896,6 +37895,8 @@ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", "license": "MIT", + "optional": true, + "peer": true, "engines": { "node": ">=8.3.0" }, diff --git a/package.json b/package.json index fd10f437de..ef93d2e071 100644 --- a/package.json +++ b/package.json @@ -40,7 +40,7 @@ "@angular/platform-browser": "17.1.3", "@angular/platform-browser-dynamic": "17.1.3", "@angular/router": "17.1.3", - "@apollo/client": "3.11.4", + "@apollo/client": "^3.13.4", "@cspell/eslint-plugin": "8.16.1", "@mat-datetimepicker/core": "13.0.2", "@ngx-translate/core": "^14.0.0", @@ -61,7 +61,6 @@ "pdfjs-dist": "3.3.122", "raphael": "2.3.0", "rxjs": "7.8.1", - "subscriptions-transport-ws": "^0.11.0", "superagent": "^9.0.1", "ts-morph": "^20.0.0", "tslib": "2.8.1", @@ -95,13 +94,12 @@ "@nx/workspace": "17.3.1", "@paperist/types-remark": "0.1.3", "@playwright/test": "1.46.1", - "@valano/change-font-size": "^1.0.0", "@schematics/angular": "17.1.4", "@storybook/addon-essentials": "8.4.7", + "@storybook/addon-interactions": "8.4.7", "@storybook/angular": "^8.4.6", "@storybook/core-server": "8.4.7", "@storybook/manager-api": "^8.4.5", - "@storybook/addon-interactions": "8.4.7", "@storybook/theming": "^8.2.9", "@types/ejs": "^3.1.5", "@types/event-emitter": "^0.3.3", @@ -119,6 +117,7 @@ "@typescript-eslint/parser": "6.21.0", "@typescript-eslint/typescript-estree": "7.1.1", "@typescript-eslint/utils": "^8.8.1", + "@valano/change-font-size": "^1.0.0", "ajv": "^8.12.0", "commander": "12.0.0", "css-loader": "^7.1.2",