2012-10-03 13 views
11

Desde dentro de una aplicación de nodo me gustaría hacer:¿TypeScript proporciona una API pública explícita para el acceso al módulo NodeJS?

var typeScript = require('typescript'); 

typeScript.compile('...') 

Estoy mirando para poner en práctica el compilador en un sistema de construcción, pero que no tienen acceso a una API pública (typescript.compile, etc) esto es imposible.

Aquí hay un ejemplo más completo de lo que me gustaría hacer, sin embargo el siguiente es para LiveScript, no mecanografiado, utilitized en un plugin escrito para el sistema de acumulación de 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 si Alguien encontró una solución alternativa?

actualización

Terminé la implementación de mi propia solución a una variedad de los problemas enumerados anteriormente y en otros lugares. Consulte https://github.com/damassi/TypeScript-Watcher para obtener más información y uso.

Respuesta

8

Este es un poco raro, pero funcionará.

Pensé en esto exactamente ayer y estaba revisando su código. Si selecciona bin/typscript.js desde su código fuente (es un archivo muy grande, con casi 21k líneas de código), verá que crea TypeScript.TypeScriptCompiler, y luego encontrará que esto EXISTE una forma de compilación .

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

Ahora, necesita una manera fácil de exponerlo. Para hacer esto, tendrás que modificar su código, que es por qué esto es hacky. Para hacer esto, puede modificar typescript.js agregando:

module.exports = exports = TypeScript; 

Justo al final del archivo.

Luego, puede crear un archivo index.js en la raíz del módulo (aviso: instale el módulo en un ámbito local para todo esto: "npm install typescript"), que expone el objeto.

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

¡Y listo! Ahora puede simplemente llamarlo y compilar su código usándolo. Puede verificar cómo usar la API para la compilación en el archivo tsc.js.

Me disculpo de antemano por el código horrible, por delante:

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

Por alguna razón el que escribió el código fue un verdadero fan de C# y procedió a seguir adelante y métodos de uso de llama WriteLine, Cierre y escribir, lo cual de hecho son solo envoltorios. Podría obtener esto de la sobrecarga de tener que agregar estas funciones, pero tendría que modificar una gran cantidad de código en el módulo y no vale la pena. Creo que es mejor tener una clase para ampliar (o si todavía está en JS, heredar el prototipo) y dejar que lo haga por usted, para hacerlo SECO.

Algo muy agradable es que si quiere traducir 500 archivos de TypeScript y ponerlos todos en un solo archivo .js, puede simplemente llamar a compiler.addUnit (anothercontent, anotherpath); 500 veces y luego ver todo en un solo archivo :)

Enfocarse en cosas mejores: si marca el código tsc.js, encontrará una clase de compilador de lotes. Si desea esto para un proceso de compilación, podría ser mejor usar algo más robusto como este. Proporciona ver archivos y más.

Después de buscar el código, creo que sólo voy a enviar un ticket al equipo de desarrollo y pedirles que aporten una API más claro ¬¬

Nota: Toda la lectura de ficheros aquí se hace de una manera sincrónica. Esto es malo, muy malo, en términos de rendimiento. No sé exactamente qué es lo que planeas hacer, pero no podría recomendar más que encuentres la manera de sincronizar esto si es posible.

+0

Excellent answer. Esperando tu ejemplo. – cnp

+0

¡Hecho! Puedes jugar con él, simplemente cambia el nombre del archivo (es test.js y test.ts) y dale otros nombres de archivos y funcionará. Tal como está ahora, la salida de error se lanzará a process.stderr, pero puedes hacer lo que quieras con ella. También puede agregar una función de controlador como compiler.setErrorCallback, y de esa manera puede generar informes sobre errores de compilación. – Mamsaac

2

Actualmente no es posible realizar una compilación simplemente con una compilación require y calling. Si puede ver los arnés.ts hay un módulo de compilación que proporciona una forma bastante simple de hacerlo, pero le sugiero que llame a tsc externamente.

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

Creo que esto haría el trabajo.

+0

Impresionante. Hará. – cnp

+0

es posible que desee eliminar esta respuesta –

1

Comprobar this github project por niutech, se puede convertir el código de transcripción de código JS sobre la marcha en el navegador, pero supongo que puede ser fácilmente modificado para que funcione en node.js.

+0

¡Gracias por mencionar mi proyecto! – niutech

1

better-require podría ayudarlo a lograr esto si todo lo que desea es ejecutar/acceder al archivo de mecanografía.

Se permite establecer como requisito() archivos mecanografiado - sin pre-compilación necesario - y un montón de otros formatos de archivo (CoffeeScript, clojurescript, YAML, XML, etc.)

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

Divulgación: Me escribió una mejor -exigir.

+0

Awesome util - Voy a intentarlo ahora en un intento de parchearlo en el ensamblador Brunch.io. – cnp

+0

¡Gracias! Siéntase libre de solicitar;; es bastante sencillo. –

1

Puede probar https://github.com/sinclairzx81/typescript.api. Este proyecto hace las cosas de extensión require(), pero también tiene alguna funcionalidad para compilar su fuente de forma manual. Debería ser posible crear un sistema de compilación automatizado con él.

tenga en cuenta que está basado en el compilador de mecanografía 0.9, por lo que puede o no tener éxito compilando la fuente 0.8.3 dado varias actualizaciones del idioma.

Cuestiones relacionadas