Skip to content

Commit ca43858

Browse files
devvaannshabose
authored andcommitted
feat: made script asynchronous, to improve efficiency
1 parent 7ef112d commit ca43858

File tree

1 file changed

+72
-102
lines changed

1 file changed

+72
-102
lines changed

build/api-docs-generator.js

Lines changed: 72 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,84 +1,66 @@
1-
const fs = require('fs');
1+
const fs = require('fs').promises;
22
const path = require('path');
33
const glob = require('glob');
4-
const { execSync } = require('child_process');
5-
4+
const util = require('util');
5+
const exec = util.promisify(require('child_process').exec);
66

77
const SRC_DIR = './src';
88
const BUILD_DIR = './build';
9-
10-
// Temp dir will automatically be removed after markdown is generated
119
const TEMP_DIR = path.join(BUILD_DIR, 'temp');
1210
const MD_FILES_DIR = path.join('./docs', 'API-Reference');
1311

12+
const globPromise = util.promisify(glob);
13+
1414
/**
15-
* Responsible to get the JS Files,
16-
* that are to be included in API DOCS
17-
* @returns {[]} list of JS Files that are to be included in API Docs
15+
* Responsible to get the JS Files that are to be included in API DOCS
16+
* @returns {Promise<string[]>} Promise resolving to list of JS Files for API Docs
1817
*/
19-
function getJsFiles() {
20-
// this gives all the JS Files, from src direcotry
21-
const allJsFiles = glob.sync(`${SRC_DIR}/**/*.js`);
22-
23-
// those files that are to be included in API Docs
18+
async function getJsFiles() {
19+
const allJsFiles = await globPromise(`${SRC_DIR}/**/*.js`);
2420
const requiredJSfiles = [];
2521

26-
for (const file of allJsFiles) {
27-
// make sure it is a file, and not a dir
28-
if (fs.statSync(file).isFile()) {
29-
const content = fs.readFileSync(file, 'utf-8');
30-
31-
// we check for this line, as we only need
32-
// those files that has this line.
22+
await Promise.all(allJsFiles.map(async (file) => {
23+
const stats = await fs.stat(file);
24+
if (stats.isFile()) {
25+
const content = await fs.readFile(file, 'utf-8');
3326
if (content.includes('@INCLUDE_IN_API_DOCS')) {
3427
requiredJSfiles.push(file);
3528
}
3629
}
37-
}
30+
}));
31+
3832
return requiredJSfiles;
3933
}
4034

4135
/**
42-
* responsible to create a directory
43-
* @param {string path} dirPath creates dir at the given path
36+
* Creates a directory
37+
* @param {string} dirPath creates dir at the given path
4438
*/
45-
function createDir(dirPath) {
46-
fs.mkdirSync(dirPath, { recursive: true });
39+
async function createDir(dirPath) {
40+
await fs.mkdir(dirPath, { recursive: true });
4741
}
4842

4943
/**
50-
* responsible to delete a directory
51-
* @param {string path} dirPath deletes dir from the given path
44+
* Deletes a directory
45+
* @param {string} dirPath deletes dir from the given path
5246
*/
53-
function removeDir(dirPath) {
54-
fs.rmSync(dirPath, { recursive: true, force: true });
47+
async function removeDir(dirPath) {
48+
await fs.rm(dirPath, { recursive: true, force: true });
5549
}
5650

5751
/**
58-
* This function adjusts JavaScript content
59-
* to ensure compatibility with jsdoc-to-markdown.
60-
* @param {string} content The content of the file, i.e. to be modified
52+
* Adjusts JavaScript content for compatibility with jsdoc-to-markdown
53+
* @param {string} content The content to be modified
6154
* @param {string} fileName To replace the define block with this name
6255
* @returns {string} Updated content
6356
*/
6457
function modifyJs(content, fileName) {
65-
66-
// remove function wrapper
6758
if (content.includes('\n(function () {')) {
68-
69-
content = content.replace(
70-
/\(function \(\) \{/,
71-
''
72-
);
73-
74-
// Remove matching closing parentheses
59+
content = content.replace(/\(function \(\) \{/, '');
7560
if (content.trim().endsWith('}());')) {
7661
content = content.trim().slice(0, -5);
7762
}
7863

79-
// Clean up any leftover unmatched brackets
80-
// removing `function wrapper` leads to an unmatched '}' and ')'
81-
// this logic just removes the unmatched brackets.
8264
let bracketCount = 0;
8365
for (let indx = 0; indx < content.length; indx++) {
8466
if (content[indx] === '{') {
@@ -90,48 +72,33 @@ function modifyJs(content, fileName) {
9072
while (content[indx] && content[indx] !== ')') {
9173
indx--;
9274
}
93-
content = content.slice(0, indx)
94-
+ content.slice(tempIndx + 1);
75+
content = content.slice(0, indx) + content.slice(tempIndx + 1);
9576
bracketCount++;
9677
break;
9778
}
9879
}
9980
}
10081
} else if (content.includes('define(function')) {
101-
102-
// remove define blocks
103-
content = content.replace(
104-
/define\(function\s*\([^)]*\)\s*{/,
105-
''
106-
);
107-
108-
// remove trailing braces from define block
82+
content = content.replace(/define\(function\s*\([^)]*\)\s*{/, '');
10983
if (content.trim().endsWith('});')) {
11084
content = content.trim().slice(0, -3);
11185
}
11286
}
113-
11487
return content;
11588
}
11689

117-
11890
/**
119-
* When generating markdown from JSDoc,
120-
* some unwanted tags gets generated at the top of the MD file,
121-
* we need to remove it, as it causes compatibility issues with docusaurus
122-
* Also adds import statements at the top of every file
91+
* Modifies markdown content for compatibility with docusaurus
12392
* @param {string} content markdown file content
12493
* @param {string} relativePath Relative path of the file from MD_FILES_DIR
12594
* @returns {string} updated markdown file content
12695
*/
12796
function modifyMarkdown(content, relativePath) {
128-
// to start the markdown from '<a' tag
12997
const anchorIndex = content.indexOf('<a name');
13098
if (anchorIndex !== -1) {
13199
content = content.slice(anchorIndex);
132100
}
133101

134-
// Add the import statement
135102
const modulePath = path.join(
136103
path.dirname(relativePath),
137104
path.basename(relativePath, '.md')
@@ -141,66 +108,69 @@ function modifyMarkdown(content, relativePath) {
141108
`\`\`\`js\nconst ${path.basename(relativePath, '.md')} = ` +
142109
`brackets.getModule("${modulePath}")\n\`\`\`\n\n`;
143110

144-
content = content.replace(/~/g, '.');
145-
146-
// Combine the import statement with the modified content
147-
return importStatement + content;
111+
return importStatement + content.replace(/~/g, '.');
148112
}
149113

150-
151114
/**
152115
* Generates markdown documentation for a given JavaScript file
153116
* @param {string} file Path to the JavaScript file
154117
* @param {string} relativePath Relative path of the file from SRC_DIR
155118
*/
156-
function generateMarkdown(file, relativePath) {
157-
let content = fs.readFileSync(file, 'utf-8');
119+
async function generateMarkdown(file, relativePath) {
120+
const content = await fs.readFile(file, 'utf-8');
158121
const fileName = path.basename(file, '.js');
159122

160-
// update the JS file to make it compatible with JsDoc-to-MD library
161-
content = modifyJs(content, fileName);
162-
fs.writeFileSync(file, content, 'utf-8');
123+
const modifiedContent = modifyJs(content, fileName);
124+
await fs.writeFile(file, modifiedContent, 'utf-8');
163125

164-
// generate the markdown on the required directory
165126
const outputDir = path.join(MD_FILES_DIR, relativePath);
166-
createDir(outputDir);
127+
await createDir(outputDir);
128+
167129
const outputFileName = path.join(outputDir, `${fileName}.md`);
168-
execSync(`npx jsdoc-to-markdown ${file} > ${outputFileName}`);
130+
await exec(`npx jsdoc-to-markdown ${file} > ${outputFileName}`);
169131

170-
// update the MD file to make it compatible with Docusaurus and add import statement
171-
let markdownContent = fs.readFileSync(outputFileName, 'utf-8');
132+
const markdownContent = await fs.readFile(outputFileName, 'utf-8');
172133
const updatedMarkdownContent = modifyMarkdown(markdownContent, path.join(relativePath, fileName));
173-
fs.writeFileSync(outputFileName, updatedMarkdownContent, 'utf-8');
134+
await fs.writeFile(outputFileName, updatedMarkdownContent, 'utf-8');
174135
}
175136

176-
177137
/**
178138
* Handles the execution and control flow of the program
179139
*/
180-
function driver() {
181-
const jsFiles = getJsFiles();
182-
console.log("Fetched all required JS files");
183-
184-
createDir(TEMP_DIR);
185-
createDir(MD_FILES_DIR);
186-
187-
for (const file of jsFiles) {
188-
const relativePath = path.relative(SRC_DIR, path.dirname(file));
189-
const tempDirPath = path.join(TEMP_DIR, relativePath);
190-
createDir(tempDirPath);
191-
192-
// copy the file from src to temp dir for modifications
193-
const fileName = path.basename(file);
194-
const destPath = path.join(tempDirPath, fileName);
195-
fs.copyFileSync(file, destPath);
140+
async function driver() {
141+
try {
142+
console.log("Fetching required JS files...");
143+
const jsFiles = await getJsFiles();
144+
console.log(`Found ${jsFiles.length} files to process`);
145+
146+
await createDir(TEMP_DIR);
147+
await createDir(MD_FILES_DIR);
148+
149+
// Process files in batches to avoid overwhelming the system
150+
const BATCH_SIZE = 12;
151+
for (let i = 0; i < jsFiles.length; i += BATCH_SIZE) {
152+
const batch = jsFiles.slice(i, i + BATCH_SIZE);
153+
await Promise.all(batch.map(async (file) => {
154+
const relativePath = path.relative(SRC_DIR, path.dirname(file));
155+
const tempDirPath = path.join(TEMP_DIR, relativePath);
156+
await createDir(tempDirPath);
157+
158+
const fileName = path.basename(file);
159+
const destPath = path.join(tempDirPath, fileName);
160+
await fs.copyFile(file, destPath);
161+
162+
await generateMarkdown(destPath, relativePath);
163+
console.log(`Processed ${file}`);
164+
}));
165+
}
196166

197-
generateMarkdown(destPath, relativePath);
198-
console.log(`${file} successfully converted to Markdown`);
167+
await removeDir(TEMP_DIR);
168+
console.log("All files processed successfully!");
169+
} catch (error) {
170+
console.error("An error occurred:", error);
171+
// Cleanup temp directory in case of error
172+
await removeDir(TEMP_DIR).catch(() => { });
199173
}
200-
201-
removeDir(TEMP_DIR);
202-
203-
console.log("All set!!!");
204174
}
205175

206-
driver();
176+
driver().catch(console.error);

0 commit comments

Comments
 (0)