smartech-base-expo-plugin
Version:
Smartech Base Expo SDK's React Native Plugin For React Native Projects.
209 lines (181 loc) • 8.98 kB
text/typescript
import {
ConfigPlugin, withInfoPlist,
withAppDelegate,
withEntitlementsPlist
} from "@expo/config-plugins";
import { promises as fs } from 'fs';
import path from 'path';
import fSystem from 'fs';
import { ExpoConfig } from "@expo/config-types";
import { SmartechBaseProps } from "./smartechBaseProps";
import { appdelegateSnippet, smartechBaseSnippet } from "./iosConstants";
import { Helper } from "./helper";
// Set custom entitlements plist
const modifyEntitlementsPlist: ConfigPlugin<SmartechBaseProps> = (config, props) => {
return withEntitlementsPlist(config, async (newConfig) => {
newConfig.modResults = {
...newConfig.modResults,
"com.apple.security.application-groups": [`group.${props.ios.groupIdentifier}`],
};
return newConfig;
});
};
// Set custom info plist
const modifyInfoPlist: ConfigPlugin<SmartechBaseProps> = (config, props) => {
return withInfoPlist(config, (newConfig) => {
newConfig.modResults = {
...newConfig.modResults,
SmartechKeys: {
SmartechAppGroup: `group.${props.ios.groupIdentifier}`,
SmartechAppId: props.ios.appId,
SmartechAutoFetchLocation: props.ios.autoFetchLocation,
SmartechUseAdvId: props.ios.useAdvID,
},
...(props.ios.smartechNudges.smartechNudgesEnabled && {
HanselKeys: {
HanselAppId: props.ios.smartechNudges.appId,
HanselAppKey: props.ios.smartechNudges.appKey,
}
})
};
return newConfig;
});
};
const addHanselURLScheme: ConfigPlugin<SmartechBaseProps> = (config, props) => {
return withInfoPlist(config, (newConfig) => {
const modResults = newConfig.modResults;
const existingURLTypes = newConfig.modResults.CFBundleURLTypes || [];
if (!props.ios.smartechNudges.smartechNudgesEnabled || !props.ios.smartechNudges.addTestDevice) {
return newConfig;
}
if (props.ios.smartechNudges?.testDeviceURLName == undefined || props.ios.smartechNudges?.testDeviceURLSchema == undefined) {
console.log(`Smartech Nudge Url scheme ${props.ios.smartechNudges?.testDeviceURLName} and ${props.ios.smartechNudges?.testDeviceURLSchema}`);
return newConfig
}
const newEntry = {
CFBundleTypeRole: "Editor",
CFBundleURLName: props.ios.smartechNudges.testDeviceURLName,
CFBundleURLSchemes: [props.ios.smartechNudges.testDeviceURLSchema || ""],
};
const isNewEntryAlreadyAdded = existingURLTypes.some((entry) => {
return (
entry.CFBundleURLName === newEntry.CFBundleURLName &&
entry.CFBundleURLSchemes.includes(newEntry.CFBundleURLSchemes[0])
);
});
if (!isNewEntryAlreadyAdded) {
existingURLTypes.push(newEntry);
modResults.CFBundleURLTypes = existingURLTypes;
}
return newConfig;
});
}
const addSmartechHeaderMod: ConfigPlugin<SmartechBaseProps> = (config, props) => {
return withAppDelegate(config, async (config) => {
const { platformProjectRoot, projectName } = config.modRequest;
if (projectName && platformProjectRoot) {
try {
const appDelegateHeaderPath = path.join(platformProjectRoot, projectName, appdelegateSnippet.fileName);
const appDelegateHeaderContents = await fs.readFile(appDelegateHeaderPath, 'utf-8');
// Add Smartech header snipper if not already present.
if (!appDelegateHeaderContents.includes(appdelegateSnippet.smartechHeaderSnippet)) {
const modifiedAppDelegateHeaderContents = `${appDelegateHeaderContents}\n${appdelegateSnippet.smartechHeaderSnippet}`;
await fs.writeFile(appDelegateHeaderPath, modifiedAppDelegateHeaderContents, 'utf-8');
} else {
console.log(`${appdelegateSnippet.smartechHeaderSnippet} is already added.`)
}
} catch (error) {
console.error('Error modifying AppDelegate.h:', error);
}
}
return config;
});
};
const addSmartechHanseleHeaderMod: ConfigPlugin<SmartechBaseProps> = (config, props) => {
return withAppDelegate(config, async (config) => {
const { platformProjectRoot, projectName } = config.modRequest;
if (platformProjectRoot && projectName) {
try {
const appDelegateHeaderPath = path.join(platformProjectRoot, projectName, appdelegateSnippet.fileName);
const appDelegateHeaderContents = await fs.readFile(appDelegateHeaderPath, 'utf-8');
// Add Hansel header snippet if Hansel is enabled and not already present
if (props.ios.smartechNudges.smartechNudgesEnabled && !appDelegateHeaderContents.includes(appdelegateSnippet.hanselHeaderSnippet)) {
const modifiedAppDelegateHeaderContents = `${appDelegateHeaderContents}\n${appdelegateSnippet.hanselHeaderSnippet}`;
await fs.writeFile(appDelegateHeaderPath, modifiedAppDelegateHeaderContents, 'utf-8');
} else {
console.log(`${appdelegateSnippet.hanselHeaderSnippet} is already added or status of SmartechNudge: ${props.ios.smartechNudges.smartechNudgesEnabled}`);
}
} catch (error) {
console.error('Error modifying AppDelegate.h:', error);
}
}
return config;
});
};
// Set custom AppDelegate contents modifications
const setCustomAppDelegateContentsMod: ConfigPlugin<SmartechBaseProps> = (config: ExpoConfig, props) => {
return withAppDelegate(config, (cfg) => {
const { modResults } = cfg;
const { contents } = modResults;
const appDelegatePath = cfg.modResults.path
const smartechInitContent = addSmartechInitCode(contents, props);
const updatedContent = Helper.Ios.addDeepLinkHandler(smartechInitContent, props);
fSystem.writeFileSync(appDelegatePath, updatedContent, 'utf-8');
modResults.contents = updatedContent;
return cfg;
});
};
// Helper function to modify AppDelegate contents
const addSmartechInitCode = (contents: string, props: SmartechBaseProps): string => {
const lines = contents.split("\n");
const didLaunchIndex = lines.findIndex(line => smartechBaseSnippet.regexPattern.test(line));
if (didLaunchIndex === -1) {
return contents;
}
// Prepare the lines to insert
const sdkLines: string[] = [
smartechBaseSnippet.smartechInit,
...(props.ios.isLogEnabled ? [smartechBaseSnippet.debugLevel] : []),
smartechBaseSnippet.trackAppInstallUpdateBySmartech,
...((props.ios.smartechNudges.smartechNudgesEnabled && props.ios.smartechNudges.isLogEnabled )? [smartechBaseSnippet.hanselLogSnippet] : []),
];
// Add the snippets before and after the `didFinishLaunching` index
const resultLines = [
...lines.slice(0, didLaunchIndex + 2),
...sdkLines,
...lines.slice(didLaunchIndex + 2),
];
return resultLines.join("\n");
};
// Set custom AppDelegate contents modifications
const modifyAppDelegateWithLinker: ConfigPlugin<SmartechBaseProps> = (config: ExpoConfig, props) => {
if (!props.ios.smartechNudges.smartechNudgesEnabled || !props.ios.smartechNudges.addTestDevice) {
return config;
}
return withAppDelegate(config, (config) => {
const { modResults } = config;
let { contents } = modResults;
const codeBlock = `BOOL handleBySmartech = [[Smartech sharedInstance] application:application openURL:url options:options];
if(!handleBySmartech) {
return [super application:application openURL:url options:options] || [RCTLinkingManager application:application openURL:url options:options];
}
return YES;`;
const lines = contents.split("\n");
if (contents.includes("openURL:")) {
const modifiedContents = contents.replace(
"return [super application:application openURL:url options:options] || [RCTLinkingManager application:application openURL:url options:options];",`${codeBlock}`);
modResults.contents = modifiedContents;
}
return config;
});
};
export const withNetcoreiOS: ConfigPlugin<SmartechBaseProps> = (config, props) => {
config = modifyEntitlementsPlist(config, props);
config = modifyInfoPlist(config, props);
config = addHanselURLScheme(config, props);
config = addSmartechHeaderMod(config, props);
config = addSmartechHanseleHeaderMod(config, props);
config = setCustomAppDelegateContentsMod(config, props);
config = modifyAppDelegateWithLinker(config, props);
return config;
}