2012-10-03 5 views
11

Dall'interno di un app nodo vorrei fare:Does TypeScript fornisce un'API pubblica esplicita per l'accesso al modulo NodeJS?

var typeScript = require('typescript'); 

typeScript.compile('...') 

Sto cercando di implementare il compilatore in un sistema di compilazione, ma senza accesso a un API pubblica (typescript.compile, ecc) questo è impossibile.

Ecco un esempio più completo di quello che vorrei fare, anche se il sotto è per LiveScript, non tipografico, utilitized in un plugin scritto per il sistema di build-Brunch.io:

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') 
    ] 

Curioso di sapere se qualcuno ha trovato un work-around?

Aggiornamento

Ho finito per attuare la mia soluzione a una serie di problemi sopra elencati e altrove. Si prega di consultare https://github.com/damassi/TypeScript-Watcher per ulteriori informazioni e utilizzo.

risposta

8

Questo è un po 'hacky ma funzionerà.

Ho pensato proprio a questo ieri e stavo controllando il loro codice. Se controlli bin/typscript.js dal loro codice sorgente (È un file molto grande, con quasi 21k linee di codice), vedrai che crea TypeScript.TypeScriptCompiler, e poi scoprirai che questo espone un modo di compilazione .

var compiler = new TypeScript.TypeScriptCompiler(outfile, errorfile, 
    new TypeScript.NullLogger(), settings); 

Ora, avete bisogno di un modo semplice per esporlo. Per fare ciò, dovrai modificare il loro codice, motivo per cui questo è hacky. Per fare questo, è possibile modificare typescript.js aggiungendo:

module.exports = exports = TypeScript; 

Proprio alla fine del file.

Quindi, è possibile creare un file index.js nella radice del modulo (avviso: installare il modulo in un ambito locale per tutto questo: "NPM installare dattiloscritto"), che espone l'oggetto.

exports.TypeScript = require("bin/typescript"); 

E pronto! Ora puoi chiamarlo e compilare il tuo codice usandolo. Puoi verificare come utilizzare l'API per la compilazione nel file tsc.js.

Mi scuso in anticipo per il codice orribile avanti:

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(); 

Per qualche ragione chi ha scritto il codice è stato un vero fan di C# e ha proceduto ad andare avanti e di utilizzare metodi chiama WriteLine, Close e scrittura, che sono in effetti solo involucri. Potresti ottenere questo sovraccarico di dover aggiungere queste funzioni, ma dovresti modificare molto codice nel modulo e non ne vale la pena. Penso che sia meglio avere una classe da estendere (o se sei ancora su JS, ereditare il prototipo) e lasciarlo fare per te, per renderlo ASCIUTTO.

Qualcosa di veramente bello è che se si vogliono tradurre 500 file TypeScript e metterli tutti in un unico file .js, basta chiamare compiler.addUnit (anothercontent, anotherpath); 500 volte e poi vedere tutto andare in un unico file :)

Concentrarsi sulle cose migliori: se controlli tsc.js codice, si trova una classe del compilatore batch. Se vuoi questo per un processo di compilazione, potrebbe essere meglio usare qualcosa di più robusto come questo. Fornisce file di sorveglianza e altro ancora.

Dopo aver dato un'occhiata al codice, penso che mi limiterò a presentare un biglietto per il team di sviluppo e chiedere loro di fornire una più chiara API ¬¬

Nota: Tutti i file di legge qui sono fatti in modo sincrono. Questo è male, molto male, in termini di prestazioni. Non so esattamente cosa pensi di fare, ma non potrei raccomandare di più di trovare un modo per renderlo asincrono se possibile.

+0

Ottima risposta. In attesa del tuo esempio. – cnp

+0

Fatto! Puoi giocarci, basta cambiare il nome del file (è test.js e test.ts) e dargli altri nomi di file e funzionerà. Per come è ora, l'output degli errori verrà rilasciato a process.stderr, ma puoi fare tutto ciò che vuoi con esso. Puoi anche aggiungere una funzione di handler come compiler.setErrorCallback, e in questo modo puoi creare report sugli errori di compilazione! – Mamsaac

2

Attualmente non è possibile ottenere una compilazione solo richiedendo una richiesta e chiamando la compilazione. Se si può guardare a harness.ts c'è un modulo compilatore che fornisce un modo piuttosto semplice per farlo, ma ti suggerisco di chiamare tsc esternamente.

///<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); 
    } 
}); 

Credo che questo sarebbe fare il lavoro.

+0

Impressionante. Andrà bene. – cnp

+0

potresti voler cancellare questa risposta –

1

Controllare this github project da niutech, è possibile convertire il codice dattiloscritto in codice JS al volo browser, ma credo che può essere facilmente essere modificato per lavorare in node.js.

+0

Grazie per aver menzionato il mio progetto! – niutech

1

better-require potrebbe aiutarvi a raggiungere questo, se invece si è in esecuzione/accesso al file dattiloscritto.

Consente di require() file dattiloscritto - senza pre-compilazione necessario - e un sacco di altri formati di file (CoffeeScript, ClojureScript, YAML, XML, etc.)

require('better-require')(); 
var myModule = require('./mymodule.ts'); 

Disclosure: ho scritto meglio -require.

+0

Ut utilissimo - Ho intenzione di provarlo ora nel tentativo di applicarlo nell'assemblatore Brunch.io. – cnp

+0

Grazie! Sentiti libero di effettuare una richiesta;) È piuttosto semplice. –

1

Si potrebbe provare https://github.com/sinclairzx81/typescript.api. Questo progetto ha l'estensione require(), ma ha anche alcune funzionalità per compilare l'origine manualmente. Dovrebbe essere possibile creare un sistema di build automatico con esso.

nota tho suo costruita sul compilatore dattiloscritto 0.9, quindi si può o non può avere successo la compilazione 0.8.3 fonte dato diversi aggiornamenti della lingua.

Problemi correlati