cli-kit
The cli-kit package furnishes a comprehensive array of utilities essential for the creation and manipulation of native code within iOS and Android projects. It offers specialized file parsers and file system APIs, facilitating seamless expansion of native functionalities beyond the foundational framework of a React Native project.
Install
Add @brandingbrand/code-cli-kit
as a development dependency to your React Native project.
yarn add --dev @brandingbrand/code-cli-kit
npm install --save-dev @brandingbrand/code-cli-kit
pnpm add --save-dev @brandingbrand/code-cli-kit
bun add --dev @brandingbrand/code-cli-kit
Your package.json should now be updated, @brandingbrand/code-cli-kit
should be listed as a devDependency
.
{ "name": "my-awesome-app", "version": "1.0.0", "author": "Your Name <email@example.com>", "dependencies": { "react": "^18.2.0", "react-native": "~0.72.0" }, "devDependencies": { "@brandingbrand/code-cli-kit": "13.0.0" }}
Modules
The modules provided by the cli-kit package are also leveraged by the @brandingbrand/code-cli
package for the purpose of native code management. This collaboration ensures efficient utilization of only the essential exposed modules, with emphasis on detailing those of utmost importance.
Parsers
The parsers module within cli-kit is tasked with the parsing and composition of domain-specific files into a structured object format, facilitating convenient manipulation in accordance with project requirements. Noteworthy available parsers include those for UTF-8, XML, Property List (plist), and Old-Style ASCII Property Lists (pbxproj).
UTF-8
The UTF-8 parser is designed to interpret generic files into a manipulable string format. Typical scenarios involve handling source code and configuration files such as MainActivity.{java|kt}, MainApplication.{java|kt}, AppDelegate.mm, AppDelegate.h, build.gradle, podfile, and similar items. Presently, there are no parsers available specifically for these types of files. However, it’s worth noting that this situation might evolve in the future, particularly for configuration files, should further parsers, grammars, and lexers be developed.
The exposed module for parsing UTF-8 files is withUTF8
. It can be used with the following options.
Function
withUTF8
type: withUTF8(filePath: string, callback(content: string): string): Promise<Void>
Options
filePath
type: string
required
The path of the file relative to the project root to be parsed.
callback
type: function (content: string): string
required
A callback function is implemented to accept the parsed file as a string and anticipates a manipulated string to be returned as its output.
Usage
Below is an illustrative example demonstrating the utilization of the UTF-8 parser to parse the build.gradle
file and subsequently update the compileSdkVersion
:
import {path, withUTF8} from '@brandingbrand/code-cli-kit';
// config supplied by @brandingbrand/cli
withUTF8(path.android.buildGradle, (content: string) => { return content.replace( content, /(compileSdkVersion\s*=\s*)[\d]+/m, `$1${config.android.gradle.projectGradle.compileSdkVersion}`, );});
XML
The XML parser serves to decipher XML-formatted files into a manipulatable object tailored to meet the specific requirements of your project. Noteworthy XML files parsed within the @brandingbrand/cli
framework include AndroidManifest.xml, colors.xml, strings.xml, styles.xml, among others. At present, this parser harnesses the capabilities of the fast-xml-parser package to accomplish its tasks efficiently.
The exposed module for parsing XML files is withXML
. It can be used with the following options.
Function
withXML
type: function withXML<T>(path: string, options: X2jOptions, callback: (xml: T): void): Promise<Void>
Options
path
type: string
required
The path of the XML file relative to the project root to be parsed.
options
type: X2jOptions
required
The options on how to parse/write and format the XML object and file.
callback
type: function<T>(content: T): void
required
A callback function is implemented to accept the parsed file as a generic object, with the expectation that no explicit return value is necessary, as the object is mutable by nature.
Usage
Below is an illustrative example demonstrating the utilization of the XML parser to parse the colors.xml
file and subsequently add a color:
import {path, withXML} from '@brandingbrand/code-cli-kit';
// config supplied by @brandingbrand/cli
type ColorAttributes = { name: string;};
type Color = { $: ColorAttributes; _: string;};
type ColorsElements = { color?: Color[];};
export type ColorsXML = { resources: ColorsElements;};
withXml<ColorsXML>( path.android.colors, { isArray: tagName => { if (['color'].indexOf(tagName) !== -1) { return true; }
return false; }, }, (xml: ColorsXML) => { if (!config.android.colors) return;
if (!xml.resources.color) { xml.resources = {...xml.resources, color: []}; }
Object.entries(config.android.colors).forEach(([name, _]) => xml.resources.color?.push({ $: {name}, _, }), ); },);
Property List (plist)
The plist parser is specifically crafted to interpret property list files into a mutable object format. Commonly, it finds application in scenarios involving the management of iOS Info.plist files.
The exposed module for parsing plist files is withPlist
. It can be used with the following options.
Function
withPlist
type: function withPlist<T>(path: string, callback(content: T): T): Promise<Void>
Options
path
type: string
required
The path of the file relative to the project root to be parsed.
callback
type: function<T>(content: T): T
required
A callback function is implemented to accept the parsed plist file as a generic object, with the expectation that the mutated object will be returned as its output.
Usage
Below is an illustrative example demonstrating the utilization of the plist parser to parse the info.plist
file and subsequently update the the bundle identifier and display name.
import {path, withPlist} from '@brandingbrand/code-cli-kit';
// config supplied by @brandingbrand/cli
type InfoPlist = Record<string, unknown> & { UIStatusBarHidden?: boolean; UIStatusBarStyle?: string; UILaunchStoryboardName?: string | 'LaunchScreen'; CFBundleShortVersionString?: string; CFBundleVersion?: string; CFBundleDisplayName?: string; CFBundleIdentifier?: string; CFBundleName?: string; // See source code for more};
withPlist<InfoPlist>(path.ios.infoPlist, (content: InfoPlist): InfoPlist => { const {displayName, bundleId} = config.ios;
return mergeAndConcat<InfoPlist, InfoPlist[]>(content, { CFBundleIdentifier: bundleId, CFBundleDisplayName: displayName, });});
Old-Style ASCII Property Lists (pbxproj)
The pbxproj parser is meticulously crafted to interpret pbxproj files into a mutable object format. Common scenarios involving its usage include the management of project.pbxproj files, encompassing tasks such as adding source files, resource files, updating build settings, and similar project-related operations.
The exposed module for parsing UTF-8 files is withPbxproj
. It can be used with the following options.
Function
withPbxproj
type: function withPbxproj(callback: (pbxproj: XcodeProject): void): Promise<Void>
Options
callback
type: function (content: XcodeProject): void
required
A callback function is established to receive the parsed file as a XcodeProject object. It expects no explicit return value, as the object is inherently mutable and intended for direct manipulation within the context of the Xcode project.
Usage
Below is an illustrative example demonstrating the utilization of the pbxproj parser to parse the project.pbxproj
file and subsequently update the IPHONEOS_DEPLOYMENT_TARGET
:
import {withPbxproj} from '@brandingbrand/code-cli-kit';
// config supplied by @brandingbrand/cli
withPbxproj(project => { if (!config.ios.deploymentTarget) return;
project.addToBuildSettings( 'IPHONEOS_DEPLOYMENT_TARGET', config.ios.deploymentTarget, );});
Libs
A comprehensive array of exposed library modules is available to assist in the generation of native code, complementing the functionality of the parsers. These modules offer a versatile toolkit to facilitate efficient native code development within the project ecosystem.
fs
The fs
module builds upon the foundation provided by fs/promises
, addressing specific gaps to enhance functionality where necessary. Within this module, four additional functions are exposed to facilitate manipulation of native code: doesKeywordExist
, doesPathExist
, update
, and renameAndCopyDirectory
. These functions serve to augment the capabilities of file system operations, offering a comprehensive toolkit for efficient native code management.
Function
doesKeywordExist
This function examines a file to determine if a specified keyword exists within it. The keyword can be provided either as a regular expression or as a string format.
type: function doesKeywordExist(path: string, keyword: RegExp | string): Promise<boolean>
Options
path
type: string
required
The path of the file relative to the project root to examine.
keyword
type: RegExp | string
required
The parameter for this function represents either a string or a regular expression that is to be checked for existence within the specified file.
Usage
Below is an illustrative example demonstrating the utilization of the doesKeywordExist
lib.
import {fs} from '@brandingbrand/code-cli-kit';// file content at ./my_file.txt// "This is someKeyword content."
const res = await fs.doesKeywordExist( path.project.resolve('my_file.txt'), 'someKeyword',);
/// res will be true
const res1 = await fs.doesKeywordExist(path, /some/);
/// res1 will be true
Function
doesPathExist
This function determines whether the provided file path exists within the file system.
Options
path
type: string
required
The path of the file relative to the project root.
Usage
Below is an illustrative example demonstrating the utilization of the doesPathExist
lib.
import {fs, path} from '@brandingbrand/code-cli-kit';
// file system has a file at ./ios/app/MyFile.swift
const res = await fs.doesPathExist( path.project.resolve('ios', 'app', 'MyFile.swift'),);
/// res will be true
Function
update
This function facilitates the updating of a text value within a file by replacing it with a new text value.
type: function update(path: string, oldText: RegExp | string, newText: string): Promise<void>
Options
path
type: string
required
The path of the file relative to the project root to update.
oldText
type: RegExp | string
required
The parameter for this function represents either a string or a regular expression that is to be replaced.
newText
type: string
required
The parameter for this function represents the string to replace the old string.
Usage
Below is an illustrative example demonstrating the utilization of the update
lib.
import {fs, path} from '@brandingbrand/code-cli-kit';// file content at ./my_file.txt// "This is someKeyword content."
await fs.update( path.project.resolve('my_file.txt'), /(some)Keyword/, `$1Example`,);
// file updated content at ./my_file.txt// "This is someExample content."
guards
The guards module provides functions designed to strictly type-guard objects, aiming to restrict side-effects specifically for @brandingbrand/code-cli
usage. Within Flagship Code, we extensively employ guards for various configurations, including Flagship Code configuration, build configurations, environment configurations, and plugin configurations. The exposed guard functions include defineConfig
, defineBuild
, defineEnv
, and definePlugin
.
Function
defineConfig
This function type guards the flagship-code.config.ts
, which serves as the base configuration for Flagship Code. For more detailed information, please refer to the Flagship Code Configuration guide.
type: function defineConfig(config: CodeConfig): CodeConfig
Options
config
type: CodeConfig
required
The parameter for this function represents the Flagship Code configuration, which undergoes type-guarding and is then returned.
Usage
Below is an illustrative example demonstrating the utilization of the defineConfig
guard.
import {defineConfig} from '@brandingbrand/code-cli-kit';
export default defineConfig({ buildPath: './coderc/build', envPath: './coderc/env', pluginPath: './coderc/plugins', plugins: [ '@brandingbrand/code-plugin-native-navigation', '@brandingbrand/code-plugin-splash-screen', '@brandingbrand/code-plugin-app-icon', ],});
Function
defineBuild
This function type guards the build.<mode>.ts
, which serves as defining the build configuration. For more detailed information, please refer to the Build Configuration guide.
type: function defineBuild<T = BuildConfig>(build: (T extends BuildConfig ? BuildConfig : BuildConfig & T) | ((pkg: PackageJson) => T extends BuildConfig ? BuildConfig : BuildConfig & T)): T
Options
build
type: BuildConfig
required
The parameter for this function represents the build configuration configuration, which undergoes type-guarding and is then returned.
Usage
Below is an illustrative example demonstrating the utilization of the defineBuild
guard. Utilizing build.internal.ts
purely as an example.
import {defineBuild} from '@brandingbrand/code-cli-kit';
export default defineBuild({ ios: { bundleId: 'com.brandingbrand', displayName: 'Branding Brand', }, android: { packageName: 'com.brandingbrand', displayName: 'Branding Brand', },});
import {defineBuild} from '@brandingbrand/code-cli-kit';
export default defineBuild(pkg => ({ ios: { bundleId: 'com.brandingbrand', displayName: 'Branding Brand', versioning: { version: pkg.version, build: 1, }, }, android: { packageName: 'com.brandingbrand', displayName: 'Branding Brand', versioning: { version: pkg.version, build: 1, }, },}));
Function
defineEnv
This function type guards the env.<mode>.ts
, which serves as the env configuration for @brandingbrand/fsapp
. For more detailed information, please refer to the Environment Configuration guide.
type: function defineEnv<T>(env: T): T
Options
env
type: Env
required
The parameter for this function represents the environment configuration, which undergoes type-guarding and is then returned.
Usage
Below is an illustrative example demonstrating the utilization of the defineEnv
guard. Utilizing env.dev.ts
purely as an example.
import {defineEnv} from '@brandingbrand/code-cli-kit';
export default defineEnv<Env>({ id: 'abc12345', domain: 'https://dev.myexampledomain.com',});
Function
definePlugin
This function type guards your plugin entry point. For more detailed information, please refer to the Plugins guide.
type: function definePlugin<T>(plugin: PluginConfig<T>): PluginConfig<T>
Options
plugin
type: PluginConfig
required
The parameter for this function represents the plugin configuration, which undergoes type-guarding and is then returned.
Usage
Below is an illustrative example demonstrating the utilization of the definePlugin
guard. Utilizing index.ts
purely as an example.
import { definePlugin, type BuildConfig, type PrebuildOptions,} from '@brandingbrand/code-cli-kit';
export default definePlugin({ ios: async function (build, options): Promise<void> { // make iOS code changes here }, android: async function (build, options): Promise<void> { // make Android code changes here },});
path
The path module offers functions and constants that extend the functionality of the path
module provided by Node.js. These extensions include convenient functions and constants designed to facilitate access to various aspects of your project’s path, including iOS and Android file paths.
Function
path.project.resolve
This project enables you to resolve paths relative to your project’s root directory. Subsequent paths are constructed based on this function.
type: function (...paths: string[]): string
Options
paths
type: string[]
required
An array of strings representing a path relative to the root of the project.
Usage
Below is an illustrative example demonstrating the utilization of the path.project.resolve
to generate the absolute path to the Podfile.
import {path} from '@brandingbrand/code-cli-kit';
const podfilePath = path.project.resolve('ios', 'Podfile');
Constant
path.ios.podfile
Generates the absolute path to the iOS Podfile file.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.ios.podfile
to generate the absolute path to the Podfile.
import {path} from '@brandingbrand/code-cli-kit';
const podfilePath = path.ios.podfile;
Constant
path.ios.infoPlist
Generates the absolute path to the iOS Info.plist file.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.ios.infoPlist
to generate the absolute path to the Info.plist.
import {path} from '@brandingbrand/code-cli-kit';
const infoPlistPath = path.ios.infoPlist;
Constant
path.ios.gemfile
Generates the absolute path to the iOS Gemfile.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.ios.gemfile
to generate the absolute path to the Gemfile.
import {path} from '@brandingbrand/code-cli-kit';
const gemfilePath = path.ios.gemfile;
Constant
path.ios.envSwitcher
Generates the absolute path to the iOS EnvSwitcher.m.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.ios.envSwitcher
to generate the absolute path to the EnvSwitcher.m.
import {path} from '@brandingbrand/code-cli-kit';
const envSwitcherPath = path.ios.envSwitcher;
Constant
path.ios.entitlements
Generates the absolute path to the iOS app.entitlements.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.ios.entitlements
to generate the absolute path to the app.entitlements.
import {path} from '@brandingbrand/code-cli-kit';
const entitlementsPath = path.ios.entitlements;
Constant
path.ios.privacyManifest
Generates the absolute path to the iOS PrivacyInfo.xcprivacy.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.ios.privacyManifest
to generate the absolute path to the PrivacyInfo.xcprivacy.
import {path} from '@brandingbrand/code-cli-kit';
const privacyManifestPath = path.ios.privacyManifest;
Constant
path.ios.nativeConstants
Generates the absolute path to the iOS NativeConstants.m.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.ios.nativeConstants
to generate the absolute path to the NativeConstants.m.
import {path} from '@brandingbrand/code-cli-kit';
const nativeConstantsPath = path.ios.nativeConstants;
Constant
path.ios.projectPbxProj
Generates the absolute path to the iOS project.pbxproj.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.ios.projectPbxProj
to generate the absolute path to the project.pbxproj.
import {path} from '@brandingbrand/code-cli-kit';
const projectPbxProjPath = path.ios.projectPbxProj;
Constant
path.android.buildGradle
Generates the absolute path to the Android build.gradle.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.android.buildGradle
to generate the absolute path to the build.gradle.
import {path} from '@brandingbrand/code-cli-kit';
const buildGradlePath = path.android.buildGradle;
Constant
path.android.gemfile
Generates the absolute path to the Android Gemfile.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.android.gemfile
to generate the absolute path to the Gemfile.
import {path} from '@brandingbrand/code-cli-kit';
const gemfilePath = path.android.gemfile;
Constant
path.android.gradleProperties
Generates the absolute path to the Android gradle.properties.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.android.gradleProperties
to generate the absolute path to the gradle.properties.
import {path} from '@brandingbrand/code-cli-kit';
const gradlePropertiesPath = path.android.gradleProperties;
Constant
path.android.appBuildGradle
Generates the absolute path to the Android app module build.gradle.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.android.appBuildGradle
to generate the absolute path to the app module build.gradle.
import {path} from '@brandingbrand/code-cli-kit';
const appBuildGradlePath = path.android.appBuildGradle;
Constant
path.android.androidManifest
Generates the absolute path to the Android AndroidManifest.xml.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.android.androidManifest
to generate the absolute path to the AndroidManifest.xml.
import {path} from '@brandingbrand/code-cli-kit';
const androidManifestPath = path.android.androidManifest;
Constant
path.android.colors
Generates the absolute path to the Android colors.xml.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.android.colors
to generate the absolute path to the colors.xml.
import {path} from '@brandingbrand/code-cli-kit';
const colorsPath = path.android.colors;
Constant
path.android.networkSecurityConfig
Generates the absolute path to the Android network_security_config.xml.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.android.networkSecurityConfig
to generate the absolute path to the network_security_config.xml.
import {path} from '@brandingbrand/code-cli-kit';
const networkSecurityConfigPath = path.android.networkSecurityConfig;
Constant
path.android.strings
Generates the absolute path to the Android strings.xml.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.android.strings
to generate the absolute path to the strings.xml.
import {path} from '@brandingbrand/code-cli-kit';
const stringsPath = path.android.strings;
Constant
path.android.styles
Generates the absolute path to the Android styles.xml.
type: string
Usage
Below is an illustrative example demonstrating the utilization of the path.android.styles
to generate the absolute path to the styles.xml.
import {path} from '@brandingbrand/code-cli-kit';
const stylesPath = path.android.styles;
Function
path.android.mainApplication
Generates the absolute path to the Android MainApplication.java.
type: function (config: BuildConfig): string
Options
config
type: BuildConfig
required
The build configuration consumed by Flagship Code represented by build.<mode>.ts
.
Usage
Below is an illustrative example demonstrating the utilization of the path.android.mainApplication
to generate the absolute path to the MainApplication.java.
import {path} from '@brandingbrand/code-cli-kit';
// config aggregated from @brandingbrand/cli
const mainApplicationPath = path.android.mainApplication(config);
Function
path.android.mainActivity
Generates the absolute path to the Android MainActivity.java.
type: function (config: BuildConfig): string
Options
config
type: BuildConfig
required
The build configuration consumed by Flagship Code represented by build.<mode>.ts
.
Usage
Below is an illustrative example demonstrating the utilization of the path.android.mainActivity
to generate the absolute path to the MainActivity.java.
import {path} from '@brandingbrand/code-cli-kit';
// config aggregated from @brandingbrand/cli
const mainActivityPath = path.android.mainActivity(config);
Function
path.android.envSwitcher
Generates the absolute path to the Android EnvSwitcher.java.
type: function (config: BuildConfig): string
Options
config
type: BuildConfig
required
The build configuration consumed by Flagship Code represented by build.<mode>.ts
.
Usage
Below is an illustrative example demonstrating the utilization of the path.android.envSwitcher
to generate the absolute path to the EnvSwitcher.java.
import {path} from '@brandingbrand/code-cli-kit';
// config aggregated from @brandingbrand/cli
const envSwitcherPath = path.android.envSwitcher(config);
Function
path.android.nativeConstants
Generates the absolute path to the Android NativeConstants.java.
type: function (config: BuildConfig): string
Options
config
type: BuildConfig
required
The build configuration consumed by Flagship Code represented by build.<mode>.ts
.
Usage
Below is an illustrative example demonstrating the utilization of the path.android.nativeConstants
to generate the absolute path to the NativeConstants.java.
import {path} from '@brandingbrand/code-cli-kit';
// config aggregated from @brandingbrand/cli
const nativeConstantsPath = path.android.nativeConstants(config);
string
A comprehensive suite of string-related utility functions facilitating efficient error handling and warning notifications.
Function
replace
Safely replaces and old string or regular expression statement with a new string.
type: function (content: string, oldText: RegExp | string, newText: string): string
Options
content
type: string
required
A string that contains text to be replaced.
oldText
type: string | RegExp
required
A string or regular expression statement to represent text that needs to be replaced.
newText
type: string
required
A string of text that will replace the old text.
Usage
Below is an illustrative example demonstrating the utilization of the replace
to update a string.
import {string} from '@brandingbrand/code-cli-kit';
const originalContent = 'Hello, world!';const newText = replace(originalContent, /world/i, 'there');
console.log(newText);
// Output: "Hello, there!"