You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
tailchat/client/packages/plugin-declaration-generator/src/index.ts

91 lines
2.3 KiB
TypeScript

import { parse, ParserPlugin } from '@babel/parser';
import traverse from '@babel/traverse';
import generate from '@babel/generator';
import template from '@babel/template';
import type { Comment } from '@babel/types';
import { program, isFunctionDeclaration } from '@babel/types';
import fs from 'fs-extra';
import _ from 'lodash';
export * from './tsgenerator';
export * from './parser';
const babelPlugins: ParserPlugin[] = ['jsx', 'typescript'];
const buildNamedExport = template('export function %%name%%(): any', {
plugins: babelPlugins,
});
interface Options {
entryPath: string;
// targetPath: string; // TODO
}
export async function generateFunctionDeclare(options: Options) {
const sourcecode = await fs.readFile(options.entryPath, 'utf8');
const exported = getSourceCodeExportedFunction(sourcecode);
const astList = exported.map((e) => {
return buildNamedExport({
name: e.name,
});
});
const code = generate(program(_.flatten(astList))).code;
return code;
}
interface ExportedItem {
name: string;
comments?: string;
}
function getSourceCodeExportedFunction(sourcecode: string): ExportedItem[] {
const ast = parse(sourcecode, {
sourceType: 'module',
plugins: babelPlugins,
});
const exported: ExportedItem[] = [];
traverse(ast, {
ExportNamedDeclaration({ node }) {
if (node.declaration) {
if (isFunctionDeclaration(node.declaration)) {
const name = node.declaration.id?.name;
if (typeof name === 'string') {
exported.push({
name,
comments: getCommentStr(node.leadingComments),
});
}
}
} else {
const names = node.specifiers.map((s) => {
const exported = s.exported;
if (exported.type === 'Identifier') {
return {
name: exported.name,
comments: getCommentStr(node.leadingComments),
};
} else {
return null;
}
});
exported.push(...names.filter((n): n is any => !!n));
}
},
});
return exported;
}
function getCommentStr(
comments: Comment[] | null | undefined
): string | undefined {
if (!comments) {
return undefined;
}
return comments.map((c) => c.value).join('\n');
}