Virtual File System Service
Perform file and directory operations — read, write, copy, move, delete, list, and zip — programmatically from a JavaScript Processor or Python Processor.
The Virtual File System Service has no input/output ports and cannot be used as a standalone Workflow step. It must be invoked from script code.
What You'll Need
- A Virtual File System Connection with at least one mount point configured
- A Script Processor to call the service from
Configuration
Name & Description
| Field | Description |
|---|---|
| Virtual FS Service name | Asset identifier. This is the name you use in script code (e.g. services.MyVfsService). No spaces allowed. |
| Virtual FS Service description | Optional summary. |
| Asset Usage | Shows where this asset is referenced. Click to expand and jump to those locations. |
Required Rolesx
In case you are deploying to a Cluster which is running (a) Reactive Engine Nodes which have (b) specific Roles configured, then you can restrict use of this Asset to those Nodes with matching roles.
If you want this restriction, then enter the names of the Required Roles here. Otherwise, leave empty to match all Nodes (no restriction).
Virtual FS Service Settings
| Field | Description |
|---|---|
| Connection | The Virtual File System Connection that defines which mount points and storage backends (local, SMB, OneDrive, SharePoint, etc.) this service can access. |
Service Functions
- File Operations
- Directory Operations
| Function | Description |
|---|---|
CopyFile | Copy a file from one location to another. |
MoveFile | Move or rename a file. |
DeleteFile | Delete a file. |
FileExists | Check whether a file exists. Returns a boolean in the response data. |
ReadFile | Read a file and return its contents. |
WriteFile | Write data to a file. Creates the file if it does not exist. |
| Function | Description |
|---|---|
ListDir | List the contents of a directory. Since 2.5.10 |
DeleteDir | Delete a directory and all contents recursively. Use with caution. Since 2.5.10 |
ZipDir | Create a zip archive from a directory. Since 2.5.10 |
Quickstart
Step 1 — Create a Virtual File System Connection
Configure a Virtual File System Connection with the mount points you need (e.g. /data/inbox, /data/archive).
Step 2 — Create the Service Asset
Create a Virtual File System Service asset and select your connection in Virtual FS Service Settings.
Step 3 — Map the Service in a Script Processor
In your JavaScript or Python Processor, add a Service Mapping:
| Field | Value |
|---|---|
| Service | Your Virtual File System Service asset |
| Logical Service Name | Any valid identifier, e.g. MyVfsService (no spaces) |
Step 4 — Call the Service
All functions follow the same pattern:
- JavaScript
- Python
// In your processor's onMessage() function:
const result = services.MyVfsService.FunctionName({
param1: 'value',
param2: 'value'
});
# In your processor's on_message() function:
result = services.MyVfsService.FunctionName({
'param1': 'value',
'param2': 'value'
})
Function Reference
The examples below assume your service is mapped as MyVfsService.
- JavaScript
- Python
// Copy a file
services.MyVfsService.CopyFile({
sourcePath: '/data/inbox/report.pdf',
targetPath: '/data/archive/report.pdf'
});
// Move a file
services.MyVfsService.MoveFile({
sourcePath: '/data/inbox/report.pdf',
targetPath: '/data/archive/report.pdf'
});
// Delete a file
services.MyVfsService.DeleteFile({
path: '/data/inbox/report.pdf'
});
// Check if a file exists
const exists = services.MyVfsService.FileExists({ path: '/data/inbox/report.pdf' });
if (!exists.data) {
processor.logWarning('File not found');
}
// Read a file
const file = services.MyVfsService.ReadFile({ path: '/data/inbox/data.json' });
const records = JSON.parse(file.data.content);
// Write a file
services.MyVfsService.WriteFile({
path: '/data/outbox/result.json',
content: JSON.stringify(records)
});
// List a directory (2.5.10+)
const listing = services.MyVfsService.ListDir({
path: '/data/inbox',
recursive: false // set true to include subdirectories
});
listing.data.forEach(entry => {
processor.logInfo(`${entry.name} (${entry.isDirectory ? 'dir' : 'file'})`);
});
// Delete a directory recursively (2.5.10+)
services.MyVfsService.DeleteDir({
path: '/data/temp/batch-001'
});
// Zip a directory (2.5.10+)
services.MyVfsService.ZipDir({
sourcePath: '/data/outbox/invoice-batch-001',
targetPath: '/data/archive/invoice-batch-001.zip',
includeSubdirectories: true
});
import json
# Copy a file
services.MyVfsService.CopyFile({
'sourcePath': '/data/inbox/report.pdf',
'targetPath': '/data/archive/report.pdf'
})
# Move a file
services.MyVfsService.MoveFile({
'sourcePath': '/data/inbox/report.pdf',
'targetPath': '/data/archive/report.pdf'
})
# Delete a file
services.MyVfsService.DeleteFile({
'path': '/data/inbox/report.pdf'
})
# Check if a file exists
exists = services.MyVfsService.FileExists({'path': '/data/inbox/report.pdf'})
if not exists.data:
processor.log_warning('File not found')
# Read a file
file = services.MyVfsService.ReadFile({'path': '/data/inbox/data.json'})
records = json.loads(file.data.content)
# Write a file
services.MyVfsService.WriteFile({
'path': '/data/outbox/result.json',
'content': json.dumps(records)
})
# List a directory (2.5.10+)
listing = services.MyVfsService.ListDir({
'path': '/data/inbox',
'recursive': False # set True to include subdirectories
})
for entry in listing.data:
entry_type = 'dir' if entry.isDirectory else 'file'
processor.log_info(f"{entry.name} ({entry_type})")
# Delete a directory recursively (2.5.10+)
services.MyVfsService.DeleteDir({
'path': '/data/temp/batch-001'
})
# Zip a directory (2.5.10+)
services.MyVfsService.ZipDir({
'sourcePath': '/data/outbox/invoice-batch-001',
'targetPath': '/data/archive/invoice-batch-001.zip',
'includeSubdirectories': True
})
Parameter names (sourcePath, targetPath, path, content, recursive, includeSubdirectories) must match the service function definitions. Confirm these in the UI or Service Testing tab if they differ in your version.
Return Values
Most functions return a response object with a data field:
| Function | data contents |
|---|---|
FileExists | true or false |
ReadFile | Object with content (string) and contentType |
ListDir | Array of entries. Each entry has name, path, isDirectory, size, and modified. |
CopyFile, MoveFile, DeleteFile, WriteFile, DeleteDir, ZipDir | Typically empty or null on success. Check for exceptions to detect errors. |
Service Testing
Service Testing
layline.io provides a test facility for testing your Services before you deploy them. In this way, you save time and effort by testing your Services without having to deploy and activate a whole Project with Workflows.
Once you have configured your Service(s), you can test them:
Within your Asset Configuration tab (1), switch to the Test tab (2) to test your Service.

Test Facility Toolbar
The toolbar provides the following options:

The Testing tab provides two major views:
- Testcase configuration: This is where you define the testcases to be executed.
- Testcase execution: This is where you can execute the testcases and see the results.
You switch between these two views by clicking on the leftmost icon in the toolbar (1).
Let's start with the Testcase configuration view.
Testcase Configuration
The concept of the Testing is to define a set of Testcases which can be executed in a batch or individually. For this purpose, you can define multiple Testcases and configure them individually. I.e. each Testcase groups a number of indidivual tests which can be executed individually or in a batch.
Adding a Testcase
Click Add Testcase in the toolbar to add a new testcase:

A new Testcase is added.
It is automatically named New<Service Asset Name>Test (3) and added to the list of Testcases (2).
Service test name(3): You can change the name of the Testcase here.Service test description(4): You can add a description to the Testcase here.
Test Case Setup
Basics
In this section you define the individual tests to be executed for this Testcase.
To start, click # END in the toolbar:
A new test is added to the list of tests (1), and the test is opened for configuration (2).

Next we fill in the details:
-
Test name(3): You can change the name of the Test here. -
Test description(4): You can add a description to the Test here. -
Service function to test(5): Select the Service function to test here.This list contains all Service functions which are defined in the Service Asset. Pick the one you want to test.

Once a Service function is selected, the system will automatically create a skeleton to fill in the respective parameters for the selected Service function.

Service Function Input Parameters
-
Service Function Input Parameters(6): Fill in the respective parameters for the selected Service function.In our example we have a function
GetAlertsForSitewhich takes two parametersbaseurlandriskId. If we click onAdd memberin the skeleton table the system will allow you to select the respective parameter from the list of available parameters:
Once you have selected the parameter, the system will automatically add the respective parameter name. You then add the respective value for the parameter:

Service Function Evaluation Parameters
To automatically evaluate the result, you can add a script which analyzes the results.
Testcase Execution
Once you have configured your Testcases, you can execute them.
There are two ways on how to trigger execution:
-
Option 1: Select
Run selected testin the toolbar (1) to execute the currently selected Testcase.
Executing a test this way will switch the tab to the Testcase execution view, execute the test and show the results.
-
Option 2: Switch to the Testcase execution view by clicking on the leftmost icon in the toolbar (1) select the test to execute, and then hit the
playbutton next to the test.
Each option will take us to the Testcase execution view:

In this view you can find the Testcase (1) and the Tests (2) we have created.
If we had created additional tests for this Testcase, they would be listed here as well.
Question marks indicate that the test has not yet been executed.
We can now either execute all tests, or run them individually:
-
Run all Tests(1): Click this button to execute all tests. -
Run Testcase(2): Click this button to a Testcase with all its underlying individual tests.
-
Run individual Test(3): Click this button next to a test to execute this individual test.
Once a test has been executed, the question mark will be replaced by a green check mark or a red cross depending on whether the test was successful or not.
The right hand-panel will show the results of the test execution respectively:

In case of errors, the system will show the error message for further investigation.
See Also
- Virtual File System Connection — configuring mount points and storage backends
- JavaScript Processor — calling services from JavaScript
- Python Processor — calling services from Python