react-native-bspatch 1.0.4 → 1.0.5

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.
@@ -14,7 +14,20 @@ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e
14
14
  * - Manifest: `${baseUrl}/${baseFolder}/ota_registry.json`
15
15
  * - Patch file: `${baseUrl}/${baseFolder}/${appVersion}/${channel}/${filename}`
16
16
  * - Assets: `${baseUrl}/${baseFolder}/assets/${hash}.${ext}`
17
+ *
18
+ * NOTE: All manifest/registry fetches include Cache-Control: no-cache and a
19
+ * timestamp query param to bypass GitHub CDN's 5-minute (max-age=300) cache.
20
+ * Asset URLs are content-addressed (hash-named) so they are immutable and
21
+ * intentionally NOT cache-busted.
17
22
  */
23
+
24
+ /** Headers to bypass GitHub CDN cache on mutable files (registry, manifests) */
25
+ const NO_CACHE_HEADERS = {
26
+ 'Cache-Control': 'no-cache'
27
+ };
28
+
29
+ /** Append a timestamp query param to defeat CDN caches on mutable URLs */
30
+ const bustCache = url => `${url}?cb=${Date.now()}`;
18
31
  class GitHubRawStorageProvider {
19
32
  async fetchManifest(config) {
20
33
  if (!config.customServer) return config.bundledPatches || [];
@@ -24,9 +37,10 @@ class GitHubRawStorageProvider {
24
37
  baseFolder = 'ota'
25
38
  } = config.customServer;
26
39
  const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
27
- const registryUrl = `${normalizedBaseUrl}/${baseFolder}/ota_registry.json`;
40
+ // Cache-bust: registry is mutable; must always fetch the latest version
41
+ const registryUrl = bustCache(`${normalizedBaseUrl}/${baseFolder}/ota_registry.json`);
28
42
  try {
29
- const res = await _reactNativeBlobUtil.default.fetch('GET', registryUrl);
43
+ const res = await _reactNativeBlobUtil.default.fetch('GET', registryUrl, NO_CACHE_HEADERS);
30
44
  if (res.respInfo.status !== 200) {
31
45
  throw new Error(`Registry fetch failed with status ${res.respInfo.status}`);
32
46
  }
@@ -53,7 +67,10 @@ class GitHubRawStorageProvider {
53
67
  } = config.customServer;
54
68
  const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
55
69
  const channelName = channel.toLowerCase();
56
- return `${normalizedBaseUrl}/${baseFolder}/${config.appVersion}/${channelName}/${filename}`;
70
+
71
+ // Cache-bust: patch files are versioned by name but GitHub CDN may
72
+ // serve a stale 404 response for newly uploaded files within 5 min.
73
+ return bustCache(`${normalizedBaseUrl}/${baseFolder}/${config.appVersion}/${channelName}/${filename}`);
57
74
  }
58
75
  async getAssetUrl(hash, ext, config) {
59
76
  if (!config.customServer) return '';
@@ -62,6 +79,8 @@ class GitHubRawStorageProvider {
62
79
  baseFolder = 'ota'
63
80
  } = config.customServer;
64
81
  const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
82
+
83
+ // Assets are content-addressed (hash = filename) → immutable, no cache-bust needed
65
84
  return `${normalizedBaseUrl}/${baseFolder}/assets/${hash}.${ext}`;
66
85
  }
67
86
  }
@@ -1 +1 @@
1
- {"version":3,"names":["_reactNative","require","_reactNativeBlobUtil","_interopRequireDefault","e","__esModule","default","GitHubRawStorageProvider","fetchManifest","config","customServer","bundledPatches","baseUrl","channel","baseFolder","normalizedBaseUrl","endsWith","slice","registryUrl","res","ReactNativeBlobUtil","fetch","respInfo","status","Error","registry","data","JSON","parse","appGroup","apps","appVersion","flavorGroup","flavors","toLowerCase","development","patches","length","filter","p","platform","Platform","OS","error","console","warn","message","getUpdateFileUrl","filename","channelName","getAssetUrl","hash","ext","exports"],"sourceRoot":"../../../../src","sources":["ota/storage/GitHubRawStorage.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["_reactNative","require","_reactNativeBlobUtil","_interopRequireDefault","e","__esModule","default","NO_CACHE_HEADERS","bustCache","url","Date","now","GitHubRawStorageProvider","fetchManifest","config","customServer","bundledPatches","baseUrl","channel","baseFolder","normalizedBaseUrl","endsWith","slice","registryUrl","res","ReactNativeBlobUtil","fetch","respInfo","status","Error","registry","data","JSON","parse","appGroup","apps","appVersion","flavorGroup","flavors","toLowerCase","development","patches","length","filter","p","platform","Platform","OS","error","console","warn","message","getUpdateFileUrl","filename","channelName","getAssetUrl","hash","ext","exports"],"sourceRoot":"../../../../src","sources":["ota/storage/GitHubRawStorage.ts"],"mappings":"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","ignoreList":[]}
@@ -9,7 +9,20 @@ import ReactNativeBlobUtil from 'react-native-blob-util';
9
9
  * - Manifest: `${baseUrl}/${baseFolder}/ota_registry.json`
10
10
  * - Patch file: `${baseUrl}/${baseFolder}/${appVersion}/${channel}/${filename}`
11
11
  * - Assets: `${baseUrl}/${baseFolder}/assets/${hash}.${ext}`
12
+ *
13
+ * NOTE: All manifest/registry fetches include Cache-Control: no-cache and a
14
+ * timestamp query param to bypass GitHub CDN's 5-minute (max-age=300) cache.
15
+ * Asset URLs are content-addressed (hash-named) so they are immutable and
16
+ * intentionally NOT cache-busted.
12
17
  */
18
+
19
+ /** Headers to bypass GitHub CDN cache on mutable files (registry, manifests) */
20
+ const NO_CACHE_HEADERS = {
21
+ 'Cache-Control': 'no-cache'
22
+ };
23
+
24
+ /** Append a timestamp query param to defeat CDN caches on mutable URLs */
25
+ const bustCache = url => `${url}?cb=${Date.now()}`;
13
26
  export class GitHubRawStorageProvider {
14
27
  async fetchManifest(config) {
15
28
  if (!config.customServer) return config.bundledPatches || [];
@@ -19,9 +32,10 @@ export class GitHubRawStorageProvider {
19
32
  baseFolder = 'ota'
20
33
  } = config.customServer;
21
34
  const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
22
- const registryUrl = `${normalizedBaseUrl}/${baseFolder}/ota_registry.json`;
35
+ // Cache-bust: registry is mutable; must always fetch the latest version
36
+ const registryUrl = bustCache(`${normalizedBaseUrl}/${baseFolder}/ota_registry.json`);
23
37
  try {
24
- const res = await ReactNativeBlobUtil.fetch('GET', registryUrl);
38
+ const res = await ReactNativeBlobUtil.fetch('GET', registryUrl, NO_CACHE_HEADERS);
25
39
  if (res.respInfo.status !== 200) {
26
40
  throw new Error(`Registry fetch failed with status ${res.respInfo.status}`);
27
41
  }
@@ -48,7 +62,10 @@ export class GitHubRawStorageProvider {
48
62
  } = config.customServer;
49
63
  const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
50
64
  const channelName = channel.toLowerCase();
51
- return `${normalizedBaseUrl}/${baseFolder}/${config.appVersion}/${channelName}/${filename}`;
65
+
66
+ // Cache-bust: patch files are versioned by name but GitHub CDN may
67
+ // serve a stale 404 response for newly uploaded files within 5 min.
68
+ return bustCache(`${normalizedBaseUrl}/${baseFolder}/${config.appVersion}/${channelName}/${filename}`);
52
69
  }
53
70
  async getAssetUrl(hash, ext, config) {
54
71
  if (!config.customServer) return '';
@@ -57,6 +74,8 @@ export class GitHubRawStorageProvider {
57
74
  baseFolder = 'ota'
58
75
  } = config.customServer;
59
76
  const normalizedBaseUrl = baseUrl.endsWith('/') ? baseUrl.slice(0, -1) : baseUrl;
77
+
78
+ // Assets are content-addressed (hash = filename) → immutable, no cache-bust needed
60
79
  return `${normalizedBaseUrl}/${baseFolder}/assets/${hash}.${ext}`;
61
80
  }
62
81
  }
@@ -1 +1 @@
1
- {"version":3,"names":["Platform","ReactNativeBlobUtil","GitHubRawStorageProvider","fetchManifest","config","customServer","bundledPatches","baseUrl","channel","baseFolder","normalizedBaseUrl","endsWith","slice","registryUrl","res","fetch","respInfo","status","Error","registry","data","JSON","parse","appGroup","apps","appVersion","flavorGroup","flavors","toLowerCase","development","patches","length","filter","p","platform","OS","error","console","warn","message","getUpdateFileUrl","filename","channelName","getAssetUrl","hash","ext"],"sourceRoot":"../../../../src","sources":["ota/storage/GitHubRawStorage.ts"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["Platform","ReactNativeBlobUtil","NO_CACHE_HEADERS","bustCache","url","Date","now","GitHubRawStorageProvider","fetchManifest","config","customServer","bundledPatches","baseUrl","channel","baseFolder","normalizedBaseUrl","endsWith","slice","registryUrl","res","fetch","respInfo","status","Error","registry","data","JSON","parse","appGroup","apps","appVersion","flavorGroup","flavors","toLowerCase","development","patches","length","filter","p","platform","OS","error","console","warn","message","getUpdateFileUrl","filename","channelName","getAssetUrl","hash","ext"],"sourceRoot":"../../../../src","sources":["ota/storage/GitHubRawStorage.ts"],"mappings":"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","ignoreList":[]}
@@ -1,12 +1,4 @@
1
1
  import type { OtaConfig, OtaPatch, OtaStorageProvider } from '../types';
2
- /**
3
- * Storage Provider for fetching OTA updates directly from a GitHub Raw repository.
4
- *
5
- * Direct URL mapping:
6
- * - Manifest: `${baseUrl}/${baseFolder}/ota_registry.json`
7
- * - Patch file: `${baseUrl}/${baseFolder}/${appVersion}/${channel}/${filename}`
8
- * - Assets: `${baseUrl}/${baseFolder}/assets/${hash}.${ext}`
9
- */
10
2
  export declare class GitHubRawStorageProvider implements OtaStorageProvider {
11
3
  fetchManifest(config: OtaConfig): Promise<OtaPatch[]>;
12
4
  getUpdateFileUrl(filename: string, config: OtaConfig): Promise<string>;
@@ -1 +1 @@
1
- {"version":3,"file":"GitHubRawStorage.d.ts","sourceRoot":"","sources":["../../../../src/ota/storage/GitHubRawStorage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAExE;;;;;;;GAOG;AACH,qBAAa,wBAAyB,YAAW,kBAAkB;IACzD,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IA6CrD,gBAAgB,CAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,GAClB,OAAO,CAAC,MAAM,CAAC;IAcZ,WAAW,CACb,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,SAAS,GAClB,OAAO,CAAC,MAAM,CAAC;CAUrB"}
1
+ {"version":3,"file":"GitHubRawStorage.d.ts","sourceRoot":"","sources":["../../../../src/ota/storage/GitHubRawStorage.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,SAAS,EAAE,QAAQ,EAAE,kBAAkB,EAAE,MAAM,UAAU,CAAC;AAuBxE,qBAAa,wBAAyB,YAAW,kBAAkB;IACzD,aAAa,CAAC,MAAM,EAAE,SAAS,GAAG,OAAO,CAAC,QAAQ,EAAE,CAAC;IAoDrD,gBAAgB,CAClB,QAAQ,EAAE,MAAM,EAChB,MAAM,EAAE,SAAS,GAClB,OAAO,CAAC,MAAM,CAAC;IAkBZ,WAAW,CACb,IAAI,EAAE,MAAM,EACZ,GAAG,EAAE,MAAM,EACX,MAAM,EAAE,SAAS,GAClB,OAAO,CAAC,MAAM,CAAC;CAWrB"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-bspatch",
3
- "version": "1.0.4",
3
+ "version": "1.0.5",
4
4
  "description": "Premium OTA Update Solution for React Native using TurboModules and bsdiff",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
@@ -9,7 +9,20 @@ import type { OtaConfig, OtaPatch, OtaStorageProvider } from '../types';
9
9
  * - Manifest: `${baseUrl}/${baseFolder}/ota_registry.json`
10
10
  * - Patch file: `${baseUrl}/${baseFolder}/${appVersion}/${channel}/${filename}`
11
11
  * - Assets: `${baseUrl}/${baseFolder}/assets/${hash}.${ext}`
12
+ *
13
+ * NOTE: All manifest/registry fetches include Cache-Control: no-cache and a
14
+ * timestamp query param to bypass GitHub CDN's 5-minute (max-age=300) cache.
15
+ * Asset URLs are content-addressed (hash-named) so they are immutable and
16
+ * intentionally NOT cache-busted.
12
17
  */
18
+
19
+ /** Headers to bypass GitHub CDN cache on mutable files (registry, manifests) */
20
+ const NO_CACHE_HEADERS = { 'Cache-Control': 'no-cache' };
21
+
22
+ /** Append a timestamp query param to defeat CDN caches on mutable URLs */
23
+ const bustCache = (url: string): string =>
24
+ `${url}?cb=${Date.now()}`;
25
+
13
26
  export class GitHubRawStorageProvider implements OtaStorageProvider {
14
27
  async fetchManifest(config: OtaConfig): Promise<OtaPatch[]> {
15
28
  if (!config.customServer) return config.bundledPatches || [];
@@ -18,10 +31,17 @@ export class GitHubRawStorageProvider implements OtaStorageProvider {
18
31
  const normalizedBaseUrl = baseUrl.endsWith('/')
19
32
  ? baseUrl.slice(0, -1)
20
33
  : baseUrl;
21
- const registryUrl = `${normalizedBaseUrl}/${baseFolder}/ota_registry.json`;
34
+ // Cache-bust: registry is mutable; must always fetch the latest version
35
+ const registryUrl = bustCache(
36
+ `${normalizedBaseUrl}/${baseFolder}/ota_registry.json`,
37
+ );
22
38
 
23
39
  try {
24
- const res = await ReactNativeBlobUtil.fetch('GET', registryUrl);
40
+ const res = await ReactNativeBlobUtil.fetch(
41
+ 'GET',
42
+ registryUrl,
43
+ NO_CACHE_HEADERS,
44
+ );
25
45
  if (res.respInfo.status !== 200) {
26
46
  throw new Error(
27
47
  `Registry fetch failed with status ${res.respInfo.status}`,
@@ -70,7 +90,11 @@ export class GitHubRawStorageProvider implements OtaStorageProvider {
70
90
  : baseUrl;
71
91
  const channelName = channel.toLowerCase();
72
92
 
73
- return `${normalizedBaseUrl}/${baseFolder}/${config.appVersion}/${channelName}/${filename}`;
93
+ // Cache-bust: patch files are versioned by name but GitHub CDN may
94
+ // serve a stale 404 response for newly uploaded files within 5 min.
95
+ return bustCache(
96
+ `${normalizedBaseUrl}/${baseFolder}/${config.appVersion}/${channelName}/${filename}`,
97
+ );
74
98
  }
75
99
 
76
100
  async getAssetUrl(
@@ -85,6 +109,7 @@ export class GitHubRawStorageProvider implements OtaStorageProvider {
85
109
  ? baseUrl.slice(0, -1)
86
110
  : baseUrl;
87
111
 
112
+ // Assets are content-addressed (hash = filename) → immutable, no cache-bust needed
88
113
  return `${normalizedBaseUrl}/${baseFolder}/assets/${hash}.${ext}`;
89
114
  }
90
115
  }
@@ -95,9 +95,11 @@ if [ "$ACTION" != "reset" ]; then
95
95
 
96
96
  if [[ "$BASE_URL" == *"github"* ]] || [[ "$BASE_URL" == *"raw.githubusercontent"* ]]; then
97
97
  echo " Downloading remote registry from GitHub..."
98
- HTTP_CODE=$(curl -s -w "%{http_code}" -o "$REGISTRY_SHARED.tmp" "$BASE_URL/$BASE_FOLDER/ota_registry.json" 2>/dev/null || true)
98
+ # Add cache-busting params + Cache-Control header to bypass GitHub CDN 5-min cache
99
+ CACHE_BUST="?cb=$(date +%s)"
100
+ HTTP_CODE=$(curl -s -w "%{http_code}" -H "Cache-Control: no-cache" -o "$REGISTRY_SHARED.tmp" "$BASE_URL/$BASE_FOLDER/ota_registry.json${CACHE_BUST}" 2>/dev/null || true)
99
101
  if [ "$HTTP_CODE" != "200" ]; then
100
- HTTP_CODE=$(curl -s -w "%{http_code}" -o "$REGISTRY_SHARED.tmp" "$BASE_URL/ota_registry.json" 2>/dev/null || true)
102
+ HTTP_CODE=$(curl -s -w "%{http_code}" -H "Cache-Control: no-cache" -o "$REGISTRY_SHARED.tmp" "$BASE_URL/ota_registry.json${CACHE_BUST}" 2>/dev/null || true)
101
103
  fi
102
104
  if [ "$HTTP_CODE" = "200" ] && [ -s "$REGISTRY_SHARED.tmp" ]; then
103
105
  mv "$REGISTRY_SHARED.tmp" "$REGISTRY_SHARED"
@@ -150,9 +152,12 @@ fi
150
152
  download_from_minio() {
151
153
  local REMOTE_PATH="$1"
152
154
  local DEST="$2"
155
+ local CB="?cb=$(date +%s)"
153
156
 
154
157
  if [[ "$BASE_URL" == *"github"* ]] || [[ "$BASE_URL" == *"raw.githubusercontent"* ]]; then
155
- curl -s -f -o "$DEST" "$BASE_URL/$REMOTE_PATH" 2>/dev/null || curl -s -f -o "$DEST" "$BASE_URL/$(basename "$REMOTE_PATH")" 2>/dev/null
158
+ # Use Cache-Control: no-cache + timestamp query to bypass GitHub CDN 5-min cache
159
+ curl -s -f -H "Cache-Control: no-cache" -o "$DEST" "$BASE_URL/$REMOTE_PATH${CB}" 2>/dev/null || \
160
+ curl -s -f -H "Cache-Control: no-cache" -o "$DEST" "$BASE_URL/$(basename "$REMOTE_PATH")${CB}" 2>/dev/null
156
161
  return $?
157
162
  fi
158
163