bigblocks
Version:
Complete Bitcoin UI component library - authentication, social, wallet, market, inscriptions, and blockchain interactions for React
185 lines (184 loc) • 6.73 kB
JavaScript
// BigBlocks Next.js Adapter
// Wraps the framework-agnostic core with Next.js specific functionality
// Works without Next.js installed (graceful fallbacks)
import { createBigBlocksAuth, } from "../bigblocks-core.js";
// Mock NextResponse class for when Next.js isn't available
class MockNextResponse {
body;
init;
constructor(body, init) {
this.body = body;
this.init = init;
}
static next() {
return new globalThis.Response("", { status: 200 });
}
static json(data, init) {
return new globalThis.Response(JSON.stringify(data), {
...init,
headers: {
"Content-Type": "application/json",
...init?.headers,
},
});
}
}
// Safe dynamic import helper that evades bundler analysis
async function tryImportNext() {
try {
// Construct the import path to avoid bundler static analysis
const nextModule = "next";
const serverPath = "server";
const importPath = `${nextModule}/${serverPath}`;
// @ts-ignore - Next.js is an optional peer dependency
const importFn = new Function("path", "return import(path)");
return await importFn(importPath);
}
catch {
return { NextResponse: MockNextResponse };
}
}
/**
* Creates BigBlocks auth handlers for Next.js
* Works with both Pages Router (/pages/api) and App Router (/app/api)
*/
export function createNextJSBigBlocks(options = {}) {
const core = createBigBlocksAuth(options);
// App Router handler (app/api/auth/[...bigblocks]/route.ts)
const handler = async (request) => {
try {
// Convert NextRequest to standard Request if needed
let webRequest;
if ("nextUrl" in request) {
// NextRequest
webRequest = new globalThis.Request(request.url, {
method: request.method,
headers: request.headers,
body: request.body,
});
}
else {
// Already a standard Request
webRequest = request;
}
const response = await core.handler(webRequest);
// Try to use NextResponse if available, fallback to Response
try {
const { NextResponse } = await tryImportNext();
return new NextResponse(response.body, {
status: response.status,
statusText: response.statusText,
headers: response.headers,
});
}
catch {
// Fallback to standard Response
return response;
}
}
catch (error) {
console.error("BigBlocks Next.js handler error:", error);
return new globalThis.Response(JSON.stringify({ error: "Internal server error" }), {
status: 500,
headers: { "Content-Type": "application/json" },
});
}
};
// Pages Router handlers (/pages/api/auth/[...bigblocks].ts)
const pageHandler = async (req, res) => {
try {
// Convert Next.js req/res to standard Request
const protocol = req.headers["x-forwarded-proto"] || "http";
const host = req.headers.host || "localhost";
const url = new URL(req.url || "/", `${protocol}://${host}`);
const body = req.method !== "GET" && req.method !== "HEAD"
? JSON.stringify(req.body)
: null;
const webRequest = new globalThis.Request(url.toString(), {
method: req.method,
headers: req.headers,
body,
});
const response = await core.handler(webRequest);
const responseBody = await response.text();
// Set response
res.status(response.status);
// Copy headers
response.headers.forEach((value, key) => {
res.setHeader(key, value);
});
res.send(responseBody);
}
catch (error) {
console.error("BigBlocks Pages API error:", error);
res.status(500).json({ error: "Internal server error" });
}
};
// Middleware helper for authentication
const middleware = async (request) => {
try {
const session = await core.api.getSession(request.headers);
if (!session) {
return new globalThis.Response(JSON.stringify({ error: "Unauthorized" }), {
status: 401,
headers: { "Content-Type": "application/json" },
});
}
// Try to use NextResponse if available
try {
const { NextResponse } = await tryImportNext();
const response = NextResponse.next();
response.headers.set("x-user-id", session.user.id);
response.headers.set("x-user-address", session.user.address);
return response;
}
catch {
// Fallback to standard Response
const response = new globalThis.Response("", { status: 200 });
response.headers.set("x-user-id", session.user.id);
response.headers.set("x-user-address", session.user.address);
return response;
}
}
catch (error) {
console.error("BigBlocks middleware error:", error);
return new globalThis.Response(JSON.stringify({ error: "Internal server error" }), {
status: 500,
headers: { "Content-Type": "application/json" },
});
}
};
return {
// App Router (recommended)
GET: handler,
POST: handler,
PUT: handler,
DELETE: handler,
// Pages Router (legacy)
handler: pageHandler,
// Middleware
middleware,
// Direct API access
api: core.api,
// Config
options: core.options,
};
}
// Convenience exports for different Next.js patterns
export const createAppRouterHandlers = (options) => {
const handlers = createNextJSBigBlocks(options);
return {
GET: handlers.GET,
POST: handlers.POST,
PUT: handlers.PUT,
DELETE: handlers.DELETE,
};
};
export const createPagesAPIHandler = (options) => {
const { handler } = createNextJSBigBlocks(options);
return handler;
};
export const createNextMiddleware = (options) => {
const { middleware } = createNextJSBigBlocks(options);
return middleware;
};