mirror of
https://github.com/kataras/iris.git
synced 2025-01-23 02:31:04 +01:00
remove the 'typescript' package entirely in favor of iris-cli and because the alm editor was deprecated by its author (consider using the designtsx.com instead)
Former-commit-id: 52888ae3fd0da9e5b98e095c665a1a538381ddef
This commit is contained in:
parent
340664dca9
commit
c5392ede6a
|
@ -18,11 +18,6 @@ after_script:
|
|||
- go get ./...
|
||||
- go test -count=1 -v -cover ./...
|
||||
- cd ../
|
||||
# typescript examples
|
||||
- cd ./typescript/_examples
|
||||
- go get ./...
|
||||
- go test -count=1 -v -cover ./...
|
||||
- cd ../../
|
||||
# make sure that the _benchmarks code is working
|
||||
- cd ./_benchmarks
|
||||
- go get ./...
|
||||
|
|
|
@ -204,7 +204,8 @@ Breaking Changes:
|
|||
|
||||
- `var mvc.AutoBinding` removed as the default behavior now resolves such dependencies automatically (see [[FEATURE REQUEST] MVC serving gRPC-compatible controller](https://github.com/kataras/iris/issues/1449))
|
||||
- `mvc#Application.SortByNumMethods()` removed as the default behavior now binds the "thinnest" empty `interface{}` automatically (see [MVC: service injecting fails](https://github.com/kataras/iris/issues/1343))
|
||||
- `mvc#BeforeActivation.Dependencies().Add` should be replaced with `mvc#BeforeActivation.Dependencies().Register` instead.
|
||||
- `mvc#BeforeActivation.Dependencies().Add` should be replaced with `mvc#BeforeActivation.Dependencies().Register` instead
|
||||
- **REMOVE** the `kataras/iris/v12/typescript` package in favor of the new [iris-cli](https://github.com/kataras/iris-cli). Also, the alm typescript online editor was removed as it is deprecated by its author, please consider using the [designtsx](https://designtsx.com/) instead.
|
||||
|
||||
# Su, 16 February 2020 | v12.1.8
|
||||
|
||||
|
|
|
@ -357,12 +357,6 @@ iris session manager lives on its own [package](https://github.com/kataras/iris/
|
|||
- [Native Messages](websocket/native-messages/main.go)
|
||||
- [TLS Enabled](websocket/secure/README.md)
|
||||
|
||||
### Typescript Automation Tools
|
||||
|
||||
typescript automation tools have their own repository: [https://github.com/kataras/iris/tree/master/typescript](https://github.com/kataras/iris/tree/master/typescript) **it contains examples**
|
||||
|
||||
> I'd like to tell you that you can use your favourite but I don't think you will find such a thing anywhere else.
|
||||
|
||||
### Hey, You
|
||||
|
||||
Developers should read the [godocs](https://godoc.org/github.com/kataras/iris) and https://docs.iris-go.com for a better understanding.
|
||||
|
|
|
@ -441,10 +441,6 @@ Iris session 管理独立包 [package](https://github.com/kataras/iris/tree/mast
|
|||
- [原生消息](websocket/native-messages/main.go) **更新**
|
||||
- [TLS支持](websocket/secure/README.md)
|
||||
|
||||
### Typescript 自动化工具
|
||||
|
||||
Typescript 自动化工具独立库: [https://github.com/kataras/iris/tree/master/typescript](https://github.com/kataras/iris/tree/master/typescript) **包含相关示例**
|
||||
|
||||
### 大兄弟
|
||||
|
||||
进一步学习可通过 [godocs](https://godoc.org/github.com/kataras/iris) 和 https://docs.iris-go.com
|
||||
|
|
|
@ -1,9 +0,0 @@
|
|||
# Typescript
|
||||
|
||||
[Typescript](http://www.typescriptlang.org/) and [alm-tools cloud editor](http://alm.tools/) automation tools for the [iris](https://github.com/kataras/iris) web framework.
|
||||
|
||||
|
||||
## Table of contents
|
||||
|
||||
* [Typescript compiler](_examples/typescript/main.go)
|
||||
* [Alm-tools cloud editor](_examples/editor/main.go)
|
|
@ -1,33 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris/v12"
|
||||
|
||||
"github.com/kataras/iris/v12/typescript/editor"
|
||||
)
|
||||
|
||||
func main() {
|
||||
app := iris.New()
|
||||
app.HandleDir("/scripts", "./www/scripts") // serve the scripts
|
||||
// when you edit a typescript file from the alm-tools
|
||||
// it compiles it to javascript, have fun!
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.ServeFile("./www/index.html", false)
|
||||
})
|
||||
|
||||
editorConfig := editor.Config{
|
||||
Hostname: "localhost",
|
||||
Port: 4444,
|
||||
WorkingDir: "./www/scripts/", // "/path/to/the/client/side/directory/",
|
||||
Username: "myusername",
|
||||
Password: "mypassword",
|
||||
}
|
||||
e := editor.New(editorConfig)
|
||||
e.Run(app.Logger().Infof) // start the editor's server
|
||||
|
||||
// http://localhost:8080
|
||||
// http://localhost:4444
|
||||
app.Listen(":8080")
|
||||
e.Stop()
|
||||
}
|
|
@ -1,8 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Load my script</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="scripts/app.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,12 +0,0 @@
|
|||
var User = (function () {
|
||||
function User(fullname) {
|
||||
this.name = fullname;
|
||||
}
|
||||
User.prototype.Hi = function (msg) {
|
||||
return msg + " " + this.name;
|
||||
};
|
||||
return User;
|
||||
}());
|
||||
var user = new User("iris web framework!");
|
||||
var hi = user.Hi("Hello");
|
||||
window.alert(hi);
|
|
@ -1,16 +0,0 @@
|
|||
class User{
|
||||
private name: string;
|
||||
|
||||
constructor(fullname:string) {
|
||||
this.name = fullname;
|
||||
}
|
||||
|
||||
Hi(msg: string): string {
|
||||
return msg + " " + this.name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var user = new User("iris web framework!");
|
||||
var hi = user.Hi("Hello");
|
||||
window.alert(hi);
|
|
@ -1,22 +0,0 @@
|
|||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"noImplicitAny": false,
|
||||
"removeComments": true,
|
||||
"preserveConstEnums": true,
|
||||
"sourceMap": false,
|
||||
"target": "ES5",
|
||||
"noEmit": false,
|
||||
"watch":true,
|
||||
"noEmitOnError": true,
|
||||
"experimentalDecorators": false,
|
||||
"outDir": "./",
|
||||
"charset": "UTF-8",
|
||||
"noLib": false,
|
||||
"diagnostics": true,
|
||||
"declaration": false
|
||||
},
|
||||
"files": [
|
||||
"./app.ts"
|
||||
]
|
||||
}
|
|
@ -1,40 +0,0 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"github.com/kataras/iris/v12"
|
||||
|
||||
"github.com/kataras/iris/v12/typescript"
|
||||
)
|
||||
|
||||
// NOTE: Some machines don't allow to install typescript automatically, so if you don't have typescript installed
|
||||
// and the typescript adaptor doesn't works for you then follow the below steps:
|
||||
// 1. close the iris server
|
||||
// 2. open your terminal and execute: npm install -g typescript
|
||||
// 3. start your iris server, it should be work, as expected, now.
|
||||
func main() {
|
||||
app := iris.New()
|
||||
|
||||
app.HandleDir("/scripts", "./www") // serve the scripts
|
||||
|
||||
app.Get("/", func(ctx iris.Context) {
|
||||
ctx.ServeFile("./www/index.html", false)
|
||||
})
|
||||
|
||||
ts := typescript.New()
|
||||
ts.Config.Dir = "./www/scripts"
|
||||
ts.Run(app.Logger().Infof)
|
||||
|
||||
// http://localhost:8080
|
||||
app.Listen(":8080")
|
||||
}
|
||||
|
||||
// open http://localhost:8080
|
||||
// go to ./www/scripts/app.ts
|
||||
// make a change
|
||||
// reload the http://localhost:8080 and you should see the changes
|
||||
//
|
||||
// what it does?
|
||||
// - compiles the typescript files using default compiler options if not tsconfig found
|
||||
// - watches for changes on typescript files, if a change then it recompiles the .ts to .js
|
||||
//
|
||||
// same as you used to do with gulp-like tools, but here I do my bests to help GO developers.
|
|
@ -1,8 +0,0 @@
|
|||
<html>
|
||||
<head>
|
||||
<title>Load my script</title>
|
||||
</head>
|
||||
<body>
|
||||
<script src="scripts/app.js"></script>
|
||||
</body>
|
||||
</html>
|
|
@ -1,16 +0,0 @@
|
|||
class User{
|
||||
private name: string;
|
||||
|
||||
constructor(fullname:string) {
|
||||
this.name = fullname;
|
||||
}
|
||||
|
||||
Hi(msg: string): string {
|
||||
return msg + " "+ this.name;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var user = new User("iris web framework");
|
||||
var hi = user.Hi("Hello");
|
||||
window.alert(hi);
|
|
@ -1,194 +0,0 @@
|
|||
package typescript
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"reflect"
|
||||
"strconv"
|
||||
|
||||
"github.com/kataras/iris/v12/typescript/npm"
|
||||
)
|
||||
|
||||
var (
|
||||
pathSeparator = string(os.PathSeparator)
|
||||
nodeModules = pathSeparator + "node_modules" + pathSeparator
|
||||
)
|
||||
|
||||
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"`
|
||||
}
|
||||
|
||||
// Config the configs for the Typescript plugin
|
||||
// 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 set then alm-tools browser-based typescript IDE will be available. Defailt is nil
|
||||
Config struct {
|
||||
// Bin the path of the tsc binary file
|
||||
// if empty then the plugin tries to find it
|
||||
Bin string
|
||||
// Dir the client side directory, which typescript (.ts) files are live
|
||||
Dir string
|
||||
// Ignore ignore folders, default is /node_modules/
|
||||
Ignore string
|
||||
// Tsconfig the typescript build configs, including the compiler's options
|
||||
Tsconfig *Tsconfig
|
||||
}
|
||||
)
|
||||
|
||||
// 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
|
||||
// this is from file
|
||||
func (tsconfig *Tsconfig) CompilerArgs() []string {
|
||||
val := reflect.ValueOf(tsconfig).Elem().FieldByName("CompilerOptions") // -> for tsconfig *Tsconfig
|
||||
// val := reflect.ValueOf(tsconfig.CompilerOptions)
|
||||
compilerOpts := make([]string, 0) // 0 because we don't know the real valid options yet.
|
||||
for i := 0; i < val.NumField(); i++ {
|
||||
typeField := val.Type().Field(i)
|
||||
valueFieldG := val.Field(i)
|
||||
var valueField string
|
||||
// only if it's string or int we need to put that
|
||||
if valueFieldG.Kind() == reflect.String {
|
||||
// if valueFieldG.String() != "" {
|
||||
// valueField = strconv.QuoteToASCII(valueFieldG.String())
|
||||
// }
|
||||
valueField = valueFieldG.String()
|
||||
} else if valueFieldG.Kind() == reflect.Int {
|
||||
if valueFieldG.Int() > 0 {
|
||||
valueField = strconv.Itoa(int(valueFieldG.Int()))
|
||||
}
|
||||
} else if valueFieldG.Kind() == reflect.Bool {
|
||||
valueField = strconv.FormatBool(valueFieldG.Bool())
|
||||
}
|
||||
|
||||
if valueField != "" && valueField != "false" {
|
||||
// var opt string
|
||||
|
||||
// key := typeField.Tag.Get("json")
|
||||
// // it's bool value of true then just --key, for example --watch
|
||||
// if valueField == "true" {
|
||||
// opt = "--" + key
|
||||
// } else {
|
||||
// // it's a string now, for example -m commonjs
|
||||
// opt = "-" + string(key[0]) + " " + valueField
|
||||
// }
|
||||
key := "--" + typeField.Tag.Get("json")
|
||||
compilerOpts = append(compilerOpts, key)
|
||||
// the form is not '--module ES6' but os.Exec should recognise them as arguments
|
||||
// so we need to put the values on the next index
|
||||
if valueField != "true" {
|
||||
// it's a string now, for example -m commonjs
|
||||
compilerOpts = append(compilerOpts, valueField)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return compilerOpts
|
||||
}
|
||||
|
||||
// FromFile reads a file & returns the Tsconfig by its contents
|
||||
func FromFile(tsConfigAbsPath string) (config Tsconfig, err error) {
|
||||
file, err := ioutil.ReadFile(tsConfigAbsPath)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
config = Tsconfig{}
|
||||
err = json.Unmarshal(file, &config)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// 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: "ES6",
|
||||
Jsx: "react",
|
||||
ModuleResolution: "classic",
|
||||
Locale: "en",
|
||||
Watch: false,
|
||||
NoImplicitAny: false,
|
||||
SourceMap: false,
|
||||
Diagnostics: true,
|
||||
NoEmit: false,
|
||||
OutDir: "", // taken from Config.Dir if it's not empty, otherwise ./ on Run()
|
||||
},
|
||||
Exclude: []string{"node_modules"},
|
||||
}
|
||||
}
|
||||
|
||||
// DefaultConfig returns the default Options of the Typescript adaptor
|
||||
// Bin and Editor are setting in runtime via the adaptor
|
||||
func DefaultConfig() Config {
|
||||
root, err := os.Getwd()
|
||||
if err != nil {
|
||||
panic("typescript: cannot get the cwd")
|
||||
}
|
||||
compilerTsConfig := DefaultTsconfig()
|
||||
c := Config{
|
||||
Dir: root + pathSeparator,
|
||||
Ignore: nodeModules,
|
||||
Tsconfig: &compilerTsConfig,
|
||||
}
|
||||
c.Bin = npm.NodeModuleAbs("typescript/lib/tsc.js")
|
||||
return c
|
||||
}
|
|
@ -1,46 +0,0 @@
|
|||
package editor
|
||||
|
||||
import (
|
||||
"os"
|
||||
)
|
||||
|
||||
// Default values for the configuration
|
||||
const (
|
||||
DefaultPort = 4444
|
||||
)
|
||||
|
||||
// Config the configs for the Editor plugin
|
||||
type Config struct {
|
||||
// Hostname if empty used the iris server's hostname
|
||||
Hostname string
|
||||
// Port if 0 4444
|
||||
Port int
|
||||
// KeyFile the key file(ssl optional)
|
||||
KeyFile string
|
||||
// CertFile the cert file (ssl optional)
|
||||
CertFile string
|
||||
// WorkingDir if empty "./"
|
||||
WorkingDir string
|
||||
// Username defaults to empty, you should set this
|
||||
Username string
|
||||
// Password defaults to empty, you should set this
|
||||
Password string
|
||||
// DisableOutput set that to true if you don't care about alm-tools' messages
|
||||
// they are useful because that the default value is "false"
|
||||
DisableOutput bool
|
||||
}
|
||||
|
||||
// DefaultConfig returns the default configs for the Editor plugin
|
||||
func DefaultConfig() Config {
|
||||
// explicit
|
||||
return Config{
|
||||
Hostname: "",
|
||||
Port: 4444,
|
||||
KeyFile: "",
|
||||
CertFile: "",
|
||||
WorkingDir: "." + string(os.PathSeparator), // alm-tools should end with path separator.
|
||||
Username: "",
|
||||
Password: "",
|
||||
DisableOutput: false,
|
||||
}
|
||||
}
|
|
@ -1,209 +0,0 @@
|
|||
package editor
|
||||
|
||||
/* Package editor provides alm-tools cloud editor automation for the iris web framework.
|
||||
|
||||
Usage:
|
||||
|
||||
|
||||
import "github.com/kataras/iris/v12/typescript/editor"
|
||||
[...]
|
||||
|
||||
app := iris.New()
|
||||
e := editor.New(editor.Config{})
|
||||
e.Run(app.Logger().Infof)
|
||||
|
||||
[...]
|
||||
app.Listen(":8080")
|
||||
e.Stop()
|
||||
|
||||
|
||||
General notes for authentication
|
||||
|
||||
|
||||
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 (
|
||||
"bufio"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strconv"
|
||||
|
||||
"github.com/kataras/iris/v12/typescript/npm"
|
||||
)
|
||||
|
||||
type (
|
||||
// Editor is the alm-tools adaptor.
|
||||
//
|
||||
// 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
|
||||
Editor struct {
|
||||
config *Config
|
||||
log func(format string, a ...interface{})
|
||||
enabled bool // default true
|
||||
// after alm started
|
||||
process *os.Process
|
||||
}
|
||||
)
|
||||
|
||||
// NoOpLogger can be used as the logger argument, it prints nothing.
|
||||
var NoOpLogger = func(string, ...interface{}) {}
|
||||
|
||||
// New creates and returns an Editor Plugin instance
|
||||
func New(cfg ...Config) *Editor {
|
||||
c := DefaultConfig()
|
||||
if len(cfg) > 0 {
|
||||
c = cfg[0]
|
||||
}
|
||||
c.WorkingDir = validateWorkingDir(c.WorkingDir) // add "/" if not exists
|
||||
|
||||
return &Editor{
|
||||
enabled: true,
|
||||
config: &c,
|
||||
}
|
||||
}
|
||||
|
||||
// User set a user, accepts two parameters: username (string), string (string)
|
||||
func (e *Editor) User(username string, password string) *Editor {
|
||||
e.config.Username = username
|
||||
e.config.Password = password
|
||||
return e
|
||||
}
|
||||
|
||||
func validateWorkingDir(workingDir string) string {
|
||||
l := workingDir[len(workingDir)-1]
|
||||
|
||||
if l != '/' && l != os.PathSeparator {
|
||||
workingDir += "/"
|
||||
}
|
||||
return workingDir
|
||||
}
|
||||
|
||||
// Dir sets the directory which the client side source code alive
|
||||
func (e *Editor) Dir(workingDir string) *Editor {
|
||||
e.config.WorkingDir = validateWorkingDir(workingDir)
|
||||
return e
|
||||
}
|
||||
|
||||
// Port sets the port (int) for the editor adaptor's standalone server
|
||||
func (e *Editor) Port(port int) *Editor {
|
||||
e.config.Port = port
|
||||
return e
|
||||
}
|
||||
|
||||
// SetEnable if true enables the editor adaptor, otherwise disables it
|
||||
func (e *Editor) SetEnable(enable bool) {
|
||||
e.enabled = enable
|
||||
}
|
||||
|
||||
// DisableOutput call that if you don't care about alm-tools' messages
|
||||
// they are useful because that the default configuration shows them
|
||||
func (e *Editor) DisableOutput() {
|
||||
e.config.DisableOutput = true
|
||||
}
|
||||
|
||||
// GetDescription EditorPlugin is a bridge between iris and the alm-tools, the browser-based IDE for client-side sources.
|
||||
func (e *Editor) GetDescription() string {
|
||||
return "A bridge between iris and the alm-tools, the browser-based IDE."
|
||||
}
|
||||
|
||||
// Run starts the editor's server.
|
||||
//
|
||||
// Developers should call the `Stop` to shutdown the editor's server when main server will be closed.
|
||||
func (e *Editor) Run(logger func(format string, a ...interface{})) {
|
||||
if logger == nil {
|
||||
logger = NoOpLogger
|
||||
}
|
||||
|
||||
e.log = logger
|
||||
if e.config.Hostname == "" {
|
||||
e.config.Hostname = "0.0.0.0"
|
||||
}
|
||||
|
||||
if e.config.Port <= 0 {
|
||||
e.config.Port = DefaultPort
|
||||
}
|
||||
|
||||
if s, err := filepath.Abs(e.config.WorkingDir); err == nil {
|
||||
e.config.WorkingDir = s
|
||||
}
|
||||
|
||||
e.start()
|
||||
}
|
||||
|
||||
// Stop kills the editor's server.
|
||||
func (e *Editor) Stop() {
|
||||
if e.process != nil {
|
||||
err := e.process.Kill()
|
||||
if err != nil {
|
||||
e.log("error while trying to terminate the Editor,please kill this process by yourself, process id: %d", e.process.Pid)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// start starts the job
|
||||
func (e *Editor) start() {
|
||||
if e.config.Username == "" || e.config.Password == "" {
|
||||
e.log("error before running alm-tools. You have to set username & password for security reasons, otherwise this adaptor won't run.")
|
||||
return
|
||||
}
|
||||
|
||||
if !npm.NodeModuleExists("alm/bin/alm") {
|
||||
e.log("installing alm-tools, please wait...")
|
||||
res := npm.NodeModuleInstall("alm")
|
||||
if res.Error != nil {
|
||||
e.log(res.Error.Error())
|
||||
return
|
||||
}
|
||||
e.log(res.Message)
|
||||
}
|
||||
|
||||
cmd := npm.CommandBuilder("node", npm.NodeModuleAbs("alm/src/server.js"))
|
||||
cmd.AppendArguments("-a", e.config.Username+":"+e.config.Password,
|
||||
"-h", e.config.Hostname, "-t", strconv.Itoa(e.config.Port), "-d", e.config.WorkingDir)
|
||||
// for auto-start in the browser: cmd.AppendArguments("-o")
|
||||
if e.config.KeyFile != "" && e.config.CertFile != "" {
|
||||
cmd.AppendArguments("--httpskey", e.config.KeyFile, "--httpscert", e.config.CertFile)
|
||||
}
|
||||
|
||||
prefix := ""
|
||||
// when debug is not disabled
|
||||
// show any messages to the user( they are useful here)
|
||||
// to the io.Writer that iris' user is defined from configuration
|
||||
if !e.config.DisableOutput {
|
||||
|
||||
outputReader, err := cmd.StdoutPipe()
|
||||
if err == nil {
|
||||
outputScanner := bufio.NewScanner(outputReader)
|
||||
|
||||
go func() {
|
||||
for outputScanner.Scan() {
|
||||
e.log(prefix + outputScanner.Text())
|
||||
}
|
||||
}()
|
||||
|
||||
errReader, err := cmd.StderrPipe()
|
||||
if err == nil {
|
||||
errScanner := bufio.NewScanner(errReader)
|
||||
go func() {
|
||||
for errScanner.Scan() {
|
||||
e.log(prefix + errScanner.Text())
|
||||
}
|
||||
}()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
err := cmd.Start()
|
||||
if err != nil {
|
||||
e.log(prefix + err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// no need, alm-tools post these
|
||||
// e.logger.Printf("Editor is running at %s:%d | %s", e.config.Hostname, e.config.Port, e.config.WorkingDir)
|
||||
}
|
|
@ -1,112 +0,0 @@
|
|||
package npm // #nosec
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
)
|
||||
|
||||
// PathSeparator is the string of os.PathSeparator
|
||||
var PathSeparator = string(os.PathSeparator)
|
||||
|
||||
type (
|
||||
// Cmd is a custom struch which 'implements' the *exec.Cmd
|
||||
Cmd struct {
|
||||
*exec.Cmd
|
||||
}
|
||||
)
|
||||
|
||||
// Arguments sets the command line arguments, including the command as Args[0].
|
||||
// If the args parameter is empty or nil, Run uses {Path}.
|
||||
//
|
||||
// In typical use, both Path and args are set by calling Command.
|
||||
func (cmd *Cmd) Arguments(args ...string) *Cmd {
|
||||
cmd.Cmd.Args = append(cmd.Cmd.Args[0:1], args...) // we need the first argument which is the command
|
||||
return cmd
|
||||
}
|
||||
|
||||
// AppendArguments appends the arguments to the exists
|
||||
func (cmd *Cmd) AppendArguments(args ...string) *Cmd {
|
||||
cmd.Cmd.Args = append(cmd.Cmd.Args, args...)
|
||||
return cmd
|
||||
}
|
||||
|
||||
// ResetArguments resets the arguments
|
||||
func (cmd *Cmd) ResetArguments() *Cmd {
|
||||
cmd.Args = cmd.Args[0:1] // keep only the first because is the command
|
||||
return cmd
|
||||
}
|
||||
|
||||
// Directory sets the working directory of the command.
|
||||
// If workingDirectory is the empty string, Run runs the command in the
|
||||
// calling process's current directory.
|
||||
func (cmd *Cmd) Directory(workingDirectory string) *Cmd {
|
||||
cmd.Cmd.Dir = workingDirectory
|
||||
return cmd
|
||||
}
|
||||
|
||||
// CommandBuilder creates a Cmd object and returns it
|
||||
// accepts 2 parameters, one is optionally
|
||||
// first parameter is the command (string)
|
||||
// second variatic parameter is the argument(s) (slice of string)
|
||||
//
|
||||
// the difference from the normal Command function is that you can re-use this Cmd, it doesn't execute until you call its Command function
|
||||
func CommandBuilder(command string, args ...string) *Cmd {
|
||||
return &Cmd{Cmd: exec.Command(command, args...)}
|
||||
}
|
||||
|
||||
// the below is just for exec.Command:
|
||||
|
||||
// Command executes a command in shell and returns it's output, it's block version
|
||||
func Command(command string, a ...string) (output string, err error) {
|
||||
var out []byte
|
||||
// if no args given, try to get them from the command
|
||||
if len(a) == 0 {
|
||||
commandArgs := strings.Split(command, " ")
|
||||
for _, commandArg := range commandArgs {
|
||||
if commandArg[0] == '-' { // if starts with - means that this is an argument, append it to the arguments
|
||||
a = append(a, commandArg)
|
||||
}
|
||||
}
|
||||
}
|
||||
out, err = exec.Command(command, a...).Output()
|
||||
|
||||
if err == nil {
|
||||
output = string(out)
|
||||
}
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// MustCommand executes a command in shell and returns it's output, it's block version. It panics on an error
|
||||
func MustCommand(command string, a ...string) (output string) {
|
||||
var out []byte
|
||||
var err error
|
||||
if len(a) == 0 {
|
||||
commandArgs := strings.Split(command, " ")
|
||||
for _, commandArg := range commandArgs {
|
||||
if commandArg[0] == '-' { // if starts with - means that this is an argument, append it to the arguments
|
||||
a = append(a, commandArg)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
out, err = exec.Command(command, a...).Output()
|
||||
if err != nil {
|
||||
argsToString := strings.Join(a, " ")
|
||||
panic(fmt.Sprintf("\nError running the command %s", command+" "+argsToString))
|
||||
}
|
||||
|
||||
output = string(out)
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
// Exists returns true if directory||file exists
|
||||
func Exists(dir string) bool {
|
||||
if _, err := os.Stat(dir); os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
|
@ -1,118 +0,0 @@
|
|||
package npm
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
// nodeModulesPath is the path of the root npm modules
|
||||
// Ex: C:\\Users\\iris\\AppData\\Roaming\\npm\\node_modules
|
||||
var nodeModulesPath string
|
||||
|
||||
type (
|
||||
// NodeModuleResult holds Message and Error, if error != nil then the npm command has failed
|
||||
NodeModuleResult struct {
|
||||
// Message the message (string)
|
||||
Message string
|
||||
// Error the error (if any)
|
||||
Error error
|
||||
}
|
||||
)
|
||||
|
||||
// NodeModulesPath sets the root directory for the node_modules and returns that
|
||||
func NodeModulesPath() string {
|
||||
if nodeModulesPath == "" {
|
||||
nodeModulesPath = MustCommand("npm", "root", "-g") // here it ends with \n we have to remove it
|
||||
nodeModulesPath = nodeModulesPath[0 : len(nodeModulesPath)-1]
|
||||
}
|
||||
return nodeModulesPath
|
||||
}
|
||||
|
||||
func success(output string, a ...interface{}) NodeModuleResult {
|
||||
return NodeModuleResult{fmt.Sprintf(output, a...), nil}
|
||||
}
|
||||
|
||||
func fail(errMsg string, a ...interface{}) NodeModuleResult {
|
||||
return NodeModuleResult{"", fmt.Errorf("\n"+errMsg, a...)}
|
||||
}
|
||||
|
||||
// Output returns the error message if result.Error exists, otherwise returns the result.Message
|
||||
func (res NodeModuleResult) Output() (out string) {
|
||||
if res.Error != nil {
|
||||
out = res.Error.Error()
|
||||
} else {
|
||||
out = res.Message
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// NodeModuleInstall installs a module
|
||||
func NodeModuleInstall(moduleName string) NodeModuleResult {
|
||||
finish := make(chan bool)
|
||||
|
||||
go func() {
|
||||
print("\n|")
|
||||
print("_")
|
||||
print("|")
|
||||
|
||||
for {
|
||||
select {
|
||||
case v := <-finish:
|
||||
{
|
||||
if v {
|
||||
print("\010\010\010") // remove the loading chars
|
||||
close(finish)
|
||||
return
|
||||
}
|
||||
}
|
||||
default:
|
||||
print("\010\010-")
|
||||
time.Sleep(time.Second / 2)
|
||||
print("\010\\")
|
||||
time.Sleep(time.Second / 2)
|
||||
print("\010|")
|
||||
time.Sleep(time.Second / 2)
|
||||
print("\010/")
|
||||
time.Sleep(time.Second / 2)
|
||||
print("\010-")
|
||||
time.Sleep(time.Second / 2)
|
||||
print("|")
|
||||
}
|
||||
}
|
||||
}()
|
||||
out, err := Command("npm", "install", moduleName, "-g")
|
||||
finish <- true
|
||||
if err != nil {
|
||||
return fail("Error installing module %s. Trace: %s", moduleName, err.Error())
|
||||
}
|
||||
|
||||
return success("\n%s installed %s", moduleName, out)
|
||||
}
|
||||
|
||||
// NodeModuleUnistall removes a module
|
||||
func NodeModuleUnistall(moduleName string) NodeModuleResult {
|
||||
out, err := Command("npm", "unistall", "-g", moduleName)
|
||||
if err != nil {
|
||||
return fail("Error unstalling module %s. Trace: %s", moduleName, err.Error())
|
||||
}
|
||||
return success("\n %s unistalled %s", moduleName, out)
|
||||
}
|
||||
|
||||
// NodeModuleAbs returns the absolute path of the global node_modules directory + relative
|
||||
func NodeModuleAbs(relativePath string) string {
|
||||
return NodeModulesPath() + PathSeparator + strings.Replace(relativePath, "/", PathSeparator, -1)
|
||||
}
|
||||
|
||||
// NodeModuleExists returns true if a module exists
|
||||
// here we have two options
|
||||
// 1 . search by command something like npm -ls -g --depth=x
|
||||
// 2. search on files, we choose the second
|
||||
func NodeModuleExists(execPath string) bool {
|
||||
if !filepath.IsAbs(execPath) {
|
||||
execPath = NodeModuleAbs(execPath)
|
||||
}
|
||||
|
||||
return Exists(execPath)
|
||||
}
|
|
@ -1,270 +0,0 @@
|
|||
// 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
|
||||
}
|
Loading…
Reference in New Issue
Block a user