@duabalabs/dps-client
A small typed client for the DPS subscription gate: given an app and an email, is there an active subscription? Use it to decide whether to let a signed-in user in.
- License: MIT · Current version:
0.3.x - Peer dependency:
parse(>=4 <6)
Don’t gate on it today. Nothing records subscriptions in DPS any more, so
checkSubscription answers active: false for every email. Subscriptions are taken and
tracked by Sellub — check one there
(@duabalabs/sellub-client’s subscriptions.status or
subscriptions.byReference).
Payment and checkout APIs were removed in v0.2.0. createCheckout, verifyPayment,
getOrder, listOrders, withTenant and the tenant helpers no longer exist. Taking money
— one-off payments, subscriptions, invoices — is done with
@duabalabs/sellub-client.
Install
npm install @duabalabs/dps-client parse
# or
pnpm add @duabalabs/dps-client parseWiring it up
createDpsClient uses the Parse JS SDK with DPS’s public app id and JavaScript key, so
it is safe in a browser, a static-export Next.js site or React Native.
// src/lib/dps/client.ts
import Parse from 'parse';
import { createDpsClient, type DpsClient } from '@duabalabs/dps-client';
let cached: DpsClient | null = null;
export function getDps(): DpsClient {
if (cached) return cached;
Parse.initialize(process.env.NEXT_PUBLIC_DPS_APP_ID!, process.env.NEXT_PUBLIC_DPS_JS_KEY);
Parse.serverURL = 'https://api.duabaforge.com/parse';
cached = createDpsClient({ Parse: Parse as any });
return cached;
}createDpsClient needs only Parse.Cloud.run from what you pass it (the ParseLike
type), so a mock works in tests.
Gate access on a subscription
import { getDps } from '@/lib/dps/client';
const status = await getDps().checkSubscription({
appId: 'your-app',
email: 'user@example.com',
});
if (status.active) {
// let them in — status.tier and status.expiresAt are available
} else {
// send them to a Sellub checkout (see @duabalabs/sellub-client)
}checkSubscription calls the dps_subscriptions_check cloud function. Both appId and
email are required; the email is trimmed and lower-cased before it is matched.
interface CheckSubscriptionInput {
appId: string;
email: string;
}
interface SubscriptionStatus {
active: boolean;
tier: string | null;
expiresAt: string | null; // ISO-8601; null when the subscription has no end date
orderId: string | null;
}The client unwraps the { success, data } envelope the cloud function returns, so you get
the SubscriptionStatus itself. Errors are whatever Parse.Cloud.run rejects with — catch
them as you would any Parse error.
The package also exports listEvents, getEvent and createDpsServerClient. Don’t use
them: the event functions they call no longer exist on DPS, and the server client needs
DPS’s master key, which DPS accepts only from its own servers.
Environment variables
| Variable | Purpose |
|---|---|
NEXT_PUBLIC_DPS_APP_ID | DPS’s Parse application id |
NEXT_PUBLIC_DPS_JS_KEY | DPS’s public JavaScript key |
These names are a convention, not something the package reads — you pass the values to
Parse.initialize yourself. Both are public values and safe in a browser bundle.
Related
@duabalabs/sellub-client— takes the payments and subscriptions.- DPS API reference — the cloud functions and REST endpoints.