Last active
June 2, 2024 06:07
-
-
Save robksawyer/c082fc6e73cc20431431f57e49f28741 to your computer and use it in GitHub Desktop.
Revisions
-
robksawyer revised this gist
Jun 2, 2024 . 2 changed files with 175 additions and 19 deletions.There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,6 +1,7 @@ import { IncomingMessage } from "http"; import { NextRequest } from "next/server"; import { Socket } from "net"; import { cookies } from "next/headers"; export async function convertNextRequestToIncomingMessage( request: NextRequest @@ -12,38 +13,74 @@ export async function convertNextRequestToIncomingMessage( const incomingMessage = new IncomingMessage(new Socket()); try { // Convert headers incomingMessage.headers = Object.fromEntries(request.headers.entries()); incomingMessage.method = request.method; incomingMessage.url = request.url; console.log("Converted headers:", incomingMessage.headers); // Ensure all cookies are set in headers const cookieStore = cookies(); const allCookies = cookieStore.getAll(); const cookieHeader = allCookies .map((cookie) => `${cookie.name}=${cookie.value}`) .join("; "); if (cookieHeader) { incomingMessage.headers["cookie"] = cookieHeader; } else { console.error("No cookies found"); } let body: Buffer | null = null; // Convert body if it exists if (request.body) { const reader = request.body.getReader(); const stream = new ReadableStream({ start(controller) { function push() { reader.read().then(({ done, value }) => { if (done) { controller.close(); return; } controller.enqueue(value); push(); }); } push(); }, }); const response = new Response(stream); const bodyBuffer = await response.arrayBuffer(); body = Buffer.from(bodyBuffer); if (body.length > 0) { incomingMessage.push(body); } incomingMessage.push(null); // Log the converted body console.log("Converted body buffer:", body); } // Mimic NextApiRequest properties const url = new URL(request.url); const query = Object.fromEntries(url.searchParams.entries()); console.log("Converted query parameters:", query); const parsedBody = body && body.length > 0 ? JSON.parse(body.toString()) : null; console.log("Parsed body:", parsedBody); (incomingMessage as any).query = query; (incomingMessage as any).cookies = Object.fromEntries( allCookies.map((cookie) => [cookie.name, cookie.value]) ); (incomingMessage as any).body = parsedBody; } catch (error) { console.error("Error converting NextRequest to IncomingMessage:", error); throw error; This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,119 @@ // lib/supabaseSessionStorage.ts import { SessionInterface } from "@shopify/shopify-api/dist/auth/session/types"; import { CustomSessionStorage } from "@shopify/shopify-api/dist/auth/session"; import { supabase } from "@/utils/supabaseClient"; const DATABASE = "shopify_sessions"; // Store session callback const storeSession = async (session: SessionInterface): Promise<boolean> => { try { console.log("Storing session:", session); // Ensure isOnline is a boolean const isOnline = typeof session.isOnline === "boolean" ? session.isOnline : session.isOnline === "true"; // Ensure isActive is a boolean and defaults to true if not a function const isActive = typeof session.isActive === "function" ? session.isActive() : true; const sessionData = { id: session.id, // Unique identifier provided by Shopify shop_domain: session.shop, state: session.state, is_online: isOnline, scope: session.scope || "", // Providing default empty string if scope is undefined expires: session.expires ? session.expires.toISOString() : null, // Providing null if expires is undefined and converting to ISO string online_access_info: session.onlineAccessInfo || {}, // Providing empty object if undefined access_token: session.accessToken, is_active: isActive, }; // Log the session data to debug issues console.log("Session data to be saved:", sessionData); // Save the session to Supabase const { data, error } = await supabase.from(DATABASE).upsert([sessionData]); // Using upsert instead of insert if (error) { console.error("Error storing session:", error.message); return false; } console.log("Session stored successfully:", session.id); return true; } catch (error) { console.error("Error storing session:", error); return false; } }; // Load session callback const loadSession = async ( id: string ): Promise<SessionInterface | undefined> => { try { const { data, error } = await supabase .from(DATABASE) .select( "shop_domain, access_token, is_online, state, scope, expires, online_access_info, is_active" ) .eq("id", id) .single(); if (error) { console.error("Error loading session:", error.message); return undefined; } if (data) { const session: SessionInterface = { id: id, shop: data.shop_domain, state: data.state, isOnline: data.is_online, scope: data.scope, expires: data.expires ? new Date(data.expires) : undefined, onlineAccessInfo: data.online_access_info, accessToken: data.access_token, isActive: () => data.is_active, }; console.log("Session loaded successfully:", session.id); return session; } return undefined; } catch (error) { console.error("Error loading session:", error); return undefined; } }; // Delete session callback const deleteSession = async (id: string): Promise<boolean> => { try { const { error } = await supabase.from(DATABASE).delete().eq("id", id); if (error) { console.error("Error deleting session:", error.message); return false; } console.log("Session deleted successfully:", id); return true; } catch (error) { console.error("Error deleting session:", error); return false; } }; class SupabaseSessionStorage extends CustomSessionStorage { constructor() { super(storeSession, loadSession, deleteSession); } } export const sessionStorage = new SupabaseSessionStorage(); -
robksawyer revised this gist
May 31, 2024 . No changes.There are no files selected for viewing
-
robksawyer revised this gist
May 31, 2024 . No changes.There are no files selected for viewing
-
robksawyer created this gist
May 31, 2024 .There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,53 @@ import { IncomingMessage } from "http"; import { NextRequest } from "next/server"; import { Socket } from "net"; export async function convertNextRequestToIncomingMessage( request: NextRequest ): Promise<IncomingMessage> { if (!request || typeof request !== "object") { throw new Error("Invalid request object"); } const incomingMessage = new IncomingMessage(new Socket()); try { incomingMessage.headers = Object.fromEntries(request.headers.entries()); incomingMessage.method = request.method; incomingMessage.url = request.url; const bodyChunks: Uint8Array[] = []; if (request.body) { const reader = request.body.getReader(); let result = await reader.read(); while (!result.done) { bodyChunks.push(result.value); result = await reader.read(); } } const bodyBuffer = Buffer.concat(bodyChunks); if (bodyBuffer.length > 0) { incomingMessage.push(bodyBuffer); } incomingMessage.push(null); // Mimic NextApiRequest properties (incomingMessage as any).query = Object.fromEntries( new URL(request.url).searchParams.entries() ); (incomingMessage as any).cookies = Object.fromEntries( request.headers .get("cookie") ?.split("; ") .map((cookie) => cookie.split("=")) || [] ); (incomingMessage as any).body = bodyBuffer.length > 0 ? JSON.parse(bodyBuffer.toString()) : null; } catch (error) { console.error("Error converting NextRequest to IncomingMessage:", error); throw error; } return incomingMessage; } This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,53 @@ import { ServerResponse } from "http"; import { NextResponse } from "next/server"; export function convertNextResponseToServerResponse( nextResponse: NextResponse ): ServerResponse { if (!nextResponse || typeof nextResponse !== "object") { throw new Error("Invalid nextResponse object"); } const serverResponse = new ServerResponse({} as any); try { serverResponse.statusCode = nextResponse.status; serverResponse.statusMessage = nextResponse.statusText; for (const [key, value] of nextResponse.headers.entries()) { serverResponse.setHeader(key, value); } // Implement write method serverResponse.write = ( chunk: any, encodingOrCallback?: any, callback?: any ): boolean => { if (typeof encodingOrCallback === "function") { encodingOrCallback(null); } else if (typeof callback === "function") { callback(null); } return true; // Ensure boolean is returned }; // Implement end method serverResponse.end = ( chunk: any, encodingOrCallback?: any, callback?: any ): ServerResponse => { if (typeof encodingOrCallback === "function") { encodingOrCallback(null); } else if (typeof callback === "function") { callback(null); } return serverResponse; // Ensure ServerResponse is returned }; } catch (error) { console.error("Error converting NextResponse to ServerResponse:", error); throw error; } return serverResponse; }