-
Notifications
You must be signed in to change notification settings - Fork 38
[draft]Optimize turbo module e2e #581
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
a689856
e6b00e3
d2a049c
6bc6c47
dfc6f04
e117c7b
dff3c4c
a5a2bda
00a43c8
3a36bd0
08fa7c1
74d4d94
a5d3d9f
9224d5d
8067cee
356ec87
25db5b3
0a9a635
c7ffe35
dfbd784
fd84b3a
d66ac3b
0487688
3398af3
3cdfeaf
2985ef6
5780768
876bead
72a9a8c
6c7eef3
7ede07b
1c5a723
addb558
a89373b
d4d038f
0d3bc24
8264771
22f73cc
435c4ec
ebc58cf
0f3663f
443dcc6
ac91559
498de4c
02fdb98
e94f338
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| 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"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -5,3 +5,4 @@ enableGlobalCache: false | |
| nmHoistingLimits: workspaces | ||
|
|
||
| nodeLinker: node-modules | ||
|
|
||
| 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"] | ||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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, | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Same as above, please validate |
||
| decisionScopeTargetMbox | ||
| ]; | ||
|
|
||
|
|
@@ -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)); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe 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())); | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -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") | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's not commit App ID |
||
| .then(() => { | ||
| console.log("AEP SDK Initialized"); | ||
|
|
||
|
|
||
| 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; |
| 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; |
There was a problem hiding this comment.
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.