From b5f9c82ae5bb4fead485d1da2fb91a6d4dd1d9d1 Mon Sep 17 00:00:00 2001 From: Dan Date: Thu, 31 Aug 2023 16:18:20 +0300 Subject: [PATCH] More TS support --- .eslintrc.json | 24 +- app/(app)/billing/change-plan/page.tsx | 1 - app/(app)/billing/page.tsx | 5 - app/(app)/billing/refresh-plans/page.tsx | 34 +- app/(app)/billing/webhook/route.ts | 30 +- app/api/subscriptions/[id]/route.ts | 5 +- app/layout.tsx | 2 - app/providers.tsx | 8 +- components/manage.tsx | 21 +- components/plan.tsx | 8 +- components/subscription.tsx | 43 +- lib/data.ts | 1 + package-lock.json | 525 ++++++++++++++++++++++- package.json | 1 + types/types.d.ts | 44 +- 15 files changed, 655 insertions(+), 97 deletions(-) diff --git a/.eslintrc.json b/.eslintrc.json index bffb357..32c9f0b 100644 --- a/.eslintrc.json +++ b/.eslintrc.json @@ -1,3 +1,25 @@ { - "extends": "next/core-web-vitals" + "env": { + "browser": true, + "es2021": true, + "node": true + }, + "extends": [ + "eslint:recommended", + "plugin:@typescript-eslint/recommended", + "plugin:react/recommended" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": "latest", + "sourceType": "module" + }, + "plugins": [ + "@typescript-eslint", + "react" + ], + "rules": { + "react/react-in-jsx-scope": "off", + "react/jsx-uses-react": "off" + } } diff --git a/app/(app)/billing/change-plan/page.tsx b/app/(app)/billing/change-plan/page.tsx index 91f3d9f..49b3311 100644 --- a/app/(app)/billing/change-plan/page.tsx +++ b/app/(app)/billing/change-plan/page.tsx @@ -1,6 +1,5 @@ import { getSession } from "@/lib/auth"; import type { Metadata } from 'next'; -import prisma from "@/lib/prisma"; import Link from 'next/link'; import { PlansComponent } from '@/components/manage'; import { getPlans, getSubscription } from '@/lib/data'; diff --git a/app/(app)/billing/page.tsx b/app/(app)/billing/page.tsx index b59b7b6..b9a69e2 100644 --- a/app/(app)/billing/page.tsx +++ b/app/(app)/billing/page.tsx @@ -1,12 +1,7 @@ import { getSession } from "@/lib/auth"; import type { Metadata } from 'next'; -import prisma from "@/lib/prisma"; -import Plans from '@/components/plan'; import { SubscriptionComponent } from '@/components/subscription'; import { getPlans, getSubscription } from '@/lib/data'; -import LemonSqueezy from '@lemonsqueezy/lemonsqueezy.js' - -const ls = new LemonSqueezy(process.env.LEMONSQUEEZY_API_KEY); export const metadata: Metadata = { diff --git a/app/(app)/billing/refresh-plans/page.tsx b/app/(app)/billing/refresh-plans/page.tsx index b64a881..6d71594 100644 --- a/app/(app)/billing/refresh-plans/page.tsx +++ b/app/(app)/billing/refresh-plans/page.tsx @@ -1,27 +1,21 @@ import prisma from "@/lib/prisma"; import LemonSqueezy from '@lemonsqueezy/lemonsqueezy.js'; -import type { Variant, Product, ProductAttributes } from '@/types/types'; +import type { Variant, Product, ProductAttributes, ApiQueryParams } from '@/types/types'; const ls = new LemonSqueezy(process.env.LEMONSQUEEZY_API_KEY); -interface QueryParams { - include?: string, - perPage?: number, - page?: number -} - async function getPlans() { // Fetch data from Lemon Squeezy - const params: QueryParams = { include: 'product', 'perPage': 50 } + const params: ApiQueryParams = { include: 'product', perPage: 50 } - var hasNextPage = true - var page = 1 + let hasNextPage = true; + let page = 1; - var variants: Variant[] = [] - var products: Product[] = [] + let variants: Variant[] = [] + let products: Product[] = [] while (hasNextPage) { const resp = await ls.getVariants(params); @@ -38,22 +32,22 @@ async function getPlans() { } // Nest products inside variants - let prods: Record = {}; - for (var i = 0; i < products.length; i++) { + const prods: Record = {}; + for (let i = 0; i < products.length; i++) { prods[products[i]['id']] = products[i]['attributes'] } - for (var i = 0; i < variants.length; i++) { + for (let i = 0; i < variants.length; i++) { variants[i]['product'] = prods[variants[i]['attributes']['product_id']] } // Save locally - var variantId, + let variantId, variant, product, productId - for (var i = 0; i < variants.length; i++) { + for (let i = 0; i < variants.length; i++) { variant = variants[i] @@ -111,12 +105,12 @@ async function getPlans() { } export default async function Page() { - const plans = await getPlans() + await getPlans() return ( - <> +

Done! - +

) } diff --git a/app/(app)/billing/webhook/route.ts b/app/(app)/billing/webhook/route.ts index 3e15c16..11a95da 100644 --- a/app/(app)/billing/webhook/route.ts +++ b/app/(app)/billing/webhook/route.ts @@ -1,30 +1,11 @@ -import { NextResponse } from 'next/server'; import { type NextRequest } from 'next/server' -import { Readable } from 'node:stream'; import prisma from "@/lib/prisma"; - - -interface UpdateData { - orderId: number, - name: string, - email: string, - status: string, - renewsAt: string, - endsAt: string, - trialEndsAt: string, - planId: number, - userId: string, - price: number | null -} - -interface CreateData extends UpdateData { - lemonSqueezyId?: number -} +import { SubscriptionCreateData, SubscriptionUpdateData } from '@/types/types'; async function processEvent(event) { - var processingError = '' + let processingError = '' const customData = event.body['meta']['custom_data'] || null @@ -59,9 +40,9 @@ async function processEvent(event) { // Update the subscription - var lemonSqueezyId = parseInt(obj['id']) + const lemonSqueezyId = parseInt(obj['id']) - var updateData: UpdateData = { + const updateData: SubscriptionUpdateData = { orderId: data['order_id'], name: data['user_name'], email: data['user_email'], @@ -74,7 +55,7 @@ async function processEvent(event) { price: event.eventName == 'subscription_created' ? plan['price'] : null } - const createData: CreateData = updateData + const createData: SubscriptionCreateData = updateData createData.lemonSqueezyId = lemonSqueezyId createData.price = plan.price @@ -145,7 +126,6 @@ export async function POST(request: NextRequest) { // Process processEvent(event) - return new Response('Done'); } diff --git a/app/api/subscriptions/[id]/route.ts b/app/api/subscriptions/[id]/route.ts index 17f65ab..0a4d512 100644 --- a/app/api/subscriptions/[id]/route.ts +++ b/app/api/subscriptions/[id]/route.ts @@ -1,5 +1,4 @@ import { NextResponse } from 'next/server'; -import { getSession } from "@/lib/auth"; import { getPlan } from '@/lib/data'; import LemonSqueezy from '@lemonsqueezy/lemonsqueezy.js' @@ -20,12 +19,10 @@ export async function GET(request, { params }) { export async function POST(request, { params }) { - const session = await getSession(); const res = await request.json() - var subscription; - + let subscription; if (res.variantId && res.productId) { diff --git a/app/layout.tsx b/app/layout.tsx index db3baca..f1a8973 100644 --- a/app/layout.tsx +++ b/app/layout.tsx @@ -1,5 +1,3 @@ -import { Inter } from 'next/font/google' -const inter = Inter({ subsets: ['latin'] }) import { Providers } from "./providers" import './globals.css' diff --git a/app/providers.tsx b/app/providers.tsx index ad440fc..0878897 100644 --- a/app/providers.tsx +++ b/app/providers.tsx @@ -1,7 +1,7 @@ "use client"; -import { SessionProvider } from "next-auth/react"; -import { Toaster } from "sonner"; +import { SessionProvider } from "next-auth/react" +import { Toaster } from "sonner" export function Providers({ children }: { children: React.ReactNode }) { return ( @@ -9,5 +9,5 @@ export function Providers({ children }: { children: React.ReactNode }) { {children} - ); -}; + ) +} \ No newline at end of file diff --git a/components/manage.tsx b/components/manage.tsx index 4efd161..811ebaa 100644 --- a/components/manage.tsx +++ b/components/manage.tsx @@ -4,9 +4,11 @@ import { useState } from 'react'; import { Loader2 } from 'lucide-react'; import { toast } from 'sonner'; import Plans from '@/components/plan'; +import { SubscriptionRecord } from '@/types/types'; +import { Subscription } from '@prisma/client'; -export function UpdateBillingLink({ subscription, type }) { +export function UpdateBillingLink({ subscription, elementType }: { subscription: SubscriptionRecord; elementType: string }) { const [isMutating, setIsMutating] = useState(false) @@ -31,7 +33,7 @@ export function UpdateBillingLink({ subscription, type }) { } } - if (type == 'button') { + if (elementType == 'button') { return ( @@ -48,7 +50,12 @@ export function UpdateBillingLink({ subscription, type }) { } } -export function CancelLink({ subscription, setSubscription }) { +interface Props { + subscription: SubscriptionRecord, + setSubscription: Function +} + +export function CancelLink({ subscription, setSubscription }: Props) { const [isMutating, setIsMutating] = useState(false) @@ -97,7 +104,7 @@ export function CancelLink({ subscription, setSubscription }) { } -export function ResumeButton({ subscription, setSubscription }) { +export function ResumeButton({ subscription, setSubscription }: Props) { const [isMutating, setIsMutating] = useState(false) @@ -147,7 +154,7 @@ export function ResumeButton({ subscription, setSubscription }) { } -export function PauseLink({ subscription, setSubscription }) { +export function PauseLink({ subscription, setSubscription }: Props) { const [isMutating, setIsMutating] = useState(false) @@ -196,7 +203,7 @@ export function PauseLink({ subscription, setSubscription }) { } -export function UnpauseButton({ subscription, setSubscription }) { +export function UnpauseButton({ subscription, setSubscription }: Props) { const [isMutating, setIsMutating] = useState(false) @@ -246,7 +253,7 @@ export function UnpauseButton({ subscription, setSubscription }) { } -export function PlansComponent({ plans, sub }) { +export function PlansComponent({ plans, sub }: { plans: object, sub: Subscription}) { const [subscription, setSubscription] = useState(() => { if (sub) { diff --git a/components/plan.tsx b/components/plan.tsx index cd0c200..a29006d 100644 --- a/components/plan.tsx +++ b/components/plan.tsx @@ -4,7 +4,7 @@ import { useState, useEffect } from 'react'; import PlanButton from '@/components/plan-button'; -function createMarkup(html: string): Object { +function createMarkup(html: string): object { return {__html: html}; } @@ -27,7 +27,7 @@ function IntervalSwitcher({ intervalValue, changeInterval }) {