@grantry/js
v0.4.1
Published
Authentication for any JavaScript application. No framework required.
Maintainers
Readme
@grantry/js
The browser client for Grantry: sign-in, sessions, account management and billing for any JavaScript application, with no framework and no dependencies.
Using React, Next.js or Vue? Install @grantry/react, @grantry/nextjs or @grantry/vue instead —
each is built on this package.
Install
npm install @grantry/jsSign people in
import { GrantryClient } from '@grantry/js';
const grantry = new GrantryClient({
publishableKey: import.meta.env.VITE_GRANTRY_PUBLISHABLE_KEY, // pk_test_… or pk_live_…
});
// Coming back from the hosted sign-in: say if it did not work.
const outcome = await grantry.redirectOutcome();
if (outcome.status === 'refused') console.warn(outcome.message);
const user = await grantry.getUser(); // null when nobody is signed in
if (!user) {
button.onclick = () => grantry.signInWithRedirect(); // or { popup: true }
}Add your page's origin to the environment's allowed origins in the Grantry dashboard (Developers → Domains → Allowed origins), or every request is refused.
Building your own forms instead of the hosted pages: signIn, signUp, verifyMfa,
sendSignInCode, requestPasswordReset and the rest are methods on the same client. Every refusal is
a GrantryError with a code to switch on, a status, and per-field issues.
Sell
A purchase is paid on a hosted checkout page on your application's own checkout domain. Make one for
the signed-in user and the browser leaves for it, coming back to successUrl once it is paid:
await grantry.redirectToCheckout({
items: [{ priceId: 'price_…' }],
// Left out, this page. Absolute, and on an origin your environment allows.
successUrl: `${location.origin}/welcome`,
});A subscription is one recurring price on its own (for somebody who already subscribes, a change of
plan, which the page explains before anything is charged); one-time products are one to twenty, in
one currency. Name the plan beside its price ({ planId, priceId }) when you know it.
createCheckout() makes the page without leaving and returns its url, which carries the checkout's
key: send the buyer to it as it is, and never log it. redirectToPaymentMethodUpdate() and
createPaymentMethodUpdate() do the same for replacing the card a plan renews with. A backend making
a checkout for one of its users uses its secret key instead: createCheckoutSession in
@grantry/react/server.
Where the session lives
The session is an httpOnly cookie on Grantry's domain; this package never reads or stores it.
getToken() exchanges it for a sixty-second access token to send to your own backend, which verifies
it there (@grantry/react/server, or the JWKS).
With a pk_test_ key in a browser, the development session is also kept in localStorage, so
development works where third-party cookies are blocked (Safari, private windows). The API refuses that
for production environments; pass developmentSession: false to rely on the cookie alone.
Entry points
| Import | What |
| -------------------------- | -------------------------------------------------------------------- |
| @grantry/js | GrantryClient, GrantryError, and everything below |
| @grantry/js/entitlements | Read plans and features off an access token (no DOM; works on Node) |
| @grantry/js/keys | Read a publishable key's environment and API host (no DOM) |
| @grantry/js/routes | Sign-in, sign-up and redirect URL resolution (no DOM) |
| @grantry/js/theme | The hosted screens' brand theme |
entitlementsFromToken decodes and does not verify: use it to decide what to render, and make every
decision that matters on your server.
Requirements
ES modules only. Any current browser; Node 18 or later for the DOM-free entry points. Redirect and popup sign-in need a secure context (https, or localhost) for the browser's cryptography.
License
MIT
