Skip to content

Commit f49a7dd

Browse files
committed
refactor: replace sync fs calls with async fs/promises
1 parent 4ebd3fa commit f49a7dd

4 files changed

Lines changed: 80 additions & 53 deletions

File tree

Lines changed: 13 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
/* eslint-disable n/no-sync */
2-
3-
import * as fs from 'fs';
1+
import * as fs from 'fs/promises';
42
import * as path from 'path';
53

64
export const SKIP_DIRS = new Set([
@@ -16,20 +14,20 @@ export const SKIP_DIRS = new Set([
1614
* Recursively find all non-test TypeScript files in a directory.
1715
*
1816
* @param dir - The directory to search.
19-
* @returns An array of absolute file paths.
17+
* @returns A promise that resolves to an array of absolute file paths.
2018
*/
21-
export function findTsFiles(dir: string): string[] {
19+
export async function findTsFiles(dir: string): Promise<string[]> {
2220
const results: string[] = [];
2321

24-
function walk(directory: string): void {
25-
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
22+
async function walk(directory: string): Promise<void> {
23+
for (const entry of await fs.readdir(directory, { withFileTypes: true })) {
2624
const full = path.join(directory, entry.name);
2725
if (entry.isDirectory()) {
2826
// Skip test dirs, node_modules, dist
2927
if (SKIP_DIRS.has(entry.name)) {
3028
continue;
3129
}
32-
walk(full);
30+
await walk(full);
3331
} else if (
3432
entry.name.endsWith('.ts') &&
3533
!entry.name.endsWith('.test.ts') &&
@@ -42,7 +40,7 @@ export function findTsFiles(dir: string): string[] {
4240
}
4341
}
4442

45-
walk(dir);
43+
await walk(dir);
4644
return results;
4745
}
4846

@@ -51,25 +49,25 @@ export function findTsFiles(dir: string): string[] {
5149
* Skips nested `node_modules` subdirectories.
5250
*
5351
* @param dir - The directory to search.
54-
* @returns An array of absolute file paths.
52+
* @returns A promise that resolves to an array of absolute file paths.
5553
*/
56-
export function findDtsFiles(dir: string): string[] {
54+
export async function findDtsFiles(dir: string): Promise<string[]> {
5755
const results: string[] = [];
5856

59-
function walk(directory: string): void {
60-
for (const entry of fs.readdirSync(directory, { withFileTypes: true })) {
57+
async function walk(directory: string): Promise<void> {
58+
for (const entry of await fs.readdir(directory, { withFileTypes: true })) {
6159
const full = path.join(directory, entry.name);
6260
if (entry.isDirectory()) {
6361
if (entry.name === 'node_modules') {
6462
continue;
6563
}
66-
walk(full);
64+
await walk(full);
6765
} else if (entry.name.endsWith('.d.cts')) {
6866
results.push(full);
6967
}
7068
}
7169
}
7270

73-
walk(dir);
71+
await walk(dir);
7472
return results;
7573
}

scripts/generate-messenger-docs/extraction.ts

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,24 @@
1-
/* eslint-disable n/no-sync */
2-
3-
import * as fs from 'fs';
1+
import * as fs from 'fs/promises';
42
import * as path from 'path';
53
import * as ts from 'typescript';
64

75
import type { MessengerItemDoc, MethodInfo } from './types';
86

7+
/**
8+
* Check whether a file exists.
9+
*
10+
* @param filePath - The path to check.
11+
* @returns A promise that resolves to true if the file exists.
12+
*/
13+
async function fileExists(filePath: string): Promise<boolean> {
14+
try {
15+
await fs.access(filePath);
16+
return true;
17+
} catch {
18+
return false;
19+
}
20+
}
21+
922
/**
1023
* Extract string constants from top-level variable declarations in a source file.
1124
* Only looks at top-level `const x = 'string'` or `const x = 'string' as const`.
@@ -60,12 +73,12 @@ function extractStringConstants(
6073
*
6174
* @param sourceFile - The TypeScript source file to search.
6275
* @param filePath - The absolute path of the source file on disk.
63-
* @returns A map of constant name to resolved string value.
76+
* @returns A promise that resolves to a map of constant name to resolved string value.
6477
*/
65-
function resolveControllerName(
78+
async function resolveControllerName(
6679
sourceFile: ts.SourceFile,
6780
filePath: string,
68-
): Map<string, string> {
81+
): Promise<Map<string, string>> {
6982
const names = extractStringConstants(sourceFile);
7083

7184
// Chase single-hop local imports (no further recursion):
@@ -98,11 +111,11 @@ function resolveControllerName(
98111
: [path.join(dir, `${spec}.ts`), path.join(dir, spec, 'index.ts')];
99112

100113
for (const candidate of candidates) {
101-
if (!fs.existsSync(candidate)) {
114+
if (!(await fileExists(candidate))) {
102115
continue;
103116
}
104117

105-
const content = fs.readFileSync(candidate, 'utf8');
118+
const content = await fs.readFile(candidate, 'utf8');
106119
const sf = ts.createSourceFile(
107120
candidate,
108121
content,
@@ -463,22 +476,22 @@ function getPropertyText(
463476
* Extract messenger action/event type definitions from a single TypeScript file.
464477
*
465478
* @param filePath - The absolute path to the TypeScript file.
466-
* @param relBase - Optional base path for computing relative source paths (defaults to ROOT).
467-
* @returns An array of extracted messenger item docs.
479+
* @param relBase - Base path for computing relative source paths.
480+
* @returns A promise that resolves to an array of extracted messenger item docs.
468481
*/
469-
export function extractFromFile(
482+
export async function extractFromFile(
470483
filePath: string,
471484
relBase: string,
472-
): MessengerItemDoc[] {
473-
const content = fs.readFileSync(filePath, 'utf8');
485+
): Promise<MessengerItemDoc[]> {
486+
const content = await fs.readFile(filePath, 'utf8');
474487
const sourceFile = ts.createSourceFile(
475488
filePath,
476489
content,
477490
ts.ScriptTarget.Latest,
478491
true,
479492
);
480493

481-
const constants = resolveControllerName(sourceFile, filePath);
494+
const constants = await resolveControllerName(sourceFile, filePath);
482495
const classMethods = collectClassMethods(sourceFile);
483496
const items: MessengerItemDoc[] = [];
484497
const relPath = path.relative(relBase, filePath);

scripts/generate-messenger-docs/index.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,7 @@
22

33
import { main } from './main';
44

5-
main();
5+
main().catch((error) => {
6+
console.error(error);
7+
process.exitCode = 1;
8+
});

scripts/generate-messenger-docs/main.ts

Lines changed: 36 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
1-
/* eslint-disable n/no-sync */
2-
3-
import * as fs from 'fs';
1+
import * as fs from 'fs/promises';
42
import * as path from 'path';
53

64
import { findDtsFiles, findTsFiles } from './discovery';
@@ -31,10 +29,25 @@ function deduplicationScore(item: MessengerItemDoc): number {
3129
return jsDocScore + homeScore;
3230
}
3331

32+
/**
33+
* Check whether a path exists.
34+
*
35+
* @param targetPath - The path to check.
36+
* @returns A promise that resolves to true if the path exists.
37+
*/
38+
async function pathExists(targetPath: string): Promise<boolean> {
39+
try {
40+
await fs.access(targetPath);
41+
return true;
42+
} catch {
43+
return false;
44+
}
45+
}
46+
3447
/**
3548
* Main entry point: scans packages, extracts messenger types, and generates docs.
3649
*/
37-
export function main(): void {
50+
export async function main(): Promise<void> {
3851
// Parse --client flag
3952
const clientIdx = process.argv.indexOf('--client');
4053
const clientPath = clientIdx === -1 ? undefined : process.argv[clientIdx + 1];
@@ -49,13 +62,13 @@ export function main(): void {
4962
);
5063

5164
const nmDir = path.join(clientPath as string, 'node_modules', '@metamask');
52-
if (!fs.existsSync(nmDir)) {
65+
if (!(await pathExists(nmDir))) {
5366
throw new Error(`${nmDir} does not exist.`);
5467
}
5568

5669
// Find @metamask packages that contain "controller" or "service" in name
57-
const pkgDirs = fs
58-
.readdirSync(nmDir, { withFileTypes: true })
70+
const entries = await fs.readdir(nmDir, { withFileTypes: true });
71+
const pkgDirs = entries
5972
.filter(
6073
(dirent) =>
6174
dirent.isDirectory() &&
@@ -65,14 +78,14 @@ export function main(): void {
6578
.map((dirent) => path.join(nmDir, dirent.name, 'dist'));
6679

6780
for (const distDir of pkgDirs) {
68-
if (!fs.existsSync(distDir)) {
81+
if (!(await pathExists(distDir))) {
6982
continue;
7083
}
7184

72-
const dtsFiles = findDtsFiles(distDir);
85+
const dtsFiles = await findDtsFiles(distDir);
7386
for (const file of dtsFiles) {
7487
try {
75-
const items = extractFromFile(file, clientPath as string);
88+
const items = await extractFromFile(file, clientPath as string);
7689
allItems.push(...items);
7790
} catch (error) {
7891
console.warn(
@@ -85,20 +98,20 @@ export function main(): void {
8598
console.log('Scanning packages for Messenger action/event types...');
8699

87100
const packagesDir = path.join(ROOT, 'packages');
88-
const packageDirs = fs
89-
.readdirSync(packagesDir, { withFileTypes: true })
101+
const entries = await fs.readdir(packagesDir, { withFileTypes: true });
102+
const packageDirs = entries
90103
.filter((dirent) => dirent.isDirectory())
91104
.map((dirent) => path.join(packagesDir, dirent.name, 'src'));
92105

93106
for (const srcDir of packageDirs) {
94-
if (!fs.existsSync(srcDir)) {
107+
if (!(await pathExists(srcDir))) {
95108
continue;
96109
}
97110

98-
const tsFiles = findTsFiles(srcDir);
111+
const tsFiles = await findTsFiles(srcDir);
99112
for (const file of tsFiles) {
100113
try {
101-
const items = extractFromFile(file, ROOT);
114+
const items = await extractFromFile(file, ROOT);
102115
allItems.push(...items);
103116
} catch (error) {
104117
console.warn(
@@ -169,39 +182,39 @@ export function main(): void {
169182
const docsDir = path.join(ROOT, 'docs-site', 'docs');
170183

171184
// Clean existing generated docs
172-
if (fs.existsSync(docsDir)) {
173-
fs.rmSync(docsDir, { recursive: true });
185+
if (await pathExists(docsDir)) {
186+
await fs.rm(docsDir, { recursive: true });
174187
}
175-
fs.mkdirSync(docsDir, { recursive: true });
188+
await fs.mkdir(docsDir, { recursive: true });
176189

177190
// Generate namespace pages
178191
for (const ns of namespaces) {
179192
const nsDir = path.join(docsDir, ns.namespace);
180-
fs.mkdirSync(nsDir, { recursive: true });
193+
await fs.mkdir(nsDir, { recursive: true });
181194

182195
if (ns.actions.length > 0) {
183-
fs.writeFileSync(
196+
await fs.writeFile(
184197
path.join(nsDir, 'actions.md'),
185198
generateNamespacePage(ns, 'action', clientMode),
186199
);
187200
}
188201

189202
if (ns.events.length > 0) {
190-
fs.writeFileSync(
203+
await fs.writeFile(
191204
path.join(nsDir, 'events.md'),
192205
generateNamespacePage(ns, 'event', clientMode),
193206
);
194207
}
195208
}
196209

197210
// Generate index page
198-
fs.writeFileSync(
211+
await fs.writeFile(
199212
path.join(docsDir, 'index.md'),
200213
generateIndexPage(namespaces, clientName),
201214
);
202215

203216
// Generate sidebars
204-
fs.writeFileSync(
217+
await fs.writeFile(
205218
path.join(ROOT, 'docs-site', 'sidebars.ts'),
206219
generateSidebars(namespaces),
207220
);

0 commit comments

Comments
 (0)