@callstack/brownfield-cli 1.0.4 → 2.0.0-rc.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/brownfield/commands/packageAndroid.d.ts.map +1 -1
- package/dist/brownfield/commands/packageAndroid.js +8 -1
- package/dist/brownfield/commands/packageIos.d.ts.map +1 -1
- package/dist/brownfield/commands/packageIos.js +23 -12
- package/dist/brownfield/commands/publishAndroid.d.ts.map +1 -1
- package/dist/brownfield/commands/publishAndroid.js +8 -1
- package/dist/brownfield/index.d.ts +0 -1
- package/dist/brownfield/index.d.ts.map +1 -1
- package/dist/brownfield/index.js +0 -1
- package/dist/brownfield/utils/expo.d.ts +7 -0
- package/dist/brownfield/utils/expo.d.ts.map +1 -0
- package/dist/brownfield/utils/expo.js +40 -0
- package/dist/brownfield/utils/paths.d.ts +6 -1
- package/dist/brownfield/utils/paths.d.ts.map +1 -1
- package/dist/brownfield/utils/paths.js +6 -4
- package/dist/brownfield/utils/project.d.ts +51 -0
- package/dist/brownfield/utils/project.d.ts.map +1 -0
- package/dist/brownfield/utils/project.js +114 -0
- package/dist/brownie/commands/codegen.d.ts.map +1 -1
- package/dist/brownie/commands/codegen.js +26 -11
- package/dist/brownie/errors/NoBrownieStoresError.d.ts +4 -0
- package/dist/brownie/errors/NoBrownieStoresError.d.ts.map +1 -0
- package/dist/brownie/errors/NoBrownieStoresError.js +6 -0
- package/dist/brownie/helpers/runBrownieCodegenIfApplicable.d.ts +5 -0
- package/dist/brownie/helpers/runBrownieCodegenIfApplicable.d.ts.map +1 -0
- package/dist/brownie/helpers/runBrownieCodegenIfApplicable.js +9 -0
- package/dist/brownie/store-discovery.d.ts.map +1 -1
- package/dist/brownie/store-discovery.js +2 -1
- package/package.json +7 -8
- package/src/brownfield/commands/packageAndroid.ts +9 -1
- package/src/brownfield/commands/packageIos.ts +28 -13
- package/src/brownfield/commands/publishAndroid.ts +9 -1
- package/src/brownfield/index.ts +0 -2
- package/src/brownfield/utils/expo.ts +71 -0
- package/src/brownfield/utils/paths.ts +7 -10
- package/src/brownfield/utils/project.ts +174 -0
- package/src/brownie/commands/codegen.ts +27 -14
- package/src/brownie/errors/NoBrownieStoresError.ts +6 -0
- package/src/brownie/helpers/runBrownieCodegenIfApplicable.ts +16 -0
- package/src/brownie/store-discovery.ts +3 -1
- package/dist/brownfield/utils/index.d.ts +0 -4
- package/dist/brownfield/utils/index.d.ts.map +0 -1
- package/dist/brownfield/utils/index.js +0 -3
- package/dist/brownfield/utils/rn-cli.d.ts +0 -17
- package/dist/brownfield/utils/rn-cli.d.ts.map +0 -1
- package/dist/brownfield/utils/rn-cli.js +0 -31
- package/src/brownfield/utils/index.ts +0 -3
- package/src/brownfield/utils/rn-cli.ts +0 -58
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageAndroid.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/packageAndroid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,OAAO,EACL,YAAY,EAGb,MAAM,uBAAuB,CAAC;
|
|
1
|
+
{"version":3,"file":"packageAndroid.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/packageAndroid.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAQpC,OAAO,EACL,YAAY,EAGb,MAAM,uBAAuB,CAAC;AAK/B,eAAO,MAAM,qBAAqB,SAwBjC,CAAC;AAEF,eAAO,MAAM,qBAAqB,cAGjC,CAAC"}
|
|
@@ -2,11 +2,18 @@ import { Command } from 'commander';
|
|
|
2
2
|
import { packageAarOptions, } from '@rock-js/platform-android';
|
|
3
3
|
import { packageAarAction } from '@rock-js/plugin-brownfield-android';
|
|
4
4
|
import { ExampleUsage, actionRunner, curryOptions, } from '../../shared/index.js';
|
|
5
|
-
import {
|
|
5
|
+
import { runExpoPrebuildIfNeeded } from '../utils/expo.js';
|
|
6
|
+
import { getProjectInfo } from '../utils/project.js';
|
|
7
|
+
import { runBrownieCodegenIfApplicable } from '../../brownie/helpers/runBrownieCodegenIfApplicable.js';
|
|
6
8
|
export const packageAndroidCommand = curryOptions(new Command('package:android').description('Build Android AAR'), packageAarOptions.map((option) => option.name.startsWith('--variant')
|
|
7
9
|
? { ...option, default: 'debug' }
|
|
8
10
|
: option)).action(actionRunner(async (options) => {
|
|
9
11
|
const { projectRoot, platformConfig } = getProjectInfo('android');
|
|
12
|
+
await runExpoPrebuildIfNeeded({
|
|
13
|
+
projectRoot,
|
|
14
|
+
platform: 'android',
|
|
15
|
+
});
|
|
16
|
+
await runBrownieCodegenIfApplicable(projectRoot, 'kotlin');
|
|
10
17
|
await packageAarAction({
|
|
11
18
|
projectRoot,
|
|
12
19
|
pluginConfig: platformConfig,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"packageIos.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/packageIos.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"packageIos.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/packageIos.ts"],"names":[],"mappings":"AAeA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAIpC,OAAO,EAGL,YAAY,EACb,MAAM,uBAAuB,CAAC;AAI/B,eAAO,MAAM,iBAAiB,SAqG7B,CAAC;AAEF,eAAO,MAAM,iBAAiB,cAG7B,CAAC"}
|
|
@@ -3,32 +3,43 @@ import { getBuildOptions, mergeFrameworks, } from '@rock-js/platform-apple-helpe
|
|
|
3
3
|
import { packageIosAction } from '@rock-js/plugin-brownfield-ios';
|
|
4
4
|
import { colorLink, getReactNativeVersion, logger, relativeToCwd, } from '@rock-js/tools';
|
|
5
5
|
import { Command } from 'commander';
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
8
|
-
import { getProjectInfo, stripFrameworkBinary } from '../utils/index.js';
|
|
6
|
+
import { runExpoPrebuildIfNeeded } from '../utils/expo.js';
|
|
7
|
+
import { getProjectInfo } from '../utils/project.js';
|
|
9
8
|
import { actionRunner, curryOptions, ExampleUsage, } from '../../shared/index.js';
|
|
9
|
+
import { runBrownieCodegenIfApplicable } from '../../brownie/helpers/runBrownieCodegenIfApplicable.js';
|
|
10
|
+
import { stripFrameworkBinary } from '../utils/stripFrameworkBinary.js';
|
|
10
11
|
export const packageIosCommand = curryOptions(new Command('package:ios').description('Build iOS XCFramework'), getBuildOptions({ platformName: 'ios' }).map((option) => option.name.startsWith('--build-folder')
|
|
11
12
|
? {
|
|
12
13
|
...option,
|
|
13
14
|
description: option.description +
|
|
14
|
-
" By default, the '
|
|
15
|
+
" By default, the '.brownfield/build' path will be used.",
|
|
15
16
|
}
|
|
16
17
|
: option)).action(actionRunner(async (options) => {
|
|
17
18
|
const { projectRoot, platformConfig, userConfig } = getProjectInfo('ios');
|
|
19
|
+
await runExpoPrebuildIfNeeded({ projectRoot, platform: 'ios' });
|
|
18
20
|
if (!userConfig.project.ios) {
|
|
19
21
|
throw new Error('iOS project not found.');
|
|
20
22
|
}
|
|
21
23
|
if (!userConfig.project.ios.xcodeProject) {
|
|
22
24
|
throw new Error('iOS Xcode project not found in the configuration.');
|
|
23
25
|
}
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
26
|
+
let dotBrownfieldDir = path.join(
|
|
27
|
+
// for Expo projects, platformConfig?.sourceDir == "", but for non-Expo projects, it's "ios"
|
|
28
|
+
...(userConfig.project.ios.sourceDir.trim().length > 0
|
|
29
|
+
? [userConfig.project.ios.sourceDir]
|
|
30
|
+
: [projectRoot, 'ios']), '.brownfield');
|
|
31
|
+
// non-Expo projects have a relative sourceDir path, so we need to make it absolute
|
|
32
|
+
if (!path.isAbsolute(dotBrownfieldDir)) {
|
|
33
|
+
dotBrownfieldDir = path.join(projectRoot, dotBrownfieldDir);
|
|
31
34
|
}
|
|
35
|
+
options.buildFolder ??= path.join(dotBrownfieldDir, 'build');
|
|
36
|
+
// The new_architecture.rb script scans Info.plist and fails on binary plist files,
|
|
37
|
+
// which is the case for our XCFrameworks.
|
|
38
|
+
// We're reusing the "build" directory which is excluded from the scan.
|
|
39
|
+
// Reference: https://github.com/facebook/react-native/blob/490c5e8dcc6cdb19c334cc39e93a39a48ba71e96/packages/react-native/scripts/cocoapods/new_architecture.rb#L171
|
|
40
|
+
const packageDir = path.join(dotBrownfieldDir, 'package', 'build');
|
|
41
|
+
const configuration = options.configuration ?? 'Debug';
|
|
42
|
+
const { hasBrownie } = await runBrownieCodegenIfApplicable(projectRoot, 'swift');
|
|
32
43
|
await packageIosAction(options, {
|
|
33
44
|
projectRoot,
|
|
34
45
|
reactNativePath: userConfig.reactNativePath,
|
|
@@ -54,7 +65,7 @@ export const packageIosCommand = curryOptions(new Command('package:ios').descrip
|
|
|
54
65
|
// Strip the binary from Brownie.xcframework to make it interface-only.
|
|
55
66
|
// This avoids duplicate symbols when consumer apps embed both BrownfieldLib
|
|
56
67
|
// (which contains Brownie symbols) and Brownie.xcframework.
|
|
57
|
-
|
|
68
|
+
stripFrameworkBinary(brownieOutputPath);
|
|
58
69
|
logger.success(`Brownie.xcframework created at ${colorLink(relativeToCwd(brownieOutputPath))}`);
|
|
59
70
|
}
|
|
60
71
|
}));
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"publishAndroid.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/publishAndroid.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"publishAndroid.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/publishAndroid.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAEpC,OAAO,EAGL,YAAY,EACb,MAAM,uBAAuB,CAAC;AAK/B,eAAO,MAAM,qBAAqB,SAqBjC,CAAC;AAEF,eAAO,MAAM,qBAAqB,cAGjC,CAAC"}
|
|
@@ -1,10 +1,17 @@
|
|
|
1
1
|
import { publishLocalAarAction } from '@rock-js/plugin-brownfield-android';
|
|
2
2
|
import { publishLocalAarOptions, } from '@rock-js/platform-android';
|
|
3
3
|
import { Command } from 'commander';
|
|
4
|
-
import { getProjectInfo } from '../utils/index.js';
|
|
5
4
|
import { actionRunner, curryOptions, ExampleUsage, } from '../../shared/index.js';
|
|
5
|
+
import { getProjectInfo } from '../utils/project.js';
|
|
6
|
+
import { runExpoPrebuildIfNeeded } from '../utils/expo.js';
|
|
7
|
+
import { runBrownieCodegenIfApplicable } from '../../brownie/helpers/runBrownieCodegenIfApplicable.js';
|
|
6
8
|
export const publishAndroidCommand = curryOptions(new Command('publish:android').description('Publish Android package to Maven local'), publishLocalAarOptions).action(actionRunner(async (options) => {
|
|
7
9
|
const { projectRoot, platformConfig } = getProjectInfo('android');
|
|
10
|
+
await runExpoPrebuildIfNeeded({
|
|
11
|
+
projectRoot,
|
|
12
|
+
platform: 'android',
|
|
13
|
+
});
|
|
14
|
+
await runBrownieCodegenIfApplicable(projectRoot, 'kotlin');
|
|
8
15
|
await publishLocalAarAction({
|
|
9
16
|
projectRoot,
|
|
10
17
|
pluginConfig: platformConfig,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/brownfield/index.ts"],"names":[],"mappings":"AAWA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/brownfield/index.ts"],"names":[],"mappings":"AAWA,eAAO,MAAM,SAAS,QAA+J,CAAC;AAEtL,eAAO,MAAM,QAAQ;;;;;;;CAOpB,CAAC;AACF,eAAe,QAAQ,CAAC"}
|
package/dist/brownfield/index.js
CHANGED
|
@@ -2,7 +2,6 @@ import { styleText } from 'node:util';
|
|
|
2
2
|
import { packageAndroidCommand, packageAndroidExample, } from './commands/packageAndroid.js';
|
|
3
3
|
import { publishAndroidCommand, publishAndroidExample, } from './commands/publishAndroid.js';
|
|
4
4
|
import { packageIosCommand, packageIosExample } from './commands/packageIos.js';
|
|
5
|
-
export * from './utils/index.js';
|
|
6
5
|
export const groupName = `${styleText(['bold', 'blueBright'], '@callstack/react-native-brownfield')}${styleText('whiteBright', ' - utilities for React Native Brownfield projects')}`;
|
|
7
6
|
export const Commands = {
|
|
8
7
|
packageAndroidCommand,
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"expo.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/expo.ts"],"names":[],"mappings":"AAMA,KAAK,YAAY,GAAG,KAAK,GAAG,SAAS,CAAC;AAqCtC,wBAAsB,uBAAuB,CAAC,EAC5C,WAAW,EACX,QAAQ,GACT,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,YAAY,CAAC;CACxB,oBAqBA"}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
import { logger } from '@rock-js/tools';
|
|
3
|
+
import { isExpoProject } from './project.js';
|
|
4
|
+
async function spawnCommand({ command, args, cwd, }) {
|
|
5
|
+
await new Promise((resolve, reject) => {
|
|
6
|
+
const child = spawn(command, args, {
|
|
7
|
+
cwd,
|
|
8
|
+
env: process.env,
|
|
9
|
+
stdio: 'inherit',
|
|
10
|
+
});
|
|
11
|
+
child.on('error', reject);
|
|
12
|
+
child.on('close', (code) => {
|
|
13
|
+
if (code === 0) {
|
|
14
|
+
resolve();
|
|
15
|
+
}
|
|
16
|
+
else {
|
|
17
|
+
reject(new Error(`Command "${command} ${args.join(' ')}" failed with exit code ${code ?? 'unknown'}.`));
|
|
18
|
+
}
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
function getNpxCommand() {
|
|
23
|
+
return process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
24
|
+
}
|
|
25
|
+
export async function runExpoPrebuildIfNeeded({ projectRoot, platform, }) {
|
|
26
|
+
if (!isExpoProject(projectRoot)) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
logger.info(`Expo project detected. Running expo prebuild for ${platform}...`);
|
|
30
|
+
const args = ['expo', 'prebuild', '--platform', platform];
|
|
31
|
+
if (platform === 'ios') {
|
|
32
|
+
args.push('--no-install');
|
|
33
|
+
}
|
|
34
|
+
await spawnCommand({
|
|
35
|
+
command: getNpxCommand(),
|
|
36
|
+
args,
|
|
37
|
+
cwd: projectRoot,
|
|
38
|
+
});
|
|
39
|
+
return true;
|
|
40
|
+
}
|
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
import type { AndroidProjectConfig, IOSProjectConfig } from '@react-native-community/cli-types';
|
|
2
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Helper function to mutate the user config paths in place to be relative to the project root
|
|
4
|
+
* @param projectRoot The path to the project root directory
|
|
5
|
+
* @param userConfig User configuration from the RNC CLI
|
|
6
|
+
*/
|
|
7
|
+
export declare function makeRelativeProjectConfigPaths<UserConfig extends AndroidProjectConfig | IOSProjectConfig | undefined>(projectRoot: string, userConfig: UserConfig): void;
|
|
3
8
|
/**
|
|
4
9
|
* Helper function to find RN project root by recursively looking for a package.json in the parent directories
|
|
5
10
|
* @returns The path to the project root directory
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/paths.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/paths.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,oBAAoB,EACpB,gBAAgB,EACjB,MAAM,mCAAmC,CAAC;AAE3C;;;;GAIG;AACH,wBAAgB,8BAA8B,CAC5C,UAAU,SAAS,oBAAoB,GAAG,gBAAgB,GAAG,SAAS,EACtE,WAAW,EAAE,MAAM,EAAE,UAAU,EAAE,UAAU,QAI5C;AAED;;;GAGG;AACH,wBAAgB,eAAe,IAAI,MAAM,CAWxC"}
|
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import * as path from 'node:path';
|
|
2
2
|
import * as fs from 'node:fs';
|
|
3
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Helper function to mutate the user config paths in place to be relative to the project root
|
|
5
|
+
* @param projectRoot The path to the project root directory
|
|
6
|
+
* @param userConfig User configuration from the RNC CLI
|
|
7
|
+
*/
|
|
4
8
|
export function makeRelativeProjectConfigPaths(projectRoot, userConfig) {
|
|
5
|
-
const relativeConfig = cloneDeep(userConfig);
|
|
6
9
|
if (userConfig?.sourceDir) {
|
|
7
|
-
|
|
10
|
+
userConfig.sourceDir = path.relative(projectRoot, userConfig.sourceDir);
|
|
8
11
|
}
|
|
9
|
-
return relativeConfig;
|
|
10
12
|
}
|
|
11
13
|
/**
|
|
12
14
|
* Helper function to find RN project root by recursively looking for a package.json in the parent directories
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import type { AndroidProjectConfig, ProjectConfig, UserConfig } from '@react-native-community/cli-types';
|
|
2
|
+
import type { PackageAarFlags } from '@rock-js/platform-android';
|
|
3
|
+
import { type ProjectConfig as ExpoProjectConfig } from '@expo/config';
|
|
4
|
+
/**
|
|
5
|
+
* Gets the Expo config if the project is an Expo project
|
|
6
|
+
* @param projectRoot The project root path
|
|
7
|
+
* @returns The Expo config if the project is an Expo project, null otherwise
|
|
8
|
+
*/
|
|
9
|
+
export declare function getExpoConfigIfIsExpo(projectRoot: string): ExpoProjectConfig | null;
|
|
10
|
+
/**
|
|
11
|
+
* Checks if the project is an Expo project; checks both if installed and explicitly listed
|
|
12
|
+
* in the project's package.json to prevent false positives in a monorepo setup
|
|
13
|
+
* @param projectRoot The project root path
|
|
14
|
+
* @returns Whether the project is an Expo project
|
|
15
|
+
*/
|
|
16
|
+
export declare function isExpoProject(projectRoot: string): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* Fills the RNC CLI project config from the Expo config by mutating the passed in `options.projectConfig` object in place
|
|
19
|
+
*/
|
|
20
|
+
export declare function fillProjectConfigFromExpoConfig({ projectConfig, expoConfig: { exp }, projectRoot, }: {
|
|
21
|
+
/** The RNC CLI project config to be filled */
|
|
22
|
+
projectConfig: ProjectConfig;
|
|
23
|
+
/** The Expo project config */
|
|
24
|
+
expoConfig: ExpoProjectConfig;
|
|
25
|
+
/** The project root path */
|
|
26
|
+
projectRoot: string;
|
|
27
|
+
}): void;
|
|
28
|
+
/**
|
|
29
|
+
* Gets the project info for the given platform from the current working directory
|
|
30
|
+
* @param platform the platform for which to get project info
|
|
31
|
+
* @returns project root and android project config
|
|
32
|
+
*/
|
|
33
|
+
export declare function getProjectInfo<Platform extends 'ios' | 'android'>(platform: Platform): {
|
|
34
|
+
projectRoot: string;
|
|
35
|
+
userConfig: UserConfig;
|
|
36
|
+
platformConfig: ProjectConfig[Platform];
|
|
37
|
+
};
|
|
38
|
+
export declare function getUserConfig({ projectRoot, platform, }: {
|
|
39
|
+
projectRoot: string;
|
|
40
|
+
platform: 'ios' | 'android';
|
|
41
|
+
}): UserConfig;
|
|
42
|
+
/**
|
|
43
|
+
* Gets the AAR packaging configuration for the given Android project
|
|
44
|
+
* @param args The AAR packaging flags
|
|
45
|
+
* @param androidConfig The Android project config
|
|
46
|
+
*/
|
|
47
|
+
export declare function getAarConfig(args: PackageAarFlags, androidConfig: AndroidProjectConfig): {
|
|
48
|
+
sourceDir: string;
|
|
49
|
+
moduleName: string;
|
|
50
|
+
};
|
|
51
|
+
//# sourceMappingURL=project.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"project.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/project.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,oBAAoB,EACpB,aAAa,EACb,UAAU,EACX,MAAM,mCAAmC,CAAC;AAC3C,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AAKjE,OAAO,EAEL,KAAK,aAAa,IAAI,iBAAiB,EACxC,MAAM,cAAc,CAAC;AAQtB;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,WAAW,EAAE,MAAM,4BAMxD;AAED;;;;;GAKG;AACH,wBAAgB,aAAa,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAc1D;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,EAC9C,aAAa,EACb,UAAU,EAAE,EAAE,GAAG,EAAE,EACnB,WAAW,GACZ,EAAE;IACD,8CAA8C;IAC9C,aAAa,EAAE,aAAa,CAAC;IAE7B,8BAA8B;IAC9B,UAAU,EAAE,iBAAiB,CAAC;IAE9B,4BAA4B;IAC5B,WAAW,EAAE,MAAM,CAAC;CACrB,QAuBA;AAED;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,SAAS,KAAK,GAAG,SAAS,EAC/D,QAAQ,EAAE,QAAQ,GACjB;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,cAAc,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;CACzC,CAeA;AAED,wBAAgB,aAAa,CAAC,EAC5B,WAAW,EACX,QAAQ,GACT,EAAE;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAC;CAC7B,GAAG,UAAU,CAuBb;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAC1B,IAAI,EAAE,eAAe,EACrB,aAAa,EAAE,oBAAoB;;;EAQpC"}
|
|
@@ -0,0 +1,114 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import cliConfigImport from '@react-native-community/cli-config';
|
|
4
|
+
import { findProjectRoot, makeRelativeProjectConfigPaths } from './paths.js';
|
|
5
|
+
import { getConfig, } from '@expo/config';
|
|
6
|
+
const cliConfig = typeof cliConfigImport === 'function'
|
|
7
|
+
? cliConfigImport
|
|
8
|
+
: // @ts-expect-error: interop default
|
|
9
|
+
cliConfigImport.default;
|
|
10
|
+
/**
|
|
11
|
+
* Gets the Expo config if the project is an Expo project
|
|
12
|
+
* @param projectRoot The project root path
|
|
13
|
+
* @returns The Expo config if the project is an Expo project, null otherwise
|
|
14
|
+
*/
|
|
15
|
+
export function getExpoConfigIfIsExpo(projectRoot) {
|
|
16
|
+
try {
|
|
17
|
+
return getConfig(projectRoot, { skipSDKVersionRequirement: true });
|
|
18
|
+
}
|
|
19
|
+
catch {
|
|
20
|
+
return null;
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Checks if the project is an Expo project; checks both if installed and explicitly listed
|
|
25
|
+
* in the project's package.json to prevent false positives in a monorepo setup
|
|
26
|
+
* @param projectRoot The project root path
|
|
27
|
+
* @returns Whether the project is an Expo project
|
|
28
|
+
*/
|
|
29
|
+
export function isExpoProject(projectRoot) {
|
|
30
|
+
const hasExpoConfig = getExpoConfigIfIsExpo(projectRoot) !== null;
|
|
31
|
+
// additionally, it is needed to check if the project depends on Expo packages explicitly
|
|
32
|
+
// to prevent false positives in a monorepo setup
|
|
33
|
+
const rnProjectRoot = findProjectRoot();
|
|
34
|
+
const packageJsonPath = path.join(rnProjectRoot, 'package.json');
|
|
35
|
+
const dependsOnExpo = fs.existsSync(packageJsonPath) &&
|
|
36
|
+
['dependencies', 'peerDependencies', 'devDependencies'].some((key) => JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))[key]?.expo);
|
|
37
|
+
return hasExpoConfig && dependsOnExpo;
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* Fills the RNC CLI project config from the Expo config by mutating the passed in `options.projectConfig` object in place
|
|
41
|
+
*/
|
|
42
|
+
export function fillProjectConfigFromExpoConfig({ projectConfig, expoConfig: { exp }, projectRoot, }) {
|
|
43
|
+
if (exp.android) {
|
|
44
|
+
projectConfig['android'] = {
|
|
45
|
+
applicationId: exp.android.package,
|
|
46
|
+
packageName: exp.android.package,
|
|
47
|
+
appName: exp.name,
|
|
48
|
+
assets: [],
|
|
49
|
+
mainActivity: 'MainActivity',
|
|
50
|
+
sourceDir: 'android',
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
if (exp.ios) {
|
|
54
|
+
projectConfig['ios'] = {
|
|
55
|
+
assets: [],
|
|
56
|
+
sourceDir: projectRoot,
|
|
57
|
+
xcodeProject: {
|
|
58
|
+
path: '.',
|
|
59
|
+
name: `${exp.name}.xcworkspace`,
|
|
60
|
+
isWorkspace: true,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
/**
|
|
66
|
+
* Gets the project info for the given platform from the current working directory
|
|
67
|
+
* @param platform the platform for which to get project info
|
|
68
|
+
* @returns project root and android project config
|
|
69
|
+
*/
|
|
70
|
+
export function getProjectInfo(platform) {
|
|
71
|
+
const projectRoot = findProjectRoot();
|
|
72
|
+
const userConfig = getUserConfig({ projectRoot, platform });
|
|
73
|
+
const platformConfig = userConfig.project[platform];
|
|
74
|
+
if (!platformConfig) {
|
|
75
|
+
throw new Error(`${platform} project not found.`);
|
|
76
|
+
}
|
|
77
|
+
return {
|
|
78
|
+
projectRoot,
|
|
79
|
+
userConfig,
|
|
80
|
+
platformConfig: platformConfig,
|
|
81
|
+
};
|
|
82
|
+
}
|
|
83
|
+
export function getUserConfig({ projectRoot, platform, }) {
|
|
84
|
+
// resolve the config using RNC CLI
|
|
85
|
+
const userConfig = cliConfig({
|
|
86
|
+
projectRoot,
|
|
87
|
+
selectedPlatform: platform,
|
|
88
|
+
});
|
|
89
|
+
let projectConfig = userConfig.project;
|
|
90
|
+
// below: try augmenting the config with values for Expo projects, if applicable
|
|
91
|
+
const maybeExpoConfig = getExpoConfigIfIsExpo(projectRoot);
|
|
92
|
+
if (maybeExpoConfig) {
|
|
93
|
+
fillProjectConfigFromExpoConfig({
|
|
94
|
+
projectConfig,
|
|
95
|
+
expoConfig: maybeExpoConfig,
|
|
96
|
+
projectRoot,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
// below: relative sourceDir path is required by RN CLI's API
|
|
100
|
+
makeRelativeProjectConfigPaths(projectRoot, projectConfig[platform]);
|
|
101
|
+
return userConfig;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Gets the AAR packaging configuration for the given Android project
|
|
105
|
+
* @param args The AAR packaging flags
|
|
106
|
+
* @param androidConfig The Android project config
|
|
107
|
+
*/
|
|
108
|
+
export function getAarConfig(args, androidConfig) {
|
|
109
|
+
const config = {
|
|
110
|
+
sourceDir: androidConfig.sourceDir,
|
|
111
|
+
moduleName: args.moduleName ?? '',
|
|
112
|
+
};
|
|
113
|
+
return config;
|
|
114
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../../src/brownie/commands/codegen.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAa5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"codegen.d.ts","sourceRoot":"","sources":["../../../src/brownie/commands/codegen.ts"],"names":[],"mappings":"AAGA,OAAO,EAAE,OAAO,EAAU,MAAM,WAAW,CAAC;AAa5C,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAsE5C,MAAM,MAAM,iBAAiB,GAAG;IAAE,QAAQ,CAAC,EAAE,QAAQ,CAAA;CAAE,CAAC;AAExD;;GAEG;AACH,wBAAsB,UAAU,CAAC,EAAE,QAAQ,EAAE,EAAE,iBAAiB,iBA8C/D;AAED,eAAO,MAAM,cAAc,SAYxB,CAAC"}
|
|
@@ -8,6 +8,7 @@ import { loadConfig, getSwiftOutputPath, } from '../config.js';
|
|
|
8
8
|
import { generateSwift } from '../generators/swift.js';
|
|
9
9
|
import { generateKotlin } from '../generators/kotlin.js';
|
|
10
10
|
import { discoverStores } from '../store-discovery.js';
|
|
11
|
+
import { NoBrownieStoresError } from '../errors/NoBrownieStoresError.js';
|
|
11
12
|
function getOutputPath(dir, name, ext) {
|
|
12
13
|
return path.join(dir, `${name}.${ext}`);
|
|
13
14
|
}
|
|
@@ -71,20 +72,34 @@ export async function runCodegen({ platform }) {
|
|
|
71
72
|
logger.error(`Invalid platform: ${platform}. Must be 'swift' or 'kotlin'`);
|
|
72
73
|
process.exit(1);
|
|
73
74
|
}
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
75
|
+
try {
|
|
76
|
+
const stores = discoverStores();
|
|
77
|
+
const isMultipleStores = stores.length > 1;
|
|
78
|
+
const schemaList = stores
|
|
79
|
+
.map((s) => path.basename(s.schemaPath))
|
|
80
|
+
.join(', ');
|
|
81
|
+
logger.info(styleText('cyan', `Generating store types from ${schemaList}...`));
|
|
82
|
+
for (const store of stores) {
|
|
83
|
+
let platforms;
|
|
84
|
+
if (platform) {
|
|
85
|
+
platforms = [platform];
|
|
86
|
+
}
|
|
87
|
+
else {
|
|
88
|
+
// Only generate Swift by default (Kotlin not yet released)
|
|
89
|
+
platforms = ['swift'];
|
|
90
|
+
}
|
|
91
|
+
await generateForStore(store, config, platforms, isMultipleStores);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
catch (error) {
|
|
95
|
+
if (error instanceof NoBrownieStoresError) {
|
|
96
|
+
logger.error(error.message);
|
|
97
|
+
outro('No brownie stores found, nothing was generated.');
|
|
98
|
+
return;
|
|
82
99
|
}
|
|
83
100
|
else {
|
|
84
|
-
|
|
85
|
-
platforms = ['swift'];
|
|
101
|
+
throw error;
|
|
86
102
|
}
|
|
87
|
-
await generateForStore(store, config, platforms, isMultipleStores);
|
|
88
103
|
}
|
|
89
104
|
outro('Done!');
|
|
90
105
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"NoBrownieStoresError.d.ts","sourceRoot":"","sources":["../../../src/brownie/errors/NoBrownieStoresError.ts"],"names":[],"mappings":"AAAA,qBAAa,oBAAqB,SAAQ,KAAK;gBACjC,OAAO,EAAE,MAAM;CAI5B"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"runBrownieCodegenIfApplicable.d.ts","sourceRoot":"","sources":["../../../src/brownie/helpers/runBrownieCodegenIfApplicable.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,aAAa,CAAC;AAE5C,wBAAsB,6BAA6B,CACjD,WAAW,EAAE,MAAM,EACnB,QAAQ,EAAE,QAAQ;;GAQnB"}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { runCodegen } from '../commands/codegen.js';
|
|
2
|
+
import { isBrownieInstalled } from '../config.js';
|
|
3
|
+
export async function runBrownieCodegenIfApplicable(projectRoot, platform) {
|
|
4
|
+
const hasBrownie = isBrownieInstalled(projectRoot);
|
|
5
|
+
if (hasBrownie) {
|
|
6
|
+
await runCodegen({ platform });
|
|
7
|
+
}
|
|
8
|
+
return { hasBrownie };
|
|
9
|
+
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store-discovery.d.ts","sourceRoot":"","sources":["../../src/brownie/store-discovery.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"store-discovery.d.ts","sourceRoot":"","sources":["../../src/brownie/store-discovery.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC9B,IAAI,EAAE,MAAM,CAAC;IACb,UAAU,EAAE,MAAM,CAAC;CACpB;AA4DD;;;GAGG;AACH,wBAAgB,cAAc,CAC5B,OAAO,GAAE,MAAsB,GAC9B,eAAe,EAAE,CAkCnB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import fs from 'node:fs';
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { Project } from 'ts-morph';
|
|
4
|
+
import { NoBrownieStoresError } from './errors/NoBrownieStoresError.js';
|
|
4
5
|
/**
|
|
5
6
|
* Recursively finds all *.brownie.ts files in a directory.
|
|
6
7
|
*/
|
|
@@ -53,7 +54,7 @@ function parseStoresFromFile(project, filePath) {
|
|
|
53
54
|
export function discoverStores(rootDir = process.cwd()) {
|
|
54
55
|
const brownieFiles = findBrownieFiles(rootDir);
|
|
55
56
|
if (brownieFiles.length === 0) {
|
|
56
|
-
throw new
|
|
57
|
+
throw new NoBrownieStoresError('No brownie store files found. Create a file ending with .brownie.ts ' +
|
|
57
58
|
'(e.g., MyStore.brownie.ts)');
|
|
58
59
|
}
|
|
59
60
|
const project = new Project({ skipAddingFilesFromTsConfig: true });
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@callstack/brownfield-cli",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "2.0.0-rc.1",
|
|
4
4
|
"license": "MIT",
|
|
5
5
|
"author": "Artur Morys-Magiera <artus9033@gmail.com>",
|
|
6
6
|
"bin": {
|
|
@@ -67,15 +67,15 @@
|
|
|
67
67
|
"@react-native-community/cli-config-android": "*"
|
|
68
68
|
},
|
|
69
69
|
"dependencies": {
|
|
70
|
+
"@expo/config": "^12.0.13",
|
|
70
71
|
"@react-native-community/cli-config": "^20.0.0",
|
|
71
72
|
"@react-native-community/cli-config-android": "^20.0.0",
|
|
72
|
-
"@rock-js/platform-android": "^0.12.
|
|
73
|
-
"@rock-js/platform-apple-helpers": "^0.12.
|
|
74
|
-
"@rock-js/plugin-brownfield-android": "^0.12.
|
|
75
|
-
"@rock-js/plugin-brownfield-ios": "^0.12.
|
|
76
|
-
"@rock-js/tools": "^0.12.
|
|
73
|
+
"@rock-js/platform-android": "^0.12.8",
|
|
74
|
+
"@rock-js/platform-apple-helpers": "^0.12.8",
|
|
75
|
+
"@rock-js/plugin-brownfield-android": "^0.12.8",
|
|
76
|
+
"@rock-js/plugin-brownfield-ios": "^0.12.8",
|
|
77
|
+
"@rock-js/tools": "^0.12.8",
|
|
77
78
|
"commander": "^14.0.2",
|
|
78
|
-
"lodash.clonedeep": "^4.5.0",
|
|
79
79
|
"ts-morph": "^27.0.2"
|
|
80
80
|
},
|
|
81
81
|
"devDependencies": {
|
|
@@ -87,7 +87,6 @@
|
|
|
87
87
|
"@react-native/eslint-config": "0.82.1",
|
|
88
88
|
"@types/babel__core": "^7.20.5",
|
|
89
89
|
"@types/babel__preset-env": "^7.10.0",
|
|
90
|
-
"@types/lodash.clonedeep": "^4.5.9",
|
|
91
90
|
"@types/node": "^25.0.8",
|
|
92
91
|
"@vitest/coverage-v8": "^4.0.17",
|
|
93
92
|
"eslint": "^9.28.0",
|
|
@@ -11,7 +11,9 @@ import {
|
|
|
11
11
|
actionRunner,
|
|
12
12
|
curryOptions,
|
|
13
13
|
} from '../../shared/index.js';
|
|
14
|
-
import {
|
|
14
|
+
import { runExpoPrebuildIfNeeded } from '../utils/expo.js';
|
|
15
|
+
import { getProjectInfo } from '../utils/project.js';
|
|
16
|
+
import { runBrownieCodegenIfApplicable } from '../../brownie/helpers/runBrownieCodegenIfApplicable.js';
|
|
15
17
|
|
|
16
18
|
export const packageAndroidCommand = curryOptions(
|
|
17
19
|
new Command('package:android').description('Build Android AAR'),
|
|
@@ -23,6 +25,12 @@ export const packageAndroidCommand = curryOptions(
|
|
|
23
25
|
).action(
|
|
24
26
|
actionRunner(async (options: PackageAarFlags) => {
|
|
25
27
|
const { projectRoot, platformConfig } = getProjectInfo('android');
|
|
28
|
+
await runExpoPrebuildIfNeeded({
|
|
29
|
+
projectRoot,
|
|
30
|
+
platform: 'android',
|
|
31
|
+
});
|
|
32
|
+
|
|
33
|
+
await runBrownieCodegenIfApplicable(projectRoot, 'kotlin');
|
|
26
34
|
|
|
27
35
|
await packageAarAction({
|
|
28
36
|
projectRoot,
|
|
@@ -15,14 +15,15 @@ import {
|
|
|
15
15
|
|
|
16
16
|
import { Command } from 'commander';
|
|
17
17
|
|
|
18
|
-
import {
|
|
19
|
-
import {
|
|
20
|
-
import { getProjectInfo, stripFrameworkBinary } from '../utils/index.js';
|
|
18
|
+
import { runExpoPrebuildIfNeeded } from '../utils/expo.js';
|
|
19
|
+
import { getProjectInfo } from '../utils/project.js';
|
|
21
20
|
import {
|
|
22
21
|
actionRunner,
|
|
23
22
|
curryOptions,
|
|
24
23
|
ExampleUsage,
|
|
25
24
|
} from '../../shared/index.js';
|
|
25
|
+
import { runBrownieCodegenIfApplicable } from '../../brownie/helpers/runBrownieCodegenIfApplicable.js';
|
|
26
|
+
import { stripFrameworkBinary } from '../utils/stripFrameworkBinary.js';
|
|
26
27
|
|
|
27
28
|
export const packageIosCommand = curryOptions(
|
|
28
29
|
new Command('package:ios').description('Build iOS XCFramework'),
|
|
@@ -32,13 +33,14 @@ export const packageIosCommand = curryOptions(
|
|
|
32
33
|
...option,
|
|
33
34
|
description:
|
|
34
35
|
option.description +
|
|
35
|
-
" By default, the '
|
|
36
|
+
" By default, the '.brownfield/build' path will be used.",
|
|
36
37
|
}
|
|
37
38
|
: option
|
|
38
39
|
)
|
|
39
40
|
).action(
|
|
40
41
|
actionRunner(async (options: AppleBuildFlags) => {
|
|
41
42
|
const { projectRoot, platformConfig, userConfig } = getProjectInfo('ios');
|
|
43
|
+
await runExpoPrebuildIfNeeded({ projectRoot, platform: 'ios' });
|
|
42
44
|
|
|
43
45
|
if (!userConfig.project.ios) {
|
|
44
46
|
throw new Error('iOS project not found.');
|
|
@@ -48,19 +50,32 @@ export const packageIosCommand = curryOptions(
|
|
|
48
50
|
throw new Error('iOS Xcode project not found in the configuration.');
|
|
49
51
|
}
|
|
50
52
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
+
let dotBrownfieldDir = path.join(
|
|
54
|
+
// for Expo projects, platformConfig?.sourceDir == "", but for non-Expo projects, it's "ios"
|
|
55
|
+
...(userConfig.project.ios.sourceDir.trim().length > 0
|
|
56
|
+
? [userConfig.project.ios.sourceDir]
|
|
57
|
+
: [projectRoot, 'ios']),
|
|
53
58
|
'.brownfield'
|
|
54
59
|
);
|
|
55
60
|
|
|
56
|
-
|
|
57
|
-
|
|
61
|
+
// non-Expo projects have a relative sourceDir path, so we need to make it absolute
|
|
62
|
+
if (!path.isAbsolute(dotBrownfieldDir)) {
|
|
63
|
+
dotBrownfieldDir = path.join(projectRoot, dotBrownfieldDir);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
options.buildFolder ??= path.join(dotBrownfieldDir, 'build');
|
|
67
|
+
|
|
68
|
+
// The new_architecture.rb script scans Info.plist and fails on binary plist files,
|
|
69
|
+
// which is the case for our XCFrameworks.
|
|
70
|
+
// We're reusing the "build" directory which is excluded from the scan.
|
|
71
|
+
// Reference: https://github.com/facebook/react-native/blob/490c5e8dcc6cdb19c334cc39e93a39a48ba71e96/packages/react-native/scripts/cocoapods/new_architecture.rb#L171
|
|
72
|
+
const packageDir = path.join(dotBrownfieldDir, 'package', 'build');
|
|
58
73
|
const configuration = options.configuration ?? 'Debug';
|
|
59
74
|
|
|
60
|
-
const hasBrownie =
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
75
|
+
const { hasBrownie } = await runBrownieCodegenIfApplicable(
|
|
76
|
+
projectRoot,
|
|
77
|
+
'swift'
|
|
78
|
+
);
|
|
64
79
|
|
|
65
80
|
await packageIosAction(
|
|
66
81
|
options,
|
|
@@ -104,7 +119,7 @@ export const packageIosCommand = curryOptions(
|
|
|
104
119
|
// Strip the binary from Brownie.xcframework to make it interface-only.
|
|
105
120
|
// This avoids duplicate symbols when consumer apps embed both BrownfieldLib
|
|
106
121
|
// (which contains Brownie symbols) and Brownie.xcframework.
|
|
107
|
-
|
|
122
|
+
stripFrameworkBinary(brownieOutputPath);
|
|
108
123
|
|
|
109
124
|
logger.success(
|
|
110
125
|
`Brownie.xcframework created at ${colorLink(relativeToCwd(brownieOutputPath))}`
|
|
@@ -6,12 +6,14 @@ import {
|
|
|
6
6
|
|
|
7
7
|
import { Command } from 'commander';
|
|
8
8
|
|
|
9
|
-
import { getProjectInfo } from '../utils/index.js';
|
|
10
9
|
import {
|
|
11
10
|
actionRunner,
|
|
12
11
|
curryOptions,
|
|
13
12
|
ExampleUsage,
|
|
14
13
|
} from '../../shared/index.js';
|
|
14
|
+
import { getProjectInfo } from '../utils/project.js';
|
|
15
|
+
import { runExpoPrebuildIfNeeded } from '../utils/expo.js';
|
|
16
|
+
import { runBrownieCodegenIfApplicable } from '../../brownie/helpers/runBrownieCodegenIfApplicable.js';
|
|
15
17
|
|
|
16
18
|
export const publishAndroidCommand = curryOptions(
|
|
17
19
|
new Command('publish:android').description(
|
|
@@ -21,6 +23,12 @@ export const publishAndroidCommand = curryOptions(
|
|
|
21
23
|
).action(
|
|
22
24
|
actionRunner(async (options: PublishLocalAarFlags) => {
|
|
23
25
|
const { projectRoot, platformConfig } = getProjectInfo('android');
|
|
26
|
+
await runExpoPrebuildIfNeeded({
|
|
27
|
+
projectRoot,
|
|
28
|
+
platform: 'android',
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
await runBrownieCodegenIfApplicable(projectRoot, 'kotlin');
|
|
24
32
|
|
|
25
33
|
await publishLocalAarAction({
|
|
26
34
|
projectRoot,
|
package/src/brownfield/index.ts
CHANGED
|
@@ -9,8 +9,6 @@ import {
|
|
|
9
9
|
} from './commands/publishAndroid.js';
|
|
10
10
|
import { packageIosCommand, packageIosExample } from './commands/packageIos.js';
|
|
11
11
|
|
|
12
|
-
export * from './utils/index.js';
|
|
13
|
-
|
|
14
12
|
export const groupName = `${styleText(['bold', 'blueBright'], '@callstack/react-native-brownfield')}${styleText('whiteBright', ' - utilities for React Native Brownfield projects')}`;
|
|
15
13
|
|
|
16
14
|
export const Commands = {
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import { spawn } from 'node:child_process';
|
|
2
|
+
|
|
3
|
+
import { logger } from '@rock-js/tools';
|
|
4
|
+
|
|
5
|
+
import { isExpoProject } from './project.js';
|
|
6
|
+
|
|
7
|
+
type ExpoPlatform = 'ios' | 'android';
|
|
8
|
+
|
|
9
|
+
async function spawnCommand({
|
|
10
|
+
command,
|
|
11
|
+
args,
|
|
12
|
+
cwd,
|
|
13
|
+
}: {
|
|
14
|
+
command: string;
|
|
15
|
+
args: string[];
|
|
16
|
+
cwd: string;
|
|
17
|
+
}) {
|
|
18
|
+
await new Promise<void>((resolve, reject) => {
|
|
19
|
+
const child = spawn(command, args, {
|
|
20
|
+
cwd,
|
|
21
|
+
env: process.env,
|
|
22
|
+
stdio: 'inherit',
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
child.on('error', reject);
|
|
26
|
+
child.on('close', (code) => {
|
|
27
|
+
if (code === 0) {
|
|
28
|
+
resolve();
|
|
29
|
+
} else {
|
|
30
|
+
reject(
|
|
31
|
+
new Error(
|
|
32
|
+
`Command "${command} ${args.join(' ')}" failed with exit code ${code ?? 'unknown'}.`
|
|
33
|
+
)
|
|
34
|
+
);
|
|
35
|
+
}
|
|
36
|
+
});
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
function getNpxCommand() {
|
|
41
|
+
return process.platform === 'win32' ? 'npx.cmd' : 'npx';
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
export async function runExpoPrebuildIfNeeded({
|
|
45
|
+
projectRoot,
|
|
46
|
+
platform,
|
|
47
|
+
}: {
|
|
48
|
+
projectRoot: string;
|
|
49
|
+
platform: ExpoPlatform;
|
|
50
|
+
}) {
|
|
51
|
+
if (!isExpoProject(projectRoot)) {
|
|
52
|
+
return false;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
logger.info(
|
|
56
|
+
`Expo project detected. Running expo prebuild for ${platform}...`
|
|
57
|
+
);
|
|
58
|
+
|
|
59
|
+
const args = ['expo', 'prebuild', '--platform', platform];
|
|
60
|
+
if (platform === 'ios') {
|
|
61
|
+
args.push('--no-install');
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
await spawnCommand({
|
|
65
|
+
command: getNpxCommand(),
|
|
66
|
+
args,
|
|
67
|
+
cwd: projectRoot,
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
return true;
|
|
71
|
+
}
|
|
@@ -5,21 +5,18 @@ import type {
|
|
|
5
5
|
AndroidProjectConfig,
|
|
6
6
|
IOSProjectConfig,
|
|
7
7
|
} from '@react-native-community/cli-types';
|
|
8
|
-
import cloneDeep from 'lodash.clonedeep';
|
|
9
8
|
|
|
9
|
+
/**
|
|
10
|
+
* Helper function to mutate the user config paths in place to be relative to the project root
|
|
11
|
+
* @param projectRoot The path to the project root directory
|
|
12
|
+
* @param userConfig User configuration from the RNC CLI
|
|
13
|
+
*/
|
|
10
14
|
export function makeRelativeProjectConfigPaths<
|
|
11
15
|
UserConfig extends AndroidProjectConfig | IOSProjectConfig | undefined,
|
|
12
|
-
>(projectRoot: string, userConfig: UserConfig)
|
|
13
|
-
const relativeConfig = cloneDeep(userConfig);
|
|
14
|
-
|
|
16
|
+
>(projectRoot: string, userConfig: UserConfig) {
|
|
15
17
|
if (userConfig?.sourceDir) {
|
|
16
|
-
|
|
17
|
-
projectRoot,
|
|
18
|
-
userConfig.sourceDir
|
|
19
|
-
);
|
|
18
|
+
userConfig.sourceDir = path.relative(projectRoot, userConfig.sourceDir);
|
|
20
19
|
}
|
|
21
|
-
|
|
22
|
-
return relativeConfig;
|
|
23
20
|
}
|
|
24
21
|
|
|
25
22
|
/**
|
|
@@ -0,0 +1,174 @@
|
|
|
1
|
+
import * as fs from 'node:fs';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import type {
|
|
4
|
+
AndroidProjectConfig,
|
|
5
|
+
ProjectConfig,
|
|
6
|
+
UserConfig,
|
|
7
|
+
} from '@react-native-community/cli-types';
|
|
8
|
+
import type { PackageAarFlags } from '@rock-js/platform-android';
|
|
9
|
+
|
|
10
|
+
import cliConfigImport from '@react-native-community/cli-config';
|
|
11
|
+
|
|
12
|
+
import { findProjectRoot, makeRelativeProjectConfigPaths } from './paths.js';
|
|
13
|
+
import {
|
|
14
|
+
getConfig,
|
|
15
|
+
type ProjectConfig as ExpoProjectConfig,
|
|
16
|
+
} from '@expo/config';
|
|
17
|
+
|
|
18
|
+
const cliConfig: typeof cliConfigImport =
|
|
19
|
+
typeof cliConfigImport === 'function'
|
|
20
|
+
? cliConfigImport
|
|
21
|
+
: // @ts-expect-error: interop default
|
|
22
|
+
cliConfigImport.default;
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Gets the Expo config if the project is an Expo project
|
|
26
|
+
* @param projectRoot The project root path
|
|
27
|
+
* @returns The Expo config if the project is an Expo project, null otherwise
|
|
28
|
+
*/
|
|
29
|
+
export function getExpoConfigIfIsExpo(projectRoot: string) {
|
|
30
|
+
try {
|
|
31
|
+
return getConfig(projectRoot, { skipSDKVersionRequirement: true });
|
|
32
|
+
} catch {
|
|
33
|
+
return null;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Checks if the project is an Expo project; checks both if installed and explicitly listed
|
|
39
|
+
* in the project's package.json to prevent false positives in a monorepo setup
|
|
40
|
+
* @param projectRoot The project root path
|
|
41
|
+
* @returns Whether the project is an Expo project
|
|
42
|
+
*/
|
|
43
|
+
export function isExpoProject(projectRoot: string): boolean {
|
|
44
|
+
const hasExpoConfig = getExpoConfigIfIsExpo(projectRoot) !== null;
|
|
45
|
+
|
|
46
|
+
// additionally, it is needed to check if the project depends on Expo packages explicitly
|
|
47
|
+
// to prevent false positives in a monorepo setup
|
|
48
|
+
const rnProjectRoot = findProjectRoot();
|
|
49
|
+
const packageJsonPath = path.join(rnProjectRoot, 'package.json');
|
|
50
|
+
const dependsOnExpo =
|
|
51
|
+
fs.existsSync(packageJsonPath) &&
|
|
52
|
+
['dependencies', 'peerDependencies', 'devDependencies'].some(
|
|
53
|
+
(key) => JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8'))[key]?.expo
|
|
54
|
+
);
|
|
55
|
+
|
|
56
|
+
return hasExpoConfig && dependsOnExpo;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
/**
|
|
60
|
+
* Fills the RNC CLI project config from the Expo config by mutating the passed in `options.projectConfig` object in place
|
|
61
|
+
*/
|
|
62
|
+
export function fillProjectConfigFromExpoConfig({
|
|
63
|
+
projectConfig,
|
|
64
|
+
expoConfig: { exp },
|
|
65
|
+
projectRoot,
|
|
66
|
+
}: {
|
|
67
|
+
/** The RNC CLI project config to be filled */
|
|
68
|
+
projectConfig: ProjectConfig;
|
|
69
|
+
|
|
70
|
+
/** The Expo project config */
|
|
71
|
+
expoConfig: ExpoProjectConfig;
|
|
72
|
+
|
|
73
|
+
/** The project root path */
|
|
74
|
+
projectRoot: string;
|
|
75
|
+
}) {
|
|
76
|
+
if (exp.android) {
|
|
77
|
+
projectConfig['android'] = {
|
|
78
|
+
applicationId: exp.android.package!,
|
|
79
|
+
packageName: exp.android.package!,
|
|
80
|
+
appName: exp.name!,
|
|
81
|
+
assets: [],
|
|
82
|
+
mainActivity: 'MainActivity',
|
|
83
|
+
sourceDir: 'android',
|
|
84
|
+
};
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
if (exp.ios) {
|
|
88
|
+
projectConfig['ios'] = {
|
|
89
|
+
assets: [],
|
|
90
|
+
sourceDir: projectRoot,
|
|
91
|
+
xcodeProject: {
|
|
92
|
+
path: '.',
|
|
93
|
+
name: `${exp.name}.xcworkspace`,
|
|
94
|
+
isWorkspace: true,
|
|
95
|
+
},
|
|
96
|
+
};
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
/**
|
|
101
|
+
* Gets the project info for the given platform from the current working directory
|
|
102
|
+
* @param platform the platform for which to get project info
|
|
103
|
+
* @returns project root and android project config
|
|
104
|
+
*/
|
|
105
|
+
export function getProjectInfo<Platform extends 'ios' | 'android'>(
|
|
106
|
+
platform: Platform
|
|
107
|
+
): {
|
|
108
|
+
projectRoot: string;
|
|
109
|
+
userConfig: UserConfig;
|
|
110
|
+
platformConfig: ProjectConfig[Platform];
|
|
111
|
+
} {
|
|
112
|
+
const projectRoot = findProjectRoot();
|
|
113
|
+
|
|
114
|
+
const userConfig = getUserConfig({ projectRoot, platform });
|
|
115
|
+
const platformConfig = userConfig.project[platform as Platform];
|
|
116
|
+
|
|
117
|
+
if (!platformConfig) {
|
|
118
|
+
throw new Error(`${platform} project not found.`);
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
projectRoot,
|
|
123
|
+
userConfig,
|
|
124
|
+
platformConfig: platformConfig,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function getUserConfig({
|
|
129
|
+
projectRoot,
|
|
130
|
+
platform,
|
|
131
|
+
}: {
|
|
132
|
+
projectRoot: string;
|
|
133
|
+
platform: 'ios' | 'android';
|
|
134
|
+
}): UserConfig {
|
|
135
|
+
// resolve the config using RNC CLI
|
|
136
|
+
const userConfig = cliConfig({
|
|
137
|
+
projectRoot,
|
|
138
|
+
selectedPlatform: platform,
|
|
139
|
+
});
|
|
140
|
+
|
|
141
|
+
let projectConfig = userConfig.project;
|
|
142
|
+
|
|
143
|
+
// below: try augmenting the config with values for Expo projects, if applicable
|
|
144
|
+
const maybeExpoConfig = getExpoConfigIfIsExpo(projectRoot);
|
|
145
|
+
if (maybeExpoConfig) {
|
|
146
|
+
fillProjectConfigFromExpoConfig({
|
|
147
|
+
projectConfig,
|
|
148
|
+
expoConfig: maybeExpoConfig,
|
|
149
|
+
projectRoot,
|
|
150
|
+
});
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
// below: relative sourceDir path is required by RN CLI's API
|
|
154
|
+
makeRelativeProjectConfigPaths(projectRoot, projectConfig[platform]);
|
|
155
|
+
|
|
156
|
+
return userConfig;
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Gets the AAR packaging configuration for the given Android project
|
|
161
|
+
* @param args The AAR packaging flags
|
|
162
|
+
* @param androidConfig The Android project config
|
|
163
|
+
*/
|
|
164
|
+
export function getAarConfig(
|
|
165
|
+
args: PackageAarFlags,
|
|
166
|
+
androidConfig: AndroidProjectConfig
|
|
167
|
+
) {
|
|
168
|
+
const config = {
|
|
169
|
+
sourceDir: androidConfig.sourceDir,
|
|
170
|
+
moduleName: args.moduleName ?? '',
|
|
171
|
+
};
|
|
172
|
+
|
|
173
|
+
return config;
|
|
174
|
+
}
|
|
@@ -15,6 +15,7 @@ import { generateSwift } from '../generators/swift.js';
|
|
|
15
15
|
import { generateKotlin } from '../generators/kotlin.js';
|
|
16
16
|
import { discoverStores, type DiscoveredStore } from '../store-discovery.js';
|
|
17
17
|
import type { Platform } from '../types.js';
|
|
18
|
+
import { NoBrownieStoresError } from '../errors/NoBrownieStoresError.js';
|
|
18
19
|
|
|
19
20
|
function getOutputPath(dir: string, name: string, ext: string): string {
|
|
20
21
|
return path.join(dir, `${name}.${ext}`);
|
|
@@ -100,25 +101,37 @@ export async function runCodegen({ platform }: RunCodegenOptions) {
|
|
|
100
101
|
process.exit(1);
|
|
101
102
|
}
|
|
102
103
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
104
|
+
try {
|
|
105
|
+
const stores = discoverStores();
|
|
106
|
+
const isMultipleStores = stores.length > 1;
|
|
107
|
+
const schemaList = stores
|
|
108
|
+
.map((s) => path.basename(s.schemaPath))
|
|
109
|
+
.join(', ');
|
|
106
110
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
111
|
+
logger.info(
|
|
112
|
+
styleText('cyan', `Generating store types from ${schemaList}...`)
|
|
113
|
+
);
|
|
114
|
+
|
|
115
|
+
for (const store of stores) {
|
|
116
|
+
let platforms: Platform[];
|
|
110
117
|
|
|
111
|
-
|
|
112
|
-
|
|
118
|
+
if (platform) {
|
|
119
|
+
platforms = [platform];
|
|
120
|
+
} else {
|
|
121
|
+
// Only generate Swift by default (Kotlin not yet released)
|
|
122
|
+
platforms = ['swift'];
|
|
123
|
+
}
|
|
113
124
|
|
|
114
|
-
|
|
115
|
-
|
|
125
|
+
await generateForStore(store, config, platforms, isMultipleStores);
|
|
126
|
+
}
|
|
127
|
+
} catch (error) {
|
|
128
|
+
if (error instanceof NoBrownieStoresError) {
|
|
129
|
+
logger.error(error.message);
|
|
130
|
+
outro('No brownie stores found, nothing was generated.');
|
|
131
|
+
return;
|
|
116
132
|
} else {
|
|
117
|
-
|
|
118
|
-
platforms = ['swift'];
|
|
133
|
+
throw error;
|
|
119
134
|
}
|
|
120
|
-
|
|
121
|
-
await generateForStore(store, config, platforms, isMultipleStores);
|
|
122
135
|
}
|
|
123
136
|
|
|
124
137
|
outro('Done!');
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { runCodegen } from '../commands/codegen.js';
|
|
2
|
+
import { isBrownieInstalled } from '../config.js';
|
|
3
|
+
|
|
4
|
+
import type { Platform } from '../types.js';
|
|
5
|
+
|
|
6
|
+
export async function runBrownieCodegenIfApplicable(
|
|
7
|
+
projectRoot: string,
|
|
8
|
+
platform: Platform
|
|
9
|
+
) {
|
|
10
|
+
const hasBrownie = isBrownieInstalled(projectRoot);
|
|
11
|
+
if (hasBrownie) {
|
|
12
|
+
await runCodegen({ platform });
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
return { hasBrownie };
|
|
16
|
+
}
|
|
@@ -2,6 +2,8 @@ import fs from 'node:fs';
|
|
|
2
2
|
import path from 'node:path';
|
|
3
3
|
import { Project } from 'ts-morph';
|
|
4
4
|
|
|
5
|
+
import { NoBrownieStoresError } from './errors/NoBrownieStoresError.js';
|
|
6
|
+
|
|
5
7
|
export interface DiscoveredStore {
|
|
6
8
|
name: string;
|
|
7
9
|
schemaPath: string;
|
|
@@ -75,7 +77,7 @@ export function discoverStores(
|
|
|
75
77
|
const brownieFiles = findBrownieFiles(rootDir);
|
|
76
78
|
|
|
77
79
|
if (brownieFiles.length === 0) {
|
|
78
|
-
throw new
|
|
80
|
+
throw new NoBrownieStoresError(
|
|
79
81
|
'No brownie store files found. Create a file ending with .brownie.ts ' +
|
|
80
82
|
'(e.g., MyStore.brownie.ts)'
|
|
81
83
|
);
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC;AAC5B,cAAc,2BAA2B,CAAC"}
|
|
@@ -1,17 +0,0 @@
|
|
|
1
|
-
import type { PackageAarFlags } from '@rock-js/platform-android';
|
|
2
|
-
import type { AndroidProjectConfig, Config as UserConfig, ProjectConfig } from '@react-native-community/cli-types';
|
|
3
|
-
/**
|
|
4
|
-
* Gets the project info for the given platform from the current working directory
|
|
5
|
-
* @param platform the platform for which to get project info
|
|
6
|
-
* @returns project root and android project config
|
|
7
|
-
*/
|
|
8
|
-
export declare function getProjectInfo<Platform extends 'ios' | 'android'>(platform: Platform): {
|
|
9
|
-
projectRoot: string;
|
|
10
|
-
userConfig: UserConfig;
|
|
11
|
-
platformConfig: ProjectConfig[Platform];
|
|
12
|
-
};
|
|
13
|
-
export declare const getAarConfig: (args: PackageAarFlags, androidConfig: AndroidProjectConfig) => {
|
|
14
|
-
sourceDir: string;
|
|
15
|
-
moduleName: string;
|
|
16
|
-
};
|
|
17
|
-
//# sourceMappingURL=rn-cli.d.ts.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"rn-cli.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/rn-cli.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,2BAA2B,CAAC;AACjE,OAAO,KAAK,EACV,oBAAoB,EACpB,MAAM,IAAI,UAAU,EACpB,aAAa,EACd,MAAM,mCAAmC,CAAC;AAW3C;;;;GAIG;AACH,wBAAgB,cAAc,CAAC,QAAQ,SAAS,KAAK,GAAG,SAAS,EAC/D,QAAQ,EAAE,QAAQ,GACjB;IACD,WAAW,EAAE,MAAM,CAAC;IACpB,UAAU,EAAE,UAAU,CAAC;IACvB,cAAc,EAAE,aAAa,CAAC,QAAQ,CAAC,CAAC;CACzC,CAmBA;AAED,eAAO,MAAM,YAAY,GACvB,MAAM,eAAe,EACrB,eAAe,oBAAoB;;;CAOpC,CAAC"}
|
|
@@ -1,31 +0,0 @@
|
|
|
1
|
-
import cliConfigImport from '@react-native-community/cli-config';
|
|
2
|
-
const cliConfig = typeof cliConfigImport === 'function'
|
|
3
|
-
? cliConfigImport
|
|
4
|
-
: // @ts-expect-error: interop default
|
|
5
|
-
cliConfigImport.default;
|
|
6
|
-
import { findProjectRoot, makeRelativeProjectConfigPaths } from './paths.js';
|
|
7
|
-
/**
|
|
8
|
-
* Gets the project info for the given platform from the current working directory
|
|
9
|
-
* @param platform the platform for which to get project info
|
|
10
|
-
* @returns project root and android project config
|
|
11
|
-
*/
|
|
12
|
-
export function getProjectInfo(platform) {
|
|
13
|
-
const projectRoot = findProjectRoot();
|
|
14
|
-
const userConfig = cliConfig({
|
|
15
|
-
projectRoot,
|
|
16
|
-
selectedPlatform: platform,
|
|
17
|
-
});
|
|
18
|
-
// below: relative sourceDir path is required by RN CLI's API
|
|
19
|
-
const platformConfig = makeRelativeProjectConfigPaths(projectRoot, userConfig.project[platform]);
|
|
20
|
-
if (!platformConfig) {
|
|
21
|
-
throw new Error(`${platform} project not found.`);
|
|
22
|
-
}
|
|
23
|
-
return { projectRoot, userConfig, platformConfig };
|
|
24
|
-
}
|
|
25
|
-
export const getAarConfig = (args, androidConfig) => {
|
|
26
|
-
const config = {
|
|
27
|
-
sourceDir: androidConfig.sourceDir,
|
|
28
|
-
moduleName: args.moduleName ?? '',
|
|
29
|
-
};
|
|
30
|
-
return config;
|
|
31
|
-
};
|
|
@@ -1,58 +0,0 @@
|
|
|
1
|
-
import type { PackageAarFlags } from '@rock-js/platform-android';
|
|
2
|
-
import type {
|
|
3
|
-
AndroidProjectConfig,
|
|
4
|
-
Config as UserConfig,
|
|
5
|
-
ProjectConfig,
|
|
6
|
-
} from '@react-native-community/cli-types';
|
|
7
|
-
import cliConfigImport from '@react-native-community/cli-config';
|
|
8
|
-
|
|
9
|
-
const cliConfig: typeof cliConfigImport =
|
|
10
|
-
typeof cliConfigImport === 'function'
|
|
11
|
-
? cliConfigImport
|
|
12
|
-
: // @ts-expect-error: interop default
|
|
13
|
-
cliConfigImport.default;
|
|
14
|
-
|
|
15
|
-
import { findProjectRoot, makeRelativeProjectConfigPaths } from './paths.js';
|
|
16
|
-
|
|
17
|
-
/**
|
|
18
|
-
* Gets the project info for the given platform from the current working directory
|
|
19
|
-
* @param platform the platform for which to get project info
|
|
20
|
-
* @returns project root and android project config
|
|
21
|
-
*/
|
|
22
|
-
export function getProjectInfo<Platform extends 'ios' | 'android'>(
|
|
23
|
-
platform: Platform
|
|
24
|
-
): {
|
|
25
|
-
projectRoot: string;
|
|
26
|
-
userConfig: UserConfig;
|
|
27
|
-
platformConfig: ProjectConfig[Platform];
|
|
28
|
-
} {
|
|
29
|
-
const projectRoot = findProjectRoot();
|
|
30
|
-
|
|
31
|
-
const userConfig = cliConfig({
|
|
32
|
-
projectRoot,
|
|
33
|
-
selectedPlatform: platform,
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
// below: relative sourceDir path is required by RN CLI's API
|
|
37
|
-
const platformConfig = makeRelativeProjectConfigPaths(
|
|
38
|
-
projectRoot,
|
|
39
|
-
userConfig.project[platform]
|
|
40
|
-
);
|
|
41
|
-
|
|
42
|
-
if (!platformConfig) {
|
|
43
|
-
throw new Error(`${platform} project not found.`);
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return { projectRoot, userConfig, platformConfig };
|
|
47
|
-
}
|
|
48
|
-
|
|
49
|
-
export const getAarConfig = (
|
|
50
|
-
args: PackageAarFlags,
|
|
51
|
-
androidConfig: AndroidProjectConfig
|
|
52
|
-
) => {
|
|
53
|
-
const config = {
|
|
54
|
-
sourceDir: androidConfig.sourceDir,
|
|
55
|
-
moduleName: args.moduleName ?? '',
|
|
56
|
-
};
|
|
57
|
-
return config;
|
|
58
|
-
};
|