bio-dts 0.3.0 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/bin/cmd.js +37 -12
- package/lib/post-transform.js +202 -43
- package/package.json +4 -4
package/bin/cmd.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
import
|
|
3
|
+
import Module from 'node:module';
|
|
4
4
|
|
|
5
5
|
import glob from 'tiny-glob';
|
|
6
6
|
|
|
@@ -10,6 +10,9 @@ import fs from 'node:fs';
|
|
|
10
10
|
import generateTypes from '../lib/generate-types.js';
|
|
11
11
|
|
|
12
12
|
async function run() {
|
|
13
|
+
|
|
14
|
+
const ts = getTypescript();
|
|
15
|
+
|
|
13
16
|
const args = process.argv.slice(2);
|
|
14
17
|
|
|
15
18
|
const {
|
|
@@ -44,18 +47,12 @@ async function run() {
|
|
|
44
47
|
|
|
45
48
|
for (const fileName of fileNames) {
|
|
46
49
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
const globbedFiles = await glob(globPattern, { cwd: fileName, filesOnly: true });
|
|
51
|
-
|
|
52
|
-
files.push(...globbedFiles.map(f => path.join(fileName, f)));
|
|
53
|
-
} else {
|
|
54
|
-
files.push(fileName);
|
|
55
|
-
}
|
|
56
|
-
} catch (err) {
|
|
50
|
+
if (isDir(fileName)) {
|
|
51
|
+
const globbedFiles = await glob(globPattern, { cwd: fileName, filesOnly: true });
|
|
57
52
|
|
|
58
|
-
|
|
53
|
+
files.push(...globbedFiles.map(f => path.join(fileName, f)));
|
|
54
|
+
} else {
|
|
55
|
+
files.push(fileName);
|
|
59
56
|
}
|
|
60
57
|
}
|
|
61
58
|
|
|
@@ -72,6 +69,34 @@ async function run() {
|
|
|
72
69
|
console.log('Done.');
|
|
73
70
|
}
|
|
74
71
|
|
|
72
|
+
function isDir(fileName) {
|
|
73
|
+
|
|
74
|
+
try {
|
|
75
|
+
return fs.statSync(fileName).isDirectory();
|
|
76
|
+
} catch (err) {
|
|
77
|
+
|
|
78
|
+
// ignore
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
function getTypescript() {
|
|
84
|
+
|
|
85
|
+
const cwd = process.cwd();
|
|
86
|
+
|
|
87
|
+
const createRequire = Module.createRequire || Module.createRequireFromPath;
|
|
88
|
+
|
|
89
|
+
const requireLocal = createRequire(
|
|
90
|
+
path.join(cwd, '__placeholder__.js')
|
|
91
|
+
);
|
|
92
|
+
|
|
93
|
+
try {
|
|
94
|
+
return requireLocal('typescript');
|
|
95
|
+
} catch (err) {
|
|
96
|
+
throw new Error(`failed to load <typescript> from <${ cwd }>`);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
|
|
75
100
|
run().catch(err => {
|
|
76
101
|
console.error(err);
|
|
77
102
|
|
package/lib/post-transform.js
CHANGED
|
@@ -45,73 +45,232 @@ export default function transform(src) {
|
|
|
45
45
|
return false;
|
|
46
46
|
}
|
|
47
47
|
|
|
48
|
-
|
|
48
|
+
function keepCommentParams(commentPath, params) {
|
|
49
49
|
|
|
50
|
-
const
|
|
51
|
-
value
|
|
52
|
-
} = path;
|
|
50
|
+
const replacements = [];
|
|
53
51
|
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
52
|
+
const comment = commentPath.value;
|
|
53
|
+
|
|
54
|
+
const doc = comment.value.replace(/\n\s+/g, '\n ');
|
|
55
|
+
const tags = parseJSDoc(doc);
|
|
56
|
+
|
|
57
|
+
for (const tag of tags) {
|
|
58
|
+
|
|
59
|
+
// remove param not mentioned anymore
|
|
60
|
+
if (tag.name === 'param' && params.every(p => p.name !== tag.param.name)) {
|
|
61
|
+
replacements.push([ { start: tag.start - 4, end: tag.end } ]);
|
|
62
|
+
|
|
63
|
+
continue;
|
|
64
|
+
}
|
|
57
65
|
}
|
|
58
66
|
|
|
59
|
-
|
|
67
|
+
const newDoc = replacements.slice().reverse().reduce((newDoc, r) => {
|
|
60
68
|
|
|
61
|
-
|
|
62
|
-
//
|
|
63
|
-
// * @typedef
|
|
64
|
-
// * @class
|
|
65
|
-
// * @constructor
|
|
66
|
-
// * @template
|
|
67
|
-
// * @method
|
|
69
|
+
const [ { start, end }, replacement = '' ] = r;
|
|
68
70
|
|
|
69
|
-
|
|
71
|
+
return replaceJSDoc(newDoc, { start, end }, replacement);
|
|
72
|
+
}, doc);
|
|
70
73
|
|
|
71
|
-
|
|
74
|
+
const builder = {
|
|
75
|
+
'CommentBlock': b.commentBlock,
|
|
76
|
+
'CommentLine': b.commentLine
|
|
77
|
+
}[comment.type];
|
|
72
78
|
|
|
73
|
-
|
|
79
|
+
return cleanComment(builder.from({
|
|
80
|
+
...comment,
|
|
81
|
+
value: newDoc
|
|
82
|
+
}));
|
|
83
|
+
}
|
|
74
84
|
|
|
75
|
-
|
|
85
|
+
function fixOptionalArgsMethods(nodePath) {
|
|
76
86
|
|
|
77
|
-
|
|
78
|
-
|
|
87
|
+
const {
|
|
88
|
+
value: node
|
|
89
|
+
} = nodePath;
|
|
79
90
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
91
|
+
if (node.type !== 'TSDeclareMethod' && node.type !== 'TSDeclareFunction') {
|
|
92
|
+
return;
|
|
93
|
+
}
|
|
83
94
|
|
|
84
|
-
|
|
85
|
-
|
|
95
|
+
const hostPath = nodePath.parentPath.value.type === 'ExportNamedDeclaration'
|
|
96
|
+
? nodePath.parentPath
|
|
97
|
+
: nodePath;
|
|
86
98
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
99
|
+
const {
|
|
100
|
+
variations
|
|
101
|
+
} = node.params.slice().reverse().reduce((res, param) => {
|
|
102
|
+
|
|
103
|
+
let {
|
|
104
|
+
required,
|
|
105
|
+
variations
|
|
106
|
+
} = res;
|
|
107
|
+
|
|
108
|
+
// required before optional
|
|
109
|
+
if (param.optional && required) {
|
|
110
|
+
variations = [
|
|
111
|
+
...variations.map(v => v.slice()),
|
|
112
|
+
...variations.map(v => v.slice())
|
|
113
|
+
];
|
|
114
|
+
|
|
115
|
+
variations.forEach((variation, idx) => {
|
|
116
|
+
|
|
117
|
+
if (idx < variations.length / 2) {
|
|
118
|
+
variation.push(b.identifier.from({
|
|
119
|
+
...param,
|
|
120
|
+
optional: false
|
|
121
|
+
}));
|
|
122
|
+
}
|
|
123
|
+
});
|
|
124
|
+
} else {
|
|
90
125
|
|
|
91
|
-
if (
|
|
92
|
-
|
|
126
|
+
if (!param.optional) {
|
|
127
|
+
required = true;
|
|
93
128
|
}
|
|
129
|
+
|
|
130
|
+
variations.forEach((variation) => {
|
|
131
|
+
const builder = {
|
|
132
|
+
'RestElement': b.restElement,
|
|
133
|
+
'Identifier': b.identifier
|
|
134
|
+
}[param.type];
|
|
135
|
+
|
|
136
|
+
variation.push(builder.from(param));
|
|
137
|
+
});
|
|
94
138
|
}
|
|
95
139
|
|
|
96
|
-
|
|
140
|
+
return {
|
|
141
|
+
required,
|
|
142
|
+
variations
|
|
143
|
+
};
|
|
144
|
+
}, {
|
|
145
|
+
variations: [
|
|
146
|
+
[]
|
|
147
|
+
],
|
|
148
|
+
required: false
|
|
149
|
+
});
|
|
150
|
+
|
|
151
|
+
if (variations.length === 1) {
|
|
152
|
+
return;
|
|
153
|
+
}
|
|
97
154
|
|
|
98
|
-
|
|
155
|
+
const commentPaths = hostPath.get('comments');
|
|
99
156
|
|
|
100
|
-
|
|
101
|
-
|
|
157
|
+
// last comment is significant
|
|
158
|
+
const commentPath = commentPaths?.value && commentPaths.get(commentPaths.value.length - 1) || { value: null };
|
|
102
159
|
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
160
|
+
const replacements = variations.slice().reverse().map(variation => {
|
|
161
|
+
|
|
162
|
+
const builder = {
|
|
163
|
+
'TSDeclareFunction': b.tsDeclareFunction,
|
|
164
|
+
'TSDeclareMethod': b.tsDeclareMethod
|
|
165
|
+
}[node.type];
|
|
166
|
+
|
|
167
|
+
const variationComments = commentPath.value ? [ keepCommentParams(commentPath, variation) ] : [ ];
|
|
168
|
+
|
|
169
|
+
const newNode = builder.from({
|
|
170
|
+
...node,
|
|
171
|
+
params: variation.slice().reverse(),
|
|
172
|
+
comments: hostPath === nodePath ? variationComments : []
|
|
173
|
+
});
|
|
174
|
+
|
|
175
|
+
return (
|
|
176
|
+
hostPath === nodePath
|
|
177
|
+
? newNode
|
|
178
|
+
: b.exportNamedDeclaration.from({
|
|
179
|
+
...hostPath.value,
|
|
180
|
+
declaration: newNode,
|
|
181
|
+
comments: variationComments
|
|
182
|
+
})
|
|
183
|
+
);
|
|
184
|
+
});
|
|
185
|
+
|
|
186
|
+
replace(hostPath, ...replacements);
|
|
187
|
+
|
|
188
|
+
return replacements;
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
|
|
192
|
+
function cleanComment(comment) {
|
|
193
|
+
|
|
194
|
+
const replacements = [];
|
|
195
|
+
|
|
196
|
+
const doc = comment.value.replace(/\n\s+/g, '\n ');
|
|
197
|
+
const tags = parseJSDoc(doc);
|
|
198
|
+
|
|
199
|
+
for (const tag of tags) {
|
|
200
|
+
|
|
201
|
+
// remove full line including the non-TS tag
|
|
202
|
+
if (/class|constructor|template|method|typedef/.test(tag.name)) {
|
|
203
|
+
replacements.push([ { start: tag.start - 4, end: tag.end } ]);
|
|
204
|
+
|
|
205
|
+
continue;
|
|
206
|
+
}
|
|
207
|
+
|
|
208
|
+
if (tag.type) {
|
|
209
|
+
replacements.push([ { start: tag.type.start - 1, end: tag.type.end }, '' ]);
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
if (tag.param) {
|
|
213
|
+
|
|
214
|
+
// [foo=10] => foo
|
|
215
|
+
replacements.push([ tag.param, tag.param.name ]);
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
const newDoc = replacements.slice().reverse().reduce((newDoc, r) => {
|
|
220
|
+
|
|
221
|
+
const [ { start, end }, replacement = '' ] = r;
|
|
222
|
+
|
|
223
|
+
return replaceJSDoc(newDoc, { start, end }, replacement);
|
|
224
|
+
}, doc);
|
|
225
|
+
|
|
226
|
+
// remove entirely, if empty
|
|
227
|
+
if (!newDoc.replace(/[/*\s]/g, '')) {
|
|
228
|
+
return null;
|
|
229
|
+
} else {
|
|
230
|
+
return b.commentBlock.from({
|
|
231
|
+
type: 'CommentBlock',
|
|
232
|
+
leading: true,
|
|
233
|
+
value: newDoc
|
|
234
|
+
});
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
/**
|
|
239
|
+
* @param {import('./util.js').Path} nodePath
|
|
240
|
+
*/
|
|
241
|
+
function cleanComments(nodePath) {
|
|
242
|
+
|
|
243
|
+
// clean JSDoc comments: remove annotation, fixup type parameters
|
|
244
|
+
const comments = nodePath.get('comments') || { value: [] };
|
|
245
|
+
|
|
246
|
+
for (const key of keys(comments.value || []).reverse()) {
|
|
247
|
+
const comment = comments.get(key);
|
|
248
|
+
|
|
249
|
+
const newComment = cleanComment(comment.value);
|
|
250
|
+
if (newComment) {
|
|
251
|
+
replace(comment, newComment);
|
|
106
252
|
} else {
|
|
107
|
-
replace(comment
|
|
108
|
-
type: 'CommentBlock',
|
|
109
|
-
leading: true,
|
|
110
|
-
value: newDoc
|
|
111
|
-
}));
|
|
253
|
+
replace(comment);
|
|
112
254
|
}
|
|
113
255
|
}
|
|
256
|
+
}
|
|
257
|
+
|
|
258
|
+
traverse(body, function(path) {
|
|
259
|
+
|
|
260
|
+
const {
|
|
261
|
+
value
|
|
262
|
+
} = path;
|
|
263
|
+
|
|
264
|
+
// filter private members
|
|
265
|
+
if (!isPublic(value)) {
|
|
266
|
+
return replace(path);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
if (fixOptionalArgsMethods(path)) {
|
|
270
|
+
return false;
|
|
271
|
+
}
|
|
114
272
|
|
|
273
|
+
cleanComments(path);
|
|
115
274
|
});
|
|
116
275
|
|
|
117
276
|
for (const [ path, args ] of replacements) {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "bio-dts",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.4.0",
|
|
4
4
|
"description": "Generate sane and clean types from JavaScript sources",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "index.js",
|
|
@@ -16,14 +16,14 @@
|
|
|
16
16
|
"dependencies": {
|
|
17
17
|
"@babel/parser": "^7.21.2",
|
|
18
18
|
"recast": "^0.22.0",
|
|
19
|
-
"tiny-glob": "^0.2.9"
|
|
20
|
-
"typescript": "^4.9.5"
|
|
19
|
+
"tiny-glob": "^0.2.9"
|
|
21
20
|
},
|
|
22
21
|
"devDependencies": {
|
|
23
22
|
"chai": "^4.3.7",
|
|
24
23
|
"eslint": "^8.36.0",
|
|
25
24
|
"eslint-plugin-bpmn-io": "^1.0.0",
|
|
26
|
-
"mocha": "^10.2.0"
|
|
25
|
+
"mocha": "^10.2.0",
|
|
26
|
+
"typescript": "^5.0.2"
|
|
27
27
|
},
|
|
28
28
|
"files": [
|
|
29
29
|
"bin",
|