mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 18:51:03 +01:00
3093d65363
Former-commit-id: cda69f08955cb0d594e98bf26197ee573cbba4b2
271 lines
6.5 KiB
Go
271 lines
6.5 KiB
Go
// Package typescript provides a typescript compiler with hot-reloader
|
|
// and optionally a cloud-based editor, called 'alm-tools'.
|
|
// typescript (by microsoft) and alm-tools (by @basarat) have their own (open-source) licenses
|
|
// the tools are not used directly by this adaptor, but it's good to know where you can find
|
|
// the software.
|
|
package typescript
|
|
|
|
import (
|
|
"errors"
|
|
"os"
|
|
"path/filepath"
|
|
"strings"
|
|
|
|
"github.com/kataras/iris/v12/typescript/npm"
|
|
)
|
|
|
|
type (
|
|
// Typescript contains the unique iris' typescript loader, holds all necessary fields & methods.
|
|
Typescript struct {
|
|
Config *Config
|
|
log func(format string, a ...interface{})
|
|
}
|
|
)
|
|
|
|
// New creates & returns a new instnace typescript plugin
|
|
func New(cfg ...Config) *Typescript {
|
|
c := DefaultConfig()
|
|
if len(cfg) > 0 {
|
|
c = cfg[0]
|
|
}
|
|
|
|
return &Typescript{Config: &c}
|
|
}
|
|
|
|
// NoOpLogger can be used as the logger argument, it prints nothing.
|
|
var NoOpLogger = func(string, ...interface{}) {}
|
|
|
|
// Run starts the typescript filewatcher watcher and the typescript compiler.
|
|
func (t *Typescript) Run(logger func(format string, a ...interface{})) {
|
|
c := t.Config
|
|
if c.Tsconfig == nil {
|
|
tsC := DefaultTsconfig()
|
|
c.Tsconfig = &tsC
|
|
}
|
|
|
|
if c.Dir == "" {
|
|
c.Tsconfig.CompilerOptions.OutDir = c.Dir
|
|
}
|
|
|
|
if c.Dir == "" {
|
|
c.Dir = "./"
|
|
}
|
|
|
|
if !strings.Contains(c.Ignore, nodeModules) {
|
|
c.Ignore += "," + nodeModules
|
|
}
|
|
|
|
if logger == nil {
|
|
logger = NoOpLogger
|
|
}
|
|
|
|
t.log = logger
|
|
|
|
t.start()
|
|
}
|
|
|
|
func (t *Typescript) start() {
|
|
if t.hasTypescriptFiles() {
|
|
// Can't check if permission denied returns always exists = true....
|
|
|
|
if !npm.NodeModuleExists(t.Config.Bin) {
|
|
t.log("installing typescript, please wait...")
|
|
res := npm.NodeModuleInstall("typescript")
|
|
if res.Error != nil {
|
|
t.log(res.Error.Error())
|
|
return
|
|
}
|
|
t.log(res.Message)
|
|
}
|
|
|
|
projects := t.getTypescriptProjects()
|
|
if len(projects) > 0 {
|
|
watchedProjects := 0
|
|
// typescript project (.tsconfig) found
|
|
for _, project := range projects {
|
|
cmd := npm.CommandBuilder("node", t.Config.Bin, "-p", project[0:strings.LastIndex(project, npm.PathSeparator)]) // remove the /tsconfig.json)
|
|
projectConfig, perr := FromFile(project)
|
|
if perr != nil {
|
|
t.log("error while trying to read tsconfig: %s", perr.Error())
|
|
continue
|
|
}
|
|
|
|
if projectConfig.CompilerOptions.Watch {
|
|
watchedProjects++
|
|
// if has watch : true then we have to wrap the command to a goroutine (I don't want to use the .Start here)
|
|
go func() {
|
|
_, err := cmd.Output()
|
|
if err != nil {
|
|
t.log("error when 'watch' is true: %v", err)
|
|
return
|
|
}
|
|
}()
|
|
} else {
|
|
_, err := cmd.Output()
|
|
if err != nil {
|
|
t.log("unexpected error from output: %v", err)
|
|
return
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
return
|
|
}
|
|
// search for standalone typescript (.ts) files and compile them
|
|
files := t.getTypescriptFiles()
|
|
if len(files) > 0 {
|
|
/* watchedFiles := 0
|
|
if t.Config.Tsconfig.CompilerOptions.Watch {
|
|
watchedFiles = len(files)
|
|
}*/
|
|
//it must be always > 0 if we came here, because of if hasTypescriptFiles == true.
|
|
for _, file := range files {
|
|
|
|
absPath, err := filepath.Abs(file)
|
|
if err != nil {
|
|
t.log("error while trying to resolve absolute path for %s: %v", file, err)
|
|
continue
|
|
}
|
|
|
|
// these will be used if no .tsconfig found.
|
|
// cmd := npm.CommandBuilder("node", t.Config.Bin)
|
|
// cmd.Arguments(t.Config.Bin, t.Config.Tsconfig.CompilerArgs()...)
|
|
// cmd.AppendArguments(absPath)
|
|
compilerArgs := t.Config.Tsconfig.CompilerArgs()
|
|
cmd := npm.CommandBuilder("node", t.Config.Bin)
|
|
|
|
for _, s := range compilerArgs {
|
|
cmd.AppendArguments(s)
|
|
}
|
|
cmd.AppendArguments(absPath)
|
|
go func() {
|
|
compilerMsgB, _ := cmd.Output()
|
|
compilerMsg := string(compilerMsgB)
|
|
cmd.Args = cmd.Args[0 : len(cmd.Args)-1] // remove the last, which is the file
|
|
|
|
if strings.Contains(compilerMsg, "error") {
|
|
t.log(compilerMsg)
|
|
}
|
|
}()
|
|
|
|
}
|
|
return
|
|
}
|
|
return
|
|
}
|
|
absPath, err := filepath.Abs(t.Config.Dir)
|
|
if err != nil {
|
|
t.log("no typescript file, the directory cannot be resolved: %v", err)
|
|
return
|
|
}
|
|
t.log("no typescript files found on : %s", absPath)
|
|
}
|
|
|
|
func (t *Typescript) hasTypescriptFiles() bool {
|
|
root := t.Config.Dir
|
|
ignoreFolders := t.getIgnoreFolders()
|
|
hasTs := false
|
|
if !npm.Exists(root) {
|
|
t.log("typescript error: directory '%s' couldn't be found,\nplease specify a valid path for your *.ts files", root)
|
|
return false
|
|
}
|
|
|
|
err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
|
if fi.IsDir() {
|
|
return nil
|
|
}
|
|
for _, s := range ignoreFolders {
|
|
if strings.HasSuffix(path, s) || path == s {
|
|
return filepath.SkipDir
|
|
}
|
|
}
|
|
|
|
if strings.HasSuffix(path, ".ts") {
|
|
hasTs = true
|
|
return errors.New("typescript found, hope that will stop here")
|
|
}
|
|
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
t.log("typescript: hasTypescriptFiles: %v", err)
|
|
}
|
|
return hasTs
|
|
}
|
|
|
|
func (t *Typescript) getIgnoreFolders() (folders []string) {
|
|
ignoreFolders := strings.Split(t.Config.Ignore, ",")
|
|
|
|
for _, s := range ignoreFolders {
|
|
if s != "" {
|
|
folders = append(folders, s)
|
|
}
|
|
}
|
|
|
|
return folders
|
|
}
|
|
|
|
func (t *Typescript) getTypescriptProjects() []string {
|
|
var projects []string
|
|
ignoreFolders := t.getIgnoreFolders()
|
|
|
|
root := t.Config.Dir
|
|
// t.logger.Printf("\nSearching for typescript projects in %s", root)
|
|
|
|
err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
|
if fi.IsDir() {
|
|
return nil
|
|
}
|
|
for _, s := range ignoreFolders {
|
|
if strings.HasSuffix(path, s) || path == s {
|
|
return filepath.SkipDir
|
|
}
|
|
}
|
|
|
|
if strings.HasSuffix(path, npm.PathSeparator+"tsconfig.json") {
|
|
// t.logger.Printf("\nTypescript project found in %s", path)
|
|
projects = append(projects, path)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
t.log("typescript: getTypescriptProjects: %v", err)
|
|
}
|
|
return projects
|
|
}
|
|
|
|
// this is being called if getTypescriptProjects return 0 len, then we are searching for files using that:
|
|
func (t *Typescript) getTypescriptFiles() []string {
|
|
var files []string
|
|
ignoreFolders := t.getIgnoreFolders()
|
|
|
|
root := t.Config.Dir
|
|
|
|
err := filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
|
if fi.IsDir() {
|
|
return nil
|
|
}
|
|
for _, s := range ignoreFolders {
|
|
if strings.HasSuffix(path, s) || path == s {
|
|
return nil
|
|
}
|
|
}
|
|
|
|
if strings.HasSuffix(path, ".ts") {
|
|
// t.logger.Printf("\nTypescript file found in %s", path)
|
|
files = append(files, path)
|
|
}
|
|
|
|
return nil
|
|
})
|
|
|
|
if err != nil {
|
|
t.log("typescript: getTypescriptFiles: %v", err)
|
|
}
|
|
|
|
return files
|
|
}
|