react-native-codepush-sdk 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,405 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ const async_storage_1 = __importDefault(require("@react-native-async-storage/async-storage"));
7
+ const react_native_device_info_1 = __importDefault(require("react-native-device-info"));
8
+ const react_native_fs_1 = __importDefault(require("react-native-fs"));
9
+ const react_native_zip_archive_1 = require("react-native-zip-archive");
10
+ const react_native_1 = require("react-native");
11
+ class CustomCodePush {
12
+ constructor(config) {
13
+ this.currentPackage = null;
14
+ this.pendingUpdate = null;
15
+ this.isCheckingForUpdate = false;
16
+ this.isDownloading = false;
17
+ this.isInstalling = false;
18
+ this.config = Object.assign({ checkFrequency: 'ON_APP_START', installMode: 'ON_NEXT_RESTART', minimumBackgroundDuration: 0 }, config);
19
+ // Initialize directories and load stored package before SDK use
20
+ this.readyPromise = (async () => {
21
+ await this.initializeDirectories();
22
+ await this.loadCurrentPackage();
23
+ })();
24
+ }
25
+ /**
26
+ * Wait for SDK initialization (directories + stored package loaded)
27
+ */
28
+ async initialize() {
29
+ return this.readyPromise;
30
+ }
31
+ async initializeDirectories() {
32
+ try {
33
+ await react_native_fs_1.default.mkdir(CustomCodePush.UPDATES_FOLDER);
34
+ await react_native_fs_1.default.mkdir(CustomCodePush.BUNDLES_FOLDER);
35
+ await react_native_fs_1.default.mkdir(CustomCodePush.DOWNLOADS_FOLDER);
36
+ }
37
+ catch (error) {
38
+ console.warn('Failed to create directories:', error);
39
+ }
40
+ }
41
+ async loadCurrentPackage() {
42
+ try {
43
+ const packageData = await async_storage_1.default.getItem(CustomCodePush.CURRENT_PACKAGE_KEY);
44
+ if (packageData) {
45
+ this.currentPackage = JSON.parse(packageData);
46
+ }
47
+ }
48
+ catch (error) {
49
+ console.warn('Failed to load current package:', error);
50
+ }
51
+ }
52
+ async saveCurrentPackage(packageInfo) {
53
+ try {
54
+ await async_storage_1.default.setItem(CustomCodePush.CURRENT_PACKAGE_KEY, JSON.stringify(packageInfo));
55
+ this.currentPackage = packageInfo;
56
+ }
57
+ catch (error) {
58
+ console.warn('Failed to save current package:', error);
59
+ }
60
+ }
61
+ async getDeviceInfo() {
62
+ var _a;
63
+ return {
64
+ platform: react_native_1.Platform.OS,
65
+ platformVersion: react_native_1.Platform.Version,
66
+ appVersion: await react_native_device_info_1.default.getVersion(),
67
+ deviceId: await react_native_device_info_1.default.getUniqueId(),
68
+ deviceModel: await react_native_device_info_1.default.getModel(),
69
+ clientUniqueId: await react_native_device_info_1.default.getUniqueId(),
70
+ currentPackageHash: ((_a = this.currentPackage) === null || _a === void 0 ? void 0 : _a.packageHash) || null,
71
+ };
72
+ }
73
+ async checkForUpdate() {
74
+ var _a, _b;
75
+ if (this.isCheckingForUpdate) {
76
+ throw new Error('Already checking for update');
77
+ }
78
+ this.isCheckingForUpdate = true;
79
+ try {
80
+ const deviceInfo = await this.getDeviceInfo();
81
+ const response = await fetch(`${this.config.serverUrl}/v0.1/public/codepush/update_check`, {
82
+ method: 'POST',
83
+ headers: {
84
+ 'Content-Type': 'application/json',
85
+ },
86
+ body: JSON.stringify({
87
+ deploymentKey: this.config.deploymentKey,
88
+ appVersion: deviceInfo.appVersion || '1.0.0',
89
+ packageHash: (_a = this.currentPackage) === null || _a === void 0 ? void 0 : _a.packageHash,
90
+ clientUniqueId: deviceInfo.clientUniqueId,
91
+ label: (_b = this.currentPackage) === null || _b === void 0 ? void 0 : _b.label,
92
+ }),
93
+ });
94
+ if (!response.ok) {
95
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
96
+ }
97
+ const data = await response.json();
98
+ if (data.updateInfo) {
99
+ const updatePackage = {
100
+ packageHash: data.updateInfo.packageHash,
101
+ label: data.updateInfo.label,
102
+ appVersion: data.updateInfo.appVersion,
103
+ description: data.updateInfo.description || '',
104
+ isMandatory: data.updateInfo.isMandatory || false,
105
+ packageSize: data.updateInfo.size || 0,
106
+ downloadUrl: data.updateInfo.downloadUrl,
107
+ rollout: data.updateInfo.rollout,
108
+ isDisabled: data.updateInfo.isDisabled,
109
+ timestamp: Date.now(),
110
+ };
111
+ this.pendingUpdate = updatePackage;
112
+ return updatePackage;
113
+ }
114
+ return null;
115
+ }
116
+ catch (error) {
117
+ console.log('Error checking for update:', error);
118
+ console.error('Error checking for update:', error);
119
+ throw error;
120
+ }
121
+ finally {
122
+ this.isCheckingForUpdate = false;
123
+ }
124
+ }
125
+ async downloadUpdate(updatePackage, progressCallback) {
126
+ if (this.isDownloading) {
127
+ throw new Error('Already downloading update');
128
+ }
129
+ this.isDownloading = true;
130
+ try {
131
+ // Check if it's a JavaScript file (demo bundles)
132
+ const isJsFile = updatePackage.downloadUrl.endsWith('.js');
133
+ const fileExtension = isJsFile ? 'js' : 'zip';
134
+ const downloadPath = `${CustomCodePush.DOWNLOADS_FOLDER}/${updatePackage.packageHash}.${fileExtension}`;
135
+ // Clean up any existing download
136
+ if (await react_native_fs_1.default.exists(downloadPath)) {
137
+ await react_native_fs_1.default.unlink(downloadPath);
138
+ }
139
+ const downloadResult = await react_native_fs_1.default.downloadFile({
140
+ fromUrl: updatePackage.downloadUrl,
141
+ toFile: downloadPath,
142
+ progress: (res) => {
143
+ if (progressCallback) {
144
+ progressCallback({
145
+ receivedBytes: res.bytesWritten,
146
+ totalBytes: res.contentLength,
147
+ });
148
+ }
149
+ },
150
+ }).promise;
151
+ if (downloadResult.statusCode !== 200) {
152
+ throw new Error(`Download failed with status ${downloadResult.statusCode}`);
153
+ }
154
+ // Verify file size (approximate for JS files)
155
+ const fileStats = await react_native_fs_1.default.stat(downloadPath);
156
+ if (isJsFile) {
157
+ // For JS files, just check if file exists and has content
158
+ if (fileStats.size === 0) {
159
+ throw new Error('Downloaded JavaScript file is empty');
160
+ }
161
+ }
162
+ else {
163
+ // For zip files, check exact size
164
+ if (fileStats.size !== updatePackage.packageSize) {
165
+ throw new Error('Downloaded file size mismatch');
166
+ }
167
+ }
168
+ let localPath;
169
+ if (isJsFile) {
170
+ // For JavaScript files, create a simple structure
171
+ localPath = `${CustomCodePush.BUNDLES_FOLDER}/${updatePackage.packageHash}`;
172
+ await react_native_fs_1.default.mkdir(localPath);
173
+ // Copy the JS file to the bundle location
174
+ const bundlePath = `${localPath}/index.bundle`;
175
+ await react_native_fs_1.default.copyFile(downloadPath, bundlePath);
176
+ // Clean up download file
177
+ await react_native_fs_1.default.unlink(downloadPath);
178
+ }
179
+ else {
180
+ // For zip files, extract as before
181
+ localPath = `${CustomCodePush.BUNDLES_FOLDER}/${updatePackage.packageHash}`;
182
+ await react_native_fs_1.default.mkdir(localPath);
183
+ await (0, react_native_zip_archive_1.unzip)(downloadPath, localPath);
184
+ // Clean up download file
185
+ await react_native_fs_1.default.unlink(downloadPath);
186
+ }
187
+ const localPackage = Object.assign(Object.assign({}, updatePackage), { localPath: localPath, isFirstRun: false, failedInstall: false });
188
+ // Save update metadata
189
+ await async_storage_1.default.setItem(`${CustomCodePush.UPDATE_METADATA_KEY}_${updatePackage.packageHash}`, JSON.stringify(localPackage));
190
+ return localPackage;
191
+ }
192
+ catch (error) {
193
+ console.error('Error downloading update:', error);
194
+ throw error;
195
+ }
196
+ finally {
197
+ this.isDownloading = false;
198
+ }
199
+ }
200
+ async installUpdate(localPackage) {
201
+ if (this.isInstalling) {
202
+ throw new Error('Already installing update');
203
+ }
204
+ this.isInstalling = true;
205
+ try {
206
+ // Validate the package
207
+ const bundlePath = `${localPackage.localPath}/index.bundle`;
208
+ if (!(await react_native_fs_1.default.exists(bundlePath))) {
209
+ throw new Error('Bundle file not found in update package');
210
+ }
211
+ // Mark as current package
212
+ await this.saveCurrentPackage(localPackage);
213
+ // Clear pending update
214
+ this.pendingUpdate = null;
215
+ await async_storage_1.default.removeItem(CustomCodePush.PENDING_UPDATE_KEY);
216
+ // Log installation
217
+ await this.logUpdateInstallation(localPackage, true);
218
+ }
219
+ catch (error) {
220
+ console.error('Error installing update:', error);
221
+ await this.logUpdateInstallation(localPackage, false);
222
+ throw error;
223
+ }
224
+ finally {
225
+ this.isInstalling = false;
226
+ }
227
+ }
228
+ async logUpdateInstallation(localPackage, success) {
229
+ try {
230
+ const deviceInfo = await this.getDeviceInfo();
231
+ await fetch(`${this.config.serverUrl}/v0.1/public/codepush/report_status/deploy`, {
232
+ method: 'POST',
233
+ headers: {
234
+ 'Content-Type': 'application/json',
235
+ },
236
+ body: JSON.stringify({
237
+ deploymentKey: this.config.deploymentKey,
238
+ label: localPackage.label,
239
+ status: success ? 'Deployed' : 'Failed',
240
+ clientUniqueId: deviceInfo.clientUniqueId,
241
+ }),
242
+ });
243
+ }
244
+ catch (error) {
245
+ console.warn('Failed to log update installation:', error);
246
+ }
247
+ }
248
+ async sync(options = {}, statusCallback, downloadProgressCallback) {
249
+ try {
250
+ // Check for update
251
+ statusCallback === null || statusCallback === void 0 ? void 0 : statusCallback({ status: 'CHECKING_FOR_UPDATE' });
252
+ const updatePackage = await this.checkForUpdate();
253
+ if (!updatePackage) {
254
+ statusCallback === null || statusCallback === void 0 ? void 0 : statusCallback({ status: 'UP_TO_DATE' });
255
+ return false;
256
+ }
257
+ // Show update dialog if needed
258
+ if (options.updateDialog && updatePackage.isMandatory) {
259
+ statusCallback === null || statusCallback === void 0 ? void 0 : statusCallback({ status: 'AWAITING_USER_ACTION' });
260
+ // In a real implementation, you would show a native dialog here
261
+ // For now, we'll proceed automatically
262
+ }
263
+ // Download update
264
+ statusCallback === null || statusCallback === void 0 ? void 0 : statusCallback({ status: 'DOWNLOADING_PACKAGE', progress: 0 });
265
+ const localPackage = await this.downloadUpdate(updatePackage, (progress) => {
266
+ const progressPercent = (progress.receivedBytes / progress.totalBytes) * 100;
267
+ statusCallback === null || statusCallback === void 0 ? void 0 : statusCallback({
268
+ status: 'DOWNLOADING_PACKAGE',
269
+ progress: progressPercent,
270
+ downloadedBytes: progress.receivedBytes,
271
+ totalBytes: progress.totalBytes,
272
+ });
273
+ downloadProgressCallback === null || downloadProgressCallback === void 0 ? void 0 : downloadProgressCallback(progress);
274
+ });
275
+ // Install update
276
+ statusCallback === null || statusCallback === void 0 ? void 0 : statusCallback({ status: 'INSTALLING_UPDATE' });
277
+ await this.installUpdate(localPackage);
278
+ const installMode = updatePackage.isMandatory
279
+ ? (options.mandatoryInstallMode || 'IMMEDIATE')
280
+ : (options.installMode || this.config.installMode || 'ON_NEXT_RESTART');
281
+ if (installMode === 'IMMEDIATE') {
282
+ // Restart the app immediately
283
+ this.restartApp();
284
+ }
285
+ statusCallback === null || statusCallback === void 0 ? void 0 : statusCallback({ status: 'UPDATE_INSTALLED' });
286
+ return true;
287
+ }
288
+ catch (error) {
289
+ console.error('Sync error:', error);
290
+ statusCallback === null || statusCallback === void 0 ? void 0 : statusCallback({ status: 'UNKNOWN_ERROR' });
291
+ return false;
292
+ }
293
+ }
294
+ async getCurrentPackage() {
295
+ return this.currentPackage;
296
+ }
297
+ async getUpdateMetadata() {
298
+ return this.currentPackage;
299
+ }
300
+ async clearUpdates() {
301
+ try {
302
+ // Clear storage
303
+ await async_storage_1.default.multiRemove([
304
+ CustomCodePush.CURRENT_PACKAGE_KEY,
305
+ CustomCodePush.PENDING_UPDATE_KEY,
306
+ CustomCodePush.FAILED_UPDATES_KEY,
307
+ ]);
308
+ // Clear files
309
+ if (await react_native_fs_1.default.exists(CustomCodePush.UPDATES_FOLDER)) {
310
+ await react_native_fs_1.default.unlink(CustomCodePush.UPDATES_FOLDER);
311
+ }
312
+ // Reinitialize
313
+ await this.initializeDirectories();
314
+ this.currentPackage = null;
315
+ this.pendingUpdate = null;
316
+ }
317
+ catch (error) {
318
+ console.error('Error clearing updates:', error);
319
+ throw error;
320
+ }
321
+ }
322
+ async rollback() {
323
+ if (!this.currentPackage) {
324
+ throw new Error('No current package to rollback from');
325
+ }
326
+ try {
327
+ // Remove current package
328
+ const packagePath = this.currentPackage.localPath;
329
+ if (await react_native_fs_1.default.exists(packagePath)) {
330
+ await react_native_fs_1.default.unlink(packagePath);
331
+ }
332
+ // Clear current package
333
+ await async_storage_1.default.removeItem(CustomCodePush.CURRENT_PACKAGE_KEY);
334
+ this.currentPackage = null;
335
+ // Log rollback
336
+ await this.logRollback();
337
+ // Restart app to use original bundle
338
+ this.restartApp();
339
+ }
340
+ catch (error) {
341
+ console.error('Error during rollback:', error);
342
+ throw error;
343
+ }
344
+ }
345
+ async logRollback() {
346
+ var _a;
347
+ try {
348
+ const deviceInfo = await this.getDeviceInfo();
349
+ await fetch(`${this.config.serverUrl}/v0.1/public/codepush/report_status/deploy`, {
350
+ method: 'POST',
351
+ headers: {
352
+ 'Content-Type': 'application/json',
353
+ },
354
+ body: JSON.stringify({
355
+ deploymentKey: this.config.deploymentKey,
356
+ label: ((_a = this.currentPackage) === null || _a === void 0 ? void 0 : _a.label) || 'unknown',
357
+ status: 'Rollback',
358
+ clientUniqueId: deviceInfo.clientUniqueId,
359
+ }),
360
+ });
361
+ }
362
+ catch (error) {
363
+ console.warn('Failed to log rollback:', error);
364
+ }
365
+ }
366
+ restartApp() {
367
+ var _a, _b;
368
+ // In a real implementation, you would use a native module to restart the app
369
+ // For now, we'll just reload the React Native bundle
370
+ if (react_native_1.Platform.OS === 'android') {
371
+ // Android restart implementation
372
+ (_a = react_native_1.NativeModules.DevSettings) === null || _a === void 0 ? void 0 : _a.reload();
373
+ }
374
+ else {
375
+ // iOS restart implementation
376
+ (_b = react_native_1.NativeModules.DevSettings) === null || _b === void 0 ? void 0 : _b.reload();
377
+ }
378
+ }
379
+ getBundleUrl() {
380
+ if (this.currentPackage && this.currentPackage.localPath) {
381
+ return `file://${this.currentPackage.localPath}/index.bundle`;
382
+ }
383
+ return null;
384
+ }
385
+ // Static methods for easy integration
386
+ static configure(config) {
387
+ return new CustomCodePush(config);
388
+ }
389
+ static async checkForUpdate(instance) {
390
+ return instance.checkForUpdate();
391
+ }
392
+ static async sync(instance, options, statusCallback, downloadProgressCallback) {
393
+ return instance.sync(options, statusCallback, downloadProgressCallback);
394
+ }
395
+ }
396
+ // Storage keys
397
+ CustomCodePush.CURRENT_PACKAGE_KEY = 'CustomCodePush_CurrentPackage';
398
+ CustomCodePush.PENDING_UPDATE_KEY = 'CustomCodePush_PendingUpdate';
399
+ CustomCodePush.FAILED_UPDATES_KEY = 'CustomCodePush_FailedUpdates';
400
+ CustomCodePush.UPDATE_METADATA_KEY = 'CustomCodePush_UpdateMetadata';
401
+ // File paths
402
+ CustomCodePush.UPDATES_FOLDER = `${react_native_fs_1.default.DocumentDirectoryPath}/CustomCodePush`;
403
+ CustomCodePush.BUNDLES_FOLDER = `${CustomCodePush.UPDATES_FOLDER}/bundles`;
404
+ CustomCodePush.DOWNLOADS_FOLDER = `${CustomCodePush.UPDATES_FOLDER}/downloads`;
405
+ exports.default = CustomCodePush;
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.BundleManager = void 0;
7
+ const react_native_fs_1 = __importDefault(require("react-native-fs"));
8
+ const react_native_1 = require("react-native");
9
+ class BundleManager {
10
+ /**
11
+ * Get the path to the current bundle that should be loaded
12
+ */
13
+ static getCurrentBundlePath() {
14
+ // In a real implementation, this would check if a custom bundle exists
15
+ // and return its path, otherwise return the original bundle path
16
+ return BundleManager.CUSTOM_BUNDLE_PATH;
17
+ }
18
+ /**
19
+ * Check if a custom bundle exists
20
+ */
21
+ static async hasCustomBundle() {
22
+ try {
23
+ return await react_native_fs_1.default.exists(BundleManager.CUSTOM_BUNDLE_PATH);
24
+ }
25
+ catch (error) {
26
+ return false;
27
+ }
28
+ }
29
+ /**
30
+ * Copy a bundle from source to the current bundle location
31
+ */
32
+ static async installBundle(sourcePath) {
33
+ try {
34
+ const bundlePath = `${sourcePath}/index.bundle`;
35
+ if (!(await react_native_fs_1.default.exists(bundlePath))) {
36
+ throw new Error('Bundle file not found in update package');
37
+ }
38
+ // Ensure directory exists
39
+ const bundleDir = BundleManager.CUSTOM_BUNDLE_PATH.substring(0, BundleManager.CUSTOM_BUNDLE_PATH.lastIndexOf('/'));
40
+ await react_native_fs_1.default.mkdir(bundleDir);
41
+ // Copy bundle
42
+ await react_native_fs_1.default.copyFile(bundlePath, BundleManager.CUSTOM_BUNDLE_PATH);
43
+ // Copy assets if they exist
44
+ const assetsSourcePath = `${sourcePath}/assets`;
45
+ const assetsDestPath = `${bundleDir}/assets`;
46
+ if (await react_native_fs_1.default.exists(assetsSourcePath)) {
47
+ // Custom folder copy implementation needed here. For now, this is a placeholder.
48
+ // TODO: Implement folder copy logic or use a third-party utility.
49
+ }
50
+ }
51
+ catch (error) {
52
+ console.error('Failed to install bundle:', error);
53
+ throw error;
54
+ }
55
+ }
56
+ /**
57
+ * Remove the current custom bundle and revert to original
58
+ */
59
+ static async removeCustomBundle() {
60
+ try {
61
+ if (await react_native_fs_1.default.exists(BundleManager.CUSTOM_BUNDLE_PATH)) {
62
+ await react_native_fs_1.default.unlink(BundleManager.CUSTOM_BUNDLE_PATH);
63
+ }
64
+ // Also remove assets directory
65
+ const bundleDir = BundleManager.CUSTOM_BUNDLE_PATH.substring(0, BundleManager.CUSTOM_BUNDLE_PATH.lastIndexOf('/'));
66
+ const assetsPath = `${bundleDir}/assets`;
67
+ if (await react_native_fs_1.default.exists(assetsPath)) {
68
+ await react_native_fs_1.default.unlink(assetsPath);
69
+ }
70
+ }
71
+ catch (error) {
72
+ console.error('Failed to remove custom bundle:', error);
73
+ throw error;
74
+ }
75
+ }
76
+ /**
77
+ * Validate that a bundle is properly formatted
78
+ */
79
+ static async validateBundle(bundlePath) {
80
+ try {
81
+ // Check if bundle file exists
82
+ if (!(await react_native_fs_1.default.exists(bundlePath))) {
83
+ return false;
84
+ }
85
+ // Check file size (should be > 0)
86
+ const stats = await react_native_fs_1.default.stat(bundlePath);
87
+ if (stats.size === 0) {
88
+ return false;
89
+ }
90
+ // Additional validation could include:
91
+ // - Checking bundle format
92
+ // - Verifying bundle signature
93
+ // - Testing bundle loading
94
+ return true;
95
+ }
96
+ catch (error) {
97
+ console.error('Bundle validation failed:', error);
98
+ return false;
99
+ }
100
+ }
101
+ /**
102
+ * Get bundle metadata
103
+ */
104
+ static async getBundleMetadata(bundlePath) {
105
+ try {
106
+ const metadataPath = `${bundlePath}/metadata.json`;
107
+ if (await react_native_fs_1.default.exists(metadataPath)) {
108
+ const metadataContent = await react_native_fs_1.default.readFile(metadataPath, 'utf8');
109
+ return JSON.parse(metadataContent);
110
+ }
111
+ return null;
112
+ }
113
+ catch (error) {
114
+ console.error('Failed to read bundle metadata:', error);
115
+ return null;
116
+ }
117
+ }
118
+ }
119
+ exports.BundleManager = BundleManager;
120
+ BundleManager.ORIGINAL_BUNDLE_PATH = react_native_1.Platform.select({
121
+ ios: `${react_native_fs_1.default.MainBundlePath}/main.jsbundle`,
122
+ android: 'assets://index.android.bundle',
123
+ });
124
+ BundleManager.CUSTOM_BUNDLE_PATH = `${react_native_fs_1.default.DocumentDirectoryPath}/CustomCodePush/current.bundle`;
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,17 @@
1
+ import { useEffect } from 'react';
2
+
3
+ declare global {
4
+ interface Window {
5
+ frameworkReady?: () => void;
6
+ }
7
+ }
8
+
9
+ declare const window: any;
10
+
11
+ export function useFrameworkReady() {
12
+ useEffect(() => {
13
+ if (typeof window !== 'undefined' && window.frameworkReady) {
14
+ window.frameworkReady();
15
+ }
16
+ });
17
+ }
package/index.ts ADDED
@@ -0,0 +1,10 @@
1
+ // Main entry point for React Native CodePush SDK
2
+ export { CodePushProvider, useCodePush } from './src/sdk/CodePushProvider';
3
+ export { default as CustomCodePush } from './src/sdk/CustomCodePush';
4
+ export { default as UpdateChecker } from './src/components/UpdateChecker';
5
+ export { BundleManager } from './src/utils/BundleManager';
6
+ export { codePushService } from './services/codepushService';
7
+ export { useFrameworkReady } from './hooks/useFrameworkReady';
8
+
9
+ // Export types
10
+ export * from './types/codepush';
package/package.json ADDED
@@ -0,0 +1,72 @@
1
+ {
2
+ "name": "react-native-codepush-sdk",
3
+ "version": "1.0.0",
4
+ "description": "A React Native CodePush SDK for over-the-air updates",
5
+ "main": "dist/index.js",
6
+ "types": "dist/index.d.ts",
7
+ "scripts": {
8
+ "build": "tsc --outDir dist",
9
+ "dev": "cd example && npm run start",
10
+ "test": "jest",
11
+ "lint": "eslint .",
12
+ "prepare": "npm run build"
13
+ },
14
+ "keywords": [
15
+ "react-native",
16
+ "codepush",
17
+ "over-the-air",
18
+ "updates",
19
+ "mobile",
20
+ "SDK"
21
+ ],
22
+ "author": "Bùi Sĩ Nam - hyper-mind.dev",
23
+ "license": "MIT",
24
+ "repository": {
25
+ "type": "git",
26
+ "url": "git+https://github.com/picassio/react-native-codepush-sdk.git"
27
+ },
28
+ "homepage": "https://github.com/picassio/react-native-codepush-sdk#readme",
29
+ "bugs": {
30
+ "url": "https://github.com/picassio/react-native-codepush-sdk/issues"
31
+ },
32
+ "publishConfig": {
33
+ "access": "public"
34
+ },
35
+ "peerDependencies": {
36
+ "react": ">=16.8.0",
37
+ "react-native": ">=0.60.0"
38
+ },
39
+ "dependencies": {
40
+ "@react-native-async-storage/async-storage": "^1.23.1",
41
+ "react-native-device-info": "^10.13.0",
42
+ "react-native-fs": "^2.20.0",
43
+ "react-native-zip-archive": "^6.1.0"
44
+ },
45
+ "devDependencies": {
46
+ "@babel/core": "^7.20.0",
47
+ "@babel/preset-env": "^7.20.0",
48
+ "@babel/runtime": "^7.20.0",
49
+ "@types/react": "^18.2.6",
50
+ "@types/react-native": "^0.72.0",
51
+ "babel-jest": "^29.6.3",
52
+ "eslint": "^8.19.0",
53
+ "jest": "^29.6.3",
54
+ "prettier": "2.8.8",
55
+ "typescript": "^5.0.4"
56
+ },
57
+ "files": [
58
+ "dist/",
59
+ "src/components/",
60
+ "src/sdk/",
61
+ "src/utils/",
62
+ "types/",
63
+ "services/",
64
+ "hooks/",
65
+ "index.ts",
66
+ "README.md",
67
+ "LICENSE"
68
+ ],
69
+ "engines": {
70
+ "node": ">=18"
71
+ }
72
+ }