Skip to content

Commit 65b9a07

Browse files
authored
Merge pull request #567 from marle3003/develop
Develop
2 parents 057d183 + d6dc998 commit 65b9a07

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

53 files changed

+1415
-1137
lines changed

api/handler_faker.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ import (
66
)
77

88
func (h *handler) handleFakerTree(w http.ResponseWriter, r *http.Request) {
9-
node := generator.FindByName("")
9+
node := generator.FindByName(generator.RootName)
1010

1111
w.Header().Set("Content-Type", "application/json")
1212
writeJsonBody(w, node)

api/handler_faker_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ func TestHandler_Faker(t *testing.T) {
2323
requestUrl: "http://foo.api/api/faker/tree",
2424
test: []try.ResponseCondition{
2525
try.HasStatusCode(http.StatusOK),
26-
try.BodyContains(`{"name":"","children":[`),
26+
try.BodyContains(`{"name":"root","children":[`),
2727
},
2828
},
2929
}

engine/common/faker.go

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,18 @@ func (ft *FakerTree) Append(node FakerNode) {
3333
})
3434
}
3535

36+
func (ft *FakerTree) Prepend(node FakerNode) {
37+
t := &generator.Node{
38+
Name: node.Name(),
39+
Fake: node.Fake,
40+
Custom: true,
41+
}
42+
ft.t.Prepend(t)
43+
ft.restore = append(ft.restore, func() error {
44+
return ft.t.Remove(t.Name)
45+
})
46+
}
47+
3648
func (ft *FakerTree) RemoveAt(index int) error {
3749
return ft.t.RemoveAt(index)
3850
}

engine/common/host.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,8 @@ type Host interface {
4040

4141
Name() string
4242

43-
FindFakerNode(name string) *FakerTree
43+
FindFakerNode(name string) *generator.Node
44+
AddCleanupFunc(f func())
4445

4546
Lock()
4647
Unlock()

engine/enginetest/host.go

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,15 @@ import (
44
"fmt"
55
"mokapi/config/dynamic"
66
"mokapi/engine/common"
7+
"mokapi/schema/json/generator"
78
"net/http"
89
"net/url"
910
"sync"
1011
)
1112

1213
type Host struct {
14+
CleanupFuncs []func()
15+
1316
OpenFileFunc func(file, hint string) (string, string, error)
1417
OpenFunc func(file, hint string) (*dynamic.Config, error)
1518
InfoFunc func(args ...interface{})
@@ -22,7 +25,7 @@ type Host struct {
2225
EveryFunc func(every string, do func(), opt common.JobOptions)
2326
CronFunc func(every string, do func(), opt common.JobOptions)
2427
OnFunc func(event string, do func(args ...interface{}) (bool, error), tags map[string]string)
25-
FindFakerNodeFunc func(name string) *common.FakerTree
28+
FindFakerNodeFunc func(name string) *generator.Node
2629
m sync.Mutex
2730
}
2831

@@ -108,7 +111,7 @@ func (h *Host) Name() string {
108111
return "test host"
109112
}
110113

111-
func (h *Host) FindFakerNode(name string) *common.FakerTree {
114+
func (h *Host) FindFakerNode(name string) *generator.Node {
112115
if h.FindFakerNodeFunc != nil {
113116
return h.FindFakerNodeFunc(name)
114117
}
@@ -146,6 +149,10 @@ func (c *KafkaClient) Produce(args *common.KafkaProduceArgs) (*common.KafkaProdu
146149
return nil, nil
147150
}
148151

152+
func (h *Host) AddCleanupFunc(f func()) {
153+
h.CleanupFuncs = append(h.CleanupFuncs, f)
154+
}
155+
149156
func mustParse(s string) *url.URL {
150157
u, err := url.Parse(s)
151158
if err != nil {

engine/host.go

Lines changed: 12 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -31,10 +31,10 @@ type scriptHost struct {
3131
events map[string][]*eventHandler
3232
file *dynamic.Config
3333

34-
eventLogger func(level, message string)
34+
eventLogger func(level, message string)
35+
cleanupFuncs []func()
3536

36-
fakerNodes []*common.FakerTree
37-
m sync.Mutex
37+
m sync.Mutex
3838
}
3939

4040
func newScriptHost(file *dynamic.Config, engine *Engine) *scriptHost {
@@ -223,14 +223,15 @@ func (sh *scriptHost) close() {
223223
sh.script.Close()
224224
}
225225

226-
for _, n := range sh.fakerNodes {
227-
err := n.Restore()
228-
if err != nil {
229-
log.Errorf("failed to close script properly: %v", err)
230-
}
226+
for index := len(sh.cleanupFuncs) - 1; index >= 0; index-- {
227+
sh.cleanupFuncs[index]()
231228
}
232229
}
233230

231+
func (sh *scriptHost) AddCleanupFunc(f func()) {
232+
sh.cleanupFuncs = append(sh.cleanupFuncs, f)
233+
}
234+
234235
func (sh *scriptHost) Info(args ...interface{}) {
235236
sh.engine.logger.Info(args...)
236237
if sh.eventLogger != nil && sh.IsLevelEnabled("info") {
@@ -310,17 +311,11 @@ func (sh *scriptHost) HttpClient(opts common.HttpClientOptions) common.HttpClien
310311
}
311312

312313
func (sh *scriptHost) CanClose() bool {
313-
return len(sh.events) == 0 && len(sh.jobs) == 0 && len(sh.fakerNodes) == 0 && sh.script.CanClose()
314+
return len(sh.events) == 0 && len(sh.jobs) == 0 && sh.script.CanClose() && len(sh.cleanupFuncs) == 0
314315
}
315316

316-
func (sh *scriptHost) FindFakerNode(name string) *common.FakerTree {
317-
t := generator.FindByName(name)
318-
if t == nil {
319-
return nil
320-
}
321-
ft := common.NewFakerTree(t)
322-
sh.fakerNodes = append(sh.fakerNodes, ft)
323-
return ft
317+
func (sh *scriptHost) FindFakerNode(name string) *generator.Node {
318+
return generator.FindByName(name)
324319
}
325320

326321
func (sh *scriptHost) Lock() {

examples/mokapi/frequency.js

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,11 @@
1-
import { findByName} from 'mokapi/faker'
1+
import { findByName, ROOT_NAME } from 'mokapi/faker'
22

33
export default function() {
4-
const faker = findByName('')
4+
const root = findByName(ROOT_NAME)
55
const frequency = ['daily', 'weekly', 'monthly', 'yearly']
6-
faker.append({
6+
root.children.unshift({
77
name: 'Frequency',
8-
test: (r) => {
9-
return r.lastName() === 'frequency'
10-
},
8+
attributes: ['frequency'],
119
fake: (r) => {
1210
return frequency[Math.floor(Math.random()*frequency.length)]
1311
}

js/faker/array.go

Lines changed: 136 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
package faker
2+
3+
import (
4+
"github.com/dop251/goja"
5+
"strconv"
6+
)
7+
8+
type TrackObject[T any] interface {
9+
convert(v goja.Value) T
10+
}
11+
12+
type JsArrayAccessor[T any] interface {
13+
Len() int
14+
Get(i int) T
15+
Set(i int, item T)
16+
Splice(start int, deleteCount int, items []T)
17+
}
18+
19+
type TrackArray[T any] struct {
20+
array JsArrayAccessor[T]
21+
vm *goja.Runtime
22+
converter converter[T]
23+
}
24+
25+
func newJsArray[T any](array JsArrayAccessor[T], vm *goja.Runtime, converter converter[T]) goja.Value {
26+
nodes := &TrackArray[T]{
27+
array: array,
28+
converter: converter,
29+
vm: vm,
30+
}
31+
32+
obj := vm.NewDynamicObject(nodes)
33+
34+
arrayProto := vm.Get("Array").ToObject(vm).Get("prototype").ToObject(vm)
35+
err := obj.SetPrototype(arrayProto)
36+
if err != nil {
37+
panic(err)
38+
}
39+
40+
return obj
41+
}
42+
43+
func (a *TrackArray[T]) Get(key string) goja.Value {
44+
switch key {
45+
case "length":
46+
return a.vm.ToValue(a.array.Len())
47+
case "push":
48+
return a.vm.ToValue(func(call goja.FunctionCall) goja.Value {
49+
arg1 := call.Argument(0)
50+
item := a.converter(arg1)
51+
a.array.Splice(a.array.Len(), 0, []T{item})
52+
return goja.Undefined()
53+
})
54+
case "pop":
55+
return a.vm.ToValue(func(call goja.FunctionCall) goja.Value {
56+
if a.array.Len() > 0 {
57+
a.array.Splice(a.array.Len()-1, 1, nil)
58+
}
59+
60+
return goja.Undefined()
61+
})
62+
case "shift":
63+
return a.vm.ToValue(func(call goja.FunctionCall) goja.Value {
64+
if a.array.Len() > 0 {
65+
a.array.Splice(0, 1, nil)
66+
}
67+
return goja.Undefined()
68+
})
69+
case "unshift":
70+
return a.vm.ToValue(func(call goja.FunctionCall) goja.Value {
71+
values := call.Arguments[0:]
72+
items := make([]T, 0, len(values))
73+
for _, v := range values {
74+
items = append(items, a.converter(v))
75+
}
76+
a.array.Splice(0, 0, items)
77+
return goja.Undefined()
78+
})
79+
case "splice":
80+
return a.vm.ToValue(func(call goja.FunctionCall) goja.Value {
81+
start := call.Argument(0).ToInteger()
82+
deleteCount := call.Argument(1).ToInteger()
83+
values := call.Arguments[2:]
84+
items := make([]T, 0, len(values))
85+
for _, v := range values {
86+
items = append(items, a.converter(v))
87+
}
88+
89+
a.array.Splice(int(start), int(deleteCount), items)
90+
return goja.Undefined()
91+
})
92+
}
93+
94+
if i, err := strconv.Atoi(key); err == nil && i >= 0 && i < a.array.Len() {
95+
return a.vm.ToValue(a.array.Get(i))
96+
}
97+
98+
return nil
99+
}
100+
101+
func (a *TrackArray[T]) Set(key string, val goja.Value) bool {
102+
if i, err := strconv.Atoi(key); err == nil && i >= 0 {
103+
a.array.Set(i, a.converter(val))
104+
105+
return true
106+
}
107+
return false
108+
}
109+
110+
func (a *TrackArray[T]) Has(key string) bool {
111+
if key == "length" {
112+
return true
113+
}
114+
if i, err := strconv.Atoi(key); err == nil {
115+
return i >= 0 && i < a.array.Len()
116+
}
117+
return false
118+
}
119+
120+
func (a *TrackArray[T]) Delete(key string) bool {
121+
if i, err := strconv.Atoi(key); err == nil && i >= 0 && i < a.array.Len() {
122+
var zero T
123+
a.array.Set(i, zero)
124+
return true
125+
}
126+
return false
127+
}
128+
129+
func (a *TrackArray[T]) Keys() []string {
130+
keys := make([]string, a.array.Len())
131+
for i := 0; i < a.array.Len(); i++ {
132+
keys[i] = strconv.Itoa(i)
133+
}
134+
keys = append(keys, "length")
135+
return keys
136+
}

js/faker/faker.go

Lines changed: 13 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,59 +10,52 @@ import (
1010
"reflect"
1111
)
1212

13-
type Faker struct {
14-
rt *goja.Runtime
13+
type Module struct {
14+
vm *goja.Runtime
1515
host common.Host
1616
}
1717

1818
func Require(rt *goja.Runtime, module *goja.Object) {
1919
o := rt.Get("mokapi/internal").(*goja.Object)
2020
host := o.Get("host").Export().(common.Host)
21-
f := &Faker{
22-
rt: rt,
21+
f := &Module{
22+
vm: rt,
2323
host: host,
2424
}
2525
obj := module.Get("exports").(*goja.Object)
2626
obj.Set("fake", f.Fake)
2727
obj.Set("findByName", f.FindByName)
28+
obj.Set("ROOT_NAME", generator.RootName)
2829
}
2930

30-
func (m *Faker) Fake(v goja.Value) interface{} {
31+
func (m *Module) Fake(v goja.Value) interface{} {
3132
if v == nil {
3233
return nil
3334
}
3435

3536
t := v.ExportType()
3637
if t.Kind() != reflect.Map {
37-
panic(m.rt.ToValue(fmt.Errorf("expect object parameter but got: %v", util.JsType(v.Export()))))
38+
panic(m.vm.ToValue(fmt.Errorf("expect object parameter but got: %v", util.JsType(v.Export()))))
3839
}
3940

4041
r := &generator.Request{}
41-
if isOpenApiSchema(v.ToObject(m.rt)) {
42-
s, err := ToOpenAPISchema(v, m.rt)
42+
if isOpenApiSchema(v.ToObject(m.vm)) {
43+
s, err := ToOpenAPISchema(v, m.vm)
4344
if err != nil {
44-
panic(m.rt.ToValue(err.Error()))
45+
panic(m.vm.ToValue(err.Error()))
4546
}
4647
r.Schema = schema.ConvertToJsonSchema(s)
4748
} else {
48-
s, err := ToJsonSchema(v, m.rt)
49+
s, err := ToJsonSchema(v, m.vm)
4950
if err != nil {
50-
panic(m.rt.ToValue(err.Error()))
51+
panic(m.vm.ToValue(err.Error()))
5152
}
5253
r.Schema = s
5354
}
5455

5556
i, err := generator.New(r)
5657
if err != nil {
57-
panic(m.rt.ToValue(err.Error()))
58+
panic(m.vm.ToValue(err.Error()))
5859
}
5960
return i
6061
}
61-
62-
func (m *Faker) FindByName(name string) goja.Value {
63-
ft := m.host.FindFakerNode(name)
64-
if ft == nil {
65-
return nil
66-
}
67-
return convertToNode(ft, m)
68-
}

0 commit comments

Comments
 (0)