Design system.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

192 lines
5.0 KiB

  1. import {
  2. cp, readFile, rm, stat, writeFile,
  3. } from 'fs/promises';
  4. import { dirname, resolve } from 'path';
  5. import { Argv } from 'yargs';
  6. import { Stats } from 'fs';
  7. import { mkdirp } from 'mkdirp';
  8. import { getPackages, TypedocData } from '../utils/data';
  9. const ensureTypedocJson = async (typedocPath: string) => {
  10. const trueTypedocPath = resolve(typedocPath);
  11. process.stdout.write(`Using typedoc.json path: ${trueTypedocPath}\n`);
  12. process.stdout.write('Does the file exist? ');
  13. let statResult: Stats;
  14. try {
  15. statResult = await stat(trueTypedocPath);
  16. } catch (errRaw) {
  17. const err = errRaw as NodeJS.ErrnoException;
  18. if (err.code === 'ENOENT') {
  19. process.stdout.write('no\n');
  20. process.stderr.write('Could not find typedoc.json\n');
  21. throw new Error('Could not find typedoc.json');
  22. }
  23. process.stdout.write('maybe?\n');
  24. process.stderr.write('Could not ensure typedoc.json\n');
  25. throw err;
  26. }
  27. if (statResult.isDirectory()) {
  28. process.stdout.write('no\n');
  29. process.stderr.write('typedoc.json is a directory\n');
  30. throw new Error('typedoc.json is a directory');
  31. }
  32. process.stdout.write('yes\n');
  33. };
  34. const generateTypedocData = async () => {
  35. process.stdout.write('Generating typedoc data...\n');
  36. const outPath = resolve(__dirname, '..', '..', '..', '.amanuensis', 'data.json');
  37. const typedocBinPath = resolve(__dirname, '..', '..', '..', 'node_modules', '.bin', 'typedoc');
  38. const { execa } = await import('execa');
  39. await execa(typedocBinPath, ['--json', outPath], {
  40. stdout: 'inherit',
  41. stderr: 'inherit',
  42. });
  43. process.stdout.write('done\n');
  44. };
  45. const produceGroupings = async () => {
  46. process.stdout.write('Grouping typedoc data...\n');
  47. const typedocDataJsonPath = resolve(__dirname, '..', '..', '..', '.amanuensis', 'data.json');
  48. const typedocDataJson = await readFile(typedocDataJsonPath, 'utf-8');
  49. const typedocData = JSON.parse(typedocDataJson) as TypedocData;
  50. const packages = await getPackages(process.cwd());
  51. const groupings = {
  52. packages,
  53. typedocData,
  54. };
  55. await writeFile(typedocDataJsonPath, JSON.stringify(groupings, null, 2));
  56. process.stdout.write(`File written to ${typedocDataJsonPath}\n`);
  57. };
  58. const linkComponents = async () => {
  59. process.stdout.write('Linking components...\n');
  60. const projectCwd = resolve(process.cwd(), '.amanuensis');
  61. const defaultCwd = resolve(__dirname, '..', '..', '..', 'default');
  62. const destCwd = resolve(__dirname, '..', '..', '..');
  63. const componentsList = [
  64. 'components/Wrapper.tsx',
  65. ];
  66. try {
  67. await rm(resolve(destCwd, 'components'), { recursive: true });
  68. } catch {
  69. // noop
  70. }
  71. await Promise.all(componentsList.map(async (componentPath) => {
  72. const destPath = resolve(destCwd, componentPath);
  73. let baseCwd = projectCwd;
  74. try {
  75. await stat(resolve(baseCwd, componentPath));
  76. } catch (errRaw) {
  77. const err = errRaw as NodeJS.ErrnoException;
  78. if (err.code === 'ENOENT') {
  79. baseCwd = defaultCwd;
  80. }
  81. }
  82. await mkdirp(dirname(destPath));
  83. await cp(
  84. resolve(baseCwd, componentPath),
  85. destPath,
  86. );
  87. process.stdout.write(`Linked ${componentPath}\n`);
  88. }));
  89. const typedocDataJsonPath = resolve(__dirname, '..', '..', '..', '.amanuensis', 'data.json');
  90. const typedocDataJson = await readFile(typedocDataJsonPath, 'utf-8');
  91. const typedocData = JSON.parse(typedocDataJson) as TypedocData;
  92. await Promise.all(
  93. typedocData.packages.map(async (pkg: any) => {
  94. await mkdirp(resolve(destCwd, 'pages', pkg.basePath));
  95. await Promise.all(
  96. pkg.markdown.map(async (m: any) => {
  97. const srcPath = resolve(process.cwd(), pkg.basePath, m.filePath);
  98. const destPath = resolve(destCwd, 'pages', pkg.basePath, m.name);
  99. console.log(srcPath);
  100. await cp(srcPath, destPath);
  101. }),
  102. );
  103. }),
  104. );
  105. // try {
  106. // await rm(resolve(destCwd, 'pages'), { recursive: true });
  107. // } catch {
  108. // // noop
  109. // }
  110. //
  111. // await cp(
  112. // resolve(defaultCwd, 'pages'),
  113. // resolve(destCwd, 'pages'),
  114. // { recursive: true },
  115. // );
  116. process.stdout.write('done\n');
  117. };
  118. export const description = 'Generate documentation from typedoc.json' as const;
  119. export enum GenerateReturnCode {
  120. SUCCESS = 0,
  121. NO_TYPEDOC_JSON = -1,
  122. COULD_NOT_GENERATE_TYPEDOC_DATA = -2,
  123. COULD_NOT_PRODUCE_GROUPINGS = -3,
  124. COULD_NOT_GENERATE_PAGES = -4,
  125. }
  126. export interface GenerateArgs {
  127. typedocJsonPath?: string;
  128. subcommands?: string[];
  129. }
  130. export const builder = (yargs: Argv) => yargs
  131. .option('typedocJsonPath', {
  132. type: 'string',
  133. alias: 't',
  134. });
  135. const generate = async (args: GenerateArgs) => {
  136. const {
  137. typedocJsonPath = resolve(process.cwd(), 'typedoc.json'),
  138. } = args;
  139. try {
  140. await ensureTypedocJson(typedocJsonPath);
  141. } catch {
  142. return GenerateReturnCode.NO_TYPEDOC_JSON;
  143. }
  144. try {
  145. await generateTypedocData();
  146. } catch {
  147. return GenerateReturnCode.COULD_NOT_GENERATE_TYPEDOC_DATA;
  148. }
  149. try {
  150. await produceGroupings();
  151. } catch {
  152. return GenerateReturnCode.COULD_NOT_PRODUCE_GROUPINGS;
  153. }
  154. try {
  155. await linkComponents();
  156. } catch {
  157. return GenerateReturnCode.COULD_NOT_GENERATE_PAGES;
  158. }
  159. return GenerateReturnCode.SUCCESS;
  160. };
  161. export default generate;