@callstack/brownfield-cli 1.0.0 → 1.0.2

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/CHANGELOG.md ADDED
@@ -0,0 +1,13 @@
1
+ # @callstack/brownfield-cli
2
+
3
+ ## 1.0.2
4
+
5
+ ### Patch Changes
6
+
7
+ - [`2a8563f`](https://github.com/callstack/react-native-brownfield/commit/2a8563f65ed152054ad1290caf963791a368ee9a) Thanks [@okwasniewski](https://github.com/okwasniewski)! - feat: strip framework binaries to avoid duplicate symbol errors
8
+
9
+ ## 1.0.1
10
+
11
+ ### Patch Changes
12
+
13
+ - [#198](https://github.com/callstack/react-native-brownfield/pull/198) [`c8c903d`](https://github.com/callstack/react-native-brownfield/commit/c8c903d0d2b78a8c06a41213dfbe781a2daf3d25) Thanks [@artus9033](https://github.com/artus9033)! - docs: added README files to all packages
package/README.md ADDED
@@ -0,0 +1,63 @@
1
+ <a href="https://www.callstack.com/open-source?utm_campaign=generic&utm_source=github&utm_medium=referral&utm_content=react-native-brownfield" align="center">
2
+ <img alt="Brownfield CLI" src="https://github.com/callstack/react-native-brownfield/raw/refs/heads/main/img/brownfield-banner.jpg">
3
+ </a>
4
+
5
+ <p align="center">
6
+ CLI for Brownie and Brownfield, a tool for generating state management code, packaging & publishing Brownfield artifacts.
7
+ </p>
8
+
9
+ ---
10
+
11
+ [![Build Status][build-badge]][build]
12
+ [![Version][version-badge]][package]
13
+ [![MIT License][license-badge]][license]
14
+
15
+ [![PRs Welcome][prs-welcome-badge]][prs-welcome]
16
+ [![Chat][chat-badge]][chat]
17
+ [![Code of Conduct][coc-badge]][coc]
18
+ [![Sponsored by Callstack][callstack-badge]][callstack]
19
+
20
+ [![tweet][tweet-badge]][tweet]
21
+
22
+ ## Features
23
+
24
+ - **Shared State** - Single source of truth accessible from both TypeScript and Swift
25
+ - **Type Safety** - Full type inference from TypeScript schema to generated Swift types
26
+ - **React Integration** - `useStore` hook with selector support for optimal re-renders
27
+ - **SwiftUI Integration** - `@UseStore` property wrapper for reactive UI updates
28
+ - **UIKit Support** - Subscribe-based API for imperative UI updates
29
+
30
+ ## Documentation
31
+
32
+ For full documentation, visit [our documentation](https://oss.callstack.com/react-native-brownfield/brownie/overview).
33
+
34
+ <a href="https://www.callstack.com/ebooks/incremental-react-native-adoption-in-native-apps?utm_campaign=brownfield&utm_source=github&utm_medium=referral&utm_content=react-native-brownfield" align="center">
35
+ <img alt="Download a free copy of Incremental React Native adoption in native apps ebook" src="https://github.com/user-attachments/assets/ba42bb29-1e7a-4683-80c5-2602afb1a7e6">
36
+ </a>
37
+
38
+ ## Made with ❤️ at Callstack
39
+
40
+ React Native Brownfield is an open source project and will always remain free to use. If you think it's cool, please star it 🌟. [Callstack](https://callstack.com) is a group of React and React Native geeks, contact us at [hello@callstack.com](mailto:hello@callstack.com) if you need any help with these or just want to say hi!
41
+
42
+ Like the project? ⚛️ [Join the team](https://callstack.com/careers/?utm_campaign=Senior_RN&utm_source=github&utm_medium=readme) who does amazing stuff for clients and drives React Native Open Source! 🔥
43
+
44
+ <!-- badges -->
45
+
46
+ [build-badge]: https://img.shields.io/circleci/build/github/callstack/react-native-brownfield/master.svg?style=flat-square
47
+ [build]: https://circleci.com/gh/callstack/react-native-brownfield
48
+ [ci]: https://github.com/callstack/react-native-brownfield/actions/workflows/ci.yml/badge.svg
49
+ [version-badge]: https://img.shields.io/npm/v/@callstack/react-native-brownfield.svg?style=flat-square
50
+ [package]: https://www.npmjs.com/package/@callstack/react-native-brownfield
51
+ [license-badge]: https://img.shields.io/npm/l/@callstack/react-native-brownfield.svg?style=flat-square
52
+ [license]: https://opensource.org/licenses/MIT
53
+ [prs-welcome-badge]: https://img.shields.io/badge/PRs-welcome-brightgreen.svg?style=flat-square
54
+ [prs-welcome]: http://makeapullrequest.com
55
+ [coc-badge]: https://img.shields.io/badge/code%20of-conduct-ff69b4.svg?style=flat-square
56
+ [coc]: https://github.com/callstack/react-native-brownfield/blob/master/CODE_OF_CONDUCT.md
57
+ [all-contributors-badge]: https://img.shields.io/badge/all_contributors-2-orange.svg?style=flat-square
58
+ [chat-badge]: https://img.shields.io/discord/613446453762719798.svg?style=flat-square&colorB=758ED3
59
+ [chat]: https://discord.gg/2SR9Mua
60
+ [tweet-badge]: https://img.shields.io/badge/tweet-%23reactnativebrownfield-blue.svg?style=flat-square&colorB=1DA1F2&logo=data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABgAAAAUCAYAAACXtf2DAAAAAXNSR0IArs4c6QAAAaRJREFUOBGtlM8rBGEYx3cWtRHJRaKcuMtBSitxkCQ3LtzkP9iUUu5ODspRHLhRLtq0FxeicEBC2cOivcge%2FMgan3fNM8bbzL4zm6c%2BPT%2Fe7%2FO8887svrFYBWbbtgWzsAt3sAcpqJFxxF1QV8oJFqFPFst5dLWQAT87oTgPB7DtziFRT1EA4yZolsFkhwjGYFRO8Op0KD8HVe7unoB6PRTBZG8IctAmG1xrHcfkQ2B55sfI%2ByGMXSBqV71xZ8CWdxBxN6ThFuECDEAL%2Bc9HIzDYumVZ966GZnX0SzCZvEqTbkaGywkyFE6hKAsBPhFQ18uPUqh2ggJ%2BUor%2F4M%2F%2FzOC8g6YzR1i%2F8g4vvSI%2ByD7FFNjexQrjHd8%2BnjABI3AU4Wl16TuF1qANGll81jsi5qu%2Bw6XIsCn4ijhU5FmCJpkV6BGNw410hfSf6JKBQ%2FUFxHGYBnWnmOwDwYQ%2BwzdHqO75HtiAMJfaC7ph32FSRJCENUhDHsLaJkL%2FX4wMF4%2BwA5bgAcrZE4sr0Cu9Jq9fxyrvBHWbNkMD5CEHWTjjT2m6r5D92jfmbbKJEWuMMAAAAABJRU5ErkJggg%3D%3D
61
+ [tweet]: https://twitter.com/intent/tweet?text=Check%20out%20react-native-brownfield!%20https://github.com/callstack/react-native-brownfield%20%F0%9F%91%8D
62
+ [callstack-badge]: https://callstack.com/images/callstack-badge.svg
63
+ [callstack]: https://callstack.com/open-source/?utm_source=github.com&utm_medium=referral&utm_campaign=rnbrownfield&utm_term=readme
@@ -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;AAKpC,OAAO,EAGL,YAAY,EACb,MAAM,uBAAuB,CAAC;AAE/B,eAAO,MAAM,iBAAiB,SAkF7B,CAAC;AAEF,eAAO,MAAM,iBAAiB,cAG7B,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;AAKpC,OAAO,EAGL,YAAY,EACb,MAAM,uBAAuB,CAAC;AAE/B,eAAO,MAAM,iBAAiB,SAuF7B,CAAC;AAEF,eAAO,MAAM,iBAAiB,cAG7B,CAAC"}
@@ -5,7 +5,7 @@ import { colorLink, getReactNativeVersion, logger, relativeToCwd, } from '@rock-
5
5
  import { Command } from 'commander';
6
6
  import { isBrownieInstalled } from '../../brownie/config.js';
7
7
  import { runCodegen } from '../../brownie/commands/codegen.js';
8
- import { getProjectInfo } from '../utils/index.js';
8
+ import { getProjectInfo, stripFrameworkBinary } from '../utils/index.js';
9
9
  import { actionRunner, curryOptions, ExampleUsage, } from '../../shared/index.js';
10
10
  export const packageIosCommand = curryOptions(new Command('package:ios').description('Build iOS XCFramework'), getBuildOptions({ platformName: 'ios' }).map((option) => option.name.startsWith('--build-folder')
11
11
  ? {
@@ -51,6 +51,10 @@ export const packageIosCommand = curryOptions(new Command('package:ios').descrip
51
51
  ],
52
52
  outputPath: brownieOutputPath,
53
53
  });
54
+ // Strip the binary from Brownie.xcframework to make it interface-only.
55
+ // This avoids duplicate symbols when consumer apps embed both BrownfieldLib
56
+ // (which contains Brownie symbols) and Brownie.xcframework.
57
+ await stripFrameworkBinary(brownieOutputPath);
54
58
  logger.success(`Brownie.xcframework created at ${colorLink(relativeToCwd(brownieOutputPath))}`);
55
59
  }
56
60
  }));
@@ -1,3 +1,4 @@
1
1
  export * from './paths.js';
2
2
  export * from './rn-cli.js';
3
+ export * from './stripFrameworkBinary.js';
3
4
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,YAAY,CAAC;AAC3B,cAAc,aAAa,CAAC"}
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,2 +1,3 @@
1
1
  export * from './paths.js';
2
2
  export * from './rn-cli.js';
3
+ export * from './stripFrameworkBinary.js';
@@ -0,0 +1,9 @@
1
+ /**
2
+ * Strips the binary from an xcframework, keeping only Swift module interfaces.
3
+ * This creates an "interface-only" framework where consumers can import the module
4
+ * but the actual symbols must come from another framework (e.g., BrownfieldLib).
5
+ *
6
+ * @param xcframeworkPath - Path to the .xcframework directory
7
+ */
8
+ export declare function stripFrameworkBinary(xcframeworkPath: string): void;
9
+ //# sourceMappingURL=stripFrameworkBinary.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"stripFrameworkBinary.d.ts","sourceRoot":"","sources":["../../../src/brownfield/utils/stripFrameworkBinary.ts"],"names":[],"mappings":"AAuFA;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,eAAe,EAAE,MAAM,GAAG,IAAI,CAsDlE"}
@@ -0,0 +1,107 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { execSync } from 'node:child_process';
5
+ import { logger } from '@rock-js/tools';
6
+ const SLICE_CONFIGS = {
7
+ 'ios-arm64': {
8
+ target: 'arm64-apple-ios15.0',
9
+ },
10
+ 'ios-arm64_x86_64-simulator': {
11
+ target: 'arm64-apple-ios15.0-simulator',
12
+ additionalTargets: ['x86_64-apple-ios15.0-simulator'],
13
+ },
14
+ };
15
+ /**
16
+ * Creates an empty static library for the given target.
17
+ */
18
+ function createEmptyStaticLib(target) {
19
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'framework-strip-'));
20
+ const tempObj = path.join(tempDir, 'empty.o');
21
+ const tempLib = path.join(tempDir, 'empty.a');
22
+ try {
23
+ execSync(`echo "" | xcrun clang -x c -c - -o "${tempObj}" -target ${target}`, {
24
+ stdio: 'pipe',
25
+ });
26
+ execSync(`xcrun ar rcs "${tempLib}" "${tempObj}"`, {
27
+ stdio: 'pipe',
28
+ });
29
+ }
30
+ catch (error) {
31
+ fs.rmSync(tempDir, { recursive: true });
32
+ throw new Error(`Failed to create empty static library for target ${target}: ${error instanceof Error ? error.message : error}`);
33
+ }
34
+ fs.unlinkSync(tempObj);
35
+ return tempLib;
36
+ }
37
+ /**
38
+ * Creates a fat static library combining multiple architectures.
39
+ */
40
+ function createFatStaticLib(targets) {
41
+ const libs = targets.map((target) => createEmptyStaticLib(target));
42
+ const outputDir = fs.mkdtempSync(path.join(os.tmpdir(), 'framework-strip-fat-'));
43
+ const outputLib = path.join(outputDir, 'fat.a');
44
+ try {
45
+ execSync(`xcrun lipo -create ${libs.map((l) => `"${l}"`).join(' ')} -output "${outputLib}"`, {
46
+ stdio: 'pipe',
47
+ });
48
+ }
49
+ catch (error) {
50
+ libs.forEach((lib) => fs.rmSync(path.dirname(lib), { recursive: true }));
51
+ fs.rmSync(outputDir, { recursive: true });
52
+ throw new Error(`Failed to create fat static library: ${error instanceof Error ? error.message : error}`);
53
+ }
54
+ libs.forEach((lib) => {
55
+ fs.unlinkSync(lib);
56
+ fs.rmSync(path.dirname(lib), { recursive: true });
57
+ });
58
+ return outputLib;
59
+ }
60
+ /**
61
+ * Strips the binary from an xcframework, keeping only Swift module interfaces.
62
+ * This creates an "interface-only" framework where consumers can import the module
63
+ * but the actual symbols must come from another framework (e.g., BrownfieldLib).
64
+ *
65
+ * @param xcframeworkPath - Path to the .xcframework directory
66
+ */
67
+ export function stripFrameworkBinary(xcframeworkPath) {
68
+ if (!fs.existsSync(xcframeworkPath)) {
69
+ throw new Error(`XCFramework not found at: ${xcframeworkPath}`);
70
+ }
71
+ const frameworkName = path.basename(xcframeworkPath, '.xcframework');
72
+ logger.info(`Stripping binary from ${frameworkName}.xcframework (interface-only)...`);
73
+ const slices = fs.readdirSync(xcframeworkPath).filter((entry) => {
74
+ const fullPath = path.join(xcframeworkPath, entry);
75
+ return fs.statSync(fullPath).isDirectory() && entry.startsWith('ios-');
76
+ });
77
+ for (const sliceName of slices) {
78
+ const frameworkDir = path.join(xcframeworkPath, sliceName, `${frameworkName}.framework`);
79
+ const binaryPath = path.join(frameworkDir, frameworkName);
80
+ if (!fs.existsSync(binaryPath)) {
81
+ logger.warn(`No binary found at ${binaryPath}, skipping`);
82
+ continue;
83
+ }
84
+ const config = SLICE_CONFIGS[sliceName];
85
+ if (!config) {
86
+ logger.warn(`Unknown slice type: ${sliceName}, skipping`);
87
+ continue;
88
+ }
89
+ let emptyLib;
90
+ if (config.additionalTargets) {
91
+ // Create fat library for multiple architectures
92
+ emptyLib = createFatStaticLib([
93
+ config.target,
94
+ ...config.additionalTargets,
95
+ ]);
96
+ }
97
+ else {
98
+ // Create single-arch library
99
+ emptyLib = createEmptyStaticLib(config.target);
100
+ }
101
+ // Replace original binary with empty stub
102
+ fs.copyFileSync(emptyLib, binaryPath);
103
+ fs.unlinkSync(emptyLib);
104
+ fs.rmSync(path.dirname(emptyLib), { recursive: true });
105
+ }
106
+ logger.success(`${frameworkName}.xcframework is now interface-only`);
107
+ }
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "@callstack/brownfield-cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "license": "MIT",
5
5
  "author": "Artur Morys-Magiera <artus9033@gmail.com>",
6
6
  "bin": {
7
- "brownfield": "./dist/main.js"
7
+ "brownfield": "dist/main.js"
8
8
  },
9
9
  "type": "module",
10
10
  "contributors": [
@@ -12,6 +12,9 @@
12
12
  "Oskar Kwasniewski <oskarkwasniewski@icloud.com>"
13
13
  ],
14
14
  "homepage": "https://github.com/callstack/react-native-brownfield",
15
+ "repository": {
16
+ "url": "https://github.com/callstack/react-native-brownfield"
17
+ },
15
18
  "description": "Brownfield CLI for React Native, gathering all packages of the RN brownfield ecosystem",
16
19
  "exports": {
17
20
  ".": {
@@ -53,7 +56,8 @@
53
56
  "!**/__tests__",
54
57
  "!**/__fixtures__",
55
58
  "!**/__mocks__",
56
- "!**/.*"
59
+ "!**/.*",
60
+ "README.md"
57
61
  ],
58
62
  "publishConfig": {
59
63
  "access": "public"
@@ -17,7 +17,7 @@ import { Command } from 'commander';
17
17
 
18
18
  import { isBrownieInstalled } from '../../brownie/config.js';
19
19
  import { runCodegen } from '../../brownie/commands/codegen.js';
20
- import { getProjectInfo } from '../utils/index.js';
20
+ import { getProjectInfo, stripFrameworkBinary } from '../utils/index.js';
21
21
  import {
22
22
  actionRunner,
23
23
  curryOptions,
@@ -101,6 +101,11 @@ export const packageIosCommand = curryOptions(
101
101
  outputPath: brownieOutputPath,
102
102
  });
103
103
 
104
+ // Strip the binary from Brownie.xcframework to make it interface-only.
105
+ // This avoids duplicate symbols when consumer apps embed both BrownfieldLib
106
+ // (which contains Brownie symbols) and Brownie.xcframework.
107
+ await stripFrameworkBinary(brownieOutputPath);
108
+
104
109
  logger.success(
105
110
  `Brownie.xcframework created at ${colorLink(relativeToCwd(brownieOutputPath))}`
106
111
  );
@@ -1,2 +1,3 @@
1
1
  export * from './paths.js';
2
2
  export * from './rn-cli.js';
3
+ export * from './stripFrameworkBinary.js';
@@ -0,0 +1,149 @@
1
+ import fs from 'node:fs';
2
+ import os from 'node:os';
3
+ import path from 'node:path';
4
+ import { execSync } from 'node:child_process';
5
+ import { logger } from '@rock-js/tools';
6
+
7
+ interface SliceConfig {
8
+ target: string;
9
+ /** Additional targets for fat binaries */
10
+ additionalTargets?: string[];
11
+ }
12
+
13
+ const SLICE_CONFIGS: Record<string, SliceConfig> = {
14
+ 'ios-arm64': {
15
+ target: 'arm64-apple-ios15.0',
16
+ },
17
+ 'ios-arm64_x86_64-simulator': {
18
+ target: 'arm64-apple-ios15.0-simulator',
19
+ additionalTargets: ['x86_64-apple-ios15.0-simulator'],
20
+ },
21
+ };
22
+
23
+ /**
24
+ * Creates an empty static library for the given target.
25
+ */
26
+ function createEmptyStaticLib(target: string): string {
27
+ const tempDir = fs.mkdtempSync(path.join(os.tmpdir(), 'framework-strip-'));
28
+ const tempObj = path.join(tempDir, 'empty.o');
29
+ const tempLib = path.join(tempDir, 'empty.a');
30
+
31
+ try {
32
+ execSync(
33
+ `echo "" | xcrun clang -x c -c - -o "${tempObj}" -target ${target}`,
34
+ {
35
+ stdio: 'pipe',
36
+ }
37
+ );
38
+
39
+ execSync(`xcrun ar rcs "${tempLib}" "${tempObj}"`, {
40
+ stdio: 'pipe',
41
+ });
42
+ } catch (error) {
43
+ fs.rmSync(tempDir, { recursive: true });
44
+ throw new Error(
45
+ `Failed to create empty static library for target ${target}: ${error instanceof Error ? error.message : error}`
46
+ );
47
+ }
48
+
49
+ fs.unlinkSync(tempObj);
50
+
51
+ return tempLib;
52
+ }
53
+
54
+ /**
55
+ * Creates a fat static library combining multiple architectures.
56
+ */
57
+ function createFatStaticLib(targets: string[]): string {
58
+ const libs = targets.map((target) => createEmptyStaticLib(target));
59
+
60
+ const outputDir = fs.mkdtempSync(
61
+ path.join(os.tmpdir(), 'framework-strip-fat-')
62
+ );
63
+ const outputLib = path.join(outputDir, 'fat.a');
64
+
65
+ try {
66
+ execSync(
67
+ `xcrun lipo -create ${libs.map((l) => `"${l}"`).join(' ')} -output "${outputLib}"`,
68
+ {
69
+ stdio: 'pipe',
70
+ }
71
+ );
72
+ } catch (error) {
73
+ libs.forEach((lib) => fs.rmSync(path.dirname(lib), { recursive: true }));
74
+ fs.rmSync(outputDir, { recursive: true });
75
+ throw new Error(
76
+ `Failed to create fat static library: ${error instanceof Error ? error.message : error}`
77
+ );
78
+ }
79
+
80
+ libs.forEach((lib) => {
81
+ fs.unlinkSync(lib);
82
+ fs.rmSync(path.dirname(lib), { recursive: true });
83
+ });
84
+
85
+ return outputLib;
86
+ }
87
+
88
+ /**
89
+ * Strips the binary from an xcframework, keeping only Swift module interfaces.
90
+ * This creates an "interface-only" framework where consumers can import the module
91
+ * but the actual symbols must come from another framework (e.g., BrownfieldLib).
92
+ *
93
+ * @param xcframeworkPath - Path to the .xcframework directory
94
+ */
95
+ export function stripFrameworkBinary(xcframeworkPath: string): void {
96
+ if (!fs.existsSync(xcframeworkPath)) {
97
+ throw new Error(`XCFramework not found at: ${xcframeworkPath}`);
98
+ }
99
+
100
+ const frameworkName = path.basename(xcframeworkPath, '.xcframework');
101
+
102
+ logger.info(
103
+ `Stripping binary from ${frameworkName}.xcframework (interface-only)...`
104
+ );
105
+
106
+ const slices = fs.readdirSync(xcframeworkPath).filter((entry) => {
107
+ const fullPath = path.join(xcframeworkPath, entry);
108
+ return fs.statSync(fullPath).isDirectory() && entry.startsWith('ios-');
109
+ });
110
+
111
+ for (const sliceName of slices) {
112
+ const frameworkDir = path.join(
113
+ xcframeworkPath,
114
+ sliceName,
115
+ `${frameworkName}.framework`
116
+ );
117
+ const binaryPath = path.join(frameworkDir, frameworkName);
118
+
119
+ if (!fs.existsSync(binaryPath)) {
120
+ logger.warn(`No binary found at ${binaryPath}, skipping`);
121
+ continue;
122
+ }
123
+
124
+ const config = SLICE_CONFIGS[sliceName];
125
+ if (!config) {
126
+ logger.warn(`Unknown slice type: ${sliceName}, skipping`);
127
+ continue;
128
+ }
129
+
130
+ let emptyLib: string;
131
+ if (config.additionalTargets) {
132
+ // Create fat library for multiple architectures
133
+ emptyLib = createFatStaticLib([
134
+ config.target,
135
+ ...config.additionalTargets,
136
+ ]);
137
+ } else {
138
+ // Create single-arch library
139
+ emptyLib = createEmptyStaticLib(config.target);
140
+ }
141
+
142
+ // Replace original binary with empty stub
143
+ fs.copyFileSync(emptyLib, binaryPath);
144
+ fs.unlinkSync(emptyLib);
145
+ fs.rmSync(path.dirname(emptyLib), { recursive: true });
146
+ }
147
+
148
+ logger.success(`${frameworkName}.xcframework is now interface-only`);
149
+ }
@@ -1,4 +0,0 @@
1
- export * from './packageAndroid.js';
2
- export * from './packageIos.js';
3
- export * from './publishAndroid.js';
4
- //# sourceMappingURL=index.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/brownfield/commands/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,iBAAiB,CAAC;AAChC,cAAc,qBAAqB,CAAC"}
@@ -1,3 +0,0 @@
1
- export * from './packageAndroid.js';
2
- export * from './packageIos.js';
3
- export * from './publishAndroid.js';
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=actionRunner.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"actionRunner.test.d.ts","sourceRoot":"","sources":["../../../src/brownfield/types/actionRunner.test.ts"],"names":[],"mappings":""}
@@ -1 +0,0 @@
1
- export {};
package/dist/cli.d.ts DELETED
@@ -1,3 +0,0 @@
1
- #!/usr/bin/env node
2
- export {};
3
- //# sourceMappingURL=cli.d.ts.map
package/dist/cli.d.ts.map DELETED
@@ -1 +0,0 @@
1
- {"version":3,"file":"cli.d.ts","sourceRoot":"","sources":["../src/cli.ts"],"names":[],"mappings":""}
package/dist/cli.js DELETED
@@ -1,54 +0,0 @@
1
- #!/usr/bin/env node
2
- import { styleText } from 'node:util';
3
- import { logger } from '@rock-js/tools';
4
- import { Command } from 'commander';
5
- import { ExampleUsage } from './shared/index.js';
6
- import brownfieldCommands, { groupName as brownfieldCommandsGroupName, } from './brownfield/index.js';
7
- import brownieCommands, { groupName as brownieCommandsGroupName, } from './brownie/index.js';
8
- const program = new Command();
9
- program
10
- .name(styleText('magenta', 'brownie'))
11
- .usage(styleText('yellow', '[options] [command]'))
12
- .description(styleText('magentaBright', 'React Native Brownfield CLI - ') +
13
- styleText(['magenta', 'bold', 'underline'], 'Brownie'))
14
- .version(process.env.npm_package_version ?? '0.0.0');
15
- program
16
- .optionsGroup('Global options:')
17
- .option('--verbose', 'enable verbose logging')
18
- .hook('preAction', () => {
19
- const opts = program.opts();
20
- if (opts.verbose) {
21
- logger.setVerbose(opts.verbose ?? false);
22
- }
23
- });
24
- program.configureHelp({
25
- styleTitle: (str) => styleText('bold', str),
26
- styleCommandText: (str) => styleText('cyan', str),
27
- styleArgumentText: (str) => styleText('yellow', str),
28
- styleSubcommandText: (str) => styleText('blue', str),
29
- });
30
- function registrationHelper(commandsRegistration, groupName) {
31
- program.commandsGroup(groupName);
32
- const exampleUsageItems = [];
33
- Object.values(commandsRegistration).forEach((commandOrExampleUsage) => {
34
- if (commandOrExampleUsage instanceof Command) {
35
- // command
36
- program.addCommand(commandOrExampleUsage);
37
- }
38
- else if (commandOrExampleUsage instanceof ExampleUsage) {
39
- // piece of example usage for the command group
40
- exampleUsageItems.push(commandOrExampleUsage);
41
- }
42
- });
43
- if (exampleUsageItems.length) {
44
- const longestUsageItemCommandLength = exampleUsageItems.reduce((max, item) => Math.max(max, item.command.length), 0);
45
- program.addHelpText('after', `\nExamples:\n${exampleUsageItems.map((item) => `\t ${styleText('dim', item.command.padEnd(longestUsageItemCommandLength))}\t${item.description}`).join('\n')}\n`);
46
- }
47
- }
48
- registrationHelper(brownfieldCommands, brownfieldCommandsGroupName);
49
- registrationHelper(brownieCommands, brownieCommandsGroupName);
50
- program.commandsGroup('Utility commands').helpCommand('help [command]');
51
- program.parse(process.argv);
52
- if (!process.argv.slice(2).length) {
53
- program.outputHelp();
54
- }