-
Notifications
You must be signed in to change notification settings - Fork 0
/
index.ts
71 lines (66 loc) · 2.15 KB
/
index.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
/**
* @module dts-merge-import
*/
// eslint-disable-next-line import/no-extraneous-dependencies
import ts from 'typescript';
import type {
Node, SourceFile, TransformerFactory,
} from 'typescript';
export const unblockModuleDot: TransformerFactory<SourceFile> = (context) => (rootNode) => {
function visit(node: Node): ts.VisitResult<ts.Node> {
if (ts.isModuleDeclaration(node)) {
if (node.name.text !== '.') {
return node;
}
if (node.body == null) {
return [];
}
if (ts.isModuleBlock(node.body)) {
// eslint-disable-next-line prefer-destructuring
const body: ts.ModuleBlock = node.body;
return body.statements;
}
}
return node;
}
return ts.visitEachChild(rootNode, visit, context) as SourceFile;
};
function mergeMember(factory: ts.NodeFactory, list: ts.InterfaceDeclaration[]) {
if (list.length < 2) {
return list[0];
}
const target = list[0];
const members = list.reduce((prev, curr) => [...prev, ...curr.members], [] as ts.TypeElement[]);
return factory.updateInterfaceDeclaration(
target,
target.modifiers,
target.name,
target.typeParameters,
target.heritageClauses,
members,
);
}
export const mergeImport: TransformerFactory<SourceFile> = (context) => (rootNode) => {
const interfaceMap: Record<string, ts.InterfaceDeclaration[]> = {};
const others: ts.Statement[] = [];
rootNode.statements.forEach((stmt) => {
if (ts.isInterfaceDeclaration(stmt)) {
const name = stmt.name.text;
if (interfaceMap[name]) {
interfaceMap[name].push(stmt);
} else {
interfaceMap[name] = [stmt];
}
} else {
others.push(stmt);
}
});
const interfaces = Object.values(interfaceMap).map((it) => mergeMember(context.factory, it));
return context.factory.updateSourceFile(rootNode, [...interfaces, ...others], true);
};
export function transformString(text: string): string {
const sourceFile = ts.createSourceFile('', text, ts.ScriptTarget.ESNext);
const result = ts.transform(sourceFile, [unblockModuleDot, mergeImport]);
result.dispose();
return ts.createPrinter().printFile(result.transformed[0]);
}