├── .gitignore ├── cmd ├── bpmnenginestate_wasm_js_test.go ├── go.mod ├── parser_test.go ├── bpmnenginestate_wasm_js.go ├── template.go ├── generator.go ├── go.sum └── parser.go ├── go.mod ├── .github ├── dependabot.yml └── workflows │ └── update-gh-pages.yml ├── README.md ├── static ├── bpmn-modeler.js ├── index.css ├── simple_task.bpmn ├── index.js └── index.html ├── LICENSE ├── simple_task.bpmn ├── main_js.go └── go.sum /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.iml 3 | .DS_Store 4 | 5 | *.wasm 6 | wasm_exec.js 7 | -------------------------------------------------------------------------------- /cmd/bpmnenginestate_wasm_js_test.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "github.com/nitram509/lib-bpmn-engine/pkg/bpmn_engine" 5 | "testing" 6 | ) 7 | 8 | func Test(t *testing.T) { 9 | wrap(bpmn_engine.New("test")) 10 | } 11 | -------------------------------------------------------------------------------- /cmd/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/nitram509/wasm-bindings 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/nitram509/lib-bpmn-engine v0.3.0-beta1 7 | golang.org/x/tools v0.2.0 8 | ) 9 | 10 | require ( 11 | github.com/antonmedv/expr v1.9.0 // indirect 12 | github.com/bwmarrin/snowflake v0.3.0 // indirect 13 | github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 // indirect 14 | golang.org/x/sys v0.1.0 // indirect 15 | ) 16 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/nitram509/lib-bpmn-engine-js 2 | 3 | go 1.19 4 | 5 | require ( 6 | github.com/nitram509/lib-bpmn-engine v0.3.0-beta2 7 | github.com/norunners/vert v0.0.0-20211229045251-b4c39e2856da 8 | ) 9 | 10 | require ( 11 | github.com/antonmedv/expr v1.9.0 // indirect 12 | github.com/bwmarrin/snowflake v0.3.0 // indirect 13 | github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 // indirect 14 | ) 15 | 16 | replace github.com/norunners/vert => github.com/nitram509/vert v0.0.0-20221023193548-8762a19797a7 17 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | # To get started with Dependabot version updates, you'll need to specify which 2 | # package ecosystems to update and where the package manifests are located. 3 | # Please see the documentation for all configuration options: 4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates 5 | 6 | version: 2 7 | updates: 8 | - package-ecosystem: "gomod" # See documentation for possible values 9 | directory: "/" # Location of package manifests 10 | schedule: 11 | interval: "daily" 12 | -------------------------------------------------------------------------------- /.github/workflows/update-gh-pages.yml: -------------------------------------------------------------------------------- 1 | name: update-gh-pages 2 | on: 3 | push: 4 | branches: 5 | - master 6 | - main 7 | jobs: 8 | update-gh-pages: 9 | runs-on: ubuntu-latest 10 | steps: 11 | - uses: actions/checkout@v2 12 | - name: Setup go 13 | uses: actions/setup-go@v2 14 | with: 15 | go-version: '1.19' 16 | - name: "Compile WASM" 17 | run: | 18 | GOOS=js GOARCH=wasm go build -o static/main.wasm . 19 | cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" static/wasm_exec.js 20 | - name: "Deploy 🚀" 21 | uses: JamesIves/github-pages-deploy-action@v4 22 | with: 23 | folder: static 24 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # lib-bpmn-engine-js 2 | 3 | ## status 4 | 5 | **experimental** playground is online 6 | https://nitram509.github.io/lib-bpmn-engine-js/ 7 | 8 | ## link 9 | 10 | The actual BPMN engine's sources are available here: https://github.com/nitram509/lib-bpmn-engine 11 | 12 | ## build 13 | 14 | ```shell 15 | GOOS=js GOARCH=wasm go build -o static/main.wasm . 16 | cp "$(go env GOROOT)/misc/wasm/wasm_exec.js" static/wasm_exec.js 17 | ``` 18 | 19 | ## test 20 | 21 | ```shell 22 | export PATH="$PATH:$(go env GOROOT)/misc/wasm" 23 | GOOS=js GOARCH=wasm go test ./... 24 | ``` 25 | 26 | ## WiP: test code generator 27 | 28 | ```shell 29 | cd cmd 30 | go run . -package=github.com/nitram509/lib-bpmn-engine/pkg/bpmn_engine -type=BpmnEngineState 31 | ``` 32 | -------------------------------------------------------------------------------- /static/bpmn-modeler.js: -------------------------------------------------------------------------------- 1 | // modeler instance 2 | var bpmnModeler = new BpmnJS({ 3 | container: '#canvas', 4 | keyboard: { 5 | bindTo: window 6 | } 7 | }); 8 | 9 | /** 10 | * Open diagram in our modeler instance. 11 | * 12 | * @param {String} bpmnXML diagram to display 13 | */ 14 | async function openDiagram(bpmnXML) { 15 | // import diagram 16 | try { 17 | await bpmnModeler.importXML(bpmnXML); 18 | // access modeler components 19 | var canvas = bpmnModeler.get('canvas'); 20 | var overlays = bpmnModeler.get('overlays'); 21 | // zoom to fit full viewport 22 | canvas.zoom('fit-viewport'); 23 | } catch (err) { 24 | console.error('could not import BPMN 2.0 diagram', err); 25 | } 26 | } 27 | 28 | 29 | // load external diagram file via AJAX and open it 30 | $.get("simple_task.bpmn", openDiagram, 'text'); 31 | -------------------------------------------------------------------------------- /static/index.css: -------------------------------------------------------------------------------- 1 | html, body { 2 | height: 100%; 3 | padding: 0; 4 | margin: 0; 5 | } 6 | 7 | #canvas { 8 | height: 900px; 9 | border: 1px solid silver; 10 | } 11 | 12 | .diagram-note { 13 | background-color: rgba(66, 180, 21, 0.7); 14 | color: White; 15 | border-radius: 5px; 16 | font-family: Arial; 17 | font-size: 12px; 18 | padding: 5px; 19 | min-height: 16px; 20 | width: 50px; 21 | text-align: center; 22 | } 23 | 24 | .needs-discussion:not(.djs-connection) .djs-visual > :nth-child(1) { 25 | stroke: rgba(66, 180, 21, 0.7) !important; /* color elements as red */ 26 | } 27 | 28 | #btn-run, #btn-save { 29 | margin-top: 20px 30 | } 31 | 32 | #task-handler-editor { 33 | width: 97%; 34 | height: 200px; 35 | } 36 | 37 | .codeflask { 38 | height: inherit !important; 39 | width: inherit !important; 40 | border: 1px dotted silver; 41 | } 42 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2022 Martin W. Kirst 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /cmd/parser_test.go: -------------------------------------------------------------------------------- 1 | // Copyright 2017 Google Inc. All rights reserved. 2 | // Licensed under the Apache License, Version 2.0 (the "License"); 3 | // you may not use this file except in compliance with the License. 4 | // You may obtain a copy of the License at 5 | // http://www.apache.org/licenses/LICENSE-2.0 6 | // 7 | // Unless required by applicable law or agreed to writing, software distributed 8 | // under the License is distributed on a "AS IS" BASIS, WITHOUT WARRANTIES OR 9 | // CONDITIONS OF ANY KIND, either express or implied. 10 | // 11 | // See the License for the specific language governing permissions and 12 | // limitations under the License. 13 | 14 | package main 15 | 16 | import ( 17 | "go/build" 18 | "io/ioutil" 19 | "os" 20 | "path/filepath" 21 | "testing" 22 | ) 23 | 24 | func must(t *testing.T, err error) { 25 | if err != nil { 26 | t.Fatal(err) 27 | } 28 | } 29 | 30 | var fakeCode = ` 31 | package main 32 | import "fmt" 33 | func main() { 34 | fmt.Println("Hello world!") 35 | } 36 | ` 37 | 38 | func TestParseFromMultipleGopath(t *testing.T) { 39 | gopaths := filepath.SplitList(build.Default.GOPATH) 40 | if len(gopaths) < 2 { 41 | t.Skipf("No multiple GOPATH (%s) exists, skiping..", build.Default.GOPATH) 42 | } 43 | gopath := gopaths[len(gopaths)-1] 44 | dir := filepath.Join(gopath, "src", "foo") 45 | defer func() { must(t, os.RemoveAll(dir)) }() 46 | must(t, os.MkdirAll(dir, 0755)) 47 | must(t, ioutil.WriteFile(filepath.Join(dir, "main.go"), []byte(fakeCode), 0644)) 48 | 49 | if _, err := parsePackage(dir); err != nil { 50 | t.Fatalf("Parse package (%v): %v", dir, err) 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /cmd/bpmnenginestate_wasm_js.go: -------------------------------------------------------------------------------- 1 | // Code generated by go wasm-bindings -package=github.com/nitram509/lib-bpmn-engine/pkg/bpmn_engine -type=BpmnEngineState; DO NOT EDIT. 2 | 3 | package main 4 | 5 | import "github.com/nitram509/lib-bpmn-engine/pkg/bpmn_engine" 6 | import "syscall/js" 7 | 8 | type BpmnEngineStateWrapper struct { 9 | wrapped *bpmn_engine.BpmnEngineState 10 | } 11 | 12 | func wrap(t bpmn_engine.BpmnEngineState) BpmnEngineStateWrapper { 13 | return BpmnEngineStateWrapper{ 14 | wrapped: &t, 15 | } 16 | } 17 | func (w *BpmnEngineStateWrapper) JsRunOrContinueInstance(this js.Value, args []js.Value) any { 18 | param0 := int64(args[0].Float()) 19 | w.wrapped.RunOrContinueInstance(param0) 20 | return js.Undefined() 21 | } 22 | 23 | func (w *BpmnEngineStateWrapper) JsGetMessageSubscriptions(this js.Value, args []js.Value) any { 24 | w.wrapped.GetMessageSubscriptions() 25 | return js.Undefined() 26 | } 27 | 28 | func (w *BpmnEngineStateWrapper) JsFindProcessInstanceById(this js.Value, args []js.Value) any { 29 | param0 := int64(args[0].Float()) 30 | w.wrapped.FindProcessInstanceById(param0) 31 | return js.Undefined() 32 | } 33 | 34 | func (w *BpmnEngineStateWrapper) JsLoadFromFile(this js.Value, args []js.Value) any { 35 | param0 := args[0].String() 36 | w.wrapped.LoadFromFile(param0) 37 | return js.Undefined() 38 | } 39 | 40 | func (w *BpmnEngineStateWrapper) JsGetTimersScheduled(this js.Value, args []js.Value) any { 41 | w.wrapped.GetTimersScheduled() 42 | return js.Undefined() 43 | } 44 | 45 | func (w *BpmnEngineStateWrapper) JsGetProcessInstances(this js.Value, args []js.Value) any { 46 | w.wrapped.GetProcessInstances() 47 | return js.Undefined() 48 | } 49 | 50 | func (w *BpmnEngineStateWrapper) JsGetName(this js.Value, args []js.Value) any { 51 | w.wrapped.GetName() 52 | return js.Undefined() 53 | } 54 | -------------------------------------------------------------------------------- /cmd/template.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "strings" 6 | "text/template" 7 | ) 8 | 9 | type analysisData struct { 10 | Command string 11 | PackageName string 12 | PackageFQN string 13 | TypeName string 14 | WrapperTypeName string 15 | TypesAndValues map[string][]string 16 | TargetPackageName string 17 | } 18 | 19 | var typeWrapperTemplate = template.Must(template.New("").Parse(`// Code generated by go wasm-bindings {{.Command}}; DO NOT EDIT. 20 | 21 | package {{.TargetPackageName}} 22 | 23 | import "{{.PackageFQN}}" 24 | import "syscall/js" 25 | 26 | type {{.WrapperTypeName}} struct { 27 | wrapped *{{.PackageName}}.{{.TypeName}} 28 | } 29 | 30 | func wrap(t {{.PackageName}}.{{.TypeName}}) {{.WrapperTypeName}} { 31 | return {{.WrapperTypeName}}{ 32 | wrapped: &t, 33 | } 34 | } 35 | `)) 36 | 37 | type functionData struct { 38 | FunctionName string 39 | WrapperTypeName string 40 | Types []string 41 | } 42 | 43 | func functionWrapperTempl(d functionData) string { 44 | b := strings.Builder{} 45 | b.WriteString("func (w *" + d.WrapperTypeName + ") Js" + d.FunctionName + "(this js.Value, args []js.Value) any {\n") 46 | for i, typ := range d.Types { 47 | switch typ { 48 | case "int64": 49 | b.WriteString(fmt.Sprintf("param%d := int64(args[%d].Float())\n", i, i)) 50 | case "int": 51 | b.WriteString(fmt.Sprintf("param%d := args[%d].Int()\n", i, i)) 52 | case "string": 53 | b.WriteString(fmt.Sprintf("param%d := args[%d].String()\n", i, i)) 54 | default: 55 | b.WriteString(fmt.Sprintf("param%d := args[%d].String()\n", i, i)) 56 | } 57 | } 58 | params := "" 59 | for i, _ := range d.Types { 60 | if i > 0 { 61 | params = params + ", " 62 | } 63 | params = params + fmt.Sprintf("param%d", i) 64 | } 65 | b.WriteString("w.wrapped." + d.FunctionName + "(" + params + ")\n") 66 | b.WriteString("return js.Undefined()\n") 67 | b.WriteString("}\n\n") 68 | return b.String() 69 | } 70 | -------------------------------------------------------------------------------- /simple_task.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flow_0xt1d7q 6 | 7 | 8 | 9 | Flow_1vz4oo2 10 | 11 | 12 | 13 | 14 | 15 | 16 | Flow_0xt1d7q 17 | Flow_1vz4oo2 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /static/simple_task.bpmn: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Flow_0xt1d7q 6 | 7 | 8 | 9 | Flow_1vz4oo2 10 | 11 | 12 | 13 | 14 | 15 | 16 | Flow_0xt1d7q 17 | Flow_1vz4oo2 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /cmd/generator.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "flag" 6 | "go/format" 7 | "log" 8 | "os" 9 | "path/filepath" 10 | "strings" 11 | ) 12 | 13 | var ( 14 | packageName = flag.String("package", "", "name of the package, e.g. 'golang.org/x/text/encoding'") 15 | typeNames = flag.String("type", "", "comma-separated list of type names; e.g. 'Decoder") 16 | outputPrefix = flag.String("prefix", "", "prefix to be added to the output file") 17 | outputSuffix = flag.String("suffix", "_wasm", "suffix to be added to the output file") 18 | ) 19 | 20 | func main() { 21 | flag.Parse() 22 | if len(*typeNames) == 0 { 23 | log.Fatalf("the flag -type must be set") 24 | } 25 | types := strings.Split(*typeNames, ",") 26 | 27 | if packageName == nil || len(*packageName) < 1 { 28 | dir := "." 29 | dir, err := filepath.Abs(dir) 30 | if err != nil { 31 | log.Fatalf("unable to determine absolute filepath for requested path %s: %v", 32 | dir, err) 33 | } 34 | packageName = &dir 35 | } 36 | 37 | pkg, err := parsePackage(*packageName) 38 | if err != nil { 39 | log.Fatalf("parsing package: %v", err) 40 | } 41 | 42 | analysis := analysisData{ 43 | Command: strings.Join(os.Args[1:], " "), 44 | PackageName: pkg.Name, 45 | PackageFQN: pkg.Name, 46 | TypesAndValues: make(map[string][]string), 47 | TargetPackageName: "main", 48 | } 49 | 50 | // Run generate for each type. 51 | for _, typeName := range types { 52 | log.Printf("typeName=" + typeName) 53 | values, err := pkg.ValuesOfType(typeName) 54 | parameters, err := pkg.findFunctionsAndParameters(typeName) 55 | if err != nil { 56 | log.Fatalf("finding functions and their parameters %v: %v", typeName, err) 57 | } 58 | log.Printf(strings.Join(values, ",")) 59 | if err != nil { 60 | log.Fatalf("finding values for type %v: %v", typeName, err) 61 | } 62 | analysis.TypesAndValues[typeName] = values 63 | analysis.TypeName = values[0] 64 | analysis.WrapperTypeName = analysis.TypeName + "Wrapper" 65 | analysis.PackageFQN = pkg.FQN 66 | 67 | var buf bytes.Buffer 68 | if err := typeWrapperTemplate.Execute(&buf, analysis); err != nil { 69 | log.Fatalf("generating code: %v", err) 70 | } 71 | 72 | for key, val := range parameters { 73 | var vals []string 74 | for _, v := range val { 75 | vals = append(vals, v.Name) 76 | } 77 | data := functionData{ 78 | FunctionName: key, 79 | WrapperTypeName: analysis.WrapperTypeName, 80 | Types: vals, 81 | } 82 | templ := functionWrapperTempl(data) 83 | buf.WriteString(templ) 84 | } 85 | 86 | src, err := format.Source(buf.Bytes()) 87 | if err != nil { 88 | // Should never happen, but can arise when developing this code. 89 | // The user can compile the output to see the error. 90 | log.Printf("warning: internal error: invalid Go generated: %s", err) 91 | log.Printf("warning: compile the package to analyze the error") 92 | src = buf.Bytes() 93 | } 94 | 95 | output := strings.ToLower(*outputPrefix + typeName + *outputSuffix + "_js.go") 96 | outputPath := filepath.Join(".", output) 97 | if err := os.WriteFile(outputPath, src, 0644); err != nil { 98 | log.Fatalf("writing output: %s", err) 99 | } 100 | } 101 | } 102 | -------------------------------------------------------------------------------- /main_js.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "github.com/nitram509/lib-bpmn-engine/pkg/bpmn_engine" 6 | "github.com/norunners/vert" 7 | "syscall/js" 8 | ) 9 | 10 | type jsBinding struct { 11 | Name string `js:"name"` 12 | } 13 | 14 | type EngineWrapper struct { 15 | engine *bpmn_engine.BpmnEngineState 16 | } 17 | 18 | type ActivatedJobHandler struct { 19 | handler js.Value 20 | } 21 | 22 | var engineCounter = 0 23 | 24 | func main() { 25 | done := make(chan struct{}, 0) 26 | js.Global().Set("NewBpmnEngine", js.FuncOf(newBpmnEngine)) 27 | <-done 28 | } 29 | 30 | func newBpmnEngine(this js.Value, args []js.Value) interface{} { 31 | engine := bpmn_engine.New(fmt.Sprintf("engine-%d", engineCounter)) 32 | engineCounter++ 33 | ew := EngineWrapper{ 34 | engine: &engine, 35 | } 36 | obj := vert.ValueOf(jsBinding{Name: engine.GetName()}) 37 | obj.Set("GetName", js.FuncOf(func(this js.Value, args []js.Value) any { 38 | return engine.GetName() 39 | })) 40 | obj.Set("CreateAndRunInstance", js.FuncOf(ew.CreateAndRunInstance)) 41 | obj.Set("LoadFromString", js.FuncOf(ew.JsLoadFromString)) 42 | obj.Set("NewTaskHandlerForId", js.FuncOf(ew.JsNewTaskHandlerForId)) 43 | return obj.JSValue() 44 | } 45 | 46 | func (ew EngineWrapper) JsLoadFromString(this js.Value, args []js.Value) any { 47 | xmlString := args[0].String() 48 | process, err := ew.engine.LoadFromBytes([]byte(xmlString)) 49 | if err != nil { 50 | return js.ValueOf(false) 51 | } 52 | return js.ValueOf(process.ProcessKey) 53 | } 54 | 55 | func (ew EngineWrapper) JsNewTaskHandlerForId(this js.Value, args []js.Value) any { 56 | id := args[0].String() 57 | jsHandler := args[1] 58 | ajh := ActivatedJobHandler{ 59 | handler: jsHandler, 60 | } 61 | ew.engine.NewTaskHandler().Id(id).Handler(ajh.JsActivatedJobHandler) 62 | return js.Undefined() 63 | } 64 | 65 | func (ew EngineWrapper) CreateAndRunInstance(this js.Value, args []js.Value) any { 66 | processKey := int64(args[0].Float()) 67 | ew.engine.CreateAndRunInstance(processKey, nil) 68 | return js.Undefined() 69 | } 70 | 71 | func (ajh ActivatedJobHandler) JsActivatedJobHandler(job bpmn_engine.ActivatedJob) { 72 | type retObj struct{} 73 | obj := vert.ValueOf(retObj{}) 74 | obj.Set("GetKey", js.FuncOf(func(this js.Value, args []js.Value) any { 75 | return job.GetKey() 76 | })) 77 | obj.Set("GetProcessInstanceKey", js.FuncOf(func(this js.Value, args []js.Value) any { 78 | return job.GetProcessInstanceKey() 79 | })) 80 | obj.Set("GetBpmnProcessId", js.FuncOf(func(this js.Value, args []js.Value) any { 81 | return job.GetBpmnProcessId() 82 | })) 83 | obj.Set("GetProcessDefinitionVersion", js.FuncOf(func(this js.Value, args []js.Value) any { 84 | return job.GetProcessDefinitionVersion() 85 | })) 86 | obj.Set("GetProcessDefinitionKey", js.FuncOf(func(this js.Value, args []js.Value) any { 87 | return job.GetProcessDefinitionKey() 88 | })) 89 | obj.Set("GetElementId", js.FuncOf(func(this js.Value, args []js.Value) any { 90 | return job.GetElementId() 91 | })) 92 | obj.Set("GetCreatedAt", js.FuncOf(func(this js.Value, args []js.Value) any { 93 | return vert.ValueOf(job.GetCreatedAt()).JSValue() 94 | })) 95 | obj.Set("Fail", js.FuncOf(func(this js.Value, args []js.Value) any { 96 | reason := args[0].String() 97 | job.Fail(reason) 98 | return js.Undefined() 99 | })) 100 | obj.Set("Complete", js.FuncOf(func(this js.Value, args []js.Value) any { 101 | job.Complete() 102 | return js.Undefined() 103 | })) 104 | ajh.handler.Invoke(obj.JSValue()) 105 | } 106 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= 2 | github.com/antonmedv/expr v1.9.0 h1:j4HI3NHEdgDnN9p6oI6Ndr0G5QryMY0FNxT4ONrFDGU= 3 | github.com/antonmedv/expr v1.9.0/go.mod h1:5qsM3oLGDND7sDmQGDXHkYfkjYMUX14qsgqmHhwGEk8= 4 | github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= 5 | github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE= 6 | github.com/corbym/gocrest v1.0.5 h1:6FUvLjKkKQ2hwMel8OKIZqN3slYEOHIFY9+lVaroFnU= 7 | github.com/corbym/gocrest v1.0.5/go.mod h1:lF3xBPnOU5DYDpa/vUq63SMxUhd5UAwGgmA8Z2pJ/Tk= 8 | github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 9 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 10 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 11 | github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= 12 | github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM= 13 | github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= 14 | github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= 15 | github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 16 | github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 17 | github.com/nitram509/lib-bpmn-engine v0.3.0-beta2 h1:Q0g7x14ClIXPryGKsi2jnFtw09tqmfWNRc6MUyM+Jaw= 18 | github.com/nitram509/lib-bpmn-engine v0.3.0-beta2/go.mod h1:6Sgm1R5CJl70VRdIgf0jJh3GsNxSQuRQNimdiMuUTzg= 19 | github.com/nitram509/vert v0.0.0-20221023193548-8762a19797a7 h1:/v4hdt9JPfKoTu84pMYlDL/JQe0uZBbA5A7v2ujNkuc= 20 | github.com/nitram509/vert v0.0.0-20221023193548-8762a19797a7/go.mod h1:iN8qHdmpCwgEA/73TvTJ7dmDh5cnU2ikuSZBzGvjSiA= 21 | github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 22 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 23 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 24 | github.com/rivo/tview v0.0.0-20200219210816-cd38d7432498/go.mod h1:6lkG1x+13OShEf0EaOCaTQYyB7d5nSbb181KtjlS+84= 25 | github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 26 | github.com/sanity-io/litter v1.2.0/go.mod h1:JF6pZUFgu2Q0sBZ+HSV35P8TVPI1TTzEwyu9FXAw2W4= 27 | github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 h1:Dz0HrI1AtNSGCE8LXLLqoZU4iuOJXPWndenCsZfstA8= 28 | github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46/go.mod h1:is8FVkzSi7PYLWEXT5MgWhglFsyyiW8ffxAoJqfuFZo= 29 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 30 | github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 31 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= 32 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 33 | golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 34 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 35 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 36 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 37 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 38 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 39 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 40 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 41 | -------------------------------------------------------------------------------- /cmd/go.sum: -------------------------------------------------------------------------------- 1 | github.com/DATA-DOG/go-sqlmock v1.3.3/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM= 2 | github.com/antonmedv/expr v1.9.0 h1:j4HI3NHEdgDnN9p6oI6Ndr0G5QryMY0FNxT4ONrFDGU= 3 | github.com/antonmedv/expr v1.9.0/go.mod h1:5qsM3oLGDND7sDmQGDXHkYfkjYMUX14qsgqmHhwGEk8= 4 | github.com/bwmarrin/snowflake v0.3.0 h1:xm67bEhkKh6ij1790JB83OujPR5CzNe8QuQqAgISZN0= 5 | github.com/bwmarrin/snowflake v0.3.0/go.mod h1:NdZxfVWX+oR6y2K0o6qAYv6gIOP9rjG0/E9WsDpxqwE= 6 | github.com/corbym/gocrest v1.0.5 h1:6FUvLjKkKQ2hwMel8OKIZqN3slYEOHIFY9+lVaroFnU= 7 | github.com/davecgh/go-spew v0.0.0-20161028175848-04cdfd42973b/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 8 | github.com/davecgh/go-spew v1.1.0 h1:ZDRjVQ15GmhC3fiQ8ni8+OwkZQO4DARzQgrnXU1Liz8= 9 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= 10 | github.com/gdamore/encoding v1.0.0/go.mod h1:alR0ol34c49FCSBLjhosxzcPHQbf2trDkoo5dl+VrEg= 11 | github.com/gdamore/tcell v1.3.0/go.mod h1:Hjvr+Ofd+gLglo7RYKxxnzCBmev3BzsS67MebKS4zMM= 12 | github.com/lucasb-eyer/go-colorful v1.0.2/go.mod h1:0MS4r+7BZKSJ5mw4/S5MPN+qHFF1fYclkSPilDOKW0s= 13 | github.com/lucasb-eyer/go-colorful v1.0.3/go.mod h1:R4dSotOR9KMtayYi1e77YzuveK+i7ruzyGqttikkLy0= 14 | github.com/mattn/go-runewidth v0.0.4/go.mod h1:LwmH8dsx7+W8Uxz3IHJYH5QSwggIsqBzpuz5H//U1FU= 15 | github.com/mattn/go-runewidth v0.0.8/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m2gUSrubnMI= 16 | github.com/nitram509/lib-bpmn-engine v0.3.0-beta1 h1:0V7n8oLWKz8XfX9IE0jq1y2xgeaDMNJzkRlTz2Uvaxw= 17 | github.com/nitram509/lib-bpmn-engine v0.3.0-beta1/go.mod h1:6Sgm1R5CJl70VRdIgf0jJh3GsNxSQuRQNimdiMuUTzg= 18 | github.com/pmezard/go-difflib v0.0.0-20151028094244-d8ed2627bdf0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 19 | github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= 20 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= 21 | github.com/rivo/tview v0.0.0-20200219210816-cd38d7432498/go.mod h1:6lkG1x+13OShEf0EaOCaTQYyB7d5nSbb181KtjlS+84= 22 | github.com/rivo/uniseg v0.1.0/go.mod h1:J6wj4VEh+S6ZtnVlnTBMWIodfgj8LQOQFoIToxlJtxc= 23 | github.com/sanity-io/litter v1.2.0/go.mod h1:JF6pZUFgu2Q0sBZ+HSV35P8TVPI1TTzEwyu9FXAw2W4= 24 | github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46 h1:Dz0HrI1AtNSGCE8LXLLqoZU4iuOJXPWndenCsZfstA8= 25 | github.com/senseyeio/duration v0.0.0-20180430131211-7c2a214ada46/go.mod h1:is8FVkzSi7PYLWEXT5MgWhglFsyyiW8ffxAoJqfuFZo= 26 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME= 27 | github.com/stretchr/testify v0.0.0-20161117074351-18a02ba4a312/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs= 28 | github.com/stretchr/testify v1.5.1 h1:nOGnQDM7FYENwehXlg/kFVnos3rEvtKTjRvOWSzb6H4= 29 | github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= 30 | golang.org/x/mod v0.6.0 h1:b9gGHsz9/HhJ3HF5DHQytPpuwocVTChQJK3AvoLRD5I= 31 | golang.org/x/sys v0.0.0-20190626150813-e07cf5db2756/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 32 | golang.org/x/sys v0.0.0-20200212091648-12a6c2dcc1e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= 33 | golang.org/x/sys v0.1.0 h1:kunALQeHf1/185U1i0GOB/fy1IPRDDpuoOOqRReG57U= 34 | golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= 35 | golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= 36 | golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= 37 | golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= 38 | golang.org/x/tools v0.2.0 h1:G6AHpWxTMGY1KyEYoAQ5WTtIekUUvDNjan3ugu60JvE= 39 | golang.org/x/tools v0.2.0/go.mod h1:y4OqIKeOV/fWJetJ8bXPU1sEVniLMIyDAZWeHdV+NTA= 40 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= 41 | gopkg.in/yaml.v2 v2.2.2 h1:ZCJp+EgiOT7lHqUV2J862kp8Qj64Jo6az82+3Td9dZw= 42 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= 43 | -------------------------------------------------------------------------------- /static/index.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | (function initApplication() { 4 | let oldLog = console.log; 5 | console.log = function (message) { 6 | let box = $("#log"); 7 | box.val(box.val() + message + "\n"); 8 | oldLog.apply(console, arguments); 9 | }; 10 | })(); 11 | 12 | function openSaveFileDialog(data, filename, mimetype) { 13 | 'use strict'; 14 | 15 | if (!data) return; 16 | 17 | var blob = data.constructor !== Blob 18 | ? new Blob([data], {type: mimetype || 'application/octet-stream'}) 19 | : data; 20 | 21 | if (navigator.msSaveBlob) { 22 | navigator.msSaveBlob(blob, filename); 23 | return; 24 | } 25 | 26 | var lnk = document.createElement('a'), 27 | url = window.URL, 28 | objectURL; 29 | 30 | if (mimetype) { 31 | lnk.type = mimetype; 32 | } 33 | 34 | lnk.download = filename || 'untitled'; 35 | lnk.href = objectURL = url.createObjectURL(blob); 36 | lnk.dispatchEvent(new MouseEvent('click')); 37 | setTimeout(url.revokeObjectURL.bind(url, objectURL)); 38 | } 39 | 40 | /** 41 | * Save diagram contents and print them to the console. 42 | */ 43 | async function exportDiagram() { 44 | 'use strict'; 45 | try { 46 | let result = await bpmnModeler.saveXML({format: true}); 47 | let filename = "diagram-" + new Date().getTime() + ".bpmn"; 48 | openSaveFileDialog(result.xml, filename, 'application/bpmn+xml'); 49 | } catch (err) { 50 | console.error('could not save BPMN 2.0 diagram', err); 51 | } 52 | } 53 | 54 | /** 55 | * @typedef NewBpmnEngine 56 | * @type {function} 57 | * @returns {BpmnEngine} 58 | */ 59 | 60 | /** 61 | * @typedef BpmnEngine 62 | * @type {object} 63 | * @property {function(id:string, callback:function(ActivatedJob))} NewTaskHandlerForId 64 | * @property {function(bpmn:string):number} LoadFromString loads BPMN returns processKey 65 | * @property {function(processKey:number)} CreateAndRunInstance 66 | */ 67 | 68 | /** 69 | * @typedef ActivatedJob 70 | * @type {object} 71 | * @property {function:number} GetKey 72 | * @property {function:number} GetProcessInstanceKey 73 | * @property {function:string} GetBpmnProcessId 74 | * @property {function:number} GetProcessDefinitionVersion 75 | * @property {function:number} GetProcessDefinitionKey 76 | * @property {function:string} GetElementId 77 | * @property {function:Date} GetCreatedAt 78 | * @property {function(reason:string)} Fail 79 | * @property {function} Complete 80 | */ 81 | 82 | /** 83 | * 84 | * @param job {ActivatedJob} 85 | */ 86 | function jobHandler(job) { 87 | const code = flask.getCode(); 88 | eval(code); 89 | } 90 | 91 | 92 | async function runWorkflow() { 93 | let e = NewBpmnEngine() 94 | let bpmn = await bpmnModeler.saveXML({format: true}); 95 | let processKey = e.LoadFromString(bpmn.xml); 96 | if (typeof processKey === 'string') { 97 | console.log("error loading bpmn: " + processKey); 98 | } else { 99 | let box = $("#log"); 100 | box.val(""); 101 | let ids = getTasksIds(bpmn.xml) 102 | ids.forEach(id => { 103 | e.NewTaskHandlerForId(id, jobHandler) 104 | }) 105 | e.CreateAndRunInstance(processKey) 106 | } 107 | } 108 | 109 | /** 110 | * 111 | * @param xmlString 112 | * @returns {[string]} 113 | */ 114 | function getTasksIds(xmlString) { 115 | let parser = new DOMParser(); 116 | let xmlDoc = parser.parseFromString(xmlString, "text/xml"); 117 | let ids = []; 118 | xmlDoc.childNodes.forEach(function (element) { 119 | if (element.localName === 'definitions') { 120 | element.childNodes.forEach(function (element) { 121 | if (element.localName === 'process') { 122 | element.childNodes.forEach(function (element) { 123 | if (element.localName === 'serviceTask') { 124 | ids.push(element.getAttribute("id")) 125 | } 126 | }); 127 | } 128 | }); 129 | } 130 | }); 131 | return ids; 132 | } 133 | -------------------------------------------------------------------------------- /cmd/parser.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | _ "github.com/nitram509/lib-bpmn-engine/pkg/bpmn_engine" 5 | 6 | "fmt" 7 | "go/ast" 8 | "go/build" 9 | "go/constant" 10 | "go/token" 11 | "go/types" 12 | "log" 13 | "strings" 14 | 15 | "golang.org/x/tools/go/loader" 16 | ) 17 | 18 | // A PackageInformation contains all the information related to a parsed package. 19 | type PackageInformation struct { 20 | Name string 21 | FQN string 22 | files []*ast.File 23 | defs map[*ast.Ident]types.Object 24 | } 25 | 26 | // parsePackage parses the package in the given directory and returns it. 27 | func parsePackage(packageName string) (*PackageInformation, error) { 28 | p, err := build.Import(packageName, "", build.FindOnly) 29 | if err != nil { 30 | return nil, fmt.Errorf("provided directory (%s) may not under GOPATH (%s): %v", 31 | packageName, build.Default.GOPATH, err) 32 | } 33 | 34 | conf := loader.Config{TypeChecker: types.Config{FakeImportC: true}} 35 | conf.Import(p.ImportPath) 36 | program, err := conf.Load() 37 | if err != nil { 38 | return nil, fmt.Errorf("couldn't load package: %v", err) 39 | } 40 | 41 | pkgInfo := program.Package(p.ImportPath) 42 | return &PackageInformation{ 43 | Name: pkgInfo.Pkg.Name(), 44 | FQN: pkgInfo.Pkg.Path(), 45 | files: pkgInfo.Files, 46 | defs: pkgInfo.Defs, 47 | }, nil 48 | } 49 | 50 | // ValuesOfType generate produces the String method for the named type. 51 | func (pkg *PackageInformation) ValuesOfType(typeName string) ([]string, error) { 52 | var values, inspectErrs []string 53 | for _, file := range pkg.files { 54 | ast.Inspect(file, func(node ast.Node) bool { 55 | decl, ok := node.(*ast.GenDecl) 56 | if !ok || decl.Tok != token.TYPE { 57 | // We only care about const declarations. 58 | return true 59 | } 60 | 61 | typeSpec := decl.Specs[0].(*ast.TypeSpec) 62 | if typeName == typeSpec.Name.String() { 63 | values = append(values, typeSpec.Name.String()) 64 | } 65 | //if vs, err := pkg.valuesOfTypeIn(typeName, decl); err != nil { 66 | // inspectErrs = append(inspectErrs, err.Error()) 67 | //} else { 68 | // values = append(values, vs...) 69 | //} 70 | return false 71 | }) 72 | } 73 | if len(inspectErrs) > 0 { 74 | return nil, fmt.Errorf("inspecting code:\n\t%v", strings.Join(inspectErrs, "\n\t")) 75 | } 76 | if len(values) == 0 { 77 | return nil, fmt.Errorf("no values defined for type %s", typeName) 78 | } 79 | return values, nil 80 | } 81 | 82 | func (pkg *PackageInformation) findFunctionsAndParameters(typeName string) (map[string][]*ast.Ident, error) { 83 | result := map[string][]*ast.Ident{} 84 | for _, file := range pkg.files { 85 | ast.Inspect(file, func(node ast.Node) bool { 86 | funcDecl, ok := node.(*ast.FuncDecl) 87 | if !ok { 88 | // We only care about const declarations. 89 | return true 90 | } 91 | 92 | if funcDecl.Recv != nil { 93 | if funcDecl.Name.Name[:1] == strings.ToUpper(funcDecl.Name.Name[:1]) { 94 | for _, recv := range funcDecl.Recv.List { 95 | typ := recv.Type 96 | starExp, ok := typ.(*ast.StarExpr) 97 | if ok { 98 | typ = starExp.X 99 | } 100 | if ident, ok := typ.(*ast.Ident); ok { 101 | if ident.Name == typeName { 102 | var pTypes []*ast.Ident 103 | if funcDecl.Type.Params != nil { 104 | for _, param := range funcDecl.Type.Params.List { 105 | p, ok := param.Type.(*ast.Ident) 106 | if ok { 107 | pTypes = append(pTypes, p) 108 | } else { 109 | log.Printf(fmt.Sprintf("unknown identifier, func %s(?) : %v", funcDecl.Name, param.Type)) 110 | } 111 | } 112 | } 113 | result[funcDecl.Name.String()] = pTypes 114 | } 115 | } 116 | } 117 | } 118 | } 119 | return false 120 | }) 121 | } 122 | return result, nil 123 | } 124 | 125 | func (pkg *PackageInformation) valuesOfTypeIn(typeName string, decl *ast.GenDecl) ([]string, error) { 126 | var values []string 127 | 128 | // The name of the type of the constants we are declaring. 129 | // Can change if this is a multi-element declaration. 130 | typ := "" 131 | // Loop over the elements of the declaration. Each element is a ValueSpec: 132 | // a list of names possibly followed by a type, possibly followed by values. 133 | // If the type and value are both missing, we carry down the type (and value, 134 | // but the "go/types" package takes care of that). 135 | for _, spec := range decl.Specs { 136 | vspec := spec.(*ast.ValueSpec) // Guaranteed to succeed as this is CONST. 137 | if vspec.Type == nil && len(vspec.Values) > 0 { 138 | // "X = 1". With no type but a value, the constant is untyped. 139 | // Skip this vspec and reset the remembered type. 140 | typ = "" 141 | continue 142 | } 143 | if vspec.Type != nil { 144 | // "X T". We have a type. Remember it. 145 | ident, ok := vspec.Type.(*ast.Ident) 146 | if !ok { 147 | continue 148 | } 149 | typ = ident.Name 150 | } 151 | if typ != typeName { 152 | // This is not the type we're looking for. 153 | continue 154 | } 155 | 156 | // We now have a list of names (from one line of source code) all being 157 | // declared with the desired type. 158 | // Grab their names and actual values and store them in f.values. 159 | for _, name := range vspec.Names { 160 | if name.Name == "_" { 161 | continue 162 | } 163 | // This dance lets the type checker find the values for us. It's a 164 | // bit tricky: look up the object declared by the name, find its 165 | // types.Const, and extract its value. 166 | obj, ok := pkg.defs[name] 167 | if !ok { 168 | return nil, fmt.Errorf("no value for constant %s", name) 169 | } 170 | info := obj.Type().Underlying().(*types.Basic).Info() 171 | if info&types.IsInteger == 0 { 172 | return nil, fmt.Errorf("can't handle non-integer constant type %s", typ) 173 | } 174 | value := obj.(*types.Const).Val() // Guaranteed to succeed as this is CONST. 175 | if value.Kind() != constant.Int { 176 | log.Fatalf("can't happen: constant is not an integer %s", name) 177 | } 178 | values = append(values, name.Name) 179 | } 180 | } 181 | return values, nil 182 | } 183 | -------------------------------------------------------------------------------- /static/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | lib-bpmn-engine playground 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 32 | 33 | 34 | 35 |
36 |
37 |
38 |
39 |
40 |
41 | 42 |

lib-bpmn-engine playground

43 |

44 | A showcase of the lib-bpmn-engine (Go) library compiled to WASM, 45 | to run in a pure browser environment. 46 | All BPMN data just resides in your browser and no data is sent to the server. 47 |

48 |

49 | This is a very experimental showcase, to highlight the power of cross-compiling Go->WASM. 50 | More documentation about the library you can find nitram509.github.io/lib-bpmn-engine. 51 |

52 |

53 | 54 | 55 |

56 |
task handler
57 |
58 | This code is executed for each service task (the little service gear). 59 | You can write arbitrary JS code and get task information by the 'job' object. 60 |
61 |
//this code is executed, when the 'Test' service task is reached 62 | console.log("--- task-handler ---") 63 | console.log("ElementId = " + job.GetElementId()); 64 | console.log("CreatedAt = " + job.GetCreatedAt()); 65 | //console.log("Key = " + job.GetKey()); 66 | //console.log("BpmnProcessId = " + job.GetBpmnProcessId()); 67 | //console.log("ProcessDefinitionKey = " + job.GetProcessDefinitionKey()); 68 | //console.log("ProcessDefinitionVersion = " + job.GetProcessDefinitionVersion()); 69 | job.Complete(); 70 |
71 | 77 |

78 |
log
79 |
80 | 81 |
82 |
83 |
84 |
85 | 86 | 87 | 88 | 89 | --------------------------------------------------------------------------------