@scalebun/react-native 1.6.1 → 1.6.3
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.
- package/README.md +9 -2
- package/bin/lib/iosCodemod.js +77 -0
- package/bin/scalebun.js +9 -5
- package/dist/scalebun.full.js +1 -1
- package/dist/scalebun.slim.js +1 -1
- package/lib/commonjs/core/constants/version.js +1 -1
- package/lib/module/core/constants/version.js +1 -1
- package/lib/typescript/core/constants/version.d.ts +1 -1
- package/package.json +2 -2
- package/src/core/constants/version.ts +1 -1
package/README.md
CHANGED
|
@@ -18,13 +18,20 @@ yarn add @scalebun/react-native
|
|
|
18
18
|
cd ios && pod install
|
|
19
19
|
```
|
|
20
20
|
|
|
21
|
-
|
|
21
|
+
Wire the AppDelegate for **OTA bundle loading** (required for OTA on iOS) and
|
|
22
|
+
Direct APNs push:
|
|
22
23
|
|
|
23
24
|
```sh
|
|
24
25
|
npx scalebun init ios # patch the AppDelegate (ObjC auto-patched; Swift prints steps)
|
|
25
|
-
npx scalebun init ios --check # verify hooks exist (exit 1 if missing)
|
|
26
|
+
npx scalebun init ios --check # verify hooks + OTA bundleURL exist (exit 1 if missing)
|
|
26
27
|
```
|
|
27
28
|
|
|
29
|
+
Like Android, iOS OTA needs the app's bundle resolution wired to the OTA slot
|
|
30
|
+
(`bundleURL` → `ScaleBunOtaModule.getBundleURL()`), or updates install but never
|
|
31
|
+
load. `init ios` auto-applies this to a standard ObjC AppDelegate and prints the
|
|
32
|
+
exact snippet for Swift / custom `bundleURL` bodies. **Rebuild the native app
|
|
33
|
+
afterwards.**
|
|
34
|
+
|
|
28
35
|
### Android
|
|
29
36
|
|
|
30
37
|
OTA updates need one wiring step in `MainApplication` so a downloaded bundle
|
package/bin/lib/iosCodemod.js
CHANGED
|
@@ -35,6 +35,18 @@ const FAIL_CALL = 'ScaleBunEngage didFailToRegisterForRemoteNotificationsWithErr
|
|
|
35
35
|
const REGISTER_SELECTOR = 'didRegisterForRemoteNotificationsWithDeviceToken';
|
|
36
36
|
const FAIL_SELECTOR = 'didFailToRegisterForRemoteNotificationsWithError';
|
|
37
37
|
|
|
38
|
+
// ── OTA bundle resolution (release bundleURL) ────────────────────────────────
|
|
39
|
+
// The release branch of AppDelegate.bundleURL must return the OTA bundle before
|
|
40
|
+
// the one baked into the .ipa, else an OTA update installs and silently never
|
|
41
|
+
// loads. The exact wiring is documented on ScaleBunOtaModule.getBundleURL().
|
|
42
|
+
// Unlike the push hooks (appended methods), this edits INSIDE an existing method,
|
|
43
|
+
// so it is auto-applied only for the standard RN template line and instructed
|
|
44
|
+
// otherwise (and always for Swift).
|
|
45
|
+
const OTA_BUNDLE_CALL = 'getBundleURL';
|
|
46
|
+
// The canonical release-bundle line RN templates emit (whitespace-tolerant).
|
|
47
|
+
const OTA_RELEASE_LINE_RE =
|
|
48
|
+
/return\s*\[\[NSBundle mainBundle\]\s*URLForResource:@"main"\s*withExtension:@"jsbundle"\]\s*;/;
|
|
49
|
+
|
|
38
50
|
// ── AppDelegate discovery ───────────────────────────────────────────────────
|
|
39
51
|
|
|
40
52
|
/**
|
|
@@ -87,6 +99,9 @@ function analyzeObjc(source) {
|
|
|
87
99
|
// does not forward to ScaleBun — we must not add a second one.
|
|
88
100
|
foreignRegisterMethod: definesRegister && !s.includes(REGISTER_CALL),
|
|
89
101
|
foreignFailMethod: definesFail && !s.includes(FAIL_CALL),
|
|
102
|
+
// OTA release-bundle resolution wired (either the ObjC `[... getBundleURL]`
|
|
103
|
+
// or a Swift `.getBundleURL()` form).
|
|
104
|
+
hasOtaBundleUrl: s.includes(OTA_BUNDLE_CALL),
|
|
90
105
|
};
|
|
91
106
|
}
|
|
92
107
|
|
|
@@ -228,9 +243,60 @@ function patchObjc(source) {
|
|
|
228
243
|
if (needFail) summary.push('Added didFailToRegisterForRemoteNotificationsWithError: forwarding');
|
|
229
244
|
}
|
|
230
245
|
|
|
246
|
+
// 5. OTA release-bundle resolution. Auto-apply only the standard template
|
|
247
|
+
// line; otherwise instruct (never rewrite a custom bundleURL body).
|
|
248
|
+
if (!a.hasOtaBundleUrl) {
|
|
249
|
+
const ota = patchBundleUrlForOta(out);
|
|
250
|
+
if (ota.applied) {
|
|
251
|
+
out = ota.source;
|
|
252
|
+
summary.push('Wired release bundleURL → [ScaleBunOtaModule getBundleURL] (OTA)');
|
|
253
|
+
} else {
|
|
254
|
+
manual.push(otaObjcInstructions());
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
|
|
231
258
|
return { changed: out !== String(source), source: out, summary, manual };
|
|
232
259
|
}
|
|
233
260
|
|
|
261
|
+
/**
|
|
262
|
+
* Wire the release branch of AppDelegate.bundleURL to prefer the OTA bundle.
|
|
263
|
+
* Only replaces the canonical RN template line (safe); returns applied:false with
|
|
264
|
+
* a reason when the AppDelegate has a custom bundleURL body we must not rewrite.
|
|
265
|
+
*/
|
|
266
|
+
function patchBundleUrlForOta(source) {
|
|
267
|
+
if (source.includes(OTA_BUNDLE_CALL)) return { source, applied: false, reason: 'present' };
|
|
268
|
+
const m = OTA_RELEASE_LINE_RE.exec(source);
|
|
269
|
+
if (!m) return { source, applied: false, reason: 'no-template-line' };
|
|
270
|
+
const lineStart = source.lastIndexOf('\n', m.index) + 1;
|
|
271
|
+
const indent = (source.slice(lineStart, m.index).match(/^\s*/) || [''])[0];
|
|
272
|
+
const replacement =
|
|
273
|
+
`NSURL *scalebunOtaURL = [ScaleBunOtaModule getBundleURL];\n` +
|
|
274
|
+
`${indent}if (scalebunOtaURL) return scalebunOtaURL;\n` +
|
|
275
|
+
`${indent}${m[0]}`;
|
|
276
|
+
return {
|
|
277
|
+
source: source.slice(0, m.index) + replacement + source.slice(m.index + m[0].length),
|
|
278
|
+
applied: true,
|
|
279
|
+
};
|
|
280
|
+
}
|
|
281
|
+
|
|
282
|
+
/** Exact ObjC OTA wiring when the standard template line is not found. */
|
|
283
|
+
function otaObjcInstructions() {
|
|
284
|
+
return [
|
|
285
|
+
'OTA bundle resolution is not wired. In your AppDelegate bundleURL (release',
|
|
286
|
+
'branch), return the OTA bundle before the one baked into the .ipa:',
|
|
287
|
+
'',
|
|
288
|
+
' - (NSURL *)bundleURL {',
|
|
289
|
+
' #if DEBUG',
|
|
290
|
+
' return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index"];',
|
|
291
|
+
' #else',
|
|
292
|
+
' NSURL *otaURL = [ScaleBunOtaModule getBundleURL];',
|
|
293
|
+
' if (otaURL) return otaURL;',
|
|
294
|
+
' return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];',
|
|
295
|
+
' #endif',
|
|
296
|
+
' }',
|
|
297
|
+
].join('\n');
|
|
298
|
+
}
|
|
299
|
+
|
|
234
300
|
/** Manual instructions for Swift AppDelegate (auto-patch not supported yet). */
|
|
235
301
|
function swiftInstructions() {
|
|
236
302
|
return [
|
|
@@ -251,6 +317,15 @@ function swiftInstructions() {
|
|
|
251
317
|
' didFailToRegisterForRemoteNotificationsWithError error: Error) {',
|
|
252
318
|
' ScaleBunEngage.didFailToRegisterForRemoteNotifications(error: error)',
|
|
253
319
|
' }',
|
|
320
|
+
'',
|
|
321
|
+
' // OTA bundle resolution — without this, OTA updates install but never load:',
|
|
322
|
+
' override func bundleURL() -> URL? {',
|
|
323
|
+
' #if DEBUG',
|
|
324
|
+
' RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")',
|
|
325
|
+
' #else',
|
|
326
|
+
' ScaleBunOtaModule.getBundleURL()',
|
|
327
|
+
' #endif',
|
|
328
|
+
' }',
|
|
254
329
|
].join('\n');
|
|
255
330
|
}
|
|
256
331
|
|
|
@@ -258,9 +333,11 @@ module.exports = {
|
|
|
258
333
|
SWIFT_HEADER,
|
|
259
334
|
IMPORT_LINE,
|
|
260
335
|
MANAGED_TAG,
|
|
336
|
+
OTA_BUNDLE_CALL,
|
|
261
337
|
findAppDelegate,
|
|
262
338
|
analyzeObjc,
|
|
263
339
|
isFullyWiredObjc,
|
|
264
340
|
patchObjc,
|
|
341
|
+
patchBundleUrlForOta,
|
|
265
342
|
swiftInstructions,
|
|
266
343
|
};
|
package/bin/scalebun.js
CHANGED
|
@@ -529,22 +529,26 @@ function runInitIos(argv) {
|
|
|
529
529
|
|
|
530
530
|
// --check: verify, never write.
|
|
531
531
|
if (isCheck) {
|
|
532
|
-
const wired = codemod.isFullyWiredObjc(original);
|
|
533
532
|
const a = codemod.analyzeObjc(original);
|
|
533
|
+
const pushWired = codemod.isFullyWiredObjc(original);
|
|
534
|
+
const wired = pushWired && a.hasOtaBundleUrl;
|
|
534
535
|
console.log('');
|
|
535
|
-
console.log(paint('
|
|
536
|
+
console.log(paint('Push hooks (APNs)', C.bold));
|
|
536
537
|
line(a.hasImport ? OK() : FAIL(), 'ScaleBun Swift import', a.hasImport ? 'present' : null);
|
|
537
538
|
line(a.hasFinishLaunchingCall ? OK() : FAIL(), 'didFinishLaunching forward', a.hasFinishLaunchingCall ? 'present' : null);
|
|
538
539
|
line(a.hasRegisterForward ? OK() : FAIL(), 'didRegister...DeviceToken forward', a.hasRegisterForward ? 'present' : null);
|
|
539
540
|
line(a.hasFailForward ? OK() : FAIL(), 'didFailToRegister forward', a.hasFailForward ? 'present' : null);
|
|
541
|
+
console.log('');
|
|
542
|
+
console.log(paint('OTA bundle resolution', C.bold));
|
|
543
|
+
line(a.hasOtaBundleUrl ? OK() : FAIL(), 'release bundleURL wiring', a.hasOtaBundleUrl ? 'present' : null);
|
|
540
544
|
const caps = detectIosCapabilities(iosDir);
|
|
541
545
|
printIosChecklist(caps);
|
|
542
546
|
console.log('');
|
|
543
547
|
if (wired) {
|
|
544
|
-
console.log(paint('✓ AppDelegate is fully wired for ScaleBun Direct APNs.', C.green));
|
|
548
|
+
console.log(paint('✓ AppDelegate is fully wired for ScaleBun (Direct APNs + OTA).', C.green));
|
|
545
549
|
process.exit(0);
|
|
546
550
|
}
|
|
547
|
-
console.log(paint('✗ AppDelegate is missing ScaleBun
|
|
551
|
+
console.log(paint('✗ AppDelegate is missing ScaleBun wiring. Run `npx scalebun init ios`.', C.red));
|
|
548
552
|
process.exit(1);
|
|
549
553
|
}
|
|
550
554
|
|
|
@@ -909,7 +913,7 @@ function printFullHelp() {
|
|
|
909
913
|
console.log('');
|
|
910
914
|
console.log(paint('SDK setup (bundled with @scalebun/react-native):', C.bold));
|
|
911
915
|
console.log(' npx scalebun doctor Diagnose push-notification setup');
|
|
912
|
-
console.log(' npx scalebun init ios Wire the iOS AppDelegate for Direct APNs');
|
|
916
|
+
console.log(' npx scalebun init ios Wire the iOS AppDelegate for Direct APNs + OTA');
|
|
913
917
|
console.log(' npx scalebun init android Wire Android MainApplication for OTA bundle loading');
|
|
914
918
|
console.log(paint(' add --check to verify (exit 1 if missing) or --dry-run to preview', C.dim));
|
|
915
919
|
console.log('');
|
package/dist/scalebun.full.js
CHANGED
package/dist/scalebun.slim.js
CHANGED
|
@@ -9,5 +9,5 @@ exports.SDK_VERSION = void 0;
|
|
|
9
9
|
* can attribute telemetry to the SDK build that produced it.
|
|
10
10
|
* Keep in sync with package.json "version".
|
|
11
11
|
*/
|
|
12
|
-
const SDK_VERSION = exports.SDK_VERSION = '1.6.
|
|
12
|
+
const SDK_VERSION = exports.SDK_VERSION = '1.6.3';
|
|
13
13
|
//# sourceMappingURL=version.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@scalebun/react-native",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.3",
|
|
4
4
|
"description": "Production-grade React Native SDK for ScaleBun",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|
|
@@ -105,7 +105,7 @@
|
|
|
105
105
|
"@babel/runtime": "^7.25.0",
|
|
106
106
|
"@jridgewell/sourcemap-codec": "1.5.5",
|
|
107
107
|
"@jridgewell/trace-mapping": "0.3.31",
|
|
108
|
-
"@scalebun/cli": "^1.6.
|
|
108
|
+
"@scalebun/cli": "^1.6.3"
|
|
109
109
|
},
|
|
110
110
|
"codegenConfig": {
|
|
111
111
|
"name": "ScaleBunSpec",
|