@oneaccount/express 0.1.2 → 0.2.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -20,7 +20,7 @@ app.use(express.json());
20
20
  // Initialize SDK
21
21
  const oa = oneAccount({
22
22
  apiKey: process.env.ONEACCOUNT_API_KEY,
23
- accountProUrl: 'https://myaccount.one', // optional
23
+ accountProUrl: 'https://accountpro.replit.app', // optional
24
24
  debug: true, // optional - logs auth errors
25
25
  });
26
26
 
@@ -53,7 +53,7 @@ app.listen(3000);
53
53
  | Option | Type | Default | Description |
54
54
  |--------|------|---------|-------------|
55
55
  | `apiKey` | string | required | Your OneAccount API key |
56
- | `accountProUrl` | string | `https://myaccount.one` | OneAccount server URL |
56
+ | `accountProUrl` | string | `https://accountpro.replit.app` | OneAccount server URL |
57
57
  | `jwksUrl` | string | auto | JWKS endpoint URL (auto-derived from accountProUrl) |
58
58
  | `debug` | boolean | `false` | Log authentication errors |
59
59
 
@@ -90,6 +90,67 @@ When you call `oa.mountRoutes(app, '/api/connect')`, the following routes are av
90
90
  | POST | `/api/connect/payment` | Create marketplace payment |
91
91
  | POST | `/api/connect/refund` | Refund a payment |
92
92
 
93
+ ## Buyer Authentication
94
+
95
+ For marketplace apps where sellers have their own customers (buyers), the SDK provides buyer authentication:
96
+
97
+ ```typescript
98
+ import type { BuyerAuthRequest } from '@oneaccount/express';
99
+
100
+ // Mount buyer auth routes
101
+ oa.mountBuyerRoutes(app, '/api/buyer');
102
+
103
+ // Add buyer middleware to routes that need buyer auth
104
+ app.use('/api/customer', oa.buyerMiddleware);
105
+
106
+ // Protected buyer route - use BuyerAuthRequest for typing
107
+ app.get('/api/customer/orders', oa.requireBuyerAuth, (req: BuyerAuthRequest, res) => {
108
+ const buyer = req.buyer!; // Non-null after requireBuyerAuth
109
+ res.json({ buyerId: buyer.buyerId, sellerId: buyer.sellerId });
110
+ });
111
+
112
+ // Restrict to specific seller's buyers
113
+ app.get('/api/customer/classes', oa.requireBuyerForSeller('seller-uuid'), (req: BuyerAuthRequest, res) => {
114
+ res.json({ message: 'Welcome!' });
115
+ });
116
+ ```
117
+
118
+ ### Buyer Auth Routes
119
+
120
+ When you call `oa.mountBuyerRoutes(app, '/api/buyer')`:
121
+
122
+ | Method | Path | Description |
123
+ |--------|------|-------------|
124
+ | POST | `/api/buyer/magic/request` | Request magic login link (email or SMS) |
125
+ | GET | `/api/buyer/magic/verify` | Verify magic token and get JWT |
126
+ | GET | `/api/buyer/profile` | Get buyer profile (requires auth) |
127
+
128
+ ### Magic Link Request Body
129
+
130
+ ```json
131
+ {
132
+ "email": "customer@example.com",
133
+ "sellerId": "seller-uuid",
134
+ "channel": "email"
135
+ }
136
+ ```
137
+
138
+ Or for SMS:
139
+
140
+ ```json
141
+ {
142
+ "phone": "+15551234567",
143
+ "sellerId": "seller-uuid",
144
+ "channel": "sms"
145
+ }
146
+ ```
147
+
148
+ ### Buyer Middleware
149
+
150
+ - `oa.buyerMiddleware` - Parses buyer JWT from `Authorization: Bearer <token>` header
151
+ - `oa.requireBuyerAuth` - Returns 401 if no authenticated buyer
152
+ - `oa.requireBuyerForSeller(sellerId)` - Returns 403 if buyer doesn't belong to seller
153
+
93
154
  ## TypeScript
94
155
 
95
156
  The SDK is fully typed. Import types as needed:
@@ -98,7 +159,9 @@ The SDK is fully typed. Import types as needed:
98
159
  import type {
99
160
  OneAccountRequest,
100
161
  OneAccountUser,
101
- Entitlements
162
+ Entitlements,
163
+ BuyerAuthRequest,
164
+ BuyerUser,
102
165
  } from '@oneaccount/express';
103
166
  ```
104
167
 
@@ -1,4 +1,4 @@
1
- import type { OneAccountConfig, StripeConnectStatus, StripeTransaction, StripeBalance } from "../types";
1
+ import type { OneAccountConfig, StripeConnectStatus, StripeTransaction, StripeBalance, BuyerMagicRequestData, BuyerMagicVerifyResponse, BuyerProfileResponse } from "../types";
2
2
  export declare class AccountProClient {
3
3
  private baseUrl;
4
4
  private apiKey;
@@ -40,4 +40,10 @@ export declare class AccountProClient {
40
40
  refundId: string;
41
41
  status: string;
42
42
  }>;
43
+ requestBuyerMagicLink(data: BuyerMagicRequestData): Promise<{
44
+ success: boolean;
45
+ message: string;
46
+ }>;
47
+ verifyBuyerMagicToken(token: string): Promise<BuyerMagicVerifyResponse>;
48
+ getBuyerProfile(buyerToken: string): Promise<BuyerProfileResponse>;
43
49
  }
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.AccountProClient = void 0;
4
4
  class AccountProClient {
5
5
  constructor(config) {
6
- this.baseUrl = config.accountProUrl || "https://myaccount.one";
6
+ this.baseUrl = config.accountProUrl || "https://accountpro.replit.app";
7
7
  this.apiKey = config.apiKey;
8
8
  this.debug = config.debug || false;
9
9
  }
@@ -82,5 +82,18 @@ class AccountProClient {
82
82
  body: JSON.stringify(data),
83
83
  });
84
84
  }
85
+ // Buyer Auth Methods
86
+ async requestBuyerMagicLink(data) {
87
+ return this.request("/buyer/magic/request", {
88
+ method: "POST",
89
+ body: JSON.stringify(data),
90
+ });
91
+ }
92
+ async verifyBuyerMagicToken(token) {
93
+ return this.request(`/buyer/magic/verify?token=${encodeURIComponent(token)}`);
94
+ }
95
+ async getBuyerProfile(buyerToken) {
96
+ return this.request("/buyer/profile", { token: buyerToken });
97
+ }
85
98
  }
86
99
  exports.AccountProClient = AccountProClient;
package/dist/index.d.ts CHANGED
@@ -1,17 +1,24 @@
1
1
  import type { Express } from "express";
2
2
  import { createAuthMiddleware, requireAuth, requireEntitlement, requireSuperAdmin } from "./middleware/auth";
3
+ import { createBuyerAuthMiddleware, requireBuyerAuth, requireBuyerForSeller } from "./middleware/buyerAuth";
3
4
  import { AccountProClient } from "./client/accountPro";
4
5
  import type { OneAccountConfig } from "./types";
5
6
  export interface OneAccountSDK {
6
7
  middleware: ReturnType<typeof createAuthMiddleware>;
8
+ buyerMiddleware: ReturnType<typeof createBuyerAuthMiddleware>;
7
9
  requireAuth: typeof requireAuth;
8
10
  requireEntitlement: typeof requireEntitlement;
9
11
  requireSuperAdmin: typeof requireSuperAdmin;
12
+ requireBuyerAuth: typeof requireBuyerAuth;
13
+ requireBuyerForSeller: typeof requireBuyerForSeller;
10
14
  client: AccountProClient;
11
15
  mountRoutes: (app: Express, basePath?: string) => void;
16
+ mountBuyerRoutes: (app: Express, basePath?: string) => void;
12
17
  }
13
18
  export declare function oneAccount(config: OneAccountConfig): OneAccountSDK;
14
19
  export { createAuthMiddleware, requireAuth, requireEntitlement, requireSuperAdmin, } from "./middleware/auth";
20
+ export { createBuyerAuthMiddleware, requireBuyerAuth, requireBuyerForSeller, } from "./middleware/buyerAuth";
15
21
  export { createStripeConnectRoutes } from "./routes/stripeConnect";
22
+ export { createBuyerAuthRoutes } from "./routes/buyerAuth";
16
23
  export { AccountProClient } from "./client/accountPro";
17
- export type { OneAccountConfig, OneAccountRequest, OneAccountUser, Entitlements, } from "./types";
24
+ export type { OneAccountConfig, OneAccountRequest, OneAccountUser, Entitlements, BuyerAuthRequest, BuyerUser, BuyerMagicRequestData, BuyerMagicVerifyResponse, BuyerProfileResponse, } from "./types";
package/dist/index.js CHANGED
@@ -1,29 +1,38 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AccountProClient = exports.createStripeConnectRoutes = exports.requireSuperAdmin = exports.requireEntitlement = exports.requireAuth = exports.createAuthMiddleware = void 0;
3
+ exports.AccountProClient = exports.createBuyerAuthRoutes = exports.createStripeConnectRoutes = exports.requireBuyerForSeller = exports.requireBuyerAuth = exports.createBuyerAuthMiddleware = exports.requireSuperAdmin = exports.requireEntitlement = exports.requireAuth = exports.createAuthMiddleware = void 0;
4
4
  exports.oneAccount = oneAccount;
5
5
  const auth_1 = require("./middleware/auth");
6
+ const buyerAuth_1 = require("./middleware/buyerAuth");
6
7
  const stripeConnect_1 = require("./routes/stripeConnect");
8
+ const buyerAuth_2 = require("./routes/buyerAuth");
7
9
  const accountPro_1 = require("./client/accountPro");
8
10
  function oneAccount(config) {
9
11
  if (!config.apiKey) {
10
12
  throw new Error("OneAccount SDK requires an API key");
11
13
  }
12
14
  const resolvedConfig = {
13
- accountProUrl: config.accountProUrl || "https://myaccount.one",
15
+ accountProUrl: config.accountProUrl || "https://accountpro.replit.app",
14
16
  ...config,
15
17
  };
16
18
  const authMiddleware = (0, auth_1.createAuthMiddleware)(resolvedConfig);
19
+ const buyerAuthMiddleware = (0, buyerAuth_1.createBuyerAuthMiddleware)(resolvedConfig);
17
20
  const client = new accountPro_1.AccountProClient(resolvedConfig);
18
21
  return {
19
22
  middleware: authMiddleware,
23
+ buyerMiddleware: buyerAuthMiddleware,
20
24
  requireAuth: auth_1.requireAuth,
21
25
  requireEntitlement: auth_1.requireEntitlement,
22
26
  requireSuperAdmin: auth_1.requireSuperAdmin,
27
+ requireBuyerAuth: buyerAuth_1.requireBuyerAuth,
28
+ requireBuyerForSeller: buyerAuth_1.requireBuyerForSeller,
23
29
  client,
24
30
  mountRoutes: (app, basePath = "/api/connect") => {
25
31
  app.use(basePath, (0, stripeConnect_1.createStripeConnectRoutes)(resolvedConfig));
26
32
  },
33
+ mountBuyerRoutes: (app, basePath = "/api/buyer") => {
34
+ app.use(basePath, (0, buyerAuth_2.createBuyerAuthRoutes)(resolvedConfig));
35
+ },
27
36
  };
28
37
  }
29
38
  var auth_2 = require("./middleware/auth");
@@ -31,7 +40,13 @@ Object.defineProperty(exports, "createAuthMiddleware", { enumerable: true, get:
31
40
  Object.defineProperty(exports, "requireAuth", { enumerable: true, get: function () { return auth_2.requireAuth; } });
32
41
  Object.defineProperty(exports, "requireEntitlement", { enumerable: true, get: function () { return auth_2.requireEntitlement; } });
33
42
  Object.defineProperty(exports, "requireSuperAdmin", { enumerable: true, get: function () { return auth_2.requireSuperAdmin; } });
43
+ var buyerAuth_3 = require("./middleware/buyerAuth");
44
+ Object.defineProperty(exports, "createBuyerAuthMiddleware", { enumerable: true, get: function () { return buyerAuth_3.createBuyerAuthMiddleware; } });
45
+ Object.defineProperty(exports, "requireBuyerAuth", { enumerable: true, get: function () { return buyerAuth_3.requireBuyerAuth; } });
46
+ Object.defineProperty(exports, "requireBuyerForSeller", { enumerable: true, get: function () { return buyerAuth_3.requireBuyerForSeller; } });
34
47
  var stripeConnect_2 = require("./routes/stripeConnect");
35
48
  Object.defineProperty(exports, "createStripeConnectRoutes", { enumerable: true, get: function () { return stripeConnect_2.createStripeConnectRoutes; } });
49
+ var buyerAuth_4 = require("./routes/buyerAuth");
50
+ Object.defineProperty(exports, "createBuyerAuthRoutes", { enumerable: true, get: function () { return buyerAuth_4.createBuyerAuthRoutes; } });
36
51
  var accountPro_2 = require("./client/accountPro");
37
52
  Object.defineProperty(exports, "AccountProClient", { enumerable: true, get: function () { return accountPro_2.AccountProClient; } });
@@ -24,8 +24,12 @@ async function fetchJWKS(jwksUrl) {
24
24
  return cachedJWKS;
25
25
  }
26
26
  function rsaPublicKeyFromJWK(jwk) {
27
- const n = Buffer.from(jwk.n, "base64url");
28
- const e = Buffer.from(jwk.e, "base64url");
27
+ // Convert base64url to base64 (some Node versions don't support base64url directly)
28
+ const base64urlToBase64 = (str) => {
29
+ return str.replace(/-/g, '+').replace(/_/g, '/');
30
+ };
31
+ const n = Buffer.from(base64urlToBase64(jwk.n), "base64");
32
+ const e = Buffer.from(base64urlToBase64(jwk.e), "base64");
29
33
  const nLen = n.length;
30
34
  const eLen = e.length;
31
35
  const nLenBytes = nLen < 128
@@ -83,7 +87,7 @@ function extractTokenFromCookies(cookieHeader, cookieName) {
83
87
  }
84
88
  function createAuthMiddleware(config) {
85
89
  const jwksUrl = config.jwksUrl ||
86
- `${config.accountProUrl || "https://myaccount.one"}/.well-known/jwks.json`;
90
+ `${config.accountProUrl || "https://accountpro.replit.app"}/.well-known/jwks.json`;
87
91
  const cookieName = config.cookieName || "auth_token";
88
92
  const autoSetCookie = config.autoSetCookie !== false; // Default to true
89
93
  return async function authMiddleware(req, res, next) {
@@ -135,6 +139,14 @@ function createAuthMiddleware(config) {
135
139
  return next();
136
140
  }
137
141
  const publicKey = rsaPublicKeyFromJWK(key);
142
+ if (config.debug) {
143
+ console.log("[OneAccount] Public key generated:", {
144
+ keyType: typeof publicKey,
145
+ keyLength: publicKey?.length,
146
+ startsWithPem: publicKey?.startsWith('-----BEGIN'),
147
+ kid: key.kid
148
+ });
149
+ }
138
150
  const payload = jsonwebtoken_1.default.verify(token, publicKey, {
139
151
  algorithms: ["RS256"],
140
152
  });
@@ -0,0 +1,5 @@
1
+ import type { Response, NextFunction } from "express";
2
+ import type { BuyerAuthRequest, OneAccountConfig } from "../types";
3
+ export declare function createBuyerAuthMiddleware(config: OneAccountConfig): (req: BuyerAuthRequest, _res: Response, next: NextFunction) => Promise<void>;
4
+ export declare function requireBuyerAuth(req: BuyerAuthRequest, res: Response, next: NextFunction): Response<any, Record<string, any>> | undefined;
5
+ export declare function requireBuyerForSeller(sellerId: string): (req: BuyerAuthRequest, res: Response, next: NextFunction) => Response<any, Record<string, any>> | undefined;
@@ -0,0 +1,138 @@
1
+ "use strict";
2
+ var __importDefault = (this && this.__importDefault) || function (mod) {
3
+ return (mod && mod.__esModule) ? mod : { "default": mod };
4
+ };
5
+ Object.defineProperty(exports, "__esModule", { value: true });
6
+ exports.createBuyerAuthMiddleware = createBuyerAuthMiddleware;
7
+ exports.requireBuyerAuth = requireBuyerAuth;
8
+ exports.requireBuyerForSeller = requireBuyerForSeller;
9
+ const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
10
+ let cachedJWKS = null;
11
+ let jwksCacheExpiry = 0;
12
+ async function fetchJWKS(jwksUrl) {
13
+ const now = Date.now();
14
+ if (cachedJWKS && now < jwksCacheExpiry) {
15
+ return cachedJWKS;
16
+ }
17
+ const response = await fetch(jwksUrl);
18
+ if (!response.ok) {
19
+ throw new Error(`Failed to fetch JWKS: ${response.status}`);
20
+ }
21
+ cachedJWKS = await response.json();
22
+ jwksCacheExpiry = now + 3600000;
23
+ return cachedJWKS;
24
+ }
25
+ function rsaPublicKeyFromJWK(jwk) {
26
+ // Convert base64url to base64 (some Node versions don't support base64url directly)
27
+ const base64urlToBase64 = (str) => {
28
+ return str.replace(/-/g, '+').replace(/_/g, '/');
29
+ };
30
+ const n = Buffer.from(base64urlToBase64(jwk.n), "base64");
31
+ const e = Buffer.from(base64urlToBase64(jwk.e), "base64");
32
+ const nLen = n.length;
33
+ const eLen = e.length;
34
+ const nLenBytes = nLen < 128
35
+ ? [nLen]
36
+ : nLen < 256
37
+ ? [0x81, nLen]
38
+ : [0x82, (nLen >> 8) & 0xff, nLen & 0xff];
39
+ const eLenBytes = eLen < 128
40
+ ? [eLen]
41
+ : eLen < 256
42
+ ? [0x81, eLen]
43
+ : [0x82, (eLen >> 8) & 0xff, eLen & 0xff];
44
+ const nSequence = [0x02, ...nLenBytes, ...n];
45
+ const eSequence = [0x02, ...eLenBytes, ...e];
46
+ const innerSequence = [...nSequence, ...eSequence];
47
+ const innerLen = innerSequence.length;
48
+ const innerLenBytes = innerLen < 128
49
+ ? [innerLen]
50
+ : innerLen < 256
51
+ ? [0x81, innerLen]
52
+ : [0x82, (innerLen >> 8) & 0xff, innerLen & 0xff];
53
+ const bitString = [0x30, ...innerLenBytes, ...innerSequence];
54
+ const bitStringWithHeader = [
55
+ 0x03,
56
+ bitString.length + 1,
57
+ 0x00,
58
+ ...bitString,
59
+ ];
60
+ const rsaOID = [
61
+ 0x30, 0x0d, 0x06, 0x09, 0x2a, 0x86, 0x48, 0x86, 0xf7, 0x0d, 0x01, 0x01,
62
+ 0x01, 0x05, 0x00,
63
+ ];
64
+ const fullSequence = [...rsaOID, ...bitStringWithHeader];
65
+ const fullLen = fullSequence.length;
66
+ const fullLenBytes = fullLen < 128
67
+ ? [fullLen]
68
+ : fullLen < 256
69
+ ? [0x81, fullLen]
70
+ : [0x82, (fullLen >> 8) & 0xff, fullLen & 0xff];
71
+ const der = Buffer.from([0x30, ...fullLenBytes, ...fullSequence]);
72
+ const pem = `-----BEGIN PUBLIC KEY-----\n${der.toString("base64").match(/.{1,64}/g)?.join("\n")}\n-----END PUBLIC KEY-----`;
73
+ return pem;
74
+ }
75
+ function createBuyerAuthMiddleware(config) {
76
+ const jwksUrl = config.jwksUrl ||
77
+ `${config.accountProUrl || "https://accountpro.replit.app"}/.well-known/jwks.json`;
78
+ return async function buyerAuthMiddleware(req, _res, next) {
79
+ req.buyer = null;
80
+ const authHeader = req.headers.authorization;
81
+ const token = authHeader?.startsWith("Bearer ") ? authHeader.substring(7) : null;
82
+ if (!token) {
83
+ return next();
84
+ }
85
+ try {
86
+ const decoded = jsonwebtoken_1.default.decode(token, { complete: true });
87
+ if (!decoded) {
88
+ return next();
89
+ }
90
+ const jwks = await fetchJWKS(jwksUrl);
91
+ const key = decoded.header.kid
92
+ ? jwks.keys.find((k) => k.kid === decoded.header.kid)
93
+ : jwks.keys[0];
94
+ if (!key) {
95
+ if (config.debug) {
96
+ console.error("[OneAccount] No matching key found in JWKS for buyer token");
97
+ }
98
+ return next();
99
+ }
100
+ const publicKey = rsaPublicKeyFromJWK(key);
101
+ const payload = jsonwebtoken_1.default.verify(token, publicKey, {
102
+ algorithms: ["RS256"],
103
+ });
104
+ if (payload.buyerId && payload.sellerId) {
105
+ req.buyer = {
106
+ buyerId: payload.buyerId,
107
+ sellerId: payload.sellerId,
108
+ email: payload.email,
109
+ name: payload.name,
110
+ phone: payload.phone,
111
+ };
112
+ }
113
+ }
114
+ catch (err) {
115
+ if (config.debug) {
116
+ console.error("[OneAccount] Buyer JWT verification failed:", err);
117
+ }
118
+ }
119
+ next();
120
+ };
121
+ }
122
+ function requireBuyerAuth(req, res, next) {
123
+ if (!req.buyer) {
124
+ return res.status(401).json({ error: "Buyer authentication required" });
125
+ }
126
+ next();
127
+ }
128
+ function requireBuyerForSeller(sellerId) {
129
+ return function (req, res, next) {
130
+ if (!req.buyer) {
131
+ return res.status(401).json({ error: "Buyer authentication required" });
132
+ }
133
+ if (req.buyer.sellerId !== sellerId) {
134
+ return res.status(403).json({ error: "Access denied for this seller" });
135
+ }
136
+ next();
137
+ };
138
+ }
@@ -0,0 +1,3 @@
1
+ import type { Router } from "express";
2
+ import type { OneAccountConfig } from "../types";
3
+ export declare function createBuyerAuthRoutes(config: OneAccountConfig): Router;
@@ -0,0 +1,78 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createBuyerAuthRoutes = createBuyerAuthRoutes;
4
+ const express_1 = require("express");
5
+ const accountPro_1 = require("../client/accountPro");
6
+ function createBuyerAuthRoutes(config) {
7
+ const router = (0, express_1.Router)();
8
+ const client = new accountPro_1.AccountProClient(config);
9
+ router.post("/magic/request", async (req, res) => {
10
+ try {
11
+ const { email, phone, sellerId, channel: rawChannel } = req.body;
12
+ if (!sellerId) {
13
+ return res.status(400).json({ error: "sellerId is required" });
14
+ }
15
+ // Default to email if channel not specified
16
+ const channel = rawChannel || "email";
17
+ if (channel === "email" && !email) {
18
+ return res.status(400).json({ error: "email is required for email channel" });
19
+ }
20
+ if (channel === "sms" && !phone) {
21
+ return res.status(400).json({ error: "phone is required for SMS channel" });
22
+ }
23
+ const result = await client.requestBuyerMagicLink({
24
+ email,
25
+ phone,
26
+ sellerId,
27
+ channel,
28
+ });
29
+ res.json(result);
30
+ }
31
+ catch (error) {
32
+ const message = error instanceof Error ? error.message : "Failed to request magic link";
33
+ res.status(400).json({ error: message });
34
+ }
35
+ });
36
+ router.get("/magic/verify", async (req, res) => {
37
+ try {
38
+ const token = req.query.token;
39
+ if (!token) {
40
+ return res.status(400).json({ error: "token is required" });
41
+ }
42
+ const result = await client.verifyBuyerMagicToken(token);
43
+ if (result.success && result.token) {
44
+ res.json({
45
+ success: true,
46
+ token: result.token,
47
+ buyer: result.buyer,
48
+ });
49
+ }
50
+ else {
51
+ res.status(401).json({
52
+ success: false,
53
+ error: result.error || "Invalid or expired token",
54
+ });
55
+ }
56
+ }
57
+ catch (error) {
58
+ const message = error instanceof Error ? error.message : "Failed to verify token";
59
+ res.status(400).json({ error: message });
60
+ }
61
+ });
62
+ router.get("/profile", async (req, res) => {
63
+ try {
64
+ const authHeader = req.headers.authorization;
65
+ const token = authHeader?.startsWith("Bearer ") ? authHeader.substring(7) : "";
66
+ if (!token) {
67
+ return res.status(401).json({ error: "Authorization required" });
68
+ }
69
+ const profile = await client.getBuyerProfile(token);
70
+ res.json(profile);
71
+ }
72
+ catch (error) {
73
+ const message = error instanceof Error ? error.message : "Failed to get profile";
74
+ res.status(400).json({ error: message });
75
+ }
76
+ });
77
+ return router;
78
+ }
@@ -60,3 +60,32 @@ export interface StripeBalance {
60
60
  currency: string;
61
61
  }[];
62
62
  }
63
+ export interface BuyerUser {
64
+ buyerId: string;
65
+ sellerId: string;
66
+ email: string;
67
+ name?: string;
68
+ phone?: string;
69
+ }
70
+ export interface BuyerAuthRequest extends Request {
71
+ buyer?: BuyerUser | null;
72
+ }
73
+ export interface BuyerMagicRequestData {
74
+ email?: string;
75
+ phone?: string;
76
+ sellerId: string;
77
+ channel?: "email" | "sms";
78
+ }
79
+ export interface BuyerMagicVerifyResponse {
80
+ success: boolean;
81
+ token?: string;
82
+ buyer?: BuyerUser;
83
+ error?: string;
84
+ }
85
+ export interface BuyerProfileResponse {
86
+ id: string;
87
+ email: string;
88
+ name?: string;
89
+ phone?: string;
90
+ sellerId: string;
91
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@oneaccount/express",
3
- "version": "0.1.2",
3
+ "version": "0.2.4",
4
4
  "description": "OneAccount SDK for Express.js - Authentication, entitlements, and Stripe Connect",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",