npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@novominteractive/ase-react-apollo

v2.0.0

Published

ASE React Apollo ===========================

Readme

ASE React Apollo

This is a library using Anyware Serverless Engine and Apollo Client to receive real-time data from an AWS IoT endpoint and merge that data into the Apollo Client's cache.

Licensed Work

This product requires a commercial license generated by Novom Interactive. This is not free software, this software is covered by copyright and to use you need a commercial license.

Please see LICENSE.md.

Peer Dependencies

| Package | Version | |---|---| | @apollo/client | ^4 | | @novominteractive/anyware-stateless-client | 2.0.0-alpha.12 | | react | >=18 |

Install

yarn add @novominteractive/ase-react-apollo

Setup

1. Create an ASE client

Instantiate a Client with the IoT endpoint and a root topic. The root topic is typically scoped per project and environment.

import { Client } from '@novominteractive/ase-react-apollo';

const aseClient = new Client({
  rootTopic: `${project}/${env}`,
  licenseKey: '<YOUR_LICENSE_KEY>',
});

2. Wrap your app with AseProvider

AseProvider must be a child of Apollo's ApolloProvider. Wrap them together so all child components have access to both the Apollo and ASE contexts.

import { ApolloClient, ApolloProvider, InMemoryCache } from '@apollo/client';
import { AseProvider } from '@novominteractive/ase-react-apollo';

const apolloClient = new ApolloClient({
  cache: new InMemoryCache(),
  uri: 'https://your-graphql-endpoint',
});

function App() {
  return (
    <ApolloProvider client={apolloClient}>
      <AseProvider client={aseClient}>
        <YourApp />
      </AseProvider>
    </ApolloProvider>
  );
}

3. Obtain an auth token and log in

The auth token must be generated server-side by an endpoint that signs a JWT using the secret key paired with your ASE license key. Never generate or store this token on the client. Retrieve it from your backend, then call login.

import { useAse } from '@novominteractive/ase-react-apollo';
import { useEffect } from 'react';

function AuthGate() {
  const { login, logout } = useAse();

  useEffect(() => {
    // Fetch a signed token from your backend — do not generate it on the client.
    fetch('/api/ase-token')
      .then((res) => res.json())
      .then(({ token }) => login(token));

    return () => { logout(); };
  }, [login, logout]);

  return null;
}

4. Subscribe to real-time data

Use useAseSubscription inside any child of AseProvider to execute a GraphQL query and keep it in sync with IoT messages.

const { data, loading } = useAseSubscription<MessagePayload, MyQueryType>(
  'my-topic',
  MY_QUERY,
  (previousData, newPayload) => ({
    ...previousData,
    messages: [...(previousData?.messages ?? []), newPayload],
  }),
);

API

Exports

| Export | Type | Description | |---|---|---| | Client | class | Re-exported from @novominteractive/anyware-stateless-client. Used to connect to the IoT endpoint. | | AseProvider | component | React provider that exposes the ASE context to its children. | | AseContext | context | The raw React context object for ASE. | | useAse | hook | Returns the ASE context: { client, loggedIn, login, logout }. | | useAseClient | hook | Returns the Client instance. Throws if the client is not defined. | | useAseMessages | hook | Subscribes to an IoT topic and calls a handler on each message. | | useAseSubscription | hook | Executes a GraphQL query and keeps its cache in sync with an IoT topic. |


AseProvider

Wraps your application (or a subtree) to provide the ASE context. Must be a parent of any component that calls useAse, useAseClient, useAseMessages, or useAseSubscription.

Props

| Prop | Type | Required | Description | |---|---|---|---| | client | Client \| undefined | Yes | The ASE client instance. | | children | ReactNode | Yes | Child components. |

import { AseProvider, Client } from '@novominteractive/ase-react-apollo';
import { useState, useEffect } from 'react';

function App() {
  const [aseClient, setAseClient] = useState<Client | undefined>();

  useEffect(() => {
    const client = new Client({
      connectionHandlers: {
        onDisconnect: () => console.info('Disconnect'),
        onError: (err: unknown) => console.error('err', err),
        onInterrupt: (err: unknown) => console.error('interrupt', err),
        onResume: (code: unknown, sessionPresent: unknown) => console.info(`Resume: ${code} ${sessionPresent}`),
      },
      iotConnect: {
        authorizerName: '<YOUR_CUSTOM_AUTHORIZER>',
      },
      licenseKey: '<YOUR_LICENSE_KEY>',
      rootTopic: '<YOUR_ROOT_TOPIC>',
    });
    setAseClient(client);
  }, []);

  return (
    <AseProvider client={aseClient}>
      {/* children have access to ASE context */}
    </AseProvider>
  );
}

useAse

Returns the ASE context.

const { client, loggedIn, login, logout } = useAse();

| Property | Type | Description | |---|---|---| | client | Client \| undefined | The ASE client instance. | | loggedIn | boolean | Whether the client is currently connected. | | login | (authToken: string) => Promise<void> | Connects the client to the IoT endpoint. The token must be generated server-side and signed with the secret key paired with your ASE license key. | | logout | () => Promise<void> | Disconnects the client from the IoT endpoint. |


useAseClient

Returns the Client instance from the context. Throws an error if no client is defined.

const client = useAseClient();

useAseMessages

Subscribes to an IoT topic and invokes a handler whenever a message is received. Automatically subscribes when the client is logged in and unsubscribes on cleanup.

useAseMessages<TPayload>(topic, handler, skip?)

| Parameter | Type | Default | Description | |---|---|---|---| | topic | string | — | The IoT topic to subscribe to. | | handler | (payload: TPayload) => any | — | Called with each incoming message payload. | | skip | boolean | false | When true, the subscription is skipped. |


useAseSubscription

Executes a GraphQL query and keeps the Apollo cache in sync with messages received on an IoT topic. The initial data comes from the network; subsequent updates are applied via the cacheMerger function when IoT messages arrive.

const result = useAseSubscription<TPayload, TData, TVariables>(
  topic,
  query,
  cacheMerger,
  queryOptions?,
);

| Parameter | Type | Description | |---|---|---| | topic | string | The IoT topic to subscribe to. | | query | DocumentNode \| TypedDocumentNode<TData, TVariables> | The GraphQL query to execute. | | cacheMerger | (previousData: TData \| null, newData: TPayload) => TData | Merges the current Apollo cache with the new IoT payload. | | queryOptions | QueryHookOptions<TData, TVariables> | Apollo useQuery options (e.g. variables, skip). |

Returns the same result object as Apollo's useQuery.

Example

import { useAse, useAseSubscription } from '@novominteractive/ase-react-apollo';
import { useEffect } from 'react';
import { MY_QUERY } from './queries';

function MyComponent() {
  const { login, logout } = useAse();

  useEffect(() => {
    login('your-auth-token');
    return () => { logout(); };
  }, [login, logout]);

  const { data, loading, error } = useAseSubscription<string, MyQueryType>(
    'my-topic',
    MY_QUERY,
    (previousData, newPayload) => ({
      ...previousData,
      items: [...(previousData?.items ?? []), newPayload],
    }),
  );

  if (loading) return <p>Loading…</p>;
  if (error) return <p>Error: {error.message}</p>;
  return <ul>{data?.items.map((item) => <li key={item}>{item}</li>)}</ul>;
}

Issue Reporting

If you are a customer and wish to report a bug or raise a new feature request, please send us an email at [email protected].