diff --git a/packages/api-client/src/controllers/user.ts b/packages/api-client/src/controllers/user.ts index 85dab4df..ff83d904 100644 --- a/packages/api-client/src/controllers/user.ts +++ b/packages/api-client/src/controllers/user.ts @@ -10,7 +10,7 @@ import { ResendEmailChangeOTPRequest, DeleteSelfResponse, ResendEmailChangeOTPResponse -} from '@api-client/types/user.types' +} from '@keyshade/schema' export default class UserController { private apiClient: APIClient diff --git a/packages/api-client/src/types/user.types.d.ts b/packages/api-client/src/types/user.types.d.ts deleted file mode 100644 index dde1907c..00000000 --- a/packages/api-client/src/types/user.types.d.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { Workspace } from '@keyshade/schema' - -export interface GetSelfResponse { - id: string - email: string - name: string - profilePictureUrl: string | null - isActive: boolean - isOnboardingFinished: boolean - isAdmin: boolean - authProvider: string - defaultWorkspace: Workspace -} -export interface UpdateSelfRequest { - name?: string - profilePictureUrl?: string - isOnboardingFinished?: boolean - email?: string -} -export interface UpdateSelfResponse - extends Partial> {} - -export interface DeleteSelfRequest {} -export interface DeleteSelfResponse {} - -export interface ValidateEmailChangeOTPRequest { - otp: string -} -export interface ValidateEmailChangeOTPResponse - extends Partial> {} - -export interface ResendEmailChangeOTPRequest {} -export interface ResendEmailChangeOTPResponse {} diff --git a/packages/schema/src/index.ts b/packages/schema/src/index.ts index b7a78ad8..dc097cda 100644 --- a/packages/schema/src/index.ts +++ b/packages/schema/src/index.ts @@ -6,14 +6,17 @@ export * from './api-key' export * from './auth/auth' +export * from './enums' + export * from './environment' export * from './integration' export * from './project' export * from './secret' + +export * from './user/user' + export * from './variable' export * from './workspace/workspace' export * from './workspace-role' - -export * from './enums' diff --git a/packages/schema/src/index.types.ts b/packages/schema/src/index.types.ts index f9d3511c..da5a840b 100644 --- a/packages/schema/src/index.types.ts +++ b/packages/schema/src/index.types.ts @@ -36,6 +36,9 @@ export type TForkProject = z.infer export type TCreateSecret = z.infer export type TUpdateSecret = z.infer +// Export types from user.types.ts +export * from './user/user.types' + export type TCreateVariable = z.infer export type TUpdateVariable = z.infer diff --git a/packages/schema/src/user/user.ts b/packages/schema/src/user/user.ts new file mode 100644 index 00000000..18c3d610 --- /dev/null +++ b/packages/schema/src/user/user.ts @@ -0,0 +1,42 @@ +import { z } from 'zod' +import { WorkspaceSchema } from '@/workspace/workspace' + +export const GetSelfResponseSchema = z.object({ + id: z.string(), + email: z.string().email(), + name: z.string(), + profilePictureUrl: z.string().nullable(), + isActive: z.boolean(), + isOnboardingFinished: z.boolean(), + isAdmin: z.boolean(), + authProvider: z.string(), + defaultWorkspace: WorkspaceSchema +}) + +export const UpdateSelfRequestSchema = z.object({ + name: z.string().optional(), + profilePictureUrl: z.string().optional(), + isOnboardingFinished: z.boolean().optional(), + email: z.string().email().optional() +}) + +export const UpdateSelfResponseSchema = GetSelfResponseSchema.partial().omit({ + defaultWorkspace: true +}) + +export const DeleteSelfRequestSchema = z.void() + +export const DeleteSelfResponseSchema = z.void() + +export const ValidateEmailChangeOTPRequestSchema = z.object({ + otp: z.string() +}) + +export const ValidateEmailChangeOTPResponseSchema = + GetSelfResponseSchema.partial().omit({ + defaultWorkspace: true + }) + +export const ResendEmailChangeOTPRequestSchema = z.void() + +export const ResendEmailChangeOTPResponseSchema = z.void() diff --git a/packages/schema/src/user/user.types.ts b/packages/schema/src/user/user.types.ts new file mode 100644 index 00000000..365015d0 --- /dev/null +++ b/packages/schema/src/user/user.types.ts @@ -0,0 +1,38 @@ +import { z } from 'zod' +import { + GetSelfResponseSchema, + UpdateSelfRequestSchema, + UpdateSelfResponseSchema, + DeleteSelfRequestSchema, + DeleteSelfResponseSchema, + ValidateEmailChangeOTPRequestSchema, + ValidateEmailChangeOTPResponseSchema, + ResendEmailChangeOTPRequestSchema, + ResendEmailChangeOTPResponseSchema +} from './user' + +export type GetSelfResponse = z.infer + +export type UpdateSelfRequest = z.infer + +export type UpdateSelfResponse = z.infer + +export type DeleteSelfRequest = z.infer + +export type DeleteSelfResponse = z.infer + +export type ValidateEmailChangeOTPRequest = z.infer< + typeof ValidateEmailChangeOTPRequestSchema +> + +export type ValidateEmailChangeOTPResponse = z.infer< + typeof ValidateEmailChangeOTPResponseSchema +> + +export type ResendEmailChangeOTPRequest = z.infer< + typeof ResendEmailChangeOTPRequestSchema +> + +export type ResendEmailChangeOTPResponse = z.infer< + typeof ResendEmailChangeOTPResponseSchema +> diff --git a/packages/schema/tests/user.spec.ts b/packages/schema/tests/user.spec.ts new file mode 100644 index 00000000..dbc051e7 --- /dev/null +++ b/packages/schema/tests/user.spec.ts @@ -0,0 +1,181 @@ +import { + GetSelfResponseSchema, + UpdateSelfRequestSchema, + UpdateSelfResponseSchema, + DeleteSelfRequestSchema, + DeleteSelfResponseSchema, + ValidateEmailChangeOTPRequestSchema, + ValidateEmailChangeOTPResponseSchema, + ResendEmailChangeOTPRequestSchema, + ResendEmailChangeOTPResponseSchema +} from '@/user/user' + +describe('User Schema Tests', () => { + // Tests for GetSelfResponseSchema + it('should validate a valid GetSelfResponseSchema', () => { + const result = GetSelfResponseSchema.safeParse({ + id: 'user123', + email: 'user@example.com', + name: 'John Doe', + profilePictureUrl: null, + isActive: true, + isOnboardingFinished: false, + isAdmin: false, + authProvider: 'email', + defaultWorkspace: { + id: 'workspace123', + name: 'My Workspace', + slug: 'my-workspace', + icon: 'icon.png', + isFreeTier: true, + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + ownerId: 'owner123', + isDefault: true, + lastUpdatedBy: 'user123' + } + }) + expect(result.success).toBe(true) + }) + + it('should fail validation for invalid GetSelfResponseSchema', () => { + const result = GetSelfResponseSchema.safeParse({ + email: 'invalid-email', + name: 'John Doe' + // Missing required fields and invalid email + }) + expect(result.success).toBe(false) + expect(result.error?.issues.length).toBe(8) + }) + + // Tests for UpdateSelfRequestSchema + it('should validate a valid UpdateSelfRequestSchema', () => { + const result = UpdateSelfRequestSchema.safeParse({ + name: 'Jane Doe', + email: 'jane@example.com', + isOnboardingFinished: true + }) + expect(result.success).toBe(true) + }) + + it('should fail validation for invalid UpdateSelfRequestSchema', () => { + const result = UpdateSelfRequestSchema.safeParse({ + email: 'invalid-email-format' + }) + expect(result.success).toBe(false) + expect(result.error?.issues.length).toBe(1) + }) + + // Tests for UpdateSelfResponseSchema + it('should validate a valid UpdateSelfResponseSchema', () => { + const result = UpdateSelfResponseSchema.safeParse({ + id: 'user123', + email: 'jane@example.com', + name: 'Jane Doe', + isActive: true + }) + expect(result.success).toBe(true) + }) + + it('should fail validation for invalid UpdateSelfResponseSchema', () => { + const result = UpdateSelfResponseSchema.safeParse({ + id: 123, // Should be a string + email: 'jane@example.com' + }) + expect(result.success).toBe(false) + expect(result.error?.issues.length).toBe(1) + }) + + // Tests for DeleteSelfRequestSchema + it('should validate a valid DeleteSelfRequestSchema', () => { + const result = DeleteSelfRequestSchema.safeParse(undefined) + expect(result.success).toBe(true) + }) + + it('should fail validation for invalid DeleteSelfRequestSchema', () => { + const result = DeleteSelfRequestSchema.safeParse({ + unexpectedField: 'value' + }) + expect(result.success).toBe(false) + expect(result.error?.issues.length).toBe(1) + }) + + // Tests for DeleteSelfResponseSchema + it('should validate a valid DeleteSelfResponseSchema', () => { + const result = DeleteSelfResponseSchema.safeParse(undefined) + expect(result.success).toBe(true) + }) + + it('should fail validation for invalid DeleteSelfResponseSchema', () => { + const result = DeleteSelfResponseSchema.safeParse({ + success: true + }) + expect(result.success).toBe(false) + expect(result.error?.issues.length).toBe(1) + }) + + // Tests for ValidateEmailChangeOTPRequestSchema + it('should validate a valid ValidateEmailChangeOTPRequestSchema', () => { + const result = ValidateEmailChangeOTPRequestSchema.safeParse({ + otp: '123456' + }) + expect(result.success).toBe(true) + }) + + it('should fail validation for invalid ValidateEmailChangeOTPRequestSchema', () => { + const result = ValidateEmailChangeOTPRequestSchema.safeParse({ + otp: 123456 // Should be a string + }) + expect(result.success).toBe(false) + expect(result.error?.issues.length).toBe(1) + }) + + // Tests for ValidateEmailChangeOTPResponseSchema + it('should validate a valid ValidateEmailChangeOTPResponseSchema', () => { + const result = ValidateEmailChangeOTPResponseSchema.safeParse({ + id: 'user123', + email: 'user@example.com', + name: 'John Doe', + profilePictureUrl: null, + isActive: true, + isOnboardingFinished: false, + isAdmin: false, + authProvider: 'email' + }) + expect(result.success).toBe(true) + }) + + it('should fail validation for invalid ValidateEmailChangeOTPResponseSchema', () => { + const result = ValidateEmailChangeOTPResponseSchema.safeParse(undefined) + expect(result.success).toBe(false) + expect(result.error?.issues.length).toBe(1) + }) + + // Tests for ResendEmailChangeOTPRequestSchema + it('should validate a valid ResendEmailChangeOTPRequestSchema', () => { + const result = ResendEmailChangeOTPRequestSchema.safeParse(undefined) + expect(result.success).toBe(true) + }) + + it('should fail validation for invalid ResendEmailChangeOTPRequestSchema', () => { + const result = ResendEmailChangeOTPRequestSchema.safeParse({ + extraField: 'value' // Should not have any fields + }) + expect(result.success).toBe(false) + expect(result.error?.issues.length).toBe(1) + }) + + // Tests for ResendEmailChangeOTPResponseSchema + it('should validate a valid ResendEmailChangeOTPResponseSchema', () => { + const result = ResendEmailChangeOTPResponseSchema.safeParse(undefined) + expect(result.success).toBe(true) + }) + + it('should fail validation for invalid ResendEmailChangeOTPResponseSchema', () => { + const result = ResendEmailChangeOTPResponseSchema.safeParse({ + success: true + }) + expect(result.success).toBe(false) + expect(result.error?.issues.length).toBe(1) + }) +})