# bzBond-js ## Table of Contents - [Introduction](#introduction) - [Features](#features) - [Installation](#installation) - [Requirements](#requirements) - [Usage](#usage) - [Performing Claris/FileMaker Scripts from JavaScript](#performing-clarisfilemaker-scripts-from-javascript) - [PerformScript](#bzbondperformscriptscriptname-scriptparameter-options) - [{Set/Get}WebViewerName](#bzbondsetwebviewernamewebviewername--bzbondgetwebviewername) - [SetWebViewerNameFromClaris](#bzbondsetwebviewernamefromclaris) - [{Set/Get}RelayScriptName](#bzbondsetrelayscriptnamerelayscriptname--bzbondgetrelayscriptname) - [SyncConfig](#bzbondsyncconfig) - [RegisterScript](#bzbondregisterscriptpluginoptions) - [Promise rejection and Error Handling](#promise-rejection-and-error-handling) - [Integrating JavaScript functions with Claris/FileMaker scripts](#integrating-javascript-functions-with-clarisfilemaker-scripts) - [Contributors](#contributors) ## Introduction bzBond-js is part of the [bzBond](/) toolset. It manages interactions between FileMaker scripts and FileMaker Web Viewers. It requires [bzBond-claris](../bzBond-claris/). ## Features - Call Claris/FileMaker scripts from web viewers using `bzBond.PerformScript`. This function returns a **JavaScript Promise** including the script result. - Use JavaScript functions in Claris/FileMaker scripts by calling the `bzBondRelay` script. Function results can be accessed in `Get ( ScriptResult )` - Extensible through a built-in plugin registration system. ## Installation 1. Install bzBond-js ``` npm i @beezwax/bzbond-js ``` 2. Download the [bzBond-claris.fmp12](https://github.com/beezwax/bzbond/blob/main/packages/bzBond-claris/bzBond-claris.fmp12?raw=true) Claris/FileMaker file, and copy the `bzBondRelay` script into the target Claris/FileMaker file. ## Requirements - FileMaker >=19.3. - Web Viewers that host the bzBond code must: - Have an **object name** assigned in Layout inspector: - Have the **'Allow JavaScript to perform FileMaker scripts'** option on in the Web Viewer Setup dialog checked: --- ## Usage ### Performing Claris/FileMaker Scripts from JavaScript #### bzBond.PerformScript(scriptName, [scriptParameter, options]) ``` bzBond.PerformScript("add two numbers", { firstNum: 1, secondNum: 2 }) .then((result) => console.log(result)); bzBond.PerformScript("Get User Data", "user-123", { timeout: 3000 }) .then((data) => console.log(data.firstName)) .catch((e) => console.log('request took too long', e)); ``` The (optional) **options** parameter 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 Claris/FileMaker 'call type'. relayScript: "bzBondRelay" // The relay script as it is named in the Claris/FileMaker solution. ignoreResult: false // When true, promise resolves immediately - does not wait for Claris/FileMaker script. } ``` The **callType** can be any of the following values (when not provided it is "continue" by default). See the [Claris documentation](https://help.claris.com/en/pro-help/content/options-for-starting-scripts.html) 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 part of an object, or string. ``` bzBond.PerformScript("Get Data", "", { callType: "interrupt" }); // is equal to bzBond.PerformScript("Get Data", "", "interrupt" ); ``` #### bzBond.SetWebViewerName(webViewerName) | bzBond.GetWebViewerName() This method manually associates bzBond with the name of the Web Viewer the code resides in. - This step is optional when using the provided bzBondRelay script (it automatically determines the name of the web viewer). - If you choose to write a custom relay script using the spec, you may need to set the name in your JS code. ``` bzBond.GetWebViewerName(); // "" (default) bzBond.SetWebViewerName("myWebViewer"); bzBond.GetWebViewerName(); // "myWebViewer" ``` #### bzBond.SetWebViewerNameFromClaris() Determines the name of the web viewer that bzBond is running in and stores it as part of the bzBond instance. This is useful for ensuring that subsequent `bzBond.PerformScript` calls do not invoke potentially expensive searches for the initiating web viewer. Returns a **promise** ``` bzBond.GetWebViewerName(); // "" bzBond.SetWebViewerNameFromClaris() .then((result) => { console.log(result) // "myWV" console.log(bzBond.GetWebViewerName()) // "myWV" }); ``` #### bzBond.SetRelayScriptName(relayScriptName) | bzBond.GetRelayScriptName() If you choose to change the name of the Relay Script in Claris/FileMaker Pro, use this step to ensure bzBond calls to Claris/FileMaker Pro perform the correct script. ``` bzBond.GetRelayScriptName(); // "bzBondRelay" (default) bzBond.SetRelayScriptName("My Relay Script"); bzBond.GetRelayScriptName(); // "My Relay Script" ``` #### bzBond.SyncConfig() To learn more about web viewer config see [bzBond-claris](../bzBond-claris/README.md#web-viewer-config) - `SyncConfig` returns the Web Viewer JSON config as a **promise** result. - `SetWebViewerConfigFromClaris` gets the current web viewer config state from Claris/FileMaker Pro and updates the config stored in bzBond-js. - `SetWebViewerConfig(webViewerConfig)` allows manual overwrite of the configuration stored in bzBond-js. - `GetConfig` returns the current configuration stored in bzBond-js. #### bzBond.RegisterScript(pluginOptions) It possible to extend bzBond-js by registering custom Claris/FileMaker scripts, which can then be can be called as methods. 1. Create a script in Claris/FileMaker Pro. 2. Perform `bzBond.RegisterScript` giving it the appropriate **pluginOptions**: - `exec`: the method that becomes available to use on the `bzBond` class. - `scriptName`: the Claris/FileMaker script that will be run when the method defined in `exec` is called. - `throwIf`: (optional) callback function that takes the result of the script defined in `scriptName` as a parameter. If the function returns `true` an error will be thrown. ``` // In this example, we create a Claris/FileMaker script called 'Execute Data Api', and associate that with the method 'executeDataApi' bzBond.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", }], }; bzBond.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 bzBond options bzBond.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 bzBond relay script will only reject when the specified Claris/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 Claris/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. ### Integrating JavaScript functions with Claris/FileMaker scripts bzBond-js works with bzBond-claris to allow Javascript functions defined in FileMaker scripts to run and return results in the regular FileMaker script flow. See the [bzBond-claris](../bzBond-claris/README.md#integrating-javascript-functions-with-filemaker-scripts) documentation for more details. **Errors** are captured and returned for the following scenarios: - function does not exist in JavaScript. - function defined as a string in Claris/FileMaker has invalid syntax (eg: `"(a, b,,, => a + b"`). - function executed in JavaScript throws an error. - bzBond does not exist in the web viewer (in this case, the PerformJavascript step itself will surface an error - this situation must be manually handled). ``` { "messages" : [ { "code" : "5", "message" : "The function 'MyGlobalFunc' is missing from the global scope, or is not a valid function definition" } ], "response" : {} } ``` ## Contributors Created by [Beezwax](https://www.beezwax.net/)