next-ts-cli 1.0.3

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.
Files changed (60) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +194 -0
  3. package/dist/index.js +94 -0
  4. package/package.json +97 -0
  5. package/template/base/.cusror/mpc.json +8 -0
  6. package/template/base/.husky/commit-msg +1 -0
  7. package/template/base/.husky/pre-commit +1 -0
  8. package/template/base/LICENSE +21 -0
  9. package/template/base/README.md +0 -0
  10. package/template/base/app/apple-icon.png +0 -0
  11. package/template/base/app/favicon.ico +0 -0
  12. package/template/base/app/globals.css +9 -0
  13. package/template/base/app/layout.tsx +61 -0
  14. package/template/base/app/loading.tsx +7 -0
  15. package/template/base/app/manifest.ts +33 -0
  16. package/template/base/app/opengraph-image.png +0 -0
  17. package/template/base/app/page.tsx +7 -0
  18. package/template/base/app/robots.ts +28 -0
  19. package/template/base/app/sitemap.ts +17 -0
  20. package/template/base/app/twitter-image.png +0 -0
  21. package/template/base/biome.jsonc +272 -0
  22. package/template/base/commitlint.config.ts +25 -0
  23. package/template/base/hooks/use-hydration.tsx +16 -0
  24. package/template/base/jest.config.js +18 -0
  25. package/template/base/jest.setup.js +2 -0
  26. package/template/base/lib/fonts.ts +14 -0
  27. package/template/base/lib/indexing.ts +14 -0
  28. package/template/base/lib/microdata.ts +51 -0
  29. package/template/base/lib/utils.ts +6 -0
  30. package/template/base/next.config.ts +7 -0
  31. package/template/base/package-lock.json +9296 -0
  32. package/template/base/package.json +59 -0
  33. package/template/base/postcss.config.js +5 -0
  34. package/template/base/providers/MicrodataScript.tsx +18 -0
  35. package/template/base/public/.gitkeep +3 -0
  36. package/template/base/test/index.test.tsx +9 -0
  37. package/template/base/tsconfig.json +38 -0
  38. package/template/extras/better-auth/api/auth/[...all]/route.ts +7 -0
  39. package/template/extras/better-auth/base-auth.ts +12 -0
  40. package/template/extras/better-auth/with-drizzle-auth.ts +31 -0
  41. package/template/extras/clerk/layout.tsx +89 -0
  42. package/template/extras/clerk/proxy.ts +21 -0
  43. package/template/extras/docker/.dockerignore +60 -0
  44. package/template/extras/docker/Dockerfile +51 -0
  45. package/template/extras/docker/docker-compose.prod.yml +34 -0
  46. package/template/extras/drizzle/db/index.ts +9 -0
  47. package/template/extras/drizzle/db/schema.ts +7 -0
  48. package/template/extras/drizzle/drizzle.config.ts +15 -0
  49. package/template/extras/neon/index.ts +10 -0
  50. package/template/extras/shadcnui/components.json +21 -0
  51. package/template/extras/shadcnui/globals.css +71 -0
  52. package/template/extras/stripe/checkout_session/route.ts +60 -0
  53. package/template/extras/stripe/stripe.ts +17 -0
  54. package/template/extras/stripe/webhook/stripe/route.ts +89 -0
  55. package/template/extras/supabase/client.ts +8 -0
  56. package/template/extras/supabase/getAuth.ts +50 -0
  57. package/template/extras/supabase/proxy.ts +70 -0
  58. package/template/extras/supabase/server.ts +34 -0
  59. package/template/extras/supabase/storage.ts +90 -0
  60. package/template/extras/vercel-ai/route.ts +12 -0
@@ -0,0 +1,89 @@
1
+ /* =============================================================================================
2
+
3
+ This page is a minimal boilerplate for managing the Stripe subscription system with your website.
4
+
5
+ If you need a non-subscription based system, the webhook configuration will be differnt,
6
+ so check the Stripe documentation for more information.
7
+
8
+ ================================================================================================ */
9
+ import { headers } from "next/headers";
10
+ import { NextResponse } from "next/server";
11
+ import { stripe } from "@/lib/stripe";
12
+ import type Stripe from "stripe";
13
+
14
+ export async function POST(req: Request) {
15
+ const body = await req.text();
16
+ const headersList = await headers();
17
+ const signature = headersList.get("Stripe-Signature") as string;
18
+
19
+ let event: Stripe.Event;
20
+
21
+ try {
22
+ event = stripe().webhooks.constructEvent(
23
+ body,
24
+ signature,
25
+ process.env.STRIPE_WEBHOOK_SECRET as string
26
+ );
27
+ } catch (error: unknown) {
28
+ const message = error instanceof Error ? error.message : "Unknown error";
29
+ return new NextResponse(`Webhook Error: ${message}`, { status: 400 });
30
+ }
31
+
32
+ try {
33
+ switch (event.type) {
34
+ // When a customer completes checkout
35
+ case "checkout.session.completed": {
36
+ try {
37
+ // Do something
38
+ } catch (e) {
39
+ return new NextResponse(`Error: ${e}`, { status: 500 });
40
+ }
41
+ break;
42
+ }
43
+
44
+ // When a new subscription is created
45
+ case "customer.subscription.created": {
46
+ const subscription = event.data.object as Stripe.Subscription;
47
+ // Do something, usually create record in DB
48
+ break;
49
+ }
50
+
51
+ // When a subscription is updated
52
+ case "customer.subscription.updated": {
53
+ const subscription = event.data.object as Stripe.Subscription;
54
+ // Do something, usually update record in DB, when subscription is renewed/stopped, etc.
55
+ break;
56
+ }
57
+
58
+ // When a subscription is specifically cancelled/deleted
59
+ case "customer.subscription.deleted": {
60
+ const subscription = event.data.object as Stripe.Subscription;
61
+ // Do something, usually delete record in DB, when subscription is cancelled/deleted, etc.
62
+ break;
63
+ }
64
+
65
+ // When a trial is about to end (3 days before)
66
+ case "customer.subscription.trial_will_end": {
67
+ const subscription = event.data.object as Stripe.Subscription;
68
+ // Do something, usually warn the user via mail or something else
69
+ break;
70
+ }
71
+
72
+ // Invoice events for payment tracking
73
+ case "invoice.payment_succeeded": {
74
+ // Do something, usually log invoices info somewhere
75
+ break;
76
+ }
77
+
78
+ // When a payment fails
79
+ case "invoice.payment_failed": {
80
+ // Do something, usually warn the user via mail or something else
81
+ break;
82
+ }
83
+ }
84
+
85
+ return new NextResponse(null, { status: 200 });
86
+ } catch (_) {
87
+ return new NextResponse("Webhook handler error", { status: 500 });
88
+ }
89
+ }
@@ -0,0 +1,8 @@
1
+ import { createBrowserClient } from "@supabase/ssr";
2
+
3
+ export function createClient() {
4
+ return createBrowserClient(
5
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
6
+ process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
7
+ );
8
+ }
@@ -0,0 +1,50 @@
1
+ import { createClient } from "@/lib/supabase/server";
2
+ import type { SupabaseClient } from "@supabase/supabase-js";
3
+ import { cookies } from "next/headers";
4
+
5
+ export type ProfileModel = {
6
+ id: string;
7
+ fullName: string;
8
+ email: string;
9
+ avatar: string;
10
+ };
11
+
12
+ export type UseAuthProps =
13
+ | {
14
+ isLoggedIn: true;
15
+ user: ProfileModel;
16
+ supabase: SupabaseClient;
17
+ }
18
+ | {
19
+ isLoggedIn: false;
20
+ user: null;
21
+ supabase: SupabaseClient;
22
+ };
23
+
24
+ /**
25
+ * Utility hook to check if the user is logged in or not
26
+ *
27
+ * It works **only Server Side**
28
+ * @returns {UseAuthProps} Auth object {@link UseAuthProps}
29
+ */
30
+ export const getAuth = async (): Promise<UseAuthProps> => {
31
+ const cookie = cookies();
32
+ const supabase = createClient(cookie);
33
+
34
+ const {
35
+ data: { user },
36
+ } = await supabase.auth.getUser();
37
+
38
+ if (user) {
39
+ const userModel: ProfileModel = {
40
+ id: user.id,
41
+ fullName: user.user_metadata?.name ?? user.user_metadata?.user_name,
42
+ email: user.email || "",
43
+ avatar: user.user_metadata.avatar_url || "",
44
+ };
45
+
46
+ return { isLoggedIn: true, user: userModel, supabase };
47
+ } else {
48
+ return { isLoggedIn: false, user: null, supabase };
49
+ }
50
+ };
@@ -0,0 +1,70 @@
1
+ import { createServerClient } from "@supabase/ssr";
2
+ import { NextResponse, type NextRequest } from "next/server";
3
+
4
+ export async function updateSession(request: NextRequest) {
5
+ let supabaseResponse = NextResponse.next({
6
+ request,
7
+ });
8
+
9
+
10
+ // With Fluid compute, don't put this client in a global environment
11
+ // variable. Always create a new one on each request.
12
+ const supabase = createServerClient(
13
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
14
+ process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
15
+ {
16
+ cookies: {
17
+ getAll() {
18
+ return request.cookies.getAll();
19
+ },
20
+ setAll(cookiesToSet) {
21
+ cookiesToSet.forEach(({ name, value }) =>
22
+ request.cookies.set(name, value),
23
+ );
24
+ supabaseResponse = NextResponse.next({
25
+ request,
26
+ });
27
+ cookiesToSet.forEach(({ name, value, options }) =>
28
+ supabaseResponse.cookies.set(name, value, options),
29
+ );
30
+ },
31
+ },
32
+ },
33
+ );
34
+
35
+ // Do not run code between createServerClient and
36
+ // supabase.auth.getClaims(). A simple mistake could make it very hard to debug
37
+ // issues with users being randomly logged out.
38
+
39
+ // IMPORTANT: If you remove getClaims() and you use server-side rendering
40
+ // with the Supabase client, your users may be randomly logged out.
41
+ const { data } = await supabase.auth.getClaims();
42
+ const user = data?.claims;
43
+
44
+ if (
45
+ request.nextUrl.pathname !== "/" &&
46
+ !user &&
47
+ !request.nextUrl.pathname.startsWith("/login") &&
48
+ !request.nextUrl.pathname.startsWith("/auth")
49
+ ) {
50
+ // no user, potentially respond by redirecting the user to the login page
51
+ const url = request.nextUrl.clone();
52
+ url.pathname = "/auth/login";
53
+ return NextResponse.redirect(url);
54
+ }
55
+
56
+ // IMPORTANT: You *must* return the supabaseResponse object as it is.
57
+ // If you're creating a new response object with NextResponse.next() make sure to:
58
+ // 1. Pass the request in it, like so:
59
+ // const myNewResponse = NextResponse.next({ request })
60
+ // 2. Copy over the cookies, like so:
61
+ // myNewResponse.cookies.setAll(supabaseResponse.cookies.getAll())
62
+ // 3. Change the myNewResponse object to fit your needs, but avoid changing
63
+ // the cookies!
64
+ // 4. Finally:
65
+ // return myNewResponse
66
+ // If this is not done, you may be causing the browser and server to go out
67
+ // of sync and terminate the user's session prematurely!
68
+
69
+ return supabaseResponse;
70
+ }
@@ -0,0 +1,34 @@
1
+ import { createServerClient } from "@supabase/ssr";
2
+ import { cookies } from "next/headers";
3
+
4
+ /**
5
+ * Especially important if using Fluid compute: Don't put this client in a
6
+ * global variable. Always create a new client within each function when using
7
+ * it.
8
+ */
9
+ export async function createClient() {
10
+ const cookieStore = await cookies();
11
+
12
+ return createServerClient(
13
+ process.env.NEXT_PUBLIC_SUPABASE_URL!,
14
+ process.env.NEXT_PUBLIC_SUPABASE_PUBLISHABLE_KEY!,
15
+ {
16
+ cookies: {
17
+ getAll() {
18
+ return cookieStore.getAll();
19
+ },
20
+ setAll(cookiesToSet) {
21
+ try {
22
+ cookiesToSet.forEach(({ name, value, options }) =>
23
+ cookieStore.set(name, value, options),
24
+ );
25
+ } catch {
26
+ // The `setAll` method was called from a Server Component.
27
+ // This can be ignored if you have proxy refreshing
28
+ // user sessions.
29
+ }
30
+ },
31
+ },
32
+ },
33
+ );
34
+ }
@@ -0,0 +1,90 @@
1
+ /* ==============================
2
+ Utility functions for Supabase storage.
3
+ ======================================
4
+ */
5
+
6
+ import { createClient } from "./client";
7
+
8
+ export interface UploadResult {
9
+ url: string;
10
+ path: string;
11
+ }
12
+
13
+ export interface DeleteResult {
14
+ success: boolean;
15
+ error?: string;
16
+ }
17
+
18
+ /**
19
+ * Upload a file to Supabase storage.
20
+ * @param bucket - The name of the bucket to upload the file to.
21
+ * @param file - The file to upload.
22
+ * @param fileName - The name of the file to upload.
23
+ * @returns The URL of the uploaded file and the path of the file.
24
+ * @throws An error if the file could not be uploaded.
25
+ * @example
26
+ * const result = await uploadFile("my-bucket", "my-file.txt", "my-file.txt");
27
+ * if (result.url) {
28
+ * console.log("File uploaded successfully");
29
+ * } else {
30
+ * console.error(result.error);
31
+ * }
32
+ */
33
+ export const uploadFile = async (
34
+ bucket: string,
35
+ file: File,
36
+ fileName: string
37
+ ): Promise<{ url: string; path: string } | { error: string }> => {
38
+ try {
39
+ const supabase = createClient();
40
+
41
+ // Upload file to Supabase storage
42
+ const { error } = await supabase.storage.from(bucket).upload(fileName, file, {
43
+ cacheControl: "3600",
44
+ upsert: false,
45
+ });
46
+
47
+ if (error) {
48
+ return { error: error.message };
49
+ }
50
+
51
+ const { data: urlData } = supabase.storage.from(bucket).getPublicUrl(fileName);
52
+
53
+ return { url: urlData.publicUrl, path: fileName };
54
+ } catch (error) {
55
+ return { error: error instanceof Error ? error.message : "Unknown error" };
56
+ }
57
+ };
58
+
59
+ /**
60
+ * Delete a file from Supabase storage.
61
+ * @param bucket - The name of the bucket to delete the file from.
62
+ * @param fileName - The name of the file to delete.
63
+ * @returns True if the file was deleted successfully, false otherwise.
64
+ * @throws An error if the file could not be deleted.
65
+ * @example
66
+ * const result = await deleteFile("my-bucket", "my-file.txt");
67
+ * if (result.success) {
68
+ * console.log("File deleted successfully");
69
+ * } else {
70
+ * console.error(result.error);
71
+ * }
72
+ */
73
+ export const deleteFile = async (
74
+ bucket: string,
75
+ fileName: string
76
+ ): Promise<{ success: boolean } | { error: string }> => {
77
+ try {
78
+ const supabase = createClient();
79
+
80
+ const { error } = await supabase.storage.from(bucket).remove([fileName]);
81
+
82
+ if (error) {
83
+ return { error: error.message };
84
+ }
85
+
86
+ return { success: true };
87
+ } catch (error) {
88
+ return { error: error instanceof Error ? error.message : "Unknown error" };
89
+ }
90
+ };
@@ -0,0 +1,12 @@
1
+ import { streamText, UIMessage, convertToModelMessages } from 'ai';
2
+
3
+ export async function POST(req: Request) {
4
+ const { messages }: { messages: UIMessage[] } = await req.json();
5
+
6
+ const result = streamText({
7
+ model: "openai/gpt-5.2-chat-latest", // or any other model you want to use
8
+ messages: await convertToModelMessages(messages),
9
+ });
10
+
11
+ return result.toUIMessageStreamResponse();
12
+ }