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 12725x 25x 25x                       25x     49x                             25x                       25x                       25x                         25x                         25x                             25x                               25x                       25x  
import { z } from 'zod';
import { requiredId, numericId } 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: numericId.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: numericId.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 };