Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
46 commits
Select commit Hold shift + click to select a range
a689856
android and ios sample app working correctly
Mar 23, 2026
e6b00e3
added optimize and core package along with assurance working
Mar 23, 2026
d2a049c
added appium for android
Mar 24, 2026
6bc6c47
ios build for e2e along with common code for e2e testing
Mar 24, 2026
dfc6f04
Added extension version e2e test
Mar 25, 2026
e117c7b
Android native modules build flag added for interop layer along with …
Mar 26, 2026
dff3c4c
added ios native module with interop layer and turbo module
Mar 26, 2026
a5a2bda
adroid e2e fixes
Mar 26, 2026
00a43c8
[WIP] added node version for spinning up builds
Mar 30, 2026
3a36bd0
generic agents playbook instead of cursor specifics
Mar 31, 2026
08fa7c1
added claude changes
Mar 31, 2026
74d4d94
added test case for update proposition api
Mar 31, 2026
a5d3d9f
added clear cached proposition tests
Mar 31, 2026
9224d5d
added tapoffer e2e test working in android
Apr 8, 2026
8067cee
[WIP] tapped offer for ios as earlier it was not able to collect logs…
Apr 8, 2026
356ec87
Claude settings
Apr 8, 2026
25db5b3
tapped proposition api e2e added working with both ios and android al…
Apr 15, 2026
0a9a635
added display proposition and tapped proposition for optimize
Apr 16, 2026
c7ffe35
optimize display and tapped proposition fixes
Apr 16, 2026
dfbd784
multiplay display , onproposition update and display
Apr 21, 2026
fd84b3a
[WIP fixing on propupdate apis
Apr 21, 2026
d66ac3b
ios turbo module fixes
Apr 23, 2026
0487688
upgrade playbook for react native added
Apr 23, 2026
3398af3
fixed flaky tests along with ios logs being dumped properly
May 8, 2026
3cdfeaf
Added aep optimize android interop build flag fixes
May 18, 2026
2985ef6
expo app integration
Jun 8, 2026
5780768
event emission updates for onpropositioUpdate api
Jun 8, 2026
876bead
Merge origin/main into optimize-turbo-module-e2e
Jun 8, 2026
72a9a8c
isolating apps along with onpropositionUpdate fixes
Jun 8, 2026
6c7eef3
removed awesome project sample app
Jun 8, 2026
7ede07b
updated aepsample app yarn lock
Jun 8, 2026
1c5a723
agent docs updated
Jun 8, 2026
addb558
circle ci fixes
Jun 9, 2026
a89373b
updated yarn lock
Jun 9, 2026
d4d038f
removed agents docs along with circle ci fixes
namArora3112 Jun 10, 2026
0d3bc24
codegen type error fixes
namArora3112 Jun 10, 2026
8264771
yarn lock updated
namArora3112 Jun 10, 2026
22f73cc
unit test fixes
namArora3112 Jun 10, 2026
435c4ec
unit tests config updates
namArora3112 Jun 10, 2026
ebc58cf
Removed dist files
namArora3112 Jun 10, 2026
0f3663f
removed e2e setup
namArora3112 Jun 10, 2026
443dcc6
yarn lock upadtes
namArora3112 Jun 10, 2026
ac91559
removed unused files
namArora3112 Jun 10, 2026
498de4c
android setting gradle changes reverted
namArora3112 Jun 11, 2026
02fdb98
e2e removed
namArora3112 Jun 15, 2026
e94f338
onproposition update api name changed back to original one
namArora3112 Jun 15, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,12 +25,19 @@ jobs:
command: sudo corepack enable

- run:
name: Install Node.js and Yarn Dependencies
name: Install Root Dependencies
command: yarn install --immutable --network-timeout 300000
no_output_timeout: 20m
environment:
NODE_OPTIONS: "--max-old-space-size=4096"

- run:
name: Install AEPSampleApp Dependencies
command: cd apps/AEPSampleApp && yarn install --immutable --network-timeout 300000
no_output_timeout: 20m
environment:
NODE_OPTIONS: "--max-old-space-size=4096"

- run:
name: Build the Project
command: yarn run build
Expand Down
18 changes: 18 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -152,3 +152,21 @@ out/

# ignore ds store
.DS_Store

# Claude Code machine-specific files (never commit these)
.claude/
**/.claude/

# Internal AI agent documentation (kept locally, not for public PRs)
agent-docs/

# Local smoke test run reports
smoke-tests/

# Compiled TypeScript build artifacts in package source/spec directories
packages/*/src/**/*.js
packages/*/src/**/*.js.map
packages/*/src/**/*.d.ts
packages/*/specs/**/*.js
packages/*/specs/**/*.js.map
packages/*/specs/**/*.d.ts
3 changes: 3 additions & 0 deletions .watchmanconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"ignore_dirs": ["node_modules", ".git", "ios/build", "android/build", "android/.gradle", ".gradle"]
}
1 change: 1 addition & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ enableGlobalCache: false
nmHoistingLimits: workspaces

nodeLinker: node-modules

16 changes: 8 additions & 8 deletions apps/AEPSampleApp/extensions/OptimizeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ import {
View,
Image,
TouchableOpacity,
Dimensions,
useWindowDimensions,
TextInput,
StyleSheet,
} from 'react-native';
Expand All @@ -49,7 +49,7 @@ const defaultPropositions = {

export default ({navigation}: any) => {
const [version, setVersion] = useState('0.0.0');
const [customScopeInput, setCustomScopeInput] = useState('demoLoc3');
const [customScopeInput, setCustomScopeInput] = useState('mboxAug');
const [textProposition, setTextProposition] = useState<Proposition>();
const [imageProposition, setImageProposition] = useState<Proposition>();
const [htmlProposition, setHtmlProposition] = useState<Proposition>();
Expand All @@ -68,13 +68,13 @@ export default ({navigation}: any) => {
const decisionScopeJson = new DecisionScope(
'eyJ4ZG06YWN0aXZpdHlJZCI6Inhjb3JlOm9mZmVyLWFjdGl2aXR5OjE0MWM4NTg2MmRiMDQ4YzkiLCJ4ZG06cGxhY2VtZW50SWQiOiJ4Y29yZTpvZmZlci1wbGFjZW1lbnQ6MTQxYzZkN2VjOTZmOTg2ZCJ9',
);
const decisionScopeTargetMbox = new DecisionScope(customScopeInput.trim() || 'demoLoc3');
const decisionScopeTargetMbox = new DecisionScope(customScopeInput.trim() || 'mboxAug');

const decisionScopes = [
decisionScopeText,
decisionScopeImage,
decisionScopeHtml,
decisionScopeJson,
// decisionScopeText,
// decisionScopeImage,
// decisionScopeHtml,
// decisionScopeJson,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Are these changes intended? I see we have updated the default target store and commented out decision scopes.

decisionScopeTargetMbox,
];

Expand Down Expand Up @@ -217,7 +217,7 @@ export default ({navigation}: any) => {
return data1 !== data2;
});

var {width} = Dimensions.get('window');
const { width } = useWindowDimensions();
const inputStyles = StyleSheet.create({
label: {fontWeight: '600', marginTop: 8, marginBottom: 2, color: '#333', alignSelf: 'flex-start'},
input: {borderWidth: 1, borderColor: '#ccc', borderRadius: 6, padding: 8, fontSize: 13, marginBottom: 2, backgroundColor: '#fff', width: width - 32},
Expand Down
6 changes: 5 additions & 1 deletion apps/AEPSampleApp/ios/Podfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,7 @@ PODS:
- RCTAEPOptimize (7.1.1):
- AEPOptimize (< 6.0.0, >= 5.0.0)
- React
- React-Codegen
- RCTAEPPlaces (7.0.1):
- AEPPlaces (< 6.0.0, >= 5.0.0)
- React
Expand Down Expand Up @@ -109,6 +110,7 @@ PODS:
- React-RCTText (= 0.85.0)
- React-RCTVibration (= 0.85.0)
- React-callinvoker (0.85.0)
- React-Codegen (0.1.0)
- React-Core (0.85.0):
- hermes-engine
- RCTDeprecation
Expand Down Expand Up @@ -2298,6 +2300,7 @@ SPEC REPOS:
- AEPSignal
- AEPTarget
- AEPUserProfile
- React-Codegen

EXTERNAL SOURCES:
FBLazyVector:
Expand Down Expand Up @@ -2517,7 +2520,7 @@ SPEC CHECKSUMS:
RCTAEPEdgeConsent: 94d66ceefac0058a1586b0b876e37f178d3733d2
RCTAEPEdgeIdentity: 2ed3fdc9a3150e9bcf268b128c22f293ab4df6aa
RCTAEPMessaging: d97f2750b4698d54953e6a9b824506a18be1695c
RCTAEPOptimize: 160b9d7aa20c4524e70b930934dbd5c0f7a58f14
RCTAEPOptimize: cf583da4e45b6db6e641c4771f5a4204882521f1
RCTAEPPlaces: 4050bda86286605a8683b4c078baac1662ca013a
RCTAEPTarget: e8bcf8864758faf07635719ffa0eff6a06861910
RCTAEPUserProfile: 799d618ffbbfc389175c8a8cd5afcc36d852709a
Expand All @@ -2528,6 +2531,7 @@ SPEC CHECKSUMS:
RCTTypeSafety: abdf2eaed5501a52f2000de668ccfc60b78c3b27
React: 1b1536b9099195944034e65b1830f463caaa8390
React-callinvoker: 6dff6d17d1d6cc8fdf85468a649bafed473c65f5
React-Codegen: 4b8b4817cea7a54b83851d4c1f91f79aa73de30a
React-Core: 39ee05b5798296f433dd3c3624c57a187c1510e3
React-Core-prebuilt: 0eb00afc411cea82c86a1a369b68da88299926f0
React-CoreModules: e78bfd2617075bc0e50c689df4a29232bd72ad82
Expand Down
3 changes: 3 additions & 0 deletions apps/AEPSampleAppNewArchEnabled/.watchmanconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"ignore_dirs": ["node_modules", ".git", "ios/build", "android/build", "android/.gradle"]
}
8 changes: 7 additions & 1 deletion apps/AEPSampleAppNewArchEnabled/app.json
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,13 @@
}
],
"expo-font",
"expo-web-browser"
"expo-web-browser",
[
"./plugins/withInteropRoot",
{
"value": "0"
}
]
],
"experiments": {
"typedRoutes": true
Expand Down
12 changes: 7 additions & 5 deletions apps/AEPSampleAppNewArchEnabled/app/OptimizeView.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -67,13 +67,13 @@ export default () => {
const decisionScopeJson = new DecisionScope(
'eyJ4ZG06YWN0aXZpdHlJZCI6Inhjb3JlOm9mZmVyLWFjdGl2aXR5OjE0MWM4NTg2MmRiMDQ4YzkiLCJ4ZG06cGxhY2VtZW50SWQiOiJ4Y29yZTpvZmZlci1wbGFjZW1lbnQ6MTQxYzZkN2VjOTZmOTg2ZCJ9',
);
const decisionScopeTargetMbox = new DecisionScope('demoLoc3');
const decisionScopeTargetMbox = new DecisionScope('mboxAug');

const decisionScopes = [
decisionScopeText,
decisionScopeImage,
decisionScopeHtml,
decisionScopeJson,
// decisionScopeText,
// decisionScopeImage,
// decisionScopeHtml,
// decisionScopeJson,

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above, please validate

decisionScopeTargetMbox
];

Expand Down Expand Up @@ -126,7 +126,9 @@ export default () => {
const onPropositionUpdate = () =>
Optimize.onPropositionUpdate({
call(propositions: Map<String, Proposition>) {
console.log('onPropositionUpdate called');
if (propositions) {
console.log('propositions bnana', JSON.stringify(Object.fromEntries(propositions), null, 2));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please sanitize logs

setTextProposition(propositions.get(decisionScopeText.getName()));
setImageProposition(propositions.get(decisionScopeImage.getName()));
setHtmlProposition(propositions.get(decisionScopeHtml.getName()));
Expand Down
2 changes: 1 addition & 1 deletion apps/AEPSampleAppNewArchEnabled/app/_layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ export default function RootLayout() {
// For functional components, use useEffect with an empty dependency array.
// For class components, call initializeWithAppId inside componentDidMount.
MobileCore.setLogLevel(LogLevel.DEBUG);
MobileCore.initializeWithAppId("YOUR-APP-ID")
MobileCore.initializeWithAppId("3149c49c3910/0f12baf27522/launch-0d096c129660-development")

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's not commit App ID

.then(() => {
console.log("AEP SDK Initialized");

Expand Down
107 changes: 69 additions & 38 deletions apps/AEPSampleAppNewArchEnabled/metro.config.js
Original file line number Diff line number Diff line change
@@ -1,52 +1,83 @@
const { getDefaultConfig } = require('expo/metro-config');
const { FileStore } = require('metro-cache');
const path = require('path');

const config = getDefaultConfig(__dirname);
const { resolve, join } = require('path');

const projectRoot = __dirname;
const monorepoRoot = path.resolve(projectRoot, '../..');
const monorepoRoot = resolve(projectRoot, '../..');

const ADOBE_PACKAGE_FOLDERS = [
'assurance',
'campaignclassic',
'core',
'edge',
'edgebridge',
'edgeconsent',
'edgeidentity',
'messaging',
'optimize',
'places',
'target',
'userprofile',
];

// Watch all files in the monorepo
config.watchFolders = [monorepoRoot];
const extraNodeModules = Object.fromEntries(
ADOBE_PACKAGE_FOLDERS.map((folder) => [
`@adobe/react-native-aep${folder}`,
join(monorepoRoot, 'packages', folder),
]),
);

// Let Metro know where to resolve packages
config.resolver.nodeModulesPaths = [
path.resolve(projectRoot, 'node_modules'),
path.resolve(monorepoRoot, 'node_modules'),
const config = getDefaultConfig(projectRoot);

config.watchFolders = [
resolve(monorepoRoot, 'packages'),
resolve(monorepoRoot, 'node_modules'),
];

// Exclude problematic nested node_modules to prevent the bundling error
// After merging main, root node_modules gained react-native@0.85 (devDep for jest).
// This app uses react-native@0.81 (Expo 54). Block root's react-native so Metro
// always resolves it from the app's own node_modules instead.
// Escape special regex chars in absolute paths used for blockList patterns.
const escapePath = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');

// Block root node_modules react-native/react (root devDeps for Jest) so Metro
// always uses the app's own Expo-managed versions.
// Block expo-router's nested @react-navigation so only ONE copy (the app's
// top-level versions) is bundled — prevents "multiple NavigationContainer" crash.
config.resolver.blockList = [
// Block nested node_modules inside packages
/packages\/.*\/node_modules\/.*/,
// Block any nested node_modules directories
/.*\/node_modules\/.*\/node_modules\/.*/,
new RegExp(`^${escapePath(resolve(monorepoRoot, 'node_modules/react-native'))}/.*`),
new RegExp(`^${escapePath(resolve(monorepoRoot, 'node_modules/react'))}/.*`),
new RegExp(`^${escapePath(join(projectRoot, 'node_modules/expo-router/node_modules/@react-navigation'))}/.*`),
];

// Don't try to transpile react-native's internal source files
config.resolver.disableHierarchicalLookup = true;
// Use a separate cache for the monorepo to avoid conflicts
config.cacheStores = [
new FileStore({
root: path.join(projectRoot, 'node_modules', '.cache', 'metro'),
}),
config.resolver.nodeModulesPaths = [
resolve(projectRoot, 'node_modules'),
resolve(monorepoRoot, 'node_modules'),
];

// Explicitly map workspace packages to their built versions
config.resolver.alias = {
'@adobe/react-native-aepassurance': path.resolve(monorepoRoot, 'packages/assurance'),
'@adobe/react-native-aepcampaignclassic': path.resolve(monorepoRoot, 'packages/campaignclassic'),
'@adobe/react-native-aepcore': path.resolve(monorepoRoot, 'packages/core'),
'@adobe/react-native-aepedge': path.resolve(monorepoRoot, 'packages/edge'),
'@adobe/react-native-aepedgebridge': path.resolve(monorepoRoot, 'packages/edgebridge'),
'@adobe/react-native-aepedgeconsent': path.resolve(monorepoRoot, 'packages/edgeconsent'),
'@adobe/react-native-aepedgeidentity': path.resolve(monorepoRoot, 'packages/edgeidentity'),
'@adobe/react-native-aepmessaging': path.resolve(monorepoRoot, 'packages/messaging'),
'@adobe/react-native-aepoptimize': path.resolve(monorepoRoot, 'packages/optimize'),
'@adobe/react-native-aepplaces': path.resolve(monorepoRoot, 'packages/places'),
'@adobe/react-native-aeptarget': path.resolve(monorepoRoot, 'packages/target'),
'@adobe/react-native-aepuserprofile': path.resolve(monorepoRoot, 'packages/userprofile'),
// Watchman's daemon socket is unavailable in this sandboxed environment, which
// makes `watch-project` hang indefinitely. Fall back to Metro's Node-based
// file watcher so bundling can proceed.
config.resolver.useWatchman = false;

config.resolver.extraNodeModules = {
...extraNodeModules,
'@babel/runtime': join(monorepoRoot, 'node_modules/@babel/runtime'),
// Pin singleton packages to the app's own node_modules so there is never more
// than one copy in the bundle.
//
// react / react-native: blocked from root node_modules (root has 0.85 devDep
// for Jest while this app uses 0.81 via Expo 54).
//
// @react-navigation/*: expo-router ships its own older nested copies
// (@react-navigation/core@7.14 vs app's 7.17, native@7.1.28 vs 7.2.2).
// Pinning here + blockList above forces a single instance → fixes
// "Couldn't register the navigator / multiple copies" crash.
'react-native': join(projectRoot, 'node_modules/react-native'),
'react': join(projectRoot, 'node_modules/react'),
'@react-navigation/core': join(projectRoot, 'node_modules/@react-navigation/core'),
'@react-navigation/native': join(projectRoot, 'node_modules/@react-navigation/native'),
'@react-navigation/routers': join(projectRoot, 'node_modules/@react-navigation/routers'),
'@react-navigation/elements': join(projectRoot, 'node_modules/@react-navigation/elements'),
};

module.exports = config;
module.exports = config;
11 changes: 10 additions & 1 deletion apps/AEPSampleAppNewArchEnabled/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -78,5 +78,14 @@
]
}
},
"private": true
"private": true,
"resolutions": {
"@react-navigation/core": "7.17.2",
"@react-navigation/native": "7.2.2",
"@react-navigation/routers": "7.5.3",
"@react-navigation/elements": "2.9.5",
"@react-navigation/bottom-tabs": "7.15.9",
"@react-navigation/drawer": "7.7.13",
"@react-navigation/native-stack": "7.14.10"
}
}
57 changes: 57 additions & 0 deletions apps/AEPSampleAppNewArchEnabled/plugins/withInteropRoot.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
const { withDangerousMod } = require('@expo/config-plugins');
const fs = require('fs');
const path = require('path');

/**
* Sets `ENV['USE_INTEROP_ROOT']` in the iOS Podfile.
*
* The AEP Optimize podspec (`packages/optimize/RCTAEPOptimize.podspec`) reads
* this env var at `pod install` time to choose the iOS compile path:
* "0" = Turbo Module (New Architecture, default)
* "1" = interop layer (legacy bridge / RCTEventEmitter)
*
* Expo has no built-in app.json key for forwarding an arbitrary env var to a
* third-party podspec, so we inject it into the Podfile. Because this runs on
* every `expo prebuild`, it survives Podfile regeneration.
*
* Uses `||=` so a shell override (e.g. `USE_INTEROP_ROOT=1 pod install`) still
* takes precedence for one-off builds.
*
* Usage in app.json:
* ["./plugins/withInteropRoot", { "value": "0" }]
*/
const START = '# >>> USE_INTEROP_ROOT (managed by withInteropRoot plugin)';
const END = '# <<< USE_INTEROP_ROOT';

const withInteropRoot = (config, { value = '0' } = {}) => {
return withDangerousMod(config, [
'ios',
(cfg) => {
const podfilePath = path.join(
cfg.modRequest.platformProjectRoot,
'Podfile',
);
let contents = fs.readFileSync(podfilePath, 'utf8');

const block = `${START}\nENV['USE_INTEROP_ROOT'] ||= '${value}'\n${END}\n`;

// Drop any previously managed block so the value stays in sync.
const blockRegex = new RegExp(`${START}[\\s\\S]*?${END}\\n?`);
contents = contents.replace(blockRegex, '');

// Insert just before prepare_react_native_project! (always present in
// Expo Podfiles); fall back to prepending if the anchor moves.
const anchor = 'prepare_react_native_project!';
if (contents.includes(anchor)) {
contents = contents.replace(anchor, `${block}\n${anchor}`);
} else {
contents = `${block}\n${contents}`;
}

fs.writeFileSync(podfilePath, contents);
return cfg;
},
]);
};

module.exports = withInteropRoot;
Loading