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 🙏

© 2024 – Pkg Stats / Ryan Hefner

@stack-spot/portal-extension

v0.3.0

Published

A Stackspot extension is an independent application that runs inside the Stackspot Portal (EDP). This application runs in a separate environment and doesn't have access to the portal itself, but it can interact with many Stackspot APIs, show toasters and

Downloads

240

Readme

Stackspot extension

A Stackspot extension is an independent application that runs inside the Stackspot Portal (EDP). This application runs in a separate environment and doesn't have access to the portal itself, but it can interact with many Stackspot APIs, show toasters and open modals through this SDK.

This SDK is responsible for communicating with the Stackspot Portal through messages. This message exchange is invisible to the developer, who can just call the method in the SDK and expect all the action to just happen!

What this the SDK do?

  • It allows the control of modals and toasters, including alerts, confirmation dialogs and floating side panels.
  • It allows access to most of the Stackspot API (backend) through simple methods.
  • Provides peer dependencies that sets up the frontend project to look just as part of the Stackspot portal as any native page.

What doesn't it do?

  • It does not provide a boilerplate for starting up the project.
  • It does not change any menu item of the parent portal.
  • It doesn't tell where the extension goes in the portal.
  • It doesn't provide a navigation system.

What can I do with extensions:

  • Create a new page that can be accessed through a new menu and/or URL. The menu is setup in the Account portal.
  • Create widgets to show in dashboards of workspaces.
  • Interact with any Stackspot API, as longs as the user logged in has access to it.

Required libraries for the extension:

  • React.
  • Citric: design system.
  • Portal theme: theme for the design system.
  • Portal translate: internationalization mechanism.
  • React Query: global network state manager.
  • Styled components: helps styling our components.

Although all these dependencies are required to exist in the extension project, you are not required to use Portal translate, React Query or Styled components if you don't want to.

Recommended libraries:

  • Citron navigator: if your extension has multiple pages, it is a good idea to handle navigation with the Citron Navigator, an in-house developed navigator for React.
  • Portal components: a set of components used by every Stackspot portal built o top of Citric. Use it only if you need some of the components of this library.

Installation

pnpm add @stack-spot/portal-extension

We recommend using pnpm, but you can also use npm or yarn.

Exposing the project as an extension:

In your entrypoint file (e.g. App.tsx):

import { StackspotExtension } from '@stack-spot/portal-extension'

export const App = () => (
  <StackspotExtension>
    {/* Your content goes here */}
  </StackspotExtension>
)

Showing modal content

import { StackspotExtension } from '@stack-spot/portal-extension'
import { Button } from '@citric/core'
import { alert, confirm, showModal, showRightPanel } from '@stack-spot/portal-extension'
export const App = () => (
  <StackspotExtension>
    <Button
      onClick={() => alert({
        title: 'Alert',
        subtitle: 'This is an alert!',
      })}
    >
      Show alert
    </Button>
    <Button
      onClick={async () => {
        const answer = await confirm({
          title: 'Confirm',
          subtitle: 'Do you confirm?',
        })
        console.log(answer ? 'confirmed' : 'canceled')
      }}
    >
      Show confirm
    </Button>
    <Button
      onClick={() => showModal({
        title: 'My modal',
        subtitle: 'This is an example of modal',
        path: '/path-to-modal',
      })}
    >
      Show modal
    </Button>
    <Button
      onClick={() => showRightPanel({
        title: 'Meu painel',
        subtitle: 'This is an example of right panel',
        path: '/path-to-right-panel',
      })}
    >
      Show floating side panel on the right
    </Button>
  </StackspotExtension>
)

Notice that modals and right panels load other views of this same application. In order to have multiple views, we suggest using a React Navigator (Citron Navigator is our recommendation).

Showing toasters

import { StackspotExtension } from '@stack-spot/portal-extension'
import { Button } from '@citric/core'
import { showToaster } from '@stack-spot/portal-extension'

export const App = () => (
  <StackspotExtension>
    <Button onClick={() => showToaster({ message: 'Hello World' })}>
      Show an info toast
    </Button>
    <Button onClick={() => showToaster({ message: 'Oops! An error.', type: 'error' })}>
      Show an error toast
    </Button>
  </StackspotExtension>
)

Performing network requests to the Stackspot API

As an extension of the portal, you don't have access to the user's access token and cannot make direct requests to the Stackspot API. Instead, you must import a network client of the SDK and use it instead. Let's see an example of how to list all studio's name for the user currently logged in:

import { StackspotExtension } from '@stack-spot/portal-extension'
import { Button, Text } from '@citric/core'
import { showToaster, contentClient } from '@stack-spot/portal-extension'

export const App = () => {
  const [studios, isLoading, error] = contentClient.studios.useStatefulQuery({})
  return (
    <StackspotExtension>
      <h1>Widget</h1>
      {isLoading && <Text>Loading...</Text>}
      {error && <Text>{`${error}`}</Text>}
      {studios && <ul>{studios.map(s => <li key={s.id}>{s.name}</li>)}</ul>}
    </div>
    </StackspotExtension>
  )
}

Above, we're using React Query to manage our request state. This is recommended, but if you want to use something else, you can always make the query yourself:

import { StackspotExtension } from '@stack-spot/portal-extension'
import { Button, Text } from '@citric/core'
import { showToaster, contentClient } from '@stack-spot/portal-extension'

export const App = () => {
  const [data, setData] = useState<any[]>() // any is not ideal here, this is just an example
  const [isLoading, setLoading] = useState(true)
  const [error, setError] = useState('')

  useEffect(() => {
    (async () => {
      setLoading(true)
      try {
        const result = await contentClient.studios.query({})
        setData(result)
      } catch (e: any) {
        setError(e.message || `${e}`) 
      }
      setLoading(false)
    })()
  }, [])
  const [studios, isLoading, error] = contentClient.studios.useStatefulQuery({})
  return (
    <StackspotExtension>
      <h1>Widget</h1>
      {isLoading && <Text>Loading...</Text>}
      {error && <Text>{`${error}`}</Text>}
      {studios && <ul>{studios.map(s => <li key={s.id}>{s.name}</li>)}</ul>}
    </div>
    </StackspotExtension>
  )
}

It is much harder to control the request state yourself, but it can be done. In general, prefer to use React Query hooks and use query, directly, only if outside a React component.

Network clients

The SDK exposes the following network clients:

  • accountClient
  • agentClient
  • aiClient
  • cloudAccountClient
  • cloudPlatformClient
  • cloudPlatformHorizonClient
  • cloudRuntimesClient
  • cloudServicesClient
  • contentClient
  • eventBusClient
  • insightsClient
  • notificationClient
  • runtimeManagerClient
  • secretsClient
  • workflowClient
  • workspaceClient
  • workspaceManagerClient
  • workspaceSearchClient

Each client exposes access to a Stackspot API. The documentation of each one is still in progress, but you can use the Typescript auto complete to check the code documentation and methods of each client. If necessary, you can install "@stack-spot/portal-network" as a dev dependency to use its types.

The methods in a client can be either queries or mutations. Queries fetch data from the backend, without any side-effect, while mutations can change data in the backend. A query will have the functions: query, useQuery (uses React Suspense), useStatefulQuery (doesn't use React Suspense), isAllowed (checks if the method is allowed for the user), useAllowed and invalidate (invalidates any cached data for that query). Mutations are similar, but they can't be invalidated and, instead of query, useQuery and useStatefulQuery, we have mutate and useMutation.

For more documentation on the hooks useQuery and useMutation, we refer to the React Query's documentation.

Sample project

In order to quick start an extension project, we have a repository with boilerplate code that can be copied:

https://github.com/Tiagoperes/stackspot-extension-sample