Skip to content
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,9 @@
"test:integration": "mocha test/integration/*.ts --slow 5000 --timeout 20000 --require ts-node/register",
"test:coverage": "nyc npm run test:unit",
"lint:src": "eslint src/ --ext .ts",
"lint:src:fix": "eslint src/ --ext .ts --fix",
"lint:test": "eslint test/ --ext .ts",
"lint:test:fix": "eslint test/ --ext .ts --fix",
"apidocs": "run-s api-extractor:local api-documenter",
"api-extractor": "node generate-reports.js",
"api-extractor:local": "npm run build && node generate-reports.js --local",
Expand Down
24 changes: 20 additions & 4 deletions src/data-connect/data-connect-api-client-internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,16 @@ const FIREBASE_DATA_CONNECT_EMULATOR_BASE_URL_FORMAT =
const EXECUTE_GRAPH_QL_ENDPOINT = 'executeGraphql';
const EXECUTE_GRAPH_QL_READ_ENDPOINT = 'executeGraphqlRead';

const DATA_CONNECT_CONFIG_HEADERS = {
'X-Firebase-Client': `fire-admin-node/${utils.getSdkVersion()}`
};
function getHeaders(isUsingGen: boolean): { [key: string]: string } {
const headerValue = {
'X-Firebase-Client': `fire-admin-node/${utils.getSdkVersion()}`,
'X-Goog-Api-Client': utils.getMetricsHeader(),
};
if (isUsingGen) {
headerValue['X-Goog-Api-Client'] += ' js/gen';
}
return headerValue;
}

/**
* Class that facilitates sending requests to the Firebase Data Connect backend API.
Expand All @@ -50,6 +57,7 @@ const DATA_CONNECT_CONFIG_HEADERS = {
export class DataConnectApiClient {
private readonly httpClient: HttpClient;
private projectId?: string;
private isUsingGen = false;

constructor(private readonly connectorConfig: ConnectorConfig, private readonly app: App) {
if (!validator.isNonNullObject(app) || !('options' in app)) {
Expand All @@ -59,6 +67,14 @@ export class DataConnectApiClient {
}
this.httpClient = new DataConnectHttpClient(app as FirebaseApp);
}

/**
* Update whether the SDK is using a generated one or not.
* @param isUsingGen
*/
setIsUsingGen(isUsingGen: boolean): void {
this.isUsingGen = isUsingGen;
}

/**
* Execute arbitrary GraphQL, including both read and write queries
Expand Down Expand Up @@ -117,7 +133,7 @@ export class DataConnectApiClient {
const request: HttpRequestConfig = {
method: 'POST',
url,
headers: DATA_CONNECT_CONFIG_HEADERS,
headers: getHeaders(this.isUsingGen),
data,
};
const resp = await this.httpClient.send(request);
Expand Down
8 changes: 8 additions & 0 deletions src/data-connect/data-connect.ts
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,14 @@ export class DataConnect {
this.client = new DataConnectApiClient(connectorConfig, app);
}

/**
* @param isUsingGen
* @internal
*/
useGen(isUsingGen: boolean): void {
this.client.setIsUsingGen(isUsingGen);
}

/**
* Execute an arbitrary GraphQL query or mutation
*
Expand Down
8 changes: 6 additions & 2 deletions src/utils/api-request.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1092,7 +1092,9 @@ export class AuthorizedHttpClient extends HttpClient {
requestCopy.httpAgent = this.app.options.httpAgent;
}

requestCopy.headers['X-Goog-Api-Client'] = getMetricsHeader()
if (!requestCopy.headers['X-Goog-Api-Client']) {
requestCopy.headers['X-Goog-Api-Client'] = getMetricsHeader()
}

return super.send(requestCopy);
});
Expand Down Expand Up @@ -1126,7 +1128,9 @@ export class AuthorizedHttp2Client extends Http2Client {
requestCopy.headers['x-goog-user-project'] = quotaProjectId;
}

requestCopy.headers['X-Goog-Api-Client'] = getMetricsHeader()
if (!requestCopy.headers['X-Goog-Api-Client']) {
requestCopy.headers['X-Goog-Api-Client'] = getMetricsHeader()
}

return super.send(requestCopy);
});
Expand Down
35 changes: 35 additions & 0 deletions test/unit/data-connect/data-connect-api-client-internal.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,12 @@ describe('DataConnectApiClient', () => {
'X-Goog-Api-Client': getMetricsHeader(),
};

const EXPECTED_HEADERS_WITH_GEN = {
'Authorization': 'Bearer mock-token',
'X-Firebase-Client': `fire-admin-node/${getSdkVersion()}`,
'X-Goog-Api-Client': getMetricsHeader() + ' js/gen',
};

const EMULATOR_EXPECTED_HEADERS = {
'Authorization': 'Bearer owner',
'X-Firebase-Client': `fire-admin-node/${getSdkVersion()}`,
Expand Down Expand Up @@ -229,6 +235,35 @@ describe('DataConnectApiClient', () => {
});
});
});
it('should use gen headers if set on success', () => {
interface UsersResponse {
users: [
user: {
id: string;
name: string;
address: string;
}
];
}
apiClient.setIsUsingGen(true);
const stub = sandbox
.stub(HttpClient.prototype, 'send')
.resolves(utils.responseFrom(TEST_RESPONSE, 200));
return apiClient.executeGraphql<UsersResponse, unknown>('query', {})
.then((resp) => {
expect(resp.data.users).to.be.not.empty;
expect(resp.data.users[0].name).to.be.not.undefined;
expect(resp.data.users[0].address).to.be.not.undefined;
expect(resp.data.users).to.deep.equal(TEST_RESPONSE.data.users);
expect(stub).to.have.been.calledOnce.and.calledWith({
method: 'POST',
url: `https://firebasedataconnect.googleapis.com/v1/projects/test-project/locations/${connectorConfig.location}/services/${connectorConfig.serviceId}:executeGraphql`,
headers: EXPECTED_HEADERS_WITH_GEN,
data: { query: 'query' }
});
apiClient.setIsUsingGen(false);
});
});
});
});

Expand Down