diff --git a/package.json b/package.json index 4890d01..03e19bb 100644 --- a/package.json +++ b/package.json @@ -5,6 +5,9 @@ "main": "dist/index.js", "types": "dist/index.d.ts", "bin": "dist/bin/qhun-transpiler.js", + "bugs": { + "url": "https://github.com/wartoshika/qhun-transpiler/issues" + }, "repository": { "type": "git", "url": "https://github.com/wartoshika/qhun-transpiler" @@ -15,9 +18,9 @@ "test-seperate": "./node_modules/.bin/mocha -r ts-node/register \"test/**/*.spec.sep.ts\"", "test:coverage": "./node_modules/.bin/nyc ./node_modules/.bin/mocha -r ts-node/register \"test/**/*.spec.ts\"", "coverage:send:coveralls": "nyc report --reporter=text-lcov | coveralls", - "build-ts": "./node_modules/.bin/tsc", + "build-ts": "./node_modules/.bin/webpack --config ./webpack.api.config.js", "build-declaration": "./node_modules/.bin/tsc -p tsconfig.api.json", - "build-cli": "./node_modules/.bin/webpack --config ./webpack.config.js", + "build-cli": "./node_modules/.bin/webpack --config ./webpack.cli.config.js", "build": "./node_modules/.bin/npm-run-all build-ts build-cli build-declaration", "run-ts": "./node_modules/.bin/ts-node src/cli/Cli.ts", "postversion": "git push --follow-tags" diff --git a/src/api/Api.ts b/src/api/Api.ts index 5da4839..fde2858 100644 --- a/src/api/Api.ts +++ b/src/api/Api.ts @@ -5,10 +5,15 @@ import { DefaultConfig } from "../config/DefaultConfig"; import { SupportedTargets } from "../target/TargetFactory"; import { TranspilePipeline } from "./TranspilePipeline"; import { CompileResult } from "../compiler/CompileResult"; +import { Logger } from "../cli/Logger"; +import { ErrorWithNode } from "../error/ErrorWithNode"; +import { CommandLineColors } from "../cli/CommandLineColors"; +import { CommandLine } from "../cli/CommandLine"; import { Observable, TeardownLogic } from "rxjs"; + import * as fs from "fs"; -import { Logger } from "../cli/Logger"; +import * as ts from "typescript"; export class Api { @@ -29,6 +34,9 @@ export class Api { // save target this.options.configuration.target = target; + + // print cli head + CommandLine.printHead(); } /** @@ -57,7 +65,7 @@ export class Api { this.compiler = new Compiler(project); // other work will be done by the internal transpiler - observer.next(new TranspilePipeline(this.internalTranspile(), this.compiler.postProjectTranspile.bind(this.compiler))); + observer.next(new TranspilePipeline(project, this.internalTranspile(), this.compiler.postProjectTranspile.bind(this.compiler))); // bind watcher if actiavted if (this.options.watch) { @@ -66,10 +74,9 @@ export class Api { new FileWatcher(project, () => { try { - observer.next(new TranspilePipeline(this.internalTranspile(), this.compiler.postProjectTranspile.bind(this.compiler))); + observer.next(new TranspilePipeline(project, this.internalTranspile(), this.compiler.postProjectTranspile.bind(this.compiler))); } catch (e) { - Logger.error("Error in the transpile pipeline: " + e); - observer.error(e); + this.printError(e); } }); } else { @@ -77,8 +84,7 @@ export class Api { } } catch (e) { - Logger.error("Error in the transpile pipeline: " + e); - observer.error(e); + this.printError(e); observer.complete(); } @@ -108,4 +114,24 @@ export class Api { return true; } + + private printError(e: Error): void { + + if (e instanceof ErrorWithNode) { + + const sourceFile = e.node.getSourceFile(); + const position = ts.getLineAndCharacterOfPosition(sourceFile, e.node.pos); + + Logger.error(); + Logger.error(e.message, "[Error] ", CommandLineColors.RED); + Logger.log(`File: ${sourceFile.fileName}`, " at "); + Logger.log(`Line: ${position.line + 1}, Column: ${position.character}`, " at "); + Logger.error(); + } else { + + Logger.error(e.message); + } + } + + } diff --git a/src/api/FileWatcher.ts b/src/api/FileWatcher.ts index b9b21b7..39fd65c 100644 --- a/src/api/FileWatcher.ts +++ b/src/api/FileWatcher.ts @@ -104,7 +104,7 @@ export class FileWatcher { // print some info Logger.log(""); // one empty line - Logger.log("Detected file change: " + filename + " > Transpiling started."); + Logger.log("Detected file change: " + filename.replace(this.project.rootDir, "") + " > Transpiling started."); const result = this.executeOnChange([absolutePath]); this.changeStack.forEach(callable => callable(result)); diff --git a/src/api/TranspilePipeline.ts b/src/api/TranspilePipeline.ts index af0db7a..6eb1093 100644 --- a/src/api/TranspilePipeline.ts +++ b/src/api/TranspilePipeline.ts @@ -1,13 +1,12 @@ import { CompileResult } from "../compiler/CompileResult"; import { Logger } from "../cli/Logger"; import { CommandLineColors } from "../cli/CommandLineColors"; - -import * as ts from "typescript"; -import * as path from "path"; +import { Project } from "../config/Project"; export class TranspilePipeline { constructor( + private project: Project, private files: CompileResult[], private postProjectTranspile: () => boolean ) { } @@ -17,24 +16,34 @@ export class TranspilePipeline { */ public printResult(): TranspilePipeline { + Logger.log(); Logger.log("Successfully transpiled " + this.files.length + " files", "> ", CommandLineColors.GREEN); + Logger.log(); return this; } + /** + * prints the transpiling result more prettier :) + */ public prettyPrintResult(): TranspilePipeline { - Logger.log("Transpiling successfull. Result: " + this.files.length + " files"); + Logger.log(); + Logger.log(`${this.files.length} file(s) transpiled`, "[Success] ", CommandLineColors.GREEN); const amountOfTopFiles = 8; this.files.slice(0, amountOfTopFiles).forEach(file => { const size = Math.round(file.generatedSourcecode.length / 1024); - Logger.log(path.basename(file.file.fileName) + " [" + size + " KB]", " + ", CommandLineColors.GREEN); + let fileName = file.file.fileName.replace(this.project.rootDir, ""); + if (fileName[0] !== "/") { + fileName = "/" + fileName; + } + Logger.log(fileName + " [" + size + " KB]", " + "); }); const otherFiles = this.files.length - amountOfTopFiles; if (otherFiles > 0) { const otherFilesLength = Math.round(this.files.slice(amountOfTopFiles).reduce((a, b) => a + b.generatedSourcecode.length, 0) / 1024); - Logger.log("And " + otherFiles + " other files [" + otherFilesLength + " KB]", " ", CommandLineColors.GREEN); + Logger.log("And " + otherFiles + " other file(s) [" + otherFilesLength + " KB]", " "); } return this; @@ -47,11 +56,13 @@ export class TranspilePipeline { */ public applyPostProjectTranspile(): TranspilePipeline { - Logger.log("Applying postProjectTranspile ..."); + Logger.log(); + Logger.log("Applying postProjectTranspile ...", "> "); if (!this.postProjectTranspile()) { throw new Error("Error in the postProjectTranspile process!"); } - Logger.log("PostProjectTranspile successfull", " + ", CommandLineColors.GREEN); + Logger.log("PostProjectTranspile done", "[Success] ", CommandLineColors.GREEN); + Logger.log(); return this; } diff --git a/src/cli/CommandLine.ts b/src/cli/CommandLine.ts index b44274e..5a9e529 100644 --- a/src/cli/CommandLine.ts +++ b/src/cli/CommandLine.ts @@ -52,6 +52,19 @@ export class CommandLine { }) as ProgramArguments; } + // tslint:disable-next-line member-ordering + public static printHead(): void { + + Logger.log(); + Logger.log(`${packageJson.name} (${packageJson.version})${CommandLineColors.RESET} by ${packageJson.author}`, "", CommandLineColors.BRIGHT); + Logger.log("--------------------------------------------------------------------------------------", ""); + Logger.log(`Visit ${packageJson.repository.url} for a description and help.`, " - "); + Logger.log(`Please post issues at ${packageJson.bugs.url}`, " - "); + Logger.log("--------------------------------------------------------------------------------------", ""); + Logger.log("Thanks for using!", " "); + Logger.log(); + } + /** * prepares the execution of the transpiling process */ @@ -96,11 +109,16 @@ export class CommandLine { */ private init(): void { + CommandLine.printHead(); + if (!fs.existsSync("./qhun-transpiler.js")) { fs.writeFileSync("./qhun-transpiler.js", initFile.default); - Logger.log("The file qhun-transpiler.js has been created!", "> ", CommandLineColors.GREEN); + Logger.log("The file qhun-transpiler.js has been created!", "[Success] ", CommandLineColors.GREEN); } else { - Logger.log("This project allready contains a qhun-transpiler.js file.", "> ", CommandLineColors.RED); + Logger.error("This project allready contains a qhun-transpiler.js file.", "[Error] "); } + + // empty line + Logger.log(); } } diff --git a/src/cli/CommandLineColors.ts b/src/cli/CommandLineColors.ts index d213f65..fed96db 100644 --- a/src/cli/CommandLineColors.ts +++ b/src/cli/CommandLineColors.ts @@ -2,5 +2,8 @@ export enum CommandLineColors { RESET = "\x1b[0m", RED = "\x1b[31m", - GREEN = "\x1b[32m" + GREEN = "\x1b[32m", + WHITE = "\x1b[37m", + GREY = "\x1b[2m\x1b[37m", + BRIGHT = "\x1b[1m" } diff --git a/src/compiler/Compiler.ts b/src/compiler/Compiler.ts index 4624096..47e6763 100644 --- a/src/compiler/Compiler.ts +++ b/src/compiler/Compiler.ts @@ -55,9 +55,9 @@ export class Compiler { /** * compiles the given files and transpiles them into the target language * @param files the files to compile and transpile - * @returns the amount of successfully transpiled and written files. false on error + * @returns the amount of successfully transpiled and written files. */ - public compile(files: string[]): CompileResult[] | false { + public compile(files: string[]): CompileResult[] { // create a typescript program const program = ts.createProgram(files, this.project.compilerOptions); @@ -70,59 +70,47 @@ export class Compiler { const transpilerMetadata: QhunTranspilerMetadata = this.getMetadata(); const transpileResult: CompileResult[] = []; - // iterate over every source file - try { - - // analyze all source files and detect external modules - this.externalModuleService.analyseSourceFilesAndCastToSourceFile( - - // analyse all program sourcefiles - program.getSourceFiles() - // that are not declaration files - .filter(file => !file.isDeclarationFile) - ).forEach(sourceFile => { - - // create the transpiler - const target = targetFactory.create(this.project.configuration.target, - this.project, typeChecker, - sourceFile, transpilerMetadata, - this.keyValueStorage - ); - const extension = target.getFileExtension(); - const transpiler = new Transpiler(target); - - // declare last instances - lastSourceFile = sourceFile; - this.lastTarget = target; - - // transpile this file - let transpiledCode = transpiler.transpile(sourceFile); - - // restore replacements - transpiledCode = TranspilerFunctions.restoreReservedChars(transpiledCode); - - // save result - transpileResult.push(new CompileResult( - sourceFile, - transpiledCode, - (code: string) => { - this.writeDestinationFile(sourceFile, code, extension); - } - )); - }); - - // cleanup compiler vars and return the amount - this.writtenFileStack = []; - return transpileResult; - - } catch (e) { - - // handle this error - this.handleCompileError(e, lastSourceFile); - } + // analyze all source files and detect external modules + this.externalModuleService.analyseSourceFilesAndCastToSourceFile( + + // analyse all program sourcefiles + program.getSourceFiles() + // that are not declaration files + .filter(file => !file.isDeclarationFile) + ).forEach(sourceFile => { + + // create the transpiler + const target = targetFactory.create(this.project.configuration.target, + this.project, typeChecker, + sourceFile, transpilerMetadata, + this.keyValueStorage + ); + const extension = target.getFileExtension(); + const transpiler = new Transpiler(target); + + // declare last instances + lastSourceFile = sourceFile; + this.lastTarget = target; + + // transpile this file + let transpiledCode = transpiler.transpile(sourceFile); + + // restore replacements + transpiledCode = TranspilerFunctions.restoreReservedChars(transpiledCode); + + // save result + transpileResult.push(new CompileResult( + sourceFile, + transpiledCode, + (code: string) => { + this.writeDestinationFile(sourceFile, code, extension); + } + )); + }); - // compiling not successfill - return false; + // cleanup compiler vars and return the amount + this.writtenFileStack = []; + return transpileResult; } /** diff --git a/tsconfig.api.json b/tsconfig.api.json index 0d8f113..7891214 100644 --- a/tsconfig.api.json +++ b/tsconfig.api.json @@ -1,6 +1,7 @@ { "extends": "./tsconfig.json", "compilerOptions": { + "outFile": "dist/index.d.ts", "declaration": true, "emitDeclarationOnly": true, "removeComments": false diff --git a/tsconfig.base.json b/tsconfig.base.json index 8a820f9..2ca7c62 100644 --- a/tsconfig.base.json +++ b/tsconfig.base.json @@ -1,6 +1,6 @@ { "compilerOptions": { - "module": "commonjs", + "module": "umd", "noImplicitAny": true, "removeComments": true, "preserveConstEnums": true, diff --git a/webpack.api.config.js b/webpack.api.config.js new file mode 100644 index 0000000..dc5ae8e --- /dev/null +++ b/webpack.api.config.js @@ -0,0 +1,41 @@ +var path = require('path'); +var fs = require('fs'); + +var nodeModules = {}; +fs.readdirSync('node_modules') + .filter(function (x) { + return ['.bin'].indexOf(x) === -1; + }) + .forEach(function (mod) { + nodeModules[mod] = 'commonjs ' + mod; + }); + +module.exports = { + entry: './src/index.ts', + target: 'node', + mode: 'production', + output: { + path: path.join(__dirname, 'dist'), + filename: 'index.js', + library: "@wartoshika/qhun-transpiler", + libraryTarget: "umd", + umdNamedDefine: true + }, + module: { + rules: [ + { + test: /\.tsx?$/, + use: 'ts-loader', + exclude: /node_modules/ + }, + { + test: /\.js$/i, + use: 'raw-loader', + } + ] + }, + resolve: { + extensions: ['.tsx', '.ts', '.js'] + }, + externals: nodeModules +} \ No newline at end of file diff --git a/webpack.config.js b/webpack.cli.config.js similarity index 96% rename from webpack.config.js rename to webpack.cli.config.js index 073df69..089a584 100644 --- a/webpack.config.js +++ b/webpack.cli.config.js @@ -1,4 +1,3 @@ -var webpack = require('webpack'); var path = require('path'); var fs = require('fs'); var BannerPlugin = require('webpack/lib/BannerPlugin')