Skip to content

Commit d8411b5

Browse files
authored
Merge pull request #2 from fabiandev/ts-transform
Transformation API (official TypeScript nightly build)
2 parents 3372e29 + ebc9d7d commit d8411b5

File tree

195 files changed

+88109
-152
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

195 files changed

+88109
-152
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,4 @@ logs
77
pids
88
*.pid
99
*.seed
10+
.tsr

dist/bin/handlers.js

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
"use strict";
2+
const cp = require("child_process");
3+
const path = require("path");
4+
const bus_1 = require("../bus");
5+
const child = cp.fork(path.join(__dirname, './status'));
6+
child.send({ message: 'init' });
7+
child.on('exit', () => {
8+
process.exit();
9+
});
10+
function handleError(error) {
11+
child.send({ message: 'error', payload: error });
12+
}
13+
process.on('uncaughtException', handleError);
14+
process.on('unhandledRejection', handleError);
15+
bus_1.bus.on('error', handleError);
16+
bus_1.bus.on('main.start', (filePaths) => {
17+
child.send({ message: 'start', payload: filePaths.length });
18+
});
19+
bus_1.bus.on('main.done', (filePaths) => {
20+
child.send({ message: 'end' });
21+
});
22+
bus_1.bus.on('transform.file.start', (filePath) => {
23+
child.send({ message: 'fileStart', payload: filePath });
24+
});
25+
bus_1.bus.on('transform.file.readError', (filePath) => {
26+
child.send({ message: 'fileReadError', payload: filePath });
27+
});
28+
bus_1.bus.on('transform.file.done', (filePath) => {
29+
child.send({ message: 'fileEnd', payload: filePath });
30+
});
31+
bus_1.bus.on('write.start', (num) => {
32+
child.send({ message: 'writeStart', payload: num });
33+
});
34+
bus_1.bus.on('write.end', (num) => {
35+
child.send({ message: 'writeEnd', payload: num });
36+
});
37+
bus_1.bus.on('write.file.start', (filePath) => {
38+
child.send({ message: 'fileWriteStart', payload: filePath });
39+
});
40+
bus_1.bus.on('transform.file.done', (filePath) => {
41+
child.send({ message: 'fileWriteEnd', payload: filePath });
42+
});
43+
// process.on('SIGINT', () => {
44+
// child.send({message: 'term'});
45+
// });
46+
//
47+
// process.on('SIGTERM', () => {
48+
// process.stdin.resume();
49+
// child.send({message: 'term'});
50+
// });

dist/bin/index.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
import './handlers';

dist/bin/index.js

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
#!/usr/bin/env node
2+
"use strict";
3+
require("./handlers");
4+
const program = require("commander");
5+
const transform_1 = require("../transform");
6+
const writer_1 = require("../writer");
7+
const pkg = require('../../package.json');
8+
const config = {};
9+
const writerConfig = writer_1.DEFAULT_CONFIG;
10+
let write = false;
11+
function defaultAction() {
12+
const files = program.args.filter((value) => {
13+
return typeof value === 'string';
14+
});
15+
transform_1.default(files)
16+
.then((compilerResult) => {
17+
if (write) {
18+
const writer = new writer_1.Writer(compilerResult);
19+
writer.writeAll();
20+
}
21+
});
22+
}
23+
function setNoAssertConst() {
24+
config.assertConst = true;
25+
}
26+
function setEncoding(encoding) {
27+
config.encoding = encoding;
28+
writerConfig.encoding = encoding;
29+
}
30+
function setWrite(location, base) {
31+
write = true;
32+
writerConfig.writePath = location || writerConfig.writePath;
33+
writerConfig.basePath = base || writerConfig.basePath;
34+
}
35+
program
36+
.version(pkg.version)
37+
.description(`--------- ts-runtime ---------
38+
Inserts runtime type checks and
39+
emits pretty printed TypeScript.
40+
--------------------------------`)
41+
.usage('[options] <file ...>')
42+
.option('-w, --write', 'persist files', setWrite)
43+
.option('-e, --encoding <encoding>', 'set file encoding. defaults to utf8', setEncoding)
44+
.option('--no-assert-const', 'turn off const declaration checks.', setNoAssertConst)
45+
.on('--help', () => {
46+
console.log(' Examples:');
47+
console.log();
48+
console.log(' $ tsr --no-assert-const file.ts');
49+
console.log(' $ tsr --write ./out ./src ./src/file1.ts ./src/file2.ts');
50+
console.log();
51+
});
52+
program.parse(process.argv);
53+
if (!process.argv.slice(2).length) {
54+
program.outputHelp();
55+
}
56+
else {
57+
defaultAction();
58+
}

dist/bin/status.js

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
"use strict";
2+
const path = require("path");
3+
const ora = require("ora");
4+
const chalk = require("chalk");
5+
const symbols = require("log-symbols");
6+
let spinner;
7+
let fileCount = 0;
8+
let processed = 0;
9+
let errors = 0;
10+
process.on('uncaughtException', (error) => {
11+
status.error(error);
12+
});
13+
process.on('unhandledRejection', (reason, p) => {
14+
status.error(new Error(reason));
15+
});
16+
process.on('SIGINT', () => {
17+
status.term();
18+
process.exit();
19+
});
20+
process.on('SIGTERM', () => {
21+
status.term();
22+
process.exit();
23+
});
24+
process.on('message', (data) => {
25+
if (typeof status[data.message] === 'function') {
26+
status[data.message](data.payload);
27+
}
28+
});
29+
const status = {};
30+
status.init = () => {
31+
spinner = null;
32+
fileCount = 0;
33+
processed = 0;
34+
errors = 0;
35+
spinner = ora();
36+
};
37+
status.start = (num) => {
38+
fileCount = num;
39+
spinner.text = chalk.bold(`Got ${num} file${num === 1 ? '' : 's'} to process:`);
40+
spinner.stopAndPersist();
41+
spinner.text = `${processed}/${fileCount}`;
42+
spinner.start();
43+
return spinner;
44+
};
45+
status.end = () => {
46+
if (errors > 0) {
47+
spinner.stopAndPersist({ symbol: symbols.warning, text: chalk.yellow(`All processing finished, but there ${errors === 1 ? 'was' : 'were'} ${errors} error${errors === 1 ? '' : 's'}`) });
48+
}
49+
else {
50+
spinner.succeed(chalk.green('All files have been processed'));
51+
}
52+
process.exit(0);
53+
};
54+
status.term = () => {
55+
spinner.fail(chalk.red('Processing was interrupted'));
56+
};
57+
status.fileStart = (filePath) => {
58+
processed++;
59+
const countStr = chalk.gray(`[${processed}/${fileCount}]`);
60+
spinner.text = `${countStr} Processing ${path.basename(filePath)}`;
61+
};
62+
status.fileEnd = (filePath) => {
63+
const countStr = chalk.gray(`[${processed}/${fileCount}]`);
64+
spinner.succeed(`${countStr} Done processing ${path.basename(filePath)}`);
65+
spinner.start();
66+
};
67+
status.fileFail = (filePath) => {
68+
errors++;
69+
const countStr = chalk.gray(`[${processed}/${fileCount}]`);
70+
spinner.fail(`${countStr} Error processing ${path.basename(filePath)}`);
71+
spinner.start();
72+
};
73+
status.fileReadError = (filePath) => {
74+
errors++;
75+
const countStr = chalk.gray(`[${processed}/${fileCount}]`);
76+
spinner.fail(`${countStr} Could not read ${path.basename(filePath)}`);
77+
spinner.start();
78+
};
79+
status.writeStart = (num) => {
80+
spinner.text = `Writing files`;
81+
};
82+
status.writeEnd = (num) => {
83+
spinner.succeed(`Wrote ${num} files`);
84+
};
85+
status.fileWriteStart = (filePath) => {
86+
};
87+
status.fileWriteEnd = (filePath) => {
88+
};
89+
status.error = (err) => {
90+
errors++;
91+
if (typeof err === 'string') {
92+
spinner.fail(chalk.red(err));
93+
}
94+
if (err instanceof Error) {
95+
spinner.fail(chalk.red(err.message));
96+
}
97+
process.exit();
98+
};

dist/bus.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export { EventBus, bus } from './bus/Bus';

dist/bus.js

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
"use strict";
2+
var Bus_1 = require("./bus/Bus");
3+
exports.EventBus = Bus_1.EventBus;
4+
exports.bus = Bus_1.bus;

dist/bus/Bus.d.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
/// <reference types="node" />
2+
import * as EventEmitter from 'events';
3+
export declare class EventBus extends EventEmitter {
4+
}
5+
export declare const bus: EventBus;
6+
export default bus;

dist/bus/Bus.js

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
"use strict";
2+
const EventEmitter = require("events");
3+
class EventBus extends EventEmitter {
4+
}
5+
exports.EventBus = EventBus;
6+
exports.bus = new EventBus();
7+
Object.defineProperty(exports, "__esModule", { value: true });
8+
exports.default = exports.bus;
File renamed without changes.

dist/compiler.js

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
"use strict";
2+
var Compiler_1 = require("./compiler/Compiler");
3+
exports.Compiler = Compiler_1.Compiler;
4+
var CompilerMode_1 = require("./compiler/CompilerMode");
5+
exports.CompilerMode = CompilerMode_1.CompilerMode;
6+
var default_config_1 = require("./compiler/default_config");
7+
exports.DEFAULT_CONFIG = default_config_1.DEFAULT_CONFIG;

dist/compiler/Compiler.d.ts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import * as ts from 'typescript';
2+
import { Config } from '../config';
3+
import { Transformer } from './transformers';
4+
import CompilerResult from './CompilerResult';
5+
export declare class Compiler {
6+
protected config: Config;
7+
protected transformers: Transformer[];
8+
constructor(config: Config, transformers?: Transformer[]);
9+
process(): Promise<CompilerResult>;
10+
protected onSubstituteNode(context: ts.EmitContext, node: ts.Node): ts.Node;
11+
private transformFile(filePath, transformers);
12+
private visit(node);
13+
private visitChildrenFirst(node);
14+
private visitParentFirst(node);
15+
}
16+
export default Compiler;

dist/compiler/Compiler.js

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
"use strict";
2+
// import * as fs from 'fs';
3+
const path = require("path");
4+
const ts = require("typescript");
5+
const transformers_1 = require("./transformers");
6+
const bus_1 = require("../bus");
7+
const CompilerMode_1 = require("./CompilerMode");
8+
class Compiler {
9+
constructor(config, transformers) {
10+
this.config = config;
11+
this.transformers = [];
12+
const transformersToEnable = transformers || transformers_1.DEFAULT_TRANSFORMERS;
13+
transformers_1.Transformer.DEFAULT_CONFIG = config;
14+
const enabledTtransformers = Object.keys(transformersToEnable)
15+
.map((key) => {
16+
return transformers ?
17+
transformers[key] :
18+
new transformersToEnable[key]();
19+
});
20+
this.transformers.push(...enabledTtransformers);
21+
}
22+
process() {
23+
bus_1.bus.emit('compiler.start', this.config);
24+
const toTransform = [];
25+
const transform = (context) => (sourceFile) => {
26+
context.onSubstituteNode = this.onSubstituteNode.bind(this);
27+
for (const transformer of this.transformers) {
28+
for (const substitution of transformer.getSubstitutions()) {
29+
context.enableSubstitution(substitution);
30+
}
31+
}
32+
return sourceFile;
33+
};
34+
for (const file of this.config.files) {
35+
toTransform.push(this.transformFile(file, [transform]));
36+
}
37+
// Do not reject this promise, if individual files fail
38+
return Promise.all(toTransform.map(p => p.catch(e => e)))
39+
.then(results => {
40+
bus_1.bus.emit('compiler.done', this.config);
41+
return {
42+
config: this.config,
43+
fileResults: results,
44+
};
45+
});
46+
}
47+
onSubstituteNode(context, node) {
48+
let substitutedNode = node;
49+
let parent = node.parent;
50+
for (const transformer of this.transformers) {
51+
substitutedNode = transformer.process(substitutedNode, context);
52+
}
53+
return substitutedNode;
54+
}
55+
transformFile(filePath, transformers) {
56+
bus_1.bus.emit('transform.file.start', filePath);
57+
return new Promise((resolve, reject) => {
58+
filePath = path.normalize(path.join(process.cwd(), filePath));
59+
const fileName = path.basename(filePath);
60+
const source = ts.sys.readFile(filePath, this.config.encoding);
61+
if (source === undefined) {
62+
bus_1.bus.emit('transform.file.readError', filePath);
63+
return reject(`Error reading ${filePath}`);
64+
}
65+
let sourceFile = ts.createSourceFile(fileName, source, this.config.languageVersion || ts.ScriptTarget.Latest, this.config.setParentNodes || true, this.config.scriptKind || ts.ScriptKind.TS);
66+
if (this.config.mode === CompilerMode_1.default.Visit) {
67+
transformers = [];
68+
sourceFile = this.visit(sourceFile);
69+
}
70+
const result = ts.emit(sourceFile, transformers).result;
71+
bus_1.bus.emit('transform.file.done', filePath);
72+
resolve({
73+
fileName,
74+
filePath,
75+
result,
76+
});
77+
});
78+
}
79+
visit(node) {
80+
return this.config.visitChildrenFirst ?
81+
this.visitChildrenFirst(node) :
82+
this.visitParentFirst(node);
83+
}
84+
visitChildrenFirst(node) {
85+
node = ts.visitEachChild(node, this.visitChildrenFirst.bind(this));
86+
return this.onSubstituteNode(undefined, node);
87+
}
88+
visitParentFirst(node) {
89+
node = this.onSubstituteNode(undefined, node);
90+
return ts.visitEachChild(node, this.visitParentFirst.bind(this));
91+
}
92+
}
93+
exports.Compiler = Compiler;
94+
Object.defineProperty(exports, "__esModule", { value: true });
95+
exports.default = Compiler;

dist/compiler/CompilerConfig.d.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import CompilerMode from './CompilerMode';
2+
import TransformerConfig from './transformers/TransformerConfig';
3+
export interface CompilerConfig extends TransformerConfig {
4+
files?: string[];
5+
encoding?: string;
6+
mode?: CompilerMode;
7+
visitChildrenFirst?: boolean;
8+
}
9+
export default CompilerConfig;

dist/compiler/CompilerConfig.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"use strict";

dist/compiler/CompilerMode.d.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
export declare enum CompilerMode {
2+
Substitute = 1,
3+
Visit = 2,
4+
}
5+
export default CompilerMode;

dist/compiler/CompilerMode.js

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"use strict";
2+
(function (CompilerMode) {
3+
CompilerMode[CompilerMode["Substitute"] = 1] = "Substitute";
4+
CompilerMode[CompilerMode["Visit"] = 2] = "Visit";
5+
})(exports.CompilerMode || (exports.CompilerMode = {}));
6+
var CompilerMode = exports.CompilerMode;
7+
;
8+
Object.defineProperty(exports, "__esModule", { value: true });
9+
exports.default = CompilerMode;

dist/compiler/CompilerResult.d.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
import FileResult from './FileResult';
2+
import { Config } from '../config';
3+
export interface CompilerResult {
4+
config: Config;
5+
fileResults: FileResult[];
6+
}
7+
export default CompilerResult;

dist/compiler/CompilerResult.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
"use strict";

0 commit comments

Comments
 (0)