> For the complete documentation index, see [llms.txt](https://ferp.mrbarry.com/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://ferp.mrbarry.com/advanced-usage/third-party-libraries-and-objects.md).

# Third-Party Libraries and Objects

## Handling Uncontrolled Third Party Objects

Not everything in the world is functional and immutable, and occasionally your application needs to manage these things. Ferp provides effects and subscriptions for handling these types of systems, but it's not always obvious which one to use and how to implement it.

### Rebuild objects by storing builder values

In the example of firebase, you may have a document reference that is constructed by:

```javascript
firebase.database(app).ref().collection('foo').document('bar')
```

While you could store the firebase ref object in state, having a serializable

{% code title="effects/firebase.js" %}

```javascript
export const firebaseReadFx = (path, afterReadAction) => effects.defer((resolve) => {
  firebase.database(app).ref(path).snapshot((value) => {
    resolve(effects.act(afterReadAction, value));
  });
});

// usage: firebaseReadFx('foo/bar', actionThatAcceptsValue)
```

{% endcode %}

### Event-driven objects

If you have objects like websockets, those are perfect for subscriptions. Here's how I would set it up:

```javascript
import { app, effects } from 'ferp';

const INITIAL_STATE = {
  websocket_url: 'wss://echo.websocket.org',
  websocket: null,
  messages: [],
};

const WebsocketSendFx = (data, websocket) => effects.thunk(() => {
  if (websocket) websocket.send(data);
  
  return effects.none();
});

const WebsocketSend = data => state => [
  state,
  WebsocketSendFx(data, state.websocket),
];

const OnConnected = (websocket) => (state) => [
  { ...state, websocket },
  effects.act(WebsocketSend, 'hello, world'),
];

const OnDisconnected = (state) => [
  { ...state, websocket: null },
  effects.none(),
];

const OnMessage = (message) => (state) => [
  { ...state, messages: state.messages.concat(message) },
  effects.none(),
};

const WebsocketSubscription = (dispatch, websocketUrl, ConnectAction, DisconnectAction, MessageAction) => {
  const websocket = new WebSocket(websocketUrl);
  
  const onOpen = () => dispatch(ConnectAction(websocket));
  const onClose = () => dispatch(Disconnect);
  const onMessage = ({ data }) => dispatch(MessageAction(data));
  
  websocket.addEventListener('open', onOpen);
  websocket.addEventListener('close', onClose);
  websocket.addEventListener('message', onMessage);
  
  return () => {
    websocket.removeEventListener('open', onOpen);
    websocket.removeEventListener('close', onClose);
    websocket.removeEventListener('message', onMessage);
  
    websocket.close();
  };
};

const dispatch = app({
  init: [INITIAL_STATE, effects.none()],
  subscribe: state => [
    state.websocketUrl && [
      WebsocketSubscription,
      state.websocketUrl,
      OnConnect,
      OnDisconnect,
      OnMessage,
    ],
  ],
});
```


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://ferp.mrbarry.com/advanced-usage/third-party-libraries-and-objects.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
