Skip to content

Commit 2b5db0d

Browse files
committed
Continue Typescript migration
1 parent 6dc7e65 commit 2b5db0d

8 files changed

Lines changed: 118 additions & 82 deletions

src/checkForUpdates.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
import { requestFetchAdapter } from "./internals/utils/request-fetch-adapter";
22
import { Platform } from "react-native";
33
import { log } from "./internals/utils/log";
4-
import type {HandleBinaryVersionMismatchCallback, RemotePackage} from "./types";
4+
import type { HandleBinaryVersionMismatchCallback, RemotePackage } from "./types";
55
import { NativeRNAppZungCodePushModule } from "./internals/NativeRNAppZungCodePushModule";
6-
import { packageMixins } from "./internals/packageMixins";
76
import { getConfiguration } from "./internals/getConfiguration";
87
import { getPromisifiedSdk, type PromisifiedSdkQueryPackage } from "./internals/getPromisifiedSdk";
98
import type { Configuration } from "./internals/types";
109
import { getCurrentPackage } from "./internals/getCurrentPackage";
10+
import { RemotePackageImpl } from "./internals/RemotePackageImplementation";
1111

1212
/**
1313
* Asks the CodePush service whether the configured app release channel has an update available.
@@ -92,7 +92,8 @@ export async function checkForUpdate(releaseChannelPublicId?: string, handleBina
9292
return null;
9393
}
9494

95-
const remotePackage = { ...update, ...packageMixins.remote(sdk.reportStatusDownload) };
95+
// @ts-expect-error sdk typing is wrong
96+
const remotePackage = new RemotePackageImpl(update, sdk.reportStatusDownload);
9697
remotePackage.failedInstall = await NativeRNAppZungCodePushModule.isFailedUpdate(remotePackage.packageHash);
9798
remotePackage.releaseChannelPublicId = releaseChannelPublicId || nativeConfig.releaseChannelPublicId;
9899
return remotePackage;

src/getUpdateMetadata.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import { UpdateState } from "./enums/UpdateState.enum";
22
import { NativeRNAppZungCodePushModule } from "./internals/NativeRNAppZungCodePushModule";
3-
import { packageMixins } from "./internals/packageMixins";
43
import type { LocalPackage } from "./types";
4+
import { LocalPackageImplementation } from "./internals/LocalPackageImplementation";
55

66
/**
77
* Retrieves the metadata for an installed update (e.g. description, mandatory).
@@ -14,7 +14,7 @@ export async function getUpdateMetadata(updateState?: UpdateState): Promise<Loca
1414
return null;
1515
}
1616

17-
const localPackage: LocalPackage = {...packageMixins.local, ...nativeUpdateMetadata };
17+
const localPackage = new LocalPackageImplementation(nativeUpdateMetadata);
1818
localPackage.failedInstall = await NativeRNAppZungCodePushModule.isFailedUpdate(nativeUpdateMetadata.packageHash);
1919
localPackage.isFirstRun = await NativeRNAppZungCodePushModule.isFirstRun(nativeUpdateMetadata.packageHash);
2020
return localPackage;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
import { NativeRNAppZungCodePushModule } from "./NativeRNAppZungCodePushModule";
2+
import type { LocalPackage } from "../types";
3+
import { cloneWithoutFunctions } from "./utils/cloneWithoutFunctions";
4+
5+
export class LocalPackageImplementation implements LocalPackage {
6+
constructor(localPackageData: LocalPackage) {
7+
Object.assign(this, localPackageData);
8+
}
9+
10+
appVersion!: string;
11+
description!: string;
12+
failedInstall!: boolean;
13+
isFirstRun!: boolean;
14+
isMandatory!: boolean;
15+
isPending = false; // A local package wouldn't be pending until it was installed
16+
label!: string;
17+
packageHash!: string;
18+
packageSize!: number;
19+
releaseChannelPublicId!: string;
20+
21+
async install(installMode = NativeRNAppZungCodePushModule.codePushInstallModeOnNextRestart, minimumBackgroundDuration = 0, updateInstalledCallback?: () => (Promise<void> | void)) {
22+
const localPackageCopy = cloneWithoutFunctions(this); // In dev mode, React Native deep freezes any object queued over the bridge
23+
await NativeRNAppZungCodePushModule.installUpdate(localPackageCopy, installMode, minimumBackgroundDuration);
24+
25+
if (installMode === NativeRNAppZungCodePushModule.codePushInstallModeImmediate) {
26+
await updateInstalledCallback?.();
27+
NativeRNAppZungCodePushModule.restartApp(false);
28+
return;
29+
}
30+
31+
NativeRNAppZungCodePushModule.clearPendingRestart();
32+
this.isPending = true; // Mark the package as pending since it hasn't been applied yet
33+
await updateInstalledCallback?.();
34+
}
35+
}
Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
import { NativeEventEmitter } from "react-native";
2+
import { NativeRNAppZungCodePushModule } from "./NativeRNAppZungCodePushModule";
3+
import type { DownloadProgressCallback, RemotePackage } from "../types";
4+
import type { Package } from "code-push/script/acquisition-sdk";
5+
import { log } from "./utils/log";
6+
import { LocalPackageImplementation } from "./LocalPackageImplementation";
7+
import { cloneWithoutFunctions } from "./utils/cloneWithoutFunctions";
8+
9+
export class RemotePackageImpl implements RemotePackage {
10+
constructor(remotePackageData: Omit<RemotePackage, "download">, private readonly reportStatusDownload?: (downloadedPackage: Package) => Promise<void>) {
11+
Object.assign(this, remotePackageData);
12+
}
13+
14+
appVersion!: string;
15+
description!: string;
16+
downloadUrl!: string;
17+
failedInstall!: boolean;
18+
isFirstRun!: boolean;
19+
isMandatory!: boolean;
20+
isPending = false; // A remote package could never be in a pending state
21+
label!: string;
22+
packageHash!: string;
23+
packageSize!: number;
24+
releaseChannelPublicId!: string;
25+
26+
async download(downloadProgressCallback: DownloadProgressCallback) {
27+
if (!this.downloadUrl) {
28+
throw new Error("Cannot download an update without a download url");
29+
}
30+
31+
let downloadProgressSubscription;
32+
33+
if (downloadProgressCallback) {
34+
const codePushEventEmitter = new NativeEventEmitter(NativeRNAppZungCodePushModule);
35+
// Use event subscription to obtain download progress.
36+
downloadProgressSubscription = codePushEventEmitter.addListener(
37+
"CodePushDownloadProgress",
38+
downloadProgressCallback
39+
);
40+
}
41+
42+
// Use the downloaded package info. Native code will save the package info
43+
// so that the client knows what the current package version is.
44+
try {
45+
const updatePackageCopy = cloneWithoutFunctions(this); // In dev mode, React Native deep freezes any object queued over the bridge
46+
const downloadedPackage = await NativeRNAppZungCodePushModule.downloadUpdate(updatePackageCopy, !!downloadProgressCallback);
47+
48+
if (this.reportStatusDownload) {
49+
this.reportStatusDownload({
50+
...this,
51+
deploymentKey: this.releaseChannelPublicId,
52+
})
53+
.catch((err) => {
54+
log(`Report download status failed: ${err}`);
55+
});
56+
}
57+
58+
return new LocalPackageImplementation(downloadedPackage);
59+
} finally {
60+
downloadProgressSubscription && downloadProgressSubscription.remove();
61+
}
62+
}
63+
}

src/internals/package-mixins.js

Lines changed: 0 additions & 74 deletions
This file was deleted.

src/internals/packageMixins.ts

Lines changed: 0 additions & 3 deletions
This file was deleted.
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
export function cloneWithoutFunctions(object: object) {
2+
const copy = Object.assign({}, object);
3+
// @ts-ignore
4+
Object.keys(copy).forEach((key) => (typeof copy[key] === "function") && delete copy[key]);
5+
return copy;
6+
}

src/reactNative.d.ts

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,14 @@ declare module "react-native" {
77
export interface NativeEventSubscription {
88
remove(): void;
99
}
10+
export class NativeEventEmitter {
11+
constructor(nativeModule?: any);
12+
addListener(
13+
eventType: string,
14+
listener: (event: any) => void,
15+
context?: Object,
16+
): NativeEventSubscription;
17+
}
1018

1119
type AppStateStatus = string;
1220
export interface AppStateStatic {

0 commit comments

Comments
 (0)