-
Notifications
You must be signed in to change notification settings - Fork 30
/
class.ts
128 lines (112 loc) · 3.31 KB
/
class.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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
import d from 'debug';
import path from 'path';
import { TsGenConfig, TsHelperConfig } from '..';
import * as utils from '../utils';
const debug = d('egg-ts-helper#generators_class');
export default function ClassGenerator(config: TsGenConfig, baseConfig: TsHelperConfig) {
const fileList = config.fileList;
const dist = path.resolve(config.dtsDir, config.distName);
debug('file list : %o', fileList);
if (!fileList.length) {
return { dist };
}
// using to compose import code
let importStr = '';
// using to create interface mapping
const interfaceMap: PlainObject = {};
fileList.forEach(f => {
const { props, moduleName: sModuleName } = utils.getModuleObjByPath(f);
const moduleName = `Export${sModuleName}`;
const importContext = utils.getImportStr(
config.dtsDir,
path.join(config.dir, f),
moduleName,
);
importStr += `${importContext}\n`;
// create mapping
let collector = interfaceMap;
while (props.length) {
const name = utils.camelProp(
props.shift() as string,
config.caseStyle || baseConfig.caseStyle,
);
if (!props.length) {
collector[name] = moduleName;
} else {
collector = collector[name] = typeof collector[name] === 'object' ? collector[name] : Object.create(Object.prototype, {
parentModuleName: {
value: typeof collector[name] === 'string' ? collector[name] : undefined,
},
});
}
}
});
// interface name
const interfaceName = config.interface || `T_${config.name.replace(/[\.\-]/g, '_')}`;
// add mount interface
let declareInterface;
if (config.declareTo) {
const interfaceList: string[] = config.declareTo.split('.');
declareInterface = composeInterface(
interfaceList.slice(1).concat(interfaceName),
interfaceList[0],
undefined,
' ',
);
}
return {
dist,
content:
`${importStr}\n` +
`declare module '${config.framework || baseConfig.framework}' {\n` +
(declareInterface ? `${declareInterface}\n` : '') +
composeInterface(
interfaceMap,
interfaceName,
utils.strToFn(config.interfaceHandle),
' ',
) +
'}\n',
};
}
ClassGenerator.defaultConfig = {
distName: 'index.d.ts',
};
// composing all the interface
function composeInterface(
obj: PlainObject | string[],
wrapInterface?: string,
preHandle?: (v: string) => string,
indent?: string,
) {
let prev = '';
let mid = '';
let after = '';
indent = indent || '';
if (wrapInterface) {
prev = `${indent}interface ${wrapInterface} {\n`;
after = `${indent}}\n`;
indent += ' ';
}
// compose array to object
// ['abc', 'bbc', 'ccc'] => { abc: { bbc: 'ccc' } }
if (Array.isArray(obj)) {
let curr: any = obj.pop();
while (obj.length) {
curr = { [obj.pop()!]: curr };
}
obj = curr;
}
Object.keys(obj).forEach(key => {
const val = obj[key];
if (typeof val === 'string') {
mid += `${indent + key}: ${preHandle ? preHandle(val) : val};\n`;
} else {
const newVal = composeInterface(val, undefined, preHandle, indent + ' ');
if (newVal) {
mid += `${indent + key}: ${val.parentModuleName ? `${val.parentModuleName} & ` : ''}{\n${newVal + indent}}\n`;
}
}
});
return `${prev}${mid}${after}`;
}