Refactor route handlers and CMS clients

Refactored the route handlers to use a new `enhanceRouteHandler` function for better control over request handlers and user authentication. CMS clients are now created using factory functions for better encapsulation and control over instance creation. Renamed `client.ts` in 'keystatic' to `keystatic-client.ts`.
This commit is contained in:
giancarlo
2024-05-02 12:37:58 +07:00
parent be5c10f1c3
commit dbce7e38ae
8 changed files with 99 additions and 66 deletions

View File

@@ -45,7 +45,7 @@ export class StripeWebhookHandlerService
const stripe = await this.loadStripe();
const event = stripe.webhooks.constructEvent(
const event = await stripe.webhooks.constructEventAsync(
body,
signature,
webhooksSecret,

View File

@@ -28,9 +28,11 @@ async function cmsClientFactory(type: CmsType) {
}
async function getWordpressClient() {
const { WordpressClient } = await import('../../wordpress/src/wp-client');
const { createWordpressClient } = await import(
'../../wordpress/src/wp-client'
);
return new WordpressClient();
return createWordpressClient();
}
async function getKeystaticClient() {
@@ -38,9 +40,11 @@ async function getKeystaticClient() {
process.env.NEXT_RUNTIME === 'nodejs' ||
process.env.KEYSTATIC_STORAGE_KIND !== 'local'
) {
const { KeystaticClient } = await import('../../keystatic/src/client');
const { createKeystaticClient } = await import(
'../../keystatic/src/keystatic-client'
);
return new KeystaticClient();
return createKeystaticClient();
}
console.error(

View File

@@ -1,2 +1,2 @@
export * from './client';
export * from './keystatic-client';
export * from './content-renderer';

View File

@@ -3,7 +3,11 @@ import { Cms, CmsClient } from '@kit/cms';
import { createKeystaticReader } from './create-reader';
import { PostEntryProps } from './keystatic.config';
export class KeystaticClient implements CmsClient {
export function createKeystaticClient() {
return new KeystaticClient();
}
class KeystaticClient implements CmsClient {
async getContentItems(options: Cms.GetContentItemsOptions) {
const reader = await createKeystaticReader();

View File

@@ -8,17 +8,19 @@ import { Cms, CmsClient } from '@kit/cms';
import GetTagsOptions = Cms.GetTagsOptions;
export function createWordpressClient(
apiUrl = process.env.WORDPRESS_API_URL as string,
) {
return new WordpressClient(apiUrl);
}
/**
* @name WordpressClient
* @description Represents a client for interacting with a Wordpress CMS.
* Implements the CmsClient interface.
*/
export class WordpressClient implements CmsClient {
private readonly apiUrl: string;
constructor(apiUrl = process.env.WORDPRESS_API_URL as string) {
this.apiUrl = apiUrl;
}
class WordpressClient implements CmsClient {
constructor(private readonly apiUrl: string) {}
/**
* Retrieves content items from a CMS based on the provided options.

View File

@@ -14,9 +14,19 @@ import { getSupabaseRouteHandlerClient } from '@kit/supabase/route-handler-clien
import { captureException, zodParseFactory } from '../utils';
interface HandlerParams<Body> {
interface Config<Schema> {
auth?: boolean;
captcha?: boolean;
captureException?: boolean;
schema?: Schema;
}
interface HandlerParams<
Body extends object,
RequireAuth extends boolean | undefined,
> {
request: NextRequest;
user: User;
user: RequireAuth extends false ? undefined : User;
body: Body;
}
@@ -41,22 +51,21 @@ interface HandlerParams<Body> {
*
*/
export const enhanceRouteHandler = <
Body,
Body extends object,
Schema extends z.ZodType<Body, z.ZodTypeDef>,
Params extends Config<Schema> = Config<Schema>,
>(
// Route handler function
handler:
| ((params: HandlerParams<z.infer<Schema>>) => NextResponse | Response)
| ((
params: HandlerParams<z.infer<Schema>>,
params: HandlerParams<z.infer<Schema>, Params['auth']>,
) => NextResponse | Response)
| ((
params: HandlerParams<z.infer<Schema>, Params['auth']>,
) => Promise<NextResponse | Response>),
// Parameters object
params?: {
captcha?: boolean;
captureException?: boolean;
schema?: Schema;
},
params?: Params,
) => {
/**
* Route handler function.
@@ -64,6 +73,10 @@ export const enhanceRouteHandler = <
* This function takes a request object as an argument and returns a response object.
*/
return async function routeHandler(request: NextRequest) {
type UserParam = Params['auth'] extends false ? undefined : User;
let user: UserParam = undefined as UserParam;
// Check if the captcha token should be verified
const shouldVerifyCaptcha = params?.captcha ?? false;
@@ -80,15 +93,22 @@ export const enhanceRouteHandler = <
}
const client = getSupabaseRouteHandlerClient();
const auth = await requireUser(client);
// If the user is not authenticated, redirect to the specified URL.
if (auth.error) {
return redirect(auth.redirectTo);
const shouldVerifyAuth = params?.auth ?? true;
// Check if the user should be authenticated
if (shouldVerifyAuth) {
// Get the authenticated user
const auth = await requireUser(client);
// If the user is not authenticated, redirect to the specified URL.
if (auth.error) {
return redirect(auth.redirectTo);
}
user = auth.data as UserParam;
}
const user = auth.data;
// clone the request to read the body
// so that we can pass it to the handler safely
let body = await request.clone().json();