prettier fix

This commit is contained in:
Danel Kungla
2025-09-19 17:22:36 +03:00
parent efa94b3322
commit 0c2cfe6d18
509 changed files with 17988 additions and 9920 deletions

View File

@@ -6,9 +6,9 @@ Make sure the app installs the `@kit/billing` package before using it.
```json
{
"name": "my-app",
"dependencies": {
"@kit/billing": "*"
}
"name": "my-app",
"dependencies": {
"@kit/billing": "*"
}
}
```
```

View File

@@ -25,21 +25,32 @@ export const LineItemSchema = z
.describe('Unique identifier for the line item. Defined by the Provider.')
.min(1),
name: z
.string().describe('Name of the line item. Displayed to the user.')
.string()
.describe('Name of the line item. Displayed to the user.')
.min(1),
description: z
.string().describe('Description of the line item. Displayed to the user and will replace the auto-generated description inferred' +
' from the line item. This is useful if you want to provide a more detailed description to the user.')
.string()
.describe(
'Description of the line item. Displayed to the user and will replace the auto-generated description inferred' +
' from the line item. This is useful if you want to provide a more detailed description to the user.',
)
.optional(),
cost: z
.number().describe('Cost of the line item. Displayed to the user.')
.number()
.describe('Cost of the line item. Displayed to the user.')
.min(0),
type: LineItemTypeSchema,
unit: z
.string().describe('Unit of the line item. Displayed to the user. Example "seat" or "GB"')
.string()
.describe(
'Unit of the line item. Displayed to the user. Example "seat" or "GB"',
)
.optional(),
setupFee: z
.number().describe(`Lemon Squeezy only: If true, in addition to the cost, a setup fee will be charged.`)
.number()
.describe(
`Lemon Squeezy only: If true, in addition to the cost, a setup fee will be charged.`,
)
.positive()
.optional(),
tiers: z
@@ -78,10 +89,12 @@ export const LineItemSchema = z
export const PlanSchema = z
.object({
id: z
.string().describe('Unique identifier for the plan. Defined by yourself.')
.string()
.describe('Unique identifier for the plan. Defined by yourself.')
.min(1),
name: z
.string().describe('Name of the plan. Displayed to the user.')
.string()
.describe('Name of the plan. Displayed to the user.')
.min(1),
interval: BillingIntervalSchema.optional(),
custom: z.boolean().default(false).optional(),
@@ -106,7 +119,10 @@ export const PlanSchema = z
},
),
trialDays: z
.number().describe('Number of days for the trial period. Leave empty for no trial.')
.number()
.describe(
'Number of days for the trial period. Leave empty for no trial.',
)
.positive()
.optional(),
paymentType: PaymentTypeSchema,
@@ -188,34 +204,43 @@ export const PlanSchema = z
const ProductSchema = z
.object({
id: z
.string().describe('Unique identifier for the product. Defined by th Provider.')
.string()
.describe('Unique identifier for the product. Defined by th Provider.')
.min(1),
name: z
.string().describe('Name of the product. Displayed to the user.')
.string()
.describe('Name of the product. Displayed to the user.')
.min(1),
description: z
.string().describe('Description of the product. Displayed to the user.')
.string()
.describe('Description of the product. Displayed to the user.')
.min(1),
currency: z
.string().describe('Currency code for the product. Displayed to the user.')
.string()
.describe('Currency code for the product. Displayed to the user.')
.min(3)
.max(3),
badge: z
.string().describe('Badge for the product. Displayed to the user. Example: "Popular"')
.string()
.describe(
'Badge for the product. Displayed to the user. Example: "Popular"',
)
.optional(),
features: z
.array(
z.string(),
).describe('Features of the product. Displayed to the user.')
.array(z.string())
.describe('Features of the product. Displayed to the user.')
.nonempty(),
enableDiscountField: z
.boolean().describe('Enable discount field for the product in the checkout.')
.boolean()
.describe('Enable discount field for the product in the checkout.')
.optional(),
highlighted: z
.boolean().describe('Highlight this product. Displayed to the user.')
.boolean()
.describe('Highlight this product. Displayed to the user.')
.optional(),
hidden: z
.boolean().describe('Hide this product from being displayed to users.')
.boolean()
.describe('Hide this product from being displayed to users.')
.optional(),
plans: z.array(PlanSchema),
})

View File

@@ -1,7 +1,11 @@
import { z } from 'zod';
export const ReportBillingUsageSchema = z.object({
id: z.string().describe('The id of the usage record. For Stripe a customer ID, for LS a subscription item ID.'),
id: z
.string()
.describe(
'The id of the usage record. For Stripe a customer ID, for LS a subscription item ID.',
),
eventName: z
.string()
.describe('The name of the event that triggered the usage')

View File

@@ -24,9 +24,7 @@ export interface IHandleWebhookEventParams {
// this method is called when an invoice is paid. We don't have a specific use case for this
// but it's extremely common for credit-based systems
onInvoicePaid: (
subscription: UpsertSubscriptionParams,
) => Promise<unknown>;
onInvoicePaid: (subscription: UpsertSubscriptionParams) => Promise<unknown>;
// generic handler for any event
onEvent?: (data: unknown) => Promise<unknown>;

View File

@@ -1,3 +1,3 @@
# Billing - @kit/billing-gateway
This package is responsible for handling all billing related operations. It is a gateway to the billing service.
This package is responsible for handling all billing related operations. It is a gateway to the billing service.

View File

@@ -107,7 +107,7 @@ function BlurryBackdrop() {
return (
<div
className={
'bg-background/30 fixed left-0 top-0 w-full backdrop-blur-sm' +
'bg-background/30 fixed top-0 left-0 w-full backdrop-blur-sm' +
' !m-0 h-full'
}
/>

View File

@@ -317,7 +317,7 @@ export function PlanPicker(
<div
className={
'flex flex-col gap-y-3 lg:flex-row lg:items-center lg:space-x-4 lg:space-y-0 lg:text-right'
'flex flex-col gap-y-3 lg:flex-row lg:items-center lg:space-y-0 lg:space-x-4 lg:text-right'
}
>
<div>

View File

@@ -2,4 +2,4 @@
This package is responsible for handling all billing related operations using Lemon Squeezy.
Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/billing/lemon-squeezy).
Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/billing/lemon-squeezy).

View File

@@ -1,4 +1,3 @@
# Billing / Montonio - @kit/montonio
This package is responsible for handling all billing related operations using Montonio.

View File

@@ -1,6 +1,5 @@
import { z } from 'zod';
export const MontonioClientEnvSchema = z
.object({
accessKey: z.string().min(1),
});
export const MontonioClientEnvSchema = z.object({
accessKey: z.string().min(1),
});

View File

@@ -1,15 +1,14 @@
import { z } from 'zod';
export const MontonioServerEnvSchema = z
.object({
secretKey: z
.string({
error: `Please provide the variable MONTONIO_SECRET_KEY`,
})
.min(1),
apiUrl: z
.string({
error: `Please provide the variable MONTONIO_API_URL`,
})
.min(1),
});
export const MontonioServerEnvSchema = z.object({
secretKey: z
.string({
error: `Please provide the variable MONTONIO_SECRET_KEY`,
})
.min(1),
apiUrl: z
.string({
error: `Please provide the variable MONTONIO_API_URL`,
})
.min(1),
});

View File

@@ -1,16 +1,19 @@
import jwt from 'jsonwebtoken';
import axios, { AxiosError } from 'axios';
import jwt from 'jsonwebtoken';
import { MontonioClientEnvSchema } from '../schema/montonio-client-env.schema';
import { MontonioServerEnvSchema } from '../schema/montonio-server-env.schema';
const clientEnv = () => MontonioClientEnvSchema.parse({
accessKey: process.env.NEXT_PUBLIC_MONTONIO_ACCESS_KEY,
});
const clientEnv = () =>
MontonioClientEnvSchema.parse({
accessKey: process.env.NEXT_PUBLIC_MONTONIO_ACCESS_KEY,
});
const serverEnv = () => MontonioServerEnvSchema.parse({
apiUrl: process.env.MONTONIO_API_URL,
secretKey: process.env.MONTONIO_SECRET_KEY,
});
const serverEnv = () =>
MontonioServerEnvSchema.parse({
apiUrl: process.env.MONTONIO_API_URL,
secretKey: process.env.MONTONIO_SECRET_KEY,
});
export class MontonioOrderHandlerService {
public async getMontonioPaymentLink({
@@ -45,23 +48,27 @@ export class MontonioOrderHandlerService {
returnUrl,
askAdditionalInfo: false,
merchantReference,
type: "one_time",
type: 'one_time',
};
const token = jwt.sign(params, secretKey, {
algorithm: "HS256",
expiresIn: "10m",
algorithm: 'HS256',
expiresIn: '10m',
});
try {
const { data } = await axios.post(`${apiUrl}/api/payment-links`, { data: token });
const { data } = await axios.post(`${apiUrl}/api/payment-links`, {
data: token,
});
return data.url;
} catch (error) {
if (error instanceof AxiosError) {
console.error(error.response?.data);
}
console.error(`Failed to create payment link, params=${JSON.stringify(params)}`, error);
throw new Error("Failed to create payment link");
console.error(
`Failed to create payment link, params=${JSON.stringify(params)}`,
error,
);
throw new Error('Failed to create payment link');
}
}
}

View File

@@ -1,7 +1,12 @@
import type { BillingWebhookHandlerService, IHandleWebhookEventParams } from '@kit/billing';
import jwt from 'jsonwebtoken';
import type {
BillingWebhookHandlerService,
IHandleWebhookEventParams,
} from '@kit/billing';
import { getLogger } from '@kit/shared/logger';
import { Database, Enums } from '@kit/supabase/database';
import jwt from 'jsonwebtoken';
import { MontonioServerEnvSchema } from '../schema/montonio-server-env.schema';
type UpsertOrderParams =
@@ -10,20 +15,26 @@ type UpsertOrderParams =
type BillingProvider = Enums<{ schema: 'medreport' }, 'billing_provider'>;
interface MontonioOrderToken {
uuid: string;
accessKey: string;
merchantReference: string;
merchantReferenceDisplay: string;
paymentStatus: 'PAID' | 'FAILED' | 'CANCELLED' | 'PENDING' | 'EXPIRED' | 'REFUNDED';
paymentMethod: string;
grandTotal: number;
currency: string;
senderIban?: string;
senderName?: string;
paymentProviderName?: string;
paymentLinkUuid: string;
iat: number;
exp: number;
uuid: string;
accessKey: string;
merchantReference: string;
merchantReferenceDisplay: string;
paymentStatus:
| 'PAID'
| 'FAILED'
| 'CANCELLED'
| 'PENDING'
| 'EXPIRED'
| 'REFUNDED';
paymentMethod: string;
grandTotal: number;
currency: string;
senderIban?: string;
senderName?: string;
paymentProviderName?: string;
paymentLinkUuid: string;
iat: number;
exp: number;
}
const { secretKey } = MontonioServerEnvSchema.parse({
@@ -39,22 +50,25 @@ export class MontonioWebhookHandlerService
async verifyWebhookSignature(request: Request) {
const logger = await getLogger();
let token: string;
try {
const url = new URL(request.url);
const searchParams = url.searchParams;
console.info("searchParams", searchParams, url);
console.info('searchParams', searchParams, url);
const tokenParam = searchParams.get('order-token') as string | null;
if (!tokenParam) {
throw new Error('Missing order-token');
}
token = tokenParam;
} catch (error) {
logger.error({
error,
name: this.namespace,
}, `Failed to parse Montonio webhook request`);
logger.error(
{
error,
name: this.namespace,
},
`Failed to parse Montonio webhook request`,
);
throw new Error('Invalid request');
}
@@ -64,24 +78,30 @@ export class MontonioWebhookHandlerService
});
return decoded as MontonioOrderToken;
} catch (error) {
logger.error({
error,
name: this.namespace,
}, `Failed to verify Montonio webhook signature`);
logger.error(
{
error,
name: this.namespace,
},
`Failed to verify Montonio webhook signature`,
);
throw new Error('Invalid signature');
}
}
async handleWebhookEvent(
event: MontonioOrderToken,
params: IHandleWebhookEventParams
params: IHandleWebhookEventParams,
) {
const logger = await getLogger();
logger.info({
name: this.namespace,
event,
}, `Received Montonio webhook event`);
logger.info(
{
name: this.namespace,
event,
},
`Received Montonio webhook event`,
);
if (event.paymentStatus === 'PAID') {
const [accountId] = event.merchantReferenceDisplay.split(':');
@@ -101,11 +121,13 @@ export class MontonioWebhookHandlerService
return params.onCheckoutSessionCompleted(order);
}
if (event.paymentStatus === 'FAILED' || event.paymentStatus === 'CANCELLED') {
if (
event.paymentStatus === 'FAILED' ||
event.paymentStatus === 'CANCELLED'
) {
return params.onPaymentFailed(event.uuid);
}
return;
}
}

View File

@@ -2,4 +2,4 @@
This package is responsible for handling all billing related operations using Stripe.
Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/billing/stripe).
Please refer to the [documentation](https://makerkit.dev/docs/next-supabase-turbo/billing/stripe).