|
- import {
- cp,
- readFile,
- rm,
- stat,
- writeFile,
- symlink,
- } from 'fs/promises';
- import {
- dirname,
- resolve,
- basename,
- extname,
- join,
- } from 'path';
- import { Argv } from 'yargs';
- import { mkdirp } from 'mkdirp';
- import { PackageData } from '../utils/data';
- import { CommandError } from '../utils/error';
- import { useBasePath } from '../mixins/base-path';
- import { useInternalPath } from '../mixins/internal-path';
-
- export enum GenerateReturnCode {
- SUCCESS = 0,
- COULD_NOT_GENERATE_PAGES = -3,
- }
-
- const cleanContent = async (internalPath: string) => {
- try {
- const destCwd = resolve(internalPath, '.amanuensis', 'next', 'src');
- await rm(resolve(destCwd, 'content'), { recursive: true });
- } catch {
- // noop
- }
- };
-
- const resetPages = async (internalPath: string) => {
- try {
- const defaultCwd = resolve(internalPath, 'src', 'next');
- const destCwd = resolve(internalPath, '.amanuensis', 'next', 'src');
- await rm(resolve(destCwd, 'pages'), { recursive: true });
- await cp(resolve(defaultCwd, 'pages'), resolve(destCwd, 'pages'), { recursive: true });
- } catch {
- // noop
- }
- };
-
- const linkComponents = async (basePath: string, internalPath: string) => {
- process.stdout.write('Linking components...\n');
-
- const customComponentDir = resolve(basePath, '.amanuensis');
- const defaultComponentDir = resolve(internalPath, 'src', 'next');
- const destCwd = resolve(internalPath, '.amanuensis', 'next', 'src');
-
- // todo merge package.json
-
- const componentsList = [
- 'next/src/components/Wrapper.tsx',
- 'next/src/components/PageLayout.tsx',
- 'next/src/components/theme.ts',
- 'next/src/components/postcss.config.js',
- 'next/src/components/tailwind.config.js',
- ];
-
- await Promise.all(componentsList.map(async (componentPath) => {
- const destPath = resolve(destCwd, componentPath);
- let componentDir = customComponentDir;
-
- try {
- await stat(resolve(componentDir, componentPath));
- } catch (errRaw) {
- const err = errRaw as NodeJS.ErrnoException;
- if (err.code === 'ENOENT') {
- componentDir = defaultComponentDir;
- }
- }
-
- await mkdirp(dirname(destPath));
- await cp(
- resolve(componentDir, componentPath),
- destPath,
- );
- process.stdout.write(`Linked ${componentPath}\n`);
- }));
-
- process.stdout.write('done\n');
- };
-
- const pageContent = (preambleImport: string) => `import {NextPage} from 'next';
- import {ComponentContext} from '@/contexts/Component';
- import {Wrapper} from '@/components/Wrapper';
- import {PreambleContext} from '@/contexts/Preamble';
- import Preamble from '${preambleImport}';
- import {PageLayout} from '@/components/PageLayout';
-
- const IndexPage: NextPage = () => {
- return (
- <PreambleContext.Provider value={Preamble}>
- <Wrapper>
- <PageLayout />
- </Wrapper>
- </PreambleContext.Provider>
- );
- };
-
- export default IndexPage;
- `;
-
- const writeContent = async (basePath: string, internalPath: string) => {
- const destCwd = resolve(internalPath, '.amanuensis', 'next', 'src');
- const packagesPath = resolve(internalPath, '.amanuensis', 'packages.json');
-
- const packagesDataJson = await readFile(packagesPath, 'utf-8');
- const packagesData = JSON.parse(packagesDataJson) as PackageData[];
-
- try {
- await Promise.all(packagesData.map(async (pkg) => {
- const packageDir = resolve(basePath, pkg.basePath);
- const packageLinkDir = resolve(internalPath, '.amanuensis', 'next', 'node_modules', pkg.name);
- await mkdirp(dirname(packageLinkDir));
-
- try {
- await symlink(packageDir, packageLinkDir);
- } catch {
- // noop
- }
-
- await mkdirp(resolve(destCwd, 'content', pkg.basePath));
- await mkdirp(resolve(destCwd, 'pages', pkg.basePath));
- await Promise.all(
- pkg.markdown.map(async (m) => {
- const srcPath = resolve(basePath, pkg.basePath, m.filePath);
- const destPath = resolve(destCwd, 'content', pkg.basePath, m.name);
- await cp(srcPath, destPath);
-
- const pageDestPath = resolve(destCwd, 'pages', pkg.basePath, `${basename(m.name, extname(m.name))}.tsx`);
- const preambleImport = `@/${join('content', pkg.basePath, m.name)}`;
-
- await writeFile(pageDestPath, pageContent(preambleImport));
-
- // todo fetch components for display to props and preamble
- // todo fix problem when building with import aliases
- // todo find a way to build with tailwind
- // todo link components to next project (done)
- // todo merge contents of .amanuensis with next project
- }),
- );
- }));
- } catch (errRaw) {
- throw new CommandError(GenerateReturnCode.COULD_NOT_GENERATE_PAGES, 'Could not write inner page file', errRaw as Error);
- }
-
- try {
- const srcPath = resolve(basePath, 'README.md');
- const destPath = resolve(destCwd, 'content', 'index.md');
- await cp(srcPath, destPath);
- } catch (errRaw) {
- throw new CommandError(GenerateReturnCode.COULD_NOT_GENERATE_PAGES, 'Could not write index file', errRaw as Error);
- }
- };
-
- export const description = 'Generate documentation from typedoc.json' as const;
-
- export interface RefreshArgs {
- subcommands?: string[];
- clean?: boolean;
- }
-
- export const builder = (yargs: Argv) => yargs
- .option('clean', {
- alias: 'c',
- type: 'boolean',
- description: 'Reset generated content',
- default: true,
- });
-
- const refresh = async (args: RefreshArgs) => {
- try {
- const internalPath = await useInternalPath();
- const { clean = true } = args;
-
- if (clean) {
- await cleanContent(internalPath);
- await resetPages(internalPath);
- }
-
- const basePath = await useBasePath();
- await linkComponents(basePath, internalPath);
- await writeContent(basePath, internalPath);
- } catch (errRaw) {
- const err = errRaw as CommandError;
- process.stderr.write(`${err.message}\n`);
- return err.exitCode;
- }
-
- return GenerateReturnCode.SUCCESS;
- };
-
- export default refresh;
|