Skip to content

Commit 1bb3077

Browse files
authored
Merge branch 'develop' into dependabot/npm_and_yarn/webui/develop/ldapts-8.1.2
2 parents ec5b69d + d4b3700 commit 1bb3077

54 files changed

Lines changed: 1053 additions & 465 deletions

Some content is hidden

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

docs/javascript-api/modules.md

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,9 +10,10 @@ Mokapi supports importing three types of modules:
1010
- **Built-in modules**: Provided by Mokapi for various functionalities.
1111
- **Local filesystem modules**: Custom scripts and Node.js packages.
1212
- **JSON & YAML modules**: Configuration files converted into JavaScript objects.
13+
- **Remote modules**: Hosted on a web server or CDN
1314

1415
``` box=tip
15-
Mokapi monitors all imported modules with `fsnotify`. If a module is modified, any dependent script is automatically reloaded.
16+
Mokapi monitors all imported modules with `fsnotify`. If a module is modified, any dependent script that contains a `default` export is automatically reloaded.
1617
```
1718

1819
## Built-in Modules
@@ -26,7 +27,7 @@ import { fake } from 'mokapi/faker'
2627

2728
## Local Filesystem Modules
2829

29-
You can import files using relative or absolute paths, and Mokapi supports Node.js modules.
30+
Import files using relative or absolute paths. Node.js resolution rules are supported.
3031

3132
```javascript
3233
import { someFunc } from './helpers.js'
@@ -36,7 +37,7 @@ import dateTime from 'date-time' // Requires: npm install date-time
3637

3738
## JSON & YAML Modules
3839

39-
Mokapi allows importing JSON and YAML files, automatically converting them into JavaScript objects.
40+
JSON and YAML files can be imported and converted automatically to objects:
4041

4142
```javascript tab=Javascript
4243
import users from './users.json'
@@ -57,4 +58,15 @@ console.log(envs[0])
5758
- production
5859
```
5960
61+
## Remote Modules
62+
63+
Modules can also be hosted remotely on public web servers, GitHub, or CDNs.
64+
65+
```js
66+
import { helper } from 'https://example.com/mokapi-helpers.js'
67+
```
68+
69+
- Mokapi uses its [HTTP provider](/docs/configuration/dynamic/http.md) to load remote modules
70+
- This allows dynamic updates without restarting Mokapi
71+
6072
By leveraging these module types, you can create flexible, maintainable, and scalable Mokapi scripts.

docs/javascript-api/mokapi/cron.md

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@ description: Schedules a new periodic job using cron expression.
66

77
Schedules a new periodic job using cron expression.
88

9-
``` box=info
10-
By default, the first execution happens immediately, check ScheduledEventArgs
11-
```
9+
### Behavior
10+
11+
- By default, **cron jobs wait for the first scheduled tick** before executing.
12+
- To run the job immediately on creation, set `SkipImmediateFirstRun: false` in `args`.
1213

1314
## Parameters
1415

docs/javascript-api/mokapi/eventhandler/scheduledeventargs.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,11 +7,11 @@ description: ScheduledEventArgs is an object used by every and cron function.
77
ScheduledEventArgs is an object used by [every](/docs/javascript-api/mokapi/every.md) and
88
[cron](/docs/javascript-api/mokapi/cron.md) function.
99

10-
| Name | Type | Description |
11-
|-----------------------|---------|---------------------------------------------------------------------------------------------------------------------------------|
12-
| times | number | Defines the number of times the scheduled function is executed. |
13-
| skipImmediateFirstRun | boolean | Toggles behavior of first execution. If true job does not start immediately but rather wait until the first scheduled interval. |
14-
| tags | object | Adds or overrides existing tags used in dashboard |
10+
| Name | Type | Default | Description |
11+
|-----------------------|----------|---------|---------------------------------------------------------------------------------------------------------------------------------|
12+
| times | number | -1 | How many times the job should execute (-1 for unlimited). |
13+
| skipImmediateFirstRun | boolean | | Toggles behavior of first execution. If true job does not start immediately but rather wait until the first scheduled interval. |
14+
| tags | object | {} | Optional tags for identifying the job. |
1515

1616
## Examples
1717

docs/javascript-api/mokapi/every.md

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,15 +8,16 @@ Schedules a new periodic job with an interval. Interval string
88
is a possibly signed sequence of decimal numbers, each with
99
optional fraction and a unit suffix, such as "300ms", "-1.5h" or "2h45m".
1010

11-
``` box=info
12-
By default, the first execution happens immediately, check ScheduledEventArgs
13-
```
11+
### Behavior
12+
13+
- By default, **`every` jobs run immediately**, then repeat according to the interval.
14+
- To skip the immediate run, set `SkipImmediateFirstRun: true` in `args`.
1415

1516
| Parameter | Type | Description |
1617
|-----------------|----------|----------------------------------------------------------------------------------------------------------------------------------|
1718
| interval | string | Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h". |
1819
| handler | function | The handler function to be executed every `interval`. By default, the first execution happens immediately. |
19-
| args (optional) | object | [ScheduledEventArgs](/docs/javascript-api/mokapi/eventhandler/scheduledeventargs.md) object contains additional event arguments. |
20+
| args (optional) | object | [ScheduledEventArgs](/docs/javascript-api/mokapi/eventhandler/scheduledeventargs.md) object contains additional event arguments. |
2021

2122
## Example
2223

docs/javascript-api/overview.md

Lines changed: 140 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,48 +1,155 @@
11
---
22
title: JavaScript API Documentation
3-
description: Explore Mokapi’s JavaScript API to extend its functionality. Learn how to use modules for HTTP, Kafka, YAML, Mustache, and more.
3+
description: Extend and customize Mokapi using JavaScript. Learn how to structure scripts, use built-in modules, and handle runtime limitations.
44
---
5+
56
# Mokapi JavaScript API
67

7-
Mokapi provides a powerful JavaScript API that allows you to extend its functionality.
8-
This documentation outlines the available modules and their capabilities.
9-
To learn how Mokapi handles module imports, see [Modules](/docs/javascript-api/modules.md).
8+
Mokapi allows you to extend and customize its behavior using JavaScript.
9+
JavaScript is used to implement dynamic logic such as request handling, data generation,
10+
scheduled jobs, and event-driven workflows.
11+
12+
Mokapi executes JavaScript in a **simple and explicit way**:
13+
only files that export a **default function** are executed.
14+
All other JavaScript files are treated as **modules**.
15+
16+
This documentation explains:
17+
- How JavaScript is executed in Mokapi
18+
- Script vs module structure
19+
- Runtime environment limitations
20+
- Built-in modules
21+
22+
## How JavaScript Is Used in Mokapi
23+
24+
JavaScript can be used for tasks such as:
25+
26+
- Handling HTTP, Kafka, and other protocol events
27+
- Generating dynamic mock data
28+
- Scheduling background jobs
29+
- Transforming or enriching request and response data
30+
31+
Each JavaScript file is either:
32+
- an **executable script**, or
33+
- a **module** imported by other scripts
34+
35+
## Executable Scripts (Default Function)
36+
37+
A JavaScript file is executed **only if it exports a default function**.
38+
39+
```js
40+
export default function (ctx) {
41+
// executed by Mokapi
42+
}
43+
```
44+
45+
- The default function is the entry point of the script
46+
- Mokapi invokes this function directly
47+
- All execution logic must be placed inside this function
48+
49+
If a file does not export a default function, Mokapi **will not execute it**.
50+
51+
## Runtime Environment
52+
53+
Mokapi executes JavaScript in its own runtime.
54+
It is **not** a Node.js environment and **not** a browser environment.
55+
56+
As a result, many APIs that are commonly available in Node.js or browsers are **not available** in Mokapi.
57+
58+
### ⚠️ Important Limitations
59+
60+
- Node.js built-ins such as `fs`, `path`, `os`, or `net` are not available
61+
- Browser APIs such as `window`, `document`, or `fetch` are not available
62+
- Third-party packages that rely on Node.js or browser APIs may fail
63+
64+
### Provided Alternatives
65+
66+
Mokapi provides its own APIs for common tasks:
67+
68+
- **HTTP requests**
69+
Use the `fetch` function from `mokapi/http`:
70+
```js
71+
import { fetch } from "mokapi/http"
72+
```
73+
- **File access**
74+
Use the global open() function to read files:
75+
```js
76+
const text = open("data/example.json")
77+
```
78+
- **Environment variables**
79+
Use env() from the core API:
80+
```js
81+
import { env } from "mokapi"
82+
```
83+
84+
## Modules
85+
86+
JavaScript files without a **default export** are treated as **modules**.
87+
Modules allow you to organize and reuse code.
88+
89+
```js
90+
export function normalizeUser(user) {
91+
return { ...user, active: true }
92+
}
93+
```
94+
95+
- Modules are not executed by Mokapi
96+
- Can be imported by executable scripts or other modules
97+
- Used to organize shared logic
98+
99+
For more details on the different types of modules (built-in, local filesystem, JSON/YAML), see the dedicated [JavaScript Modules guide](/docs/javascript-api/modules.md).
100+
101+
## Module Resolution
102+
103+
Mokapi resolves imports using the same algorithm as Node.js:
104+
105+
1. The directory of the importing file
106+
2. Any node_modules directory in the same folder
107+
3. Parent directories up to the nearest package.json
108+
109+
> Module resolution only determines where Mokapi looks for the file.
110+
Runtime limitations still apply: modules that rely on Node.js or browser APIs may fail.
111+
112+
## TypeScript Support
10113

11114
``` box=tip url=[@types/mokapi on npm](https://www.npmjs.com/package/@types/mokapi)
12-
Mokapi offers a TypeScript definition package. Install it using:
115+
Mokapi provides TypeScript type definitions for its JavaScript API.
116+
Install them using:
13117
`npm install @types/mokapi --save-dev`
14118
```
15119

16-
## Available Modules
120+
## Built-in Modules
121+
122+
Mokapi provides a set of built-in JavaScript modules that can be used from executable scripts
123+
and custom modules.
17124

18125
### mokapi (Core API)
19126

20127
Provides core functions for scheduling jobs, handling events, and accessing environment variables.
21128

22-
| Functions | Description |
23-
|------------------------------------------------------------------------------|-------------------------------------------------------|
24-
| [cron( expression, handler, \[args\] )](/docs/javascript-api/mokapi/cron.md) | Schedules a new periodic job using a cron expression. |
25-
| [date( \[args\] )](/docs/javascript-api/mokapi/date.md) | Returns a formatted date string. |
26-
| [env( name )](/docs/javascript-api/mokapi/env.md) | Gets the value of an environment variable. |
27-
| [every( interval, handler, \[args\] )](/docs/javascript-api/mokapi/every.md) | Runs a periodic job at a fixed interval. |
28-
| [on( event, handler, \[args\]](/docs/javascript-api/mokapi/on.md) ) | Registers an event handler. |
29-
| [sleep( time )](/docs/javascript-api/mokapi/sleep.md) | Pauses execution for a specified duration. |
30-
| [marshal( value, \[encoding\] )](/docs/javascript-api/mokapi/marshal.md) | Converts a value to a marshaled string. |
129+
| Functions | Description |
130+
|------------------------------------------------------------------------------|---------------------------------------------------|
131+
| [cron( expression, handler, \[args\] )](/docs/javascript-api/mokapi/cron.md) | Schedules a periodic job using a cron expression. |
132+
| [date( \[args\] )](/docs/javascript-api/mokapi/date.md) | Returns a formatted date string. |
133+
| [env( name )](/docs/javascript-api/mokapi/env.md) | Gets the value of an environment variable. |
134+
| [every( interval, handler, \[args\] )](/docs/javascript-api/mokapi/every.md) | Runs a periodic job at a fixed interval. |
135+
| [on( event, handler, \[args\]](/docs/javascript-api/mokapi/on.md) ) | Registers an event handler. |
136+
| [sleep( time )](/docs/javascript-api/mokapi/sleep.md) | Pauses execution |
137+
| [marshal( value, \[encoding\] )](/docs/javascript-api/mokapi/marshal.md) | Converts a value to a marshaled string. |
31138

32139
### mokapi/http (HTTP Requests)
33140

34141
Functions to send HTTP requests within Mokapi scripts.
35142

36-
| Functions | Description |
37-
|-----------------------------------------------------------------------------------|----------------------------------------|
38-
| [get( url, \[args\] )](/docs/javascript-api/mokapi-http/get.md) | Sends an HTTP GET request. |
39-
| [post( url, \[body\], \[args\] )](/docs/javascript-api/mokapi-http/post.md) | Sends an HTTP POST request |
40-
| [put( url, \[body\], \[args\] )](/docs/javascript-api/mokapi-http/put.md) | Sends an HTTP PUT request |
41-
| [head( url, \[args\] )](/docs/javascript-api/mokapi-http/head.md) | Sends an HTTP HEAD request |
42-
| [patch( url, \[body\], \[args\] )](/docs/javascript-api/mokapi-http/patch.md) | Sends an HTTP PATCH request |
43-
| [delete( url, \[body\], \[args\] )](/docs/javascript-api/mokapi-http/delete.md) | Sends an HTTP DELETE request |
44-
| [options( url, \[body\], \[args\] )](/docs/javascript-api/mokapi-http/options.md) | Sends an HTTP OPTIONS request |
45-
| [fetch( url, \[opts\] )](/docs/javascript-api/mokapi-http/fetch.md) | Create an HTTP request using Fetch API |
143+
| Functions | Description |
144+
|-----------------------------------------------------------------------------------|-------------------------------|
145+
| [get( url, \[args\] )](/docs/javascript-api/mokapi-http/get.md) | Sends an HTTP GET request. |
146+
| [post( url, \[body\], \[args\] )](/docs/javascript-api/mokapi-http/post.md) | Sends an HTTP POST request |
147+
| [put( url, \[body\], \[args\] )](/docs/javascript-api/mokapi-http/put.md) | Sends an HTTP PUT request |
148+
| [head( url, \[args\] )](/docs/javascript-api/mokapi-http/head.md) | Sends an HTTP HEAD request |
149+
| [patch( url, \[body\], \[args\] )](/docs/javascript-api/mokapi-http/patch.md) | Sends an HTTP PATCH request |
150+
| [delete( url, \[body\], \[args\] )](/docs/javascript-api/mokapi-http/delete.md) | Sends an HTTP DELETE request |
151+
| [options( url, \[body\], \[args\] )](/docs/javascript-api/mokapi-http/options.md) | Sends an HTTP OPTIONS request |
152+
| [fetch( url, \[opts\] )](/docs/javascript-api/mokapi-http/fetch.md) | Fetch using Mokapi's API |
46153

47154
### mokapi/faker (Mock Data Generator)
48155

@@ -72,19 +179,19 @@ Processes Mustache templates with dynamic data.
72179

73180
Handles YAML data parsing and conversion.
74181

75-
| Functions | Description |
76-
|---------------------------------------------------------------------|-------------------------------------------------|
77-
| [parse( text )](/docs/javascript-api/mokapi-yaml/parse.md) | Parses a YAML string into a JavaScript object. |
78-
| [stringify( value )](/docs/javascript-api/mokapi-yaml/stringify.md) | Converts a JavaScript object into YAML format. |
182+
| Functions | Description |
183+
|---------------------------------------------------------------------|--------------------------------------|
184+
| [parse( text )](/docs/javascript-api/mokapi-yaml/parse.md) | Parses a YAML string into an object. |
185+
| [stringify( value )](/docs/javascript-api/mokapi-yaml/stringify.md) | Converts an object to YAML. |
79186

80187
### mokapi/encoding (Encoding Utilities)
81188

82189
Functions for encoding and decoding data.
83190

84-
| Functions | Description |
85-
|---------------------------------------------------------------------------------|-----------------------------------|
86-
| [base64.encode( input )](/docs/javascript-api/mokapi-encoding/base64-encode.md) | Encodes a string using Base64. |
87-
| [base64.decode( input )](/docs/javascript-api/mokapi-encoding/base64-decode.md) | Decodes a Base64-encoded string. |
191+
| Functions | Description |
192+
|---------------------------------------------------------------------------------|-----------------------------|
193+
| [base64.encode( input )](/docs/javascript-api/mokapi-encoding/base64-encode.md) | Encodes a string to Base64. |
194+
| [base64.decode( input )](/docs/javascript-api/mokapi-encoding/base64-decode.md) | Decodes a Base64 string. |
88195

89196

90197

engine/engine.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -83,9 +83,12 @@ func (e *Engine) AddScript(evt dynamic.ConfigEvent) error {
8383
err := e.run(host)
8484
if err != nil {
8585
if errors.Is(err, UnsupportedError) {
86-
log.Debugf("script not supported: %v", evt.Config.Info.Url.Path)
86+
log.Debugf(
87+
"skipping script execution: JavaScript runner does not support this file type: %s",
88+
evt.Config.Info.Url,
89+
)
8790
} else {
88-
log.Errorf("error executing script %v: %v", evt.Config.Info.Url, err)
91+
log.Errorf("error executing script %s: %v", evt.Config.Info.Url, err)
8992
}
9093
}
9194
}()

engine/scheduler.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,11 @@
11
package engine
22

33
import (
4-
"github.com/go-co-op/gocron"
54
"mokapi/engine/common"
65
"sync"
76
"time"
7+
8+
"github.com/go-co-op/gocron"
89
)
910

1011
type Scheduler interface {
@@ -54,8 +55,8 @@ func (s *DefaultScheduler) Cron(expr string, handler func(), opt common.JobOptio
5455
if opt.Times > 0 {
5556
s.scheduler.LimitRunsTo(opt.Times)
5657
}
57-
if opt.SkipImmediateFirstRun {
58-
s.scheduler.WaitForSchedule()
58+
if !opt.SkipImmediateFirstRun {
59+
handler()
5960
}
6061

6162
return s.scheduler.Do(handler)

imap/idle_test.go

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,8 @@ func TestIdle(t *testing.T) {
178178
require.NoError(t, err)
179179
require.Equal(t, "+ idling", res)
180180

181+
time.Sleep(500 * time.Millisecond)
182+
181183
res, err = c.ReadLine()
182184
require.NoError(t, err)
183185
require.Equal(t, "* 10 EXISTS", res)

js/mokapi/cron.go

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,11 @@ import (
1111
)
1212

1313
func (m *Module) Cron(expr string, do goja.Value, args goja.Value) (int, error) {
14-
options, err := getJobOptions(m.vm, args)
14+
options, err := getJobOptions(m.vm, args, common.JobOptions{
15+
Tags: map[string]string{},
16+
Times: -1,
17+
SkipImmediateFirstRun: true,
18+
})
1519
if err != nil {
1620
panic(m.vm.ToValue(err.Error()))
1721
}
@@ -33,8 +37,8 @@ func (m *Module) Cron(expr string, do goja.Value, args goja.Value) (int, error)
3337
return m.host.Cron(expr, f, options)
3438
}
3539

36-
func getJobOptions(vm *goja.Runtime, opt goja.Value) (common.JobOptions, error) {
37-
options := common.NewJobOptions()
40+
func getJobOptions(vm *goja.Runtime, opt goja.Value, defaultOptions common.JobOptions) (common.JobOptions, error) {
41+
options := defaultOptions
3842

3943
if opt != nil && !goja.IsUndefined(opt) && !goja.IsNull(opt) {
4044
if opt.ExportType().Kind() != reflect.Map {

js/mokapi/every.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
package mokapi
22

33
import (
4+
"mokapi/engine/common"
45
"mokapi/js/eventloop"
56

67
"github.com/dop251/goja"
78
)
89

910
func (m *Module) Every(every string, do goja.Value, args goja.Value) (int, error) {
10-
options, err := getJobOptions(m.vm, args)
11+
options, err := getJobOptions(m.vm, args, common.JobOptions{
12+
Tags: map[string]string{},
13+
Times: -1,
14+
SkipImmediateFirstRun: false,
15+
})
1116
if err != nil {
1217
panic(m.vm.ToValue(err.Error()))
1318
}

0 commit comments

Comments
 (0)