From df7a2717e63e6515b8ac46c6cc5ed106ca32ea76 Mon Sep 17 00:00:00 2001 From: Harshi-Shah-CS Date: Wed, 5 Nov 2025 18:02:18 +0530 Subject: [PATCH] fix: suppress error message in non-development environments --- package-lock.json | 8 +- package.json | 2 +- src/util/apollo-client.ts | 38 +++++++++ src/util/logs-polling-utilities.ts | 71 +++++++++++++++- test/unit/util/apollo-client.test.ts | 121 +++++++++++++++++++++++++++ 5 files changed, 231 insertions(+), 9 deletions(-) create mode 100644 test/unit/util/apollo-client.test.ts diff --git a/package-lock.json b/package-lock.json index 38cb32a..03819d3 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,7 +9,7 @@ "version": "1.9.3", "license": "MIT", "dependencies": { - "@apollo/client": "^3.11.8", + "@apollo/client": "^3.14.0", "@contentstack/cli-command": "^1.4.0", "@contentstack/cli-utilities": "^1.12.0", "@oclif/core": "^4.2.7", @@ -81,9 +81,9 @@ } }, "node_modules/@apollo/client": { - "version": "3.13.8", - "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.13.8.tgz", - "integrity": "sha512-YM9lQpm0VfVco4DSyKooHS/fDTiKQcCHfxr7i3iL6a0kP/jNO5+4NFK6vtRDxaYisd5BrwOZHLJpPBnvRVpKPg==", + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/@apollo/client/-/client-3.14.0.tgz", + "integrity": "sha512-0YQKKRIxiMlIou+SekQqdCo0ZTHxOcES+K8vKB53cIDpwABNR0P0yRzPgsbgcj3zRJniD93S/ontsnZsCLZrxQ==", "license": "MIT", "dependencies": { "@graphql-typed-document-node/core": "^3.1.1", diff --git a/package.json b/package.json index 77ee471..a8c665e 100755 --- a/package.json +++ b/package.json @@ -20,7 +20,7 @@ "/oclif.manifest.json" ], "dependencies": { - "@apollo/client": "^3.11.8", + "@apollo/client": "^3.14.0", "@contentstack/cli-command": "^1.4.0", "@contentstack/cli-utilities": "^1.12.0", "@oclif/core": "^4.2.7", diff --git a/src/util/apollo-client.ts b/src/util/apollo-client.ts index 205ea7c..1224fbc 100755 --- a/src/util/apollo-client.ts +++ b/src/util/apollo-client.ts @@ -13,12 +13,50 @@ import { Operation, ApolloClient, InMemoryCache, + setLogVerbosity, } from '@apollo/client/core'; import { cliux as ux, authHandler, configHandler } from '@contentstack/cli-utilities'; import config from '../config'; import { GraphqlApiClientInput } from '../types'; +export const isNotDevelopment = process.env.NODE_ENV !== 'development'; + +function isApolloMessage(message: string): boolean { + return ( + message.includes('go.apollo.dev/c/err') || + message.includes('cache.diff') || + message.includes('canonizeResults') + ); +} + +if (isNotDevelopment) { + try { + setLogVerbosity('silent'); + } catch {} + + const originalError = console.error; + const originalWarn = console.warn; + + console.error = (...args: any[]) => { + const message = args[0]?.toString() || ''; + + if (isApolloMessage(message)) { + return; + } + originalError.apply(console, args); + }; + + console.warn = (...args: any[]) => { + const message = args[0]?.toString() || ''; + + if (isApolloMessage(message)) { + return; + } + originalWarn.apply(console, args); + }; +} + export default class GraphqlApiClient { private authType: string; private cmaHost: string | undefined; diff --git a/src/util/logs-polling-utilities.ts b/src/util/logs-polling-utilities.ts index ae24782..68d33af 100755 --- a/src/util/logs-polling-utilities.ts +++ b/src/util/logs-polling-utilities.ts @@ -6,6 +6,7 @@ import { Ora } from 'ora'; import { LogPollingInput, ConfigType } from '../types'; import { deploymentQuery, deploymentLogsQuery, serverlessLogsQuery } from '../graphql'; import { setTimeout as sleep } from 'timers/promises'; +import { isNotDevelopment } from './apollo-client'; export default class LogPolling { private config: ConfigType; @@ -25,6 +26,61 @@ export default class LogPolling { if ($event) this.$event = $event; } + /** + * @method withDeprecationsDisabled - Helper to disable Apollo Client deprecation warnings + * + * Wraps the provided function so that Apollo deprecation warnings are disabled + * only during its execution, and restored immediately after. + */ + private withDeprecationsDisabled(fn: () => T): T { + + if (!isNotDevelopment) { + return fn(); + } + + let withDisabledDeprecations: any; + try { + withDisabledDeprecations = require('@apollo/client/utilities/deprecation').withDisabledDeprecations; + } catch { + return fn(); + } + + const handler = withDisabledDeprecations(); + try { + return fn(); + } finally { + this.disposeDeprecationHandler(handler); + } + } + + private disposeDeprecationHandler(handler?: any): void { + if (!handler) return; + try { + const dispose = (handler as any)[(Symbol as any).dispose]; + if (typeof dispose === 'function') { + dispose.call(handler); + return; + } + } catch {} + try { + const asyncDispose = (handler as any)[(Symbol as any).asyncDispose]; + if (typeof asyncDispose === 'function') { + asyncDispose.call(handler); + return; + } + } catch {} + try { + const symbols = Object.getOwnPropertySymbols(handler); + for (const sym of symbols) { + const maybeDispose = (handler as any)[sym]; + if (typeof maybeDispose === 'function') { + maybeDispose.call(handler); + break; + } + } + } catch {} + } + /** * @method getDeploymentStatus - deployment status polling * @@ -43,7 +99,8 @@ export default class LogPolling { }; } > { - const statusWatchQuery = this.apolloManageClient.watchQuery({ + return this.withDeprecationsDisabled(() => { + const statusWatchQuery = this.apolloManageClient.watchQuery({ fetchPolicy: 'network-only', query: deploymentQuery, variables: { @@ -55,7 +112,8 @@ export default class LogPolling { pollInterval: this.config.pollingInterval, errorPolicy: 'all', }); - return statusWatchQuery; + return statusWatchQuery; + }); } /** @@ -86,7 +144,8 @@ export default class LogPolling { statusWatchQuery.stopPolling(); } }); - const logsWatchQuery = this.apolloLogsClient.watchQuery({ + const logsWatchQuery = this.withDeprecationsDisabled(() => { + return this.apolloLogsClient.watchQuery({ fetchPolicy: 'network-only', query: deploymentLogsQuery, variables: { @@ -95,6 +154,7 @@ export default class LogPolling { pollInterval: this.config.pollingInterval, errorPolicy: 'all', }); + }); this.subscribeDeploymentLogs(logsWatchQuery); } @@ -180,7 +240,9 @@ export default class LogPolling { async serverLogs(): Promise { this.startTime = new Date().getTime() - 10 * 1000; this.endTime = new Date().getTime(); - const serverLogsWatchQuery = this.apolloLogsClient.watchQuery({ + + const serverLogsWatchQuery = this.withDeprecationsDisabled(() => { + return this.apolloLogsClient.watchQuery({ fetchPolicy: 'network-only', query: serverlessLogsQuery, variables: { @@ -194,6 +256,7 @@ export default class LogPolling { pollInterval: this.config.pollingInterval, errorPolicy: 'all', }); + }); this.subscribeServerLogs(serverLogsWatchQuery); } diff --git a/test/unit/util/apollo-client.test.ts b/test/unit/util/apollo-client.test.ts new file mode 100644 index 00000000..ff70684 --- /dev/null +++ b/test/unit/util/apollo-client.test.ts @@ -0,0 +1,121 @@ +//@ts-nocheck +import { describe, it, beforeEach, afterEach } from 'mocha'; +import { expect } from 'chai'; +import { createSandbox } from 'sinon'; + +describe('Apollo Client Console Suppression', () => { + let sandbox; + let originalEnv; + let originalError; + let originalWarn; + let modulePath; + + beforeEach(() => { + sandbox = createSandbox(); + originalEnv = process.env.NODE_ENV; + originalError = console.error; + originalWarn = console.warn; + modulePath = require.resolve('../../../src/util/apollo-client'); + }); + + afterEach(() => { + process.env.NODE_ENV = originalEnv; + console.error = originalError; + console.warn = originalWarn; + sandbox.restore(); + + if (require.cache[modulePath]) { + delete require.cache[modulePath]; + } + }); + + it('should show errors/warnings when NODE_ENV is development', () => { + process.env.NODE_ENV = 'development'; + + const errorSpy = sandbox.spy(); + const warnSpy = sandbox.spy(); + + delete require.cache[modulePath]; + + console.error = errorSpy; + console.warn = warnSpy; + + const apolloClientModule = require('../../../src/util/apollo-client'); + + expect(apolloClientModule.isNotDevelopment).to.be.false; + + const apolloErrorMsg = 'Error: go.apollo.dev/c/err/test'; + const apolloWarnMsg = 'Warning: cache.diff issue'; + const regularErrorMsg = 'Regular error message'; + const regularWarnMsg = 'Regular warning message'; + + console.error(apolloErrorMsg); + console.warn(apolloWarnMsg); + console.error(regularErrorMsg); + console.warn(regularWarnMsg); + + expect(errorSpy.callCount).to.equal(2); + expect(warnSpy.callCount).to.equal(2); + expect(errorSpy.calledWith(apolloErrorMsg)).to.be.true; + expect(errorSpy.calledWith(regularErrorMsg)).to.be.true; + expect(warnSpy.calledWith(apolloWarnMsg)).to.be.true; + expect(warnSpy.calledWith(regularWarnMsg)).to.be.true; + }); + + it('should suppress Apollo errors/warnings when NODE_ENV is not development', () => { + process.env.NODE_ENV = 'isNotDevelopment'; + + const originalErrorBefore = console.error; + const originalWarnBefore = console.warn; + + const errorSpy = sandbox.spy(originalErrorBefore); + const warnSpy = sandbox.spy(originalWarnBefore); + + console.error = errorSpy; + console.warn = warnSpy; + + delete require.cache[modulePath]; + + const apolloClientModule = require('../../../src/util/apollo-client'); + + expect(apolloClientModule.isNotDevelopment).to.be.true; + expect(console.error).to.not.equal(errorSpy); + expect(console.warn).to.not.equal(warnSpy); + + const apolloErrorMsg = 'Error: go.apollo.dev/c/err/test'; + const apolloWarnMsg = 'Warning: cache.diff issue'; + const apolloCanonizeMsg = 'Warning: canonizeResults deprecated'; + const regularErrorMsg = 'Regular error message'; + const regularWarnMsg = 'Regular warning message'; + + console.error(apolloErrorMsg); + console.warn(apolloWarnMsg); + console.warn(apolloCanonizeMsg); + console.error(regularErrorMsg); + console.warn(regularWarnMsg); + + const errorCalls = errorSpy.getCalls(); + const warnCalls = warnSpy.getCalls(); + + const regularErrorLogged = errorCalls.some((call) => + call.args[0] === regularErrorMsg || call.args[0]?.toString() === regularErrorMsg + ); + const regularWarnLogged = warnCalls.some((call) => + call.args[0] === regularWarnMsg || call.args[0]?.toString() === regularWarnMsg + ); + + expect(regularErrorLogged).to.be.true; + expect(regularWarnLogged).to.be.true; + + const apolloErrorLogged = errorCalls.some((call) => + call.args[0]?.toString().includes('go.apollo.dev/c/err') + ); + const apolloWarnLogged = warnCalls.some((call) => + call.args[0]?.toString().includes('cache.diff') || + call.args[0]?.toString().includes('canonizeResults') + ); + + expect(apolloErrorLogged).to.be.false; + expect(apolloWarnLogged).to.be.false; + }); +});