mirror of
https://github.com/kataras/iris.git
synced 2026-02-28 21:45:57 +00:00
Version 3.0.0-beta cleaned
This commit is contained in:
45
plugin/editor/README.md
Normal file
45
plugin/editor/README.md
Normal file
@@ -0,0 +1,45 @@
|
||||
## Package information
|
||||
|
||||
Editor Plugin is just a bridge between Iris and [alm-tools](http://alm.tools).
|
||||
|
||||
|
||||
[alm-tools](http://alm.tools) is a typescript online IDE/Editor, made by [@basarat](https://twitter.com/basarat) one of the top contributors of the [Typescript](http://www.typescriptlang.org).
|
||||
|
||||
Iris gives you the opportunity to edit your client-side using the alm-tools editor, via the editor plugin.
|
||||
|
||||
|
||||
This plugin starts it's own server, if Iris server is using TLS then the editor will use the same key and cert.
|
||||
|
||||
## How to use
|
||||
|
||||
```go
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/plugin/editor"
|
||||
)
|
||||
|
||||
func main(){
|
||||
e := editor.New("username","password").Port(4444).Dir("/path/to/the/client/side/directory")
|
||||
|
||||
iris.Plugins().Add(e)
|
||||
|
||||
iris.Get("/", func (ctx *iris.Context){})
|
||||
|
||||
iris.Listen(":8080")
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
> Note for username, password: The Authorization specifies the authentication mechanism (in this case Basic) followed by the username and password.
|
||||
Although, the string aHR0cHdhdGNoOmY= may look encrypted it is simply a base64 encoded version of <username>:<password>.
|
||||
Would be readily available to anyone who could intercept the HTTP request. [Read more.](https://www.httpwatch.com/httpgallery/authentication/)
|
||||
|
||||
> The editor can't work if the directory doesn't contains a [tsconfig.json](http://www.typescriptlang.org/docs/handbook/tsconfig.json.html).
|
||||
|
||||
> If you are using the [typescript plugin](https://github.com/kataras/iris/tree/development/plugin/typescript) you don't have to call the .Dir(...)
|
||||
|
||||
|
||||
157
plugin/editor/editor.go
Normal file
157
plugin/editor/editor.go
Normal file
@@ -0,0 +1,157 @@
|
||||
package editor
|
||||
|
||||
/* Notes for Auth
|
||||
The Authorization specifies the authentication mechanism (in this case Basic) followed by the username and password.
|
||||
Although, the string aHR0cHdhdGNoOmY= may look encrypted it is simply a base64 encoded version of <username>:<password>.
|
||||
Would be readily available to anyone who could intercept the HTTP request.
|
||||
*/
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/config"
|
||||
"github.com/kataras/iris/logger"
|
||||
"github.com/kataras/iris/npm"
|
||||
"github.com/kataras/iris/utils"
|
||||
)
|
||||
|
||||
const (
|
||||
// Name the name of the Plugin, which is "EditorPlugin"
|
||||
Name = "EditorPlugin"
|
||||
)
|
||||
|
||||
type (
|
||||
// Plugin is an Editor Plugin the struct which implements the iris.IPlugin
|
||||
// it holds a logger from the iris' station
|
||||
// username,password for basic auth
|
||||
// directory which the client side code is
|
||||
// keyfile,certfile for TLS listening
|
||||
// and a host which is listening for
|
||||
Plugin struct {
|
||||
config *config.Editor
|
||||
logger *logger.Logger
|
||||
enabled bool // default true
|
||||
keyfile string
|
||||
certfile string
|
||||
// after alm started
|
||||
process *os.Process
|
||||
}
|
||||
)
|
||||
|
||||
// New creates and returns an Editor Plugin instance
|
||||
func New(cfg ...config.Editor) *Plugin {
|
||||
c := config.DefaultEditor().Merge(cfg)
|
||||
e := &Plugin{enabled: true, config: &c}
|
||||
return e
|
||||
}
|
||||
|
||||
// User set a user, accepts two parameters: username (string), string (string)
|
||||
func (e *Plugin) User(username string, password string) *Plugin {
|
||||
e.config.Username = username
|
||||
e.config.Password = password
|
||||
return e
|
||||
}
|
||||
|
||||
// Dir sets the directory which the client side source code alive
|
||||
func (e *Plugin) Dir(workingDir string) *Plugin {
|
||||
e.config.WorkingDir = workingDir
|
||||
return e
|
||||
}
|
||||
|
||||
// Port sets the port (int) for the editor plugin's standalone server
|
||||
func (e *Plugin) Port(port int) *Plugin {
|
||||
e.config.Port = port
|
||||
return e
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// SetEnable if true enables the editor plugin, otherwise disables it
|
||||
func (e *Plugin) SetEnable(enable bool) {
|
||||
e.enabled = enable
|
||||
}
|
||||
|
||||
// GetName returns the name of the Plugin
|
||||
func (e *Plugin) GetName() string {
|
||||
return Name
|
||||
}
|
||||
|
||||
// GetDescription EditorPlugin is a bridge between Iris and the alm-tools, the browser-based IDE for client-side sources.
|
||||
func (e *Plugin) GetDescription() string {
|
||||
return Name + " is a bridge between Iris and the alm-tools, the browser-based IDE for client-side sources. \n"
|
||||
}
|
||||
|
||||
// PreListen runs before the server's listens, saves the keyfile,certfile and the host from the Iris station to listen for
|
||||
func (e *Plugin) PreListen(s *iris.Iris) {
|
||||
e.logger = s.Logger()
|
||||
e.keyfile = s.Server().Config.KeyFile
|
||||
e.certfile = s.Server().Config.CertFile
|
||||
|
||||
if e.config.Host == "" {
|
||||
h := s.Server().Config.ListeningAddr
|
||||
|
||||
if idx := strings.Index(h, ":"); idx >= 0 {
|
||||
h = h[0:idx]
|
||||
}
|
||||
if h == "" {
|
||||
h = "127.0.0.1"
|
||||
}
|
||||
|
||||
e.config.Host = h
|
||||
|
||||
}
|
||||
e.start()
|
||||
}
|
||||
|
||||
// PreClose kills the editor's server when Iris is closed
|
||||
func (e *Plugin) PreClose(s *iris.Iris) {
|
||||
if e.process != nil {
|
||||
err := e.process.Kill()
|
||||
if err != nil {
|
||||
e.logger.Printf("\nError while trying to terminate the (Editor)Plugin, please kill this process by yourself, process id: %d", e.process.Pid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// start starts the job
|
||||
func (e *Plugin) start() {
|
||||
if e.config.Username == "" || e.config.Password == "" {
|
||||
e.logger.Println("Error before running alm-tools. You have to set username & password for security reasons, otherwise this plugin won't run.")
|
||||
return
|
||||
}
|
||||
|
||||
if !npm.Exists("alm/bin/alm") {
|
||||
e.logger.Println("Installing alm-tools, please wait...")
|
||||
res := npm.Install("alm")
|
||||
if res.Error != nil {
|
||||
e.logger.Print(res.Error.Error())
|
||||
return
|
||||
}
|
||||
e.logger.Print(res.Message)
|
||||
}
|
||||
|
||||
cmd := utils.CommandBuilder("node", npm.Abs("alm/src/server.js"))
|
||||
cmd.AppendArguments("-a", e.config.Username+":"+e.config.Password, "-h", e.config.Host, "-t", strconv.Itoa(e.config.Port), "-d", e.config.WorkingDir[0:len(e.config.WorkingDir)-1])
|
||||
// for auto-start in the browser: cmd.AppendArguments("-o")
|
||||
if e.keyfile != "" && e.certfile != "" {
|
||||
cmd.AppendArguments("--httpskey", e.keyfile, "--httpscert", e.certfile)
|
||||
}
|
||||
|
||||
//For debug only:
|
||||
//cmd.Stdout = os.Stdout
|
||||
//cmd.Stderr = os.Stderr
|
||||
//os.Stdin = os.Stdin
|
||||
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
e.logger.Println("Error while running alm-tools. Trace: " + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
//we lose the internal error handling but ok...
|
||||
e.logger.Printf("Editor is running at %s:%d | %s", e.config.Host, e.config.Port, e.config.WorkingDir)
|
||||
|
||||
}
|
||||
48
plugin/iriscontrol/README.md
Normal file
48
plugin/iriscontrol/README.md
Normal file
@@ -0,0 +1,48 @@
|
||||
## Iris Control
|
||||
|
||||
### THIS IS NOT READY YET
|
||||
|
||||
This plugin will give you remotely ( and local ) access to your iris server's information via a web interface
|
||||
|
||||
|
||||
### Assets
|
||||
No assets here because this is go -getable folder I don't want to messup with the folder size, in order to solve this
|
||||
I created a downloader manager inside this package which downloads the first time the assets and unzip them to the kataras/iris/plugin/iris-control/iris-control-assets/ .
|
||||
|
||||
|
||||
|
||||
The assets files are inside [this repository](https://github.com/iris-contrib/iris-control-assets)
|
||||
|
||||
|
||||
## How to use
|
||||
|
||||
```go
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/plugin/iriscontrol"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
iris.Plugins().Add(iriscontrol.Web(9090, map[string]string{
|
||||
"irisusername1": "irispassword1",
|
||||
"irisusername2": "irispassowrd2",
|
||||
}))
|
||||
|
||||
iris.Get("/", func(ctx *iris.Context) {
|
||||
})
|
||||
|
||||
iris.Post("/something", func(ctx *iris.Context) {
|
||||
})
|
||||
|
||||
fmt.Printf("Iris is listening on :%d", 8080)
|
||||
iris.Listen(":8080")
|
||||
}
|
||||
|
||||
|
||||
|
||||
```
|
||||
105
plugin/iriscontrol/control_panel.go
Normal file
105
plugin/iriscontrol/control_panel.go
Normal file
@@ -0,0 +1,105 @@
|
||||
package iriscontrol
|
||||
|
||||
import (
|
||||
"os"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/plugin/routesinfo"
|
||||
)
|
||||
|
||||
var pathSeperator = string(os.PathSeparator)
|
||||
var pluginPath = os.Getenv("GOPATH") + pathSeperator + "src" + pathSeperator + "github.com" + pathSeperator + "kataras" + pathSeperator + "iris" + pathSeperator + "plugin" + pathSeperator + "iriscontrol" + pathSeperator
|
||||
var assetsURL = "https://github.com/iris-contrib/iris-control-assets/archive/master.zip"
|
||||
var assetsFolderName = "iris-control-assets-master"
|
||||
var installationPath = pluginPath + assetsFolderName + pathSeperator
|
||||
|
||||
// for the plugin server
|
||||
func (i *irisControlPlugin) startControlPanel() {
|
||||
|
||||
// install the assets first
|
||||
if err := i.installAssets(); err != nil {
|
||||
i.pluginContainer.Printf("[%s] %s Error %s: Couldn't install the assets from the internet,\n make sure you are connecting to the internet the first time running the iris-control plugin", time.Now().UTC().String(), Name, err.Error())
|
||||
i.Destroy()
|
||||
return
|
||||
}
|
||||
|
||||
i.server = iris.New()
|
||||
i.server.Config().Render.Template.Directory = installationPath + "templates"
|
||||
//i.server.SetRenderConfig(i.server.Config.Render)
|
||||
i.setPluginsInfo()
|
||||
i.setPanelRoutes()
|
||||
|
||||
go i.server.Listen(strconv.Itoa(i.options.Port))
|
||||
i.pluginContainer.Printf("[%s] %s is running at port %d with %d authenticated users", time.Now().UTC().String(), Name, i.options.Port, len(i.auth.authenticatedUsers))
|
||||
|
||||
}
|
||||
|
||||
// DashboardPage is the main data struct for the index
|
||||
// contains a boolean if server is running, the routes and the plugins
|
||||
type DashboardPage struct {
|
||||
ServerIsRunning bool
|
||||
Routes []routesinfo.RouteInfo
|
||||
Plugins []PluginInfo
|
||||
}
|
||||
|
||||
func (i *irisControlPlugin) setPluginsInfo() {
|
||||
plugins := i.pluginContainer.GetAll()
|
||||
i.plugins = make([]PluginInfo, 0, len(plugins))
|
||||
for _, plugin := range plugins {
|
||||
i.plugins = append(i.plugins, PluginInfo{Name: i.pluginContainer.GetName(plugin), Description: i.pluginContainer.GetDescription(plugin)})
|
||||
}
|
||||
}
|
||||
|
||||
// installAssets checks if must install ,if yes download the zip and unzip it, returns error.
|
||||
func (i *irisControlPlugin) installAssets() (err error) {
|
||||
//we know already what is the zip folder inside it, so we can check if it's exists, if yes then don't install it again.
|
||||
if i.pluginContainer.GetDownloader().DirectoryExists(installationPath) {
|
||||
return
|
||||
}
|
||||
//set the installationPath ,although we know it but do it here too
|
||||
installationPath, err = i.pluginContainer.GetDownloader().Install(assetsURL, pluginPath)
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
func (i *irisControlPlugin) setPanelRoutes() {
|
||||
|
||||
i.server.Static("/public", installationPath+"static", 1)
|
||||
i.server.Get("/login", func(ctx *iris.Context) {
|
||||
ctx.Render("login", nil)
|
||||
})
|
||||
|
||||
i.server.Post("/login", func(ctx *iris.Context) {
|
||||
i.auth.login(ctx)
|
||||
})
|
||||
|
||||
i.server.Use(i.auth)
|
||||
i.server.Get("/", func(ctx *iris.Context) {
|
||||
ctx.Render("index", DashboardPage{ServerIsRunning: i.station.Server().IsListening(), Routes: i.routes.All(), Plugins: i.plugins})
|
||||
})
|
||||
|
||||
i.server.Post("/logout", func(ctx *iris.Context) {
|
||||
i.auth.logout(ctx)
|
||||
})
|
||||
|
||||
//the controls
|
||||
i.server.Post("/start_server", func(ctx *iris.Context) {
|
||||
//println("server start")
|
||||
old := i.stationServer
|
||||
if !old.IsSecure() {
|
||||
i.station.Listen(old.Config.ListeningAddr)
|
||||
//yes but here it does re- post listen to this plugin so ...
|
||||
} else {
|
||||
i.station.ListenTLS(old.Config.ListeningAddr, old.Config.CertFile, old.Config.KeyFile)
|
||||
}
|
||||
|
||||
})
|
||||
|
||||
i.server.Post("/stop_server", func(ctx *iris.Context) {
|
||||
//println("server stop")
|
||||
i.station.Close()
|
||||
})
|
||||
|
||||
}
|
||||
11
plugin/iriscontrol/index.go
Normal file
11
plugin/iriscontrol/index.go
Normal file
@@ -0,0 +1,11 @@
|
||||
package iriscontrol
|
||||
|
||||
// NOT READY YET
|
||||
|
||||
// PluginInfo holds the Name and the description of the registed plugins
|
||||
type PluginInfo struct {
|
||||
Name string
|
||||
Description string
|
||||
}
|
||||
|
||||
//func getPluginlist...
|
||||
112
plugin/iriscontrol/iriscontrol.go
Normal file
112
plugin/iriscontrol/iriscontrol.go
Normal file
@@ -0,0 +1,112 @@
|
||||
package iriscontrol
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/config"
|
||||
"github.com/kataras/iris/plugin/routesinfo"
|
||||
"github.com/kataras/iris/server"
|
||||
)
|
||||
|
||||
// Name the name(string) of this plugin which is Iris Control
|
||||
const Name = "Iris Control"
|
||||
|
||||
type irisControlPlugin struct {
|
||||
options config.IrisControl
|
||||
// the pluginContainer is the container which keeps this plugin from the main user's iris instance
|
||||
pluginContainer iris.IPluginContainer
|
||||
// the station object of the main user's iris instance
|
||||
station *iris.Iris
|
||||
//a copy of the server which the main user's iris is listening for
|
||||
stationServer *server.Server
|
||||
|
||||
// the server is this plugin's server object, it is managed by this plugin only
|
||||
server *iris.Iris
|
||||
//
|
||||
//infos
|
||||
routes *routesinfo.Plugin
|
||||
plugins []PluginInfo
|
||||
//
|
||||
|
||||
auth *userAuth
|
||||
}
|
||||
|
||||
// New returns the plugin which is ready-to-use inside iris.Plugin method
|
||||
// receives config.IrisControl
|
||||
func New(cfg ...config.IrisControl) iris.IPlugin {
|
||||
c := config.DefaultIrisControl()
|
||||
if len(cfg) > 0 {
|
||||
c = cfg[0]
|
||||
}
|
||||
auth := newUserAuth(c.Users)
|
||||
if auth == nil {
|
||||
panic(Name + " Error: you should pass authenticated users map to the options, refer to the docs!")
|
||||
}
|
||||
|
||||
return &irisControlPlugin{options: c, auth: auth, routes: routesinfo.RoutesInfo()}
|
||||
}
|
||||
|
||||
// Web set the options for the plugin and return the plugin which is ready-to-use inside iris.Plugin method
|
||||
// first parameter is port
|
||||
// second parameter is map of users (username:password)
|
||||
func Web(port int, users map[string]string) iris.IPlugin {
|
||||
return New(config.IrisControl{port, users})
|
||||
}
|
||||
|
||||
// implement the base IPlugin
|
||||
|
||||
func (i *irisControlPlugin) Activate(container iris.IPluginContainer) error {
|
||||
i.pluginContainer = container
|
||||
container.Add(i.routes) // add the routesinfo plugin to the main server
|
||||
return nil
|
||||
}
|
||||
|
||||
func (i irisControlPlugin) GetName() string {
|
||||
return Name
|
||||
}
|
||||
|
||||
func (i irisControlPlugin) GetDescription() string {
|
||||
return Name + " is just a web interface which gives you control of your Iris.\n"
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// implement the rest of the plugin
|
||||
|
||||
// PostHandle
|
||||
func (i *irisControlPlugin) PostHandle(route iris.IRoute) {
|
||||
|
||||
}
|
||||
|
||||
// PostListen sets the station object after the main server starts
|
||||
// starts the actual work of the plugin
|
||||
func (i *irisControlPlugin) PostListen(s *iris.Iris) {
|
||||
//if the first time, because other times start/stop of the server so listen and no listen will be only from the control panel
|
||||
if i.station == nil {
|
||||
i.station = s
|
||||
i.stationServer = i.station.Server()
|
||||
i.startControlPanel()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
func (i *irisControlPlugin) PreClose(s *iris.Iris) {
|
||||
// Do nothing. This is a wrapper of the main server if we destroy when users stop the main server then we cannot continue the control panel i.Destroy()
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// Destroy removes entirely the plugin, the options and all of these properties, you cannot re-use this plugin after this method.
|
||||
func (i *irisControlPlugin) Destroy() {
|
||||
i.pluginContainer.Remove(Name)
|
||||
|
||||
i.options = config.IrisControl{}
|
||||
i.routes = nil
|
||||
i.station = nil
|
||||
i.server.Close()
|
||||
i.pluginContainer = nil
|
||||
i.auth.Destroy()
|
||||
i.auth = nil
|
||||
i.pluginContainer.Printf("[%s] %s is turned off", time.Now().UTC().String(), Name)
|
||||
}
|
||||
20
plugin/iriscontrol/main_controls.go
Normal file
20
plugin/iriscontrol/main_controls.go
Normal file
@@ -0,0 +1,20 @@
|
||||
package iriscontrol
|
||||
|
||||
// for the main server
|
||||
func (i *irisControlPlugin) StartServer() {
|
||||
if i.station.Server().IsListening() == false {
|
||||
if i.station.Server().IsSecure() {
|
||||
//listen with ListenTLS
|
||||
i.station.ListenTLS(i.station.Server().Config.ListeningAddr, i.station.Server().Config.CertFile, i.station.Server().Config.KeyFile)
|
||||
} else {
|
||||
//listen normal
|
||||
i.station.Listen(i.station.Server().Config.ListeningAddr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (i *irisControlPlugin) StopServer() {
|
||||
if i.station.Server().IsListening() {
|
||||
i.station.Close()
|
||||
}
|
||||
}
|
||||
97
plugin/iriscontrol/user_auth.go
Normal file
97
plugin/iriscontrol/user_auth.go
Normal file
@@ -0,0 +1,97 @@
|
||||
package iriscontrol
|
||||
|
||||
import (
|
||||
"strings"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/sessions"
|
||||
// _ empty because it auto-registers
|
||||
_ "github.com/kataras/iris/sessions/providers/memory"
|
||||
)
|
||||
|
||||
var panelSessions *sessions.Manager
|
||||
|
||||
func init() {
|
||||
//using the default
|
||||
panelSessions = sessions.New()
|
||||
}
|
||||
|
||||
type user struct {
|
||||
username string
|
||||
password string
|
||||
}
|
||||
type userAuth struct {
|
||||
authenticatedUsers []user
|
||||
}
|
||||
|
||||
// newUserAuth returns a new userAuth object, parameter is the authenticated users as map
|
||||
func newUserAuth(usersMap map[string]string) *userAuth {
|
||||
if usersMap != nil {
|
||||
obj := &userAuth{make([]user, 0)}
|
||||
for key, val := range usersMap {
|
||||
obj.authenticatedUsers = append(obj.authenticatedUsers, user{key, val})
|
||||
}
|
||||
|
||||
return obj
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (u *userAuth) login(ctx *iris.Context) {
|
||||
session := panelSessions.Start(ctx)
|
||||
|
||||
username := ctx.PostFormValue("username")
|
||||
password := ctx.PostFormValue("password")
|
||||
|
||||
for _, authenticatedUser := range u.authenticatedUsers {
|
||||
if authenticatedUser.username == username && authenticatedUser.password == password {
|
||||
session.Set("username", username)
|
||||
session.Set("password", password)
|
||||
ctx.Write("success")
|
||||
return
|
||||
}
|
||||
}
|
||||
ctx.Write("fail")
|
||||
|
||||
}
|
||||
|
||||
func (u *userAuth) logout(ctx *iris.Context) {
|
||||
session := panelSessions.Start(ctx)
|
||||
session.Set("user", nil)
|
||||
|
||||
ctx.Redirect("/login")
|
||||
}
|
||||
|
||||
// check if session stored, then check if this user is the correct, each time, then continue, else not
|
||||
func (u *userAuth) Serve(ctx *iris.Context) {
|
||||
if ctx.PathString() == "/login" || strings.HasPrefix(ctx.PathString(), "/public") {
|
||||
ctx.Next()
|
||||
return
|
||||
}
|
||||
session := panelSessions.Start(ctx)
|
||||
|
||||
if sessionVal := session.Get("username"); sessionVal != nil {
|
||||
username := sessionVal.(string)
|
||||
password := session.GetString("password")
|
||||
if username != "" && password != "" {
|
||||
|
||||
for _, authenticatedUser := range u.authenticatedUsers {
|
||||
if authenticatedUser.username == username && authenticatedUser.password == password {
|
||||
ctx.Next()
|
||||
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
//if not logged in the redirect to the /login
|
||||
ctx.Redirect("/login")
|
||||
|
||||
}
|
||||
|
||||
// Destroy this is called on PreClose by the iriscontrol.go
|
||||
func (u *userAuth) Destroy() {
|
||||
|
||||
}
|
||||
61
plugin/routesinfo/README.md
Normal file
61
plugin/routesinfo/README.md
Normal file
@@ -0,0 +1,61 @@
|
||||
## RoutesInfo plugin
|
||||
|
||||
This plugin collects & stores all registered routes and gives information about them.
|
||||
|
||||
#### The RouteInfo
|
||||
|
||||
```go
|
||||
|
||||
type RouteInfo struct {
|
||||
Method string
|
||||
Domain string
|
||||
Path string
|
||||
RegistedAt time.Time
|
||||
}
|
||||
|
||||
```
|
||||
## How to use
|
||||
|
||||
```go
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/plugin/routesinfo"
|
||||
)
|
||||
|
||||
func main() {
|
||||
|
||||
info := routesinfo.New()
|
||||
iris.Plugins().Add(info)
|
||||
|
||||
iris.Get("/yourpath", func(c *iris.Context) {
|
||||
c.Write("yourpath")
|
||||
})
|
||||
|
||||
iris.Post("/otherpostpath", func(c *iris.Context) {
|
||||
c.Write("other post path")
|
||||
})
|
||||
|
||||
all := info.All()
|
||||
// allget := info.ByMethod("GET") -> slice
|
||||
// alllocalhost := info.ByDomain("localhost") -> slice
|
||||
// bypath:= info.ByPath("/yourpath") -> slice
|
||||
// bydomainandmethod:= info.ByDomainAndMethod("localhost","GET") -> slice
|
||||
// bymethodandpath:= info.ByMethodAndPath("GET","/yourpath") -> single (it could be slice for all domains too but it's not)
|
||||
|
||||
println("The first registed route was: ", all[0].Path, "registed at: ", all[0].RegistedAt.String())
|
||||
println("All routes info:")
|
||||
for i:= range all {
|
||||
println(all[i].String())
|
||||
//outputs->
|
||||
// Domain: localhost Method: GET Path: /yourpath RegistedAt: 2016/03/27 15:27:05:029 ...
|
||||
// Domain: localhost Method: POST Path: /otherpostpath RegistedAt: 2016/03/27 15:27:05:030 ...
|
||||
}
|
||||
iris.Listen(":8080")
|
||||
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
151
plugin/routesinfo/routesinfo.go
Normal file
151
plugin/routesinfo/routesinfo.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package routesinfo
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
)
|
||||
|
||||
//Name the name of the plugin, is "RoutesInfo"
|
||||
const Name = "RoutesInfo"
|
||||
|
||||
// RouteInfo holds the method, domain, path and registered time of a route
|
||||
type RouteInfo struct {
|
||||
Method string
|
||||
Domain string
|
||||
Path string
|
||||
RegistedAt time.Time
|
||||
}
|
||||
|
||||
// String returns the string presentation of the Route(Info)
|
||||
func (ri RouteInfo) String() string {
|
||||
if ri.Domain == "" {
|
||||
ri.Domain = "localhost" // only for printing, this doesn't save it, no pointer.
|
||||
}
|
||||
return fmt.Sprintf("Domain: %s Method: %s Path: %s RegistedAt: %s", ri.Domain, ri.Method, ri.Path, ri.RegistedAt.String())
|
||||
}
|
||||
|
||||
// Plugin the routes info plugin, holds the routes as RouteInfo objects
|
||||
type Plugin struct {
|
||||
routes []RouteInfo
|
||||
}
|
||||
|
||||
// implement the base IPlugin
|
||||
|
||||
// GetName ...
|
||||
func (r Plugin) GetName() string {
|
||||
return Name
|
||||
}
|
||||
|
||||
// GetDescription RoutesInfo gives information about the registed routes
|
||||
func (r Plugin) GetDescription() string {
|
||||
return Name + " gives information about the registed routes.\n"
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// implement the rest of the plugin
|
||||
|
||||
// PostHandle collect the registed routes information
|
||||
func (r *Plugin) PostHandle(route iris.IRoute) {
|
||||
if r.routes == nil {
|
||||
r.routes = make([]RouteInfo, 0)
|
||||
}
|
||||
r.routes = append(r.routes, RouteInfo{route.GetMethod(), route.GetDomain(), route.GetPath(), time.Now()})
|
||||
}
|
||||
|
||||
// All returns all routeinfos
|
||||
// returns a slice
|
||||
func (r Plugin) All() []RouteInfo {
|
||||
return r.routes
|
||||
}
|
||||
|
||||
// ByDomain returns all routeinfos which registed to a specific domain
|
||||
// returns a slice, if nothing founds this slice has 0 len&cap
|
||||
func (r Plugin) ByDomain(domain string) []RouteInfo {
|
||||
var routesByDomain []RouteInfo
|
||||
rlen := len(r.routes)
|
||||
if domain == "localhost" || domain == "127.0.0.1" || domain == ":" {
|
||||
domain = ""
|
||||
}
|
||||
for i := 0; i < rlen; i++ {
|
||||
if r.routes[i].Domain == domain {
|
||||
routesByDomain = append(routesByDomain, r.routes[i])
|
||||
}
|
||||
}
|
||||
return routesByDomain
|
||||
}
|
||||
|
||||
// ByMethod returns all routeinfos by a http method
|
||||
// returns a slice, if nothing founds this slice has 0 len&cap
|
||||
func (r Plugin) ByMethod(method string) []RouteInfo {
|
||||
var routesByMethod []RouteInfo
|
||||
rlen := len(r.routes)
|
||||
method = strings.ToUpper(method)
|
||||
for i := 0; i < rlen; i++ {
|
||||
if r.routes[i].Method == method {
|
||||
routesByMethod = append(routesByMethod, r.routes[i])
|
||||
}
|
||||
}
|
||||
return routesByMethod
|
||||
}
|
||||
|
||||
// ByPath returns all routeinfos by a path
|
||||
// maybe one path is the same on GET and POST ( for example /login GET, /login POST)
|
||||
// because of that it returns a slice and not only one RouteInfo
|
||||
// returns a slice, if nothing founds this slice has 0 len&cap
|
||||
func (r Plugin) ByPath(path string) []RouteInfo {
|
||||
var routesByPath []RouteInfo
|
||||
rlen := len(r.routes)
|
||||
for i := 0; i < rlen; i++ {
|
||||
if r.routes[i].Path == path {
|
||||
routesByPath = append(routesByPath, r.routes[i])
|
||||
}
|
||||
}
|
||||
return routesByPath
|
||||
}
|
||||
|
||||
// ByDomainAndMethod returns all routeinfos registed to a specific domain and has specific http method
|
||||
// returns a slice, if nothing founds this slice has 0 len&cap
|
||||
func (r Plugin) ByDomainAndMethod(domain string, method string) []RouteInfo {
|
||||
var routesByDomainAndMethod []RouteInfo
|
||||
rlen := len(r.routes)
|
||||
method = strings.ToUpper(method)
|
||||
if domain == "localhost" || domain == "127.0.0.1" || domain == ":" {
|
||||
domain = ""
|
||||
}
|
||||
|
||||
for i := 0; i < rlen; i++ {
|
||||
if r.routes[i].Method == method && r.routes[i].Domain == domain {
|
||||
routesByDomainAndMethod = append(routesByDomainAndMethod, r.routes[i])
|
||||
}
|
||||
}
|
||||
return routesByDomainAndMethod
|
||||
}
|
||||
|
||||
// ByMethodAndPath returns a single *RouteInfo which has specific http method and path
|
||||
// returns only the first match
|
||||
// if nothing founds returns nil
|
||||
func (r Plugin) ByMethodAndPath(method string, path string) *RouteInfo {
|
||||
|
||||
rlen := len(r.routes)
|
||||
for i := 0; i < rlen; i++ {
|
||||
if r.routes[i].Method == method && r.routes[i].Path == path {
|
||||
return &r.routes[i]
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
//
|
||||
// RoutesInfo returns the Plugin, same as New()
|
||||
func RoutesInfo() *Plugin {
|
||||
return &Plugin{}
|
||||
}
|
||||
|
||||
// New returns the Plugin, same as RoutesInfo()
|
||||
func New() *Plugin {
|
||||
return &Plugin{}
|
||||
}
|
||||
83
plugin/typescript/README.md
Normal file
83
plugin/typescript/README.md
Normal file
@@ -0,0 +1,83 @@
|
||||
## Package information
|
||||
|
||||
This is an Iris and typescript bridge plugin.
|
||||
|
||||
1. Search for typescript files (.ts)
|
||||
2. Search for typescript projects (.tsconfig)
|
||||
3. If 1 || 2 continue else stop
|
||||
4. Check if typescript is installed, if not then auto-install it (always inside npm global modules, -g)
|
||||
5. If typescript project then build the project using tsc -p $dir
|
||||
6. If typescript files and no project then build each typescript using tsc $filename
|
||||
7. Watch typescript files if any changes happens, then re-build (5|6)
|
||||
|
||||
> Note: Ignore all typescript files & projects whose path has '/node_modules/'
|
||||
|
||||
|
||||
## Options
|
||||
|
||||
This plugin has **optionally** options
|
||||
1. Bin: string, the typescript installation path/bin/tsc or tsc.cmd, if empty then it will search to the global npm modules
|
||||
2. Dir: string, Dir set the root, where to search for typescript files/project. Default "./"
|
||||
3. Ignore: string, comma separated ignore typescript files/project from these directories. Default "" (node_modules are always ignored)
|
||||
4. Tsconfig: &typescript.Tsconfig{}, here you can set all compilerOptions if no tsconfig.json exists inside the 'Dir'
|
||||
5. Editor: typescript.Editor(), if setted then alm-tools browser-based typescript IDE will be available. Defailt is nil
|
||||
|
||||
> Note: if any string in Ignore doesn't start with './' then it will ignore all files which contains this path string.
|
||||
For example /node_modules/ will ignore all typescript files that are inside at ANY '/node_modules/', that means and the submodules.
|
||||
|
||||
|
||||
## How to use
|
||||
|
||||
```go
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/plugin/typescript"
|
||||
)
|
||||
|
||||
func main(){
|
||||
/* Options
|
||||
Bin -> the typescript installation path/bin/tsc or tsc.cmd, if empty then it will search to the global npm modules
|
||||
Dir -> where to search for typescript files/project. Default "./"
|
||||
Ignore -> comma separated ignore typescript files/project from these directories (/node_modules/ are always ignored). Default ""
|
||||
Tsconfig -> &typescript.Tsconfig{}, here you can set all compilerOptions if no tsconfig.json exists inside the 'Dir'
|
||||
Editor -> typescript.Editor(), if setted then alm-tools browser-based typescript IDE will be available. Default is nil.
|
||||
*/
|
||||
|
||||
ts := typescript.Options {
|
||||
Dir: "./scripts/src",
|
||||
Tsconfig: &typescript.Tsconfig{Module: "commonjs", Target: "es5"}, // or typescript.DefaultTsconfig()
|
||||
}
|
||||
|
||||
//if you want to change only certain option(s) but you want default to all others then you have to do this:
|
||||
ts = typescript.DefaultOptions()
|
||||
//
|
||||
|
||||
iris.Plugins().Add(typescript.New(ts)) //or with the default options just: typescript.New()
|
||||
|
||||
iris.Get("/", func (ctx *iris.Context){})
|
||||
|
||||
iris.Listen(":8080")
|
||||
}
|
||||
|
||||
|
||||
```
|
||||
|
||||
## Editor
|
||||
|
||||
[alm-tools](http://alm.tools) is a typescript online IDE/Editor, made by [@basarat](https://twitter.com/basarat) one of the top contributors of the [Typescript](http://www.typescriptlang.org).
|
||||
|
||||
Iris gives you the opportunity to edit your client-side using the alm-tools editor, via the editor plugin.
|
||||
With typescript plugin you have to set the Editor option and you're ready:
|
||||
|
||||
```go
|
||||
typescript.Options {
|
||||
//...
|
||||
Editor: typescript.Editor("username","passowrd")
|
||||
//...
|
||||
}
|
||||
```
|
||||
|
||||
> [Read more](https://github.com/kataras/iris/tree/development/plugin/editor) for Editor
|
||||
102
plugin/typescript/tsconfig.go
Normal file
102
plugin/typescript/tsconfig.go
Normal file
@@ -0,0 +1,102 @@
|
||||
package typescript
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"reflect"
|
||||
)
|
||||
|
||||
type (
|
||||
// Tsconfig the struct for tsconfig.json
|
||||
Tsconfig struct {
|
||||
CompilerOptions CompilerOptions `json:"compilerOptions"`
|
||||
Exclude []string `json:"exclude"`
|
||||
}
|
||||
|
||||
// CompilerOptions contains all the compiler options used by the tsc (typescript compiler)
|
||||
CompilerOptions struct {
|
||||
Declaration bool `json:"declaration"`
|
||||
Module string `json:"module"`
|
||||
Target string `json:"target"`
|
||||
Watch bool `json:"watch"`
|
||||
Charset string `json:"charset"`
|
||||
Diagnostics bool `json:"diagnostics"`
|
||||
EmitBOM bool `json:"emitBOM"`
|
||||
EmitDecoratorMetadata bool `json:"emitDecoratorMetadata"`
|
||||
ExperimentalDecorators bool `json:"experimentalDecorators"`
|
||||
InlineSourceMap bool `json:"inlineSourceMap"`
|
||||
InlineSources bool `json:"inlineSources"`
|
||||
IsolatedModules bool `json:"isolatedModules"`
|
||||
Jsx string `json:"jsx"`
|
||||
ReactNamespace string `json:"reactNamespace"`
|
||||
ListFiles bool `json:"listFiles"`
|
||||
Locale string `json:"locale"`
|
||||
MapRoot string `json:"mapRoot"`
|
||||
ModuleResolution string `json:"moduleResolution"`
|
||||
NewLine string `json:"newLine"`
|
||||
NoEmit bool `json:"noEmit"`
|
||||
NoEmitOnError bool `json:"noEmitOnError"`
|
||||
NoEmitHelpers bool `json:"noEmitHelpers"`
|
||||
NoImplicitAny bool `json:"noImplicitAny"`
|
||||
NoLib bool `json:"noLib"`
|
||||
NoResolve bool `json:"noResolve"`
|
||||
SkipDefaultLibCheck bool `json:"skipDefaultLibCheck"`
|
||||
OutDir string `json:"outDir"`
|
||||
OutFile string `json:"outFile"`
|
||||
PreserveConstEnums bool `json:"preserveConstEnums"`
|
||||
Pretty bool `json:"pretty"`
|
||||
RemoveComments bool `json:"removeComments"`
|
||||
RootDir string `json:"rootDir"`
|
||||
SourceMap bool `json:"sourceMap"`
|
||||
SourceRoot string `json:"sourceRoot"`
|
||||
StripInternal bool `json:"stripInternal"`
|
||||
SuppressExcessPropertyErrors bool `json:"suppressExcessPropertyErrors"`
|
||||
SuppressImplicitAnyIndexErrors bool `json:"suppressImplicitAnyIndexErrors"`
|
||||
AllowUnusedLabels bool `json:"allowUnusedLabels"`
|
||||
NoImplicitReturns bool `json:"noImplicitReturns"`
|
||||
NoFallthroughCasesInSwitch bool `json:"noFallthroughCasesInSwitch"`
|
||||
AllowUnreachableCode bool `json:"allowUnreachableCode"`
|
||||
ForceConsistentCasingInFileNames bool `json:"forceConsistentCasingInFileNames"`
|
||||
AllowSyntheticDefaultImports bool `json:"allowSyntheticDefaultImports"`
|
||||
AllowJs bool `json:"allowJs"`
|
||||
NoImplicitUseStrict bool `json:"noImplicitUseStrict"`
|
||||
}
|
||||
)
|
||||
|
||||
// CompilerArgs returns the CompilerOptions' contents of the Tsconfig
|
||||
// it reads the json tags, add '--' at the start of each one and returns an array of strings
|
||||
func (tsconfig *Tsconfig) CompilerArgs() []string {
|
||||
val := reflect.ValueOf(tsconfig).Elem().FieldByName("CompilerOptions")
|
||||
compilerOpts := make([]string, val.NumField())
|
||||
for i := 0; i < val.NumField(); i++ {
|
||||
typeField := val.Type().Field(i)
|
||||
compilerOpts[i] = "--" + typeField.Tag.Get("json")
|
||||
}
|
||||
|
||||
return compilerOpts
|
||||
}
|
||||
|
||||
// FromFile reads a file & returns the Tsconfig by its contents
|
||||
func FromFile(tsConfigAbsPath string) *Tsconfig {
|
||||
file, err := ioutil.ReadFile(tsConfigAbsPath)
|
||||
if err != nil {
|
||||
panic("[IRIS TypescriptPlugin.FromFile]" + err.Error())
|
||||
}
|
||||
config := &Tsconfig{}
|
||||
json.Unmarshal(file, config)
|
||||
return config
|
||||
}
|
||||
|
||||
// DefaultTsconfig returns the default Tsconfig, with CompilerOptions module: commonjs, target: es5 and ignore the node_modules
|
||||
func DefaultTsconfig() *Tsconfig {
|
||||
return &Tsconfig{
|
||||
CompilerOptions: CompilerOptions{
|
||||
Module: "commonjs",
|
||||
Target: "es5",
|
||||
NoImplicitAny: false,
|
||||
SourceMap: false,
|
||||
},
|
||||
Exclude: []string{"node_modules"},
|
||||
}
|
||||
|
||||
}
|
||||
300
plugin/typescript/typescript.go
Normal file
300
plugin/typescript/typescript.go
Normal file
@@ -0,0 +1,300 @@
|
||||
package typescript
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
"github.com/kataras/iris"
|
||||
"github.com/kataras/iris/config"
|
||||
"github.com/kataras/iris/logger"
|
||||
"github.com/kataras/iris/npm"
|
||||
"github.com/kataras/iris/plugin/editor"
|
||||
"github.com/kataras/iris/utils"
|
||||
)
|
||||
|
||||
/* Notes
|
||||
|
||||
The editor is working when the typescript plugin finds a typescript project (tsconfig.json),
|
||||
also working only if one typescript project found (normaly is one for client-side).
|
||||
|
||||
*/
|
||||
|
||||
// Name the name of the plugin, is "TypescriptPlugin"
|
||||
const Name = "TypescriptPlugin"
|
||||
|
||||
var nodeModules = utils.PathSeparator + "node_modules" + utils.PathSeparator
|
||||
|
||||
type (
|
||||
// Options the struct which holds the TypescriptPlugin options
|
||||
// Has five (5) fields
|
||||
//
|
||||
// 1. Bin: string, the typescript installation directory/typescript/lib/tsc.js, if empty it will search inside global npm modules
|
||||
// 2. Dir: string, Dir set the root, where to search for typescript files/project. Default "./"
|
||||
// 3. Ignore: string, comma separated ignore typescript files/project from these directories. Default "" (node_modules are always ignored)
|
||||
// 4. Tsconfig: &typescript.Tsconfig{}, here you can set all compilerOptions if no tsconfig.json exists inside the 'Dir'
|
||||
// 5. Editor: typescript.Editor("username","password"), if setted then alm-tools browser-based typescript IDE will be available. Defailt is nil
|
||||
Options struct {
|
||||
Bin string
|
||||
Dir string
|
||||
Ignore string
|
||||
Tsconfig *Tsconfig
|
||||
Editor *editor.Plugin // the editor is just a plugin also
|
||||
}
|
||||
// Plugin the struct of the Typescript Plugin, holds all necessary fields & methods
|
||||
Plugin struct {
|
||||
options Options
|
||||
// taken from Activate
|
||||
pluginContainer iris.IPluginContainer
|
||||
// taken at the PreListen
|
||||
logger *logger.Logger
|
||||
}
|
||||
)
|
||||
|
||||
// Editor is just a shortcut for github.com/kataras/iris/plugin/editor.New()
|
||||
// returns a new (Editor)Plugin, it's exists here because the typescript plugin has direct interest with the EditorPlugin
|
||||
func Editor(username, password string) *editor.Plugin {
|
||||
editorCfg := config.DefaultEditor()
|
||||
editorCfg.Username = username
|
||||
editorCfg.Password = password
|
||||
return editor.New(editorCfg)
|
||||
}
|
||||
|
||||
// DefaultOptions returns the default Options of the Plugin
|
||||
func DefaultOptions() Options {
|
||||
root, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic("Typescript Plugin: Cannot get the Current Working Directory !!! [os.getwd()]")
|
||||
}
|
||||
opt := Options{Dir: root + utils.PathSeparator, Ignore: nodeModules, Tsconfig: DefaultTsconfig()}
|
||||
opt.Bin = npm.Abs("typescript/lib/tsc.js")
|
||||
return opt
|
||||
|
||||
}
|
||||
|
||||
// Plugin
|
||||
|
||||
// New creates & returns a new instnace typescript plugin
|
||||
func New(_opt ...Options) *Plugin {
|
||||
var options = DefaultOptions()
|
||||
|
||||
if _opt != nil && len(_opt) > 0 { //not nil always but I like this way :)
|
||||
opt := _opt[0]
|
||||
|
||||
if opt.Bin != "" {
|
||||
options.Bin = opt.Bin
|
||||
}
|
||||
if opt.Dir != "" {
|
||||
options.Dir = opt.Dir
|
||||
}
|
||||
|
||||
if !strings.Contains(opt.Ignore, nodeModules) {
|
||||
opt.Ignore += "," + nodeModules
|
||||
}
|
||||
|
||||
if opt.Tsconfig != nil {
|
||||
options.Tsconfig = opt.Tsconfig
|
||||
}
|
||||
|
||||
options.Ignore = opt.Ignore
|
||||
}
|
||||
|
||||
return &Plugin{options: options}
|
||||
}
|
||||
|
||||
// implement the IPlugin & IPluginPreListen
|
||||
|
||||
// Activate ...
|
||||
func (t *Plugin) Activate(container iris.IPluginContainer) error {
|
||||
t.pluginContainer = container
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetName ...
|
||||
func (t *Plugin) GetName() string {
|
||||
return Name + "[" + utils.RandomString(10) + "]" // this allows the specific plugin to be registed more than one time
|
||||
}
|
||||
|
||||
// GetDescription TypescriptPlugin scans and compile typescript files with ease
|
||||
func (t *Plugin) GetDescription() string {
|
||||
return Name + " scans and compile typescript files with ease. \n"
|
||||
}
|
||||
|
||||
// PreListen ...
|
||||
func (t *Plugin) PreListen(s *iris.Iris) {
|
||||
t.logger = s.Logger()
|
||||
t.start()
|
||||
}
|
||||
|
||||
//
|
||||
|
||||
// implementation
|
||||
|
||||
func (t *Plugin) start() {
|
||||
defaultCompilerArgs := t.options.Tsconfig.CompilerArgs() //these will be used if no .tsconfig found.
|
||||
if t.hasTypescriptFiles() {
|
||||
//Can't check if permission denied returns always exists = true....
|
||||
//typescriptModule := out + string(os.PathSeparator) + "typescript" + string(os.PathSeparator) + "bin"
|
||||
if !npm.Exists(t.options.Bin) {
|
||||
t.logger.Println("Installing typescript, please wait...")
|
||||
res := npm.Install("typescript")
|
||||
if res.Error != nil {
|
||||
t.logger.Print(res.Error.Error())
|
||||
return
|
||||
}
|
||||
t.logger.Print(res.Message)
|
||||
|
||||
}
|
||||
|
||||
projects := t.getTypescriptProjects()
|
||||
if len(projects) > 0 {
|
||||
watchedProjects := 0
|
||||
//typescript project (.tsconfig) found
|
||||
for _, project := range projects {
|
||||
cmd := utils.CommandBuilder("node", t.options.Bin, "-p", project[0:strings.LastIndex(project, utils.PathSeparator)]) //remove the /tsconfig.json)
|
||||
projectConfig := FromFile(project)
|
||||
|
||||
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.logger.Println(err.Error())
|
||||
return
|
||||
}
|
||||
}()
|
||||
} else {
|
||||
|
||||
_, err := cmd.Output()
|
||||
if err != nil {
|
||||
t.logger.Println(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
t.logger.Printf("%d Typescript project(s) compiled ( %d monitored by a background file watcher ) ", len(projects), watchedProjects)
|
||||
} else {
|
||||
//search for standalone typescript (.ts) files and compile them
|
||||
files := t.getTypescriptFiles()
|
||||
|
||||
if len(files) > 0 {
|
||||
watchedFiles := 0
|
||||
if t.options.Tsconfig.CompilerOptions.Watch {
|
||||
watchedFiles = len(files)
|
||||
}
|
||||
//it must be always > 0 if we came here, because of if hasTypescriptFiles == true.
|
||||
for _, file := range files {
|
||||
cmd := utils.CommandBuilder("node", t.options.Bin)
|
||||
cmd.AppendArguments(defaultCompilerArgs...)
|
||||
cmd.AppendArguments(file)
|
||||
_, err := cmd.Output()
|
||||
cmd.Args = cmd.Args[0 : len(cmd.Args)-1] //remove the last, which is the file
|
||||
if err != nil {
|
||||
t.logger.Println(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
}
|
||||
t.logger.Printf("%d Typescript file(s) compiled ( %d monitored by a background file watcher )", len(files), watchedFiles)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//editor activation
|
||||
if len(projects) == 1 && t.options.Editor != nil {
|
||||
dir := projects[0][0:strings.LastIndex(projects[0], utils.PathSeparator)]
|
||||
t.options.Editor.Dir(dir)
|
||||
t.pluginContainer.Add(t.options.Editor)
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
func (t *Plugin) hasTypescriptFiles() bool {
|
||||
root := t.options.Dir
|
||||
ignoreFolders := strings.Split(t.options.Ignore, ",")
|
||||
hasTs := false
|
||||
|
||||
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
||||
|
||||
if fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
for i := range ignoreFolders {
|
||||
if strings.Contains(path, ignoreFolders[i]) {
|
||||
return nil
|
||||
}
|
||||
}
|
||||
if strings.HasSuffix(path, ".ts") {
|
||||
hasTs = true
|
||||
return errors.New("Typescript found, hope that will stop here")
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return hasTs
|
||||
}
|
||||
|
||||
func (t *Plugin) getTypescriptProjects() []string {
|
||||
var projects []string
|
||||
ignoreFolders := strings.Split(t.options.Ignore, ",")
|
||||
|
||||
root := t.options.Dir
|
||||
//t.logger.Printf("\nSearching for typescript projects in %s", root)
|
||||
|
||||
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
||||
if fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
for i := range ignoreFolders {
|
||||
if strings.Contains(path, ignoreFolders[i]) {
|
||||
//t.logger.Println(path + " ignored")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasSuffix(path, utils.PathSeparator+"tsconfig.json") {
|
||||
//t.logger.Printf("\nTypescript project found in %s", path)
|
||||
projects = append(projects, path)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return projects
|
||||
}
|
||||
|
||||
// this is being called if getTypescriptProjects return 0 len, then we are searching for files using that:
|
||||
func (t *Plugin) getTypescriptFiles() []string {
|
||||
var files []string
|
||||
ignoreFolders := strings.Split(t.options.Ignore, ",")
|
||||
|
||||
root := t.options.Dir
|
||||
//t.logger.Printf("\nSearching for typescript files in %s", root)
|
||||
|
||||
filepath.Walk(root, func(path string, fi os.FileInfo, err error) error {
|
||||
if fi.IsDir() {
|
||||
return nil
|
||||
}
|
||||
for i := range ignoreFolders {
|
||||
if strings.Contains(path, ignoreFolders[i]) {
|
||||
//t.logger.Println(path + " ignored")
|
||||
return nil
|
||||
}
|
||||
}
|
||||
|
||||
if strings.HasSuffix(path, ".ts") {
|
||||
//t.logger.Printf("\nTypescript file found in %s", path)
|
||||
files = append(files, path)
|
||||
}
|
||||
|
||||
return nil
|
||||
})
|
||||
return files
|
||||
}
|
||||
|
||||
//
|
||||
//
|
||||
Reference in New Issue
Block a user