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
8 changes: 8 additions & 0 deletions etc/firebase-admin.remote-config.api.md
Original file line number Diff line number Diff line change
Expand Up @@ -199,15 +199,23 @@ export class RemoteConfig {
// (undocumented)
readonly app: App;
createTemplateFromJSON(json: string): RemoteConfigTemplate;
getServerConfigTemplate(): Promise<RemoteConfigTemplate>;
getServerConfigTemplateAtVersion(versionNumber: number | string): Promise<RemoteConfigTemplate>;
getServerTemplate(options?: GetServerTemplateOptions): Promise<ServerTemplate>;
getTemplate(): Promise<RemoteConfigTemplate>;
getTemplateAtVersion(versionNumber: number | string): Promise<RemoteConfigTemplate>;
initServerTemplate(options?: InitServerTemplateOptions): ServerTemplate;
listServerConfigVersions(options?: ListVersionsOptions): Promise<ListVersionsResult>;
listVersions(options?: ListVersionsOptions): Promise<ListVersionsResult>;
publishServerConfigTemplate(template: RemoteConfigTemplate, options?: {
force: boolean;
}): Promise<RemoteConfigTemplate>;
publishTemplate(template: RemoteConfigTemplate, options?: {
force: boolean;
}): Promise<RemoteConfigTemplate>;
rollback(versionNumber: number | string): Promise<RemoteConfigTemplate>;
rollbackServerConfigTemplate(versionNumber: number | string): Promise<RemoteConfigTemplate>;
validateServerConfigTemplate(template: RemoteConfigTemplate): Promise<RemoteConfigTemplate>;
validateTemplate(template: RemoteConfigTemplate): Promise<RemoteConfigTemplate>;
}

Expand Down
157 changes: 119 additions & 38 deletions src/remote-config/remote-config-api-client-internal.ts
Original file line number Diff line number Diff line change
Expand Up @@ -68,15 +68,40 @@ export class RemoteConfigApiClient {
}

public getTemplate(): Promise<RemoteConfigTemplate> {
return this.getUrl()
.then((url) => {
const request: HttpRequestConfig = {
method: 'GET',
url: `${url}/remoteConfig`,
headers: FIREBASE_REMOTE_CONFIG_HEADERS
};
return this.httpClient.send(request);
return this.getTemplateInternal('remoteConfig');
}

public getTemplateAtVersion(versionNumber: number | string): Promise<RemoteConfigTemplate> {
return this.getTemplateInternal('remoteConfig', versionNumber);
}

public validateTemplate(template: RemoteConfigTemplate): Promise<RemoteConfigTemplate> {
template = this.validateInputRemoteConfigTemplate(template);
return this.sendPutRequest(template, template.etag, true)
.then((resp) => {
// validating a template returns an etag with the suffix -0 means that your update
// was successfully validated. We set the etag back to the original etag of the template
// to allow future operations.
this.validateEtag(resp.headers['etag']);
return this.toRemoteConfigTemplate(resp, template.etag);
})
.catch((err) => {
throw this.toFirebaseError(err);
});
}

public publishTemplate(
template: RemoteConfigTemplate,
options?: { force: boolean; }
): Promise<RemoteConfigTemplate> {
template = this.validateInputRemoteConfigTemplate(template);
let ifMatch: string = template.etag;
if (options && options.force === true) {
// setting `If-Match: *` forces the Remote Config template to be updated
// and circumvent the ETag, and the protection from that it provides.
ifMatch = '*';
}
return this.sendPutRequest(template, ifMatch)
.then((resp) => {
return this.toRemoteConfigTemplate(resp);
})
Expand All @@ -85,29 +110,43 @@ export class RemoteConfigApiClient {
});
}

public getTemplateAtVersion(versionNumber: number | string): Promise<RemoteConfigTemplate> {
const data = { versionNumber: this.validateVersionNumber(versionNumber) };
public rollback(versionNumber: number | string): Promise<RemoteConfigTemplate> {
return this.rollbackInternal('remoteConfig:rollback', versionNumber);
}

public listVersions(options?: ListVersionsOptions): Promise<ListVersionsResult> {
return this.listVersionsInternal('remoteConfig:listVersions', options);
}

public getServerTemplate(): Promise<ServerTemplateData> {
return this.getUrl()
.then((url) => {
const request: HttpRequestConfig = {
method: 'GET',
url: `${url}/remoteConfig`,
headers: FIREBASE_REMOTE_CONFIG_HEADERS,
data
url: `${url}/namespaces/firebase-server/serverRemoteConfig`,
headers: FIREBASE_REMOTE_CONFIG_HEADERS
};
return this.httpClient.send(request);
})
.then((resp) => {
return this.toRemoteConfigTemplate(resp);
return this.toRemoteConfigServerTemplate(resp);
})
.catch((err) => {
throw this.toFirebaseError(err);
});
}

public validateTemplate(template: RemoteConfigTemplate): Promise<RemoteConfigTemplate> {
public getServerConfigTemplate(): Promise<RemoteConfigTemplate> {
return this.getTemplateInternal('namespaces/firebase-server/remoteConfig');
}

public getServerConfigTemplateAtVersion(versionNumber: number | string): Promise<RemoteConfigTemplate> {
return this.getTemplateInternal('namespaces/firebase-server/remoteConfig', versionNumber);
}

public validateServerConfigTemplate(template: RemoteConfigTemplate): Promise<RemoteConfigTemplate> {
template = this.validateInputRemoteConfigTemplate(template);
return this.sendPutRequest(template, template.etag, true)
return this.sendServerPutRequest(template, template.etag, true)
.then((resp) => {
// validating a template returns an etag with the suffix -0 means that your update
// was successfully validated. We set the etag back to the original etag of the template
Expand All @@ -120,15 +159,18 @@ export class RemoteConfigApiClient {
});
}
Comment thread
congminh1254 marked this conversation as resolved.

public publishTemplate(template: RemoteConfigTemplate, options?: { force: boolean; }): Promise<RemoteConfigTemplate> {
public publishServerConfigTemplate(
template: RemoteConfigTemplate,
options?: { force: boolean; }
): Promise<RemoteConfigTemplate> {
template = this.validateInputRemoteConfigTemplate(template);
let ifMatch: string = template.etag;
if (options && options.force === true) {
// setting `If-Match: *` forces the Remote Config template to be updated
// and circumvent the ETag, and the protection from that it provides.
ifMatch = '*';
}
return this.sendPutRequest(template, ifMatch)
return this.sendServerPutRequest(template, ifMatch)
.then((resp) => {
return this.toRemoteConfigTemplate(resp);
})
Expand All @@ -137,16 +179,31 @@ export class RemoteConfigApiClient {
});
}
Comment thread
congminh1254 marked this conversation as resolved.

public rollback(versionNumber: number | string): Promise<RemoteConfigTemplate> {
const data = { versionNumber: this.validateVersionNumber(versionNumber) };
public rollbackServerConfigTemplate(versionNumber: number | string): Promise<RemoteConfigTemplate> {
return this.rollbackInternal('namespaces/firebase-server/remoteConfig:rollback', versionNumber);
}

public listServerConfigVersions(options?: ListVersionsOptions): Promise<ListVersionsResult> {
return this.listVersionsInternal('namespaces/firebase-server/remoteConfig:listVersions', options);
}

private getTemplateInternal(
path: string,
versionNumber?: number | string
): Promise<RemoteConfigTemplate> {
const data = typeof versionNumber !== 'undefined'
? { versionNumber: this.validateVersionNumber(versionNumber) }
: undefined;
return this.getUrl()
.then((url) => {
const request: HttpRequestConfig = {
method: 'POST',
url: `${url}/remoteConfig:rollback`,
headers: FIREBASE_REMOTE_CONFIG_HEADERS,
data
method: 'GET',
url: `${url}/${path}`,
headers: FIREBASE_REMOTE_CONFIG_HEADERS
};
if (typeof data !== 'undefined') {
request.data = data;
}
return this.httpClient.send(request);
})
.then((resp) => {
Expand All @@ -157,52 +214,60 @@ export class RemoteConfigApiClient {
});
}

public listVersions(options?: ListVersionsOptions): Promise<ListVersionsResult> {
if (typeof options !== 'undefined') {
options = this.validateListVersionsOptions(options);
}
private rollbackInternal(
path: string,
versionNumber: number | string
): Promise<RemoteConfigTemplate> {
const data = { versionNumber: this.validateVersionNumber(versionNumber) };
return this.getUrl()
.then((url) => {
const request: HttpRequestConfig = {
method: 'GET',
url: `${url}/remoteConfig:listVersions`,
method: 'POST',
url: `${url}/${path}`,
headers: FIREBASE_REMOTE_CONFIG_HEADERS,
data: options
data
};
return this.httpClient.send(request);
})
.then((resp) => {
return resp.data;
return this.toRemoteConfigTemplate(resp);
})
.catch((err) => {
throw this.toFirebaseError(err);
});
}

public getServerTemplate(): Promise<ServerTemplateData> {
private listVersionsInternal(
path: string,
options?: ListVersionsOptions
): Promise<ListVersionsResult> {
if (typeof options !== 'undefined') {
options = this.validateListVersionsOptions(options);
}
return this.getUrl()
.then((url) => {
const request: HttpRequestConfig = {
method: 'GET',
url: `${url}/namespaces/firebase-server/serverRemoteConfig`,
headers: FIREBASE_REMOTE_CONFIG_HEADERS
url: `${url}/${path}`,
headers: FIREBASE_REMOTE_CONFIG_HEADERS,
data: options
};
return this.httpClient.send(request);
})
.then((resp) => {
return this.toRemoteConfigServerTemplate(resp);
return resp.data;
})
.catch((err) => {
throw this.toFirebaseError(err);
});
}

private sendPutRequest(
private sendPutRequestInternal(
path: string,
template: RemoteConfigTemplate,
etag: string,
validateOnly?: boolean
): Promise<RequestResponse> {
let path = 'remoteConfig';
if (validateOnly) {
path += '?validate_only=true';
}
Expand All @@ -223,6 +288,22 @@ export class RemoteConfigApiClient {
});
}

private sendServerPutRequest(
template: RemoteConfigTemplate,
etag: string,
validateOnly?: boolean
): Promise<RequestResponse> {
return this.sendPutRequestInternal('namespaces/firebase-server/remoteConfig', template, etag, validateOnly);
}

private sendPutRequest(
template: RemoteConfigTemplate,
etag: string,
validateOnly?: boolean
): Promise<RequestResponse> {
return this.sendPutRequestInternal('remoteConfig', template, etag, validateOnly);
}

private getUrl(): Promise<string> {
return this.getProjectIdPrefix()
.then((projectIdPrefix) => {
Expand Down
89 changes: 89 additions & 0 deletions src/remote-config/remote-config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -213,6 +213,95 @@ export class RemoteConfig {

return template;
}

/**
* Gets the current active version of the server-side {@link RemoteConfigTemplate} of the project.
*
* @returns A promise that fulfills with a `RemoteConfigTemplate`.
*/
public getServerConfigTemplate(): Promise<RemoteConfigTemplate> {
return this.client.getServerConfigTemplate()
.then((templateResponse) => {
return new RemoteConfigTemplateImpl(templateResponse);
});
}

/**
* Gets the requested version of the server-side {@link RemoteConfigTemplate} of the project.
*
* @param versionNumber - Version number of the Remote Config template to look up.
*
* @returns A promise that fulfills with a `RemoteConfigTemplate`.
*/
public getServerConfigTemplateAtVersion(versionNumber: number | string): Promise<RemoteConfigTemplate> {
return this.client.getServerConfigTemplateAtVersion(versionNumber)
.then((templateResponse) => {
return new RemoteConfigTemplateImpl(templateResponse);
});
}

/**
* Validates a server-side {@link RemoteConfigTemplate}.
*
* @param template - The Remote Config template to be validated.
* @returns A promise that fulfills with the validated `RemoteConfigTemplate`.
*/
public validateServerConfigTemplate(template: RemoteConfigTemplate): Promise<RemoteConfigTemplate> {
return this.client.validateServerConfigTemplate(template)
.then((templateResponse) => {
return new RemoteConfigTemplateImpl(templateResponse);
});
}

/**
* Publishes a server-side Remote Config template.
*
* @param template - The Remote Config template to be published.
* @param options - Optional options object when publishing a Remote Config template:
* - `force`: Setting this to `true` forces the Remote Config template to
* be updated and circumvent the ETag.
*
* @returns A Promise that fulfills with the published `RemoteConfigTemplate`.
*/
public publishServerConfigTemplate(
template: RemoteConfigTemplate,
options?: { force: boolean }
): Promise<RemoteConfigTemplate> {
return this.client.publishServerConfigTemplate(template, options)
.then((templateResponse) => {
return new RemoteConfigTemplateImpl(templateResponse);
});
}

/**
* Rolls back a project's published server-side Remote Config template to the specified version.
*
* @param versionNumber - The version number of the Remote Config template to roll back to.
* @returns A promise that fulfills with the published `RemoteConfigTemplate`.
*/
public rollbackServerConfigTemplate(versionNumber: number | string): Promise<RemoteConfigTemplate> {
return this.client.rollbackServerConfigTemplate(versionNumber)
.then((templateResponse) => {
return new RemoteConfigTemplateImpl(templateResponse);
});
}

/**
* Gets a list of server-side Remote Config template versions that have been published, sorted in reverse
* chronological order.
*
* @param options - Optional options object for getting a list of versions.
* @returns A promise that fulfills with a `ListVersionsResult`.
*/
public listServerConfigVersions(options?: ListVersionsOptions): Promise<ListVersionsResult> {
return this.client.listServerConfigVersions(options)
.then((listVersionsResponse) => {
return {
versions: listVersionsResponse.versions?.map(version => new VersionImpl(version)) ?? [],
nextPageToken: listVersionsResponse.nextPageToken,
};
});
}
}

/**
Expand Down
Loading