Skip to content

Commit 9ef4dba

Browse files
author
FOLUSO ONATEMOWO
committed
Implemented initilization and queries for the admin node core sdk, changes include:queryref
1 parent 18f1851 commit 9ef4dba

File tree

6 files changed

+221
-9
lines changed

6 files changed

+221
-9
lines changed

.firebaserc

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"projects": {
3+
"default": "test-suite-e6c23"
4+
},
5+
"targets": {},
6+
"etags": {}
7+
}

dataconnect_test.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
const { getDataConnect } = require('./lib/data-connect');
2+
const { initializeApp } = require('./lib/app');
3+
4+
const app = initializeApp();
5+
6+
const config = {
7+
serviceId: "your-service-id",
8+
location: "us-central1",
9+
connector:"movie-connector"
10+
};
11+
12+
const dataConnect = getDataConnect({
13+
connectorConfig: config
14+
});
15+
16+
const listOfMovies = dataConnect.queryRef('ListMovies').execute();
17+
18+
console.log(listOfMovies)

package-lock.json

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/data-connect/data-connect-api-client-internal.ts

Lines changed: 89 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,22 @@ const API_VERSION = 'v1alpha';
3131
const FIREBASE_DATA_CONNECT_BASE_URL_FORMAT =
3232
'https://firebasedataconnect.googleapis.com/{version}/projects/{projectId}/locations/{locationId}/services/{serviceId}:{endpointId}';
3333

34-
/** Firebase Data Connect base URl format when using the Data Connect emultor. */
34+
/** The Firebase Data Connect backend base URL format including a connector. */
35+
const FIREBASE_DATA_CONNECT_BASE_URL_FORMAT_WITH_CONNECTOR =
36+
'https://firebasedataconnect.googleapis.com/{version}/projects/{projectId}/locations/{locationId}/services/{serviceId}/connectors/${connector}:{endpointId}';
37+
38+
/** Firebase Data Connect base URl format when using the Data Connect emulator. */
3539
const FIREBASE_DATA_CONNECT_EMULATOR_BASE_URL_FORMAT =
3640
'http://{host}/{version}/projects/{projectId}/locations/{locationId}/services/{serviceId}:{endpointId}';
3741

42+
/** Firebase Data Connect base URl format when using the Data Connect emulator including a connector. */
43+
const FIREBASE_DATA_CONNECT_EMULATOR_BASE_URL_FORMAT_WITH_CONNECTOR =
44+
'http://{host}/{version}/projects/{projectId}/locations/{locationId}/services/{serviceId}/connectors/${connector}:{endpointId}';
45+
3846
const EXECUTE_GRAPH_QL_ENDPOINT = 'executeGraphql';
3947
const EXECUTE_GRAPH_QL_READ_ENDPOINT = 'executeGraphqlRead';
48+
const EXECUTE_QUERY_ENDPOINT = 'executeQuery';
49+
// const EXECUTE_MUTATION_ENDPOINT = 'executeMutation';
4050

4151
const DATA_CONNECT_CONFIG_HEADERS = {
4252
'X-Firebase-Client': `fire-admin-node/${utils.getSdkVersion()}`
@@ -75,7 +85,7 @@ export class DataConnectApiClient {
7585
}
7686

7787
/**
78-
* Execute arbitrary read-only GraphQL queries
88+
* Execute arbi<QueryResult<Data, Variables>>trary read-only GraphQL queries
7989
*
8090
* @param query - The GraphQL (read-only) string to be executed.
8191
* @param options - GraphQL Options
@@ -89,6 +99,68 @@ export class DataConnectApiClient {
8999
return this.executeGraphqlHelper(query, EXECUTE_GRAPH_QL_READ_ENDPOINT, options);
90100
}
91101

102+
/**
103+
* Uses the name and the variables parameters to execute a query.
104+
*/
105+
public async executeQuery<Data, Variables>(
106+
options: GraphqlOptions<Variables>,
107+
): Promise<ExecuteGraphqlResponse<Data>>{
108+
// const {data} = await this.executeHelper(options.operationName!, EXECUTE_QUERY_ENDPOINT, options);
109+
return this.executeHelper(EXECUTE_QUERY_ENDPOINT,options);
110+
}
111+
112+
private async executeHelper<GraphqlResponse, Variables>(
113+
endpoint: string,
114+
options?: GraphqlOptions<Variables>,
115+
gql?: string
116+
): Promise<ExecuteGraphqlResponse<GraphqlResponse>> {
117+
if (!validator.isNonEmptyString(gql)) {
118+
throw new FirebaseDataConnectError(
119+
DATA_CONNECT_ERROR_CODE_MAPPING.INVALID_ARGUMENT,
120+
'`query` must be a non-empty string.');
121+
}
122+
if (typeof options !== 'undefined') {
123+
if (!validator.isNonNullObject(options)) {
124+
throw new FirebaseDataConnectError(
125+
DATA_CONNECT_ERROR_CODE_MAPPING.INVALID_ARGUMENT,
126+
'GraphqlOptions must be a non-null object');
127+
}
128+
}
129+
const data = {
130+
query: gql,
131+
...(!gql && { name: options?.operationName}),
132+
...(options?.variables && { variables: options?.variables }),
133+
//change to if query != operationName for executeQuery and executeMutation
134+
//Also how was this needed in conjuncton with executeGraphql before? Just the name of an operation normally doesn't that mean this is how it was used before?
135+
...(options?.operationName && { operationName: options?.operationName }),
136+
...(options?.impersonate && { extensions: { impersonate: options?.impersonate } }),
137+
};
138+
return this.getUrl(API_VERSION, this.connectorConfig.location, this.connectorConfig.serviceId, endpoint,this.connectorConfig.connector)
139+
.then(async (url) => {
140+
const request: HttpRequestConfig = {
141+
method: 'POST',
142+
url,
143+
headers: DATA_CONNECT_CONFIG_HEADERS,
144+
data,
145+
};
146+
const resp = await this.httpClient.send(request);
147+
if (resp.data.errors && validator.isNonEmptyArray(resp.data.errors)) {
148+
const allMessages = resp.data.errors.map((error: { message: any; }) => error.message).join(' ');
149+
throw new FirebaseDataConnectError(
150+
DATA_CONNECT_ERROR_CODE_MAPPING.QUERY_ERROR, allMessages);
151+
}
152+
return Promise.resolve({
153+
data: resp.data.data as GraphqlResponse,
154+
});
155+
})
156+
.then((resp) => {
157+
return resp;
158+
})
159+
.catch((err) => {
160+
throw this.toFirebaseError(err);
161+
});
162+
}
163+
92164
private async executeGraphqlHelper<GraphqlResponse, Variables>(
93165
query: string,
94166
endpoint: string,
@@ -138,23 +210,34 @@ export class DataConnectApiClient {
138210
});
139211
}
140212

141-
private async getUrl(version: string, locationId: string, serviceId: string, endpointId: string): Promise<string> {
213+
private async getUrl(version: string, locationId: string, serviceId: string, endpointId: string, connector?: string): Promise<string> {
142214
return this.getProjectId()
143215
.then((projectId) => {
144216
const urlParams = {
145217
version,
146218
projectId,
147219
locationId,
148220
serviceId,
149-
endpointId
221+
endpointId,
222+
...(connector && { connector })
150223
};
151224
let urlFormat: string;
152225
if (useEmulator()) {
153-
urlFormat = utils.formatString(FIREBASE_DATA_CONNECT_EMULATOR_BASE_URL_FORMAT, {
226+
if ('connector' in urlParams){
227+
urlFormat = utils.formatString(FIREBASE_DATA_CONNECT_EMULATOR_BASE_URL_FORMAT_WITH_CONNECTOR, {
154228
host: emulatorHost()
155229
});
230+
}
231+
else{
232+
urlFormat = utils.formatString(FIREBASE_DATA_CONNECT_EMULATOR_BASE_URL_FORMAT, {
233+
host: emulatorHost()
234+
});
235+
}
156236
} else {
157-
urlFormat = FIREBASE_DATA_CONNECT_BASE_URL_FORMAT;
237+
if ('connector' in urlParams){
238+
urlFormat = FIREBASE_DATA_CONNECT_BASE_URL_FORMAT_WITH_CONNECTOR}
239+
else{
240+
urlFormat = FIREBASE_DATA_CONNECT_BASE_URL_FORMAT;}
158241
}
159242
return utils.formatString(urlFormat, urlParams);
160243
});

src/data-connect/data-connect-api.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,11 @@ export interface ConnectorConfig {
3030
* Service ID of the Data Connect service.
3131
*/
3232
serviceId: string;
33+
34+
/**
35+
* Connector of the Data Connect service.
36+
*/
37+
connector?: string;
3338
}
3439

3540
/**

src/data-connect/data-connect.ts

Lines changed: 100 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
*/
1717

1818
import { App } from '../app';
19-
import { DataConnectApiClient } from './data-connect-api-client-internal';
19+
import { DATA_CONNECT_ERROR_CODE_MAPPING, DataConnectApiClient, FirebaseDataConnectError } from './data-connect-api-client-internal';
2020

2121
import {
2222
ConnectorConfig,
@@ -157,4 +157,103 @@ export class DataConnect {
157157
): Promise<ExecuteGraphqlResponse<GraphQlResponse>> {
158158
return this.client.upsertMany(tableName, variables);
159159
}
160+
161+
/**
162+
* Returns Query Reference
163+
* @param name Name of Query
164+
* @returns QueryRef
165+
*/
166+
public queryRef<Data>(name: string): QueryRef<Data, undefined>;
167+
/**
168+
*
169+
* Returns Query Reference
170+
* @param name Name of Query
171+
* @param variables
172+
* @returns QueryRef
173+
*/
174+
public queryRef<Data, Variables>(name: string, variables: Variables): QueryRef<Data, Variables>;
175+
/**
176+
*
177+
* Returns Query Reference
178+
* @param name Name of Query
179+
* @param variables
180+
* @returns QueryRef
181+
*/
182+
public queryRef<Data, Variables>(name: string, variables?: Variables): QueryRef<Data, Variables> {
183+
console.log(this)
184+
if (!("connector" in this.connectorConfig)){
185+
throw new FirebaseDataConnectError(DATA_CONNECT_ERROR_CODE_MAPPING.INVALID_ARGUMENT,'executeQuery requires a connector');
186+
}
187+
return new QueryRef(this, name, variables as Variables, this.client);
188+
}
189+
/**
190+
* Returns Mutation Reference
191+
* @param name Name of Mutation
192+
* @returns MutationRef
193+
*/
194+
// public mutationRef<Data>(name: string): MutationRef<Data, undefined>;
195+
/**
196+
*
197+
* Returns Mutation Reference
198+
* @param name Name of Mutation
199+
* @param variables
200+
* @returns MutationRef
201+
*/
202+
// public mutationRef<Data, Variables>(name: string, variables: Variables): MutationRef<Data, Variables>;
203+
/**
204+
*
205+
* Returns Query Reference
206+
* @param name Name of Mutation
207+
* @param variables
208+
* @returns MutationRef
209+
*/
210+
// public mutationRef<Data, Variables>(name: string, variables?: Variables): MutationRef<Data, Variables> {
211+
// return new MutationRef(name, variables as Variables, this.client);
212+
// }
213+
}
214+
215+
abstract class OperationRef<Data, Variables> {
216+
_data?: Data;
217+
constructor(public readonly dataConnect: DataConnect, public readonly name: string, public readonly variables: Variables, protected readonly client: DataConnectApiClient) {
218+
219+
}
220+
abstract execute(): Promise<OperationResult<Data, Variables>>;
221+
}
222+
223+
interface OperationResult<Data, Variables> {
224+
ref: OperationRef<Data, Variables>;
225+
data: Data;
226+
variables: Variables;
227+
dataConnect: DataConnect;
160228
}
229+
export interface QueryResult<Data, Variables> extends OperationResult<Data, Variables> {
230+
ref: QueryRef<Data, Variables>;
231+
}
232+
// interface MutationResult<Data, Variables> extends OperationResult<Data, Variables> {
233+
// ref: MutationRef<Data, Variables>;
234+
// }
235+
236+
class QueryRef<Data, Variables> extends OperationRef<Data, Variables> {
237+
option_params:GraphqlOptions<Variables>;
238+
async execute(): Promise<QueryResult<Data, Variables>> {
239+
// return this.client.executeQuery(this.name, this.variables);
240+
const option_params = {
241+
variables: this.variables,
242+
operationName: this.name
243+
};
244+
const {data} = await this.client.executeQuery<Data, Variables>(option_params)
245+
246+
return {
247+
ref: this,
248+
data: data,
249+
variables: this.variables,
250+
dataConnect: this.dataConnect
251+
}
252+
}
253+
}
254+
255+
// class MutationRef<Data, Variables> extends OperationRef<Data, Variables> {
256+
// execute(): Promise<MutationResult<Data, Variables>> {
257+
// return this.client.executeMutation(this.name, this.variables);
258+
// }
259+
// }

0 commit comments

Comments
 (0)