javascript - Gir TypeScript en eksplisitt offentlig API for NodeJS-modultilgang?
Fra innenfor en node-app vil jeg gjøre:
var typeScript = require('typescript');
typeScript.compile('...')
Jeg ser etter å implementere kompilatoren i et bygge system, men uten tilgang til et offentlig API (typescript.compile, osv.) er dette umulig.
Her er et mer komplett eksempel på hva jeg ønsker å gjøre, selv om det nedenfor er for LiveScript, ikke TypeScript, brukt i en plugin skrevet for Brunch.io byggesystem:
LiveScript = require 'LiveScript'
sysPath = require 'path'
module.exports = class LiveScriptCompiler
brunchPlugin: yes
type: 'javascript'
extension: 'ls'
constructor: (@config) ->
null
compile: (data, path, callback) ->
try
result = LiveScript.compile data, bare: yes
catch err
error = err
finally
callback error, result
include: [
(sysPath.join __dirname, '..', 'vendor', 'prelude-browser-0.6.0.js')
]
Nysgjerrig på om noen har funnet en løsning?
Oppdatering
Jeg endte opp med å implementere min egen løsning på en rekke av problemene nevnt ovenfor og andre steder. Vennligst se https://github.com/damassi/TypeScript-Watcher for mer informasjon og bruk.
Svar #1
Denne er litt klønete, men den vil fungere.
Jeg tenkte på akkurat dette i går, og jeg sjekket koden deres. Hvis du sjekker bin/typscript.js fra kildekoden deres (det er en veldig, veldig stor fil, med nesten 21 000 linjer kode), vil du se at den oppretter TypeScript.TypeScriptCompiler, og deretter vil du finne ut at dette GIR faktisk en måte å kompilere på.
var compiler = new TypeScript.TypeScriptCompiler(outfile, errorfile,
new TypeScript.NullLogger(), settings);
Nå trenger du en enkel måte å eksponere det på. For å gjøre dette må du endre koden deres, noe som er grunnen til at dette er hackete. For å gjøre dette kan du endre typescript.js ved å legge til:
module.exports = exports = TypeScript;
Rett på slutten av filen.
Deretter kan du opprette en index.js-fil i roten av modulen (merk: installer modulen lokalt for alt dette: "npm install typescript"), som eksponerer objektet.
exports.TypeScript = require("bin/typescript");
Og ferdig! Nå kan du bare kalle det og kompilere koden din ved å bruke det. Du kan sjekke hvordan du bruker API-en for kompilering i tsc.js-filen.
Jeg beklager på forhånd for den forferdelige koden som kommer:
var fs = require("fs");
var TypeScript = require("typescript");
var path = "test.ts";
var pathout = "test.js";
var content = fs.readFileSync(path, "utf-8");
var fd = fs.openSync(pathout, 'w');
var outFile = {
Write: function (str) {
fs.writeSync(fd, str);
},
WriteLine: function (str) {
console.log(fd, str);
fs.writeSync(fd, str + '\r\n');
},
Close: function () {
fs.closeSync(fd);
fd = null;
}
};
var createFile = function (path) {
function mkdirRecursiveSync(path) {
var stats = fs.statSync(path);
if(stats.isFile()) {
throw "\"" + path + "\" exists but isn't a directory.";
} else {
if(stats.isDirectory()) {
return;
} else {
mkdirRecursiveSync(_path.dirname(path));
fs.mkdirSync(path, 509);
}
}
}
mkdirRecursiveSync(_path.dirname(path));
console.log(path)
var fd = fs.openSync(path, 'w');
return {
Write: function (str) {
fs.writeSync(fd, str);
},
WriteLine: function (str) {
fs.writeSync(fd, str + '\r\n');
},
Close: function () {
fs.closeSync(fd);
fd = null;
}
};
};
var stderr = {
Write: function (str) {
process.stderr.write(str);
},
WriteLine: function (str) {
process.stderr.write(str + '\n');
},
Close: function () {
}
}
var compiler = new TypeScript.TypeScriptCompiler(outFile, outFile);
compiler.setErrorOutput(stderr);
compiler.addUnit(content, path);
compiler.typeCheck();
compiler.emit(false, createFile);
outFile.Close();
Av en eller annen grunn var den som skrev koden en ekte fan av C# og gikk videre med å bruke metoder kalt WriteLine, Close og Write, som faktisk bare er wrappers. Du kunne kvittet deg med denne overheaden ved å måtte legge til disse funksjonene, men du måtte endre mye kode i modulen, og det er ikke verdt det. Jeg tror det er best å ha en klasse å utvide (eller hvis du fortsatt er på JS, arve prototypen) og la den gjøre det for deg, for å gjøre det DRY.
Noe som er virkelig fint er at hvis du vil oversette 500 TypeScript-filer og legge dem alle i en enkelt .js-fil, kan du bare kalle compiler.addUnit(anothercontent, anotherpath); 500 ganger og deretter se alt gå inn i en enkelt fil :)
Fokusere på bedre ting: hvis du sjekker tsc.js-koden, vil du finne en batch-kompilator-klasse. Hvis du vil ha dette for en byggeprosess, kan det være bedre å bruke noe mer robust som det. Den tilbyr overvåking av filer og mer.
Etter å ha bladd gjennom koden, tror jeg jeg bare vil sende inn en sak til utviklingsteamet og be dem om å gi en tydeligere API.
Merk: Alle fillesninger her gjøres på en synkron måte. Dette er dårlig, veldig dårlig, når det gjelder ytelse. Jeg vet ikke nøyaktig hva du planlegger å gjøre, men jeg kan ikke anbefale mer at du finner en måte å gjøre dette asynkront på hvis mulig.
Svar #2
For øyeblikket er det ikke mulig å oppnå en kompilering bare ved å ha en require og kalle compile. Hvis du kan se på harness.ts, finnes det en compiler-modul som gir en ganske enkel måte å gjøre det på, men jeg vil foreslå at du kaller tsc eksternt.
///<reference path='node.d.ts'/>
import exec = module('child_process');
var child = exec.exec('tsc foo.ts',
function (error, stdout, stderr) {
if (error !== null) {
console.log('exec error: ' + error);
}
});
Jeg tror dette ville gjøre jobben.
