relay-ota-react-native 0.1.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.
Files changed (56) hide show
  1. package/README.md +376 -0
  2. package/dist/client.d.ts +3 -0
  3. package/dist/client.d.ts.map +1 -0
  4. package/dist/client.js +16 -0
  5. package/dist/client.js.map +1 -0
  6. package/dist/downloader.d.ts +6 -0
  7. package/dist/downloader.d.ts.map +1 -0
  8. package/dist/downloader.js +65 -0
  9. package/dist/downloader.js.map +1 -0
  10. package/dist/filesystem.d.ts +4 -0
  11. package/dist/filesystem.d.ts.map +1 -0
  12. package/dist/filesystem.js +63 -0
  13. package/dist/filesystem.js.map +1 -0
  14. package/dist/hooks.d.ts +15 -0
  15. package/dist/hooks.d.ts.map +1 -0
  16. package/dist/hooks.js +34 -0
  17. package/dist/hooks.js.map +1 -0
  18. package/dist/index.d.ts +9 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +25 -0
  21. package/dist/index.js.map +1 -0
  22. package/dist/installer.d.ts +6 -0
  23. package/dist/installer.d.ts.map +1 -0
  24. package/dist/installer.js +46 -0
  25. package/dist/installer.js.map +1 -0
  26. package/dist/provider.d.ts +18 -0
  27. package/dist/provider.d.ts.map +1 -0
  28. package/dist/provider.js +82 -0
  29. package/dist/provider.js.map +1 -0
  30. package/dist/storage.d.ts +12 -0
  31. package/dist/storage.d.ts.map +1 -0
  32. package/dist/storage.js +44 -0
  33. package/dist/storage.js.map +1 -0
  34. package/dist/types.d.ts +55 -0
  35. package/dist/types.d.ts.map +1 -0
  36. package/dist/types.js +3 -0
  37. package/dist/types.js.map +1 -0
  38. package/dist/updater.d.ts +17 -0
  39. package/dist/updater.d.ts.map +1 -0
  40. package/dist/updater.js +98 -0
  41. package/dist/updater.js.map +1 -0
  42. package/package.json +60 -0
  43. package/src/client.ts +19 -0
  44. package/src/downloader.ts +79 -0
  45. package/src/filesystem.ts +62 -0
  46. package/src/hooks.ts +46 -0
  47. package/src/index.ts +21 -0
  48. package/src/installer.ts +42 -0
  49. package/src/native/OtaBundleUpdater.h +5 -0
  50. package/src/native/OtaBundleUpdater.m +56 -0
  51. package/src/native/OtaBundleUpdaterModule.kt +73 -0
  52. package/src/native/OtaBundleUpdaterPackage.kt +14 -0
  53. package/src/provider.tsx +77 -0
  54. package/src/storage.ts +42 -0
  55. package/src/types.ts +68 -0
  56. package/src/updater.ts +115 -0
package/README.md ADDED
@@ -0,0 +1,376 @@
1
+ # relay-ota-react-native
2
+
3
+ **Over-the-air updates for React Native — ship JS bundle changes instantly, without App Store review.**
4
+
5
+ Open-source drop-in replacement for the retired Microsoft CodePush and a self-hosted alternative to Expo EAS Updates.
6
+
7
+ [![npm version](https://img.shields.io/npm/v/relay-ota-react-native.svg?style=flat-square)](https://www.npmjs.com/package/relay-ota-react-native)
8
+ [![npm downloads](https://img.shields.io/npm/dm/relay-ota-react-native.svg?style=flat-square)](https://www.npmjs.com/package/relay-ota-react-native)
9
+ [![license](https://img.shields.io/npm/l/relay-ota-react-native.svg?style=flat-square)](https://github.com/aglaonematech/relay-ota-react-native/blob/main/LICENSE)
10
+ [![GitHub stars](https://img.shields.io/github/stars/aglaonematech/relay-ota-react-native?style=flat-square)](https://github.com/aglaonematech/relay-ota-react-native)
11
+
12
+ **Website:** [relayota.com](https://relayota.com) · **Docs:** [relayota.com/docs](https://relayota.com/docs) · **GitHub:** [aglaonematech/relay-ota-react-native](https://github.com/aglaonematech/relay-ota-react-native)
13
+
14
+ ---
15
+
16
+ ## What is Relay OTA?
17
+
18
+ Relay OTA lets you push JavaScript bundle updates directly to your users' devices — no App Store or Play Store review needed. It's a fully open-source, self-hosted platform: you own the server, you own the data, and you pay nothing.
19
+
20
+ - **Zero review wait** — critical fixes reach users in seconds
21
+ - **One-click rollback** — bad update? revert instantly from the dashboard
22
+ - **Channels** — separate `production` and `staging` environments
23
+ - **Staged rollouts** — release to a percentage of users before going 100%
24
+ - **Mandatory updates** — auto-apply security patches without user interaction
25
+ - **Analytics** — track check, download, and apply rates per release
26
+
27
+ Works with **Expo managed workflow** and **bare React Native** (0.72+).
28
+
29
+ ---
30
+
31
+ ## Installation
32
+
33
+ ```sh
34
+ npm install relay-ota-react-native @react-native-async-storage/async-storage
35
+ ```
36
+
37
+ ### Expo projects
38
+
39
+ ```sh
40
+ npx expo install expo-file-system
41
+ ```
42
+
43
+ ### Bare React Native projects
44
+
45
+ ```sh
46
+ npm install react-native-fs
47
+ cd ios && pod install
48
+ ```
49
+
50
+ ---
51
+
52
+ ## Quick start — Expo
53
+
54
+ ```tsx
55
+ import { OtaProvider, useOtaUpdate, createExpoFileSystemAdapter } from 'relay-ota-react-native';
56
+
57
+ const fs = createExpoFileSystemAdapter();
58
+
59
+ export default function App() {
60
+ return (
61
+ <OtaProvider
62
+ fileSystem={fs}
63
+ config={{
64
+ serverUrl: 'https://ota.yourcompany.com', // your self-hosted server
65
+ appId: 'YOUR_APP_ID',
66
+ channel: 'production',
67
+ platform: 'IOS', // or 'ANDROID'
68
+ currentVersion: '1.0.0',
69
+ runtimeVersion: '1.0.0',
70
+ }}
71
+ >
72
+ <YourNavigator />
73
+ </OtaProvider>
74
+ );
75
+ }
76
+ ```
77
+
78
+ Show an update prompt anywhere in your app:
79
+
80
+ ```tsx
81
+ import { useOtaUpdate } from 'relay-ota-react-native';
82
+ import { View, Text, Button } from 'react-native';
83
+
84
+ export function UpdateBanner() {
85
+ const { hasUpdate, isReady, isLoading, progress, downloadUpdate, applyUpdate } = useOtaUpdate();
86
+
87
+ if (hasUpdate) return (
88
+ <View>
89
+ <Text>New version available</Text>
90
+ <Button title="Download" onPress={downloadUpdate} />
91
+ </View>
92
+ );
93
+
94
+ if (isLoading) return <Text>Downloading… {Math.round(progress * 100)}%</Text>;
95
+
96
+ if (isReady) return (
97
+ <View>
98
+ <Text>Update ready</Text>
99
+ <Button title="Restart now" onPress={applyUpdate} />
100
+ </View>
101
+ );
102
+
103
+ return null;
104
+ }
105
+ ```
106
+
107
+ ---
108
+
109
+ ## Quick start — Bare React Native
110
+
111
+ ```tsx
112
+ import { OtaProvider, createRNFSFileSystemAdapter } from 'relay-ota-react-native';
113
+
114
+ const fs = createRNFSFileSystemAdapter();
115
+
116
+ export default function App() {
117
+ return (
118
+ <OtaProvider
119
+ fileSystem={fs}
120
+ config={{
121
+ serverUrl: 'https://ota.yourcompany.com',
122
+ appId: 'YOUR_APP_ID',
123
+ channel: 'production',
124
+ platform: 'ANDROID',
125
+ currentVersion: '1.0.0',
126
+ runtimeVersion: '1.0.0',
127
+ }}
128
+ >
129
+ <YourNavigator />
130
+ </OtaProvider>
131
+ );
132
+ }
133
+ ```
134
+
135
+ Bare React Native requires the `OtaBundleUpdater` native module — see [Native module setup](#native-module-setup) below.
136
+
137
+ ---
138
+
139
+ ## Self-hosting the server
140
+
141
+ This SDK connects to a **Relay OTA server** you run yourself. Getting the server up takes about 5 minutes:
142
+
143
+ ```sh
144
+ git clone https://github.com/aglaonematech/relay-ota.git
145
+ cd relay-ota
146
+ docker compose up -d # starts Postgres, Redis, MinIO
147
+ npm install
148
+ npm run dev
149
+ ```
150
+
151
+ Full setup guide → [relayota.com/docs](https://relayota.com/docs)
152
+
153
+ ---
154
+
155
+ ## OtaProvider config
156
+
157
+ | Prop | Type | Required | Description |
158
+ |------|------|----------|-------------|
159
+ | `serverUrl` | `string` | ✅ | Base URL of your OTA server |
160
+ | `appId` | `string` | ✅ | App ID from the OTA dashboard |
161
+ | `channel` | `string` | ✅ | Release channel — e.g. `'production'`, `'staging'` |
162
+ | `platform` | `'IOS' \| 'ANDROID'` | ✅ | Target platform |
163
+ | `currentVersion` | `string` | ✅ | Current JS bundle version |
164
+ | `runtimeVersion` | `string` | ✅ | Native runtime version — must match the release |
165
+ | `checkOnForeground` | `boolean` | — | Auto-check when app returns to foreground (default: `true`) |
166
+ | `onUpdate` | `(release) => void` | — | Called when a new update is found |
167
+ | `onError` | `(error: Error) => void` | — | Called on check/download errors |
168
+
169
+ ---
170
+
171
+ ## Hooks
172
+
173
+ ### `useOtaUpdate`
174
+
175
+ Full update state and actions:
176
+
177
+ ```tsx
178
+ const {
179
+ status, // UpdateStatus
180
+ progress, // number 0–100 during download
181
+ release, // release metadata or null
182
+ error, // Error | null
183
+ localBundlePath, // path to downloaded bundle or null
184
+
185
+ isLoading, // checking or downloading
186
+ hasUpdate, // status === 'update_available'
187
+ isReady, // status === 'ready'
188
+
189
+ checkForUpdates, // () => Promise<void>
190
+ downloadUpdate, // () => Promise<void>
191
+ applyUpdate, // () => Promise<void> — reloads the app
192
+ rollback, // () => Promise<void> — removes staged bundle, reloads
193
+ } = useOtaUpdate();
194
+ ```
195
+
196
+ **`UpdateStatus` values**
197
+
198
+ | Status | Meaning |
199
+ |--------|---------|
200
+ | `idle` | No check has run yet |
201
+ | `checking` | Checking for an update |
202
+ | `up_to_date` | No update available |
203
+ | `update_available` | Update found, not downloaded |
204
+ | `downloading` | Download in progress |
205
+ | `ready` | Downloaded, waiting for `applyUpdate()` |
206
+ | `error` | Last operation failed — see `error` |
207
+
208
+ ---
209
+
210
+ ### `useAutoUpdate`
211
+
212
+ Automatically downloads mandatory updates. Optionally applies on next foreground.
213
+
214
+ ```tsx
215
+ import { useAutoUpdate } from 'relay-ota-react-native';
216
+
217
+ const { isReady, applyUpdate } = useAutoUpdate({ applyImmediately: false });
218
+ ```
219
+
220
+ | Option | Type | Default | Description |
221
+ |--------|------|---------|-------------|
222
+ | `applyImmediately` | `boolean` | `false` | Auto-call `applyUpdate()` when bundle is ready |
223
+
224
+ ---
225
+
226
+ ## Rollback
227
+
228
+ ```tsx
229
+ const { rollback } = useOtaUpdate();
230
+
231
+ // Clears staged bundle and reloads — app falls back to bundled JS
232
+ <Button title="Rollback" onPress={rollback} />
233
+ ```
234
+
235
+ ---
236
+
237
+ ## Channels
238
+
239
+ ```tsx
240
+ // Staging builds
241
+ config={{ ..., channel: 'staging' }}
242
+
243
+ // Production builds
244
+ config={{ ..., channel: 'production' }}
245
+ ```
246
+
247
+ Releases are scoped per-channel on the server — staging users never receive production releases.
248
+
249
+ ---
250
+
251
+ ## Push a release (CLI)
252
+
253
+ ```sh
254
+ # Build the JS bundle
255
+ npx react-native bundle \
256
+ --platform ios \
257
+ --dev false \
258
+ --bundle-output ./main.jsbundle
259
+
260
+ # Push to your OTA server
261
+ ota release push \
262
+ --channel production \
263
+ --bundle ./main.jsbundle
264
+ ```
265
+
266
+ ---
267
+
268
+ ## Native module setup (bare React Native only)
269
+
270
+ > **Expo managed workflow**: skip — the Expo filesystem adapter handles everything.
271
+
272
+ ### iOS
273
+
274
+ 1. Copy `OtaBundleUpdater.h` and `OtaBundleUpdater.m` from `node_modules/relay-ota-react-native/src/native/` into your Xcode project
275
+ 2. Run `pod install`
276
+
277
+ ### Android
278
+
279
+ 1. Copy `OtaBundleUpdaterModule.kt` and `OtaBundleUpdaterPackage.kt` into `android/app/src/main/java/<your-package>/`
280
+ 2. Register in `MainApplication.kt`:
281
+
282
+ ```kotlin
283
+ override fun getPackages(): List<ReactPackage> =
284
+ PackageList(this).packages.apply {
285
+ add(OtaBundleUpdaterPackage())
286
+ }
287
+ ```
288
+
289
+ ---
290
+
291
+ ## TypeScript types
292
+
293
+ ```ts
294
+ import type {
295
+ OtaConfig,
296
+ UpdateStatus,
297
+ UpdateState,
298
+ IFileSystemAdapter,
299
+ INativeBundleUpdater,
300
+ Platform,
301
+ } from 'relay-ota-react-native';
302
+ ```
303
+
304
+ ### `OtaConfig`
305
+
306
+ ```ts
307
+ interface OtaConfig {
308
+ serverUrl: string;
309
+ appId: string;
310
+ channel: string;
311
+ platform: 'IOS' | 'ANDROID';
312
+ currentVersion: string;
313
+ runtimeVersion: string;
314
+ checkOnForeground?: boolean;
315
+ onUpdate?: (release: Release) => void;
316
+ onError?: (error: Error) => void;
317
+ }
318
+ ```
319
+
320
+ ### `IFileSystemAdapter`
321
+
322
+ Implement this to bring your own filesystem layer:
323
+
324
+ ```ts
325
+ interface IFileSystemAdapter {
326
+ getDocumentDirectory(): string;
327
+ exists(path: string): Promise<boolean>;
328
+ readAsString(path: string, encoding: 'utf8' | 'base64'): Promise<string>;
329
+ writeAsString(path: string, content: string, encoding: 'utf8' | 'base64'): Promise<void>;
330
+ deleteFile(path: string): Promise<void>;
331
+ makeDirectory(path: string): Promise<void>;
332
+ }
333
+ ```
334
+
335
+ ---
336
+
337
+ ## Low-level API
338
+
339
+ ```ts
340
+ import {
341
+ checkForUpdate, // (serverUrl, request) => Promise<OtaCheckResponse>
342
+ downloadBundle, // (release, fs, onProgress) => Promise<string>
343
+ OtaUpdater, // Class — manages the full state machine
344
+ } from 'relay-ota-react-native';
345
+ ```
346
+
347
+ ---
348
+
349
+ ## Migrating from CodePush
350
+
351
+ Microsoft retired CodePush in 2025. Relay OTA uses the same update model and a compatible SDK surface. Key differences:
352
+
353
+ | | CodePush | Relay OTA |
354
+ |---|---|---|
355
+ | Hosting | Vendor (shut down) | Self-hosted, you own it |
356
+ | Source | Closed | Open source (MIT) |
357
+ | Cost | Was paid | Free forever |
358
+ | Rollback | Yes | Yes |
359
+ | Analytics | Basic | Built-in, detailed |
360
+ | Staged rollouts | Yes | Yes |
361
+
362
+ ---
363
+
364
+ ## Links
365
+
366
+ - **Website:** [relayota.com](https://relayota.com)
367
+ - **Docs:** [relayota.com/docs](https://relayota.com/docs)
368
+ - **GitHub:** [github.com/aglaonematech/relay-ota-react-native](https://github.com/aglaonematech/relay-ota-react-native)
369
+ - **npm:** [relay-ota-react-native](https://www.npmjs.com/package/relay-ota-react-native)
370
+ - **Issues:** [github.com/aglaonematech/relay-ota-react-native/issues](https://github.com/aglaonematech/relay-ota-react-native/issues)
371
+
372
+ ---
373
+
374
+ ## License
375
+
376
+ MIT — see [LICENSE](https://github.com/aglaonematech/relay-ota-react-native/blob/main/LICENSE)
@@ -0,0 +1,3 @@
1
+ import type { OtaCheckRequest, OtaCheckResponse } from './types';
2
+ export declare function checkForUpdate(serverUrl: string, request: OtaCheckRequest): Promise<OtaCheckResponse>;
3
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEjE,wBAAsB,cAAc,CAClC,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,gBAAgB,CAAC,CAa3B"}
package/dist/client.js ADDED
@@ -0,0 +1,16 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.checkForUpdate = checkForUpdate;
4
+ async function checkForUpdate(serverUrl, request) {
5
+ const url = `${serverUrl.replace(/\/$/, '')}/api/v1/ota/check`;
6
+ const response = await fetch(url, {
7
+ method: 'POST',
8
+ headers: { 'Content-Type': 'application/json' },
9
+ body: JSON.stringify(request),
10
+ });
11
+ if (!response.ok) {
12
+ throw new Error(`OTA check failed: HTTP ${response.status}`);
13
+ }
14
+ return response.json();
15
+ }
16
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;AAEA,wCAgBC;AAhBM,KAAK,UAAU,cAAc,CAClC,SAAiB,EACjB,OAAwB;IAExB,MAAM,GAAG,GAAG,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,mBAAmB,CAAC;IAC/D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;QAChC,MAAM,EAAE,MAAM;QACd,OAAO,EAAE,EAAE,cAAc,EAAE,kBAAkB,EAAE;QAC/C,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;KAC9B,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,CAAC;QACjB,MAAM,IAAI,KAAK,CAAC,0BAA0B,QAAQ,CAAC,MAAM,EAAE,CAAC,CAAC;IAC/D,CAAC;IAED,OAAO,QAAQ,CAAC,IAAI,EAA+B,CAAC;AACtD,CAAC"}
@@ -0,0 +1,6 @@
1
+ import type { IFileSystemAdapter } from './types';
2
+ import type { OtaCheckResponse } from './types';
3
+ type Release = NonNullable<OtaCheckResponse['release']>;
4
+ export declare function downloadBundle(release: Release, fs: IFileSystemAdapter, onProgress?: (progress: number) => void): Promise<string>;
5
+ export {};
6
+ //# sourceMappingURL=downloader.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"downloader.d.ts","sourceRoot":"","sources":["../src/downloader.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAClD,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,SAAS,CAAC;AAEhD,KAAK,OAAO,GAAG,WAAW,CAAC,gBAAgB,CAAC,SAAS,CAAC,CAAC,CAAC;AAExD,wBAAsB,cAAc,CAClC,OAAO,EAAE,OAAO,EAChB,EAAE,EAAE,kBAAkB,EACtB,UAAU,CAAC,EAAE,CAAC,QAAQ,EAAE,MAAM,KAAK,IAAI,GACtC,OAAO,CAAC,MAAM,CAAC,CAsDjB"}
@@ -0,0 +1,65 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.downloadBundle = downloadBundle;
4
+ async function downloadBundle(release, fs, onProgress) {
5
+ const bundleDir = `${fs.getDocumentDirectory()}ota-bundles/${release.id}`;
6
+ const bundlePath = `${bundleDir}/bundle.js`;
7
+ await fs.makeDirectory(bundleDir);
8
+ const response = await fetch(release.downloadUrl);
9
+ if (!response.ok) {
10
+ throw new Error(`Download failed: HTTP ${response.status}`);
11
+ }
12
+ const contentLength = parseInt(response.headers.get('content-length') ?? '0', 10);
13
+ const reader = response.body?.getReader();
14
+ if (!reader) {
15
+ // Fallback: read entire body at once (no streaming progress)
16
+ const buffer = await response.arrayBuffer();
17
+ const bytes = new Uint8Array(buffer);
18
+ const b64 = uint8ArrayToBase64(bytes);
19
+ await fs.writeAsString(bundlePath, b64, 'base64');
20
+ onProgress?.(100);
21
+ }
22
+ else {
23
+ const chunks = [];
24
+ let received = 0;
25
+ while (true) {
26
+ const { done, value } = await reader.read();
27
+ if (done)
28
+ break;
29
+ chunks.push(value);
30
+ received += value.length;
31
+ if (contentLength > 0) {
32
+ onProgress?.(Math.round((received / contentLength) * 100));
33
+ }
34
+ }
35
+ const total = chunks.reduce((acc, c) => acc + c.length, 0);
36
+ const merged = new Uint8Array(total);
37
+ let offset = 0;
38
+ for (const chunk of chunks) {
39
+ merged.set(chunk, offset);
40
+ offset += chunk.length;
41
+ }
42
+ const checksum = await sha256Hex(merged);
43
+ if (checksum !== release.checksum) {
44
+ throw new Error(`Checksum mismatch: expected ${release.checksum}, got ${checksum}`);
45
+ }
46
+ const b64 = uint8ArrayToBase64(merged);
47
+ await fs.writeAsString(bundlePath, b64, 'base64');
48
+ onProgress?.(100);
49
+ }
50
+ return bundlePath;
51
+ }
52
+ async function sha256Hex(data) {
53
+ const hashBuffer = await crypto.subtle.digest('SHA-256', data);
54
+ const hashArray = Array.from(new Uint8Array(hashBuffer));
55
+ return hashArray.map((b) => b.toString(16).padStart(2, '0')).join('');
56
+ }
57
+ function uint8ArrayToBase64(bytes) {
58
+ let binary = '';
59
+ const len = bytes.byteLength;
60
+ for (let i = 0; i < len; i++) {
61
+ binary += String.fromCharCode(bytes[i]);
62
+ }
63
+ return btoa(binary);
64
+ }
65
+ //# sourceMappingURL=downloader.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"downloader.js","sourceRoot":"","sources":["../src/downloader.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { IFileSystemAdapter } from './types';
2
+ export declare function createExpoFileSystemAdapter(): IFileSystemAdapter;
3
+ export declare function createRNFSFileSystemAdapter(): IFileSystemAdapter;
4
+ //# sourceMappingURL=filesystem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.d.ts","sourceRoot":"","sources":["../src/filesystem.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,SAAS,CAAC;AAGlD,wBAAgB,2BAA2B,IAAI,kBAAkB,CA8BhE;AAGD,wBAAgB,2BAA2B,IAAI,kBAAkB,CAyBhE"}
@@ -0,0 +1,63 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createExpoFileSystemAdapter = createExpoFileSystemAdapter;
4
+ exports.createRNFSFileSystemAdapter = createRNFSFileSystemAdapter;
5
+ // Expo adapter — requires expo-file-system
6
+ function createExpoFileSystemAdapter() {
7
+ // Lazily require so non-Expo projects don't fail at import time
8
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
9
+ const ExpoFS = require('expo-file-system');
10
+ return {
11
+ getDocumentDirectory() {
12
+ return ExpoFS.documentDirectory ?? '';
13
+ },
14
+ async exists(path) {
15
+ const info = await ExpoFS.getInfoAsync(path);
16
+ return info.exists;
17
+ },
18
+ async readAsString(path, encoding) {
19
+ return ExpoFS.readAsStringAsync(path, {
20
+ encoding: encoding === 'base64' ? ExpoFS.EncodingType.Base64 : ExpoFS.EncodingType.UTF8,
21
+ });
22
+ },
23
+ async writeAsString(path, content, encoding) {
24
+ await ExpoFS.writeAsStringAsync(path, content, {
25
+ encoding: encoding === 'base64' ? ExpoFS.EncodingType.Base64 : ExpoFS.EncodingType.UTF8,
26
+ });
27
+ },
28
+ async deleteFile(path) {
29
+ await ExpoFS.deleteAsync(path, { idempotent: true });
30
+ },
31
+ async makeDirectory(path) {
32
+ await ExpoFS.makeDirectoryAsync(path, { intermediates: true });
33
+ },
34
+ };
35
+ }
36
+ // Bare React Native adapter — requires react-native-fs
37
+ function createRNFSFileSystemAdapter() {
38
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
39
+ const RNFS = require('react-native-fs');
40
+ return {
41
+ getDocumentDirectory() {
42
+ return `${RNFS.DocumentDirectoryPath}/`;
43
+ },
44
+ async exists(path) {
45
+ return RNFS.exists(path);
46
+ },
47
+ async readAsString(path, encoding) {
48
+ return RNFS.readFile(path, encoding);
49
+ },
50
+ async writeAsString(path, content, encoding) {
51
+ await RNFS.writeFile(path, content, encoding);
52
+ },
53
+ async deleteFile(path) {
54
+ const exists = await RNFS.exists(path);
55
+ if (exists)
56
+ await RNFS.unlink(path);
57
+ },
58
+ async makeDirectory(path) {
59
+ await RNFS.mkdir(path);
60
+ },
61
+ };
62
+ }
63
+ //# sourceMappingURL=filesystem.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"filesystem.js","sourceRoot":"","sources":["../src/filesystem.ts"],"names":[],"mappings":";;AAGA,kEA8BC;AAGD,kEAyBC;AA3DD,2CAA2C;AAC3C,SAAgB,2BAA2B;IACzC,gEAAgE;IAChE,8DAA8D;IAC9D,MAAM,MAAM,GAAG,OAAO,CAAC,kBAAkB,CAAQ,CAAC;IAElD,OAAO;QACL,oBAAoB;YAClB,OAAO,MAAM,CAAC,iBAAiB,IAAI,EAAE,CAAC;QACxC,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,IAAI;YACf,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YAC7C,OAAO,IAAI,CAAC,MAAM,CAAC;QACrB,CAAC;QACD,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ;YAC/B,OAAO,MAAM,CAAC,iBAAiB,CAAC,IAAI,EAAE;gBACpC,QAAQ,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI;aACxF,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ;YACzC,MAAM,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,OAAO,EAAE;gBAC7C,QAAQ,EAAE,QAAQ,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,YAAY,CAAC,IAAI;aACxF,CAAC,CAAC;QACL,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,IAAI;YACnB,MAAM,MAAM,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,UAAU,EAAE,IAAI,EAAE,CAAC,CAAC;QACvD,CAAC;QACD,KAAK,CAAC,aAAa,CAAC,IAAI;YACtB,MAAM,MAAM,CAAC,kBAAkB,CAAC,IAAI,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACjE,CAAC;KACF,CAAC;AACJ,CAAC;AAED,uDAAuD;AACvD,SAAgB,2BAA2B;IACzC,8DAA8D;IAC9D,MAAM,IAAI,GAAG,OAAO,CAAC,iBAAiB,CAAQ,CAAC;IAE/C,OAAO;QACL,oBAAoB;YAClB,OAAO,GAAG,IAAI,CAAC,qBAAqB,GAAG,CAAC;QAC1C,CAAC;QACD,KAAK,CAAC,MAAM,CAAC,IAAI;YACf,OAAO,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QAC3B,CAAC;QACD,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,QAAQ;YAC/B,OAAO,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE,QAAQ,CAAC,CAAC;QACvC,CAAC;QACD,KAAK,CAAC,aAAa,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ;YACzC,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,OAAO,EAAE,QAAQ,CAAC,CAAC;QAChD,CAAC;QACD,KAAK,CAAC,UAAU,CAAC,IAAI;YACnB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;YACvC,IAAI,MAAM;gBAAE,MAAM,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACtC,CAAC;QACD,KAAK,CAAC,aAAa,CAAC,IAAI;YACtB,MAAM,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACzB,CAAC;KACF,CAAC;AACJ,CAAC"}
@@ -0,0 +1,15 @@
1
+ import type { UpdateState } from './types';
2
+ export interface UseOtaUpdateReturn extends UpdateState {
3
+ checkForUpdates: () => Promise<void>;
4
+ downloadUpdate: () => Promise<void>;
5
+ applyUpdate: () => Promise<void>;
6
+ rollback: () => Promise<void>;
7
+ isLoading: boolean;
8
+ hasUpdate: boolean;
9
+ isReady: boolean;
10
+ }
11
+ export declare function useOtaUpdate(): UseOtaUpdateReturn;
12
+ export declare function useAutoUpdate(options?: {
13
+ applyImmediately?: boolean;
14
+ }): UseOtaUpdateReturn;
15
+ //# sourceMappingURL=hooks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,SAAS,CAAC;AAE3C,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,eAAe,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACrC,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,WAAW,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACjC,QAAQ,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IAC9B,SAAS,EAAE,OAAO,CAAC;IACnB,SAAS,EAAE,OAAO,CAAC;IACnB,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAgB,YAAY,IAAI,kBAAkB,CAajD;AAGD,wBAAgB,aAAa,CAAC,OAAO,CAAC,EAAE;IAAE,gBAAgB,CAAC,EAAE,OAAO,CAAA;CAAE,sBAerE"}
package/dist/hooks.js ADDED
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.useOtaUpdate = useOtaUpdate;
4
+ exports.useAutoUpdate = useAutoUpdate;
5
+ const react_1 = require("react");
6
+ const provider_1 = require("./provider");
7
+ function useOtaUpdate() {
8
+ const { state, checkForUpdates, downloadUpdate, applyUpdate, rollback } = (0, provider_1.useOtaContext)();
9
+ return {
10
+ ...state,
11
+ checkForUpdates: (0, react_1.useCallback)(checkForUpdates, [checkForUpdates]),
12
+ downloadUpdate: (0, react_1.useCallback)(downloadUpdate, [downloadUpdate]),
13
+ applyUpdate: (0, react_1.useCallback)(applyUpdate, [applyUpdate]),
14
+ rollback: (0, react_1.useCallback)(rollback, [rollback]),
15
+ isLoading: state.status === 'checking' || state.status === 'downloading',
16
+ hasUpdate: state.status === 'update_available',
17
+ isReady: state.status === 'ready',
18
+ };
19
+ }
20
+ // Hook that auto-downloads and applies mandatory updates
21
+ function useAutoUpdate(options) {
22
+ const ota = useOtaUpdate();
23
+ const applyImmediately = options?.applyImmediately ?? false;
24
+ // Auto-download when update is detected
25
+ if (ota.hasUpdate && ota.release?.isMandatory) {
26
+ ota.downloadUpdate();
27
+ }
28
+ // Auto-apply when ready and applyImmediately is set
29
+ if (ota.isReady && applyImmediately) {
30
+ ota.applyUpdate();
31
+ }
32
+ return ota;
33
+ }
34
+ //# sourceMappingURL=hooks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks.js","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":";;AAcA,oCAaC;AAGD,sCAeC;AA7CD,iCAAoC;AACpC,yCAA2C;AAa3C,SAAgB,YAAY;IAC1B,MAAM,EAAE,KAAK,EAAE,eAAe,EAAE,cAAc,EAAE,WAAW,EAAE,QAAQ,EAAE,GAAG,IAAA,wBAAa,GAAE,CAAC;IAE1F,OAAO;QACL,GAAG,KAAK;QACR,eAAe,EAAE,IAAA,mBAAW,EAAC,eAAe,EAAE,CAAC,eAAe,CAAC,CAAC;QAChE,cAAc,EAAE,IAAA,mBAAW,EAAC,cAAc,EAAE,CAAC,cAAc,CAAC,CAAC;QAC7D,WAAW,EAAE,IAAA,mBAAW,EAAC,WAAW,EAAE,CAAC,WAAW,CAAC,CAAC;QACpD,QAAQ,EAAE,IAAA,mBAAW,EAAC,QAAQ,EAAE,CAAC,QAAQ,CAAC,CAAC;QAC3C,SAAS,EAAE,KAAK,CAAC,MAAM,KAAK,UAAU,IAAI,KAAK,CAAC,MAAM,KAAK,aAAa;QACxE,SAAS,EAAE,KAAK,CAAC,MAAM,KAAK,kBAAkB;QAC9C,OAAO,EAAE,KAAK,CAAC,MAAM,KAAK,OAAO;KAClC,CAAC;AACJ,CAAC;AAED,yDAAyD;AACzD,SAAgB,aAAa,CAAC,OAAwC;IACpE,MAAM,GAAG,GAAG,YAAY,EAAE,CAAC;IAC3B,MAAM,gBAAgB,GAAG,OAAO,EAAE,gBAAgB,IAAI,KAAK,CAAC;IAE5D,wCAAwC;IACxC,IAAI,GAAG,CAAC,SAAS,IAAI,GAAG,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC;QAC9C,GAAG,CAAC,cAAc,EAAE,CAAC;IACvB,CAAC;IAED,oDAAoD;IACpD,IAAI,GAAG,CAAC,OAAO,IAAI,gBAAgB,EAAE,CAAC;QACpC,GAAG,CAAC,WAAW,EAAE,CAAC;IACpB,CAAC;IAED,OAAO,GAAG,CAAC;AACb,CAAC"}
@@ -0,0 +1,9 @@
1
+ export { OtaProvider, useOtaContext } from './provider';
2
+ export { useOtaUpdate, useAutoUpdate } from './hooks';
3
+ export { OtaUpdater } from './updater';
4
+ export { checkForUpdate } from './client';
5
+ export { downloadBundle } from './downloader';
6
+ export { createExpoFileSystemAdapter, createRNFSFileSystemAdapter } from './filesystem';
7
+ export { isNativeModuleAvailable, setStagedBundlePath, getStagedBundlePath, clearStagedBundlePath, reload, } from './installer';
8
+ export type { OtaConfig, UpdateStatus, UpdateState, IFileSystemAdapter, INativeBundleUpdater, Platform, } from './types';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AACxD,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,WAAW,CAAC;AACvC,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAC9C,OAAO,EAAE,2BAA2B,EAAE,2BAA2B,EAAE,MAAM,cAAc,CAAC;AACxF,OAAO,EACL,uBAAuB,EACvB,mBAAmB,EACnB,mBAAmB,EACnB,qBAAqB,EACrB,MAAM,GACP,MAAM,aAAa,CAAC;AACrB,YAAY,EACV,SAAS,EACT,YAAY,EACZ,WAAW,EACX,kBAAkB,EAClB,oBAAoB,EACpB,QAAQ,GACT,MAAM,SAAS,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.reload = exports.clearStagedBundlePath = exports.getStagedBundlePath = exports.setStagedBundlePath = exports.isNativeModuleAvailable = exports.createRNFSFileSystemAdapter = exports.createExpoFileSystemAdapter = exports.downloadBundle = exports.checkForUpdate = exports.OtaUpdater = exports.useAutoUpdate = exports.useOtaUpdate = exports.useOtaContext = exports.OtaProvider = void 0;
4
+ var provider_1 = require("./provider");
5
+ Object.defineProperty(exports, "OtaProvider", { enumerable: true, get: function () { return provider_1.OtaProvider; } });
6
+ Object.defineProperty(exports, "useOtaContext", { enumerable: true, get: function () { return provider_1.useOtaContext; } });
7
+ var hooks_1 = require("./hooks");
8
+ Object.defineProperty(exports, "useOtaUpdate", { enumerable: true, get: function () { return hooks_1.useOtaUpdate; } });
9
+ Object.defineProperty(exports, "useAutoUpdate", { enumerable: true, get: function () { return hooks_1.useAutoUpdate; } });
10
+ var updater_1 = require("./updater");
11
+ Object.defineProperty(exports, "OtaUpdater", { enumerable: true, get: function () { return updater_1.OtaUpdater; } });
12
+ var client_1 = require("./client");
13
+ Object.defineProperty(exports, "checkForUpdate", { enumerable: true, get: function () { return client_1.checkForUpdate; } });
14
+ var downloader_1 = require("./downloader");
15
+ Object.defineProperty(exports, "downloadBundle", { enumerable: true, get: function () { return downloader_1.downloadBundle; } });
16
+ var filesystem_1 = require("./filesystem");
17
+ Object.defineProperty(exports, "createExpoFileSystemAdapter", { enumerable: true, get: function () { return filesystem_1.createExpoFileSystemAdapter; } });
18
+ Object.defineProperty(exports, "createRNFSFileSystemAdapter", { enumerable: true, get: function () { return filesystem_1.createRNFSFileSystemAdapter; } });
19
+ var installer_1 = require("./installer");
20
+ Object.defineProperty(exports, "isNativeModuleAvailable", { enumerable: true, get: function () { return installer_1.isNativeModuleAvailable; } });
21
+ Object.defineProperty(exports, "setStagedBundlePath", { enumerable: true, get: function () { return installer_1.setStagedBundlePath; } });
22
+ Object.defineProperty(exports, "getStagedBundlePath", { enumerable: true, get: function () { return installer_1.getStagedBundlePath; } });
23
+ Object.defineProperty(exports, "clearStagedBundlePath", { enumerable: true, get: function () { return installer_1.clearStagedBundlePath; } });
24
+ Object.defineProperty(exports, "reload", { enumerable: true, get: function () { return installer_1.reload; } });
25
+ //# sourceMappingURL=index.js.map