@fastaar/nextjs 0.1.0

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 ADDED
@@ -0,0 +1,159 @@
1
+ # Fastaar Next.js integration
2
+
3
+ Accept bKash & Nagad payments in your Next.js application using [Fastaar](https://fastaar.com).
4
+
5
+ This package is optimized for the Next.js App Router, featuring full support for **React Server Components (RSC)**, **Server Actions**, and Next.js **Route Handlers** for webhook signature verification. Written entirely in TypeScript.
6
+
7
+ ## Features
8
+
9
+ - **React Server Components**: `<CheckoutButton>` for instant checkout forms.
10
+ - **Server Actions**: Clean integration with server redirects.
11
+ - **Route Handlers Webhook Helper**: Automatically reads, verifies, and parses incoming webhooks.
12
+ - **Client Caching**: Singleton instance caching to prevent multiple instances during fast-refresh in development.
13
+ - **Full TypeScript Support**: Auto-complete and strict types for payments, config, and webhooks.
14
+
15
+ ## Install
16
+
17
+ Install the package and its peer dependencies (if not already installed):
18
+
19
+ ```bash
20
+ npm install @fastaar/nextjs
21
+ ```
22
+
23
+ ## Configuration
24
+
25
+ Set the following environment variables in your `.env.local` or hosting provider:
26
+
27
+ ```env
28
+ # Required: Your Fastaar Live/Test API key
29
+ FASTAAR_API_KEY="fk_live_..."
30
+
31
+ # Optional: Your Webhook secret for signature verification
32
+ FASTAAR_WEBHOOK_SECRET="whsec_..."
33
+ ```
34
+
35
+ ---
36
+
37
+ ## Usage
38
+
39
+ ### 1. Simple Checkout Button (Server Component)
40
+
41
+ Use the built-in `<CheckoutButton>` React Server Component. It renders a HTML form that invokes a Server Action to create the payment intent and automatically redirects the customer.
42
+
43
+ ```tsx
44
+ import { CheckoutButton } from '@fastaar/nextjs';
45
+
46
+ export default function CheckoutPage() {
47
+ return (
48
+ <main style={{ padding: '2rem' }}>
49
+ <h1>Complete your purchase</h1>
50
+ <p>Amount: 1,250 BDT</p>
51
+
52
+ <CheckoutButton
53
+ paymentParams={{
54
+ amount: 1250,
55
+ invoice_id: 'ORDER-42',
56
+ success_url: 'https://your-site.com/thanks',
57
+ cancel_url: 'https://your-site.com/cart',
58
+ metadata: { userId: 'usr_1001' },
59
+ }}
60
+ className="px-4 py-2 bg-green-600 text-white rounded hover:bg-green-700"
61
+ >
62
+ Pay with bKash / Nagad
63
+ </CheckoutButton>
64
+ </main>
65
+ );
66
+ }
67
+ ```
68
+
69
+ ### 2. Custom Flow (Server Actions)
70
+
71
+ If you need to perform additional server-side operations (like saving the order in your database as "pending" before redirecting), use `getFastaarClient` in your own Server Action:
72
+
73
+ ```tsx
74
+ import { getFastaarClient } from '@fastaar/nextjs';
75
+ import { redirect } from 'next/navigation';
76
+
77
+ export default function CheckoutPage() {
78
+ async function handleCheckout() {
79
+ 'use server';
80
+
81
+ // 1. Create order in your database
82
+ // const order = await db.order.create(...);
83
+
84
+ // 2. Initialize Fastaar client and create payment
85
+ const fastaar = getFastaarClient();
86
+ const payment = await fastaar.createPayment({
87
+ amount: 1250,
88
+ invoice_id: 'ORDER-42',
89
+ success_url: 'https://your-site.com/thanks',
90
+ cancel_url: 'https://your-site.com/cart',
91
+ });
92
+
93
+ // 3. Redirect to checkout page
94
+ redirect(payment.checkout_url);
95
+ }
96
+
97
+ return (
98
+ <form action={handleCheckout}>
99
+ <button type="submit">Pay Now</button>
100
+ </form>
101
+ );
102
+ }
103
+ ```
104
+
105
+ ### 3. Webhook Route Handler (Next.js App Router)
106
+
107
+ Handle payment status notifications securely using Next.js Route Handlers. The `verifyNextWebhook` helper handles raw stream reading and signature verification using your `FASTAAR_WEBHOOK_SECRET`.
108
+
109
+ Create a file at `app/api/webhooks/fastaar/route.ts`:
110
+
111
+ ```typescript
112
+ import { verifyNextWebhook } from '@fastaar/nextjs';
113
+ import { NextResponse } from 'next/server';
114
+
115
+ export async function POST(req: Request) {
116
+ const { isValid, event } = await verifyNextWebhook(req);
117
+
118
+ if (!isValid || !event) {
119
+ return new NextResponse('Invalid signature', { status: 400 });
120
+ }
121
+
122
+ // Handle the webhook event
123
+ if (event.event === 'payment.completed') {
124
+ const payment = event.data;
125
+ const invoiceId = payment.invoice_id; // e.g. 'ORDER-42'
126
+ const trxId = payment.trx_id; // operator transaction ID
127
+
128
+ // Mark order as paid in database idempotently
129
+ // await db.order.update({ where: { id: invoiceId }, data: { paid: true, trxId } });
130
+
131
+ console.log(`Payment completed for invoice ${invoiceId}`);
132
+ }
133
+
134
+ return new NextResponse('OK', { status: 200 });
135
+ }
136
+ ```
137
+
138
+ ### 4. Fetching Payment Details
139
+
140
+ To manually fetch details for a payment or invoice:
141
+
142
+ ```typescript
143
+ import { getFastaarClient } from '@fastaar/nextjs';
144
+
145
+ const fastaar = getFastaarClient();
146
+
147
+ // Get by Fastaar payment ID
148
+ const payment = await fastaar.getPayment('01jxyz...');
149
+
150
+ // Look up by your own invoice ID
151
+ const payment = await fastaar.findByInvoiceId('ORDER-42');
152
+
153
+ // List payments
154
+ const payments = await fastaar.listPayments({ status: 'completed', per_page: 10 });
155
+ ```
156
+
157
+ ## License
158
+
159
+ MIT
@@ -0,0 +1,36 @@
1
+ "use strict";
2
+ "use server";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+ var actions_exports = {};
21
+ __export(actions_exports, {
22
+ createCheckoutRedirect: () => createCheckoutRedirect
23
+ });
24
+ module.exports = __toCommonJS(actions_exports);
25
+ var import_navigation = require("next/navigation");
26
+ var import_client = require("./client");
27
+ async function createCheckoutRedirect(params) {
28
+ const client = (0, import_client.getFastaarClient)();
29
+ const payment = await client.createPayment(params);
30
+ (0, import_navigation.redirect)(payment.checkout_url);
31
+ }
32
+ // Annotate the CommonJS export names for ESM import in node:
33
+ 0 && (module.exports = {
34
+ createCheckoutRedirect
35
+ });
36
+ //# sourceMappingURL=actions.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/actions.ts"],"sourcesContent":["\"use server\";\n\nimport { redirect } from 'next/navigation';\nimport { getFastaarClient } from './client';\nimport { CreatePaymentParams } from './types';\n\n/**\n * Server Action to create a payment intent and redirect the user to the checkout URL.\n * \n * @param params Payment creation parameters\n */\nexport async function createCheckoutRedirect(params: CreatePaymentParams): Promise<never> {\n const client = getFastaarClient();\n const payment = await client.createPayment(params);\n redirect(payment.checkout_url);\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAEA,wBAAyB;AACzB,oBAAiC;AAQjC,eAAsB,uBAAuB,QAA6C;AACxF,QAAM,aAAS,gCAAiB;AAChC,QAAM,UAAU,MAAM,OAAO,cAAc,MAAM;AACjD,kCAAS,QAAQ,YAAY;AAC/B;","names":[]}
@@ -0,0 +1,10 @@
1
+ import { CreatePaymentParams } from './types.cjs';
2
+
3
+ /**
4
+ * Server Action to create a payment intent and redirect the user to the checkout URL.
5
+ *
6
+ * @param params Payment creation parameters
7
+ */
8
+ declare function createCheckoutRedirect(params: CreatePaymentParams): Promise<never>;
9
+
10
+ export { createCheckoutRedirect };
@@ -0,0 +1,10 @@
1
+ import { CreatePaymentParams } from './types.js';
2
+
3
+ /**
4
+ * Server Action to create a payment intent and redirect the user to the checkout URL.
5
+ *
6
+ * @param params Payment creation parameters
7
+ */
8
+ declare function createCheckoutRedirect(params: CreatePaymentParams): Promise<never>;
9
+
10
+ export { createCheckoutRedirect };
@@ -0,0 +1,12 @@
1
+ "use server";
2
+ import { redirect } from "next/navigation";
3
+ import { getFastaarClient } from "./client";
4
+ async function createCheckoutRedirect(params) {
5
+ const client = getFastaarClient();
6
+ const payment = await client.createPayment(params);
7
+ redirect(payment.checkout_url);
8
+ }
9
+ export {
10
+ createCheckoutRedirect
11
+ };
12
+ //# sourceMappingURL=actions.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/actions.ts"],"sourcesContent":["\"use server\";\n\nimport { redirect } from 'next/navigation';\nimport { getFastaarClient } from './client';\nimport { CreatePaymentParams } from './types';\n\n/**\n * Server Action to create a payment intent and redirect the user to the checkout URL.\n * \n * @param params Payment creation parameters\n */\nexport async function createCheckoutRedirect(params: CreatePaymentParams): Promise<never> {\n const client = getFastaarClient();\n const payment = await client.createPayment(params);\n redirect(payment.checkout_url);\n}\n"],"mappings":";AAEA,SAAS,gBAAgB;AACzB,SAAS,wBAAwB;AAQjC,eAAsB,uBAAuB,QAA6C;AACxF,QAAM,SAAS,iBAAiB;AAChC,QAAM,UAAU,MAAM,OAAO,cAAc,MAAM;AACjD,WAAS,QAAQ,YAAY;AAC/B;","names":[]}
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+ var client_exports = {};
20
+ __export(client_exports, {
21
+ FastaarClient: () => FastaarClient,
22
+ FastaarError: () => FastaarError,
23
+ getFastaarClient: () => getFastaarClient
24
+ });
25
+ module.exports = __toCommonJS(client_exports);
26
+ const API_BASE_URL = "https://fastaar.com";
27
+ class FastaarError extends Error {
28
+ /**
29
+ * The type of the error returned by the API (e.g. 'authentication_error', 'validation_error').
30
+ */
31
+ errorType;
32
+ /**
33
+ * The HTTP status code returned by the API.
34
+ */
35
+ statusCode;
36
+ constructor(message, errorType = "api_error", statusCode = 0) {
37
+ super(message);
38
+ this.name = "FastaarError";
39
+ this.errorType = errorType;
40
+ this.statusCode = statusCode;
41
+ }
42
+ }
43
+ class FastaarClient {
44
+ apiKey;
45
+ timeoutMs;
46
+ /**
47
+ * @param apiKey Your Fastaar API Key (fk_live_... or fk_test_...)
48
+ * @param options Client configuration options
49
+ */
50
+ constructor(apiKey, options = {}) {
51
+ if (!apiKey) {
52
+ throw new FastaarError("API key is required to initialize FastaarClient.", "authentication_error");
53
+ }
54
+ this.apiKey = apiKey;
55
+ this.timeoutMs = options.timeoutMs ?? 15e3;
56
+ }
57
+ /**
58
+ * Create a payment intent. Returns the payment object including
59
+ * `id`, `status`, and `checkout_url`.
60
+ *
61
+ * Reusing the same `invoice_id` returns the existing payment instead of
62
+ * creating a duplicate, so retries are safe. Supply `success_url`/`cancel_url`
63
+ * to return the customer to your site after checkout.
64
+ */
65
+ async createPayment(params) {
66
+ return this.request("POST", "/api/v1/payments", params);
67
+ }
68
+ /**
69
+ * Retrieve a payment by its reference ID.
70
+ */
71
+ async getPayment(paymentId) {
72
+ return this.request("GET", `/api/v1/payments/${encodeURIComponent(paymentId)}`);
73
+ }
74
+ /**
75
+ * List payments, newest first.
76
+ */
77
+ async listPayments(params = {}) {
78
+ const stringParams = {};
79
+ for (const [key, value] of Object.entries(params)) {
80
+ if (value !== void 0) {
81
+ stringParams[key] = String(value);
82
+ }
83
+ }
84
+ const query = new URLSearchParams(stringParams).toString();
85
+ return this.request("GET", `/api/v1/payments${query ? `?${query}` : ""}`);
86
+ }
87
+ /**
88
+ * Find the most recent payment for one of your invoice IDs, or null if none exist.
89
+ */
90
+ async findByInvoiceId(invoiceId) {
91
+ const payments = await this.listPayments({ invoice_id: invoiceId });
92
+ return payments[0] ?? null;
93
+ }
94
+ /**
95
+ * Helper to perform HTTP request to Fastaar API.
96
+ */
97
+ async request(method, path, body) {
98
+ let response;
99
+ try {
100
+ response = await fetch(API_BASE_URL + path, {
101
+ method,
102
+ headers: {
103
+ Authorization: `Bearer ${this.apiKey}`,
104
+ Accept: "application/json",
105
+ ...body ? { "Content-Type": "application/json" } : {}
106
+ },
107
+ body: body ? JSON.stringify(body) : void 0,
108
+ signal: AbortSignal.timeout(this.timeoutMs)
109
+ });
110
+ } catch (error) {
111
+ throw new FastaarError(`Could not reach the Fastaar API: ${error.message}`, "connection_error");
112
+ }
113
+ const payload = await response.json().catch(() => null);
114
+ if (!response.ok || payload === null) {
115
+ throw new FastaarError(
116
+ payload?.error?.message ?? `Fastaar API returned HTTP ${response.status}.`,
117
+ payload?.error?.type ?? "api_error",
118
+ response.status
119
+ );
120
+ }
121
+ return payload.data ?? payload;
122
+ }
123
+ }
124
+ const globalForFastaar = globalThis;
125
+ function getFastaarClient() {
126
+ if (!globalForFastaar.fastaarClient) {
127
+ const apiKey = process.env.FASTAAR_API_KEY;
128
+ if (!apiKey) {
129
+ throw new FastaarError(
130
+ "FASTAAR_API_KEY environment variable is not defined.",
131
+ "authentication_error"
132
+ );
133
+ }
134
+ const timeoutMs = process.env.FASTAAR_TIMEOUT_MS ? parseInt(process.env.FASTAAR_TIMEOUT_MS, 10) : void 0;
135
+ globalForFastaar.fastaarClient = new FastaarClient(apiKey, { timeoutMs });
136
+ }
137
+ return globalForFastaar.fastaarClient;
138
+ }
139
+ // Annotate the CommonJS export names for ESM import in node:
140
+ 0 && (module.exports = {
141
+ FastaarClient,
142
+ FastaarError,
143
+ getFastaarClient
144
+ });
145
+ //# sourceMappingURL=client.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import { CreatePaymentParams, FastaarClientOptions, ListPaymentsParams, Payment } from './types';\n\nconst API_BASE_URL = 'https://fastaar.com';\n\n/**\n * Custom error class for Fastaar API errors.\n */\nexport class FastaarError extends Error {\n /**\n * The type of the error returned by the API (e.g. 'authentication_error', 'validation_error').\n */\n errorType: string;\n\n /**\n * The HTTP status code returned by the API.\n */\n statusCode: number;\n\n constructor(message: string, errorType = 'api_error', statusCode = 0) {\n super(message);\n this.name = 'FastaarError';\n this.errorType = errorType;\n this.statusCode = statusCode;\n }\n}\n\n/**\n * Client for interacting with the Fastaar Payment Gateway API.\n */\nexport class FastaarClient {\n private apiKey: string;\n private timeoutMs: number;\n\n /**\n * @param apiKey Your Fastaar API Key (fk_live_... or fk_test_...)\n * @param options Client configuration options\n */\n constructor(apiKey: string, options: FastaarClientOptions = {}) {\n if (!apiKey) {\n throw new FastaarError('API key is required to initialize FastaarClient.', 'authentication_error');\n }\n this.apiKey = apiKey;\n this.timeoutMs = options.timeoutMs ?? 15000;\n }\n\n /**\n * Create a payment intent. Returns the payment object including\n * `id`, `status`, and `checkout_url`.\n *\n * Reusing the same `invoice_id` returns the existing payment instead of\n * creating a duplicate, so retries are safe. Supply `success_url`/`cancel_url`\n * to return the customer to your site after checkout.\n */\n async createPayment(params: CreatePaymentParams): Promise<Payment> {\n return this.request<Payment>('POST', '/api/v1/payments', params);\n }\n\n /**\n * Retrieve a payment by its reference ID.\n */\n async getPayment(paymentId: string): Promise<Payment> {\n return this.request<Payment>('GET', `/api/v1/payments/${encodeURIComponent(paymentId)}`);\n }\n\n /**\n * List payments, newest first.\n */\n async listPayments(params: ListPaymentsParams = {}): Promise<Payment[]> {\n const stringParams: Record<string, string> = {};\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n stringParams[key] = String(value);\n }\n }\n const query = new URLSearchParams(stringParams).toString();\n return this.request<Payment[]>('GET', `/api/v1/payments${query ? `?${query}` : ''}`);\n }\n\n /**\n * Find the most recent payment for one of your invoice IDs, or null if none exist.\n */\n async findByInvoiceId(invoiceId: string): Promise<Payment | null> {\n const payments = await this.listPayments({ invoice_id: invoiceId });\n return payments[0] ?? null;\n }\n\n /**\n * Helper to perform HTTP request to Fastaar API.\n */\n private async request<T>(method: string, path: string, body?: any): Promise<T> {\n let response: Response;\n\n try {\n response = await fetch(API_BASE_URL + path, {\n method,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n Accept: 'application/json',\n ...(body ? { 'Content-Type': 'application/json' } : {}),\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n } catch (error: any) {\n throw new FastaarError(`Could not reach the Fastaar API: ${error.message}`, 'connection_error');\n }\n\n const payload = await response.json().catch(() => null);\n\n if (!response.ok || payload === null) {\n throw new FastaarError(\n payload?.error?.message ?? `Fastaar API returned HTTP ${response.status}.`,\n payload?.error?.type ?? 'api_error',\n response.status,\n );\n }\n\n return (payload.data ?? payload) as T;\n }\n}\n\n// Global caching pattern for Next.js hot-reloading\nconst globalForFastaar = globalThis as unknown as {\n fastaarClient?: FastaarClient;\n};\n\n/**\n * Retrieves a cached singleton instance of FastaarClient initialized with\n * environment variables (FASTAAR_API_KEY, FASTAAR_TIMEOUT_MS).\n * Useful in Next.js API route handlers, Server Actions, and Server Components.\n */\nexport function getFastaarClient(): FastaarClient {\n if (!globalForFastaar.fastaarClient) {\n const apiKey = process.env.FASTAAR_API_KEY;\n if (!apiKey) {\n throw new FastaarError(\n 'FASTAAR_API_KEY environment variable is not defined.',\n 'authentication_error'\n );\n }\n\n const timeoutMs = process.env.FASTAAR_TIMEOUT_MS\n ? parseInt(process.env.FASTAAR_TIMEOUT_MS, 10)\n : undefined;\n\n globalForFastaar.fastaarClient = new FastaarClient(apiKey, { timeoutMs });\n }\n\n return globalForFastaar.fastaarClient;\n}\n"],"mappings":"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","names":[]}
@@ -0,0 +1,61 @@
1
+ import { FastaarClientOptions, CreatePaymentParams, Payment, ListPaymentsParams } from './types.cjs';
2
+
3
+ /**
4
+ * Custom error class for Fastaar API errors.
5
+ */
6
+ declare class FastaarError extends Error {
7
+ /**
8
+ * The type of the error returned by the API (e.g. 'authentication_error', 'validation_error').
9
+ */
10
+ errorType: string;
11
+ /**
12
+ * The HTTP status code returned by the API.
13
+ */
14
+ statusCode: number;
15
+ constructor(message: string, errorType?: string, statusCode?: number);
16
+ }
17
+ /**
18
+ * Client for interacting with the Fastaar Payment Gateway API.
19
+ */
20
+ declare class FastaarClient {
21
+ private apiKey;
22
+ private timeoutMs;
23
+ /**
24
+ * @param apiKey Your Fastaar API Key (fk_live_... or fk_test_...)
25
+ * @param options Client configuration options
26
+ */
27
+ constructor(apiKey: string, options?: FastaarClientOptions);
28
+ /**
29
+ * Create a payment intent. Returns the payment object including
30
+ * `id`, `status`, and `checkout_url`.
31
+ *
32
+ * Reusing the same `invoice_id` returns the existing payment instead of
33
+ * creating a duplicate, so retries are safe. Supply `success_url`/`cancel_url`
34
+ * to return the customer to your site after checkout.
35
+ */
36
+ createPayment(params: CreatePaymentParams): Promise<Payment>;
37
+ /**
38
+ * Retrieve a payment by its reference ID.
39
+ */
40
+ getPayment(paymentId: string): Promise<Payment>;
41
+ /**
42
+ * List payments, newest first.
43
+ */
44
+ listPayments(params?: ListPaymentsParams): Promise<Payment[]>;
45
+ /**
46
+ * Find the most recent payment for one of your invoice IDs, or null if none exist.
47
+ */
48
+ findByInvoiceId(invoiceId: string): Promise<Payment | null>;
49
+ /**
50
+ * Helper to perform HTTP request to Fastaar API.
51
+ */
52
+ private request;
53
+ }
54
+ /**
55
+ * Retrieves a cached singleton instance of FastaarClient initialized with
56
+ * environment variables (FASTAAR_API_KEY, FASTAAR_TIMEOUT_MS).
57
+ * Useful in Next.js API route handlers, Server Actions, and Server Components.
58
+ */
59
+ declare function getFastaarClient(): FastaarClient;
60
+
61
+ export { FastaarClient, FastaarError, getFastaarClient };
@@ -0,0 +1,61 @@
1
+ import { FastaarClientOptions, CreatePaymentParams, Payment, ListPaymentsParams } from './types.js';
2
+
3
+ /**
4
+ * Custom error class for Fastaar API errors.
5
+ */
6
+ declare class FastaarError extends Error {
7
+ /**
8
+ * The type of the error returned by the API (e.g. 'authentication_error', 'validation_error').
9
+ */
10
+ errorType: string;
11
+ /**
12
+ * The HTTP status code returned by the API.
13
+ */
14
+ statusCode: number;
15
+ constructor(message: string, errorType?: string, statusCode?: number);
16
+ }
17
+ /**
18
+ * Client for interacting with the Fastaar Payment Gateway API.
19
+ */
20
+ declare class FastaarClient {
21
+ private apiKey;
22
+ private timeoutMs;
23
+ /**
24
+ * @param apiKey Your Fastaar API Key (fk_live_... or fk_test_...)
25
+ * @param options Client configuration options
26
+ */
27
+ constructor(apiKey: string, options?: FastaarClientOptions);
28
+ /**
29
+ * Create a payment intent. Returns the payment object including
30
+ * `id`, `status`, and `checkout_url`.
31
+ *
32
+ * Reusing the same `invoice_id` returns the existing payment instead of
33
+ * creating a duplicate, so retries are safe. Supply `success_url`/`cancel_url`
34
+ * to return the customer to your site after checkout.
35
+ */
36
+ createPayment(params: CreatePaymentParams): Promise<Payment>;
37
+ /**
38
+ * Retrieve a payment by its reference ID.
39
+ */
40
+ getPayment(paymentId: string): Promise<Payment>;
41
+ /**
42
+ * List payments, newest first.
43
+ */
44
+ listPayments(params?: ListPaymentsParams): Promise<Payment[]>;
45
+ /**
46
+ * Find the most recent payment for one of your invoice IDs, or null if none exist.
47
+ */
48
+ findByInvoiceId(invoiceId: string): Promise<Payment | null>;
49
+ /**
50
+ * Helper to perform HTTP request to Fastaar API.
51
+ */
52
+ private request;
53
+ }
54
+ /**
55
+ * Retrieves a cached singleton instance of FastaarClient initialized with
56
+ * environment variables (FASTAAR_API_KEY, FASTAAR_TIMEOUT_MS).
57
+ * Useful in Next.js API route handlers, Server Actions, and Server Components.
58
+ */
59
+ declare function getFastaarClient(): FastaarClient;
60
+
61
+ export { FastaarClient, FastaarError, getFastaarClient };
package/dist/client.js ADDED
@@ -0,0 +1,119 @@
1
+ const API_BASE_URL = "https://fastaar.com";
2
+ class FastaarError extends Error {
3
+ /**
4
+ * The type of the error returned by the API (e.g. 'authentication_error', 'validation_error').
5
+ */
6
+ errorType;
7
+ /**
8
+ * The HTTP status code returned by the API.
9
+ */
10
+ statusCode;
11
+ constructor(message, errorType = "api_error", statusCode = 0) {
12
+ super(message);
13
+ this.name = "FastaarError";
14
+ this.errorType = errorType;
15
+ this.statusCode = statusCode;
16
+ }
17
+ }
18
+ class FastaarClient {
19
+ apiKey;
20
+ timeoutMs;
21
+ /**
22
+ * @param apiKey Your Fastaar API Key (fk_live_... or fk_test_...)
23
+ * @param options Client configuration options
24
+ */
25
+ constructor(apiKey, options = {}) {
26
+ if (!apiKey) {
27
+ throw new FastaarError("API key is required to initialize FastaarClient.", "authentication_error");
28
+ }
29
+ this.apiKey = apiKey;
30
+ this.timeoutMs = options.timeoutMs ?? 15e3;
31
+ }
32
+ /**
33
+ * Create a payment intent. Returns the payment object including
34
+ * `id`, `status`, and `checkout_url`.
35
+ *
36
+ * Reusing the same `invoice_id` returns the existing payment instead of
37
+ * creating a duplicate, so retries are safe. Supply `success_url`/`cancel_url`
38
+ * to return the customer to your site after checkout.
39
+ */
40
+ async createPayment(params) {
41
+ return this.request("POST", "/api/v1/payments", params);
42
+ }
43
+ /**
44
+ * Retrieve a payment by its reference ID.
45
+ */
46
+ async getPayment(paymentId) {
47
+ return this.request("GET", `/api/v1/payments/${encodeURIComponent(paymentId)}`);
48
+ }
49
+ /**
50
+ * List payments, newest first.
51
+ */
52
+ async listPayments(params = {}) {
53
+ const stringParams = {};
54
+ for (const [key, value] of Object.entries(params)) {
55
+ if (value !== void 0) {
56
+ stringParams[key] = String(value);
57
+ }
58
+ }
59
+ const query = new URLSearchParams(stringParams).toString();
60
+ return this.request("GET", `/api/v1/payments${query ? `?${query}` : ""}`);
61
+ }
62
+ /**
63
+ * Find the most recent payment for one of your invoice IDs, or null if none exist.
64
+ */
65
+ async findByInvoiceId(invoiceId) {
66
+ const payments = await this.listPayments({ invoice_id: invoiceId });
67
+ return payments[0] ?? null;
68
+ }
69
+ /**
70
+ * Helper to perform HTTP request to Fastaar API.
71
+ */
72
+ async request(method, path, body) {
73
+ let response;
74
+ try {
75
+ response = await fetch(API_BASE_URL + path, {
76
+ method,
77
+ headers: {
78
+ Authorization: `Bearer ${this.apiKey}`,
79
+ Accept: "application/json",
80
+ ...body ? { "Content-Type": "application/json" } : {}
81
+ },
82
+ body: body ? JSON.stringify(body) : void 0,
83
+ signal: AbortSignal.timeout(this.timeoutMs)
84
+ });
85
+ } catch (error) {
86
+ throw new FastaarError(`Could not reach the Fastaar API: ${error.message}`, "connection_error");
87
+ }
88
+ const payload = await response.json().catch(() => null);
89
+ if (!response.ok || payload === null) {
90
+ throw new FastaarError(
91
+ payload?.error?.message ?? `Fastaar API returned HTTP ${response.status}.`,
92
+ payload?.error?.type ?? "api_error",
93
+ response.status
94
+ );
95
+ }
96
+ return payload.data ?? payload;
97
+ }
98
+ }
99
+ const globalForFastaar = globalThis;
100
+ function getFastaarClient() {
101
+ if (!globalForFastaar.fastaarClient) {
102
+ const apiKey = process.env.FASTAAR_API_KEY;
103
+ if (!apiKey) {
104
+ throw new FastaarError(
105
+ "FASTAAR_API_KEY environment variable is not defined.",
106
+ "authentication_error"
107
+ );
108
+ }
109
+ const timeoutMs = process.env.FASTAAR_TIMEOUT_MS ? parseInt(process.env.FASTAAR_TIMEOUT_MS, 10) : void 0;
110
+ globalForFastaar.fastaarClient = new FastaarClient(apiKey, { timeoutMs });
111
+ }
112
+ return globalForFastaar.fastaarClient;
113
+ }
114
+ export {
115
+ FastaarClient,
116
+ FastaarError,
117
+ getFastaarClient
118
+ };
119
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/client.ts"],"sourcesContent":["import { CreatePaymentParams, FastaarClientOptions, ListPaymentsParams, Payment } from './types';\n\nconst API_BASE_URL = 'https://fastaar.com';\n\n/**\n * Custom error class for Fastaar API errors.\n */\nexport class FastaarError extends Error {\n /**\n * The type of the error returned by the API (e.g. 'authentication_error', 'validation_error').\n */\n errorType: string;\n\n /**\n * The HTTP status code returned by the API.\n */\n statusCode: number;\n\n constructor(message: string, errorType = 'api_error', statusCode = 0) {\n super(message);\n this.name = 'FastaarError';\n this.errorType = errorType;\n this.statusCode = statusCode;\n }\n}\n\n/**\n * Client for interacting with the Fastaar Payment Gateway API.\n */\nexport class FastaarClient {\n private apiKey: string;\n private timeoutMs: number;\n\n /**\n * @param apiKey Your Fastaar API Key (fk_live_... or fk_test_...)\n * @param options Client configuration options\n */\n constructor(apiKey: string, options: FastaarClientOptions = {}) {\n if (!apiKey) {\n throw new FastaarError('API key is required to initialize FastaarClient.', 'authentication_error');\n }\n this.apiKey = apiKey;\n this.timeoutMs = options.timeoutMs ?? 15000;\n }\n\n /**\n * Create a payment intent. Returns the payment object including\n * `id`, `status`, and `checkout_url`.\n *\n * Reusing the same `invoice_id` returns the existing payment instead of\n * creating a duplicate, so retries are safe. Supply `success_url`/`cancel_url`\n * to return the customer to your site after checkout.\n */\n async createPayment(params: CreatePaymentParams): Promise<Payment> {\n return this.request<Payment>('POST', '/api/v1/payments', params);\n }\n\n /**\n * Retrieve a payment by its reference ID.\n */\n async getPayment(paymentId: string): Promise<Payment> {\n return this.request<Payment>('GET', `/api/v1/payments/${encodeURIComponent(paymentId)}`);\n }\n\n /**\n * List payments, newest first.\n */\n async listPayments(params: ListPaymentsParams = {}): Promise<Payment[]> {\n const stringParams: Record<string, string> = {};\n for (const [key, value] of Object.entries(params)) {\n if (value !== undefined) {\n stringParams[key] = String(value);\n }\n }\n const query = new URLSearchParams(stringParams).toString();\n return this.request<Payment[]>('GET', `/api/v1/payments${query ? `?${query}` : ''}`);\n }\n\n /**\n * Find the most recent payment for one of your invoice IDs, or null if none exist.\n */\n async findByInvoiceId(invoiceId: string): Promise<Payment | null> {\n const payments = await this.listPayments({ invoice_id: invoiceId });\n return payments[0] ?? null;\n }\n\n /**\n * Helper to perform HTTP request to Fastaar API.\n */\n private async request<T>(method: string, path: string, body?: any): Promise<T> {\n let response: Response;\n\n try {\n response = await fetch(API_BASE_URL + path, {\n method,\n headers: {\n Authorization: `Bearer ${this.apiKey}`,\n Accept: 'application/json',\n ...(body ? { 'Content-Type': 'application/json' } : {}),\n },\n body: body ? JSON.stringify(body) : undefined,\n signal: AbortSignal.timeout(this.timeoutMs),\n });\n } catch (error: any) {\n throw new FastaarError(`Could not reach the Fastaar API: ${error.message}`, 'connection_error');\n }\n\n const payload = await response.json().catch(() => null);\n\n if (!response.ok || payload === null) {\n throw new FastaarError(\n payload?.error?.message ?? `Fastaar API returned HTTP ${response.status}.`,\n payload?.error?.type ?? 'api_error',\n response.status,\n );\n }\n\n return (payload.data ?? payload) as T;\n }\n}\n\n// Global caching pattern for Next.js hot-reloading\nconst globalForFastaar = globalThis as unknown as {\n fastaarClient?: FastaarClient;\n};\n\n/**\n * Retrieves a cached singleton instance of FastaarClient initialized with\n * environment variables (FASTAAR_API_KEY, FASTAAR_TIMEOUT_MS).\n * Useful in Next.js API route handlers, Server Actions, and Server Components.\n */\nexport function getFastaarClient(): FastaarClient {\n if (!globalForFastaar.fastaarClient) {\n const apiKey = process.env.FASTAAR_API_KEY;\n if (!apiKey) {\n throw new FastaarError(\n 'FASTAAR_API_KEY environment variable is not defined.',\n 'authentication_error'\n );\n }\n\n const timeoutMs = process.env.FASTAAR_TIMEOUT_MS\n ? parseInt(process.env.FASTAAR_TIMEOUT_MS, 10)\n : undefined;\n\n globalForFastaar.fastaarClient = new FastaarClient(apiKey, { timeoutMs });\n }\n\n return globalForFastaar.fastaarClient;\n}\n"],"mappings":"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","names":[]}