diff --git a/gulpfile.js b/gulpfile.js index 959cf46c05..d058227482 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -76,9 +76,6 @@ gulp.task('compile', function() { // Compile Typescript into .js and .d.ts files .pipe(buildProject()) - // Replace SDK version - .pipe(replace(/\/g, pkg.version)) - // Add header .pipe(header(banner)) diff --git a/src/auth/auth-api-request.ts b/src/auth/auth-api-request.ts index 359bc90c4d..cf0df17b92 100644 --- a/src/auth/auth-api-request.ts +++ b/src/auth/auth-api-request.ts @@ -44,7 +44,7 @@ import { Tenant, TenantOptions, TenantServerResponse } from './tenant'; /** Firebase Auth request header. */ const FIREBASE_AUTH_HEADER = { - 'X-Client-Version': 'Node/Admin/', + 'X-Client-Version': `Node/Admin/${utils.getSdkVersion()}`, }; /** Firebase Auth request timeout duration in milliseconds. */ const FIREBASE_AUTH_TIMEOUT = 25000; diff --git a/src/database/database.ts b/src/database/database.ts index cb013e6469..686120909d 100644 --- a/src/database/database.ts +++ b/src/database/database.ts @@ -8,6 +8,7 @@ import { Database } from '@firebase/database'; import * as validator from '../utils/validator'; import { AuthorizedHttpClient, HttpRequestConfig, HttpError } from '../utils/api-request'; +import { getSdkVersion } from '../utils/index'; /** @@ -78,8 +79,7 @@ export class DatabaseService implements FirebaseServiceInterface { let db: Database = this.INTERNAL.databases[dbUrl]; if (typeof db === 'undefined') { const rtdb = require('@firebase/database'); // eslint-disable-line @typescript-eslint/no-var-requires - const { version } = require('../../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires - db = rtdb.initStandalone(this.appInternal, dbUrl, version).instance; + db = rtdb.initStandalone(this.appInternal, dbUrl, getSdkVersion()).instance; const rulesClient = new DatabaseRulesClient(this.app, dbUrl); db.getRules = () => { diff --git a/src/firebase-namespace.ts b/src/firebase-namespace.ts index a9caf80802..916132ebbf 100644 --- a/src/firebase-namespace.ts +++ b/src/firebase-namespace.ts @@ -39,6 +39,7 @@ import { SecurityRules } from './security-rules/security-rules'; import { RemoteConfig } from './remote-config/remote-config'; import * as validator from './utils/validator'; +import { getSdkVersion } from './utils/index'; const DEFAULT_APP_NAME = '[DEFAULT]'; @@ -309,7 +310,7 @@ export class FirebaseNamespace { /* tslint:enable:variable-name */ public credential = firebaseCredential; - public SDK_VERSION = ''; + public SDK_VERSION = getSdkVersion(); public INTERNAL: FirebaseNamespaceInternals; /* tslint:disable */ diff --git a/src/machine-learning/machine-learning-api-client.ts b/src/machine-learning/machine-learning-api-client.ts index 56b47118c7..4e7a1a7383 100644 --- a/src/machine-learning/machine-learning-api-client.ts +++ b/src/machine-learning/machine-learning-api-client.ts @@ -23,7 +23,7 @@ import { FirebaseApp } from '../firebase-app'; const ML_V1BETA2_API = 'https://firebaseml.googleapis.com/v1beta2'; const FIREBASE_VERSION_HEADER = { - 'X-Firebase-Client': 'fire-admin-node/', + 'X-Firebase-Client': `fire-admin-node/${utils.getSdkVersion()}`, }; export interface StatusErrorResponse { diff --git a/src/messaging/messaging-api-request.ts b/src/messaging/messaging-api-request.ts index 6a44ac67f6..65b9944a04 100644 --- a/src/messaging/messaging-api-request.ts +++ b/src/messaging/messaging-api-request.ts @@ -21,16 +21,17 @@ import { import { createFirebaseError, getErrorCode } from './messaging-errors'; import { SubRequest, BatchRequestClient } from './batch-request'; import { SendResponse, BatchResponse } from './messaging-types'; +import { getSdkVersion } from '../utils/index'; // FCM backend constants const FIREBASE_MESSAGING_TIMEOUT = 10000; const FIREBASE_MESSAGING_BATCH_URL = 'https://fcm.googleapis.com/batch'; const FIREBASE_MESSAGING_HTTP_METHOD: HttpMethod = 'POST'; const FIREBASE_MESSAGING_HEADERS = { - 'X-Firebase-Client': 'fire-admin-node/', + 'X-Firebase-Client': `fire-admin-node/${getSdkVersion()}`, }; const LEGACY_FIREBASE_MESSAGING_HEADERS = { - 'X-Firebase-Client': 'fire-admin-node/', + 'X-Firebase-Client': `fire-admin-node/${getSdkVersion()}`, 'access_token_auth': 'true', }; diff --git a/src/project-management/project-management-api-request.ts b/src/project-management/project-management-api-request.ts index c7528f9157..95dcb76a56 100644 --- a/src/project-management/project-management-api-request.ts +++ b/src/project-management/project-management-api-request.ts @@ -21,6 +21,7 @@ import { import { FirebaseProjectManagementError, ProjectManagementErrorCode } from '../utils/error'; import * as validator from '../utils/validator'; import { ShaCertificate } from './android-app'; +import { getSdkVersion } from '../utils/index'; /** Project management backend host and port. */ const PROJECT_MANAGEMENT_HOST_AND_PORT = 'firebase.googleapis.com:443'; @@ -30,7 +31,7 @@ const PROJECT_MANAGEMENT_PATH = '/v1/'; const PROJECT_MANAGEMENT_BETA_PATH = '/v1beta1/'; /** Project management request header. */ const PROJECT_MANAGEMENT_HEADERS = { - 'X-Client-Version': 'Node/Admin/', + 'X-Client-Version': `Node/Admin/${getSdkVersion()}`, }; /** Project management request timeout duration in milliseconds. */ const PROJECT_MANAGEMENT_TIMEOUT_MILLIS = 10000; diff --git a/src/remote-config/remote-config-api-client.ts b/src/remote-config/remote-config-api-client.ts index ed1d4d759f..26bd1b8931 100644 --- a/src/remote-config/remote-config-api-client.ts +++ b/src/remote-config/remote-config-api-client.ts @@ -25,7 +25,7 @@ import { deepCopy } from '../utils/deep-copy'; // Remote Config backend constants const FIREBASE_REMOTE_CONFIG_V1_API = 'https://firebaseremoteconfig.googleapis.com/v1'; const FIREBASE_REMOTE_CONFIG_HEADERS = { - 'X-Firebase-Client': 'fire-admin-node/', + 'X-Firebase-Client': `fire-admin-node/${utils.getSdkVersion()}`, // There is a known issue in which the ETag is not properly returned in cases where the request // does not specify a compression type. Currently, it is required to include the header // `Accept-Encoding: gzip` or equivalent in all requests. diff --git a/src/security-rules/security-rules-api-client.ts b/src/security-rules/security-rules-api-client.ts index 87e379513f..5048113825 100644 --- a/src/security-rules/security-rules-api-client.ts +++ b/src/security-rules/security-rules-api-client.ts @@ -23,7 +23,7 @@ import { FirebaseApp } from '../firebase-app'; const RULES_V1_API = 'https://firebaserules.googleapis.com/v1'; const FIREBASE_VERSION_HEADER = { - 'X-Firebase-Client': 'fire-admin-node/', + 'X-Firebase-Client': `fire-admin-node/${utils.getSdkVersion()}`, }; export interface Release { diff --git a/src/utils/index.ts b/src/utils/index.ts index f3f75d6d80..8c3a540dc0 100644 --- a/src/utils/index.ts +++ b/src/utils/index.ts @@ -19,6 +19,16 @@ import { ServiceAccountCredential, ComputeEngineCredential } from '../auth/crede import * as validator from './validator'; +let sdkVersion: string; + +export function getSdkVersion(): string { + if (!sdkVersion) { + const { version } = require('../../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires + sdkVersion = version; + } + return sdkVersion; +} + /** * Renames properties on an object given a mapping from old to new property names. * diff --git a/test/unit/auth/auth-api-request.spec.ts b/test/unit/auth/auth-api-request.spec.ts index 98e8781d7d..3599aac026 100644 --- a/test/unit/auth/auth-api-request.spec.ts +++ b/test/unit/auth/auth-api-request.spec.ts @@ -47,6 +47,7 @@ import { UserIdentifier } from '../../../src/auth/identifier'; import { TenantOptions } from '../../../src/auth/tenant'; import { UpdateRequest, UpdateMultiFactorInfoRequest } from '../../../src/auth/user-record'; import { expectUserImportResult } from './user-import-builder.spec'; +import { getSdkVersion } from '../../../src/utils/index'; chai.should(); chai.use(sinonChai); @@ -849,7 +850,7 @@ AUTH_REQUEST_HANDLER_TESTS.forEach((handler) => { let getTokenStub: sinon.SinonStub; const mockAccessToken: string = utils.generateRandomAccessToken(); const expectedHeaders: {[key: string]: string} = { - 'X-Client-Version': 'Node/Admin/', + 'X-Client-Version': `Node/Admin/${getSdkVersion()}`, 'Authorization': 'Bearer ' + mockAccessToken, }; const callParams = (path: string, method: any, data: any): HttpRequestConfig => { diff --git a/test/unit/firebase-namespace.spec.ts b/test/unit/firebase-namespace.spec.ts index 2c3a7b2dc1..60b26ff91d 100644 --- a/test/unit/firebase-namespace.spec.ts +++ b/test/unit/firebase-namespace.spec.ts @@ -52,6 +52,7 @@ import { InstanceId } from '../../src/instance-id/instance-id'; import { ProjectManagement } from '../../src/project-management/project-management'; import { SecurityRules } from '../../src/security-rules/security-rules'; import { RemoteConfig } from '../../src/remote-config/remote-config'; +import { getSdkVersion } from '../../src/utils/index'; chai.should(); chai.use(sinonChai); @@ -73,7 +74,7 @@ describe('FirebaseNamespace', () => { describe('#SDK_VERSION', () => { it('should return the SDK version', () => { - expect(firebaseNamespace.SDK_VERSION).to.equal(''); + expect(firebaseNamespace.SDK_VERSION).to.equal(getSdkVersion()); }); }); diff --git a/test/unit/machine-learning/machine-learning-api-client.spec.ts b/test/unit/machine-learning/machine-learning-api-client.spec.ts index 69f5f1d877..aa2dc536d6 100644 --- a/test/unit/machine-learning/machine-learning-api-client.spec.ts +++ b/test/unit/machine-learning/machine-learning-api-client.spec.ts @@ -27,6 +27,7 @@ import * as utils from '../utils'; import * as mocks from '../../resources/mocks'; import { FirebaseAppError } from '../../../src/utils/error'; import { FirebaseApp } from '../../../src/firebase-app'; +import { getSdkVersion } from '../../../src/utils/index'; const expect = chai.expect; @@ -86,7 +87,7 @@ describe('MachineLearningApiClient', () => { }; const EXPECTED_HEADERS = { 'Authorization': 'Bearer mock-token', - 'X-Firebase-Client': 'fire-admin-node/', + 'X-Firebase-Client': `fire-admin-node/${getSdkVersion()}`, }; const noProjectId = 'Failed to determine project ID. Initialize the SDK with service ' + 'account credentials, or set project ID as an app option. Alternatively, set the ' diff --git a/test/unit/messaging/messaging.spec.ts b/test/unit/messaging/messaging.spec.ts index 69453a216e..b99542278d 100644 --- a/test/unit/messaging/messaging.spec.ts +++ b/test/unit/messaging/messaging.spec.ts @@ -35,6 +35,7 @@ import { Messaging, BLACKLISTED_OPTIONS_KEYS, BLACKLISTED_DATA_PAYLOAD_KEYS, } from '../../../src/messaging/messaging'; import { HttpClient } from '../../../src/utils/api-request'; +import { getSdkVersion } from '../../../src/utils/index'; chai.should(); chai.use(sinonChai); @@ -321,7 +322,7 @@ describe('Messaging', () => { const mockAccessToken: string = utils.generateRandomAccessToken(); const expectedHeaders = { 'Authorization': 'Bearer ' + mockAccessToken, - 'X-Firebase-Client': 'fire-admin-node/', + 'X-Firebase-Client': `fire-admin-node/${getSdkVersion()}`, 'access_token_auth': 'true', }; const emptyResponse = utils.responseFrom({}); diff --git a/test/unit/project-management/project-management-api-request.spec.ts b/test/unit/project-management/project-management-api-request.spec.ts index f2978b4a34..dcffb29b76 100644 --- a/test/unit/project-management/project-management-api-request.spec.ts +++ b/test/unit/project-management/project-management-api-request.spec.ts @@ -26,6 +26,7 @@ import { ProjectManagementRequestHandler } from '../../../src/project-management import { HttpClient } from '../../../src/utils/api-request'; import * as mocks from '../../resources/mocks'; import * as utils from '../utils'; +import { getSdkVersion } from '../../../src/utils/index'; import { ShaCertificate } from '../../../src/project-management/android-app'; import { AppPlatform } from '../../../src/project-management/app-metadata'; @@ -72,7 +73,7 @@ describe('ProjectManagementRequestHandler', () => { beforeEach(() => { mockApp = mocks.app(); expectedHeaders = { - 'X-Client-Version': 'Node/Admin/', + 'X-Client-Version': `Node/Admin/${getSdkVersion()}`, 'Authorization': 'Bearer ' + mockAccessToken, }; requestHandler = new ProjectManagementRequestHandler(mockApp); diff --git a/test/unit/remote-config/remote-config-api-client.spec.ts b/test/unit/remote-config/remote-config-api-client.spec.ts index 9543b3b957..0561d0d40b 100644 --- a/test/unit/remote-config/remote-config-api-client.spec.ts +++ b/test/unit/remote-config/remote-config-api-client.spec.ts @@ -33,6 +33,7 @@ import * as mocks from '../../resources/mocks'; import { FirebaseAppError } from '../../../src/utils/error'; import { FirebaseApp } from '../../../src/firebase-app'; import { deepCopy } from '../../../src/utils/deep-copy'; +import { getSdkVersion } from '../../../src/utils/index'; const expect = chai.expect; @@ -53,7 +54,7 @@ describe('RemoteConfigApiClient', () => { const EXPECTED_HEADERS = { 'Authorization': 'Bearer mock-token', - 'X-Firebase-Client': 'fire-admin-node/', + 'X-Firebase-Client': `fire-admin-node/${getSdkVersion()}`, 'Accept-Encoding': 'gzip', }; diff --git a/test/unit/security-rules/security-rules-api-client.spec.ts b/test/unit/security-rules/security-rules-api-client.spec.ts index 6ffa7d9c3d..81b4472dc2 100644 --- a/test/unit/security-rules/security-rules-api-client.spec.ts +++ b/test/unit/security-rules/security-rules-api-client.spec.ts @@ -26,6 +26,7 @@ import * as utils from '../utils'; import * as mocks from '../../resources/mocks'; import { FirebaseAppError } from '../../../src/utils/error'; import { FirebaseApp } from '../../../src/firebase-app'; +import { getSdkVersion } from '../../../src/utils/index'; const expect = chai.expect; @@ -42,7 +43,7 @@ describe('SecurityRulesApiClient', () => { }; const EXPECTED_HEADERS = { 'Authorization': 'Bearer mock-token', - 'X-Firebase-Client': 'fire-admin-node/', + 'X-Firebase-Client': `fire-admin-node/${getSdkVersion()}`, }; const noProjectId = 'Failed to determine project ID. Initialize the SDK with service ' + 'account credentials, or set project ID as an app option. Alternatively, set the ' diff --git a/test/unit/utils/index.spec.ts b/test/unit/utils/index.spec.ts index 1cd683de48..acb76f074a 100644 --- a/test/unit/utils/index.spec.ts +++ b/test/unit/utils/index.spec.ts @@ -29,11 +29,19 @@ import { ComputeEngineCredential } from '../../../src/auth/credential'; import { HttpClient } from '../../../src/utils/api-request'; import * as utils from '../utils'; import { FirebaseAppError } from '../../../src/utils/error'; +import { getSdkVersion } from '../../../src/utils/index'; interface Obj { [key: string]: any; } +describe('SDK_VERSION', () => { + it('utils index should retrieve the SDK_VERSION from package.json', () => { + const { version } = require('../../../package.json'); // eslint-disable-line @typescript-eslint/no-var-requires + expect(getSdkVersion()).to.equal(version); + }); +}); + describe('addReadonlyGetter()', () => { it('should add a new property to the provided object', () => { const obj: Obj = {};