Skip to content

Commit 9d712f1

Browse files
committed
Make the CLI runnable
1 parent 41d6a47 commit 9d712f1

File tree

7 files changed

+105
-27
lines changed

7 files changed

+105
-27
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# Output folder
22
dist
3+
out
34

45
# Yarn 2
56
.yarn/*

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
"@types/lodash": "^4.17.15",
3535
"@types/node": "^22.13.4",
3636
"@types/react": "^19.0.10",
37+
"@types/yargs": "^17.0.33",
3738
"fast-glob": "^3.3.3",
3839
"prettier": "^3.5.1",
3940
"rimraf": "^6.0.1",

pnpm-lock.yaml

Lines changed: 15 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

scripts/cli.ts

Lines changed: 75 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,40 +1,88 @@
1+
import * as fs from 'node:fs';
12
import yargs from 'yargs';
23
import { hideBin } from 'yargs/helpers';
34
import * as rae from '../src';
45

5-
const INCLUDE_EXTERNAL = false;
6-
76
interface RunOptions {
8-
files: string[];
7+
files?: string[];
98
configPath: string;
109
includeExternal: boolean;
10+
out?: string;
1111
}
1212

1313
function run(options: RunOptions) {
14-
const program = rae.createProgram(options.files, rae.loadConfig(options.configPath));
14+
const config = rae.loadConfig(options.configPath);
15+
const files = options.files ?? config.fileNames;
16+
17+
const program = rae.createProgram(files, config.options);
18+
19+
const components: any[] = [];
20+
const hooks: any[] = [];
1521

16-
for (const file of options.files) {
17-
const ast = rae.parseFromProgram(file, program);
22+
let errorCounter = 0;
1823

19-
const translated = ast.body.map((component) => {
20-
return {
21-
name: component.name,
22-
props: component.types
23-
.map((prop) => {
24+
for (const file of files) {
25+
console.log(`Processing ${file}`);
26+
console.group();
27+
try {
28+
const ast = rae.parseFromProgram(file, program);
29+
30+
const componentsApi = ast.body.filter(rae.isComponentNode).map((component) => {
31+
return {
32+
name: component.name,
33+
props: component.props
34+
.map((prop) => {
35+
return {
36+
...prop,
37+
filenames: Array.from(prop.filenames),
38+
};
39+
})
40+
.filter(
41+
(prop) =>
42+
options.includeExternal ||
43+
!Array.from(prop.filenames).some((filename) => filename.includes('/node_modules/')),
44+
),
45+
};
46+
});
47+
48+
const hooksApi = ast.body.filter(rae.isHookNode).map((hook) => {
49+
return {
50+
name: hook.name,
51+
parameters: hook.callSignatures[0].parameters.map((parameter) => {
2452
return {
25-
...prop,
26-
filenames: Array.from(prop.filenames),
53+
...parameter,
2754
};
28-
})
29-
.filter(
55+
}),
56+
/*.filter(
3057
(prop) =>
3158
options.includeExternal ||
3259
!Array.from(prop.filenames).some((filename) => filename.includes('/node_modules/')),
33-
),
34-
};
35-
});
60+
),*/
61+
};
62+
});
63+
64+
components.push(...componentsApi);
65+
hooks.push(...hooksApi);
66+
} catch (e) {
67+
console.error(`⛔ Error processing ${file}: ${e.message}`);
68+
++errorCounter;
69+
} finally {
70+
console.groupEnd();
71+
}
72+
}
73+
74+
const outputJSON = JSON.stringify({ components, hooks }, null, 2);
75+
if (options.out) {
76+
fs.writeFileSync(options.out, outputJSON);
77+
console.log(`Output written to ${options.out}`);
78+
} else {
79+
console.log(outputJSON);
80+
}
3681

37-
console.log(JSON.stringify(translated, null, 2));
82+
console.log(`\nProcessed ${files.length} files.`);
83+
if (errorCounter > 0) {
84+
console.log(`❌ Found ${errorCounter} errors.`);
85+
process.exit(1);
3886
}
3987
}
4088

@@ -47,8 +95,9 @@ yargs(hideBin(process.argv))
4795
.option('files', {
4896
alias: 'f',
4997
type: 'array',
50-
demandOption: true,
51-
description: 'The files to extract the API descriptions from',
98+
demandOption: false,
99+
description:
100+
'The files to extract the API descriptions from. If not provided, all files in the tsconfig.json are used',
52101
})
53102
.option('configPath', {
54103
alias: 'c',
@@ -61,6 +110,11 @@ yargs(hideBin(process.argv))
61110
type: 'boolean',
62111
default: false,
63112
description: 'Include props defined outside of the project',
113+
})
114+
.option('out', {
115+
alias: 'o',
116+
type: 'string',
117+
description: 'The output file. If not provided, the output is printed to the console',
64118
});
65119
},
66120
run,

src/config.ts

Lines changed: 7 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import * as ts from 'typescript';
1+
import ts from 'typescript';
22
import fs from 'fs';
33
import path from 'path';
44

@@ -7,19 +7,22 @@ import path from 'path';
77
* @param tsConfigPath The location for a `tsconfig.json` file
88
*/
99
export function loadConfig(tsConfigPath: string) {
10+
const resolvedConfigPath = path.resolve(tsConfigPath);
11+
const projectDirectory = path.dirname(resolvedConfigPath);
12+
1013
const { config, error } = ts.readConfigFile(tsConfigPath, (filePath) =>
1114
fs.readFileSync(filePath).toString(),
1215
);
1316

1417
if (error) throw error;
1518

16-
const { options, errors } = ts.parseJsonConfigFileContent(
19+
const { options, errors, fileNames } = ts.parseJsonConfigFileContent(
1720
config,
1821
ts.sys,
19-
path.dirname(tsConfigPath),
22+
projectDirectory,
2023
);
2124

2225
if (errors.length > 0) throw errors[0];
2326

24-
return options;
27+
return { options, fileNames };
2528
}

src/parser.ts

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -504,7 +504,11 @@ export function parseFromProgram(
504504
: symbolType;
505505

506506
if (!type) {
507-
throw new Error('No types found');
507+
if (symbol.name) {
508+
throw new Error('No types found for symbol ' + symbol.name);
509+
} else {
510+
throw new Error('No types found for symbol');
511+
}
508512
}
509513

510514
// Typechecker only gives the type "any" if it's present in a union

src/types/nodes/function.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ const typeString = 'function';
55

66
export interface FunctionNode {
77
nodeType: typeof typeString;
8-
callSignatures?: CallSignature[];
8+
callSignatures: CallSignature[];
99
}
1010

1111
export interface CallSignature {

0 commit comments

Comments
 (0)