Skip to content

Commit 037cceb

Browse files
committed
feat(remote-config): implement server template management methods
1 parent 4ca39f3 commit 037cceb

5 files changed

Lines changed: 587 additions & 0 deletions

File tree

etc/firebase-admin.remote-config.api.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -199,15 +199,23 @@ export class RemoteConfig {
199199
// (undocumented)
200200
readonly app: App;
201201
createTemplateFromJSON(json: string): RemoteConfigTemplate;
202+
getServerConfigTemplate(): Promise<RemoteConfigTemplate>;
203+
getServerConfigTemplateAtVersion(versionNumber: number | string): Promise<RemoteConfigTemplate>;
202204
getServerTemplate(options?: GetServerTemplateOptions): Promise<ServerTemplate>;
203205
getTemplate(): Promise<RemoteConfigTemplate>;
204206
getTemplateAtVersion(versionNumber: number | string): Promise<RemoteConfigTemplate>;
205207
initServerTemplate(options?: InitServerTemplateOptions): ServerTemplate;
208+
listServerConfigVersions(options?: ListVersionsOptions): Promise<ListVersionsResult>;
206209
listVersions(options?: ListVersionsOptions): Promise<ListVersionsResult>;
210+
publishServerConfigTemplate(template: RemoteConfigTemplate, options?: {
211+
force: boolean;
212+
}): Promise<RemoteConfigTemplate>;
207213
publishTemplate(template: RemoteConfigTemplate, options?: {
208214
force: boolean;
209215
}): Promise<RemoteConfigTemplate>;
210216
rollback(versionNumber: number | string): Promise<RemoteConfigTemplate>;
217+
rollbackServerConfigTemplate(versionNumber: number | string): Promise<RemoteConfigTemplate>;
218+
validateServerConfigTemplate(template: RemoteConfigTemplate): Promise<RemoteConfigTemplate>;
211219
validateTemplate(template: RemoteConfigTemplate): Promise<RemoteConfigTemplate>;
212220
}
213221

src/remote-config/remote-config-api-client-internal.ts

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -197,6 +197,142 @@ export class RemoteConfigApiClient {
197197
});
198198
}
199199

200+
public getServerConfigTemplate(): Promise<RemoteConfigTemplate> {
201+
return this.getUrl()
202+
.then((url) => {
203+
const request: HttpRequestConfig = {
204+
method: 'GET',
205+
url: `${url}/namespaces/firebase-server/remoteConfig`,
206+
headers: FIREBASE_REMOTE_CONFIG_HEADERS
207+
};
208+
return this.httpClient.send(request);
209+
})
210+
.then((resp) => {
211+
return this.toRemoteConfigTemplate(resp);
212+
})
213+
.catch((err) => {
214+
throw this.toFirebaseError(err);
215+
});
216+
}
217+
218+
public getServerConfigTemplateAtVersion(versionNumber: number | string): Promise<RemoteConfigTemplate> {
219+
const data = { versionNumber: this.validateVersionNumber(versionNumber) };
220+
return this.getUrl()
221+
.then((url) => {
222+
const request: HttpRequestConfig = {
223+
method: 'GET',
224+
url: `${url}/namespaces/firebase-server/remoteConfig`,
225+
headers: FIREBASE_REMOTE_CONFIG_HEADERS,
226+
data
227+
};
228+
return this.httpClient.send(request);
229+
})
230+
.then((resp) => {
231+
return this.toRemoteConfigTemplate(resp);
232+
})
233+
.catch((err) => {
234+
throw this.toFirebaseError(err);
235+
});
236+
}
237+
238+
public validateServerConfigTemplate(template: RemoteConfigTemplate): Promise<RemoteConfigTemplate> {
239+
template = this.validateInputRemoteConfigTemplate(template);
240+
return this.sendServerPutRequest(template, template.etag, true)
241+
.then((resp) => {
242+
this.validateEtag(resp.headers['etag']);
243+
return this.toRemoteConfigTemplate(resp, template.etag);
244+
})
245+
.catch((err) => {
246+
throw this.toFirebaseError(err);
247+
});
248+
}
249+
250+
public publishServerConfigTemplate(
251+
template: RemoteConfigTemplate,
252+
options?: { force: boolean; }
253+
): Promise<RemoteConfigTemplate> {
254+
template = this.validateInputRemoteConfigTemplate(template);
255+
let ifMatch: string = template.etag;
256+
if (options && options.force === true) {
257+
ifMatch = '*';
258+
}
259+
return this.sendServerPutRequest(template, ifMatch)
260+
.then((resp) => {
261+
return this.toRemoteConfigTemplate(resp);
262+
})
263+
.catch((err) => {
264+
throw this.toFirebaseError(err);
265+
});
266+
}
267+
268+
public rollbackServerConfigTemplate(versionNumber: number | string): Promise<RemoteConfigTemplate> {
269+
const data = { versionNumber: this.validateVersionNumber(versionNumber) };
270+
return this.getUrl()
271+
.then((url) => {
272+
const request: HttpRequestConfig = {
273+
method: 'POST',
274+
url: `${url}/namespaces/firebase-server/remoteConfig:rollback`,
275+
headers: FIREBASE_REMOTE_CONFIG_HEADERS,
276+
data
277+
};
278+
return this.httpClient.send(request);
279+
})
280+
.then((resp) => {
281+
return this.toRemoteConfigTemplate(resp);
282+
})
283+
.catch((err) => {
284+
throw this.toFirebaseError(err);
285+
});
286+
}
287+
288+
public listServerConfigVersions(options?: ListVersionsOptions): Promise<ListVersionsResult> {
289+
if (typeof options !== 'undefined') {
290+
options = this.validateListVersionsOptions(options);
291+
}
292+
return this.getUrl()
293+
.then((url) => {
294+
const request: HttpRequestConfig = {
295+
method: 'GET',
296+
url: `${url}/namespaces/firebase-server/remoteConfig:listVersions`,
297+
headers: FIREBASE_REMOTE_CONFIG_HEADERS,
298+
data: options
299+
};
300+
return this.httpClient.send(request);
301+
})
302+
.then((resp) => {
303+
return resp.data;
304+
})
305+
.catch((err) => {
306+
throw this.toFirebaseError(err);
307+
});
308+
}
309+
310+
private sendServerPutRequest(
311+
template: RemoteConfigTemplate,
312+
etag: string,
313+
validateOnly?: boolean
314+
): Promise<RequestResponse> {
315+
let path = 'namespaces/firebase-server/remoteConfig';
316+
if (validateOnly) {
317+
path += '?validate_only=true';
318+
}
319+
return this.getUrl()
320+
.then((url) => {
321+
const request: HttpRequestConfig = {
322+
method: 'PUT',
323+
url: `${url}/${path}`,
324+
headers: { ...FIREBASE_REMOTE_CONFIG_HEADERS, 'If-Match': etag },
325+
data: {
326+
conditions: template.conditions,
327+
parameters: template.parameters,
328+
parameterGroups: template.parameterGroups,
329+
version: template.version,
330+
}
331+
};
332+
return this.httpClient.send(request);
333+
});
334+
}
335+
200336
private sendPutRequest(
201337
template: RemoteConfigTemplate,
202338
etag: string,

src/remote-config/remote-config.ts

Lines changed: 89 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -213,6 +213,95 @@ export class RemoteConfig {
213213

214214
return template;
215215
}
216+
217+
/**
218+
* Gets the current active version of the server-side {@link RemoteConfigTemplate} of the project.
219+
*
220+
* @returns A promise that fulfills with a `RemoteConfigTemplate`.
221+
*/
222+
public getServerConfigTemplate(): Promise<RemoteConfigTemplate> {
223+
return this.client.getServerConfigTemplate()
224+
.then((templateResponse) => {
225+
return new RemoteConfigTemplateImpl(templateResponse);
226+
});
227+
}
228+
229+
/**
230+
* Gets the requested version of the server-side {@link RemoteConfigTemplate} of the project.
231+
*
232+
* @param versionNumber - Version number of the Remote Config template to look up.
233+
*
234+
* @returns A promise that fulfills with a `RemoteConfigTemplate`.
235+
*/
236+
public getServerConfigTemplateAtVersion(versionNumber: number | string): Promise<RemoteConfigTemplate> {
237+
return this.client.getServerConfigTemplateAtVersion(versionNumber)
238+
.then((templateResponse) => {
239+
return new RemoteConfigTemplateImpl(templateResponse);
240+
});
241+
}
242+
243+
/**
244+
* Validates a server-side {@link RemoteConfigTemplate}.
245+
*
246+
* @param template - The Remote Config template to be validated.
247+
* @returns A promise that fulfills with the validated `RemoteConfigTemplate`.
248+
*/
249+
public validateServerConfigTemplate(template: RemoteConfigTemplate): Promise<RemoteConfigTemplate> {
250+
return this.client.validateServerConfigTemplate(template)
251+
.then((templateResponse) => {
252+
return new RemoteConfigTemplateImpl(templateResponse);
253+
});
254+
}
255+
256+
/**
257+
* Publishes a server-side Remote Config template.
258+
*
259+
* @param template - The Remote Config template to be published.
260+
* @param options - Optional options object when publishing a Remote Config template:
261+
* - `force`: Setting this to `true` forces the Remote Config template to
262+
* be updated and circumvent the ETag.
263+
*
264+
* @returns A Promise that fulfills with the published `RemoteConfigTemplate`.
265+
*/
266+
public publishServerConfigTemplate(
267+
template: RemoteConfigTemplate,
268+
options?: { force: boolean }
269+
): Promise<RemoteConfigTemplate> {
270+
return this.client.publishServerConfigTemplate(template, options)
271+
.then((templateResponse) => {
272+
return new RemoteConfigTemplateImpl(templateResponse);
273+
});
274+
}
275+
276+
/**
277+
* Rolls back a project's published server-side Remote Config template to the specified version.
278+
*
279+
* @param versionNumber - The version number of the Remote Config template to roll back to.
280+
* @returns A promise that fulfills with the published `RemoteConfigTemplate`.
281+
*/
282+
public rollbackServerConfigTemplate(versionNumber: number | string): Promise<RemoteConfigTemplate> {
283+
return this.client.rollbackServerConfigTemplate(versionNumber)
284+
.then((templateResponse) => {
285+
return new RemoteConfigTemplateImpl(templateResponse);
286+
});
287+
}
288+
289+
/**
290+
* Gets a list of server-side Remote Config template versions that have been published, sorted in reverse
291+
* chronological order.
292+
*
293+
* @param options - Optional options object for getting a list of versions.
294+
* @returns A promise that fulfills with a `ListVersionsResult`.
295+
*/
296+
public listServerConfigVersions(options?: ListVersionsOptions): Promise<ListVersionsResult> {
297+
return this.client.listServerConfigVersions(options)
298+
.then((listVersionsResponse) => {
299+
return {
300+
versions: listVersionsResponse.versions?.map(version => new VersionImpl(version)) ?? [],
301+
nextPageToken: listVersionsResponse.nextPageToken,
302+
};
303+
});
304+
}
216305
}
217306

218307
/**

0 commit comments

Comments
 (0)