@coursebuilder/next
Version:
Next for Course Builder.
142 lines (141 loc) • 6.07 kB
JavaScript
import { headers } from 'next/headers.js';
import { NextResponse, } from 'next/server.js';
import { CourseBuilder, createActionURL, } from '@coursebuilder/core';
import { reqWithEnvURL } from './env.js';
function isReqWrapper(arg) {
return typeof arg === 'function';
}
export function initCourseBuilder(config, onLazyLoad) {
if (typeof config === 'function') {
return async (...args) => {
if (!args.length) {
// React Server Components
const _headers = await headers();
const _config = config(undefined); // Review: Should we pass headers() here instead?
onLazyLoad?.(_config);
return getSession(_headers, _config).then((r) => r.json());
}
if (args[0] instanceof Request) {
// middleware.ts inline
// export { auth as default } from "auth"
const req = args[0];
const ev = args[1];
const _config = config(req);
onLazyLoad?.(_config);
// args[0] is supposed to be NextRequest but the instanceof check is failing.
return handleCourseBuilder([req, ev], _config);
}
if (isReqWrapper(args[0])) {
// middleware.ts wrapper/route.ts
// import { auth } from "auth"
// export default auth((req) => { console.log(req.auth) }})
const userMiddlewareOrRoute = args[0];
return async (...args) => {
return handleCourseBuilder(args, config(args[0]), userMiddlewareOrRoute);
};
}
// API Routes, getServerSideProps
const request = 'req' in args[0] ? args[0].req : args[0];
const response = 'res' in args[0] ? args[0].res : args[1];
// @ts-expect-error -- request is NextRequest
const _config = config(request);
onLazyLoad?.(_config);
// @ts-expect-error -- request is NextRequest
return getSession(new Headers(request.headers), _config).then(async (courseBuilderResponse) => {
const coursebuilder = await courseBuilderResponse.json();
for (const cookie of courseBuilderResponse.headers.getSetCookie())
if ('headers' in response)
response.headers.append('set-cookie', cookie);
else
response.appendHeader('set-cookie', cookie);
return coursebuilder;
});
};
}
return async (...args) => {
if (!args.length) {
// React Server Components
return getSession(await headers(), config).then((r) => r.json());
}
if (args[0] instanceof Request) {
// middleware.ts inline
// export { auth as default } from "auth"
const req = args[0];
const ev = args[1];
return handleCourseBuilder([req, ev], config);
}
if (isReqWrapper(args[0])) {
// middleware.ts wrapper/route.ts
// import { auth } from "auth"
// export default auth((req) => { console.log(req.auth) }})
const userMiddlewareOrRoute = args[0];
return async (...args) => {
return handleCourseBuilder(args, config, userMiddlewareOrRoute).then((res) => {
return res;
});
};
}
// API Routes, getServerSideProps
const request = 'req' in args[0] ? args[0].req : args[0];
const response = 'res' in args[0] ? args[0].res : args[1];
return getSession(
// @ts-expect-error
new Headers(request.headers), config).then(async (courseBuilderResponse) => {
const coursebuilder = await courseBuilderResponse.json();
for (const cookie of courseBuilderResponse.headers.getSetCookie())
if ('headers' in response)
response.headers.append('set-cookie', cookie);
else
response.appendHeader('set-cookie', cookie);
return coursebuilder;
});
};
}
async function getSession(headers, config) {
const url = createActionURL('session',
// @ts-expect-error `x-forwarded-proto` is not nullable, next.js sets it by default
headers.get('x-forwarded-proto'), headers, process.env, config.basePath);
const request = new Request(url, {
headers: { cookie: headers.get('cookie') ?? '' },
});
return CourseBuilder(request, {
...config,
callbacks: {
...config.callbacks,
async session(...args) {
const session =
// If the user defined a custom session callback, use that instead
(await config.callbacks?.session?.(...args)) ?? {};
return session;
},
},
});
}
async function handleCourseBuilder(args, config, userMiddlewareOrRoute) {
const request = reqWithEnvURL(args[0]);
const sessionResponse = await getSession(request.headers, config);
const coursebuilder = await sessionResponse.json();
let response = NextResponse.next?.();
if (userMiddlewareOrRoute) {
const augmentedReq = request;
augmentedReq.coursebuilder = coursebuilder;
response =
// @ts-expect-error
(await userMiddlewareOrRoute(augmentedReq, args[1])) ??
NextResponse.next();
}
const finalResponse = new Response(response?.body, response);
for (const cookie of sessionResponse.headers.getSetCookie())
finalResponse.headers.append('set-cookie', cookie);
return finalResponse;
}
function isSameAuthAction(requestPath, redirectPath, config) {
const action = redirectPath.replace(`${requestPath}/`, '');
return actions.has(action) && redirectPath === requestPath;
}
const actions = new Set([
'webhook',
'session',
'srt',
'checkout',
]);