@beezwax/fmbond
v1.3.1
Published
A bridge for sending/receiving data between FileMaker and the web viewer
Downloads
2
Readme
FMBond
Table of Contents
Introduction
FMBondJS is part of the FMBond toolset. It manages interactions between FileMaker scripts and FileMaker web viewers.
Features
- Get FileMaker script results as JavaScript Promises.
- Perform JavaScript functions from FileMaker and return the results to FileMaker as part of the regular script flow.
- Safely wait for the availability of the FileMaker injected class before attempting to perform scripts.
- Extend through a built-in plugin registration system.
FMBondJS is also used as the function runner for the FMBondServer web service
Installation
- Install FMBondJS
npm i @beezwax/fmbond
- Download the following FileMaker file, and copy the
FMBondRelay
script into the target FileMaker file.
curl -O https://github.com/beezwax/fmbond-relay-script/raw/main/fmbond-relay-script.fmp12
Requirements
- FileMaker 19.3 or higher.
- All FileMaker web viewer objects used with FMBondJS must be named in the FileMaker layout inspector.
- The option 'Allow JavaScript to perform FileMaker scripts' must be checked in all web viewers used with FMBondJS.
Usage
Performing FileMaker Scripts from JavaScript
FMBond.PerformScript(scriptName, scriptParameter [, options])
FMBond.PerformScript("add two numbers", { firstNum: 1, secondNum: 2 })
.then((result) => console.log(result));
FMBond.PerformScript("Get User Data", "user-123", { timeout: 3000 })
.then((data) => console.log(data.firstName))
.catch((e) => console.log('request took too long', e));
The options object is optional and can contain any of the following (defaults shown):
{
webViewerName: "", // The name of the web viewer hosting the web code.
timeout: null, // Number of milliseconds to wait before a promise is rejected.
callType: 0 // The FileMaker 'call type'.
relayScript: "FMBondRelay" // The relay script as it is named in the FileMaker solution.
ignoreResult: false // When true, promise resolves immediately - does not wait for FileMaker script.
}
The callType can be any of the following values (when not provided it is "continue" by default). See the Claris documentation for more details
"continue" (or 0, "0")
"halt" (or 1, "1")
"exit" (or 2, "2")
"resume" (or 3, "3")
"pause" (or 4, "4")
"interrupt" (or 5, "5")
The callType can alternatively be provided as the third parameter to PerformScript.
FMBond.PerformScript("Get Data", "", { callType: "interrupt" });
// is equal to
FMBond.PerformScript("Get Data", "", "interrupt" );
FMBond.SetWebViewerName(webViewerName) | FMBond.GetWebViewerName()
The Web Viewer name can be globally adjusted. The provided FMBondRelay script does not require this, however when using a custom relay script usng the spec, the web viewer name may need to set in JS code.
FMBond.GetWebViewerName(); // "" (default)
FMBond.SetWebViewerName("myWebViewer");
FMBond.GetWebViewerName(); // "myWebViewer"
FMBond.SetRelayScriptName(relayScriptName) | FMBond.GetRelayScriptName()
The Relay Script name can be globally adjusted. This is required if the default name (FMBondRelay
) is not used.
FMBond.GetRelayScriptName(); // "FMBondRelay" (default)
FMBond.SetRelayScriptName("My Relay Script");
FMBond.GetRelayScriptName(); // "My Relay Script"
FMBond.SetWebViewerNameFromFM()
Determines the name of the web viewer that FMBond is running in and stores it. This is useful for ensuring that subsequent FMBond.PerformScript
calls do not invoke potentially expensive searches for the initiating web viewer.
Returns a promise
FMBond.GetWebViewerName(); // ""
FMBond.SetWebViewerNameFromFM()
.then((result) => {
console.log(result) // "myWV"
console.log(FMBond.GetWebViewerName()) // "myWV"
});
FMBond.SyncConfig()
By defining a JSON blob in the Web Address
portion of the Web Viewer:
SyncConfig
returns the Web Viewer JSON configuration as a promise result.SetWebViewerConfigFromFM
calls FileMaker and updates the configuration stored in FMBond.SetWebViewerConfig(webViewerConfig)
allows manual overwrite of the configuration stored in FMBond.GetConfig
returns the current configuration stored in FMBond.
// For example:
// • A Web Viewer is in the context of the PERSON table.
// • The PERSON::NAME field is "John Smith".
// • This Web Viewer's Web Address is set to JSONSetElement( "{}" ; "NAME" ; PERSON::NAME ; JSONString )
FMBond.GetConfig() // "{}"
FMBond.SetConfig({"NAME": "Kevin Paddlesmith"});
FMBond.GetConfig() // { "NAME": "Kevin Paddlesmith" }
FMBond.SyncConfig().then((config) => {
console.log(config.NAME) // "John Smith"
});
FMBond.RegisterScript(pluginOptions)
It possible to extend FMBond by registering custom FileMaker scripts, which can then be can be called as methods. This allows the FMBondRelay script to be bypassed and may make it easier to implement custom behavior.
- Create a script in FileMaker.
- Perform
FMBond.RegisterScript
giving it the appropriate pluginOptions.
pluginOptions
exec
: the method that becomes available to use on theFMBond
class.scriptName
: the FileMaker script that will be run when the method defined inexec
is called.throwIf
: (optional) callback function that takes the result of the script defined inscriptName
as a parameter. If the function returnstrue
an error will be thrown.
// define the script
FMBond.RegisterScript({
exec: "executeDataApi",
scriptName: "Execute Data Api",
throwIf: (scriptResult) => {
return scriptResult.messages[0].code !== "0" ;
},
});
// Performing the script
const myQuery = {
layouts: "FAKE_DATA",
query: [{
SOME_DATA: "==definitely data here",
}],
};
FMBond.executeDataApi(myQuery)
.then((result) => {
console.log('my data', result);
})
.catch((e) => {
console.log('query failed', e.toString());
});
// The second parameter can also take advantage of FMBond options
FMBond.executeDataApi(myQuery, { timeout: 3000, callType: "interrupt" })
.then((result) => {
console.log('my data', result);
})
.catch((e) => {
console.log('query failed', e.toString());
});
Promise rejection and Error Handling
The promises settled by the FMBondRelay script will only reject when the specified FileMaker script is missing.
Otherwise, the result of the script's Exit Script[]
step will be returned as the result of resolved promise and not a rejected promise. Because there is no standard way to indicate that a FileMaker script resulted in an error, the result of the promise will need to be inspected and an error thrown if required.
Note that when registering a plugin, the throwIf
parameter can be used set the result state(s) that should throw errors.
Performing JavaScript functions from FileMaker
A web viewer that contains the FMBond class can return the result of a JavaScript function performed by FileMaker's Perform Javascript in Web Viewer
script step. This allows the following FileMaker scripting pattern:
Perform JavaScript in Web Viewer [ ... ]
Set Variable[ $javaScriptResult; Get ( ScriptResult ) ]
That is, results of functions called using Perform Javascript in Web Viewer
can be captured inline with minimal impact on the normal FileMaker script flow.
To utilize this feature configure the Perform Javascript in Web Viewer
script step as follows:
- Function Name:
FMBond
- First parameter either
- a function in the global (window) JavaScript context of the web viewer OR
- a JavaScript function (arrow or classic) defined as a string
- Subsequent parameters will be passed into the function. To treat a JavaScript parameter as a callback function, prefix it with the 'ƒ' symbol (⌥ + f on macs).
Results are always obtained via Get ( ScriptResult )
, nested in the response.result
key. The response.result prop will be appropriately formatted (eg: as a number for numbers, string for strings, object for objects, etc...).
Example 1 Calling a function AddTwoNumbers that is accessible via window.AddTwoNumbers
in the web viewer.
Perform JavaScript in Web Viewer [
Object Name: "MyWebViewer" ;
Function Name: "FMBond" ;
Parameters: "AddTwoNumbers", 3, 5
]
Set Variable [
$_new_number ;
Value: JSONGetElement ( Get ( ScriptResult ) ; "response.result" )
]
// $_new_number = 8
Example 2 Calling a FileMaker-defined function (define and run JavaScript on the fly in FileMaker)
Set Variable [
$_add_two_numbers_func ;
Value: "(a, b) => a + b"
]
Perform JavaScript in Web Viewer [
Object Name: "MyWebViewer" ;
Function Name: "FMBond" ;
Parameters: $_add_two_numbers_func, 3, 5
]
Set Variable [
$_new_number ;
Value: JSONGetElement ( Get ( ScriptResult ) ; "response.result" )
]
// $_new_number = 8
Example 3 Support for Callbacks (remember to prefix with an 'ƒ')
Set Variable [
$_add_number_with_callback ;
Value: "function (myCallbackForC, a, b, c) { return a + b + myCallbackForC(c); }"
]
Set Variable [
$_times_two ;
Value: "ƒ(value) => value * 2"
]
Perform JavaScript in Web Viewer [
Object Name: "MyWebViewer" ;
Function Name: "FMBond" ;
Parameters: $_add_two_numbers_func, $_times_two, 3, 5, 50
]
Set Variable [
$_new_number ;
Value: JSONGetElement ( Get ( ScriptResult ) ; "response.result" )
]
// $_new_number = 108
Get ( ScriptResult ) response
{
"messages" :
[
{
"code" : "0",
"message" : "OK"
}
],
"response" :
{
"result" : 108
}
}
Errors are captured and returned for the following scenarios:
- function does not exist in JavaScript.
- function defined in FileMaker has invalid syntax (for example, a missing parenthesis:
"(a, b => a + b"
). - function executed in JavaScript throws an error.
- FMBond does not exist in the web viewer (in this case, the PerformJavascript step itself will surface an error).
{
"messages" :
[
{
"code" : "5",
"message" : "The function 'MyGlobalFunc' is missing from the global scope, or is not a valid function definition"
}
],
"response" : {}
}
Contributors
Brendan Pierce, Alec Gregory, Brandon Montoya, Max Petrusenko, and valuable contributions from members of the Beezwax team