@callstack/brownfield-cli 3.0.0 → 3.1.0

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.
Files changed (66) hide show
  1. package/CHANGELOG.md +6 -0
  2. package/dist/brownfield/commands/packageAndroid.d.ts.map +1 -1
  3. package/dist/brownfield/commands/packageAndroid.js +2 -0
  4. package/dist/brownfield/commands/packageIos.d.ts.map +1 -1
  5. package/dist/brownfield/commands/packageIos.js +17 -1
  6. package/dist/brownfield/commands/publishAndroid.d.ts.map +1 -1
  7. package/dist/brownfield/commands/publishAndroid.js +2 -0
  8. package/dist/index.d.ts.map +1 -1
  9. package/dist/index.js +2 -0
  10. package/dist/navigation/commands/codegen.d.ts +9 -0
  11. package/dist/navigation/commands/codegen.d.ts.map +1 -0
  12. package/dist/navigation/commands/codegen.js +24 -0
  13. package/dist/navigation/commands/index.d.ts +2 -0
  14. package/dist/navigation/commands/index.d.ts.map +1 -0
  15. package/dist/navigation/commands/index.js +1 -0
  16. package/dist/navigation/config.d.ts +6 -0
  17. package/dist/navigation/config.d.ts.map +1 -0
  18. package/dist/navigation/config.js +25 -0
  19. package/dist/navigation/generators/android.d.ts +4 -0
  20. package/dist/navigation/generators/android.d.ts.map +1 -0
  21. package/dist/navigation/generators/android.js +91 -0
  22. package/dist/navigation/generators/ios.d.ts +4 -0
  23. package/dist/navigation/generators/ios.d.ts.map +1 -0
  24. package/dist/navigation/generators/ios.js +141 -0
  25. package/dist/navigation/generators/models.d.ts +13 -0
  26. package/dist/navigation/generators/models.d.ts.map +1 -0
  27. package/dist/navigation/generators/models.js +112 -0
  28. package/dist/navigation/generators/ts.d.ts +6 -0
  29. package/dist/navigation/generators/ts.d.ts.map +1 -0
  30. package/dist/navigation/generators/ts.js +96 -0
  31. package/dist/navigation/helpers/runNavigationCodegenIfApplicable.d.ts +5 -0
  32. package/dist/navigation/helpers/runNavigationCodegenIfApplicable.d.ts.map +1 -0
  33. package/dist/navigation/helpers/runNavigationCodegenIfApplicable.js +11 -0
  34. package/dist/navigation/index.d.ts +7 -0
  35. package/dist/navigation/index.d.ts.map +1 -0
  36. package/dist/navigation/index.js +6 -0
  37. package/dist/navigation/parser.d.ts +3 -0
  38. package/dist/navigation/parser.d.ts.map +1 -0
  39. package/dist/navigation/parser.js +33 -0
  40. package/dist/navigation/runner.d.ts +8 -0
  41. package/dist/navigation/runner.d.ts.map +1 -0
  42. package/dist/navigation/runner.js +126 -0
  43. package/dist/navigation/spec-discovery.d.ts +3 -0
  44. package/dist/navigation/spec-discovery.d.ts.map +1 -0
  45. package/dist/navigation/spec-discovery.js +15 -0
  46. package/dist/navigation/types.d.ts +24 -0
  47. package/dist/navigation/types.d.ts.map +1 -0
  48. package/dist/navigation/types.js +1 -0
  49. package/package.json +6 -1
  50. package/src/brownfield/commands/packageAndroid.ts +2 -0
  51. package/src/brownfield/commands/packageIos.ts +34 -1
  52. package/src/brownfield/commands/publishAndroid.ts +2 -0
  53. package/src/index.ts +4 -0
  54. package/src/navigation/commands/codegen.ts +57 -0
  55. package/src/navigation/commands/index.ts +1 -0
  56. package/src/navigation/config.ts +35 -0
  57. package/src/navigation/generators/android.ts +127 -0
  58. package/src/navigation/generators/ios.ts +169 -0
  59. package/src/navigation/generators/models.ts +170 -0
  60. package/src/navigation/generators/ts.ts +123 -0
  61. package/src/navigation/helpers/runNavigationCodegenIfApplicable.ts +17 -0
  62. package/src/navigation/index.ts +10 -0
  63. package/src/navigation/parser.ts +43 -0
  64. package/src/navigation/runner.ts +256 -0
  65. package/src/navigation/spec-discovery.ts +25 -0
  66. package/src/navigation/types.ts +25 -0
@@ -0,0 +1,256 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ import { logger } from '@rock-js/tools';
5
+ import {
6
+ DEFAULT_ANDROID_JAVA_PACKAGE,
7
+ getNavigationPackagePath,
8
+ } from './config.js';
9
+ import { parseNavigationSpec } from './parser.js';
10
+ import { resolveNavigationSpecPath } from './spec-discovery.js';
11
+ import {
12
+ generateIndexDts,
13
+ generateIndexTs,
14
+ generateTurboModuleSpec,
15
+ transpileWithConsumerBabel,
16
+ } from './generators/ts.js';
17
+ import {
18
+ generateObjCImplementation,
19
+ generateSwiftDelegate,
20
+ } from './generators/ios.js';
21
+ import {
22
+ generateKotlinDelegate,
23
+ generateKotlinModule,
24
+ } from './generators/android.js';
25
+ import { generateNavigationModels } from './generators/models.js';
26
+ import type { GeneratedNavigationArtifacts } from './types.js';
27
+
28
+ interface RunNavigationCodegenOptions {
29
+ specPath?: string;
30
+ dryRun?: boolean;
31
+ projectRoot?: string;
32
+ }
33
+
34
+ interface NavigationOutputPaths {
35
+ turboModuleSpec: string;
36
+ navigationTs: string;
37
+ commonjsIndexJs: string;
38
+ moduleIndexJs: string;
39
+ commonjsIndexDts: string;
40
+ moduleIndexDts: string;
41
+ swiftDelegate: string;
42
+ swiftModels: string;
43
+ objcImplementation: string;
44
+ kotlinDelegate: string;
45
+ kotlinModule: string;
46
+ kotlinModels: string;
47
+ }
48
+
49
+ function getOutputPaths(
50
+ packageRoot: string,
51
+ androidJavaPackageName: string
52
+ ): NavigationOutputPaths {
53
+ const androidPackagePathSegments = androidJavaPackageName.split('.');
54
+
55
+ return {
56
+ turboModuleSpec: path.join(packageRoot, 'src', 'NativeBrownfieldNavigation.ts'),
57
+ navigationTs: path.join(packageRoot, 'src', 'index.ts'),
58
+ commonjsIndexJs: path.join(packageRoot, 'lib', 'commonjs', 'index.js'),
59
+ moduleIndexJs: path.join(packageRoot, 'lib', 'module', 'index.js'),
60
+ commonjsIndexDts: path.join(
61
+ packageRoot,
62
+ 'lib',
63
+ 'typescript',
64
+ 'commonjs',
65
+ 'src',
66
+ 'index.d.ts'
67
+ ),
68
+ moduleIndexDts: path.join(
69
+ packageRoot,
70
+ 'lib',
71
+ 'typescript',
72
+ 'module',
73
+ 'src',
74
+ 'index.d.ts'
75
+ ),
76
+ swiftDelegate: path.join(
77
+ packageRoot,
78
+ 'ios',
79
+ 'BrownfieldNavigationDelegate.swift'
80
+ ),
81
+ swiftModels: path.join(packageRoot, 'ios', 'BrownfieldNavigationModels.swift'),
82
+ objcImplementation: path.join(
83
+ packageRoot,
84
+ 'ios',
85
+ 'NativeBrownfieldNavigation.mm'
86
+ ),
87
+ kotlinDelegate: path.join(
88
+ packageRoot,
89
+ 'android',
90
+ 'src',
91
+ 'main',
92
+ 'java',
93
+ ...androidPackagePathSegments,
94
+ 'BrownfieldNavigationDelegate.kt'
95
+ ),
96
+ kotlinModule: path.join(
97
+ packageRoot,
98
+ 'android',
99
+ 'src',
100
+ 'main',
101
+ 'java',
102
+ ...androidPackagePathSegments,
103
+ 'NativeBrownfieldNavigationModule.kt'
104
+ ),
105
+ kotlinModels: path.join(
106
+ packageRoot,
107
+ 'android',
108
+ 'src',
109
+ 'main',
110
+ 'java',
111
+ ...androidPackagePathSegments,
112
+ 'BrownfieldNavigationModels.kt'
113
+ ),
114
+ };
115
+ }
116
+
117
+ function writeArtifacts(
118
+ paths: NavigationOutputPaths,
119
+ artifacts: GeneratedNavigationArtifacts
120
+ ): void {
121
+ fs.writeFileSync(paths.turboModuleSpec, artifacts.turboModuleSpec);
122
+ logger.success(`Generated ${paths.turboModuleSpec}`);
123
+
124
+ fs.writeFileSync(paths.navigationTs, artifacts.indexTs);
125
+ logger.success(`Generated ${paths.navigationTs}`);
126
+
127
+ fs.writeFileSync(paths.commonjsIndexJs, artifacts.indexJs);
128
+ logger.success(`Generated ${paths.commonjsIndexJs}`);
129
+
130
+ fs.writeFileSync(paths.moduleIndexJs, artifacts.indexJs);
131
+ logger.success(`Generated ${paths.moduleIndexJs}`);
132
+
133
+ fs.writeFileSync(paths.commonjsIndexDts, artifacts.indexDts);
134
+ logger.success(`Generated ${paths.commonjsIndexDts}`);
135
+
136
+ fs.writeFileSync(paths.moduleIndexDts, artifacts.indexDts);
137
+ logger.success(`Generated ${paths.moduleIndexDts}`);
138
+
139
+ fs.writeFileSync(paths.swiftDelegate, artifacts.swiftDelegate);
140
+ logger.success(`Generated ${paths.swiftDelegate}`);
141
+
142
+ if (artifacts.swiftModels) {
143
+ fs.writeFileSync(paths.swiftModels, artifacts.swiftModels);
144
+ logger.success(`Generated ${paths.swiftModels}`);
145
+ }
146
+
147
+ fs.writeFileSync(paths.objcImplementation, artifacts.objcImplementation);
148
+ logger.success(`Generated ${paths.objcImplementation}`);
149
+
150
+ fs.writeFileSync(paths.kotlinDelegate, artifacts.kotlinDelegate);
151
+ logger.success(`Generated ${paths.kotlinDelegate}`);
152
+
153
+ fs.writeFileSync(paths.kotlinModule, artifacts.kotlinModule);
154
+ logger.success(`Generated ${paths.kotlinModule}`);
155
+
156
+ if (artifacts.kotlinModels) {
157
+ fs.writeFileSync(paths.kotlinModels, artifacts.kotlinModels);
158
+ logger.success(`Generated ${paths.kotlinModels}`);
159
+ }
160
+ }
161
+
162
+ function printDryRun(
163
+ androidJavaPackageName: string,
164
+ artifacts: GeneratedNavigationArtifacts
165
+ ): void {
166
+ logger.info('\n--- Generated: src/NativeBrownfieldNavigation.ts ---\n');
167
+ logger.log(artifacts.turboModuleSpec);
168
+ logger.info('\n--- Generated: src/index.ts ---\n');
169
+ logger.log(artifacts.indexTs);
170
+ logger.info('\n--- Generated (Babel): lib/{commonjs,module}/index.js ---\n');
171
+ logger.log(artifacts.indexJs);
172
+ logger.info(
173
+ '\n--- Generated: lib/typescript/{commonjs,module}/src/index.d.ts ---\n'
174
+ );
175
+ logger.log(artifacts.indexDts);
176
+ logger.info('\n--- Generated: ios/BrownfieldNavigationDelegate.swift ---\n');
177
+ logger.log(artifacts.swiftDelegate);
178
+ if (artifacts.swiftModels) {
179
+ logger.info('\n--- Generated: ios/BrownfieldNavigationModels.swift ---\n');
180
+ logger.log(artifacts.swiftModels);
181
+ }
182
+ logger.info('\n--- Generated: ios/NativeBrownfieldNavigation.mm ---\n');
183
+ logger.log(artifacts.objcImplementation);
184
+ logger.info(
185
+ `\n--- Generated: android/src/main/java/${androidJavaPackageName.replaceAll('.', '/')}/BrownfieldNavigationDelegate.kt ---\n`
186
+ );
187
+ logger.log(artifacts.kotlinDelegate);
188
+ logger.info(
189
+ `\n--- Generated: android/src/main/java/${androidJavaPackageName.replaceAll('.', '/')}/NativeBrownfieldNavigationModule.kt ---\n`
190
+ );
191
+ logger.log(artifacts.kotlinModule);
192
+ if (artifacts.kotlinModels) {
193
+ logger.info(
194
+ `\n--- Generated: android/src/main/java/${androidJavaPackageName.replaceAll('.', '/')}/BrownfieldNavigationModels.kt ---\n`
195
+ );
196
+ logger.log(artifacts.kotlinModels);
197
+ }
198
+ }
199
+
200
+ export async function runNavigationCodegen({
201
+ specPath,
202
+ dryRun = false,
203
+ projectRoot = process.cwd(),
204
+ }: RunNavigationCodegenOptions): Promise<void> {
205
+ const resolvedSpecPath = resolveNavigationSpecPath(specPath, projectRoot);
206
+ if (!fs.existsSync(resolvedSpecPath)) {
207
+ throw new Error(`Spec file not found: ${resolvedSpecPath}`);
208
+ }
209
+
210
+ logger.info(`Parsing spec file: ${resolvedSpecPath}`);
211
+ const methods = parseNavigationSpec(resolvedSpecPath);
212
+ if (methods.length === 0) {
213
+ throw new Error('No methods found in spec file');
214
+ }
215
+
216
+ logger.info(
217
+ `Found ${methods.length} method(s): ${methods.map((method) => method.name).join(', ')}`
218
+ );
219
+
220
+ const packageRoot = getNavigationPackagePath(projectRoot);
221
+ const androidJavaPackageName = DEFAULT_ANDROID_JAVA_PACKAGE;
222
+ const indexTs = generateIndexTs(methods);
223
+ const models = await generateNavigationModels({
224
+ specPath: resolvedSpecPath,
225
+ methods,
226
+ kotlinPackageName: androidJavaPackageName,
227
+ });
228
+
229
+ const artifacts: GeneratedNavigationArtifacts = {
230
+ turboModuleSpec: generateTurboModuleSpec(methods),
231
+ indexTs,
232
+ indexJs: transpileWithConsumerBabel(indexTs, projectRoot, packageRoot),
233
+ indexDts: generateIndexDts(methods),
234
+ swiftDelegate: generateSwiftDelegate(methods),
235
+ objcImplementation: generateObjCImplementation(methods),
236
+ kotlinDelegate: generateKotlinDelegate(methods, androidJavaPackageName),
237
+ kotlinModule: generateKotlinModule(methods, androidJavaPackageName),
238
+ };
239
+
240
+ if (models.modelTypeNames.length > 0) {
241
+ logger.info(
242
+ `Generating quicktype models for types: ${models.modelTypeNames.join(', ')}`
243
+ );
244
+ artifacts.swiftModels = models.swiftModels;
245
+ artifacts.kotlinModels = models.kotlinModels;
246
+ } else {
247
+ logger.info('No complex model types found; skipping quicktype model generation');
248
+ }
249
+
250
+ if (dryRun) {
251
+ printDryRun(androidJavaPackageName, artifacts);
252
+ return;
253
+ }
254
+
255
+ writeArtifacts(getOutputPaths(packageRoot, androidJavaPackageName), artifacts);
256
+ }
@@ -0,0 +1,25 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+
4
+ import { DEFAULT_SPEC_FILENAME } from './config.js';
5
+
6
+ export function resolveNavigationSpecPath(
7
+ specPath: string | undefined,
8
+ projectRoot: string
9
+ ): string {
10
+ if (specPath) {
11
+ return path.isAbsolute(specPath)
12
+ ? specPath
13
+ : path.resolve(projectRoot, specPath);
14
+ }
15
+
16
+ return path.resolve(projectRoot, DEFAULT_SPEC_FILENAME);
17
+ }
18
+
19
+ export function isNavigationSpecPresent(
20
+ specPath: string | undefined,
21
+ projectRoot: string = process.cwd()
22
+ ): boolean {
23
+ const resolvedSpecPath = resolveNavigationSpecPath(specPath, projectRoot);
24
+ return fs.existsSync(resolvedSpecPath);
25
+ }
@@ -0,0 +1,25 @@
1
+ export interface MethodParam {
2
+ name: string;
3
+ type: string;
4
+ optional: boolean;
5
+ }
6
+
7
+ export interface MethodSignature {
8
+ name: string;
9
+ params: MethodParam[];
10
+ returnType: string;
11
+ isAsync: boolean;
12
+ }
13
+
14
+ export interface GeneratedNavigationArtifacts {
15
+ turboModuleSpec: string;
16
+ indexTs: string;
17
+ indexJs: string;
18
+ indexDts: string;
19
+ swiftDelegate: string;
20
+ objcImplementation: string;
21
+ kotlinDelegate: string;
22
+ kotlinModule: string;
23
+ swiftModels?: string;
24
+ kotlinModels?: string;
25
+ }