Editor Integration

In this section you will learn how to embed the Fusebit Editor into your frontend web application.

For a detailed reference of the Fusebit Editor API, refer to the Editor API Reference.

Example Code

<div id="editor" style="width:800px;height:500px;"></div>

<script
  src="https://cdn.fusebit.io/fusebit/js/fusebit-editor/latest/fusebit-editor.min.js"
  type="text/javascript"
></script>

<script type="text/javascript">
  // Load existing function or create one from template
  fusebit
    .createEditor(
      document.getElementById('editor'),
      '{boundaryId}',
      '{functionId}',
      {
        accountId: '{accountId}',
        subscriptionId: '{subscriptionId}',
        baseUrl: 'https://api.{region}.fusebit.io',
        accessToken: '{accessToken}',
      },
      {
        template: {}, // IFunctionSpecification - function template if one does not exist yet
        editor: {}, // IEditorOptions - control editor presentation and behavior
      }
    )
    .then((editorContext) => {
      // EditorContext
      // ... subscribe to events etc.
    })
    .catch((err) => {
      // ... display any errors
      alert(err);
    });
</script>

Conceptual Overview

The Fusebit Editor is a Javascript library that you can use to generate a UI component for editing a single Fusebit function. The Fusebit Editor communicates directly with the Fusebit HTTP API, allowing you to offer an authoring experience for Fusebit functions in your frontend application with a minimal amount of code.

Generally you will initialize the Fusebit Editor using the createEditor method. You must specify the HTML element within which to create the editor, the function and boundary names, and the account details to use when communicating with the Fusebit HTTP API.

You can specify the account details as a static Javascript object that implements the IAccount interface or you can dynamically resolve the account details by providing an AccountResolver callback function. Use the IAccount interface in cases when the access token is known ahead of time and does not need to be refreshed during the session. Use an AccountResolver instance if you want to periodically refresh the access token and you want the editor to call back to the hosting application before every call to the Fusebit HTTP API.

By default, if the function identified by the boundary and function names does not exist yet, createEditor will fail. You can optionally specify the template property on the ICreateEditorOptions object to provide a template that will be used to create a function if one does not already exist. This allows you to implement load-or-create semantics. You can also customize many aspects of the editor's presentation or behavior using the editor property of the ICreateEditorOptions object. For more details on configuring the editor, see below.

On success, createEditor will return a promise that resolves to an EditorContext instance. This allows you to subscribe to a variety of interesting Events and perform simple operations on the editor.

📘

Only a single instance of the editor on a given page is currently supported.

Including the Fusebit Library

The Fusebit library containing the editor is hosted on the CDN at the following location:

https://cdn.fusebit.io/fusebit/js/fusebit-editor/{major}/fusebit-editor.min.js
https://cdn.fusebit.io/fusebit/js/fusebit-editor/{major}/{minor}/fusebit-editor.min.js
https://cdn.fusebit.io/fusebit/js/fusebit-editor/{major}/{minor}/{patch}/fusebit-editor.min.js
https://cdn.fusebit.io/fusebit/js/fusebit-editor/latest/fusebit-editor.min.js

The library uses semver versioning, and you can decide what level of changes in the editor you want to receive automatically vs which you want to opt-in to. For example, using

https://cdn.fusebit.io/fusebit/js/fusebit-editor/1/0/fusebit-editor.min.js

will allow your application pick up all latest patch releases to version 1.0.x of the library, while using

https://cdn.fusebit.io/fusebit/js/fusebit-editor/1/fusebit-editor.min.js

will pin only the major version of the library and therefore allow your application to pick up all new non-breaking minor features and changes in the editor.

The URL with the latest path segment will always point to the latest patch version available.

Accessing the Fusebit HTTP API

When you were on-boarded to the Fusebit platform, you should have been provided with a URL to the HTTP API instance running in the AWS region of your choice. Usually this will be the same region where your own application is hosted in AWS. In our documentation, we use https://api.{region}.fusebit.io as a stand-in for the HTTP API base URL, but you will need to replace it with the instance you are provided during onboarding, for example <https://api.us-east-1.fusebit.io >.

Authorization

The Fusebit Editor communicates directly with the Fusebit HTTP API to manage Fusebit functions. All calls to the Fusebit HTTP API must be authorized using an access token. Mechanisms to obtain a valid access token are documented in the authorization model section.

There are two ways of providing an access token to the Fusebit Editor.

Static Access Token

The Access token, along with accountId, subcriptionId and the baseUrl of the Fusebit HTTP API can be directly provided to the Fusebit Editor using the IAccount interface when calling the createEditor method:

fusebit
  .createEditor(document.getElementById('editor'), '{boundaryId}', '{functionId}', {
    accountId: '{accountId}',
    subscriptionId: '{subscriptionId}',
    baseUrl: 'https://api.{region}.fusebit.io',
    accessToken: '{accessToken}',
  })
  .then((editorContext) => {
    // ...
  });

The editor will use this access token for the duration of its lifetime. Since access tokens typically have expiry times associated with them, this mechanism is suitable only if the expected duration of the user's session with the editor does not exceed the expiry time.

Dynamic Access Token

An alternative to the static access token method, is to provide an AccountResolver callback function to resolve the token. The Fusebit Editor will invoke this callback function before every call it makes to the Fusebit HTTP API. Since refreshing access tokens typically involves making HTTP API calls, it is important that the implementation of the callback supports in-memory caching of the access token for a duration adequate to its expiry time. A simplistic implementation might look like this:

let accountResolver = (currentAccount) => {
  if (currentAccount && currentAccount.validUntil > Date.now()) {
    // access token is still valid - return immediately
    return Promise.resolve(currentAccount);
  }
  // refreshAccessToken is an application-specific way of obtaining the access token
  return refreshAccessToken().then((newAccessToken) => {
    return {
      accountId: '{accountId}',
      subscriptionId: '{subscriptionId}',
      baseUrl: 'https://api.{region}.fusebit.io',
      accessToken: newAccessToken,
      validUntil: Date.now() + 60 * 60 * 1000, // valid for 1h
    };
  });
};

fusebit
  .createEditor(document.getElementById('editor'), '{boundaryId}', '{functionId}', accountResolver)
  .then((editorContext) => {
    // ...
  });

The dynamic access token method, while more involved, is also more robust than the static method. It allows the user to continue an uninterrupted session with the Fusebit Editor even if the access token expires and needs to be refreshed.

Configuring the Editor

The Fusebit editor is highly configurable. The template property of the ICreateEditorOptions object, which is passed to createEditor, lets you specify a template for the function that the editor will create if the function does not exist already. That property is of type IFunctionSpecification, and contains the following settings:

{
  nodejs: { // Specify the files that comprise the function
    files: {
      'index.js': 'module.exports = (ctx, cb) => cb(null, { body: "hello" });',
      'package.json': { dependencies: { async: '*' }},
    }
  },
  configuration: { // Specify any Application Settings you want the editor to use
    'MY_API_KEY': 'abc!123'
  },
  schedule: { // Configure scheduled execution
    cron: '0 0 * * *',
    timezone: 'US/Pacific'
  },
  metadata: { // Specify arbitrary metadata for the function, stored server-side
    fusebit: { // Store metadata settings used by the Fusebit editor
      runner : 'ctx => Superagent.get(ctx.url);',
    }
  }
}

The editor property of the ICreateEditorOptions object lets you configure the editor layout itself. The editor property is of type IEditorOptions, and contains the following settings:

{
  theme: 'light', // Use light/dark built-in visual themes or custom themes
  actionPanel: { // Configure the left-hand action panel
    enableCodeOnlyToggle: true, // Display distraction-free coding toggle button
    enableFullScreen: true, // Display full-screen button
  },
  logsPanel: { // Configure the bottom logs panel
    maxSize: 10 * 1024, // Maximum number of characters that the logs panel shows
  },
  navigationPanel: { // Configure the left-hand navigation panel
    hideCode: false, // Hide list of code files from the panel
    hideFiles: [ 'middleware.js' ], // Hide select code files from the panel
    hideConfigurationSettings: false, // Hide Application Settings from the panel
    hideScheduleSettings: false, // Hide Scheduler Settings from the panel
    hideRunnerTool: false // Hide Runner Settings from the panel
  },
  editorPanel: {}, // Currently unused
  statusPanel: {}, // Currently unused
}

Styling the Editor

As mentioned in the previous section, the theme property of IEditorOptions allows the user to select between the built-in light and dark themes.

In certain cases, you may want to further customize the editor styling for a better fit with the rest of your application. To create a custom theme, you can use the built-in themes as a starting point, and modify them to your needs. You can find the theme CSS stylesheets for each version of the editor at the same CDN location where the editor is hosted, for example:

https://cdn.fusebit.io/fusebit/js/fusebit-editor/1/4/0/fusebit-light.css
https://cdn.fusebit.io/fusebit/js/fusebit-editor/1/4/0/fusebit-dark.css

To instantiate the editor with a custom theme:

  1. Create your own stylesheet based on the built-in themes, and make sure each rule selector starts with .fusebit-theme-foo, assuming foo is the name of your custom theme
  2. Reference your stylesheet in the page where you are hosting the editor, either using an inline <style> block or by linking to it using a <link rel="stylesheet" type="text/css" href="fusebit-foo.css"> tag
  3. When instantiating the editor set the theme property of IEditorOptions to your theme name, or foo in the above example.

📘

When using custom themes, we recommend you pin the editor down to the patch version as described here. This ensures your application loads the exact version of the editor that you customized in your theme. Failing to do so may result in your application loading newer versions of the editor, which are not appropriately styled by your custom theme.

Handling Editor Dirty State

In certain scenarios, the hosting application may need to know whether the user has any unsaved changes in the editor. This is common if you are implementing functionality to close the editor or navigate away from it.

To detect unsaved changes (editor is in a "dirty state"), simply listen for
DirtyStateChangedEvent as shown in the following snippet:

fusebit.createEditor(document.getElementById('editor'), '{boundaryId}', '{functionId}', {
  // ...
}).then(editorContext => {
  editorContext.on('dirty-state:changed', (event) => {
    if(event.newState){
      // Editor has unsaved changes
    } else {
      // All changes have been saved
    }
});