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

@feedmepos/auth

v1.7.0

Published

Browser SDK for FeedMe's global authentication service. Embeds the account service's login/one-tap pages via iframe and exposes the signed-in session to your web app through a small static API (`FeedMeAuth`).

Readme

@feedmepos/auth

Browser SDK for FeedMe's global authentication service. Embeds the account service's login/one-tap pages via iframe and exposes the signed-in session to your web app through a small static API (FeedMeAuth).

Install

npm install @feedmepos/auth

Quick start

import { FeedMeAuth } from "@feedmepos/auth";

// Point at the environment (dev shown; omit/`false` for prod).
FeedMeAuth.setBaseUrl(true); // https://account.feedmedev.cc

FeedMeAuth.initialize({
  clientId: "<your client id>",
  loginMode: "iframe", // or "new_window"
  locale: "en-US",
});

FeedMeAuth.onAuthStateChanged((user, token) => {
  // user is null when signed out
});

// Show the login UI (one-tap → iframe/new-window login)
FeedMeAuth.signIn();

Merchant-owned login (SSO)

Some merchants run their own customer login. When an app serves such a merchant, pass its business id:

FeedMeAuth.initialize({
  clientId: "<your client id>",
  businessId: "<merchant business id>",
  loginMode: "new_window", // or "redirect"
});

FeedMeAuth.signIn();

signIn() then asks account-service (POST /api/sso/resolve) whether that business has a login provider registered:

  • no provider — everything behaves exactly as it does without businessId: one-tap, the FeedMe phone form, saved accounts.
  • a provider — the customer goes to the merchant's identity provider, comes back with a one-time ticket, and the SDK signs them into that merchant's tenant session. They have no FeedMe account and no FeedMe profile.

A tenant session lives in its own Firebase app instance, so it never signs out or overwrites a FeedMe session in the same browser: a customer can be signed into the FeedMe app and a merchant miniprogram at the same time.

Which session the API reports

While a merchant session is active, currentUser(), token, refreshToken(), getCustomToken() and onAuthStateChanged all report that session, and signOut() clears only it. With businessId set, the FeedMe session is reported only once /api/sso/resolve has answered that the business has no provider. Until then, and whenever the business cannot be classified (the call fails, is refused for your origin, or answers something unexpected), currentUser() resolves null and token is null, unless a merchant session is active, in which case they report that. In the same cases refreshToken() and getCustomToken() reject rather than fall back to the FeedMe session, and signOut() resolves without signing the FeedMe session out. An account-service that predates the route counts as "no provider", so the FeedMe session keeps working there.

A merchant session restored from this browser's storage is used only when the business runs its own login. After a business is switched back to FeedMe login, a restored merchant session is ignored and the FeedMe session is reported instead. If the classification fails, the restored merchant session is still used: it belongs to the customer, so it is safe to show.

| Method | Purpose | |---|---| | activeTenantId() | Identity Platform tenant of the active merchant session, else null. | | isTenantSessionActive() | Whether a merchant session is signed in and in use. | | isMerchantLogin() | Whether this app's business runs its own login. | | merchantName() | Merchant display name, once resolved. | | lastSsoError() | Last merchant sign-in failure code this page load, else null. | | signInTenantSession({ customToken, tenantId, businessId }) | Sign in a merchant session directly (native shells that run the flow themselves). Rejects, leaving no session active, when the sign-in fails or returns no user or token. |

Login modes

| loginMode | Merchant SSO | Notes | |---|---|---| | "new_window" | ✅ | Popup; the login page hands the session back to the SDK. Default. | | "redirect" | ✅ | Navigates the whole page and returns to location.href. The only mode that is reliable inside native webviews, where popups are often blocked or opened in a separate browser. | | "iframe" | ❌ | The merchant's consent page and IdP are not guaranteed to be frameable. When the business runs its own login, signIn() logs a warning and opens a "new_window" popup. A business without a provider keeps iframe mode. |

In "redirect" mode the app is returned to with a one-time sso_ticket parameter (never a token). initialize() exchanges it, signs the session in and strips the parameter from the URL, so no application code is needed beyond setting the mode. A failure comes back as sso_error and is readable through lastSsoError().

What is switched off for merchant sessions

  • one-tap and saved accounts — those are FeedMe accounts.
  • verifyOtp() — FeedMe phone verification; it rejects with "FeedMeAuth: phone verification is not available for merchant sessions".

Manage profile for merchant sessions

openManageProfile() / getManageProfileUrl() open the customer's merchant membership page (/manage/account/merchant?business_id=…) instead of the FeedMe account page. It shows the customer's merchant profile (name and phone from the merchant sign-in, email, birthday and gender from account-service; the CRM is not read) and lets the customer edit name, email, birthday and gender there. The phone stays read-only, and the email is saved as contact data without a verification code, so it is not a sign-in method. Your app needs no write route of its own.

The page gets its session from your app: it asks the SDK (its window.opener) for the merchant session, and the SDK answers only for its own businessId. The URL carries your app's origin as host_origin, since the page cannot read its opener's origin itself. So open it with openManageProfile() from a user gesture. A copied link or a severed opener shows an error screen, never the FeedMe login page.

Both calls throw when there is no merchant session to show:

  • "FeedMeAuth: manage profile needs a signed-in merchant session": the business runs its own login and no customer is signed in.
  • "FeedMeAuth: manage profile is not available until the business login mode is known": called before /api/sso/resolve answered. Wait for currentUser() or the first onAuthStateChanged callback first.

The id token of a merchant session carries phone_number exactly as a FeedMe one does, plus businessId and firebase.tenant, so ordering and CRM need no change beyond sending the customer's businessId when they look users up.

Opening the account-management page

openManageProfile() opens the user's FeedMe account page in a new tab:

FeedMeAuth.openManageProfile();
// or build the URL yourself:
const url = FeedMeAuth.getManageProfileUrl();

How the session reaches the new tab

The new tab needs the current session to show the right account. As of 1.5.0 the SDK hands that session over directly: the URL carries an opener=1 flag, the page asks its window.opener (your app) for a token via postMessage, and the SDK answers with a freshly minted custom token. The tab signs in with it — no shared cookies or storage involved.

This matters because when your app and the account service are on different domains (e.g. app.example.com → account.feedmedev.cc), browsers that block third-party cookies or partition iframe storage — Safari, all iOS browsers, Firefox, Chrome incognito — prevent the tab from recovering the session on its own. The postMessage hand-off is not subject to those restrictions, so it works across every browser and domain. Where the hand-off can't run, the SDK falls back to the previous cookie/storage recovery, so same-domain setups keep working exactly as before.

⚠️ COOP requirement (cross-domain hand-off)

The hand-off relies on the new tab keeping a live window.opener reference back to your app. If your app's pages send a strict Cross-Origin-Opener-Policy header, the browser severs that reference for cross-origin popups and the hand-off cannot happen — the tab then falls back to cookie/storage recovery, which fails on the privacy-strict browsers above, sending the user to a login prompt even though they're already signed in.

If you serve Cross-Origin-Opener-Policy on the pages that call openManageProfile(), use a value that preserves the opener link:

| Header value | Manage-profile hand-off | |---|---| | (no COOP header) | ✅ works | | same-origin-allow-popups | ✅ works | | same-origin | ❌ opener severed — hand-off disabled | | unsafe-none | ✅ works |

same-origin-allow-popups is the standard choice for apps that open OAuth-style popups, and is the recommended setting if you need COOP at all.

Also do not pass noopener when opening the page yourself (window.open(url, "_blank", "noopener") or rel="noopener" links) — it nulls window.opener for the same reason. openManageProfile() opens correctly on your behalf.

API

| Method | Purpose | |---|---| | setBaseUrl(isDev \| url) | Select the account-service environment. | | initialize(options) | Boot the SDK (background iframe, listeners). | | signIn(opts?) | Show the login UI. | | signOut() | Sign out; resolves once the session is cleared. | | onAuthStateChanged(cb) | Subscribe to (user, token) changes; returns an unsubscribe fn. | | onLoginComplete(cb) | Fires when a login flow completes. | | currentUser() | Resolve the current FeedMeUser \| null. | | token / refreshToken() | Read / force-refresh the id token. | | getCustomToken(idToken?) | Mint a custom token for the session. | | getManageProfileUrl() / openManageProfile() | Account-management page URL / open it in a new tab. | | verifyOtp({ phone, tokenType }) | Run the standalone OTP verification flow. | | activeTenantId() | Tenant of the active merchant session (see Merchant-owned login). | | isMerchantLogin() | Whether this app's business runs its own login. | | lastSsoError() | Last merchant sign-in failure code, if any. |