Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[zod-openapi] Question - Generic createRoute generator #725

Open
DBain07 opened this issue Sep 1, 2024 · 0 comments
Open

[zod-openapi] Question - Generic createRoute generator #725

DBain07 opened this issue Sep 1, 2024 · 0 comments

Comments

@DBain07
Copy link

DBain07 commented Sep 1, 2024

I would like to hear opinions on something like this. I was just trying to think of ways to further simplify creating new routes to reduce duplication.

import type {
  ResponseConfig,
  RouteParameter,
  ZodRequestBody,
} from '@asteasolutions/zod-to-openapi/dist/openapi-registry.js';
import { createRoute, type RouteConfig } from '@hono/zod-openapi';
import type { StatusCode } from 'hono/utils/http-status';
import type { ZodSchema } from 'zod';
import type { Scopes } from '../env/scopes.mjs';
import {
  generateScopeDescription,
  validateCallerScopes,
} from '../middlewares/validate-caller-scopes/validate-caller-scopes.middleware.mjs';
import { getFilteredCommonResponses } from './filter-common-responses.utils.mjs';

const security = [{ 'x-api-key': [] }];

interface RouteOptions {
  method: 'get' | 'post' | 'patch' | 'delete';
  path: string;
  paramsSchema?: RouteParameter;
  bodySchema?: ZodRequestBody;
  scopes: Scopes[];
  tags: string[];
  description: string;
  successSchema: ZodSchema<unknown>;
  requiredResponses: StatusCode[];
  additionalResponses?: Record<number, any>;
  isPublic?: boolean;
}

export function createGenericRoute<
  TRequest extends RouteConfig['request'] | undefined,
  TResponse extends { [key in StatusCode]?: ResponseConfig },
>(options: RouteOptions) {
  const filteredCommonResponses = getFilteredCommonResponses(
    options.requiredResponses,
  );
  return createRoute({
    method: options.method,
    path: options.path,
    request: {
      // add query and whatnot
      ...(options.paramsSchema
        ? { params: options.paramsSchema }
        : { params: undefined }),
      ...(options.bodySchema
        ? {
            body: {
              content: { 'application/json': { schema: options.bodySchema } },
            },
          }
        : { body: undefined }),
    } as TRequest,
    // type?
    middleware: options.isPublic
      ? []
      : [validateCallerScopes<Scopes>({ scopes: options.scopes })],
    responses: {
      200: {
        content: {
          'application/json': {
            schema: options.successSchema,
          },
        },
        description: 'Success',
      },
      ...filteredCommonResponses,
      ...options.additionalResponses,
      // any way to remove as unknown
    } as unknown as TResponse,
    // dynamoic security
    security: options.isPublic ? [] : security,
    tags: options.tags,
    description: [
      options.description,
      generateScopeDescription<Scopes>(options.scopes),
    ].join('\n'),
  });
}

and its usage:

export const updateUserIdRoute = createGenericRoute<
  {
    params: typeof EmailToUserIdParamsSchema;
    body: typeof requestBody;
  },
  typeof res
>({
  method: 'patch',
  path: '/userId/{email}',
  paramsSchema: ParamsSchema,
  bodySchema: getRequestBodySchema(User),
  scopes: ['plane:service:update:user'],
  tags: ['User'],
  description: 'Updates information associated with user.',
  successSchema: User,
  requiredResponses: [400, 401, 403, 409, 500],
});
@DBain07 DBain07 changed the title Discussion - Generic createRoute generator [zod-openai] - Discussion - Generic createRoute generator Sep 1, 2024
@DBain07 DBain07 changed the title [zod-openai] - Discussion - Generic createRoute generator [zod-openapi] - Discussion - Generic createRoute generator Sep 1, 2024
@DBain07 DBain07 changed the title [zod-openapi] - Discussion - Generic createRoute generator [zod-openapi] Question - Generic createRoute generator Sep 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant