├── .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 |
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 | ▶ Run
54 | Download BPMN
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 |
--------------------------------------------------------------------------------