spaps-sdk
v1.6.5
Published
Sweet Potato Authentication & Payment Service SDK - Zero-config client with built-in permission checking, role-based access control, and dayrate scheduling
Maintainers
Readme
spaps-sdk
Typed TypeScript client for SPAPS-compatible APIs.
Examples in this README use placeholders such as [email protected], [email protected], and https://api.example.test. Replace them with values from your own deployment.
Install
npm install spaps-sdkAlternative package managers:
pnpm add spaps-sdk
yarn add spaps-sdkThis package targets Node.js >=14.
When It Fits
| Need | Package gives you |
| --- | --- |
| One client for many SPAPS surfaces | auth, payments, sessions, secureMessages, issueReporting, email, entitlements, dayrate, admin, and cfo namespaces |
| Local development without extra config | Localhost URLs automatically enable local mode |
| Browser and server usage | publishableKey, secretKey, or legacy apiKey support |
| Shared contracts | Re-exports a large slice of spaps-types |
Quick Start
import { SPAPSClient } from "spaps-sdk";
const spaps = new SPAPSClient({
apiUrl: "http://localhost:3301",
publishableKey: "spaps_pub_example",
});
const auth = await spaps.auth.signInWithPassword({
email: "[email protected]",
password: "correct-horse-battery-staple",
});
const me = await spaps.getUser();
const issues = await spaps.issueReporting.list({
status: "open",
scope: "mine",
limit: 20,
});
console.log(auth.user.id, me.data.email, issues.total);Configuration
Constructor values take precedence over environment variables.
| Option | Purpose |
| --- | --- |
| apiUrl | Base API URL. Localhost values enable local mode automatically |
| publishableKey | Browser-safe key for client-side usage |
| secretKey | Server-side key for privileged access |
| apiKey | Legacy key field kept for compatibility |
| timeout | Request timeout override |
Relevant environment variables:
SPAPS_API_URLNEXT_PUBLIC_SPAPS_API_URLSPAPS_API_KEYNEXT_PUBLIC_SPAPS_API_KEY
Core Surface
| Namespace | Covers |
| --- | --- |
| auth | Password, wallet, magic-link, refresh, logout, and password-management flows |
| payments | Checkout sessions, products, prices, subscriptions, and crypto helpers |
| sessions | Session lookup, validation, and lifecycle helpers |
| secureMessages | Secure-message create/list helpers |
| issueReporting | Status, history, create, update, and reply flows |
| email | Template lookup, preview, and send helpers |
| entitlements | User and resource entitlement queries |
| dayrate | Availability and booking helpers |
| admin | Product and pricing admin helpers |
| cfo | CFO-facing reporting endpoints |
Common Patterns
Typed Secure Messages
type SecureMessageMetadata = { urgency: "low" | "high"; tags?: string[] };
const spaps = new SPAPSClient<SecureMessageMetadata>({
apiUrl: "https://api.example.test",
secretKey: process.env.SPAPS_API_KEY,
});
await spaps.secureMessages.create({
patientId: "3d6f0a51-8d77-4b38-8248-2d1b2f1f6c7f",
practitionerId: "a3d7f431-6c9d-4cbc-9f78-4e5b6a7c8d9e",
content: "Follow up scheduled for next week.",
metadata: { urgency: "low", tags: ["follow-up"] },
});Permission Helpers With Explicit Admin Config
import {
canAccessAdmin,
createPermissionChecker,
isAdminAccount,
} from "spaps-sdk";
const customAdmins = ["[email protected]"];
const checker = createPermissionChecker(customAdmins);
const role = checker.getRole("[email protected]");
const adminCheck = canAccessAdmin(
{ id: "user_123", email: "[email protected]" },
customAdmins,
);
const isAdmin = isAdminAccount("[email protected]", customAdmins);
console.log(role, adminCheck.allowed, isAdmin);Convenience Helpers
const spaps = new SPAPSClient({ apiUrl: "http://localhost:3301" });
spaps.isLocalMode();
spaps.isAuthenticated();
spaps.getAccessToken();
spaps.setAccessToken("token");
await spaps.health();Development
cd packages/sdk
npm ci
npm run build
npm run typecheck:readme
npm run test:readme
npm run testTroubleshooting
401 Unauthorized
Check the access token, API key choice, and target environment. Browser apps should generally use publishableKey, not a server secret.
Local mode is not activating
Use a localhost URL such as http://localhost:3301, then confirm with spaps.isLocalMode().
I need shared types in app code
Import them from spaps-sdk if the re-export exists, or install spaps-types directly for a narrower dependency.
Limitations
- The SDK is handwritten around the current SPAPS surface. It is not a generated client for every backend route.
- Some admin and entitlement flows still depend on upstream permissions and token context.
- The legacy
apiKeyfield remains for compatibility, but new integrations should preferpublishableKeyorsecretKey.
FAQ
Does this work in browsers?
Yes. The package is intended for both browser and server use.
Does it include a fetch polyfill?
Yes. It loads cross-fetch/polyfill when fetch is missing.
Can I use it from plain JavaScript?
Yes. The runtime works in JavaScript projects and ships bundled type declarations for TypeScript users.
Does it re-export shared types?
Yes. Many spaps-types exports are re-exported for convenience.
How do I validate the README snippets?
Run:
npm run typecheck:readme
npm run test:readmeAbout Contributions
About Contributions: Please don't take this the wrong way, but I do not accept outside contributions for any of my projects. I simply don't have the mental bandwidth to review anything, and it's my name on the thing, so I'm responsible for any problems it causes; thus, the risk-reward is highly asymmetric from my perspective. I'd also have to worry about other "stakeholders," which seems unwise for tools I mostly make for myself for free. Feel free to submit issues, and even PRs if you want to illustrate a proposed fix, but know I won't merge them directly. Instead, I'll have Claude or Codex review submissions via
ghand independently decide whether and how to address them. Bug reports in particular are welcome. Sorry if this offends, but I want to avoid wasted time and hurt feelings. I understand this isn't in sync with the prevailing open-source ethos that seeks community contributions, but it's the only way I can move at this velocity and keep my sanity.
License
MIT
