All files / src/entities/members schema-readonly.ts

100% Statements 13/13
100% Branches 0/0
100% Functions 1/1
100% Lines 13/13

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 12720x 20x 20x                       20x     35x                             20x                       20x                       20x                         20x                         20x                             20x                               20x                       20x  
import { z } from 'zod';
import { requiredId } from '../utils';
import { PaginationOptionsSchema } from '../shared';
 
/**
 * Access levels for GitLab members
 * - 0: No access
 * - 5: Minimal access
 * - 10: Guest (view only)
 * - 20: Reporter (view + comment)
 * - 30: Developer (push code)
 * - 40: Maintainer (manage settings)
 * - 50: Owner (full control)
 */
const AccessLevelSchema = z
  .number()
  .int()
  .refine((val) => [0, 5, 10, 20, 30, 40, 50].includes(val), {
    message:
      'Access level must be 0 (No access), 5 (Minimal), 10 (Guest), 20 (Reporter), 30 (Developer), 40 (Maintainer), or 50 (Owner)',
  })
  .describe(
    'Access level: 0=No access, 5=Minimal, 10=Guest, 20=Reporter, 30=Developer, 40=Maintainer, 50=Owner',
  );
 
// =============================================================================
// Browse Members Actions (Query)
// =============================================================================
 
/**
 * List project members
 */
const ListProjectMembersSchema = z
  .object({
    action: z.literal('list_project').describe('List all members of a project'),
    project_id: requiredId.describe('Project ID or URL-encoded path'),
    query: z.string().optional().describe('Search members by name or username'),
    user_ids: z.array(z.coerce.string()).optional().describe('Filter to specific user IDs'),
  })
  .merge(PaginationOptionsSchema);
 
/**
 * List group members
 */
const ListGroupMembersSchema = z
  .object({
    action: z.literal('list_group').describe('List all members of a group'),
    group_id: requiredId.describe('Group ID or URL-encoded path'),
    query: z.string().optional().describe('Search members by name or username'),
    user_ids: z.array(z.coerce.string()).optional().describe('Filter to specific user IDs'),
  })
  .merge(PaginationOptionsSchema);
 
/**
 * Get specific member from project
 */
const GetProjectMemberSchema = z.object({
  action: z.literal('get_project').describe('Get a specific member of a project'),
  project_id: requiredId.describe('Project ID or URL-encoded path'),
  user_id: requiredId.describe('User ID of the member'),
  include_inherited: z
    .boolean()
    .optional()
    .describe('Include members inherited from parent groups'),
});
 
/**
 * Get specific member from group
 */
const GetGroupMemberSchema = z.object({
  action: z.literal('get_group').describe('Get a specific member of a group'),
  group_id: requiredId.describe('Group ID or URL-encoded path'),
  user_id: requiredId.describe('User ID of the member'),
  include_inherited: z
    .boolean()
    .optional()
    .describe('Include members inherited from parent groups'),
});
 
/**
 * List all members including inherited (project)
 */
const ListAllProjectMembersSchema = z
  .object({
    action: z
      .literal('list_all_project')
      .describe('List all project members including inherited from parent groups'),
    project_id: requiredId.describe('Project ID or URL-encoded path'),
    query: z.string().optional().describe('Search members by name or username'),
    user_ids: z.array(z.coerce.string()).optional().describe('Filter to specific user IDs'),
    state: z.enum(['active', 'awaiting', 'blocked']).optional().describe('Filter by member state'),
  })
  .merge(PaginationOptionsSchema);
 
/**
 * List all members including inherited (group)
 */
const ListAllGroupMembersSchema = z
  .object({
    action: z
      .literal('list_all_group')
      .describe('List all group members including inherited from parent groups'),
    group_id: requiredId.describe('Group ID or URL-encoded path'),
    query: z.string().optional().describe('Search members by name or username'),
    user_ids: z.array(z.coerce.string()).optional().describe('Filter to specific user IDs'),
    state: z.enum(['active', 'awaiting', 'blocked']).optional().describe('Filter by member state'),
  })
  .merge(PaginationOptionsSchema);
 
// =============================================================================
// BrowseMembersSchema - Discriminated Union
// =============================================================================
 
export const BrowseMembersSchema = z.discriminatedUnion('action', [
  ListProjectMembersSchema,
  ListGroupMembersSchema,
  GetProjectMemberSchema,
  GetGroupMemberSchema,
  ListAllProjectMembersSchema,
  ListAllGroupMembersSchema,
]);
 
export type BrowseMembersOptions = z.infer<typeof BrowseMembersSchema>;
 
// Export AccessLevelSchema for reuse in manage schema
export { AccessLevelSchema };