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

@gabrielmorais-dev-id/web-sdk

v0.1.8

Published

Oreus Web SDK: framework-agnostic Web Components backed by the Oreus HTTP facade.

Downloads

1,543

Readme

@oreus/web-sdk

Install (temporary)

npm i @gabrielmorais-dev-id/web-sdk@latest 

Quick start

import { registerOreusComponents } from "@oreus/web-sdk";
import "@oreus/web-sdk/styles.css";
registerOreusComponents();
<oreus-provider
  issuer="https://sso.example.com/oidc"
  client-id="your-app-id"
  api-base-url="https://api.example.com"
  resource="https://api.example.com"
  redirect-uri="https://your-app.example.com/oauth/callback"
  scopes="read:vox write:vox"
>
  <oreus-auth></oreus-auth>
  <oreus-vox-chat></oreus-vox-chat>
</oreus-provider>

Every other component must be a descendant of <oreus-provider>: the provider owns the session, the API client and the state, and hands them to its children.

Provider configuration

| Attribute | Required | Description | | ---------------- | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | issuer | yes | OIDC issuer of your Oreus tenant (usually ends with/oidc). | | client-id | yes | Id of your third-party application. | | api-base-url | yes | Origin of the Oreus HTTP facade. Read once, before the runtime starts, and immutable afterwards, so production, staging and local use the same artifact with a different value. | | resource | yes | OAuth resource identifier of the API. | | redirect-uri | yes | Must match a redirect URI registered for your application exactly. | | scopes | yes | Space-separated scopes to request. SeeScopes. | | locale | no | en or fr. See Localization. | | theme | no | light (default) or dark. |

Changing issuer, client-id, api-base-url, resource, redirect-uri or scopes after mount reconfigures the provider.

Authentication

<oreus-auth> renders the sign-in / sign-out control. The SDK signs the user in with OIDC (authorization code + PKCE) against issuer, then obtains an organization token for the active organization. All API calls use that token. The active organization is the one the user authorized on the Logto consent screen; the SDK shows no organization picker.

Besides the scopes you list in scopes, the provider always requests openid profile email offline_access urn:logto:scope:organizations.

No scope is needed to sign in. Without any of the read:* / write:* scopes below the user can sign in, but there is nothing to show.

Identity provider setup: register your application with the redirect URI used in redirect-uri. After sign-out the user returns to the current page URL (without query or hash).

Scopes

How scopes work

  1. You request scopes with the scopes attribute.
  2. The SDK reads the scopes that the organization token actually grants, from its scope claim. Requesting a scope the organization does not grant does not enable it.
  3. Each component checks those effective scopes.

A missing scope hides a feature, it never blocks the app.

  • A component whose main read scope is missing renders a "forbidden" state in place of its content. The rest of the page keeps working.
  • A missing write or delete scope removes only the related action: the menu entry, button or drop zone is not rendered.
  • Optional capabilities degrade quietly. For example, without read:sessions the chat input has no @ session mentions and no history, but it still sends messages.

Request only what the screens you use need.

Scope reference by component

| Component | Needs | Without it | | -------------------------------- | ----------------------------------------------------------------- | ------------------------------------- | | oreus-auth | none (sign-in scopes only) | n/a | | oreus-vox-chat | write:vox to send messages (write:voxies in a voxie chat) | "Forbidden" state, chat is not usable | | oreus-chat-history | read:sessions | "Forbidden" state | | oreus-agent-library | read:stores | "Forbidden" state | | oreus-voxie-list | read:voxies | "Forbidden" state | | oreus-describe-voxie | write:voxies | "Forbidden" state | | oreus-collections | read:folders | "Forbidden" state | | oreus-files-table | read:files | "Forbidden" state | | oreus-or-organization-card | read:orbs | "Forbidden" state | | oreus-or-usage-alert | read:orbs | Renders nothing |

Sub-scopes (features inside a component)

| Scope | Feature it enables | Where | | ---------------------- | --------------------------------------------------------------- | ---------------------------------------------------------------- | | read:vox | Vox data (conversation context) | oreus-vox-chat | | read:sessions | Past conversations,@ session mentions, saving chats | oreus-vox-chat, oreus-chat-history | | write:sessions | Rename conversations; save a conversation that is not temporary | oreus-chat-history, oreus-vox-chat | | read:voxies | Load the selected voxie into the chat | oreus-vox-chat | | write:voxies | Create a voxie, edit it, start a chat from a voxie card | oreus-voxie-list, oreus-describe-voxie | | delete:voxies | Delete a voxie | oreus-voxie-list | | read:agents | Agents in the@ mention menu and agent details | oreus-vox-chat, oreus-agent-library | | write:stores | Publish / manage store items from the agent details dialog | oreus-agent-library | | read:reviews | See agent reviews | oreus-agent-library | | write:reviews | Write a review | oreus-agent-library | | write:attachments | Attach files from the computer in the chat input | oreus-vox-chat | | read:folders | Attach from collections; folder lists and the move dialog | oreus-vox-chat, oreus-collections, oreus-files-table | | write:folders | Rename a collection | oreus-collections | | delete:folders | Delete a collection | oreus-collections | | read:files | Open and preview files | oreus-files-table, oreus-vox-chat | | write:files | Upload (button and drop zone), rename, move | oreus-files-table | | delete:files | Delete a file | oreus-files-table | | read:organizations | Active organization type: the Business Drive shows only when the active organization is PROFESSIONAL | oreus-vox-chat |

Components

Eleven elements are public; every other oreus-* element is internal and may change without notice. Each public element comes with all its features (dialogs, menus, uploads, empty and error states).

Attributes are written in kebab-case in HTML. Components in the same <oreus-provider> share state: selecting a conversation in oreus-chat-history opens it in the oreus-vox-chat of the same provider, wherever it is on the page.

oreus-provider

Session, API client and state for every component below it. Attributes: see Provider configuration. Emits no event.

oreus-auth

Sign-in / sign-out button. No attribute, no event.

oreus-vox-chat

The chat. Vox and Voxie conversations share this one element.

| Attribute | Type | Default | Description | | ------------------------ | ------- | --------- | ---------------------------------------------------------------- | | session-id | string | none | Conversation to open, for example restored from your URL. | | voxie-id | string | none | Voxie to chat with, for example restored from your URL. |

| Event | detail | Fired when | | --------------------- | --------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | oreus-chat-change | { sessionId?: string \| null, voxieId?: string } | The open conversation changes from inside the chat (a new conversation is created, a voxie is picked, …). Not fired when you changesession-id / voxie-id yourself. |

oreus-chat-history

List of past conversations, with search, rename and "New chat". No attribute.

| Event | detail | Fired when | What the SDK already does | | ------------------------ | ------------------------------------------------------------------- | ------------------------- | ----------------------------------------- | | oreus-new-chat | none | "New chat" is clicked | Resets the chat of the same provider | | oreus-session-select | SessionSummary: { id, name?, updatedAt?, voxie?, voxieId? } | A conversation is clicked | Opens it in the chat of the same provider |

oreus-agent-library

Agent store: Discover, Most popular and My agents, with "See all" pages and an agent details dialog.

| Attribute | Type | Default | Description | | ------------ | ------ | ------- | ------------------------------------------------------------------------------- | | sections | string | all | Comma-separated sections to show:discover, most_popular, my_agents. |

| Event | detail | Fired when | What the SDK already does | | ----------------- | ---------------------------------------------------------- | ---------------------------------------- | ------------------------------ | | oreus-select | { storeItemId: string, item: StoreItem } | An agent card is clicked | Opens the agent details dialog | | oreus-see-all | { section: "discover" \| "most_popular" \| "my_agents" } | "See all" of a section is clicked | Expands that section | | oreus-back | none | "Back" is clicked in an expanded section | Returns to the overview |

oreus-voxie-list

List of voxies with edit and delete. No attribute.

| Event | detail | Fired when | What the SDK already does | | ---------------- | -------------------------------------------- | ----------------------- | -------------------------------------------------------------------------- | | oreus-select | { voxieId: string, voxie: VoxieSummary } | A voxie card is clicked | Withwrite:voxies, switches the chat of the same provider to that voxie |

oreus-describe-voxie

Prompt box that generates a new voxie from a description, then opens the voxie editor. No attribute, no event.

oreus-collections

Collections (folders) with rename and delete.

| Attribute | Type | Default | Description | | ------------- | ------ | ------- | --------------------- | | page-size | number | 12 | Collections per page. |

| Event | detail | Fired when | What the SDK already does | | ---------------- | -------------------------------------- | ----------------------- | -------------------------------------------------- | | oreus-select | { folderId: string, name: string } | A collection is clicked | Nothing. Show its files withoreus-files-table. |

oreus-files-table

Files of one folder, with upload button, drop zone, upload progress, preview, rename, move and delete. Emits no event.

| Attribute | Type | Default | Description | | ------------- | ------ | -------- | ------------------------------------------------------------------------------ | | folder-id | string | required | Folder to list, usually thefolderId of an oreus-collections selection. |

oreus-or-organization-card

OR balance and usage of the active organization. No attribute, no event.

oreus-or-usage-alert

Alert for low (10% or less left) or used-up included OR, with the time until reset once they run out. Renders nothing while the balance is fine. oreus-vox-chat already shows it above its input. Emits no event.

| Attribute | Type | Default | Description | | --------- | ------------------------------------- | -------- | ------------------------------------------------------------------------ | | variant | "auto" | "warning" | "depleted" | "auto" | auto follows the balance; warning or depleted always shows that alert. |

Events

The SDK never navigates. Events tell your app what the user clicked and carry the data you need; what happens next is up to you: change the URL, open a page or a modal, send analytics, or ignore the event. The table "What the SDK already does" lists what happens inside the components anyway.

  • Every event is a CustomEvent: read the payload from event.detail.
  • Events bubble and cross shadow DOM (composed), so you can listen on the element or on any ancestor.
  • Only the events listed in Components are part of the public contract. Other oreus-* events may escape internal elements; do not rely on them.
  • The SDK does not emit domain or status events. Errors are rendered by the related component (inline state or toast).
const collections = document.querySelector("oreus-collections");
collections.addEventListener("oreus-select", (event) => {
  const { folderId, name } = event.detail;
  document.querySelector("oreus-files-table").setAttribute("folder-id", folderId);
});

Keeping the chat in the URL: store sessionId / voxieId from oreus-chat-change (and from oreus-session-select / oreus-select if you route on those), then pass them back through session-id / voxie-id after a reload.

Styling

Components live in shadow DOM and are isolated from your page CSS: inherited properties such as text-align, font or color from the host page do not leak in. Customize through the CSS custom properties below, set on <oreus-provider> or any ancestor.

oreus-provider {
  --oreus-primary: #1a5cff;
  --oreus-font-family: "Inter", sans-serif;
}

| Property | Effect | | ----------------------- | ---------------------------------------------------- | | --oreus-primary | Primary button color, including the gradient variant, and the focus ring | | --oreus-font-family | Font of every component |

theme="dark" on the provider switches to the dark palette. Everything else keeps the Oreus look.

Localization

Set locale on the provider: en or fr. Any other value falls back to en, and a value starting with fr (such as fr-CA) selects fr. Without the attribute the SDK uses document.documentElement.lang, then en. Changing locale at runtime re-renders texts, dates and numbers.

State

Every <oreus-provider> is isolated from the others. The provider owns a provider-scoped Nano Stores Query context, so query caches, the active organization, and local chat state are never shared between provider trees.

Remote data lives in domain query stores (runtime.data.agents, sessions, drive, orbs, voxies, vox, organizations), which expose loading, error, empty, and content states. Components subscribe through StoreController and render through <oreus-content-state>; a revalidation keeps already-cached data visible instead of replacing it with a spinner. Mutations expose their own loading and error state and revalidate only the related query.

The active organization is the one the user authorized for your app on the Logto consent screen. The organizations claim lists all the user's organizations, so the SDK asks the token endpoint for each in turn until one is granted (the others answer access_denied). The granted organization ID is then kept in localStorage, per user, and tried first on the next loads; signing out clears it. The organization token and the query caches are never persisted.

Integrations

Call registerOreusComponents() once before using the elements. The SDK has no dependency on a host UI library.

Template types need no setup: importing the package types the elements' props and events in React, Preact, Solid, Qwik, Stencil, Hono, Vue and Svelte. Typings for a framework that is not installed are ignored. Other hosts can extend their own JSX namespace with CustomElements from the /jsx entry.

| Host | Runtime setup | | ------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | React 19+ / Next.js 15+ | Register from client code ("use client"); custom events use onoreus-select style props. React 18 is not supported: it drops event handlers on custom elements. | | Vue / Nuxt | ConfigureisCustomElement: tag => tag.startsWith("oreus-"); in Nuxt render under <ClientOnly>. | | Solid | Useon:oreus-select for custom events. | | Angular | AddCUSTOM_ELEMENTS_SCHEMA. | | Preact, Svelte, Lit, plain JavaScript | None. |

Editor data: the package publishes custom-elements.json through its customElements field. For VS Code HTML autocomplete, set "html.customData": ["./node_modules/@oreus/web-sdk/dist/vscode.html-custom-data.json"].

document.querySelector("oreus-vox-chat") is typed with the element class. Public event detail types (SessionSummary, StoreItem, VoxieSummary, LibrarySectionId) are exported from the main entry.

Development

pnpm --dir packages/web-sdk typecheck
pnpm --dir packages/web-sdk build
pnpm --dir packages/web-sdk test
pnpm --dir packages/web-sdk dev   # demo in examples/, reads .env (copy .env.example)