@flopay/node 0.5.19 → 1.0.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 +4 -3
- package/dist/index.cjs +7 -4
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +2 -1
- package/dist/index.d.ts +2 -1
- package/dist/index.mjs +5 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@ Server-side FloPay SDK for Node.js. Creates checkout sessions via the billing AP
|
|
|
8
8
|
pnpm add @flopay/node
|
|
9
9
|
```
|
|
10
10
|
|
|
11
|
-
Depends on `stripe` (^
|
|
11
|
+
Depends on `stripe` (^22.1.1) and `@flopay/shared`.
|
|
12
12
|
|
|
13
13
|
## Quick Start
|
|
14
14
|
|
|
@@ -18,6 +18,7 @@ Depends on `stripe` (^17.0.0) and `@flopay/shared`.
|
|
|
18
18
|
import { FloPay } from '@flopay/node';
|
|
19
19
|
|
|
20
20
|
const flopay = new FloPay('sk_test_...');
|
|
21
|
+
// Direct Stripe operations default to API version 2026-04-22.dahlia.
|
|
21
22
|
```
|
|
22
23
|
|
|
23
24
|
### Create a Checkout Session (Billing API)
|
|
@@ -119,8 +120,8 @@ new FloPay(secretKey: string, options?: FloPayNodeOptions)
|
|
|
119
120
|
| Parameter | Type | Description |
|
|
120
121
|
|-----------|------|-------------|
|
|
121
122
|
| `secretKey` | `string` | Stripe secret key (`sk_test_...` or `sk_live_...`). Required. |
|
|
122
|
-
| `options.apiVersion` | `string?` | API version override |
|
|
123
|
-
| `options.stripeSecretKey` | `string?` | Explicit Stripe key
|
|
123
|
+
| `options.apiVersion` | `string?` | Direct Stripe API version override. Defaults to `2026-04-22.dahlia`. |
|
|
124
|
+
| `options.stripeSecretKey` | `string?` | Explicit Stripe key override for direct Stripe operations. |
|
|
124
125
|
|
|
125
126
|
### `flopay.checkout.sessions`
|
|
126
127
|
|
package/dist/index.cjs
CHANGED
|
@@ -30,13 +30,15 @@ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: tru
|
|
|
30
30
|
// src/index.ts
|
|
31
31
|
var index_exports = {};
|
|
32
32
|
__export(index_exports, {
|
|
33
|
-
FloPay: () => FloPay
|
|
33
|
+
FloPay: () => FloPay,
|
|
34
|
+
STRIPE_API_VERSION: () => STRIPE_API_VERSION
|
|
34
35
|
});
|
|
35
36
|
module.exports = __toCommonJS(index_exports);
|
|
36
37
|
|
|
37
38
|
// src/flopay-node.ts
|
|
38
39
|
var import_stripe = __toESM(require("stripe"), 1);
|
|
39
40
|
var import_shared = require("@flopay/shared");
|
|
41
|
+
var STRIPE_API_VERSION = "2026-04-22.dahlia";
|
|
40
42
|
var FloPay = class {
|
|
41
43
|
constructor(secretKey, options) {
|
|
42
44
|
if (!secretKey) {
|
|
@@ -45,8 +47,8 @@ var FloPay = class {
|
|
|
45
47
|
"authentication_error"
|
|
46
48
|
);
|
|
47
49
|
}
|
|
48
|
-
this.stripe = new import_stripe.default(secretKey, {
|
|
49
|
-
apiVersion:
|
|
50
|
+
this.stripe = new import_stripe.default(options?.stripeSecretKey ?? secretKey, {
|
|
51
|
+
apiVersion: options?.apiVersion ?? STRIPE_API_VERSION,
|
|
50
52
|
appInfo: {
|
|
51
53
|
name: "flopay-node",
|
|
52
54
|
version: import_shared.SDK_VERSION
|
|
@@ -255,6 +257,7 @@ var FloPay = class {
|
|
|
255
257
|
};
|
|
256
258
|
// Annotate the CommonJS export names for ESM import in node:
|
|
257
259
|
0 && (module.exports = {
|
|
258
|
-
FloPay
|
|
260
|
+
FloPay,
|
|
261
|
+
STRIPE_API_VERSION
|
|
259
262
|
});
|
|
260
263
|
//# sourceMappingURL=index.cjs.map
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/flopay-node.ts"],"sourcesContent":["export { FloPay } from './flopay-node.js';\nexport type { FloPayNodeOptions } from './flopay-node.js';\n","import Stripe from 'stripe';\nimport type {\n CheckoutSession,\n LineItem,\n CreateSessionParams,\n CheckoutSessionResult,\n CreateCustomerParams,\n UpdateCustomerParams,\n WebhookEvent,\n Customer,\n} from '@flopay/shared';\nimport { FloPayError, SDK_VERSION } from '@flopay/shared';\n\n/** Options for the FloPay Node SDK constructor. */\nexport interface FloPayNodeOptions {\n apiVersion?: string;\n /** Stripe secret key, required when using Stripe-specific operations. */\n stripeSecretKey?: string;\n}\n\n/**\n * Server-side FloPay SDK.\n *\n * Supports two modes of operation:\n *\n * 1. **Billing API mode** — Creates checkout sessions via the FloPay/ClickTech\n * billing API (`POST /v1/checkouts/sessions`). This mirrors the\n * `createCheckoutSession` function from `clicktech-core-ui`.\n *\n * 2. **Stripe direct mode** — When a `stripeSecretKey` is provided, also\n * exposes direct Stripe operations (customers, webhooks).\n *\n * @example\n * ```ts\n * import { FloPay } from '@flopay/node';\n *\n * const flopay = new FloPay('sk_test_...');\n *\n * // Create session via billing API\n * const result = await flopay.checkout.sessions.create({\n * billingApiUrl: 'https://billing.example.com',\n * checkoutBaseUrl: 'https://checkout.example.com',\n * clientId: 'client_123',\n * items: [{ providerItemId: 'prod_abc', totalAmount: 49.99 }],\n * account: { userId: 'user_1', email: 'user@example.com' },\n * successUrl: '/success',\n * cancelUrl: '/cancel',\n * });\n * ```\n */\nexport class FloPay {\n private readonly stripe: Stripe;\n\n readonly checkout: {\n sessions: {\n /** Create a checkout session via the billing API. */\n create: (params: CreateSessionParams) => Promise<CheckoutSessionResult>;\n /** Retrieve a checkout session from Stripe. */\n retrieve: (id: string) => Promise<CheckoutSession>;\n /** Expire a checkout session on Stripe. */\n expire: (id: string) => Promise<CheckoutSession>;\n /** List line items for a Stripe checkout session. */\n listLineItems: (id: string) => Promise<LineItem[]>;\n };\n };\n\n readonly webhooks: {\n constructEvent: (\n payload: string | Buffer,\n signature: string,\n secret: string,\n ) => WebhookEvent;\n };\n\n readonly customers: {\n create: (params: CreateCustomerParams) => Promise<Customer>;\n retrieve: (id: string) => Promise<Customer>;\n update: (id: string, params: UpdateCustomerParams) => Promise<Customer>;\n };\n\n constructor(secretKey: string, options?: FloPayNodeOptions) {\n if (!secretKey) {\n throw new FloPayError(\n 'A secret key is required to initialize the FloPay server SDK.',\n 'authentication_error',\n );\n }\n\n this.stripe = new Stripe(secretKey, {\n apiVersion: '2025-04-30.basil' as Stripe.LatestApiVersion,\n appInfo: {\n name: 'flopay-node',\n version: SDK_VERSION,\n },\n });\n\n this.checkout = {\n sessions: {\n create: this.createSession.bind(this),\n retrieve: this.retrieveSession.bind(this),\n expire: this.expireSession.bind(this),\n listLineItems: this.listLineItems.bind(this),\n },\n };\n\n this.webhooks = {\n constructEvent: this.constructWebhookEvent.bind(this),\n };\n\n this.customers = {\n create: this.createCustomer.bind(this),\n retrieve: this.retrieveCustomer.bind(this),\n update: this.updateCustomer.bind(this),\n };\n }\n\n /**\n * Create a checkout session via the billing API.\n *\n * Mirrors `createCheckoutSession` from `clicktech-core-ui/modules`.\n * Posts to `{billingApiUrl}/v1/checkouts/sessions` and returns\n * the session UUID for redirect.\n */\n private async createSession(\n params: CreateSessionParams,\n ): Promise<CheckoutSessionResult> {\n const {\n billingApiUrl,\n checkoutBaseUrl,\n items = [],\n subscriptions = [],\n account,\n successUrl,\n cancelUrl,\n checkoutMode = 'confirm',\n couponCodes = [],\n tagsData,\n redirectParams = {},\n timeoutMs = 12000,\n clientId,\n utmMetadata,\n } = params;\n\n const payload: Record<string, unknown> = {\n clientId,\n successUrl,\n cancelUrl,\n checkoutMode,\n items: items.map((item) => ({\n providerItemId: item.providerItemId,\n providerItemName: item.providerItemName ?? null,\n quantity: item.quantity ?? 1,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount ?? null,\n currency: item.currency ?? 'USD',\n })),\n subscriptions: subscriptions.map((sub) => ({\n providerPlanId: sub.providerPlanId,\n providerPlanName: sub.providerPlanName ?? null,\n quantity: sub.quantity ?? 1,\n totalAmount: sub.totalAmount,\n overrideAmount: sub.overrideAmount ?? null,\n currency: sub.currency ?? 'USD',\n })),\n accountData: {\n userId: account.userId,\n firstName: account.firstName ?? null,\n lastName: account.lastName ?? null,\n email: account.email,\n country: account.country ?? null,\n gender: account.gender ?? null,\n city: account.city ?? null,\n state: account.state ?? null,\n zip: account.zip ?? null,\n },\n couponCodes,\n };\n\n if (tagsData) {\n payload['tagsData'] = tagsData;\n }\n\n if (utmMetadata?.length) {\n payload['utmMetadata'] = utmMetadata;\n }\n\n const url = `${billingApiUrl.replace(/\\/+$/, '')}/v1/checkouts/sessions`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let status: number;\n let body: { data?: { uuid?: string } } | undefined;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n status = response.status;\n\n try {\n body = await response.json() as { data?: { uuid?: string } };\n } catch {\n // 204 or empty body\n }\n } finally {\n clearTimeout(timer);\n }\n\n if (status === 201) {\n const uuid = body?.data?.uuid;\n\n if (!uuid) {\n throw new Error('Checkout session created but no UUID was returned by the billing API');\n }\n\n const redirectUrl = new URL(`${checkoutBaseUrl.replace(/\\/+$/, '')}/secure`);\n redirectUrl.searchParams.set('id', uuid);\n\n for (const [key, value] of Object.entries(redirectParams)) {\n redirectUrl.searchParams.set(key, value);\n }\n\n return { status: 201, redirectUrl: redirectUrl.toString() };\n }\n\n if (status === 204) {\n return { status: 204 };\n }\n\n return { status };\n }\n\n private normalizeStripeSession(\n session: Stripe.Checkout.Session,\n ): CheckoutSession {\n const statusMap: Record<string, CheckoutSession['status']> = {\n open: 'open',\n complete: 'complete',\n expired: 'expired',\n };\n\n return {\n id: session.id,\n clientSecret: session.client_secret ?? '',\n mode: session.mode as CheckoutSession['mode'],\n status: statusMap[session.status ?? 'open'] ?? 'open',\n amount: session.amount_total ?? 0,\n currency: session.currency ?? 'usd',\n metadata: (session.metadata as Record<string, string>) ?? {},\n };\n }\n\n private async retrieveSession(id: string): Promise<CheckoutSession> {\n const session = await this.stripe.checkout.sessions.retrieve(id);\n return this.normalizeStripeSession(session);\n }\n\n private async expireSession(id: string): Promise<CheckoutSession> {\n const session = await this.stripe.checkout.sessions.expire(id);\n return this.normalizeStripeSession(session);\n }\n\n private async listLineItems(id: string): Promise<LineItem[]> {\n const items = await this.stripe.checkout.sessions.listLineItems(id);\n return items.data.map((item) => ({\n price: item.price?.id,\n quantity: item.quantity ?? 1,\n }));\n }\n\n private constructWebhookEvent(\n payload: string | Buffer,\n signature: string,\n secret: string,\n ): WebhookEvent {\n const event = this.stripe.webhooks.constructEvent(payload, signature, secret);\n\n return {\n id: event.id,\n type: event.type,\n data: event.data as unknown as Record<string, unknown>,\n created: event.created,\n };\n }\n\n private async createCustomer(params: CreateCustomerParams): Promise<Customer> {\n const customer = await this.stripe.customers.create({\n email: params.email,\n name: params.name,\n metadata: params.metadata,\n });\n\n return {\n id: customer.id,\n email: customer.email ?? params.email,\n firstName: params.name?.split(' ')[0],\n lastName: params.name?.split(' ').slice(1).join(' '),\n };\n }\n\n private async retrieveCustomer(id: string): Promise<Customer> {\n const customer = await this.stripe.customers.retrieve(id);\n\n if (customer.deleted) {\n throw new FloPayError(\n `Customer ${id} has been deleted`,\n 'api_error',\n { code: 'resource_missing' },\n );\n }\n\n return {\n id: customer.id,\n email: customer.email ?? '',\n firstName: customer.name?.split(' ')[0],\n lastName: customer.name?.split(' ').slice(1).join(' '),\n };\n }\n\n private async updateCustomer(\n id: string,\n params: UpdateCustomerParams,\n ): Promise<Customer> {\n const customer = await this.stripe.customers.update(id, {\n email: params.email,\n name: params.name,\n metadata: params.metadata,\n });\n\n return {\n id: customer.id,\n email: customer.email ?? '',\n firstName: customer.name?.split(' ')[0],\n lastName: customer.name?.split(' ').slice(1).join(' '),\n };\n }\n}\n"],"mappings":"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","names":["Stripe"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/flopay-node.ts"],"sourcesContent":["export { FloPay, STRIPE_API_VERSION } from './flopay-node.js';\nexport type { FloPayNodeOptions } from './flopay-node.js';\n","import Stripe from 'stripe';\nimport type {\n CheckoutSession,\n LineItem,\n CreateSessionParams,\n CheckoutSessionResult,\n CreateCustomerParams,\n UpdateCustomerParams,\n WebhookEvent,\n Customer,\n} from '@flopay/shared';\nimport { FloPayError, SDK_VERSION } from '@flopay/shared';\n\nexport const STRIPE_API_VERSION = '2026-04-22.dahlia';\n\ntype StripeConfig = NonNullable<ConstructorParameters<typeof Stripe>[1]>;\n\n/** Options for the FloPay Node SDK constructor. */\nexport interface FloPayNodeOptions {\n apiVersion?: string;\n /** Stripe secret key, required when using Stripe-specific operations. */\n stripeSecretKey?: string;\n}\n\n/**\n * Server-side FloPay SDK.\n *\n * Supports two modes of operation:\n *\n * 1. **Billing API mode** — Creates checkout sessions via the FloPay/ClickTech\n * billing API (`POST /v1/checkouts/sessions`). This mirrors the\n * `createCheckoutSession` function from `clicktech-core-ui`.\n *\n * 2. **Stripe direct mode** — When a `stripeSecretKey` is provided, also\n * exposes direct Stripe operations (customers, webhooks).\n *\n * @example\n * ```ts\n * import { FloPay } from '@flopay/node';\n *\n * const flopay = new FloPay('sk_test_...');\n *\n * // Create session via billing API\n * const result = await flopay.checkout.sessions.create({\n * billingApiUrl: 'https://billing.example.com',\n * checkoutBaseUrl: 'https://checkout.example.com',\n * clientId: 'client_123',\n * items: [{ providerItemId: 'prod_abc', totalAmount: 49.99 }],\n * account: { userId: 'user_1', email: 'user@example.com' },\n * successUrl: '/success',\n * cancelUrl: '/cancel',\n * });\n * ```\n */\nexport class FloPay {\n private readonly stripe: Stripe;\n\n readonly checkout: {\n sessions: {\n /** Create a checkout session via the billing API. */\n create: (params: CreateSessionParams) => Promise<CheckoutSessionResult>;\n /** Retrieve a checkout session from Stripe. */\n retrieve: (id: string) => Promise<CheckoutSession>;\n /** Expire a checkout session on Stripe. */\n expire: (id: string) => Promise<CheckoutSession>;\n /** List line items for a Stripe checkout session. */\n listLineItems: (id: string) => Promise<LineItem[]>;\n };\n };\n\n readonly webhooks: {\n constructEvent: (\n payload: string | Buffer,\n signature: string,\n secret: string,\n ) => WebhookEvent;\n };\n\n readonly customers: {\n create: (params: CreateCustomerParams) => Promise<Customer>;\n retrieve: (id: string) => Promise<Customer>;\n update: (id: string, params: UpdateCustomerParams) => Promise<Customer>;\n };\n\n constructor(secretKey: string, options?: FloPayNodeOptions) {\n if (!secretKey) {\n throw new FloPayError(\n 'A secret key is required to initialize the FloPay server SDK.',\n 'authentication_error',\n );\n }\n\n this.stripe = new Stripe(options?.stripeSecretKey ?? secretKey, {\n apiVersion: (options?.apiVersion ?? STRIPE_API_VERSION) as StripeConfig['apiVersion'],\n appInfo: {\n name: 'flopay-node',\n version: SDK_VERSION,\n },\n });\n\n this.checkout = {\n sessions: {\n create: this.createSession.bind(this),\n retrieve: this.retrieveSession.bind(this),\n expire: this.expireSession.bind(this),\n listLineItems: this.listLineItems.bind(this),\n },\n };\n\n this.webhooks = {\n constructEvent: this.constructWebhookEvent.bind(this),\n };\n\n this.customers = {\n create: this.createCustomer.bind(this),\n retrieve: this.retrieveCustomer.bind(this),\n update: this.updateCustomer.bind(this),\n };\n }\n\n /**\n * Create a checkout session via the billing API.\n *\n * Mirrors `createCheckoutSession` from `clicktech-core-ui/modules`.\n * Posts to `{billingApiUrl}/v1/checkouts/sessions` and returns\n * the session UUID for redirect.\n */\n private async createSession(\n params: CreateSessionParams,\n ): Promise<CheckoutSessionResult> {\n const {\n billingApiUrl,\n checkoutBaseUrl,\n items = [],\n subscriptions = [],\n account,\n successUrl,\n cancelUrl,\n checkoutMode = 'confirm',\n couponCodes = [],\n tagsData,\n redirectParams = {},\n timeoutMs = 12000,\n clientId,\n utmMetadata,\n } = params;\n\n const payload: Record<string, unknown> = {\n clientId,\n successUrl,\n cancelUrl,\n checkoutMode,\n items: items.map((item) => ({\n providerItemId: item.providerItemId,\n providerItemName: item.providerItemName ?? null,\n quantity: item.quantity ?? 1,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount ?? null,\n currency: item.currency ?? 'USD',\n })),\n subscriptions: subscriptions.map((sub) => ({\n providerPlanId: sub.providerPlanId,\n providerPlanName: sub.providerPlanName ?? null,\n quantity: sub.quantity ?? 1,\n totalAmount: sub.totalAmount,\n overrideAmount: sub.overrideAmount ?? null,\n currency: sub.currency ?? 'USD',\n })),\n accountData: {\n userId: account.userId,\n firstName: account.firstName ?? null,\n lastName: account.lastName ?? null,\n email: account.email,\n country: account.country ?? null,\n gender: account.gender ?? null,\n city: account.city ?? null,\n state: account.state ?? null,\n zip: account.zip ?? null,\n },\n couponCodes,\n };\n\n if (tagsData) {\n payload['tagsData'] = tagsData;\n }\n\n if (utmMetadata?.length) {\n payload['utmMetadata'] = utmMetadata;\n }\n\n const url = `${billingApiUrl.replace(/\\/+$/, '')}/v1/checkouts/sessions`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let status: number;\n let body: { data?: { uuid?: string } } | undefined;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n status = response.status;\n\n try {\n body = await response.json() as { data?: { uuid?: string } };\n } catch {\n // 204 or empty body\n }\n } finally {\n clearTimeout(timer);\n }\n\n if (status === 201) {\n const uuid = body?.data?.uuid;\n\n if (!uuid) {\n throw new Error('Checkout session created but no UUID was returned by the billing API');\n }\n\n const redirectUrl = new URL(`${checkoutBaseUrl.replace(/\\/+$/, '')}/secure`);\n redirectUrl.searchParams.set('id', uuid);\n\n for (const [key, value] of Object.entries(redirectParams)) {\n redirectUrl.searchParams.set(key, value);\n }\n\n return { status: 201, redirectUrl: redirectUrl.toString() };\n }\n\n if (status === 204) {\n return { status: 204 };\n }\n\n return { status };\n }\n\n private normalizeStripeSession(\n session: Stripe.Checkout.Session,\n ): CheckoutSession {\n const statusMap: Record<string, CheckoutSession['status']> = {\n open: 'open',\n complete: 'complete',\n expired: 'expired',\n };\n\n return {\n id: session.id,\n clientSecret: session.client_secret ?? '',\n mode: session.mode as CheckoutSession['mode'],\n status: statusMap[session.status ?? 'open'] ?? 'open',\n amount: session.amount_total ?? 0,\n currency: session.currency ?? 'usd',\n metadata: (session.metadata as Record<string, string>) ?? {},\n };\n }\n\n private async retrieveSession(id: string): Promise<CheckoutSession> {\n const session = await this.stripe.checkout.sessions.retrieve(id);\n return this.normalizeStripeSession(session);\n }\n\n private async expireSession(id: string): Promise<CheckoutSession> {\n const session = await this.stripe.checkout.sessions.expire(id);\n return this.normalizeStripeSession(session);\n }\n\n private async listLineItems(id: string): Promise<LineItem[]> {\n const items = await this.stripe.checkout.sessions.listLineItems(id);\n return items.data.map((item) => ({\n price: item.price?.id,\n quantity: item.quantity ?? 1,\n }));\n }\n\n private constructWebhookEvent(\n payload: string | Buffer,\n signature: string,\n secret: string,\n ): WebhookEvent {\n const event = this.stripe.webhooks.constructEvent(payload, signature, secret);\n\n return {\n id: event.id,\n type: event.type,\n data: event.data as unknown as Record<string, unknown>,\n created: event.created,\n };\n }\n\n private async createCustomer(params: CreateCustomerParams): Promise<Customer> {\n const customer = await this.stripe.customers.create({\n email: params.email,\n name: params.name,\n metadata: params.metadata,\n });\n\n return {\n id: customer.id,\n email: customer.email ?? params.email,\n firstName: params.name?.split(' ')[0],\n lastName: params.name?.split(' ').slice(1).join(' '),\n };\n }\n\n private async retrieveCustomer(id: string): Promise<Customer> {\n const customer = await this.stripe.customers.retrieve(id);\n\n if (customer.deleted) {\n throw new FloPayError(\n `Customer ${id} has been deleted`,\n 'api_error',\n { code: 'resource_missing' },\n );\n }\n\n return {\n id: customer.id,\n email: customer.email ?? '',\n firstName: customer.name?.split(' ')[0],\n lastName: customer.name?.split(' ').slice(1).join(' '),\n };\n }\n\n private async updateCustomer(\n id: string,\n params: UpdateCustomerParams,\n ): Promise<Customer> {\n const customer = await this.stripe.customers.update(id, {\n email: params.email,\n name: params.name,\n metadata: params.metadata,\n });\n\n return {\n id: customer.id,\n email: customer.email ?? '',\n firstName: customer.name?.split(' ')[0],\n lastName: customer.name?.split(' ').slice(1).join(' '),\n };\n }\n}\n"],"mappings":"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","names":["Stripe"]}
|
package/dist/index.d.cts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CreateSessionParams, CheckoutSessionResult, CheckoutSession, LineItem, WebhookEvent, CreateCustomerParams, Customer, UpdateCustomerParams } from '@flopay/shared';
|
|
2
2
|
|
|
3
|
+
declare const STRIPE_API_VERSION = "2026-04-22.dahlia";
|
|
3
4
|
/** Options for the FloPay Node SDK constructor. */
|
|
4
5
|
interface FloPayNodeOptions {
|
|
5
6
|
apiVersion?: string;
|
|
@@ -77,4 +78,4 @@ declare class FloPay {
|
|
|
77
78
|
private updateCustomer;
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
export { FloPay, type FloPayNodeOptions };
|
|
81
|
+
export { FloPay, type FloPayNodeOptions, STRIPE_API_VERSION };
|
package/dist/index.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { CreateSessionParams, CheckoutSessionResult, CheckoutSession, LineItem, WebhookEvent, CreateCustomerParams, Customer, UpdateCustomerParams } from '@flopay/shared';
|
|
2
2
|
|
|
3
|
+
declare const STRIPE_API_VERSION = "2026-04-22.dahlia";
|
|
3
4
|
/** Options for the FloPay Node SDK constructor. */
|
|
4
5
|
interface FloPayNodeOptions {
|
|
5
6
|
apiVersion?: string;
|
|
@@ -77,4 +78,4 @@ declare class FloPay {
|
|
|
77
78
|
private updateCustomer;
|
|
78
79
|
}
|
|
79
80
|
|
|
80
|
-
export { FloPay, type FloPayNodeOptions };
|
|
81
|
+
export { FloPay, type FloPayNodeOptions, STRIPE_API_VERSION };
|
package/dist/index.mjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
// src/flopay-node.ts
|
|
2
2
|
import Stripe from "stripe";
|
|
3
3
|
import { FloPayError, SDK_VERSION } from "@flopay/shared";
|
|
4
|
+
var STRIPE_API_VERSION = "2026-04-22.dahlia";
|
|
4
5
|
var FloPay = class {
|
|
5
6
|
constructor(secretKey, options) {
|
|
6
7
|
if (!secretKey) {
|
|
@@ -9,8 +10,8 @@ var FloPay = class {
|
|
|
9
10
|
"authentication_error"
|
|
10
11
|
);
|
|
11
12
|
}
|
|
12
|
-
this.stripe = new Stripe(secretKey, {
|
|
13
|
-
apiVersion:
|
|
13
|
+
this.stripe = new Stripe(options?.stripeSecretKey ?? secretKey, {
|
|
14
|
+
apiVersion: options?.apiVersion ?? STRIPE_API_VERSION,
|
|
14
15
|
appInfo: {
|
|
15
16
|
name: "flopay-node",
|
|
16
17
|
version: SDK_VERSION
|
|
@@ -218,6 +219,7 @@ var FloPay = class {
|
|
|
218
219
|
}
|
|
219
220
|
};
|
|
220
221
|
export {
|
|
221
|
-
FloPay
|
|
222
|
+
FloPay,
|
|
223
|
+
STRIPE_API_VERSION
|
|
222
224
|
};
|
|
223
225
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/flopay-node.ts"],"sourcesContent":["import Stripe from 'stripe';\nimport type {\n CheckoutSession,\n LineItem,\n CreateSessionParams,\n CheckoutSessionResult,\n CreateCustomerParams,\n UpdateCustomerParams,\n WebhookEvent,\n Customer,\n} from '@flopay/shared';\nimport { FloPayError, SDK_VERSION } from '@flopay/shared';\n\n/** Options for the FloPay Node SDK constructor. */\nexport interface FloPayNodeOptions {\n apiVersion?: string;\n /** Stripe secret key, required when using Stripe-specific operations. */\n stripeSecretKey?: string;\n}\n\n/**\n * Server-side FloPay SDK.\n *\n * Supports two modes of operation:\n *\n * 1. **Billing API mode** — Creates checkout sessions via the FloPay/ClickTech\n * billing API (`POST /v1/checkouts/sessions`). This mirrors the\n * `createCheckoutSession` function from `clicktech-core-ui`.\n *\n * 2. **Stripe direct mode** — When a `stripeSecretKey` is provided, also\n * exposes direct Stripe operations (customers, webhooks).\n *\n * @example\n * ```ts\n * import { FloPay } from '@flopay/node';\n *\n * const flopay = new FloPay('sk_test_...');\n *\n * // Create session via billing API\n * const result = await flopay.checkout.sessions.create({\n * billingApiUrl: 'https://billing.example.com',\n * checkoutBaseUrl: 'https://checkout.example.com',\n * clientId: 'client_123',\n * items: [{ providerItemId: 'prod_abc', totalAmount: 49.99 }],\n * account: { userId: 'user_1', email: 'user@example.com' },\n * successUrl: '/success',\n * cancelUrl: '/cancel',\n * });\n * ```\n */\nexport class FloPay {\n private readonly stripe: Stripe;\n\n readonly checkout: {\n sessions: {\n /** Create a checkout session via the billing API. */\n create: (params: CreateSessionParams) => Promise<CheckoutSessionResult>;\n /** Retrieve a checkout session from Stripe. */\n retrieve: (id: string) => Promise<CheckoutSession>;\n /** Expire a checkout session on Stripe. */\n expire: (id: string) => Promise<CheckoutSession>;\n /** List line items for a Stripe checkout session. */\n listLineItems: (id: string) => Promise<LineItem[]>;\n };\n };\n\n readonly webhooks: {\n constructEvent: (\n payload: string | Buffer,\n signature: string,\n secret: string,\n ) => WebhookEvent;\n };\n\n readonly customers: {\n create: (params: CreateCustomerParams) => Promise<Customer>;\n retrieve: (id: string) => Promise<Customer>;\n update: (id: string, params: UpdateCustomerParams) => Promise<Customer>;\n };\n\n constructor(secretKey: string, options?: FloPayNodeOptions) {\n if (!secretKey) {\n throw new FloPayError(\n 'A secret key is required to initialize the FloPay server SDK.',\n 'authentication_error',\n );\n }\n\n this.stripe = new Stripe(secretKey, {\n apiVersion: '2025-04-30.basil' as Stripe.LatestApiVersion,\n appInfo: {\n name: 'flopay-node',\n version: SDK_VERSION,\n },\n });\n\n this.checkout = {\n sessions: {\n create: this.createSession.bind(this),\n retrieve: this.retrieveSession.bind(this),\n expire: this.expireSession.bind(this),\n listLineItems: this.listLineItems.bind(this),\n },\n };\n\n this.webhooks = {\n constructEvent: this.constructWebhookEvent.bind(this),\n };\n\n this.customers = {\n create: this.createCustomer.bind(this),\n retrieve: this.retrieveCustomer.bind(this),\n update: this.updateCustomer.bind(this),\n };\n }\n\n /**\n * Create a checkout session via the billing API.\n *\n * Mirrors `createCheckoutSession` from `clicktech-core-ui/modules`.\n * Posts to `{billingApiUrl}/v1/checkouts/sessions` and returns\n * the session UUID for redirect.\n */\n private async createSession(\n params: CreateSessionParams,\n ): Promise<CheckoutSessionResult> {\n const {\n billingApiUrl,\n checkoutBaseUrl,\n items = [],\n subscriptions = [],\n account,\n successUrl,\n cancelUrl,\n checkoutMode = 'confirm',\n couponCodes = [],\n tagsData,\n redirectParams = {},\n timeoutMs = 12000,\n clientId,\n utmMetadata,\n } = params;\n\n const payload: Record<string, unknown> = {\n clientId,\n successUrl,\n cancelUrl,\n checkoutMode,\n items: items.map((item) => ({\n providerItemId: item.providerItemId,\n providerItemName: item.providerItemName ?? null,\n quantity: item.quantity ?? 1,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount ?? null,\n currency: item.currency ?? 'USD',\n })),\n subscriptions: subscriptions.map((sub) => ({\n providerPlanId: sub.providerPlanId,\n providerPlanName: sub.providerPlanName ?? null,\n quantity: sub.quantity ?? 1,\n totalAmount: sub.totalAmount,\n overrideAmount: sub.overrideAmount ?? null,\n currency: sub.currency ?? 'USD',\n })),\n accountData: {\n userId: account.userId,\n firstName: account.firstName ?? null,\n lastName: account.lastName ?? null,\n email: account.email,\n country: account.country ?? null,\n gender: account.gender ?? null,\n city: account.city ?? null,\n state: account.state ?? null,\n zip: account.zip ?? null,\n },\n couponCodes,\n };\n\n if (tagsData) {\n payload['tagsData'] = tagsData;\n }\n\n if (utmMetadata?.length) {\n payload['utmMetadata'] = utmMetadata;\n }\n\n const url = `${billingApiUrl.replace(/\\/+$/, '')}/v1/checkouts/sessions`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let status: number;\n let body: { data?: { uuid?: string } } | undefined;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n status = response.status;\n\n try {\n body = await response.json() as { data?: { uuid?: string } };\n } catch {\n // 204 or empty body\n }\n } finally {\n clearTimeout(timer);\n }\n\n if (status === 201) {\n const uuid = body?.data?.uuid;\n\n if (!uuid) {\n throw new Error('Checkout session created but no UUID was returned by the billing API');\n }\n\n const redirectUrl = new URL(`${checkoutBaseUrl.replace(/\\/+$/, '')}/secure`);\n redirectUrl.searchParams.set('id', uuid);\n\n for (const [key, value] of Object.entries(redirectParams)) {\n redirectUrl.searchParams.set(key, value);\n }\n\n return { status: 201, redirectUrl: redirectUrl.toString() };\n }\n\n if (status === 204) {\n return { status: 204 };\n }\n\n return { status };\n }\n\n private normalizeStripeSession(\n session: Stripe.Checkout.Session,\n ): CheckoutSession {\n const statusMap: Record<string, CheckoutSession['status']> = {\n open: 'open',\n complete: 'complete',\n expired: 'expired',\n };\n\n return {\n id: session.id,\n clientSecret: session.client_secret ?? '',\n mode: session.mode as CheckoutSession['mode'],\n status: statusMap[session.status ?? 'open'] ?? 'open',\n amount: session.amount_total ?? 0,\n currency: session.currency ?? 'usd',\n metadata: (session.metadata as Record<string, string>) ?? {},\n };\n }\n\n private async retrieveSession(id: string): Promise<CheckoutSession> {\n const session = await this.stripe.checkout.sessions.retrieve(id);\n return this.normalizeStripeSession(session);\n }\n\n private async expireSession(id: string): Promise<CheckoutSession> {\n const session = await this.stripe.checkout.sessions.expire(id);\n return this.normalizeStripeSession(session);\n }\n\n private async listLineItems(id: string): Promise<LineItem[]> {\n const items = await this.stripe.checkout.sessions.listLineItems(id);\n return items.data.map((item) => ({\n price: item.price?.id,\n quantity: item.quantity ?? 1,\n }));\n }\n\n private constructWebhookEvent(\n payload: string | Buffer,\n signature: string,\n secret: string,\n ): WebhookEvent {\n const event = this.stripe.webhooks.constructEvent(payload, signature, secret);\n\n return {\n id: event.id,\n type: event.type,\n data: event.data as unknown as Record<string, unknown>,\n created: event.created,\n };\n }\n\n private async createCustomer(params: CreateCustomerParams): Promise<Customer> {\n const customer = await this.stripe.customers.create({\n email: params.email,\n name: params.name,\n metadata: params.metadata,\n });\n\n return {\n id: customer.id,\n email: customer.email ?? params.email,\n firstName: params.name?.split(' ')[0],\n lastName: params.name?.split(' ').slice(1).join(' '),\n };\n }\n\n private async retrieveCustomer(id: string): Promise<Customer> {\n const customer = await this.stripe.customers.retrieve(id);\n\n if (customer.deleted) {\n throw new FloPayError(\n `Customer ${id} has been deleted`,\n 'api_error',\n { code: 'resource_missing' },\n );\n }\n\n return {\n id: customer.id,\n email: customer.email ?? '',\n firstName: customer.name?.split(' ')[0],\n lastName: customer.name?.split(' ').slice(1).join(' '),\n };\n }\n\n private async updateCustomer(\n id: string,\n params: UpdateCustomerParams,\n ): Promise<Customer> {\n const customer = await this.stripe.customers.update(id, {\n email: params.email,\n name: params.name,\n metadata: params.metadata,\n });\n\n return {\n id: customer.id,\n email: customer.email ?? '',\n firstName: customer.name?.split(' ')[0],\n lastName: customer.name?.split(' ').slice(1).join(' '),\n };\n }\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/flopay-node.ts"],"sourcesContent":["import Stripe from 'stripe';\nimport type {\n CheckoutSession,\n LineItem,\n CreateSessionParams,\n CheckoutSessionResult,\n CreateCustomerParams,\n UpdateCustomerParams,\n WebhookEvent,\n Customer,\n} from '@flopay/shared';\nimport { FloPayError, SDK_VERSION } from '@flopay/shared';\n\nexport const STRIPE_API_VERSION = '2026-04-22.dahlia';\n\ntype StripeConfig = NonNullable<ConstructorParameters<typeof Stripe>[1]>;\n\n/** Options for the FloPay Node SDK constructor. */\nexport interface FloPayNodeOptions {\n apiVersion?: string;\n /** Stripe secret key, required when using Stripe-specific operations. */\n stripeSecretKey?: string;\n}\n\n/**\n * Server-side FloPay SDK.\n *\n * Supports two modes of operation:\n *\n * 1. **Billing API mode** — Creates checkout sessions via the FloPay/ClickTech\n * billing API (`POST /v1/checkouts/sessions`). This mirrors the\n * `createCheckoutSession` function from `clicktech-core-ui`.\n *\n * 2. **Stripe direct mode** — When a `stripeSecretKey` is provided, also\n * exposes direct Stripe operations (customers, webhooks).\n *\n * @example\n * ```ts\n * import { FloPay } from '@flopay/node';\n *\n * const flopay = new FloPay('sk_test_...');\n *\n * // Create session via billing API\n * const result = await flopay.checkout.sessions.create({\n * billingApiUrl: 'https://billing.example.com',\n * checkoutBaseUrl: 'https://checkout.example.com',\n * clientId: 'client_123',\n * items: [{ providerItemId: 'prod_abc', totalAmount: 49.99 }],\n * account: { userId: 'user_1', email: 'user@example.com' },\n * successUrl: '/success',\n * cancelUrl: '/cancel',\n * });\n * ```\n */\nexport class FloPay {\n private readonly stripe: Stripe;\n\n readonly checkout: {\n sessions: {\n /** Create a checkout session via the billing API. */\n create: (params: CreateSessionParams) => Promise<CheckoutSessionResult>;\n /** Retrieve a checkout session from Stripe. */\n retrieve: (id: string) => Promise<CheckoutSession>;\n /** Expire a checkout session on Stripe. */\n expire: (id: string) => Promise<CheckoutSession>;\n /** List line items for a Stripe checkout session. */\n listLineItems: (id: string) => Promise<LineItem[]>;\n };\n };\n\n readonly webhooks: {\n constructEvent: (\n payload: string | Buffer,\n signature: string,\n secret: string,\n ) => WebhookEvent;\n };\n\n readonly customers: {\n create: (params: CreateCustomerParams) => Promise<Customer>;\n retrieve: (id: string) => Promise<Customer>;\n update: (id: string, params: UpdateCustomerParams) => Promise<Customer>;\n };\n\n constructor(secretKey: string, options?: FloPayNodeOptions) {\n if (!secretKey) {\n throw new FloPayError(\n 'A secret key is required to initialize the FloPay server SDK.',\n 'authentication_error',\n );\n }\n\n this.stripe = new Stripe(options?.stripeSecretKey ?? secretKey, {\n apiVersion: (options?.apiVersion ?? STRIPE_API_VERSION) as StripeConfig['apiVersion'],\n appInfo: {\n name: 'flopay-node',\n version: SDK_VERSION,\n },\n });\n\n this.checkout = {\n sessions: {\n create: this.createSession.bind(this),\n retrieve: this.retrieveSession.bind(this),\n expire: this.expireSession.bind(this),\n listLineItems: this.listLineItems.bind(this),\n },\n };\n\n this.webhooks = {\n constructEvent: this.constructWebhookEvent.bind(this),\n };\n\n this.customers = {\n create: this.createCustomer.bind(this),\n retrieve: this.retrieveCustomer.bind(this),\n update: this.updateCustomer.bind(this),\n };\n }\n\n /**\n * Create a checkout session via the billing API.\n *\n * Mirrors `createCheckoutSession` from `clicktech-core-ui/modules`.\n * Posts to `{billingApiUrl}/v1/checkouts/sessions` and returns\n * the session UUID for redirect.\n */\n private async createSession(\n params: CreateSessionParams,\n ): Promise<CheckoutSessionResult> {\n const {\n billingApiUrl,\n checkoutBaseUrl,\n items = [],\n subscriptions = [],\n account,\n successUrl,\n cancelUrl,\n checkoutMode = 'confirm',\n couponCodes = [],\n tagsData,\n redirectParams = {},\n timeoutMs = 12000,\n clientId,\n utmMetadata,\n } = params;\n\n const payload: Record<string, unknown> = {\n clientId,\n successUrl,\n cancelUrl,\n checkoutMode,\n items: items.map((item) => ({\n providerItemId: item.providerItemId,\n providerItemName: item.providerItemName ?? null,\n quantity: item.quantity ?? 1,\n totalAmount: item.totalAmount,\n overrideAmount: item.overrideAmount ?? null,\n currency: item.currency ?? 'USD',\n })),\n subscriptions: subscriptions.map((sub) => ({\n providerPlanId: sub.providerPlanId,\n providerPlanName: sub.providerPlanName ?? null,\n quantity: sub.quantity ?? 1,\n totalAmount: sub.totalAmount,\n overrideAmount: sub.overrideAmount ?? null,\n currency: sub.currency ?? 'USD',\n })),\n accountData: {\n userId: account.userId,\n firstName: account.firstName ?? null,\n lastName: account.lastName ?? null,\n email: account.email,\n country: account.country ?? null,\n gender: account.gender ?? null,\n city: account.city ?? null,\n state: account.state ?? null,\n zip: account.zip ?? null,\n },\n couponCodes,\n };\n\n if (tagsData) {\n payload['tagsData'] = tagsData;\n }\n\n if (utmMetadata?.length) {\n payload['utmMetadata'] = utmMetadata;\n }\n\n const url = `${billingApiUrl.replace(/\\/+$/, '')}/v1/checkouts/sessions`;\n const controller = new AbortController();\n const timer = setTimeout(() => controller.abort(), timeoutMs);\n\n let status: number;\n let body: { data?: { uuid?: string } } | undefined;\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(payload),\n signal: controller.signal,\n });\n\n status = response.status;\n\n try {\n body = await response.json() as { data?: { uuid?: string } };\n } catch {\n // 204 or empty body\n }\n } finally {\n clearTimeout(timer);\n }\n\n if (status === 201) {\n const uuid = body?.data?.uuid;\n\n if (!uuid) {\n throw new Error('Checkout session created but no UUID was returned by the billing API');\n }\n\n const redirectUrl = new URL(`${checkoutBaseUrl.replace(/\\/+$/, '')}/secure`);\n redirectUrl.searchParams.set('id', uuid);\n\n for (const [key, value] of Object.entries(redirectParams)) {\n redirectUrl.searchParams.set(key, value);\n }\n\n return { status: 201, redirectUrl: redirectUrl.toString() };\n }\n\n if (status === 204) {\n return { status: 204 };\n }\n\n return { status };\n }\n\n private normalizeStripeSession(\n session: Stripe.Checkout.Session,\n ): CheckoutSession {\n const statusMap: Record<string, CheckoutSession['status']> = {\n open: 'open',\n complete: 'complete',\n expired: 'expired',\n };\n\n return {\n id: session.id,\n clientSecret: session.client_secret ?? '',\n mode: session.mode as CheckoutSession['mode'],\n status: statusMap[session.status ?? 'open'] ?? 'open',\n amount: session.amount_total ?? 0,\n currency: session.currency ?? 'usd',\n metadata: (session.metadata as Record<string, string>) ?? {},\n };\n }\n\n private async retrieveSession(id: string): Promise<CheckoutSession> {\n const session = await this.stripe.checkout.sessions.retrieve(id);\n return this.normalizeStripeSession(session);\n }\n\n private async expireSession(id: string): Promise<CheckoutSession> {\n const session = await this.stripe.checkout.sessions.expire(id);\n return this.normalizeStripeSession(session);\n }\n\n private async listLineItems(id: string): Promise<LineItem[]> {\n const items = await this.stripe.checkout.sessions.listLineItems(id);\n return items.data.map((item) => ({\n price: item.price?.id,\n quantity: item.quantity ?? 1,\n }));\n }\n\n private constructWebhookEvent(\n payload: string | Buffer,\n signature: string,\n secret: string,\n ): WebhookEvent {\n const event = this.stripe.webhooks.constructEvent(payload, signature, secret);\n\n return {\n id: event.id,\n type: event.type,\n data: event.data as unknown as Record<string, unknown>,\n created: event.created,\n };\n }\n\n private async createCustomer(params: CreateCustomerParams): Promise<Customer> {\n const customer = await this.stripe.customers.create({\n email: params.email,\n name: params.name,\n metadata: params.metadata,\n });\n\n return {\n id: customer.id,\n email: customer.email ?? params.email,\n firstName: params.name?.split(' ')[0],\n lastName: params.name?.split(' ').slice(1).join(' '),\n };\n }\n\n private async retrieveCustomer(id: string): Promise<Customer> {\n const customer = await this.stripe.customers.retrieve(id);\n\n if (customer.deleted) {\n throw new FloPayError(\n `Customer ${id} has been deleted`,\n 'api_error',\n { code: 'resource_missing' },\n );\n }\n\n return {\n id: customer.id,\n email: customer.email ?? '',\n firstName: customer.name?.split(' ')[0],\n lastName: customer.name?.split(' ').slice(1).join(' '),\n };\n }\n\n private async updateCustomer(\n id: string,\n params: UpdateCustomerParams,\n ): Promise<Customer> {\n const customer = await this.stripe.customers.update(id, {\n email: params.email,\n name: params.name,\n metadata: params.metadata,\n });\n\n return {\n id: customer.id,\n email: customer.email ?? '',\n firstName: customer.name?.split(' ')[0],\n lastName: customer.name?.split(' ').slice(1).join(' '),\n };\n }\n}\n"],"mappings":"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","names":[]}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@flopay/node",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "1.0.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"registry": "https://registry.npmjs.org/",
|
|
7
|
-
"access": "
|
|
7
|
+
"access": "public"
|
|
8
8
|
},
|
|
9
9
|
"repository": {
|
|
10
10
|
"type": "git",
|
|
@@ -25,11 +25,11 @@
|
|
|
25
25
|
"dist"
|
|
26
26
|
],
|
|
27
27
|
"dependencies": {
|
|
28
|
-
"stripe": "^
|
|
29
|
-
"@flopay/shared": "0.
|
|
28
|
+
"stripe": "^22.1.1",
|
|
29
|
+
"@flopay/shared": "1.0.0"
|
|
30
30
|
},
|
|
31
31
|
"devDependencies": {
|
|
32
|
-
"typescript": "^
|
|
32
|
+
"typescript": "^6.0.3",
|
|
33
33
|
"tsup": "^8.3.0",
|
|
34
34
|
"vitest": "^2.1.0"
|
|
35
35
|
},
|