Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@shopify/app-bridge-host

Package Overview
Dependencies
Maintainers
13
Versions
383
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@shopify/app-bridge-host

App Bridge Host contains components and middleware to be consumed by the app's host, as well as the host itself. The middleware and `Frame` component are responsible for facilitating communication between the client and host, and used to act on actions se

  • 1.11.1
  • Source
  • npm
  • Socket score

Version published
Maintainers
13
Created
Source

@shopify/app-bridge-host

App Bridge Host contains components and middleware to be consumed by the app's host, as well as the host itself. The middleware and Frame component are responsible for facilitating communication between the client and host, and used to act on actions sent from the App Bridge client. This package is used by Shopify's web admin.

License: MIT

App Bridge Host architecture

The App Bridge host uses a cross-platform, modular architecture. The host has several responsibilities. First, the host brokers communication between contexts (ie between the app and Shopify Admin). Second, the host maintains a central store representing the current state of all App Bridge features, which is exposed to the client app. Third, the host provides functionality to the client app.

Functionality is exposed to the client app via App Bridge actions. When an action is dispatched using App Bridge, the host evaluates the action against the relevant reducers, which make changes to the central store of app state. The state is then passed to UI components, which render functionality based on the state.

Features and UI components are treated separately in App Bridge. A feature consists of an action set and reducers, and the associated UI component consumes the resulting state. Most UI components have an associated feature, but this is not required.

The <HostProvider> is not responsible for rendering the client app, by Iframe or other means.

Building an App Bridge host

You can create your own App Bridge host using the <HostProvider> component.

<HostProvider> requires three types of data: app configuration, functionality to provide to the client app, and an initial state for the store.

App configuration

The <HostProvider> requires configuration information about the client app to be loaded:

const config = {
  apiKey: 'API key from Shopify Partner Dashboard',
  appId: 'app id from GraphQL',
  handle: 'my-app-handle',
  shopId: 'shop id from GraphQL',
  url: 'app url from Shopify Partner Dashboard',
  name: 'app name',
};

Note that we'll be referring to this sample config throughout the examples below.

Providing functionality

The <HostProvider> does not load any components by default. In order to provide a feature to an app, you must load the necessary component(s).

You can find pre-defined host UI components inside the @shopify/app-bridge-host/components directory. You can also write your own components.

Initial state

In App Bridge, features are gated using a permission model, which lives in the store. All feature permissions default to false. To provide a feature, you must also set the relevant permissions. If you don’t, the client app will not be permitted to use the feature, even if the component is available. Most components are associated with a single feature, but this is not a requirement.

The <HostProvider> accepts an initial state for the store. This allows a host to pre-populate the store with information the app can immediately access, such as feature permissions.

The setFeaturesAvailable utility can be used to build the initialState.features object. The following example shows a host with several components, and the corresponding feature availability set in initialState:

import {HostProvider} from '@shopify/app-bridge-host';
import {Loading} from '@shopify/app-bridge-host/components/Loading';
import {Modal} from '@shopify/app-bridge-host/components/Modal';
import {Navigation} from '@shopify/app-bridge-host/components/Navigation';

import {Group} from '@shopify/app-bridge/actions';
import {setFeaturesAvailable} from '@shopify/app-bridge-host/store';

const initialState = {
  features: setFeaturesAvailable(Group.Loading, Group.Modal, Group.Navigation),
};

function Host() {
  return (
    <HostProvider
      config={config}
      components={[Loading, Modal, Navigation]}
      initialState={initialState}
    />
  );
}

Custom components

HostProvider can render any type of React component; it’s not limited to the components in this package.

To connect a component to the App Bridge host, wrap it using the withFeature decorator. This decorator provides the component with access to the store and actions for a specified App Bridge feature (remember to set the corresponding feature permissions in initialState).

Here is an example of creating a custom component that utilizes the App Bridge Toast feature, rendering the Toast component from Polaris.

import {HostProvider, ComponentProps, withFeature} from '@shopify/app-bridge-host';
import {feature as toastFeature, WithFeature} from '@shopify/app-bridge-host/store/reducers/embeddedApp/toast';
import {Toast} from '@shopify/polaris';
import compose from '@shopify/react-compose';

function CustomToastComponent(props: WithFeature) {
  const {
    actions,
    store: {content},
  } = props;

  if (!content) {
    return null;
  }

  const {duration, error, id, message} = content;
  return (
    <Toast
      error={error}
      duration={duration}
      onDismiss={() => actions.clear({id: id})}
      content={message}
    />
  );
}

const Toast = compose<ComponentProps>(withFeature(toastFeature))(CustomToastComponent);

function Host() {
  return <HostProvider config={config} components={[Toast]} />;
}

Asynchronous components

You can load host components asynchronously, ie using @shopify/react-async. The <HostProvider> handles adding the feature's reducer to the Redux store. Actions that are dispatched by the app before the feature is available is automatically queued and resolved once the feature's component is loaded.

import {createAsyncComponent, DeferTiming} from '@shopify/react-async';
import {HostProvider} from '@shopify/app-bridge-host';

const Loading = createAsyncComponent<ComponentProps>({
  load: () =>
    import(
      /* webpackChunkName: 'AppBridgeLoading' */ '@shopify/app-bridge-host/components/Loading'
    ),
  defer: DeferTiming.Idle,
  displayName: 'AppBridgeLoading',
});

function Host() {
  return <HostProvider config={config} components={[Loading]} router={router} />;
}

Rendering the client app, with navigation

Since <HostProvider> is not responsible for rendering the client app, one of the components must handle this task. The Apps section in Shopify Admin uses the MainFrame component, which additionally requires a router context to provide navigation to the client app.

If you want to provide navigation capabilities to your app, you will need to include the Navigation component and provide a router to the <HostProvider>. The router should keep the app’s current location in sync with the host page’s current location, and manage updating the location when the route changes.

The following example shows a simple router being passed into <HostProvider>, along with the MainFrame and Navigation components:

import {HostProvider} from '@shopify/app-bridge-host';
import {MainFrame} from '@shopify/app-bridge-host/components/MainFrame';
import {Navigation} from '@shopify/app-bridge-host/components/Navigation';

const router = {
  location: {
    pathname: window.location.pathname,
    search: window.location.search,
  },
  history: {
    push(path: string) {
      window.history.pushState('', null, path);
    },
    replace(path: string) {
      window.history.replaceState('', null, path);
    },
  },
};

const initialState = {
  features: setFeaturesAvailable(Group.Navigation),
};


function Host() {
  return (
    <HostProvider
      config={config}
      components={[MainFrame, Navigation]}
      initialState={initialState}
      router={router}
    />
  );
}

Note that since MainFrame only renders the app itself and does not provide features to the app, there is no related initialState. Navigation, however, provides a feature to the app. To allow the app to use that feature, it is made made available in initialState.

FAQs

Package last updated on 27 Nov 2019

Did you know?

Socket

Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.

Install

Related posts

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc