react-native-acoustic-connect-beta 18.0.36 → 18.0.38
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/CHANGELOG.md +2 -1
- package/android/src/main/assets/ConnectBasicConfig.properties +4 -4
- package/cli/doctor.mjs +294 -0
- package/cli/index.mjs +64 -0
- package/cli/ios/add_push_extensions.rb +192 -0
- package/cli/ios/connect_pods.rb +48 -0
- package/cli/ios/setup-push.mjs +196 -0
- package/cli/ios/templates/nce/ConnectNCE.entitlements +10 -0
- package/cli/ios/templates/nce/Info.plist +45 -0
- package/cli/ios/templates/nse/ConnectNSE.entitlements +10 -0
- package/cli/ios/templates/nse/Info.plist +33 -0
- package/cli/lib.mjs +240 -0
- package/ios/AcousticConnectRNConfig.json +7 -153
- package/ios/HybridAcousticConnectRN.swift +16 -0
- package/package.json +7 -3
- package/plugin/build/index.d.ts +16 -7
- package/plugin/build/index.d.ts.map +1 -1
- package/plugin/build/index.js +18 -7
- package/plugin/build/index.js.map +1 -1
- package/plugin/build/withConnectAndroidConfig.d.ts +20 -0
- package/plugin/build/withConnectAndroidConfig.d.ts.map +1 -0
- package/plugin/build/withConnectAndroidConfig.js +64 -0
- package/plugin/build/withConnectAndroidConfig.js.map +1 -0
- package/plugin/build/withConnectNCE.d.ts.map +1 -1
- package/plugin/build/withConnectNCE.js +20 -1
- package/plugin/build/withConnectNCE.js.map +1 -1
- package/plugin/build/withConnectNSE.d.ts +10 -2
- package/plugin/build/withConnectNSE.d.ts.map +1 -1
- package/plugin/build/withConnectNSE.js +13 -2
- package/plugin/build/withConnectNSE.js.map +1 -1
- package/plugin/src/index.ts +17 -7
- package/plugin/src/withConnectAndroidConfig.ts +70 -0
- package/plugin/src/withConnectNCE.ts +26 -1
- package/plugin/src/withConnectNSE.ts +13 -2
- package/scripts/postinstall.mjs +35 -0
- package/scripts/xmlparser.js +1 -1
- package/scripts/postInstallScripts.sh +0 -10
- package/scripts/verifyConnectSetup.js +0 -87
package/plugin/src/index.ts
CHANGED
|
@@ -9,16 +9,25 @@
|
|
|
9
9
|
import { type ConfigPlugin } from '@expo/config-plugins'
|
|
10
10
|
import { withConnectNSE, type ConnectPluginProps } from './withConnectNSE'
|
|
11
11
|
import { withConnectNCE } from './withConnectNCE'
|
|
12
|
+
import { withConnectAndroidConfig } from './withConnectAndroidConfig'
|
|
12
13
|
|
|
13
14
|
/**
|
|
14
15
|
* Expo Config Plugin for react-native-acoustic-connect-beta.
|
|
15
16
|
*
|
|
16
|
-
*
|
|
17
|
-
* Notification Content Extension targets during `expo prebuild`.
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
17
|
+
* iOS: provisions the ConnectNSE Notification Service Extension and the
|
|
18
|
+
* ConnectNCE Notification Content Extension targets during `expo prebuild`.
|
|
19
|
+
*
|
|
20
|
+
* Android: wires the SDK's config.gradle into the generated app build so
|
|
21
|
+
* ConnectConfig.json values (collector URL, app key) reach the native assets
|
|
22
|
+
* at build time (withConnectAndroidConfig). FCM push needs no mod here — Expo
|
|
23
|
+
* wires the google-services Gradle plugin natively when the consumer sets
|
|
24
|
+
* `android.googleServicesFile` in app.json.
|
|
25
|
+
*
|
|
26
|
+
* Designed as a chainable composition: additional mods are appended by adding
|
|
27
|
+
* to the mods array. Order matters for the iOS pair — withConnectNSE runs
|
|
28
|
+
* first so it seeds the host entitlements and the
|
|
29
|
+
* PBXTargetDependency/PBXContainerItemProxy sections that withConnectNCE
|
|
30
|
+
* reuses. The Android mod is independent of that ordering.
|
|
22
31
|
*
|
|
23
32
|
* Consumer app.json usage:
|
|
24
33
|
* // With explicit App Group override:
|
|
@@ -40,11 +49,12 @@ const withAcousticConnect: ConfigPlugin<ConnectPluginProps | void> = (
|
|
|
40
49
|
const mods: Array<ConfigPlugin<ConnectPluginProps>> = [
|
|
41
50
|
withConnectNSE,
|
|
42
51
|
withConnectNCE,
|
|
52
|
+
withConnectAndroidConfig,
|
|
43
53
|
]
|
|
44
54
|
|
|
45
55
|
return mods.reduce((accConfig, mod) => mod(accConfig, resolvedProps), config)
|
|
46
56
|
}
|
|
47
57
|
|
|
48
58
|
export default withAcousticConnect
|
|
49
|
-
export { withConnectNSE, withConnectNCE }
|
|
59
|
+
export { withConnectNSE, withConnectNCE, withConnectAndroidConfig }
|
|
50
60
|
export type { ConnectPluginProps }
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
// Copyright (C) 2026 Acoustic, L.P. All rights reserved.
|
|
2
|
+
//
|
|
3
|
+
// NOTICE: This file contains material that is confidential and proprietary to
|
|
4
|
+
// Acoustic, L.P. and/or other developers. No license is granted under any
|
|
5
|
+
// intellectual or industrial property rights of Acoustic, L.P. except as may
|
|
6
|
+
// be provided in an agreement with Acoustic, L.P. Any unauthorized copying or
|
|
7
|
+
// distribution of content from this file is prohibited.
|
|
8
|
+
|
|
9
|
+
import { withAppBuildGradle, type ConfigPlugin } from '@expo/config-plugins'
|
|
10
|
+
import type { ConnectPluginProps } from './withConnectNSE'
|
|
11
|
+
|
|
12
|
+
// The Gradle snippet that runs the SDK's config.gradle. config.gradle reads
|
|
13
|
+
// the consumer app's ConnectConfig.json (`$project.rootDir/../ConnectConfig.json`)
|
|
14
|
+
// and writes AppKey / PostMessageUrl / KillSwitchUrl (and the Tealeaf + EOCore
|
|
15
|
+
// configs) into the SDK module's `src/main/assets/*` at Gradle configuration
|
|
16
|
+
// time — so the collector the app reports to is driven by ConnectConfig.json.
|
|
17
|
+
//
|
|
18
|
+
// This mirrors the line `scripts/gradleParser.js` appends for the bare-workflow
|
|
19
|
+
// sample (Examples/bare-workflow/android/app/build.gradle). The Expo Android
|
|
20
|
+
// project is gitignored and regenerated by `expo prebuild`, so the line cannot
|
|
21
|
+
// be committed there — this mod re-injects it on every prebuild instead.
|
|
22
|
+
//
|
|
23
|
+
// The ':react-native-acoustic-connect-beta' Gradle project is provided by
|
|
24
|
+
// React Native autolinking and resolves in the Expo app the same way it does
|
|
25
|
+
// in bare-workflow.
|
|
26
|
+
export const CONFIG_GRADLE_APPLY =
|
|
27
|
+
`apply from: project(':react-native-acoustic-connect-beta')` +
|
|
28
|
+
`.projectDir.getPath() + "/config.gradle"`
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Append the config.gradle `apply from:` line to an app `build.gradle` body.
|
|
32
|
+
*
|
|
33
|
+
* Idempotent: a no-op when the line is already present, so repeated prebuilds
|
|
34
|
+
* (and a prebuild over an already-patched, non-`--clean` project) don't stack
|
|
35
|
+
* duplicate applies.
|
|
36
|
+
*/
|
|
37
|
+
export function appendConfigGradleApply(contents: string): string {
|
|
38
|
+
if (contents.includes('/config.gradle')) {
|
|
39
|
+
return contents
|
|
40
|
+
}
|
|
41
|
+
return `${contents}\n\n${CONFIG_GRADLE_APPLY}\n`
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Expo config mod: wire the SDK's config.gradle into the generated Android
|
|
46
|
+
* app build so ConnectConfig.json values reach the native assets at build
|
|
47
|
+
* time. Without it, the Android SDK ships its committed default collector
|
|
48
|
+
* config and the app reports to the wrong endpoint (iOS is unaffected — it
|
|
49
|
+
* uses AcousticConnectRNConfig.json via a separate flow).
|
|
50
|
+
*/
|
|
51
|
+
export const withConnectAndroidConfig: ConfigPlugin<ConnectPluginProps> = (
|
|
52
|
+
config
|
|
53
|
+
) =>
|
|
54
|
+
withAppBuildGradle(config, (cfg) => {
|
|
55
|
+
// The RN/Expo template app build.gradle is Groovy. If a future template
|
|
56
|
+
// switches to the Kotlin DSL the append heuristic no longer applies —
|
|
57
|
+
// warn and skip rather than corrupt the file.
|
|
58
|
+
if (cfg.modResults.language !== 'groovy') {
|
|
59
|
+
console.warn(
|
|
60
|
+
`[react-native-acoustic-connect-beta] Skipping Android config ` +
|
|
61
|
+
`propagation: app/build.gradle is '${cfg.modResults.language}', ` +
|
|
62
|
+
`expected 'groovy'. Add the following line manually:\n` +
|
|
63
|
+
` ${CONFIG_GRADLE_APPLY}`
|
|
64
|
+
)
|
|
65
|
+
return cfg
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
cfg.modResults.contents = appendConfigGradleApply(cfg.modResults.contents)
|
|
69
|
+
return cfg
|
|
70
|
+
})
|
|
@@ -264,13 +264,38 @@ export function withNCEXcodeProject(
|
|
|
264
264
|
nceTarget.uuid
|
|
265
265
|
)
|
|
266
266
|
|
|
267
|
-
// Add Frameworks build phase
|
|
267
|
+
// Add the Frameworks build phase, then explicitly link the two
|
|
268
|
+
// user-notifications system frameworks into the NCE target.
|
|
269
|
+
//
|
|
270
|
+
// The NCE principal class conforms to `UNNotificationContentExtension`,
|
|
271
|
+
// whose extension-point context class
|
|
272
|
+
// (`_UNNotificationContentExtensionVendorContext`) is vended by
|
|
273
|
+
// UserNotificationsUI.framework, and whose `didReceive(_:)` consumes
|
|
274
|
+
// `UNNotification` / `UNNotificationContent` from UserNotifications.framework.
|
|
275
|
+
// Without these explicit links the extension binary never loads them, so on
|
|
276
|
+
// a PHYSICAL DEVICE iOS logs "Unable to find NSExtensionContextClass … did
|
|
277
|
+
// you link the framework that declares the extension point?" and never calls
|
|
278
|
+
// `didReceive(_:)`. The custom expanded view (rich-media `expandedImage`)
|
|
279
|
+
// then silently never renders, while the NSE-produced thumbnail still shows.
|
|
280
|
+
// The iOS Simulator resolves these classes implicitly, masking the omission —
|
|
281
|
+
// so this only surfaces on device. Both are Apple SYSTEM frameworks, so
|
|
282
|
+
// CocoaPods does NOT add them; they must be linked here, mirroring the
|
|
283
|
+
// canonical Examples/bare-workflow ConnectNCE target (which also lists the
|
|
284
|
+
// auto-linked Foundation/UIKit — omitted here as Swift links them implicitly).
|
|
268
285
|
xcodeProject.addBuildPhase(
|
|
269
286
|
[],
|
|
270
287
|
'PBXFrameworksBuildPhase',
|
|
271
288
|
'Frameworks',
|
|
272
289
|
nceTarget.uuid
|
|
273
290
|
)
|
|
291
|
+
xcodeProject.addFramework(
|
|
292
|
+
'System/Library/Frameworks/UserNotifications.framework',
|
|
293
|
+
{ target: nceTarget.uuid }
|
|
294
|
+
)
|
|
295
|
+
xcodeProject.addFramework(
|
|
296
|
+
'System/Library/Frameworks/UserNotificationsUI.framework',
|
|
297
|
+
{ target: nceTarget.uuid }
|
|
298
|
+
)
|
|
274
299
|
|
|
275
300
|
// Make the host app target depend on ConnectNCE. CocoaPods resolves an
|
|
276
301
|
// extension's host target through PBXTargetDependency
|
|
@@ -268,14 +268,25 @@ export function injectPodfileBlock(podfileContent: string): string {
|
|
|
268
268
|
// ─── Entitlements mod ─────────────────────────────────────────────────────────
|
|
269
269
|
|
|
270
270
|
/**
|
|
271
|
-
* Adds the
|
|
272
|
-
* —
|
|
271
|
+
* Adds the HOST app's push entitlements. Merges idempotently:
|
|
272
|
+
* - `aps-environment` — the APNs (Push Notifications) capability. Required for
|
|
273
|
+
* the SDK's automatic `registerForRemoteNotifications()` to receive a device
|
|
274
|
+
* token; without it iOS fails registration with "no valid aps-environment
|
|
275
|
+
* entitlement string found", so no token is ever sent to the collector.
|
|
276
|
+
* Mirrors the bare-workflow host entitlements. `development` targets the
|
|
277
|
+
* sandbox APNs used by dev/`expo run:ios`/EAS `development` builds;
|
|
278
|
+
* production/TestFlight builds need `production`.
|
|
279
|
+
* - `com.apple.security.application-groups` — shared App Group for the host app
|
|
280
|
+
* and the NSE/NCE extensions. Never clobbers an existing array.
|
|
273
281
|
*/
|
|
274
282
|
export function withNSEEntitlements(
|
|
275
283
|
config: ExpoConfig,
|
|
276
284
|
appGroupIdentifier: string
|
|
277
285
|
): ExpoConfig {
|
|
278
286
|
return withEntitlementsPlist(config, (c) => {
|
|
287
|
+
if (!c.modResults['aps-environment']) {
|
|
288
|
+
c.modResults['aps-environment'] = 'development'
|
|
289
|
+
}
|
|
279
290
|
const existing: string[] =
|
|
280
291
|
(c.modResults['com.apple.security.application-groups'] as
|
|
281
292
|
| string[]
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
// Cross-platform postinstall (replaces the bash-only postInstallScripts.sh,
|
|
2
|
+
// which silently no-opped on Windows and violated the repo's cross-platform
|
|
3
|
+
// rule). Runs the same three helper scripts that integrate the SDK into a
|
|
4
|
+
// consumer project, from the package root, best-effort: a non-zero exit from
|
|
5
|
+
// any of them is logged but never fails `npm install`.
|
|
6
|
+
|
|
7
|
+
import {spawnSync} from 'node:child_process'
|
|
8
|
+
import path from 'node:path'
|
|
9
|
+
import {fileURLToPath} from 'node:url'
|
|
10
|
+
|
|
11
|
+
const scriptsDir = path.dirname(fileURLToPath(import.meta.url))
|
|
12
|
+
const packageRoot = path.dirname(scriptsDir)
|
|
13
|
+
|
|
14
|
+
// Order matches the original postInstallScripts.sh. Note: the file is
|
|
15
|
+
// `xmlparser.js` (lowercase) — the old shell script referenced `xmlParser.js`
|
|
16
|
+
// with a capital P, which failed on case-sensitive filesystems (Linux CI).
|
|
17
|
+
const steps = ['reviewConnectConfig.js', 'xmlparser.js', 'gradleParser.js']
|
|
18
|
+
|
|
19
|
+
console.log(
|
|
20
|
+
'**Acoustic Integration***********************************************************************',
|
|
21
|
+
)
|
|
22
|
+
for (const step of steps) {
|
|
23
|
+
console.log(`Running scripts/${step} ...`)
|
|
24
|
+
const result = spawnSync(process.execPath, [path.join('scripts', step)], {
|
|
25
|
+
cwd: packageRoot,
|
|
26
|
+
stdio: 'inherit',
|
|
27
|
+
})
|
|
28
|
+
if (result.status !== 0)
|
|
29
|
+
console.log(
|
|
30
|
+
`scripts/${step} exited with ${result.status ?? result.signal} — continuing (postinstall is best-effort).`,
|
|
31
|
+
)
|
|
32
|
+
}
|
|
33
|
+
console.log(
|
|
34
|
+
'*********************************************************************************************',
|
|
35
|
+
)
|
package/scripts/xmlparser.js
CHANGED
|
@@ -14,7 +14,7 @@ const xmlPaserPlugin = require("@prettier/plugin-xml");
|
|
|
14
14
|
const { exit } = require('process');
|
|
15
15
|
const { isValid } = require('./util');
|
|
16
16
|
|
|
17
|
-
console.log("Run
|
|
17
|
+
console.log("Run xmlparser.js");
|
|
18
18
|
|
|
19
19
|
const directoryPath = path.join(__dirname,"..","..","..")
|
|
20
20
|
const filePath = `${directoryPath}/android/app/src/main/AndroidManifest.xml`;
|
|
@@ -1,10 +0,0 @@
|
|
|
1
|
-
#!/bin/bash
|
|
2
|
-
echo "**Acoustic Integration***********************************************************************"
|
|
3
|
-
echo "Current directory:"
|
|
4
|
-
pwd
|
|
5
|
-
echo "Running Node scripts..."
|
|
6
|
-
node ./scripts/reviewConnectConfig.js
|
|
7
|
-
node ./scripts/xmlParser.js
|
|
8
|
-
node ./scripts/gradleParser.js
|
|
9
|
-
echo "*********************************************************************************************"
|
|
10
|
-
echo "Running here scripts..."
|
|
@@ -1,87 +0,0 @@
|
|
|
1
|
-
/********************************************************************************************
|
|
2
|
-
* Copyright (C) 2024 Acoustic, L.P. All rights reserved.
|
|
3
|
-
*
|
|
4
|
-
* NOTICE: This file contains material that is confidential and proprietary to
|
|
5
|
-
* Acoustic, L.P. and/or other developers. No license is granted under any intellectual or
|
|
6
|
-
* industrial property rights of Acoustic, L.P. except as may be provided in an agreement with
|
|
7
|
-
* Acoustic, L.P. Any unauthorized copying or distribution of content from this file is
|
|
8
|
-
* prohibited.
|
|
9
|
-
********************************************************************************************/
|
|
10
|
-
|
|
11
|
-
/**
|
|
12
|
-
* Verify and Update React Native SDK integration to capture screen tracking.
|
|
13
|
-
*
|
|
14
|
-
* cd node_modules/react-native-acoustic-connect-beta folder
|
|
15
|
-
*
|
|
16
|
-
* yarn run verifyConnectSetup
|
|
17
|
-
*
|
|
18
|
-
*/
|
|
19
|
-
const fs = require('fs');
|
|
20
|
-
|
|
21
|
-
//const filePath = "../../src/components/RootComponent.tsx"
|
|
22
|
-
const filePath = "Example/nativebase-v3-kitchensink/src/components/RootComponent.tsx"
|
|
23
|
-
|
|
24
|
-
function log(message) {
|
|
25
|
-
console.log(message);
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
function isRootFileAvailable() {
|
|
29
|
-
return fs.existsSync(filePath);
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
function isConnectComponentAvailable() {
|
|
33
|
-
log("Looking for Connect tag...");
|
|
34
|
-
return isComponentAvailable(/<Connect/);
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
function isNavigationContainerAvailable() {
|
|
38
|
-
log("Looking for NavigationContainer tag...");
|
|
39
|
-
return isComponentAvailable(/<NavigationContainer/);
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
function isComponentAvailable(componentTag) {
|
|
43
|
-
try {
|
|
44
|
-
let data = fs.readFileSync(filePath, 'utf8');
|
|
45
|
-
const re = new RegExp(componentTag, "g");
|
|
46
|
-
const found = re.test(data);
|
|
47
|
-
|
|
48
|
-
return found;
|
|
49
|
-
} catch (err) {
|
|
50
|
-
console.error(err);
|
|
51
|
-
}
|
|
52
|
-
}
|
|
53
|
-
|
|
54
|
-
if (isRootFileAvailable()) {
|
|
55
|
-
if (isConnectComponentAvailable()) {
|
|
56
|
-
log("Connect component found. You are ready to go!");
|
|
57
|
-
} else if (isNavigationContainerAvailable()) {
|
|
58
|
-
log("NavigationContainer component is available but Connect component is missing.\n I'll add Connect around NavigationContainer component.");
|
|
59
|
-
AddConnectComponent();
|
|
60
|
-
} else {
|
|
61
|
-
log("Missing both Connect and NavigationContainer component.\n Please refer to SDK integration without React Navigation.");
|
|
62
|
-
};
|
|
63
|
-
} else {
|
|
64
|
-
console.error("App.js file not found in root app folder.");
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
// Update and add Connect around NavigationContainer
|
|
68
|
-
function AddConnectComponent() {
|
|
69
|
-
const connectImport = `import { Connect } from 'react-native-acoustic-connect-beta';`
|
|
70
|
-
|
|
71
|
-
const startNavigationContainer = /<NavigationContainer/
|
|
72
|
-
const startConnectComponent = `<Connect><NavigationContainer`
|
|
73
|
-
|
|
74
|
-
const endNavigationContainer = /<\/NavigationContainer>/
|
|
75
|
-
const endConnectComponent = `</NavigationContainer></Connect>`
|
|
76
|
-
|
|
77
|
-
try {
|
|
78
|
-
let data = fs.readFileSync(filePath, 'utf8');
|
|
79
|
-
data = data
|
|
80
|
-
.replace(startNavigationContainer, startConnectComponent)
|
|
81
|
-
.replace(endNavigationContainer, endConnectComponent);
|
|
82
|
-
fs.writeFileSync(filePath, ConnectImport + '\n' + data);
|
|
83
|
-
} catch (err) {
|
|
84
|
-
log("Something went wrong.\n Please refer to SDK integration with React Navigation.");
|
|
85
|
-
console.error(err);
|
|
86
|
-
}
|
|
87
|
-
}
|