Skip to content

Commit 179ca04

Browse files
authored
chore: safe copy mechanism (#480)
1 parent dca59d6 commit 179ca04

File tree

2 files changed

+48
-8
lines changed

2 files changed

+48
-8
lines changed

src/generators/legacy-html/index.mjs

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,13 @@
11
'use strict';
22

3-
import { cp, readFile, rm, writeFile } from 'node:fs/promises';
3+
import { readFile, rm, writeFile, mkdir } from 'node:fs/promises';
44
import { join } from 'node:path';
55

66
import HTMLMinifier from '@minify-html/node';
77

88
import buildContent from './utils/buildContent.mjs';
99
import dropdowns from './utils/buildDropdowns.mjs';
10+
import { safeCopy } from './utils/safeCopy.mjs';
1011
import tableOfContents from './utils/tableOfContents.mjs';
1112
import { groupNodesByModule } from '../../utils/generators.mjs';
1213
import { getRemarkRehype } from '../../utils/remark.mjs';
@@ -169,6 +170,9 @@ export default {
169170
}
170171

171172
if (output) {
173+
// Define the source folder for API docs assets
174+
const srcAssets = join(baseDir, 'assets');
175+
172176
// Define the output folder for API docs assets
173177
const assetsFolder = join(output, 'assets');
174178

@@ -177,13 +181,11 @@ export default {
177181
// If the path does not exists, it will simply ignore and continue
178182
await rm(assetsFolder, { recursive: true, force: true, maxRetries: 10 });
179183

180-
// We copy all the other assets to the output folder at the end of the process
181-
// to ensure that all latest changes on the styles are applied to the output
182-
// Note.: This is not meant to be used for DX/developer purposes.
183-
await cp(join(baseDir, 'assets'), assetsFolder, {
184-
recursive: true,
185-
force: true,
186-
});
184+
// Creates the assets folder if it does not exist
185+
await mkdir(assetsFolder, { recursive: true });
186+
187+
// Copy all files from assets folder to output, skipping unchanged files
188+
await safeCopy(srcAssets, assetsFolder);
187189
}
188190

189191
return generatedValues;
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
'use strict';
2+
3+
import { readFile, writeFile, stat, readdir } from 'node:fs/promises';
4+
import { join } from 'node:path';
5+
6+
/**
7+
* Safely copies files from source to target directory, skipping files that haven't changed
8+
* based on file stats (size and modification time)
9+
*
10+
* @param {string} srcDir - Source directory path
11+
* @param {string} targetDir - Target directory path
12+
*/
13+
export async function safeCopy(srcDir, targetDir) {
14+
const files = await readdir(srcDir);
15+
16+
for (const file of files) {
17+
const sourcePath = join(srcDir, file);
18+
const targetPath = join(targetDir, file);
19+
20+
const [sStat, tStat] = await Promise.allSettled([
21+
stat(sourcePath),
22+
stat(targetPath),
23+
]);
24+
25+
const shouldWrite =
26+
tStat.status === 'rejected' ||
27+
sStat.value.size !== tStat.value.size ||
28+
sStat.value.mtimeMs > tStat.value.mtimeMs;
29+
30+
if (!shouldWrite) {
31+
continue;
32+
}
33+
34+
const fileContent = await readFile(sourcePath);
35+
36+
await writeFile(targetPath, fileContent);
37+
}
38+
}

0 commit comments

Comments
 (0)