-
Notifications
You must be signed in to change notification settings - Fork 34
Expand file tree
/
Copy pathcodegen.ts
More file actions
130 lines (109 loc) · 3.61 KB
/
codegen.ts
File metadata and controls
130 lines (109 loc) · 3.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
import path from 'node:path';
import { styleText } from 'node:util';
import { Command, Option } from 'commander';
import { intro, logger, outro } from '@rock-js/tools';
import { QuickTypeError } from 'quicktype-core';
import { actionRunner } from '../../shared/index.js';
import { loadConfig, type BrownieConfig } from '../config.js';
import { generateSwift } from '../generators/swift.js';
import { generateKotlin } from '../generators/kotlin.js';
import { discoverStores, type DiscoveredStore } from '../store-discovery.js';
import { Platform } from '../types.js';
function getOutputPath(dir: string, name: string, ext: string): string {
return path.join(dir, `${name}.${ext}`);
}
function formatQuickTypeError(error: QuickTypeError): string {
let message = error.errorMessage;
for (const [key, value] of Object.entries(error.properties)) {
message = message.replaceAll('${' + key + '}', value);
}
return message;
}
async function generateForStore(
store: DiscoveredStore,
config: BrownieConfig,
platforms: Platform[],
showLabel: boolean
): Promise<void> {
const { name, schemaPath } = store;
const storeLabel = showLabel ? ` [${name}]` : '';
logger.info(`Generating types for store ${name}`);
for (const p of platforms) {
const outputDir = config[p];
if (!outputDir) {
continue;
}
const ext = p === 'swift' ? 'swift' : 'kt';
const outputPath = getOutputPath(outputDir, name, ext);
try {
if (p === 'swift') {
await generateSwift({
name,
schemaPath,
typeName: name,
outputPath,
});
} else {
await generateKotlin({
name,
schemaPath,
typeName: name,
outputPath,
packageName: config.kotlinPackageName,
});
}
logger.success(
`Generated ${outputPath}${styleText('italic', storeLabel)}`
);
} catch (error) {
logger.error(
`Error generating ${p}${storeLabel}: ${error instanceof QuickTypeError ? formatQuickTypeError(error) : error instanceof Error ? error.message : error}`
);
process.exit(1);
}
}
}
export type RunCodegenOptions = { platform?: Platform };
/**
* Runs the codegen command with the given arguments.
*/
export async function runCodegen({ platform }: RunCodegenOptions) {
intro(
`Running Brownie codegen for ${platform ? `platform ${platform}` : 'all platforms'}`
);
const config = loadConfig();
if (platform && !['swift', 'kotlin'].includes(platform)) {
logger.error(`Invalid platform: ${platform}. Must be 'swift' or 'kotlin'`);
process.exit(1);
}
const stores = discoverStores();
const isMultipleStores = stores.length > 1;
const schemaList = stores.map((s) => path.basename(s.schemaPath)).join(', ');
logger.info(
styleText('cyan', `Generating store types from ${schemaList}...`)
);
for (const store of stores) {
const platforms: Platform[] = platform
? [platform]
: (['swift', 'kotlin'] as Platform[]).filter((p) => config[p]);
if (platforms.length === 0) {
logger.warn(`No output paths configured for store ${store.name}`);
continue;
}
await generateForStore(store, config, platforms, isMultipleStores);
}
outro('Done!');
}
export const codegenCommand = new Command('codegen')
.description('Generate native store types from TypeScript schema')
.addOption(
new Option(
'-p, --platform <platform>',
'Generate for specific platform (swift, kotlin)'
).choices(['swift', 'kotlin'])
)
.action(
actionRunner(async (options: RunCodegenOptions) => {
await runCodegen(options);
})
);