Skip to content
Open
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
7 changes: 4 additions & 3 deletions etc/firebase-admin.remote-config.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ export interface ExplicitParameterValue {
value: string;
}

// @public
// @public @deprecated
export interface FetchResponseData {
config?: {
[key: string]: string;
Expand Down Expand Up @@ -236,10 +236,11 @@ export const RemoteConfigErrorCode: {
// @public
export type RemoteConfigErrorCode = typeof RemoteConfigErrorCode[keyof typeof RemoteConfigErrorCode];

// @public
// @public @deprecated
export class RemoteConfigFetchResponse {
// @deprecated
constructor(app: App, serverConfig: ServerConfig, requestEtag?: string);
// (undocumented)
// @deprecated (undocumented)
toJSON(): FetchResponseData;
}

Expand Down
4 changes: 4 additions & 0 deletions src/remote-config/remote-config-api.ts
Original file line number Diff line number Diff line change
Expand Up @@ -879,6 +879,10 @@ export interface ServerConfig {
/**
* JSON-serializable representation of evaluated config values. This can be consumed by
* Remote Config web client SDKs.
*
* @deprecated Remote Config server-side rendering (SSR) hydration of the
* client SDK is no longer supported. This type will be removed in the
* next major release.
*/
export interface FetchResponseData {
/**
Expand Down
23 changes: 23 additions & 0 deletions src/remote-config/remote-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -704,8 +704,14 @@ class VersionImpl implements Version {
const HTTP_NOT_MODIFIED = 304;
const HTTP_OK = 200;

let fetchResponseDeprecationWarned = false;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Using a global module-level variable fetchResponseDeprecationWarned to track whether the deprecation warning has been logged makes the unit tests order-dependent and fragile. If other tests instantiate RemoteConfigFetchResponse before the deprecation test runs, or if a single test is run in isolation (e.g., using it.only), the deprecation warning test will fail because the warning will not be logged again.

To make the tests robust and independent, we can store this state as a private static property on the RemoteConfigFetchResponse class and reset it in the test suite's beforeEach hook.


/**
* Represents a fetch response that can be used to interact with RC's client SDK.
*
* @deprecated Remote Config server-side rendering (SSR) hydration of the
* client SDK is no longer supported. This class will be removed in the
* next major release.
*/
export class RemoteConfigFetchResponse {
private response: FetchResponseData;
Expand All @@ -714,8 +720,21 @@ export class RemoteConfigFetchResponse {
* @param app - The app for this RemoteConfig service.
* @param serverConfig - The server config for which to generate a fetch response.
* @param requestEtag - A request eTag with which to compare the current response.
*
* @deprecated Remote Config server-side rendering (SSR) hydration of the
* client SDK is no longer supported. This class will be removed in the
* next major release.
*/
constructor(app: App, serverConfig: ServerConfig, requestEtag?: string) {
if (!fetchResponseDeprecationWarned) {
fetchResponseDeprecationWarned = true;
console.warn(
'RemoteConfigFetchResponse is deprecated and will be removed in the next major ' +
'release. Remote Config server-side rendering (SSR) hydration of the client SDK ' +
'is no longer supported.'
);
}
Comment on lines +729 to +736

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Update the constructor to use the class's static property RemoteConfigFetchResponse.deprecationWarned instead of the global module-level variable. This allows the warning state to be reset between tests. Note that you should also add private static deprecationWarned = false; inside the RemoteConfigFetchResponse class definition.

Suggested change
if (!fetchResponseDeprecationWarned) {
fetchResponseDeprecationWarned = true;
console.warn(
'RemoteConfigFetchResponse is deprecated and will be removed in the next major ' +
'release. Remote Config server-side rendering (SSR) hydration of the client SDK ' +
'is no longer supported.'
);
}
if (!RemoteConfigFetchResponse.deprecationWarned) {
RemoteConfigFetchResponse.deprecationWarned = true;
console.warn(
'RemoteConfigFetchResponse is deprecated and will be removed in the next major ' +
'release. Remote Config server-side rendering (SSR) hydration of the client SDK ' +
'is no longer supported.'
);
}


const config: { [key: string]: string } = {};
for (const [param, value] of Object.entries(serverConfig.getAll())) {
config[param] = value.asString();
Expand All @@ -740,6 +759,10 @@ export class RemoteConfigFetchResponse {
/**
* @returns JSON representation of the fetch response that can be consumed
* by the RC client SDK.
*
* @deprecated Remote Config server-side rendering (SSR) hydration of the
* client SDK is no longer supported. This method will be removed in the
* next major release.
*/
public toJSON(): FetchResponseData {
return this.response;
Expand Down
21 changes: 21 additions & 0 deletions test/unit/remote-config/remote-config.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1585,6 +1585,27 @@ describe('RemoteConfig', () => {
});

describe('RemoteConfigFetchResponse', () => {
let warnStub: sinon.SinonStub;

beforeEach(() => {
warnStub = sinon.stub(console, 'warn');
});
Comment on lines +1590 to +1592

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

Reset the static deprecationWarned property on RemoteConfigFetchResponse before each test to ensure that tests are completely isolated and independent of execution order.

Suggested change
beforeEach(() => {
warnStub = sinon.stub(console, 'warn');
});
beforeEach(() => {
warnStub = sinon.stub(console, 'warn');
(RemoteConfigFetchResponse as any).deprecationWarned = false;
});


afterEach(() => {
warnStub.restore();
});

// This test must run before any other construction of RemoteConfigFetchResponse
// in this process, since the deprecation warning is emitted only once per process.
it('should log a deprecation warning only once', () => {
const templateData = deepCopy(SERVER_REMOTE_CONFIG_RESPONSE) as ServerTemplateData;
const template = remoteConfig.initServerTemplate({ template: templateData });
new RemoteConfigFetchResponse(mockApp, template.evaluate());
new RemoteConfigFetchResponse(mockApp, template.evaluate());
expect(warnStub).to.have.been.calledOnce;
expect(warnStub.firstCall.args[0]).to.include('RemoteConfigFetchResponse is deprecated');
});

it('should return a 200 response when supplied with no etag', () => {
const templateData = deepCopy(SERVER_REMOTE_CONFIG_RESPONSE) as ServerTemplateData;
// Defines remote parameter values.
Expand Down
Loading