What is a Listener?

Listeners are the core of the Flatfile Platform. All of your configurations, from data transformations, to custom styling, to data export are done in a Listener. They hold the logic backing your Flatfile Spaces, defining the functionality of your implementation.

Fundamentally, a Listener is a function that listens for Events and takes action when they occur. This means your configurations are implemented in response to events. To understand how to configure a Listener, it’s important to understand the anatomy of an Event.

An Event-Driven System

Flatfile is an event-driven system, meaning interactions with Flatfile (clicking a button, editing a record, uploading a file, etc) trigger the publication of an Event.

Each Event contains information about its source and execution context including a domain, topic, context, and optionally, a payload.

ComponentDescriptionExample
Domainthe jurisdiction of the eventrecord, sheet, workbook, space, file, job, agent
Topica combination of a domain and an actionworkbook:created workbook:updated workbook:deleted
Contextdetailed information about context of the event
{ spaceId: "us_sp_1234", fileId: "us_fl_1234", ... }
Payload (optional)detailed information about execution of the event
{ status: "complete", workbookId: "us_wb_1234", ... }

Anatomy of a Listener

A Listener is a function designed to receive Events as they occur and take action by executing a callback function. For example, when a file is uploaded, a Listener can extract its data to a target sheet, or when a record is created, a Listener can validate the data.

The callback function can be as simple as logging the event or as advanced as integrating with external systems. Here is an example that logs the topic of any incoming event:

export default function (listener) {
  listener.on("**", (event) => {
    console.log(`Received event: ${event.topic}`);
  });
}

This function is listening on ”**”, which is a wildcard that matches all events. For a complete list of events that can be listened to, see Event Topics.

Filtering

Listeners may be notified of every event on your Environment, but the Events that a Listener responds to are configurable. You can target which events your code responds to in a few ways.

One way is to use a filter. A filter is a string that matches the topic of an event. For example, the filter “commit:created” will match any event of that topic.

A simple way to filter events is to use the shorthand syntax listener.on:

listener.on("commit:created", { sheet: "contacts" }, async (event) => {
  // Custom action responding to the commit
});

This is equivalent to:

listener.filter({ sheet: "contacts" }).on("commit:created", async (event) => {
  // Custom action responding to the commit
});

For cases when you want to use multiple listeners under one filter, this syntax may be useful:

export default function flatfileEventListener(listener) {
  listener.filter({ sheet: "contacts" }, (configure) => {
    configure.on("commit:created", async (event) => {
      // Custom action responding to the commit
    })
  })
});

Namespaces

Namespaces are another way to organize Listener configurations and target specific Events. If you have two different workflows, for example, you can assign them to different namespaces to keep them separate.

To configure a listener to only act on events for a given namespace, simply use the listener.namespace method.

listener.namespace(['space:green'], (listener) => { ... })
listener.namespace(['space:red'], (listener) => { ... })

This will scope the listener to only respond to events that match the namespace.

Learn more about namespaces in the Namespaces guide.

Listener Types

Listeners can be hosted everywhere from your local machine to Flatfile’s secure cloud. The location of your listener determines the type of listener it is.

ListenerLocationDescription
developmentdeveloper machinelocal listener for development
client-sideuser machinebrowser embedded listener
AgentFlatfile secure cloudFlatfile hosted server-side listener
server-sideyour secure serverself-hosted server-side listener

Flatfile Listeners can be either client-side or server-side.

Client-side listeners run in the end user’s web browser and respond to user interactions. Client-side listeners are perfect for scenarios that need to tap into values available in the browser, such as the current user’s session or the current page URL.

Server-side listeners run where deployed, either on your own servers or on Flatfile’s secure cloud, and can perform more complex tasks like running intensive calculations or using secured credentials to integrate with external systems.

Server-side listeners can leverage packages that need the capabilities of a server environment.

Agent

In Flatfile, an Agent refers to a server-side listener bundled and deployed to Flatfile to be hosted in our secure cloud. You may deploy multiple Agents to a single Environment, each with its own configurations and codebase. But be careful, as multiple Agents can interfere with each other if not properly managed.

Managing Multiple Agents

With the capability to deploy multiple Agents within the same Environment, it is crucial to manage them carefully to avoid race conditions and conflicts. When multiple Agents are listening to the same event topics, they can interfere with each other, leading to unpredictable outcomes.

Strategies for Conflict Avoidance

  1. Event Filtering: Ensure each Agent is configured to listen for specific events or topics. Properly defining the scope of events an Agent should handle can prevent overlap and reduce the chance of race conditions.

  2. Use of Namespaces: Utilize namespaces to segment the operational scope of each Agent. This method ensures that Agents only respond to Events within their designated namespaces, effectively isolating their operations and minimizing conflict.

  3. Unique Topic Handling: Design Agents so that no two Agents act on the same event topic without coordination. Establish protocols for event handling that specify which Agent should handle particular events or topics.

Agent Configuration

When deploying an Agent, the CLI will automatically reduce the topic scope your Agent listens to by examining your listener code and registering itself to listen to only the topics your listener is configured to act on.

For example if your listener code only listens to commit:created events, the CLI will automatically configure the Agent to only listen to commit:created events. If your listener has a wildcard listener **, the CLI will configure the Agent to listen to all events.

Agent Deployment

To deploy an Agent, run the following command in your terminal from the root directory containing your entry file:

npx flatfile@latest deploy

Please note that the -s flag can be used to give your Agent a unique slug. This slug is useful when managing multiple Agents in the same Environment.

If no slug is provided and you already have a single Agent deployed, your Agent will be updated and given a slug of default.

If more than one Agent is deployed to the same environment and no slug is provided the CLI will prompt you to select which Agent you would like to update.

Please see Deploying to Flatfile for more information on deploying an Agent.

Agent Logs

When using Flatfile’s secure cloud to host your listener, you can view the executions of your Agent in the “Event Logs” tab of your dashboard. Note: If you are running your Agent locally using the develop command to test, these logs will not be recorded in your dashboard.

Event logs are useful in monitoring and troubleshooting your listener. Each execution of your agent is recorded here, including any custom console logs you have configured in your listener code.

Failures

Failures occur when an Agent fails to execute properly. That means either an uncaught error is thrown, or the execution times out.

If you are catching and handling errors within your code, those executions will not be marked as failures. If you would prefer to see them marked this way, re-throw your error after handling to bubble it up to the execution handler.

export default function (listener) {
  listener.on("**", (event) => {
    try {
      // do something
    } catch (error) {
      // handle error
      throw error; // re-throw error to mark execution as failure
    }
  });
}

Learn More

Learn more about the Flatfile Platform in our other concept guides: