This repository has been archived by the owner on Dec 15, 2023. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 100
/
Copy pathrun.ts
172 lines (153 loc) · 6.74 KB
/
run.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
#!/usr/bin/env node
import * as fs from 'fs';
import * as path from 'path';
import * as yargs from 'yargs';
import * as guess from './';
import writeDefinitelyTypedPackage from './definitely-typed';
const templatesDirectory = path.join(__dirname, "..", "..", "templates");
interface Options {
module?: string;
expression?: string;
'expression-file': string;
identifier?: string;
template?: string;
name?: string;
file?: string | boolean;
dt?: string | boolean;
stdout?: boolean;
overwrite?: boolean;
version?: boolean;
}
const args = yargs
.alias('m', 'module')
.alias('i', 'identifier')
.alias('e', 'expression')
.alias('n', 'name')
.alias('f', 'file')
.alias('d', 'dt')
.alias('s', 'stdout')
.alias('o', 'overwrite')
.alias('t', 'template')
.alias('v', 'version')
.argv as any as Options;
class ArgsError extends Error {
constructor(public argsError: string) {
super();
this.name = 'ArgsError';
this.message = argsError;
Object.setPrototypeOf(this, ArgsError.prototype);
}
}
let result: string | undefined;
try {
if (args.version) {
console.log(require("../../package.json").version);
process.exit(0);
}
if (+!!args.dt + +!!args.file + +!!args.stdout > 1) {
throw new ArgsError('Cannot specify more than one output mode');
}
if (+!!args.identifier + +!!args.expression + +!!args.module + +!!args['expression-file'] + +!!args.template
!== 1) {
throw new ArgsError('Must specify exactly one input');
}
if (typeof args.name === 'boolean') throw new ArgsError('Must specify a value for "--name"');
if (typeof args.identifier === 'boolean') throw new ArgsError('Must specify a value for "--identifier"');
if (typeof args.module === 'boolean') throw new ArgsError('Must specify a value for "--module"');
if (args.overwrite !== undefined && args.overwrite !== true)
throw new ArgsError('--overwrite does not accept an argument');
let name: string;
if (args.module) {
if (args.name) throw new ArgsError('Cannot use --name with --module');
name = args.module;
(module as any).paths.unshift(process.cwd() + '/node_modules');
result = guess.generateModuleDeclarationFile(args.module, require(args.module));
} else if (args.expression) {
name = args.name || 'dts_gen_expr';
result = guess.generateIdentifierDeclarationFile(name, eval(args.expression));
} else if (args['expression-file']) {
if (args.name) throw new ArgsError('Cannot use --name with --expression-file');
const filename = args['expression-file'];
name = path.basename(filename, path.extname(filename)).replace(/[^A-Za-z0-9]/g, '_');
(module as any).paths.unshift(process.cwd() + '/node_modules');
const fileContent = fs.readFileSync(filename, "utf-8");
result = guess.generateIdentifierDeclarationFile(name, eval(fileContent));
} else if (args.identifier) {
if (args.name) throw new ArgsError('Cannot use --name with --identifier');
if (args.module || args.expression) throw new ArgsError('Cannot specify more than one input');
name = args.identifier;
result = guess.generateIdentifierDeclarationFile(args.identifier, eval(args.identifier));
} else if (args.template) {
if (!args.name) throw new ArgsError('Needs a name');
name = args.name;
if (args.module || args.expression) throw new ArgsError('Cannot mix --template with --module or --expression');
result = getTemplate(args.template);
} else {
throw new Error('Internal error, please log a bug with the commandline you specified');
}
if (args.dt) {
writeDefinitelyTypedPackage(result, name, !!args.overwrite);
} else if (args.stdout) {
console.log(result);
} else {
let filename =
typeof args.file === 'boolean' || args.file === undefined ? name + '.d.ts' : args.file;
if (!filename.endsWith('.d.ts')) {
filename = filename + '.d.ts';
}
if (!args.overwrite && fs.existsSync(filename)) {
console.error(`File ${filename} already exists and --overwrite was not specified; exiting.`);
process.exit(2);
}
fs.writeFileSync(filename, prependOurHeader(result), 'utf-8');
console.log(`Wrote ${result.split(/\r\n|\r|\n/).length} lines to ${filename}.`);
}
} catch (e) {
if (e instanceof ArgsError) {
console.error('Invalid arguments: ' + e.argsError);
console.log('');
printHelp();
process.exit(1);
} else if (e.code === 'MODULE_NOT_FOUND') {
console.log(`Couldn't load module "${args.module}". ` +
`Please install it globally (npm install -g ${args.module}) and try again.`);
process.exit(1);
} else {
console.log('Unexpected crash! Please log a bug with the commandline you specified.');
throw e;
}
}
function printHelp() {
console.log('Usage: dts-gen input [settings] [output]');
console.log('');
console.log('Input Options:');
console.log(' -m[odule] fs The "fs" node module (must be installed)');
console.log(' -i[dentifier] Math The global variable "Math"');
console.log(' -e[xpression] "new C()" The expression "new C()"');
console.log(' -t[emplate] module Name of a template. Templates are:');
console.log(` ${allTemplateNames()}`);
console.log('');
console.log('Settings:');
console.log(' -n[ame] n The name to emit when generating for an expression');
console.log('');
console.log('Output Options:');
console.log(' -f[ile] [filename.d.ts] Write to a file (default)');
console.log(' -d[t] [dirName] Create a folder suitable for DefinitelyTyped');
console.log(' -s[tdout] Write to stdout');
console.log(' -o[verwrite] Allow overwriting files');
console.log('');
console.log('Example: dts-gen -m fs --stdout');
}
function prependOurHeader(result: string) {
return `/** Declaration file generated by dts-gen */\r\n\r\n` + result;
}
function getTemplate(templateName: string): string {
try {
return fs.readFileSync(path.join(templatesDirectory, templateName + ".d.ts"), "utf-8");
} catch (e) {
throw new ArgsError(`Could not read template '${templateName}'. Expected one of:\n${allTemplateNames()}`);
}
}
function allTemplateNames(): string {
return fs.readdirSync(templatesDirectory).map(t => t.slice(0, t.length - ".d.ts".length)).join(", ");
}