mirror of
https://github.com/vercel/commerce.git
synced 2025-04-28 13:57:50 +00:00
chore: setting up rapyd api stuff
This commit is contained in:
parent
3e8d97331d
commit
5f4b245ea7
36
app/actions/checkout.ts
Normal file
36
app/actions/checkout.ts
Normal file
@ -0,0 +1,36 @@
|
|||||||
|
"use server";
|
||||||
|
|
||||||
|
import {
|
||||||
|
createCheckout,
|
||||||
|
type CreateCheckoutParams,
|
||||||
|
} from "@/lib/rapyd/checkout";
|
||||||
|
import { z } from "zod";
|
||||||
|
|
||||||
|
const checkoutSchema = z.object({
|
||||||
|
amount: z.number().positive(),
|
||||||
|
merchantReferenceId: z.string(),
|
||||||
|
completeCheckoutUrl: z.string().url(),
|
||||||
|
cancelCheckoutUrl: z.string().url(),
|
||||||
|
description: z.string().optional(),
|
||||||
|
});
|
||||||
|
|
||||||
|
export const createCheckoutAction = async (data: CreateCheckoutParams) => {
|
||||||
|
try {
|
||||||
|
// Validate input
|
||||||
|
const validatedData = checkoutSchema.parse(data);
|
||||||
|
|
||||||
|
// Create checkout
|
||||||
|
const checkout = await createCheckout(validatedData);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
data: checkout,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
console.error("Checkout creation failed:", error);
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
error: error instanceof Error ? error.message : "Unknown error occurred",
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
48
app/components/checkout-button.tsx
Normal file
48
app/components/checkout-button.tsx
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
"use client";
|
||||||
|
|
||||||
|
import { createCheckoutAction } from "@/app/actions/checkout";
|
||||||
|
import { Button } from "@/components/ui/button";
|
||||||
|
import { useRouter } from "next/navigation";
|
||||||
|
import { useTransition } from "react";
|
||||||
|
import { toast } from "sonner";
|
||||||
|
|
||||||
|
interface CheckoutButtonProps {
|
||||||
|
amount: number;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const CheckoutButton = ({
|
||||||
|
amount,
|
||||||
|
description,
|
||||||
|
}: CheckoutButtonProps) => {
|
||||||
|
const [isPending, startTransition] = useTransition();
|
||||||
|
const router = useRouter();
|
||||||
|
|
||||||
|
const handleCheckout = () => {
|
||||||
|
startTransition(async () => {
|
||||||
|
const merchantReferenceId = crypto.randomUUID();
|
||||||
|
|
||||||
|
const result = await createCheckoutAction({
|
||||||
|
amount,
|
||||||
|
merchantReferenceId,
|
||||||
|
completeCheckoutUrl: `${window.location.origin}/checkout/complete`,
|
||||||
|
cancelCheckoutUrl: `${window.location.origin}/checkout/cancel`,
|
||||||
|
description,
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!result.success) {
|
||||||
|
toast.error("Failed to create checkout session");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirect to Rapyd checkout page
|
||||||
|
router.push(result.data.redirect_url);
|
||||||
|
});
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<Button onClick={handleCheckout} disabled={isPending}>
|
||||||
|
{isPending ? "Creating checkout..." : "Proceed to Checkout"}
|
||||||
|
</Button>
|
||||||
|
);
|
||||||
|
};
|
69
lib/rapyd/checkout.ts
Normal file
69
lib/rapyd/checkout.ts
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
import { makeRequest } from "@/lib/rapyd/utilities";
|
||||||
|
import { cache } from "react";
|
||||||
|
import "server-only";
|
||||||
|
|
||||||
|
// Icelandic card payment methods
|
||||||
|
const ICELANDIC_PAYMENT_METHODS = [
|
||||||
|
"is_visa_card",
|
||||||
|
"is_mastercard_card",
|
||||||
|
] as const;
|
||||||
|
|
||||||
|
interface CheckoutResponse {
|
||||||
|
id: string;
|
||||||
|
redirect_url: string;
|
||||||
|
status: string;
|
||||||
|
payment: {
|
||||||
|
id: string;
|
||||||
|
amount: number;
|
||||||
|
currency: string;
|
||||||
|
status: string;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
interface CreateCheckoutParams {
|
||||||
|
amount: number;
|
||||||
|
merchantReferenceId: string;
|
||||||
|
completeCheckoutUrl: string;
|
||||||
|
cancelCheckoutUrl: string;
|
||||||
|
description?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const DEFAULT_CHECKOUT_CONFIG = {
|
||||||
|
country: "IS",
|
||||||
|
currency: "ISK",
|
||||||
|
} as const;
|
||||||
|
|
||||||
|
export const preloadCheckout = (params: CreateCheckoutParams) => {
|
||||||
|
void createCheckout(params);
|
||||||
|
};
|
||||||
|
|
||||||
|
export const createCheckout = cache(
|
||||||
|
async ({
|
||||||
|
amount,
|
||||||
|
merchantReferenceId,
|
||||||
|
completeCheckoutUrl,
|
||||||
|
cancelCheckoutUrl,
|
||||||
|
description,
|
||||||
|
}: CreateCheckoutParams): Promise<CheckoutResponse> => {
|
||||||
|
const checkoutBody = {
|
||||||
|
amount,
|
||||||
|
merchant_reference_id: merchantReferenceId,
|
||||||
|
complete_checkout_url: completeCheckoutUrl,
|
||||||
|
cancel_checkout_url: cancelCheckoutUrl,
|
||||||
|
country: DEFAULT_CHECKOUT_CONFIG.country,
|
||||||
|
currency: DEFAULT_CHECKOUT_CONFIG.currency,
|
||||||
|
payment_method_types_include: ICELANDIC_PAYMENT_METHODS,
|
||||||
|
...(description && { description }),
|
||||||
|
};
|
||||||
|
|
||||||
|
const response = await makeRequest({
|
||||||
|
method: "post",
|
||||||
|
path: "/v1/checkout",
|
||||||
|
body: checkoutBody,
|
||||||
|
});
|
||||||
|
|
||||||
|
return response as CheckoutResponse;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
export type { CheckoutResponse, CreateCheckoutParams };
|
147
lib/rapyd/utilities.ts
Normal file
147
lib/rapyd/utilities.ts
Normal file
@ -0,0 +1,147 @@
|
|||||||
|
import crypto from "crypto";
|
||||||
|
|
||||||
|
const BASE_URL = process.env.RAPYD_BASE_URL;
|
||||||
|
const SECRET_KEY = process.env.RAPYD_SECRET_KEY;
|
||||||
|
const ACCESS_KEY = process.env.RAPYD_ACCESS_KEY;
|
||||||
|
|
||||||
|
if (!SECRET_KEY || !ACCESS_KEY) {
|
||||||
|
throw new Error("RAPYD_SECRET_KEY and RAPYD_ACCESS_KEY must be set");
|
||||||
|
}
|
||||||
|
|
||||||
|
type HttpMethod = "get" | "put" | "post" | "delete";
|
||||||
|
|
||||||
|
interface SignatureHeaders {
|
||||||
|
access_key: string;
|
||||||
|
salt: string;
|
||||||
|
timestamp: string;
|
||||||
|
signature: string;
|
||||||
|
idempotency: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
interface RequestConfig {
|
||||||
|
method: HttpMethod;
|
||||||
|
path: string;
|
||||||
|
body?: Record<string, unknown>;
|
||||||
|
}
|
||||||
|
|
||||||
|
const generateSalt = (length = 12): string => {
|
||||||
|
const characters =
|
||||||
|
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
||||||
|
return Array.from(
|
||||||
|
{ length },
|
||||||
|
() => characters[Math.floor(Math.random() * characters.length)]
|
||||||
|
).join("");
|
||||||
|
};
|
||||||
|
|
||||||
|
const getUnixTime = ({
|
||||||
|
days = 0,
|
||||||
|
hours = 0,
|
||||||
|
minutes = 0,
|
||||||
|
seconds = 0,
|
||||||
|
} = {}): number => {
|
||||||
|
const now = new Date();
|
||||||
|
now.setDate(now.getDate() + days);
|
||||||
|
now.setHours(now.getHours() + hours);
|
||||||
|
now.setMinutes(now.getMinutes() + minutes);
|
||||||
|
now.setSeconds(now.getSeconds() + seconds);
|
||||||
|
return Math.floor(now.getTime() / 1000);
|
||||||
|
};
|
||||||
|
|
||||||
|
const updateTimestampSaltSig = ({
|
||||||
|
method,
|
||||||
|
path,
|
||||||
|
body,
|
||||||
|
}: RequestConfig): {
|
||||||
|
salt: string;
|
||||||
|
timestamp: number;
|
||||||
|
signature: string;
|
||||||
|
} => {
|
||||||
|
const normalizedPath = path.startsWith("http")
|
||||||
|
? path.substring(path.indexOf("/v1"))
|
||||||
|
: path;
|
||||||
|
|
||||||
|
const salt = generateSalt();
|
||||||
|
const timestamp = getUnixTime();
|
||||||
|
const bodyString = body ? JSON.stringify(body) : "";
|
||||||
|
|
||||||
|
const toSign = [
|
||||||
|
method,
|
||||||
|
normalizedPath,
|
||||||
|
salt,
|
||||||
|
timestamp.toString(),
|
||||||
|
ACCESS_KEY,
|
||||||
|
SECRET_KEY,
|
||||||
|
bodyString,
|
||||||
|
].join("");
|
||||||
|
|
||||||
|
const hmac = crypto.createHmac("sha256", SECRET_KEY);
|
||||||
|
hmac.update(toSign);
|
||||||
|
const signature = Buffer.from(hmac.digest("hex")).toString("base64url");
|
||||||
|
|
||||||
|
return { salt, timestamp, signature };
|
||||||
|
};
|
||||||
|
|
||||||
|
const createHeaders = ({
|
||||||
|
method,
|
||||||
|
path,
|
||||||
|
body,
|
||||||
|
}: RequestConfig): {
|
||||||
|
headers: SignatureHeaders;
|
||||||
|
body: string;
|
||||||
|
} => {
|
||||||
|
const { salt, timestamp, signature } = updateTimestampSaltSig({
|
||||||
|
method,
|
||||||
|
path,
|
||||||
|
body,
|
||||||
|
});
|
||||||
|
|
||||||
|
const headers: SignatureHeaders = {
|
||||||
|
access_key: ACCESS_KEY,
|
||||||
|
salt,
|
||||||
|
timestamp: timestamp.toString(),
|
||||||
|
signature,
|
||||||
|
idempotency: `${getUnixTime()}${salt}`,
|
||||||
|
};
|
||||||
|
|
||||||
|
return {
|
||||||
|
headers,
|
||||||
|
body: body ? JSON.stringify(body) : "",
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
const makeRequest = async ({
|
||||||
|
method,
|
||||||
|
path,
|
||||||
|
body,
|
||||||
|
}: RequestConfig): Promise<unknown> => {
|
||||||
|
const { headers, body: stringifiedBody } = createHeaders({
|
||||||
|
method,
|
||||||
|
path,
|
||||||
|
body,
|
||||||
|
});
|
||||||
|
const url = `${BASE_URL}${path}`;
|
||||||
|
|
||||||
|
const requestConfig: RequestInit = {
|
||||||
|
method: method.toUpperCase(),
|
||||||
|
headers: {
|
||||||
|
...headers,
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
if (method !== "get" && stringifiedBody) {
|
||||||
|
requestConfig.body = stringifiedBody;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(url, requestConfig);
|
||||||
|
|
||||||
|
if (!response.ok) {
|
||||||
|
throw new Error(
|
||||||
|
`Request failed: ${response.status} ${response.statusText}`
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return response.json();
|
||||||
|
};
|
||||||
|
|
||||||
|
export { makeRequest, type HttpMethod, type RequestConfig };
|
11
package.json
11
package.json
@ -13,10 +13,11 @@
|
|||||||
"@heroicons/react": "^2.2.0",
|
"@heroicons/react": "^2.2.0",
|
||||||
"clsx": "^2.1.1",
|
"clsx": "^2.1.1",
|
||||||
"geist": "^1.3.1",
|
"geist": "^1.3.1",
|
||||||
"next": "15.2.0-canary.67",
|
"next": "15.3.0-canary.9",
|
||||||
"react": "19.0.0",
|
"react": "19.0.0",
|
||||||
"react-dom": "19.0.0",
|
"react-dom": "19.0.0",
|
||||||
"sonner": "^2.0.1"
|
"sonner": "^2.0.1",
|
||||||
|
"zod": "^3.24.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@tailwindcss/container-queries": "^0.1.1",
|
"@tailwindcss/container-queries": "^0.1.1",
|
||||||
@ -30,5 +31,11 @@
|
|||||||
"prettier-plugin-tailwindcss": "^0.6.11",
|
"prettier-plugin-tailwindcss": "^0.6.11",
|
||||||
"tailwindcss": "^4.0.8",
|
"tailwindcss": "^4.0.8",
|
||||||
"typescript": "5.7.3"
|
"typescript": "5.7.3"
|
||||||
|
},
|
||||||
|
"pnpm": {
|
||||||
|
"overrides": {
|
||||||
|
"@types/react": "19.0.10",
|
||||||
|
"@types/react-dom": "19.0.4"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
102
pnpm-lock.yaml
generated
102
pnpm-lock.yaml
generated
@ -4,6 +4,10 @@ settings:
|
|||||||
autoInstallPeers: true
|
autoInstallPeers: true
|
||||||
excludeLinksFromLockfile: false
|
excludeLinksFromLockfile: false
|
||||||
|
|
||||||
|
overrides:
|
||||||
|
'@types/react': 19.0.10
|
||||||
|
'@types/react-dom': 19.0.4
|
||||||
|
|
||||||
importers:
|
importers:
|
||||||
|
|
||||||
.:
|
.:
|
||||||
@ -19,10 +23,10 @@ importers:
|
|||||||
version: 2.1.1
|
version: 2.1.1
|
||||||
geist:
|
geist:
|
||||||
specifier: ^1.3.1
|
specifier: ^1.3.1
|
||||||
version: 1.3.1(next@15.2.0-canary.67(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
|
version: 1.3.1(next@15.3.0-canary.9(react-dom@19.0.0(react@19.0.0))(react@19.0.0))
|
||||||
next:
|
next:
|
||||||
specifier: 15.2.0-canary.67
|
specifier: 15.3.0-canary.9
|
||||||
version: 15.2.0-canary.67(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 15.3.0-canary.9(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
react:
|
react:
|
||||||
specifier: 19.0.0
|
specifier: 19.0.0
|
||||||
version: 19.0.0
|
version: 19.0.0
|
||||||
@ -32,6 +36,9 @@ importers:
|
|||||||
sonner:
|
sonner:
|
||||||
specifier: ^2.0.1
|
specifier: ^2.0.1
|
||||||
version: 2.0.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
version: 2.0.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
zod:
|
||||||
|
specifier: ^3.24.2
|
||||||
|
version: 3.24.2
|
||||||
devDependencies:
|
devDependencies:
|
||||||
'@tailwindcss/container-queries':
|
'@tailwindcss/container-queries':
|
||||||
specifier: ^0.1.1
|
specifier: ^0.1.1
|
||||||
@ -214,53 +221,53 @@ packages:
|
|||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@next/env@15.2.0-canary.67':
|
'@next/env@15.3.0-canary.9':
|
||||||
resolution: {integrity: sha512-Is8AU8GcBrDoyXTmEKPTM+K87Xb5SA545jkw0E6+51Zb/1sg5MSCH9OmQf2KlvbqSrkiVuQ8UA23pY5+xGFGpw==}
|
resolution: {integrity: sha512-kvABHn6GmJbyf02wozUzrC4evHdVSmc6FYV8I7Q4g3qZW1x64v6ppi3Hw1KEUzKieC1Car/maGT+r3oRalCg4Q==}
|
||||||
|
|
||||||
'@next/swc-darwin-arm64@15.2.0-canary.67':
|
'@next/swc-darwin-arm64@15.3.0-canary.9':
|
||||||
resolution: {integrity: sha512-BNBt0qWhnZR2pSxlofSBsmy5PYRa7/t4txnYH5z41lSs0B9OlhlsYyiokefmiw6EKKLxzT23hmb+ZPtxTCjiFw==}
|
resolution: {integrity: sha512-llJnHJGXQGux7sHJ4t0q5HbMnID+M3+s5ghvYBw79uP4QDkH5XVXRC2oQUwTvEPzHXUhWpB/kf6KUpWmOEI8xQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@next/swc-darwin-x64@15.2.0-canary.67':
|
'@next/swc-darwin-x64@15.3.0-canary.9':
|
||||||
resolution: {integrity: sha512-ZPC0/iL3dhexN+MQ6QOfaOO6y3WMhyxns01KA9mae0V0sp/uC+KwpSbNCVXptjmiZQ9j0Q9TYjqQBQ4KwtBK8Q==}
|
resolution: {integrity: sha512-igGqAeBB/3tJ4XLqbdcuzbgwgdNh9kRp2AFSME/Ok4jyetSPmcQFX43+C6piuMj2gQ06Q6gDWj3qib0MNf5IWw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [darwin]
|
os: [darwin]
|
||||||
|
|
||||||
'@next/swc-linux-arm64-gnu@15.2.0-canary.67':
|
'@next/swc-linux-arm64-gnu@15.3.0-canary.9':
|
||||||
resolution: {integrity: sha512-t+i9tRB0uYj3OoZS2qhPwDrlcf5bRTKQY5GtFwboyCzBLv9KcU1xa3cwXulNxq1soo8wTiWRnhq8CkvUT+Fbvw==}
|
resolution: {integrity: sha512-Ym9FxqbBmQyUjoe2bW7MsDkrYV3sSR8WXCEqJQthETjAqSsG6zwUfL86dMAKe2RUetqlNzWlXDH/+FM9fdPVOw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-linux-arm64-musl@15.2.0-canary.67':
|
'@next/swc-linux-arm64-musl@15.3.0-canary.9':
|
||||||
resolution: {integrity: sha512-9jffwDN4X2ER5eqj16XJHCf4MmRI3QI0L52JLYH9/3OPxD86bDeQlH/+NK3iEu/3X4KX1rDb7cF9uulB9hjfXw==}
|
resolution: {integrity: sha512-aB9umTo1HHcQWRTXffWSrt6wTMvhg+fYbtZ8PR7h28gBrQaYL6Lu8Kg7BQynYEx8Ze42GqVcS0MlwVsTQrpwMw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-linux-x64-gnu@15.2.0-canary.67':
|
'@next/swc-linux-x64-gnu@15.3.0-canary.9':
|
||||||
resolution: {integrity: sha512-pWp5NIAbMLKy6tfZF22tsDC3A9IJm/p+UQf9l906NClYKtMXLYDFmapXVpTUB7fdb9xDOvB+DtAX11nQk5bukw==}
|
resolution: {integrity: sha512-d+tU/H5SaPAuHcxGJ9fiqt0qzXpkOmksu1lF9JQNHd6WKtBnnJMzpYL8onLLYXThrIPaETVSLpBiv1wvwIgwFg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-linux-x64-musl@15.2.0-canary.67':
|
'@next/swc-linux-x64-musl@15.3.0-canary.9':
|
||||||
resolution: {integrity: sha512-RjSu9pEgQuUmkt1FINCCvpV0SHYrLpf7LaF7pZPem1N2lgDySnazt4ag7ZDaWL0XMBiTKGmNxkk185HeST2PSg==}
|
resolution: {integrity: sha512-b+V+36WIopplWQI2/xOIqzuRGCRGTDLVe2luhhtjcwewRqUujktGnphHW5zRcEVD9nNwwPCisxC01XLL3geggg==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [linux]
|
os: [linux]
|
||||||
|
|
||||||
'@next/swc-win32-arm64-msvc@15.2.0-canary.67':
|
'@next/swc-win32-arm64-msvc@15.3.0-canary.9':
|
||||||
resolution: {integrity: sha512-DM+ysK87Q10MkoxgZeFOZsRx4Yt1WtynDVZoogdEjikfxZrMLCEo22O2uFVNh2E0kHCdE89K3dODO9rQz9EjAw==}
|
resolution: {integrity: sha512-6YbKTAP1Z+dnFtEoPQc4NuQ9J3VIN0vc8gHmZHBl5qfBQgF9f4DfBwcTrXMXEKIFVkQN4YMZU83v+2DSzT+7FQ==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [arm64]
|
cpu: [arm64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
|
|
||||||
'@next/swc-win32-x64-msvc@15.2.0-canary.67':
|
'@next/swc-win32-x64-msvc@15.3.0-canary.9':
|
||||||
resolution: {integrity: sha512-gI3Hk/6YrFXMJn018ZjZo832Pxrsj2DpyXbLc9Vxs4wOZ0x3ChVk2yhFA/SJZY7yhdD3vwG9Srdn8gfCuO4xHg==}
|
resolution: {integrity: sha512-Ujf4+i1memQV3Qk0EjY00C4bzumV6jOZze9kCdi4PnpPjzEefTj88CFGR7ACmYgu1qDHOKaZQxR08MALy/yvIw==}
|
||||||
engines: {node: '>= 10'}
|
engines: {node: '>= 10'}
|
||||||
cpu: [x64]
|
cpu: [x64]
|
||||||
os: [win32]
|
os: [win32]
|
||||||
@ -406,7 +413,7 @@ packages:
|
|||||||
'@types/react-dom@19.0.4':
|
'@types/react-dom@19.0.4':
|
||||||
resolution: {integrity: sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==}
|
resolution: {integrity: sha512-4fSQ8vWFkg+TGhePfUzVmat3eC14TXYSsiiDSLI0dVLsrm9gZFABjPy/Qu6TKgl1tq1Bu1yDsuQgY3A3DOjCcg==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
'@types/react': ^19.0.0
|
'@types/react': 19.0.10
|
||||||
|
|
||||||
'@types/react@19.0.10':
|
'@types/react@19.0.10':
|
||||||
resolution: {integrity: sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==}
|
resolution: {integrity: sha512-JuRQ9KXLEjaUNjTWpzuR231Z2WpIwczOkBEIvbHNCzQefFIT0L8IqE6NV6ULLyC1SI/i234JnDoMkfg+RjQj2g==}
|
||||||
@ -553,8 +560,8 @@ packages:
|
|||||||
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
|
|
||||||
next@15.2.0-canary.67:
|
next@15.3.0-canary.9:
|
||||||
resolution: {integrity: sha512-hKZjcmngKiY/HzHXNN0SGXR9Xio6pirraWu8GqRD24pMiGueY0ykxTbOp0SrqgHDsgWGTOxy3hXCriGiyyVb8w==}
|
resolution: {integrity: sha512-R9+FanTpLPN4cez/lJurj/kedcOERPCQebl/F5kevPSzCQzp8Dj/LCv6L10wTqBH3zBgqepp0eytzsVrjW8VjA==}
|
||||||
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
|
engines: {node: ^18.18.0 || ^19.8.0 || >= 20.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@ -724,6 +731,9 @@ packages:
|
|||||||
util-deprecate@1.0.2:
|
util-deprecate@1.0.2:
|
||||||
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
|
||||||
|
|
||||||
|
zod@3.24.2:
|
||||||
|
resolution: {integrity: sha512-lY7CDW43ECgW9u1TcT3IoXHflywfVqDYze4waEz812jR/bZ8FHDsl7pFQoSZTz5N+2NqRXs8GBwnAwo3ZNxqhQ==}
|
||||||
|
|
||||||
snapshots:
|
snapshots:
|
||||||
|
|
||||||
'@alloc/quick-lru@5.2.0': {}
|
'@alloc/quick-lru@5.2.0': {}
|
||||||
@ -846,30 +856,30 @@ snapshots:
|
|||||||
'@img/sharp-win32-x64@0.33.5':
|
'@img/sharp-win32-x64@0.33.5':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/env@15.2.0-canary.67': {}
|
'@next/env@15.3.0-canary.9': {}
|
||||||
|
|
||||||
'@next/swc-darwin-arm64@15.2.0-canary.67':
|
'@next/swc-darwin-arm64@15.3.0-canary.9':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-darwin-x64@15.2.0-canary.67':
|
'@next/swc-darwin-x64@15.3.0-canary.9':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-arm64-gnu@15.2.0-canary.67':
|
'@next/swc-linux-arm64-gnu@15.3.0-canary.9':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-arm64-musl@15.2.0-canary.67':
|
'@next/swc-linux-arm64-musl@15.3.0-canary.9':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-x64-gnu@15.2.0-canary.67':
|
'@next/swc-linux-x64-gnu@15.3.0-canary.9':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-linux-x64-musl@15.2.0-canary.67':
|
'@next/swc-linux-x64-musl@15.3.0-canary.9':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-win32-arm64-msvc@15.2.0-canary.67':
|
'@next/swc-win32-arm64-msvc@15.3.0-canary.9':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@next/swc-win32-x64-msvc@15.2.0-canary.67':
|
'@next/swc-win32-x64-msvc@15.3.0-canary.9':
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
'@react-aria/focus@3.19.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
'@react-aria/focus@3.19.1(react-dom@19.0.0(react@19.0.0))(react@19.0.0)':
|
||||||
@ -1059,9 +1069,9 @@ snapshots:
|
|||||||
graceful-fs: 4.2.11
|
graceful-fs: 4.2.11
|
||||||
tapable: 2.2.1
|
tapable: 2.2.1
|
||||||
|
|
||||||
geist@1.3.1(next@15.2.0-canary.67(react-dom@19.0.0(react@19.0.0))(react@19.0.0)):
|
geist@1.3.1(next@15.3.0-canary.9(react-dom@19.0.0(react@19.0.0))(react@19.0.0)):
|
||||||
dependencies:
|
dependencies:
|
||||||
next: 15.2.0-canary.67(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
next: 15.3.0-canary.9(react-dom@19.0.0(react@19.0.0))(react@19.0.0)
|
||||||
|
|
||||||
graceful-fs@4.2.11: {}
|
graceful-fs@4.2.11: {}
|
||||||
|
|
||||||
@ -1123,9 +1133,9 @@ snapshots:
|
|||||||
|
|
||||||
nanoid@3.3.8: {}
|
nanoid@3.3.8: {}
|
||||||
|
|
||||||
next@15.2.0-canary.67(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
next@15.3.0-canary.9(react-dom@19.0.0(react@19.0.0))(react@19.0.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@next/env': 15.2.0-canary.67
|
'@next/env': 15.3.0-canary.9
|
||||||
'@swc/counter': 0.1.3
|
'@swc/counter': 0.1.3
|
||||||
'@swc/helpers': 0.5.15
|
'@swc/helpers': 0.5.15
|
||||||
busboy: 1.6.0
|
busboy: 1.6.0
|
||||||
@ -1135,14 +1145,14 @@ snapshots:
|
|||||||
react-dom: 19.0.0(react@19.0.0)
|
react-dom: 19.0.0(react@19.0.0)
|
||||||
styled-jsx: 5.1.6(react@19.0.0)
|
styled-jsx: 5.1.6(react@19.0.0)
|
||||||
optionalDependencies:
|
optionalDependencies:
|
||||||
'@next/swc-darwin-arm64': 15.2.0-canary.67
|
'@next/swc-darwin-arm64': 15.3.0-canary.9
|
||||||
'@next/swc-darwin-x64': 15.2.0-canary.67
|
'@next/swc-darwin-x64': 15.3.0-canary.9
|
||||||
'@next/swc-linux-arm64-gnu': 15.2.0-canary.67
|
'@next/swc-linux-arm64-gnu': 15.3.0-canary.9
|
||||||
'@next/swc-linux-arm64-musl': 15.2.0-canary.67
|
'@next/swc-linux-arm64-musl': 15.3.0-canary.9
|
||||||
'@next/swc-linux-x64-gnu': 15.2.0-canary.67
|
'@next/swc-linux-x64-gnu': 15.3.0-canary.9
|
||||||
'@next/swc-linux-x64-musl': 15.2.0-canary.67
|
'@next/swc-linux-x64-musl': 15.3.0-canary.9
|
||||||
'@next/swc-win32-arm64-msvc': 15.2.0-canary.67
|
'@next/swc-win32-arm64-msvc': 15.3.0-canary.9
|
||||||
'@next/swc-win32-x64-msvc': 15.2.0-canary.67
|
'@next/swc-win32-x64-msvc': 15.3.0-canary.9
|
||||||
sharp: 0.33.5
|
sharp: 0.33.5
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- '@babel/core'
|
- '@babel/core'
|
||||||
@ -1244,3 +1254,5 @@ snapshots:
|
|||||||
undici-types@6.20.0: {}
|
undici-types@6.20.0: {}
|
||||||
|
|
||||||
util-deprecate@1.0.2: {}
|
util-deprecate@1.0.2: {}
|
||||||
|
|
||||||
|
zod@3.24.2: {}
|
||||||
|
@ -21,7 +21,10 @@
|
|||||||
{
|
{
|
||||||
"name": "next"
|
"name": "next"
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"paths": {
|
||||||
|
"@/*": ["./*"]
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
|
||||||
"exclude": ["node_modules"]
|
"exclude": ["node_modules"]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user