check.js 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. // @ts-check
  2. import { spawn } from 'node:child_process';
  3. import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
  4. import * as path from 'node:path';
  5. import pLimit from 'p-limit';
  6. import { tsconfigResolverSync } from 'tsconfig-resolver';
  7. function checkExamples() {
  8. let examples = readdirSync('./examples', { withFileTypes: true });
  9. examples = examples.filter((dirent) => dirent.isDirectory());
  10. console.log(`Running astro check on ${examples.length} examples...`);
  11. // Run astro check in parallel with 5 at most
  12. const checkPromises = [];
  13. const limit = pLimit(5);
  14. for (const example of examples) {
  15. checkPromises.push(
  16. limit(
  17. () =>
  18. new Promise((resolve) => {
  19. // Sometimes some examples may get deleted, but after a `git pull` the directory still exists.
  20. // This can stall the process time as it'll typecheck the entire monorepo, so do a quick exist
  21. // check here before typechecking this directory.
  22. if (!existsSync(path.join('./examples/', example.name, 'package.json'))) {
  23. resolve(0);
  24. return;
  25. }
  26. const originalConfig = prepareExample(example.name);
  27. let data = '';
  28. const child = spawn('node', ['../../packages/astro/astro.js', 'check'], {
  29. cwd: path.join('./examples', example.name),
  30. env: { ...process.env, FORCE_COLOR: 'true' },
  31. });
  32. child.stdout.on('data', function (buffer) {
  33. data += buffer.toString();
  34. });
  35. child.on('exit', (code) => {
  36. if (code !== 0) {
  37. console.error(data);
  38. }
  39. if (originalConfig) {
  40. resetExample(example.name, originalConfig);
  41. }
  42. resolve(code);
  43. });
  44. })
  45. )
  46. );
  47. }
  48. Promise.all(checkPromises).then((codes) => {
  49. if (codes.some((code) => code !== 0)) {
  50. process.exit(1);
  51. }
  52. console.log('No errors found!');
  53. });
  54. }
  55. /**
  56. * @param {string} examplePath
  57. */
  58. function prepareExample(examplePath) {
  59. const tsconfigPath = path.join('./examples/', examplePath, 'tsconfig.json');
  60. const tsconfig = tsconfigResolverSync({ filePath: tsconfigPath, cache: false });
  61. let originalConfig = undefined;
  62. if (tsconfig.exists) {
  63. tsconfig.config.extends = 'astro/tsconfigs/strictest';
  64. originalConfig = readFileSync(tsconfigPath).toString();
  65. if (!tsconfig.config.compilerOptions) {
  66. tsconfig.config.compilerOptions = {};
  67. }
  68. tsconfig.config.compilerOptions = Object.assign(tsconfig.config.compilerOptions, {
  69. types: tsconfig.config.compilerOptions.types ?? [], // Speeds up tests
  70. });
  71. }
  72. if (tsconfig.config) {
  73. writeFileSync(tsconfigPath, JSON.stringify(tsconfig.config));
  74. }
  75. return originalConfig;
  76. }
  77. /**
  78. * @param {string} examplePath
  79. * @param {string} originalConfig
  80. */
  81. function resetExample(examplePath, originalConfig) {
  82. const tsconfigPath = path.join('./examples/', examplePath, 'tsconfig.json');
  83. writeFileSync(tsconfigPath, originalConfig);
  84. }
  85. checkExamples();