@appzung/react-native-code-push
Version:
React Native plugin for the CodePush service
161 lines (132 loc) • 5.67 kB
text/typescript
import { LogLevel } from '../enums/LogLevel.enum';
import { CodePushError, CodePushHttpError } from './CodePushApiSdk.errors';
import {
type ApiSdkConfiguration,
type ApiSdkDeployReportPackageInfo,
type ApiSdkDownloadReportPackageInfo,
type ApiSdkNativeUpdateNotification,
type ApiSdkQueryUpdatePackageInfo,
type ApiSdkRemotePackage,
type CheckUpdateRequestInput,
type CheckUpdateResponse,
DeploymentStatus,
type Http,
type ReportDeployInput,
type ReportDownloadInput,
} from './CodePushApiSdk.types';
import { queryStringify } from './utils/queryStringify';
// TODO move this to @appzung/code-push-api-sdk
export class CodePushApiSdk {
private configuration: ApiSdkConfiguration;
constructor(
private readonly httpRequester: Http.Requester,
private readonly log: (level: LogLevel, message: string) => void,
configuration: ApiSdkConfiguration,
) {
this.configuration = { ...configuration };
if (this.configuration.serverUrl.slice(-1) !== '/') {
this.configuration.serverUrl += '/';
}
this.configuration.serverUrl += 'v0.1/public/codepush';
}
async queryUpdateWithCurrentPackage(
currentPackageInfo: ApiSdkQueryUpdatePackageInfo,
): Promise<ApiSdkRemotePackage | ApiSdkNativeUpdateNotification | null> {
if (!this.configuration.dataTransmissionEnabled) {
this.log(LogLevel.DEBUG, 'Skipped querying for update because data transmission is disabled');
return null;
}
const query: CheckUpdateRequestInput = {
deployment_key: this.configuration.releaseChannelPublicId,
app_version: currentPackageInfo.appVersion,
package_hash: currentPackageInfo.packageHash,
is_companion: this.configuration.ignoreAppVersion,
label: currentPackageInfo.label,
client_unique_id: this.configuration.clientUniqueId,
};
const url = `${this.configuration.serverUrl}/update_check?${queryStringify(query)}`;
const response = await this.httpRequester.request('GET', url);
if (response.statusCode < 200 || response.statusCode >= 300) {
throw new CodePushHttpError(url, response.statusCode, response.body || 'No body');
}
const responseObject: CheckUpdateResponse | Record<string, never> = JSON.parse(response.body || '{}');
if (!responseObject.update_info) {
throw new CodePushError('Missing update info in response');
}
const { update_info: updateInfo } = responseObject;
if (updateInfo.update_app_version) {
return {
updateAppVersion: true,
appVersion: responseObject.update_info.target_binary_range,
};
}
if (!updateInfo.is_available) {
return null;
}
return {
releaseChannelPublicId: this.configuration.releaseChannelPublicId,
description: updateInfo.description,
label: updateInfo.label,
appVersion: updateInfo.target_binary_range,
isMandatory: updateInfo.is_mandatory,
packageHash: updateInfo.package_hash,
packageSize: updateInfo.package_size,
downloadUrl: updateInfo.download_url,
};
}
async reportStatusDeploy(
deployedPackageInfo: { package: ApiSdkDeployReportPackageInfo; status: DeploymentStatus } | null,
previousLabelOrAppVersion: string | null,
previousDeploymentKey: string | null,
): Promise<void> {
if (!this.configuration.dataTransmissionEnabled) {
this.log(LogLevel.DEBUG, 'Skipped reporting deploy status because data transmission is disabled');
return;
}
if (!this.configuration.telemetryEnabled) {
this.log(LogLevel.DEBUG, 'Skipped reporting deploy status because telemetry is disabled');
return;
}
const requestBody: ReportDeployInput = {
app_version: this.configuration.appVersion,
deployment_key: this.configuration.releaseChannelPublicId,
client_unique_id: this.configuration.clientUniqueId,
};
if (deployedPackageInfo) {
requestBody.label = deployedPackageInfo.package.label;
requestBody.app_version = deployedPackageInfo.package.appVersion;
requestBody.status = deployedPackageInfo.status;
}
if (previousLabelOrAppVersion) {
requestBody.previous_label_or_app_version = previousLabelOrAppVersion;
}
if (previousDeploymentKey) {
requestBody.previous_deployment_key = previousDeploymentKey;
}
const url = `${this.configuration.serverUrl}/report_status/deploy`;
const response = await this.httpRequester.request('POST', url, JSON.stringify(requestBody));
if (response.statusCode < 200 || response.statusCode >= 300) {
throw new CodePushHttpError(url, response.statusCode, response.body || 'No body');
}
}
async reportStatusDownload(downloadedPackage: ApiSdkDownloadReportPackageInfo): Promise<void> {
if (!this.configuration.dataTransmissionEnabled) {
this.log(LogLevel.DEBUG, 'Skipped reporting download because data transmission is disabled');
return;
}
if (!this.configuration.telemetryEnabled) {
this.log(LogLevel.DEBUG, 'Skipped reporting download because telemetry is disabled');
return;
}
const requestBody: ReportDownloadInput = {
client_unique_id: this.configuration.clientUniqueId,
deployment_key: this.configuration.releaseChannelPublicId,
label: downloadedPackage.label,
};
const url = `${this.configuration.serverUrl}/report_status/download`;
const response = await this.httpRequester.request('POST', url, JSON.stringify(requestBody));
if (response.statusCode < 200 || response.statusCode >= 300) {
throw new CodePushHttpError(url, response.statusCode, response.body || 'No body');
}
}
}