|
- import { readFile } from 'fs/promises';
- import { dirname, basename, resolve } from 'path';
- import { glob } from 'glob';
- import { minimatch } from 'minimatch';
-
- export interface AmanuensisConfig {
- package: {
- searchPatterns: string | string[];
- classifications: Record<string, Record<string, string | string[]>>;
- }
- }
-
- interface TypedocDataTextNode {
- kind: 'text';
- text: string;
- }
-
- interface TypedocDataInlineTagNode {
- kind: 'inline-tag';
- tag: string;
- text: string;
- target: number;
- tsLinkText: string;
- }
-
- interface SymbolIdMapEntry {
- sourceFileName: string;
- qualifiedName: string;
- }
-
- type TypedocDataNode = TypedocDataTextNode | TypedocDataInlineTagNode;
-
- export interface TypedocData {
- readme: TypedocDataNode[];
- symbolIdMap: Record<string, SymbolIdMapEntry>;
- }
-
- export interface PackageData {
- name: string;
- packageJson: Record<string, unknown>;
- basePath: string;
- markdown: { name: string; filePath: string; content: string }[];
- classifications: Record<string, string | undefined>;
- }
-
- export const getPackages = async (configPath: string, cwd: string): Promise<PackageData[]> => {
- const configString = await readFile(configPath, 'utf-8');
- const config = JSON.parse(configString) as AmanuensisConfig;
- const searchPatternsRaw = config.package.searchPatterns;
- const searchPatterns = Array.isArray(searchPatternsRaw) ? searchPatternsRaw : [searchPatternsRaw];
- const patternPackagePaths = await Promise.all(
- searchPatterns.map(async (searchPattern) => glob(
- searchPattern === 'package.json' || searchPattern.endsWith('/package.json')
- ? searchPattern
- : `${searchPattern}/package.json`,
- {
- cwd,
- ignore: ['**/node_modules/**'],
- },
- )),
- );
- const packagePaths = patternPackagePaths.flat();
- const markdownFilePathsRaw = await glob(
- '**/*.{md,mdx}',
- {
- cwd,
- ignore: ['**/node_modules/**'],
- },
- );
- const markdownFilePaths = markdownFilePathsRaw.map((p) => resolve(cwd, p));
-
- const readPackages = await Promise.all(
- packagePaths.map(async (packagePathRaw) => {
- const absolutePackagePath = resolve(cwd, packagePathRaw);
- const packageString = await readFile(absolutePackagePath, 'utf-8');
- const basePath = dirname(absolutePackagePath);
- const packageJson = JSON.parse(packageString) as { name: string };
- const classifications = Object.fromEntries(
- Object.entries(config.package.classifications)
- .map(([classification, c]) => {
- const [thisClassifications] = Object.entries(c)
- .find(([, globRaw]) => {
- const globs = Array.isArray(globRaw) ? globRaw : [globRaw];
- return globs.some((g) => minimatch(packageJson.name, g));
- }) ?? [];
- return [classification, thisClassifications] as const;
- }),
- );
-
- const markdownFiles = markdownFilePaths.filter((markdownFilePath) => (
- markdownFilePath.startsWith(basePath)
- ));
-
- const markdown = await Promise.all(
- markdownFiles.map(async (markdownFilePath) => {
- const content = await readFile(markdownFilePath, 'utf-8');
- const filePath = markdownFilePath.slice(basePath.length + 1);
- const file = filePath.split('/').at(-1) ?? '';
- const name = filePath === 'README.md' ? 'index.md' : basename(file);
-
- return {
- name,
- filePath,
- content,
- };
- }),
- );
-
- return {
- name: packageJson.name,
- packageJson,
- basePath: basePath.slice(cwd.length + 1),
- markdown,
- classifications,
- };
- }),
- );
-
- return readPackages.sort((a, b) => a.name.localeCompare(b.name));
- };
-
- export const getFileSources = async (cwd = process.cwd()) => {
- const typedocDataJsonPath = resolve(cwd, '.amanuensis', 'data.json');
- const typedocDataJson = await readFile(typedocDataJsonPath, 'utf-8');
- const typedocData = JSON.parse(typedocDataJson) as TypedocData;
- const symbolIdMapEntries = Object.values(typedocData.symbolIdMap);
- const firstPartySources = symbolIdMapEntries.filter(
- ({ sourceFileName }) => !sourceFileName.startsWith('node_modules'),
- );
- const firstPartySourceFiles = firstPartySources.map(({ sourceFileName }) => sourceFileName);
- return Array.from(new Set(firstPartySourceFiles));
- };
|