create-file.ts 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  1. import { asyncWriteToStream } from 'foxts/async-write-to-stream';
  2. import { fastStringArrayJoin } from 'foxts/fast-string-array-join';
  3. import fs from 'node:fs';
  4. import picocolors from 'picocolors';
  5. import type { Span } from '../trace';
  6. import { readFileByLine } from './fetch-text-by-line';
  7. import { writeFile } from './misc';
  8. import { createCompareSource, fileEqualWithCommentComparator } from 'foxts/compare-source';
  9. export const fileEqual = createCompareSource(fileEqualWithCommentComparator);
  10. export async function compareAndWriteFile(span: Span, linesA: string[], filePath: string) {
  11. const isEqual = await span.traceChildAsync(`compare ${filePath}`, async () => {
  12. if (fs.existsSync(filePath)) {
  13. return fileEqual(linesA, readFileByLine(filePath));
  14. }
  15. console.log(`${filePath} does not exists, writing...`);
  16. return false;
  17. });
  18. if (isEqual) {
  19. console.log(picocolors.gray(picocolors.dim(`same content, bail out writing: ${filePath}`)));
  20. return;
  21. }
  22. return span.traceChildAsync<void>(`writing ${filePath}`, async () => {
  23. const linesALen = linesA.length;
  24. // The default highwater mark is normally 16384,
  25. // So we make sure direct write to file if the content is
  26. // most likely less than 500 lines
  27. if (linesALen < 500) {
  28. return writeFile(filePath, fastStringArrayJoin(linesA, '\n') + '\n');
  29. }
  30. const writeStream = fs.createWriteStream(filePath);
  31. for (let i = 0; i < linesALen; i++) {
  32. const p = asyncWriteToStream(writeStream, linesA[i] + '\n');
  33. // eslint-disable-next-line no-await-in-loop -- stream high water mark
  34. if (p) await p;
  35. }
  36. writeStream.end();
  37. writeStream.close();
  38. });
  39. }