diff --git a/packages/api-client/src/controllers/environment.ts b/packages/api-client/src/controllers/environment.ts index 67f21b0e..8a002f86 100644 --- a/packages/api-client/src/controllers/environment.ts +++ b/packages/api-client/src/controllers/environment.ts @@ -12,7 +12,7 @@ import { GetEnvironmentResponse, UpdateEnvironmentRequest, UpdateEnvironmentResponse -} from '@api-client/types/environment.types' +} from '@keyshade/schema' import { ClientResponse } from '@keyshade/schema' export default class EnvironmentController { diff --git a/packages/api-client/src/controllers/project.ts b/packages/api-client/src/controllers/project.ts index 7c2bfae9..33921885 100644 --- a/packages/api-client/src/controllers/project.ts +++ b/packages/api-client/src/controllers/project.ts @@ -19,7 +19,7 @@ import { UnlinkProjectResponse, UpdateProjectRequest, UpdateProjectResponse -} from '@api-client/types/project.types' +} from '@keyshade/schema' import { parseResponse } from '@api-client/core/response-parser' import { parsePaginationUrl } from '@api-client/core/pagination-parser' diff --git a/packages/api-client/src/types/environment.types.d.ts b/packages/api-client/src/types/environment.types.d.ts deleted file mode 100644 index fab55d8f..00000000 --- a/packages/api-client/src/types/environment.types.d.ts +++ /dev/null @@ -1,55 +0,0 @@ -import { PageRequest, PageResponse } from '@keyshade/schema' - -export interface Environment { - id: string - name: string - slug: string - description: string | null - createdAt: string - updatedAt: string - lastUpdatedById: string - projectId: string -} - -export interface CreateEnvironmentRequest { - name: string - description?: string - projectId: string -} - -export interface CreateEnvironmentResponse extends Environment {} - -export interface UpdateEnvironmentRequest - extends Partial> { - slug: string -} - -export interface UpdateEnvironmentResponse extends Environment {} - -export interface GetEnvironmentRequest { - slug: string -} - -export interface GetEnvironmentResponse extends Environment {} - -export interface GetAllEnvironmentsOfProjectRequest extends PageRequest { - projectSlug: string -} - -export interface GetAllEnvironmentsOfProjectResponse - extends PageResponse< - Environment & { - lastUpdatedBy: { - id: string - name: string - email: string - profilePictureUrl: string | null - } - } - > {} - -export interface DeleteEnvironmentRequest { - slug: string -} - -export interface DeleteEnvironmentResponse {} diff --git a/packages/api-client/src/types/project.types.d.ts b/packages/api-client/src/types/project.types.d.ts deleted file mode 100644 index 0cb2db81..00000000 --- a/packages/api-client/src/types/project.types.d.ts +++ /dev/null @@ -1,87 +0,0 @@ -import { PageRequest, PageResponse } from '@keyshade/schema' - -export interface Project { - id: string - name: string - slug: string - description: string - createdAt: string - updatedAt: string - publicKey: string - privateKey: string - storePrivateKey: boolean - isDisabled: boolean - accessLevel: string - pendingCreation: boolean - isForked: boolean - lastUpdatedById: string - workspaceId: string - forkedFromId: string -} - -export interface CreateProjectRequest { - name: string - workspaceSlug: string - description?: string - storePrivateKey?: boolean - environments?: CreateEnvironment[] - accessLevel: string -} - -export interface CreateProjectResponse extends Project {} - -export interface UpdateProjectRequest - extends Partial> { - projectSlug: string - regenerateKeyPair?: boolean - privateKey?: string -} - -export interface UpdateProjectResponse extends Project {} - -export interface DeleteProjectRequest { - projectSlug: string -} - -export interface DeleteProjectResponse {} - -export interface GetProjectRequest { - projectSlug: string -} - -export interface GetProjectResponse extends Project {} - -export interface ForkProjectRequest { - projectSlug: string - name?: string - workspaceSlug?: string - storePrivateKey?: boolean -} - -export interface ForkProjectResponse extends Project {} - -export interface SyncProjectRequest { - projectSlug: string - hardSync?: boolean -} - -export interface SyncProjectResponse {} - -export interface UnlinkProjectRequest { - projectSlug: string -} - -export interface UnlinkProjectResponse {} - -export interface GetForkRequest extends PageRequest { - projectSlug: string - workspaceSlug: string -} - -export interface GetForkResponse extends PageResponse {} - -export interface GetAllProjectsRequest extends PageRequest { - workspaceSlug: string -} - -export interface GetAllProjectsResponse extends PageResponse {} diff --git a/packages/schema/src/environment.ts b/packages/schema/src/environment.ts deleted file mode 100644 index 834acb4e..00000000 --- a/packages/schema/src/environment.ts +++ /dev/null @@ -1,8 +0,0 @@ -import { z } from 'zod' - -export const CreateEnvironmentSchema = z.object({ - name: z.string(), - description: z.string().optional() -}) - -export const UpdateEnvironmentSchema = CreateEnvironmentSchema.partial() diff --git a/packages/schema/src/environment/index.ts b/packages/schema/src/environment/index.ts new file mode 100644 index 00000000..1ca54ad2 --- /dev/null +++ b/packages/schema/src/environment/index.ts @@ -0,0 +1,56 @@ +import { z } from 'zod' +import { PageRequestSchema, PageResponseSchema } from '@/pagination/pagination' + +export const EnvironmentSchema = z.object({ + id: z.string(), + name: z.string(), + slug: z.string(), + description: z.string().nullable(), + createdAt: z.string(), + updatedAt: z.string(), + lastUpdatedById: z.string(), + projectId: z.string() +}) + +export const CreateEnvironmentRequestSchema = z.object({ + name: z.string(), + description: z.string().optional(), + projectId: z.string() +}) + +export const CreateEnvironmentResponseSchema = EnvironmentSchema + +export const UpdateEnvironmentRequestSchema = + CreateEnvironmentRequestSchema.omit({ projectId: true }) + .partial() + .extend({ slug: z.string() }) + +export const UpdateEnvironmentResponseSchema = EnvironmentSchema + +export const GetEnvironmentRequestSchema = z.object({ + slug: z.string() +}) + +export const GetEnvironmentResponseSchema = EnvironmentSchema + +export const GetAllEnvironmentsOfProjectRequestSchema = + PageRequestSchema.extend({ + projectSlug: z.string() + }) + +export const GetAllEnvironmentsOfProjectResponseSchema = PageResponseSchema( + EnvironmentSchema.extend({ + lastUpdatedBy: z.object({ + id: z.string(), + name: z.string(), + email: z.string(), + profilePictureUrl: z.string().nullable() + }) + }) +) + +export const DeleteEnvironmentRequestSchema = z.object({ + slug: z.string() +}) + +export const DeleteEnvironmentResponseSchema = z.void() diff --git a/packages/schema/src/environment/index.types.ts b/packages/schema/src/environment/index.types.ts new file mode 100644 index 00000000..a042bc00 --- /dev/null +++ b/packages/schema/src/environment/index.types.ts @@ -0,0 +1,54 @@ +import { z } from 'zod' +import { + EnvironmentSchema, + CreateEnvironmentRequestSchema, + CreateEnvironmentResponseSchema, + UpdateEnvironmentRequestSchema, + UpdateEnvironmentResponseSchema, + GetEnvironmentRequestSchema, + GetEnvironmentResponseSchema, + GetAllEnvironmentsOfProjectRequestSchema, + GetAllEnvironmentsOfProjectResponseSchema, + DeleteEnvironmentRequestSchema, + DeleteEnvironmentResponseSchema +} from '.' + +export type Environment = z.infer + +export type CreateEnvironmentRequest = z.infer< + typeof CreateEnvironmentRequestSchema +> + +export type CreateEnvironmentResponse = z.infer< + typeof CreateEnvironmentResponseSchema +> + +export type UpdateEnvironmentRequest = z.infer< + typeof UpdateEnvironmentRequestSchema +> + +export type UpdateEnvironmentResponse = z.infer< + typeof UpdateEnvironmentResponseSchema +> + +export type GetEnvironmentRequest = z.infer + +export type GetEnvironmentResponse = z.infer< + typeof GetEnvironmentResponseSchema +> + +export type GetAllEnvironmentsOfProjectRequest = z.infer< + typeof GetAllEnvironmentsOfProjectRequestSchema +> + +export type GetAllEnvironmentsOfProjectResponse = z.infer< + typeof GetAllEnvironmentsOfProjectResponseSchema +> + +export type DeleteEnvironmentRequest = z.infer< + typeof DeleteEnvironmentRequestSchema +> + +export type DeleteEnvironmentResponse = z.infer< + typeof DeleteEnvironmentResponseSchema +> diff --git a/packages/schema/src/index.ts b/packages/schema/src/index.ts index fe0f46c3..c735fd4c 100644 --- a/packages/schema/src/index.ts +++ b/packages/schema/src/index.ts @@ -7,7 +7,6 @@ export * from './api-key' export * from './auth/auth' export * from './enums' - export * from './environment' export * from './integration' export * from './project' diff --git a/packages/schema/src/index.types.ts b/packages/schema/src/index.types.ts index 27cc9615..3c683178 100644 --- a/packages/schema/src/index.types.ts +++ b/packages/schema/src/index.types.ts @@ -1,12 +1,6 @@ import { z } from 'zod' import { CreateApiKeySchema, UpdateApiKeySchema } from './api-key' -import { CreateEnvironmentSchema, UpdateEnvironmentSchema } from './environment' import { CreateIntegrationSchema, UpdateIntegrationSchema } from './integration' -import { - CreateProjectSchema, - ForkProjectSchema, - UpdateProjectSchema -} from './project' import { CreateSecretSchema, UpdateSecretSchema } from './secret' import { CreateVariableSchema, UpdateVariableSchema } from './variable' import { @@ -23,15 +17,12 @@ export type TUpdateApiKey = z.infer // Export types from auth.types.ts export * from './auth/auth.types' -export type TCreateEnvironment = z.infer -export type TUpdateEnvironment = z.infer +export * from './environment/index.types' export type TCreateIntegration = z.infer export type TUpdateIntegration = z.infer -export type TCreateProject = z.infer -export type TUpdateProject = z.infer -export type TForkProject = z.infer +export * from './project/index.types' export type TCreateSecret = z.infer export type TUpdateSecret = z.infer diff --git a/packages/schema/src/project.ts b/packages/schema/src/project.ts deleted file mode 100644 index c53afc9b..00000000 --- a/packages/schema/src/project.ts +++ /dev/null @@ -1,19 +0,0 @@ -import { z } from 'zod' -import { projectAccessLevelEnum } from '@/enums' -import { CreateEnvironmentSchema } from './environment' - -export const CreateProjectSchema = z.object({ - name: z.string(), - description: z.string().optional(), - storePrivateKey: z.boolean().optional(), - accessLevel: projectAccessLevelEnum, - environments: z.array(CreateEnvironmentSchema).optional() -}) - -export const UpdateProjectSchema = CreateProjectSchema.partial() - -export const ForkProjectSchema = z.object({ - workspaceId: z.string().optional(), - name: z.string().optional(), - storePrivateKey: z.boolean().optional() -}) diff --git a/packages/schema/src/project/index.ts b/packages/schema/src/project/index.ts new file mode 100644 index 00000000..ea9bd720 --- /dev/null +++ b/packages/schema/src/project/index.ts @@ -0,0 +1,99 @@ +import { z } from 'zod' +import { PageRequestSchema, PageResponseSchema } from '@/pagination/pagination' +import { CreateEnvironmentRequestSchema } from '@/environment' +import { projectAccessLevelEnum } from '@/enums' + +export const ProjectSchema = z + .object({ + id: z.string(), + name: z.string(), + slug: z.string(), + description: z.string(), + createdAt: z.string(), + updatedAt: z.string(), + publicKey: z.string(), + privateKey: z.string(), + storePrivateKey: z.boolean(), + isDisabled: z.boolean(), + accessLevel: z.string(), + pendingCreation: z.boolean(), + isForked: z.boolean(), + lastUpdatedById: z.string(), + workspaceId: z.string(), + forkedFromId: z.string().nullable() + }) + .refine((obj) => + obj.isForked ? obj.forkedFromId !== null : obj.forkedFromId === null + ) + +export const CreateProjectRequestSchema = z.object({ + name: z.string(), + workspaceSlug: z.string(), + description: z.string().optional(), + storePrivateKey: z.boolean().optional(), + environments: CreateEnvironmentRequestSchema.array().optional(), + accessLevel: projectAccessLevelEnum +}) + +export const CreateProjectResponseSchema = ProjectSchema + +export const UpdateProjectRequestSchema = CreateProjectRequestSchema.partial() + .omit({ + workspaceSlug: true + }) + .merge( + z.object({ + projectSlug: z.string(), + regenerateKeyPair: z.boolean().optional(), + privateKey: z.string().optional() + }) + ) + +export const UpdateProjectResponseSchema = ProjectSchema + +export const DeleteProjectRequestSchema = z.object({ + projectSlug: z.string() +}) + +export const DeleteProjectResponseSchema = z.void() + +export const GetProjectRequestSchema = z.object({ + projectSlug: z.string() +}) + +export const GetProjectResponseSchema = ProjectSchema + +export const ForkProjectRequestSchema = z.object({ + projectSlug: z.string(), + name: z.string().optional(), + workspaceSlug: z.string().optional(), + storePrivateKey: z.boolean().optional() +}) + +export const ForkProjectResponseSchema = ProjectSchema + +export const SyncProjectRequestSchema = z.object({ + projectSlug: z.string(), + hardSync: z.boolean().optional() +}) + +export const SyncProjectResponseSchema = z.void() + +export const UnlinkProjectRequestSchema = z.object({ + projectSlug: z.string() +}) + +export const UnlinkProjectResponseSchema = z.void() + +export const GetForkRequestSchema = PageRequestSchema.extend({ + projectSlug: z.string(), + workspaceSlug: z.string() +}) + +export const GetForkResponseSchema = PageResponseSchema(ProjectSchema) + +export const GetAllProjectsRequestSchema = PageRequestSchema.extend({ + workspaceSlug: z.string() +}) + +export const GetAllProjectsResponseSchema = PageResponseSchema(ProjectSchema) diff --git a/packages/schema/src/project/index.types.ts b/packages/schema/src/project/index.types.ts new file mode 100644 index 00000000..eed00025 --- /dev/null +++ b/packages/schema/src/project/index.types.ts @@ -0,0 +1,62 @@ +import { z } from 'zod' +import { + ProjectSchema, + CreateProjectRequestSchema, + CreateProjectResponseSchema, + UpdateProjectRequestSchema, + UpdateProjectResponseSchema, + DeleteProjectRequestSchema, + DeleteProjectResponseSchema, + GetProjectRequestSchema, + GetProjectResponseSchema, + ForkProjectRequestSchema, + ForkProjectResponseSchema, + SyncProjectRequestSchema, + SyncProjectResponseSchema, + UnlinkProjectRequestSchema, + UnlinkProjectResponseSchema, + GetForkRequestSchema, + GetForkResponseSchema, + GetAllProjectsRequestSchema, + GetAllProjectsResponseSchema +} from '.' + +export type Project = z.infer + +export type CreateProjectRequest = z.infer + +export type CreateProjectResponse = z.infer + +export type UpdateProjectRequest = z.infer + +export type UpdateProjectResponse = z.infer + +export type DeleteProjectRequest = z.infer + +export type DeleteProjectResponse = z.infer + +export type GetProjectRequest = z.infer + +export type GetProjectResponse = z.infer + +export type ForkProjectRequest = z.infer + +export type ForkProjectResponse = z.infer + +export type SyncProjectRequest = z.infer + +export type SyncProjectResponse = z.infer + +export type UnlinkProjectRequest = z.infer + +export type UnlinkProjectResponse = z.infer + +export type GetForkRequest = z.infer + +export type GetForkResponse = z.infer + +export type GetAllProjectsRequest = z.infer + +export type GetAllProjectsResponse = z.infer< + typeof GetAllProjectsResponseSchema +> diff --git a/packages/schema/tests/environment.spec.ts b/packages/schema/tests/environment.spec.ts index 0adbb494..1a161d6e 100644 --- a/packages/schema/tests/environment.spec.ts +++ b/packages/schema/tests/environment.spec.ts @@ -1,27 +1,331 @@ -import { CreateEnvironmentSchema } from '@/environment' +import { + EnvironmentSchema, + CreateEnvironmentRequestSchema, + CreateEnvironmentResponseSchema, + UpdateEnvironmentRequestSchema, + UpdateEnvironmentResponseSchema, + GetEnvironmentRequestSchema, + GetEnvironmentResponseSchema, + GetAllEnvironmentsOfProjectRequestSchema, + GetAllEnvironmentsOfProjectResponseSchema, + DeleteEnvironmentRequestSchema, + DeleteEnvironmentResponseSchema +} from '@/environment' describe('Environment Schema Tests', () => { - it('should validate if proper input is specified', () => { - const result = CreateEnvironmentSchema.safeParse({ + // Tests for EnvironmentSchema + it('should validate a valid EnvironmentSchema', () => { + const result = EnvironmentSchema.safeParse({ + id: 'env123', + name: 'Development', + slug: 'development', + description: null, + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + lastUpdatedById: 'user123', + projectId: 'project123' + }) + expect(result.success).toBe(true) + }) + + it('should not validate an invalid EnvironmentSchema with missing fields', () => { + const result = EnvironmentSchema.safeParse({ + id: 'env123', + name: 'Development' + // Missing required fields + }) + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(6) + }) + + it('should not validate an invalid EnvironmentSchema with incorrect types', () => { + const result = EnvironmentSchema.safeParse({ + id: 'env123', + name: 'Development', + slug: 'development', + description: 'Development environment', + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + lastUpdatedById: 'user123', + projectId: 123 // Should be a string + }) + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) + }) + + // Tests for CreateEnvironmentRequestSchema + it('should validate if proper input is specified for CreateEnvironmentRequestSchema', () => { + const result = CreateEnvironmentRequestSchema.safeParse({ + name: 'test', + description: 'test description', + projectId: 'project123' + }) + expect(result.success).toBe(true) + }) + + it('should not validate if invalid values are specified for CreateEnvironmentRequestSchema', () => { + const result = CreateEnvironmentRequestSchema.safeParse({ + name: 123, + projectId: 'project123' + }) + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) + }) + + it('should not validate if required values are not specified for CreateEnvironmentRequestSchema', () => { + const result = CreateEnvironmentRequestSchema.safeParse({ name: 'test' }) + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) + }) + + // Tests for CreateEnvironmentResponseSchema + it('should validate a valid CreateEnvironmentResponseSchema', () => { + const result = CreateEnvironmentResponseSchema.safeParse({ + id: 'env123', + name: 'Development', + slug: 'development', + description: 'Development environment', + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + lastUpdatedById: 'user123', + projectId: 'project123' + }) + expect(result.success).toBe(true) + }) + + it('should not validate an invalid CreateEnvironmentResponseSchema with multiple incorrect types', () => { + const result = CreateEnvironmentResponseSchema.safeParse({ + id: 123, // Should be a string + name: 'Development', + slug: 'development', + description: 456, // Should be a string or null + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + lastUpdatedById: 'user123', + projectId: true // Should be a string + }) + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(3) + }) + + // Tests for UpdateEnvironmentRequestSchema + it('should validate if proper input is specified for UpdateEnvironmentRequestSchema', () => { + const result = UpdateEnvironmentRequestSchema.safeParse({ + name: 'updatedTest', + slug: 'updated-slug' + }) + expect(result.success).toBe(true) + }) + + it('should not validate if invalid values are specified for UpdateEnvironmentRequestSchema', () => { + const result = UpdateEnvironmentRequestSchema.safeParse({ + name: 123, + slug: 'updated-slug' + }) + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) + }) + + // Tests for UpdateEnvironmentResponseSchema + it('should validate a valid UpdateEnvironmentResponseSchema', () => { + const result = UpdateEnvironmentResponseSchema.safeParse({ + id: 'env123', + name: 'Development', + slug: 'development', + description: 'Development environment', + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + lastUpdatedById: 'user123', + projectId: 'project123' + }) + expect(result.success).toBe(true) + }) + it('should not validate an invalid UpdateEnvironmentResponseSchema with multiple incorrect types', () => { + const result = UpdateEnvironmentResponseSchema.safeParse({ + id: 123, // Should be a string + name: 'Development', + slug: 'development', + description: 456, // Should be a string or null + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + lastUpdatedById: 'user123', + projectId: true // Should be a string + }) + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(3) + }) + + // Tests for GetEnvironmentRequestSchema + it('should validate if proper input is specified for GetEnvironmentRequestSchema', () => { + const result = GetEnvironmentRequestSchema.safeParse({ + slug: 'test-slug' + }) expect(result.success).toBe(true) }) - it('should not validate if invalid values are specified', () => { - const result = CreateEnvironmentSchema.safeParse({ - name: 123 + it('should not validate if invalid values are specified for GetEnvironmentRequestSchema', () => { + const result = GetEnvironmentRequestSchema.safeParse({ + slug: 123 + }) + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) + }) + + // Tests for GetEnvironmentResponseSchema + it('should validate a valid GetEnvironmentResponseSchema', () => { + const result = GetEnvironmentResponseSchema.safeParse({ + id: 'env123', + name: 'Development', + slug: 'development', + description: 'Development environment', + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + lastUpdatedById: 'user123', + projectId: 'project123' }) + expect(result.success).toBe(true) + }) + it('should not validate an invalid GetEnvironmentResponseSchema with multiple incorrect types', () => { + const result = GetEnvironmentResponseSchema.safeParse({ + id: 123, // Should be a string + name: 'Development', + slug: 'development', + description: 456, // Should be a string or null + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + lastUpdatedById: 'user123', + projectId: true // Should be a string + }) + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(3) + }) + + // Tests for GetAllEnvironmentsOfProjectRequestSchema + it('should validate if proper input is specified for GetAllEnvironmentsOfProjectRequestSchema', () => { + const result = GetAllEnvironmentsOfProjectRequestSchema.safeParse({ + projectSlug: 'project-slug', + page: 1, + limit: 10 + }) + expect(result.success).toBe(true) + }) + + it('should not validate if invalid values are specified for GetAllEnvironmentsOfProjectRequestSchema', () => { + const result = GetAllEnvironmentsOfProjectRequestSchema.safeParse({ + projectSlug: 123, + page: 'one', + limit: 'ten' + }) + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(3) + }) + + // Tests for GetAllEnvironmentsOfProjectResponseSchema + it('should validate a valid GetAllEnvironmentsOfProjectResponseSchema', () => { + const result = GetAllEnvironmentsOfProjectResponseSchema.safeParse({ + items: [ + { + id: 'env123', + name: 'Development', + slug: 'development', + description: 'Development environment', + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + lastUpdatedById: 'user123', + projectId: 'project123', + lastUpdatedBy: { + id: 'user123', + name: 'John Doe', + email: 'john.doe@example.com', + profilePictureUrl: 'http://example.com/profile.jpg' + } + } + ], + metadata: { + page: 1, + perPage: 10, + pageCount: 1, + totalCount: 1, + links: { + self: 'http://example.com/page/1', + first: 'http://example.com/page/1', + previous: null, + next: null, + last: 'http://example.com/page/1' + } + } + }) + expect(result.success).toBe(true) + }) + + it('should not validate an invalid GetAllEnvironmentsOfProjectResponseSchema with incorrect types', () => { + const result = GetAllEnvironmentsOfProjectResponseSchema.safeParse({ + items: [ + { + id: 'env123', + name: 'Development', + slug: 'development', + description: 'Development environment', + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + lastUpdatedById: 'user123', + projectId: 'project123', + lastUpdatedBy: { + id: 'user123', + name: 'John Doe', + email: 'john.doe@example.com', + profilePictureUrl: null + } + } + ], + metadata: { + page: 'one', // Should be a number + perPage: 10, + pageCount: 1, + totalCount: 1, + links: { + self: 'http://example.com/page/1', + first: 'http://example.com/page/1', + previous: null, + next: null, + last: 'http://example.com/page/1' + } + } + }) expect(result.success).toBe(false) expect(result.error?.issues).toHaveLength(1) }) - it('should not validate if required values are not specified', () => { - const result = CreateEnvironmentSchema.safeParse({}) + // Tests for DeleteEnvironmentRequestSchema + it('should validate if proper input is specified for DeleteEnvironmentRequestSchema', () => { + const result = DeleteEnvironmentRequestSchema.safeParse({ + slug: 'test-slug' + }) + expect(result.success).toBe(true) + }) + it('should not validate if invalid values are specified for DeleteEnvironmentRequestSchema', () => { + const result = DeleteEnvironmentRequestSchema.safeParse({ + slug: 123 + }) expect(result.success).toBe(false) expect(result.error?.issues).toHaveLength(1) }) + + // Tests for DeleteEnvironmentResponseSchema + it('should validate a valid DeleteEnvironmentResponseSchema', () => { + const result = DeleteEnvironmentResponseSchema.safeParse(undefined) + expect(result.success).toBe(true) + }) + + it('should not validate an invalid DeleteEnvironmentResponseSchema', () => { + const result = DeleteEnvironmentResponseSchema.safeParse({ + unexpectedField: 'value' + }) + expect(result.success).toBe(false) + }) }) diff --git a/packages/schema/tests/project.spec.ts b/packages/schema/tests/project.spec.ts index 42815628..54d766d8 100644 --- a/packages/schema/tests/project.spec.ts +++ b/packages/schema/tests/project.spec.ts @@ -1,48 +1,308 @@ -import { CreateProjectSchema, ForkProjectSchema } from '@/project' +import { + ProjectSchema, + CreateProjectRequestSchema, + CreateProjectResponseSchema, + UpdateProjectRequestSchema, + UpdateProjectResponseSchema, + DeleteProjectRequestSchema, + DeleteProjectResponseSchema, + GetProjectRequestSchema, + GetProjectResponseSchema, + ForkProjectRequestSchema, + ForkProjectResponseSchema, + SyncProjectRequestSchema, + SyncProjectResponseSchema, + UnlinkProjectRequestSchema, + UnlinkProjectResponseSchema, + GetForkRequestSchema, + GetForkResponseSchema, + GetAllProjectsRequestSchema, + GetAllProjectsResponseSchema +} from '@/project' import { projectAccessLevelEnum } from '@/enums' describe('Project Schema Tests', () => { - it('should validate if proper input is specified for CreateProjectSchema', () => { - const result = CreateProjectSchema.safeParse({ + // Tests for ProjectSchema + it('should validate a valid ProjectSchema', () => { + const result = ProjectSchema.safeParse({ + id: 'project123', + name: 'Project Name', + slug: 'project-slug', + description: 'Project Description', + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + publicKey: 'public-key', + privateKey: 'private-key', + storePrivateKey: true, + isDisabled: false, + accessLevel: 'admin', + pendingCreation: false, + isForked: false, + lastUpdatedById: 'user123', + workspaceId: 'workspace123', + forkedFromId: null + }) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid ProjectSchema', () => { + const result = ProjectSchema.safeParse({ + id: 'project123', + name: 'Project Name' + // Missing required fields + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(14) + }) + + it('should not validate ProjectSchema when isForked is true but forkedFromId is null', () => { + const result = ProjectSchema.safeParse({ + id: 'project123', + name: 'Project Name', + slug: 'project-slug', + description: 'Project Description', + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + publicKey: 'public-key', + privateKey: 'private-key', + storePrivateKey: true, + isDisabled: false, + accessLevel: 'admin', + pendingCreation: false, + isForked: true, + lastUpdatedById: 'user123', + workspaceId: 'workspace123', + forkedFromId: null + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) + expect(result.error?.issues[0].message).toBe('Invalid input') + }) + + // Tests for CreateProjectRequestSchema + it('should validate if proper input is specified for CreateProjectRequestSchema', () => { + const result = CreateProjectRequestSchema.safeParse({ name: 'Project Test', + workspaceSlug: 'workspace123', accessLevel: projectAccessLevelEnum.Enum.PRIVATE, - environments: [{ name: 'Environment 1' }] + environments: [{ name: 'Environment 1', projectId: 'project123' }] }) expect(result.success).toBe(true) }) - it('should not validate if invalid values are specified for CreateProjectSchema', () => { - const result = CreateProjectSchema.safeParse({ + it('should not validate if invalid values are specified for CreateProjectRequestSchema', () => { + const result = CreateProjectRequestSchema.safeParse({ name: 123, accessLevel: 'invalid_access_level' }) expect(result.success).toBe(false) - expect(result.error?.issues).toHaveLength(2) + expect(result.error?.issues).toHaveLength(3) }) - it('should validate if only required fields are specified for CreateProjectSchema', () => { - const result = CreateProjectSchema.safeParse({ + it('should validate if only required fields are specified for CreateProjectRequestSchema', () => { + const result = CreateProjectRequestSchema.safeParse({ name: 'Project Test', + workspaceSlug: 'workspace123', accessLevel: projectAccessLevelEnum.Enum.PRIVATE }) expect(result.success).toBe(true) }) - it('should validate if optional fields are omitted for CreateProjectSchema', () => { - const result = CreateProjectSchema.safeParse({ - name: 'Project Test', - accessLevel: projectAccessLevelEnum.Enum.PRIVATE + // Tests for CreateProjectResponseSchema + it('should validate a valid CreateProjectResponseSchema', () => { + const result = CreateProjectResponseSchema.safeParse({ + id: 'project123', + name: 'Project Name', + slug: 'project-slug', + description: 'Project Description', + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + publicKey: 'public-key', + privateKey: 'private-key', + storePrivateKey: true, + isDisabled: false, + accessLevel: 'admin', + pendingCreation: false, + isForked: false, + lastUpdatedById: 'user123', + workspaceId: 'workspace123', + forkedFromId: null + }) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid CreateProjectResponseSchema', () => { + const result = CreateProjectResponseSchema.safeParse({ + id: 'project123', + name: 'Project Name' + // Missing required fields + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(14) + }) + + // Tests for UpdateProjectRequestSchema + it('should validate a valid UpdateProjectRequestSchema', () => { + const result = UpdateProjectRequestSchema.safeParse({ + projectSlug: 'project-slug', + name: 'Updated Project Name' + }) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid UpdateProjectRequestSchema', () => { + const result = UpdateProjectRequestSchema.safeParse({ + projectSlug: 123, // Should be a string + name: 'Updated Project Name' + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) + }) + + it('should validate if only required fields are specified for UpdateProjectRequestSchema', () => { + const result = UpdateProjectRequestSchema.safeParse({ + projectSlug: 'project-slug' + }) + + expect(result.success).toBe(true) + }) + + // Tests for UpdateProjectResponseSchema + it('should validate a valid UpdateProjectResponseSchema', () => { + const result = UpdateProjectResponseSchema.safeParse({ + id: 'project123', + name: 'Project Name', + slug: 'project-slug', + description: 'Project Description', + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + publicKey: 'public-key', + privateKey: 'private-key', + storePrivateKey: true, + isDisabled: false, + accessLevel: 'admin', + pendingCreation: false, + isForked: false, + lastUpdatedById: 'user123', + workspaceId: 'workspace123', + forkedFromId: null + }) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid UpdateProjectResponseSchema', () => { + const result = UpdateProjectResponseSchema.safeParse({ + id: 'project123', + name: 'Project Name' + // Missing required fields + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(14) + }) + + // Tests for DeleteProjectRequestSchema + it('should validate a valid DeleteProjectRequestSchema', () => { + const result = DeleteProjectRequestSchema.safeParse({ + projectSlug: 'project-slug' }) expect(result.success).toBe(true) }) - it('should validate if proper input is specified for ForkProjectSchema', () => { - const result = ForkProjectSchema.safeParse({ + it('should not validate an invalid DeleteProjectRequestSchema', () => { + const result = DeleteProjectRequestSchema.safeParse({ + projectSlug: 123 // Should be a string + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) + }) + + // Tests for DeleteProjectResponseSchema + it('should validate a valid DeleteProjectResponseSchema', () => { + const result = DeleteProjectResponseSchema.safeParse(undefined) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid DeleteProjectResponseSchema', () => { + const result = DeleteProjectResponseSchema.safeParse({ + unexpectedField: 'value' + }) + + expect(result.success).toBe(false) + }) + + // Tests for GetProjectRequestSchema + it('should validate a valid GetProjectRequestSchema', () => { + const result = GetProjectRequestSchema.safeParse({ + projectSlug: 'project-slug' + }) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid GetProjectRequestSchema', () => { + const result = GetProjectRequestSchema.safeParse({ + projectSlug: 123 // Should be a string + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) + }) + + // Tests for GetProjectResponseSchema + it('should validate a valid GetProjectResponseSchema', () => { + const result = GetProjectResponseSchema.safeParse({ + id: 'project123', + name: 'Project Name', + slug: 'project-slug', + description: 'Project Description', + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + publicKey: 'public-key', + privateKey: 'private-key', + storePrivateKey: true, + isDisabled: false, + accessLevel: 'admin', + pendingCreation: false, + isForked: false, + lastUpdatedById: 'user123', workspaceId: 'workspace123', + forkedFromId: null + }) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid GetProjectResponseSchema', () => { + const result = GetProjectResponseSchema.safeParse({ + id: 'project123', + name: 'Project Name' + // Missing required fields + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(14) + }) + + // Tests for ForkProjectRequestSchema + it('should validate if proper input is specified for ForkProjectRequestSchema', () => { + const result = ForkProjectRequestSchema.safeParse({ + projectSlug: 'project123', + workspaceSlug: 'workspace123', name: 'Forked Project', storePrivateKey: true }) @@ -50,19 +310,296 @@ describe('Project Schema Tests', () => { expect(result.success).toBe(true) }) - it('should validate if all fields are omitted for ForkProjectSchema', () => { - const result = ForkProjectSchema.safeParse({}) + it('should validate if only required fields are present for ForkProjectRequestSchema', () => { + const result = ForkProjectRequestSchema.safeParse({ + projectSlug: 'project123' + }) expect(result.success).toBe(true) }) - it('should not validate if invalid values are specified for ForkProjectSchema', () => { - const result = ForkProjectSchema.safeParse({ - workspaceId: 123, + it('should not validate if invalid values are specified for ForkProjectRequestSchema', () => { + const result = ForkProjectRequestSchema.safeParse({ + projectSlug: 456, + workspaceSlug: 123, storePrivateKey: 'invalid_boolean' }) expect(result.success).toBe(false) - expect(result.error?.issues).toHaveLength(2) + expect(result.error?.issues).toHaveLength(3) + }) + + // Tests for ForkProjectResponseSchema + it('should validate a valid ForkProjectResponseSchema', () => { + const result = ForkProjectResponseSchema.safeParse({ + id: 'project123', + name: 'Project Name', + slug: 'project-slug', + description: 'Project Description', + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + publicKey: 'public-key', + privateKey: 'private-key', + storePrivateKey: true, + isDisabled: false, + accessLevel: 'admin', + pendingCreation: false, + isForked: false, + lastUpdatedById: 'user123', + workspaceId: 'workspace123', + forkedFromId: null + }) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid ForkProjectResponseSchema', () => { + const result = ForkProjectResponseSchema.safeParse({ + id: 'project123', + name: 'Project Name' + // Missing required fields + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(14) + }) + + // Tests for SyncProjectRequestSchema + it('should validate a valid SyncProjectRequestSchema', () => { + const result = SyncProjectRequestSchema.safeParse({ + projectSlug: 'project-slug', + hardSync: true + }) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid SyncProjectRequestSchema', () => { + const result = SyncProjectRequestSchema.safeParse({ + projectSlug: 123, // Should be a string + hardSync: true + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) + }) + + // Tests for SyncProjectResponseSchema + it('should validate a valid SyncProjectResponseSchema', () => { + const result = SyncProjectResponseSchema.safeParse(undefined) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid SyncProjectResponseSchema', () => { + const result = SyncProjectResponseSchema.safeParse({ + unexpectedField: 'value' + }) + + expect(result.success).toBe(false) + }) + + // Tests for UnlinkProjectRequestSchema + it('should validate a valid UnlinkProjectRequestSchema', () => { + const result = UnlinkProjectRequestSchema.safeParse({ + projectSlug: 'project-slug' + }) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid UnlinkProjectRequestSchema', () => { + const result = UnlinkProjectRequestSchema.safeParse({ + projectSlug: 123 // Should be a string + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) + }) + + // Tests for UnlinkProjectResponseSchema + it('should validate a valid UnlinkProjectResponseSchema', () => { + const result = UnlinkProjectResponseSchema.safeParse(undefined) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid UnlinkProjectResponseSchema', () => { + const result = UnlinkProjectResponseSchema.safeParse({ + unexpectedField: 'value' + }) + + expect(result.success).toBe(false) + }) + + // Tests for GetForkRequestSchema + it('should validate a valid GetForkRequestSchema', () => { + const result = GetForkRequestSchema.safeParse({ + projectSlug: 'project-slug', + workspaceSlug: 'workspace-slug', + page: 1, + perPage: 10 + }) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid GetForkRequestSchema', () => { + const result = GetForkRequestSchema.safeParse({ + projectSlug: 123, // Should be a string + workspaceSlug: 'workspace-slug', + page: 1, + perPage: 10 + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) + }) + + // Tests for GetForkResponseSchema + it('should validate a valid GetForkResponseSchema', () => { + const result = GetForkResponseSchema.safeParse({ + items: [ + { + id: 'project123', + name: 'Project Name', + slug: 'project-slug', + description: 'Project Description', + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + publicKey: 'public-key', + privateKey: 'private-key', + storePrivateKey: true, + isDisabled: false, + accessLevel: 'admin', + pendingCreation: false, + isForked: false, + lastUpdatedById: 'user123', + workspaceId: 'workspace123', + forkedFromId: null + } + ], + metadata: { + page: 1, + perPage: 10, + pageCount: 1, + totalCount: 1, + links: { + self: 'http://example.com/page/1', + first: 'http://example.com/page/1', + previous: null, + next: null, + last: 'http://example.com/page/1' + } + } + }) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid GetForkResponseSchema', () => { + const result = GetForkResponseSchema.safeParse({ + items: 'not-an-array', // Should be an array + metadata: { + page: 1, + perPage: 10, + pageCount: 1, + totalCount: 1, + links: { + self: 'http://example.com/page/1', + first: 'http://example.com/page/1', + previous: null, + next: null, + last: 'http://example.com/page/1' + } + } + }) + + expect(result.success).toBe(false) + }) + + // Tests for GetAllProjectsRequestSchema + it('should validate a valid GetAllProjectsRequestSchema', () => { + const result = GetAllProjectsRequestSchema.safeParse({ + workspaceSlug: 'workspace-slug', + page: 1, + perPage: 10 + }) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid GetAllProjectsRequestSchema', () => { + const result = GetAllProjectsRequestSchema.safeParse({ + workspaceSlug: 123, // Should be a string + page: 1, + perPage: 10 + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) + }) + + // Tests for GetAllProjectsResponseSchema + it('should validate a valid GetAllProjectsResponseSchema', () => { + const result = GetAllProjectsResponseSchema.safeParse({ + items: [ + { + id: 'project123', + name: 'Project Name', + slug: 'project-slug', + description: 'Project Description', + createdAt: '2024-10-01T00:00:00Z', + updatedAt: '2024-10-01T00:00:00Z', + publicKey: 'public-key', + privateKey: 'private-key', + storePrivateKey: true, + isDisabled: false, + accessLevel: 'admin', + pendingCreation: false, + isForked: false, + lastUpdatedById: 'user123', + workspaceId: 'workspace123', + forkedFromId: null + } + ], + metadata: { + page: 1, + perPage: 10, + pageCount: 1, + totalCount: 1, + links: { + self: 'http://example.com/page/1', + first: 'http://example.com/page/1', + previous: null, + next: null, + last: 'http://example.com/page/1' + } + } + }) + + expect(result.success).toBe(true) + }) + + it('should not validate an invalid GetAllProjectsResponseSchema', () => { + const result = GetAllProjectsResponseSchema.safeParse({ + items: 'not-an-array', // Should be an array + metadata: { + page: 1, + perPage: 10, + pageCount: 1, + totalCount: 1, + links: { + self: 'http://example.com/page/1', + first: 'http://example.com/page/1', + previous: null, + next: null, + last: 'http://example.com/page/1' + } + } + }) + + expect(result.success).toBe(false) + expect(result.error?.issues).toHaveLength(1) }) })