Skip to content

Commit

Permalink
refactor: improve responses and schema validation
Browse files Browse the repository at this point in the history
  • Loading branch information
cerinoligutom committed Jun 6, 2023
1 parent c285285 commit 26e679a
Show file tree
Hide file tree
Showing 2 changed files with 37 additions and 22 deletions.
28 changes: 15 additions & 13 deletions src/modules/user/factories/user.factory.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { GQL_User } from '@/generated/graphql/index.js';
import { ResponseUserFull, ResponseUserSimple } from '../responses/user.response.js';
import { ResponseUserFull, ResponseUserFullSchema, ResponseUserSimple, ResponseUserSimpleSchema } from '../responses/user.response.js';
import { Selectable } from 'kysely';
import { User } from '@/db/types.js';

Expand All @@ -12,6 +12,18 @@ import { User } from '@/db/types.js';
// Make sure to set the return type of the factory functions!

function createGQLUser(user: Selectable<User>): GQL_User {
/**
* Using Zod Schemas to validate GQL responses, I think, is up to you or your team.
* The GraphQL Scalar types usually handles this for us so depending on your
* preference, you can either use Zod Schemas or not.
*
* Take for example, the `Int` Scalar only accepts integer values but does not
* restrict values to be within a certain range.
* Some teams prefer making use of GraphQL Directives (https://www.apollographql.com/docs/apollo-server/schema/directives/)
* to achieve this, some prefer doing it on this level using whatever schema validation
* tool the team prefers (for this boilerplate, it's Zod.).
*/

return {
id: user.id,
firstName: user.firstName,
Expand All @@ -32,21 +44,11 @@ function createGQLUser(user: Selectable<User>): GQL_User {
}

function toFullResponse(user: Selectable<User>): ResponseUserFull {
return {
id: user.id,
firstName: user.firstName,
middleName: user.middleName,
lastName: user.lastName,
email: user.email,
createdAt: user.createdAt.toISOString(),
updatedAt: user.updatedAt.toISOString(),
};
return ResponseUserFullSchema.parse(user);
}

function toSimpleResponse(user: Selectable<User>): ResponseUserSimple {
return {
id: user.id,
};
return ResponseUserSimpleSchema.parse(user);
}

export const userFactory = {
Expand Down
31 changes: 22 additions & 9 deletions src/modules/user/responses/user.response.ts
Original file line number Diff line number Diff line change
@@ -1,13 +1,26 @@
export type ResponseUserFull = {
id: string;
firstName: string;
middleName: string | null;
lastName: string;
email: string;
createdAt: string;
updatedAt: string;
};
import { z } from 'zod';
import { UserSchema } from '@/db/schema/index.js';

export const ResponseUserFullSchema = z
.object({
id: UserSchema.shape.id,
firstName: UserSchema.shape.firstName,
middleName: UserSchema.shape.middleName,
lastName: UserSchema.shape.lastName,
email: UserSchema.shape.email,
createdAt: UserSchema.shape.createdAt,
updatedAt: UserSchema.shape.updatedAt,
})
.extend({
// We need the date objects to be serialized but in valid datetime format.
createdAt: z.string().datetime(),
updatedAt: z.string().datetime(),
});
export type ResponseUserFull = z.infer<typeof ResponseUserFullSchema>;

export const ResponseUserSimpleSchema = z.object({
id: UserSchema.shape.id,
});
export type ResponseUserSimple = {
id: string;
};

0 comments on commit 26e679a

Please sign in to comment.