Skip to content

chore(example): showcase optional Customer.io inclusion via CIO_ENABLED flag#597

Draft
mahmoud-elmorabea wants to merge 3 commits into
mainfrom
showcase/optional-cio-inclusion
Draft

chore(example): showcase optional Customer.io inclusion via CIO_ENABLED flag#597
mahmoud-elmorabea wants to merge 3 commits into
mainfrom
showcase/optional-cio-inclusion

Conversation

@mahmoud-elmorabea

@mahmoud-elmorabea mahmoud-elmorabea commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Sample-app showcase for making Customer.io an optional, build-time dependency.

A host that ships separate builds per customer can flip a single flag to include the full SDK in some builds and completely exclude it from others — leaving no compiled code, no bundled JS, and zero runtime footprint when off — without changing application code between builds.

…ld flag

Demonstrates how a host that ships separate per-customer builds can include
Customer.io for some builds and fully exclude it for others — no compiled CIO
code, none of the SDK's JS bundled, and zero runtime footprint — all driven by
one build-time flag, CIO_ENABLED.

The sample app now imports CIO only through a `@cio` facade, never from
'customerio-reactnative' directly:

- JS: metro.config.js resolveRequest swaps `@cio` between src/cio/index.real.ts
  and src/cio/index.noop.ts on CIO_ENABLED; tsconfig maps `@cio` -> real for
  types. The noop redefines enums and stubs the API surface without importing
  the package, so the SDK's getEnforcing TurboModules are never evaluated.
- Native: react-native.config.js disables autolinking on both platforms when
  off; the Podfile skips the customerio-reactnative + rich-push pods; and
  AppDelegate.swift guards the CIO app-delegate wrapper and push init behind
  `#if canImport(CioMessagingPush…)` so they compile out when the pods are
  absent.

All four levers read the same flag, so the JS and native layers can never
disagree (native-off + JS-real would crash via getEnforcing at launch).

Verified locally for both flag states: tsc clean; Metro bundle swaps real/noop
(disabled bundle has no CIO getEnforcing and excludes the SDK code);
`react-native config` links/excludes CIO on both platforms; and full Android
assembleDebug builds succeed both ways (PackageList.java registers
CustomerIOReactNativePackage only when enabled; disabled APK is ~3.5 MB
smaller).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
@github-actions

github-actions Bot commented Jun 10, 2026

Copy link
Copy Markdown
Contributor

Sample app builds 📱

Below you will find the list of the latest versions of the sample apps. It's recommended to always download the latest builds of the sample apps to accurately test the pull request.


  • Android APN: 597.3.0 (29685297)
  • iOS FCM: 597.3.0 (29685297)

@mahmoud-elmorabea mahmoud-elmorabea changed the title Showcase: optional Customer.io inclusion via a single build flag (CIO_ENABLED) chore(example): showcase optional Customer.io inclusion via CIO_ENABLED flag Jun 10, 2026
mahmoud-elmorabea and others added 2 commits June 10, 2026 22:33
…abled path

Showcase-only: forces CI sample-app builds to exclude Customer.io so the
off path is exercised in CI. Not for merge — normal builds leave the flag
unset (defaults to enabled).

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
…r the off path

The NSE source imported CioMessagingPushFCM/APN unconditionally, so with
CIO_ENABLED=0 (rich-push pod excluded) the extension failed to compile.
Guard the CIO push code with #if canImport(...) — same approach as
AppDelegate.swift — and fall back to delivering the notification unmodified
when Customer.io is excluded, so the NSE is coherent in both flag states.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant