Skip to content

instantdb/eventsource

 
 

@instantdb/eventsource

Fork of eventsource that adds support for passing in a custom MessageEvent constructor. This is needed for environments like the Vercel Edge Runtime where MessageEvent is either missing or throws when constructed.

Installation

npm install --save @instantdb/eventsource

Supported engines

  • Node.js >= 20
  • Chrome >= 71
  • Safari >= 11.3
  • Firefox >= 65
  • Edge >= 79
  • Deno >= 1.30
  • Bun >= 1.1.23

Basically, any environment that supports:

If you need to support older runtimes, try the 2.x branch/version range (note: 2.x branch is primarily targetted at Node.js, not browsers).

Usage

import {EventSource} from 'eventsource'

const es = new EventSource('https://my-server.com/sse')

/*
 * This will listen for events with the field `event: notice`.
 */
es.addEventListener('notice', (event) => {
  console.log(event.data)
})

/*
 * This will listen for events with the field `event: update`.
 */
es.addEventListener('update', (event) => {
  console.log(event.data)
})

/*
 * The event "message" is a special case, as it will capture events _without_ an
 * event field, as well as events that have the specific type `event: message`.
 * It will not trigger on any other event type.
 */
es.addEventListener('message', (event) => {
  console.log(event.data)
})

/**
 * To explicitly close the connection, call the `close` method.
 * This will prevent any reconnection from happening.
 */
setTimeout(() => {
  es.close()
}, 10_000)

TypeScript

Make sure you have configured your TSConfig so it matches the environment you are targetting. If you are targetting browsers, this would be dom:

{
  "compilerOptions": {
    "lib": ["dom"],
  },
}

If you're using Node.js, ensure you have @types/node installed (and it is version 18 or higher). Cloudflare workers have @cloudflare/workers-types etc.

The following errors are caused by targetting an environment that does not have the necessary types available:

error TS2304: Cannot find name 'Event'.
error TS2304: Cannot find name 'EventTarget'.
error TS2304: Cannot find name 'MessageEvent'.

Migrating from v1 / v2

See MIGRATION.md for a detailed migration guide.

Extensions to the WhatWG/W3C API

Message and code properties on errors

The error event has a message and code property that can be used to get more information about the error. In the specification, the Event

es.addEventListener('error', (err) => {
  if (err.code === 401 || err.code === 403) {
    console.log('not authorized')
  }
})

Specify fetch implementation

The EventSource constructor accepts an optional fetch property in the second argument that can be used to specify the fetch implementation to use.

This can be useful in environments where the global fetch function is not available - but it can also be used to alter the request/response behaviour.

Setting HTTP request headers

const es = new EventSource('https://my-server.com/sse', {
  fetch: (input, init) =>
    fetch(input, {
      ...init,
      headers: {
        ...init.headers,
        Authorization: 'Bearer myToken',
      },
    }),
})

HTTP/HTTPS proxy

Use a package like undici to add proxy support, either through environment variables or explicit configuration.

// npm install undici --save
import {fetch, EnvHttpProxyAgent} from 'undici'

const proxyAgent = new EnvHttpProxyAgent()

const es = new EventSource('https://my-server.com/sse', {
  fetch: (input, init) => fetch(input, {...init, dispatcher: proxyAgent}),
})

Using HTTP2

Use a package like undici that supports HTTP2.

// npm install undici --save
import {Agent, fetch} from 'undici'

const http2Dispatcher = new Agent({allowH2: true})

const es = new EventSource('https://my-server.com/sse', {
  fetch: (url, init) => fetch(url, {...init, dispatcher: http2Dispatcher}),
})

Allow unauthorized HTTPS requests

Use a package like undici for more control of fetch options through the use of an Agent.

// npm install undici --save
import {fetch, Agent} from 'undici'

const unsafeAgent = new Agent({
  connect: {
    rejectUnauthorized: false,
  },
})

await fetch('https://my-server.com/sse', {
  dispatcher: unsafeAgent,
})

Feature checking

For library authors, you may want to feature-check if an EventSource implementation supports passing a custom fetch implementation (such as this library does). We declare (from v4.1.0 and onwards) a non-enumerable symbol on the EventSource class to indicate this, named eventsource.supports-fetch-override. It can be used downstream such as:

function yourLibrary(options) {
  const OurEventSource = options.polyfills.EventSource || globalThis.EventSource

  if (OurEventSource && Symbol.for('eventsource.supports-fetch-override') in OurEventSource) {
    // We can safely assume this supports overriding/specifying `fetch`!
    const es = new OurEventSource('https://some.url', {
      fetch: (input, init) =>
        fetch(input, {
          ...init,
          headers: {
            ...(init.headers || {}),
            'x-some-header': 'foo',
          },
        }),
    })
    // …
  }
}

Releasing

To publish a new version:

  1. Bump the version field in package.json and commit to main
  2. Go to Actions > Release in GitHub and click "Run workflow" on main

The workflow runs npm publish, publishing whatever version is in package.json.

Versioning

Versions follow the upstream eventsource package version with a prerelease suffix for our changes. For example, if upstream is at 4.1.0, our versions are 4.1.0-0, 4.1.0-1, 4.1.0-2, etc. Increment the number after the dash for each release. When syncing with a new upstream version, reset the suffix (e.g. 4.2.0-0).

Required setup

The repo must be linked to the @instantdb/eventsource npm package with GitHub Actions as a trusted publishing source (configured in the npm package settings). No secret tokens are needed — authentication is handled via GitHub's OIDC provider.

License

MIT-licensed. See LICENSE.

About

EventSource client for Node.js, browsers and other JavaScript runtimes

Resources

License

Code of conduct

Contributing

Security policy

Stars

Watchers

Forks

Packages

 
 
 

Contributors

Languages

  • TypeScript 99.1%
  • HTML 0.9%