fork of hey-api/openapi-ts because I need some additional things
1import fs from 'node:fs';
2import path from 'node:path';
3
4import type { AnyString } from '@hey-api/types';
5import ts from 'typescript';
6
7export function findPackageJson(initialDir: string): unknown | undefined {
8 let dir = initialDir;
9 while (dir !== path.dirname(dir)) {
10 const files = fs.readdirSync(dir);
11 const candidates = files.filter((file) => file === 'package.json');
12
13 if (candidates[0]) {
14 const packageJsonPath = path.join(dir, candidates[0]);
15 return JSON.parse(
16 fs.readFileSync(packageJsonPath, {
17 encoding: 'utf8',
18 }),
19 );
20 }
21
22 dir = path.dirname(dir);
23 }
24
25 return;
26}
27
28type PackageJson = {
29 bugs: {
30 url: string;
31 };
32 name: string;
33 version: string;
34};
35
36export function loadPackageJson(initialDir: string): PackageJson | undefined {
37 const packageJson = findPackageJson(initialDir);
38
39 const safePackage: PackageJson = {
40 bugs: {
41 url: '',
42 },
43 name: '',
44 version: '',
45 };
46
47 if (packageJson && typeof packageJson === 'object') {
48 if ('name' in packageJson && typeof packageJson.name === 'string') {
49 safePackage.name = packageJson.name;
50 }
51
52 if ('version' in packageJson && typeof packageJson.version === 'string') {
53 safePackage.version = packageJson.version;
54 }
55
56 if ('bugs' in packageJson && packageJson.bugs && typeof packageJson.bugs === 'object') {
57 if ('url' in packageJson.bugs && typeof packageJson.bugs.url === 'string') {
58 safePackage.bugs.url = packageJson.bugs.url;
59 if (safePackage.bugs.url && !safePackage.bugs.url.endsWith('/')) {
60 safePackage.bugs.url += '/';
61 }
62 }
63 }
64 }
65
66 if (!safePackage.name) return;
67
68 return safePackage;
69}
70
71export function findTsConfigPath(baseDir: string, tsConfigPath?: AnyString | null): string | null {
72 if (tsConfigPath === null) {
73 return null;
74 }
75
76 if (tsConfigPath) {
77 const resolved = path.isAbsolute(tsConfigPath)
78 ? tsConfigPath
79 : path.resolve(baseDir, tsConfigPath);
80 return fs.existsSync(resolved) ? resolved : null;
81 }
82
83 let dir = baseDir;
84 while (dir !== path.dirname(dir)) {
85 const files = fs.readdirSync(dir);
86 const candidates = files
87 .filter((file) => file.startsWith('tsconfig') && file.endsWith('.json'))
88 .sort((file) => (file === 'tsconfig.json' ? -1 : 1));
89
90 if (candidates[0]) {
91 return path.join(dir, candidates[0]);
92 }
93
94 dir = path.dirname(dir);
95 }
96
97 return null;
98}
99
100export function loadTsConfig(configPath: string | null): ts.ParsedCommandLine | null {
101 if (!configPath) {
102 return null;
103 }
104
105 const raw = ts.readConfigFile(configPath, ts.sys.readFile);
106
107 if (raw.error) {
108 throw new Error(`Couldn't read tsconfig from path: ${configPath}`);
109 }
110
111 return ts.parseJsonConfigFileContent(raw.config, ts.sys, path.dirname(configPath));
112}