payload-authjs
Version:
A Payload CMS 3 plugin for Auth.js 5
78 lines (77 loc) • 3.15 kB
JavaScript
import { deepCopyObjectSimple, getPayload } from "payload";
import { PayloadAdapter } from "./PayloadAdapter";
/**
* Wraps the Auth.js configuration
*
* @example
* import { config } from "./auth.config";
*
* export const { handlers, signIn, signOut, auth } = NextAuth(
* withPayload(config, { payloadConfig }),
* );
*/ export function withPayload(authjsConfig, { updateUserOnSignIn, events, ...options }) {
authjsConfig = {
...authjsConfig
};
// Set default session strategy to "jwt"
authjsConfig.session = {
...authjsConfig.session,
strategy: authjsConfig.session?.strategy || "jwt"
};
// Register the Payload adapter for authjs
authjsConfig.adapter = PayloadAdapter(options);
/**
* Update the user profile after every sign in
* This is useful when you add new fields to the user collection (e.g. roles)
* @see https://authjs.dev/guides/role-based-access-control#with-database
*/ if (updateUserOnSignIn === true) {
const { signIn, ...callbacks } = authjsConfig.callbacks ?? {};
async function updateUserOnSignInWrapper(params) {
// Call the original signIn callback
if (await signIn?.(params) === false) {
return false;
}
// Try to update the user profile
try {
if (params.user.id && params.profile) {
await authjsConfig.adapter?.updateUser?.({
// eslint-disable-next-line @typescript-eslint/no-explicit-any
...params.profile,
id: params.user.id
});
}
} catch {
// If user signed in the first time, the user is not found in the database and an error is thrown
}
return true;
}
authjsConfig.callbacks = {
...callbacks,
// Prevent injecting the same wrapper multiple times
signIn: signIn?.name !== "updateUserOnSignInWrapper" ? updateUserOnSignInWrapper : signIn
};
}
// Forward all events from authjs and enrich them with additional parameters
const originalEvents = deepCopyObjectSimple(authjsConfig.events ?? {});
authjsConfig.events = Object.entries(events ?? {}).reduce((result, [key, customEvent])=>{
const originalEvent = result[key];
// eslint-disable-next-line @typescript-eslint/no-explicit-any
result[key] = async (message)=>{
// Call the original event
await originalEvent?.(message);
// Call the custom event
await customEvent?.({
...message,
// Add the adapter to the event
adapter: authjsConfig.adapter,
// Add payload to the event
payload: options.payload ? await options.payload : options.payloadConfig ? await getPayload({
config: options.payloadConfig
}) : undefined
});
};
return result;
}, originalEvents);
return authjsConfig;
}
//# sourceMappingURL=withPayload.js.map