-
-
Notifications
You must be signed in to change notification settings - Fork 320
Description
Description
Hi! 👋 First of all - thank you for this package. It makes working with the GitLab API much easier and the developer experience is great.
After using Gitbeaker in a few projects, I noticed that the current API responses map very cleanly to Zod or Standard Schema. Gitbeaker already has solid TypeScript definitions, so there's a good foundation to generate proper runtime validation schemas on top of them.
This could open the door to safer integrations - especially in environments where API responses need to be validated, transformed, or exposed through other internal services.
Right now developers need to maintain their own schemas manually. Adding optional built-in schemas (or a generator) would make this much simpler and reduce duplication.
Proposal
Introduce a way to use Gitbeaker with Zod or Standard Schema:
- Provide Zod schemas generated from existing TypeScript types (either directly bundled or generated through a small build step).
- Expose them as a separate optional module, e.g.
@gitbeaker/zodorgitbeaker/schemas. - Keep it fully optional so core users aren't affected - but allow developers who rely on runtime validation to plug schemas in easily.
- Ensure schemas stay in sync with the official GitLab API types. Ideally the generation would run automatically during releases.
- If full coverage is too large for the first iteration, start with core resources (Projects, Users, Issues, Merge Requests) and expand over time.
- And if it helps - I'm happy to contribute and assist with the implementation.
Example use cases
1. Basic API response validation
import { Gitlab } from '@gitbeaker/rest';
import { zProjectSchema, zUserSchema } from '@gitbeaker/zod';
const api = new Gitlab({ token: 'xxx' });
// Validate single project
const rawProject = await api.Projects.show(123);
const project = zProjectSchema.parse(rawProject);
// ✅ Guaranteed type safety + runtime validation
// Validate list of users
const rawUsers = await api.Users.all();
const users = zUserSchema.array().parse(rawUsers);2. Webhook validation in API endpoints
import { zWebhookPushEventSchema, zWebhookMergeRequestEventSchema } from '@gitbeaker/zod';
import { z } from 'zod';
// Express/Next.js endpoint
app.post('/webhook/gitlab', async (req, res) => {
const eventType = req.headers['x-gitlab-event'];
try {
if (eventType === 'Push Hook') {
const event = zWebhookPushEventSchema.parse(req.body);
await handlePushEvent(event);
} else if (eventType === 'Merge Request Hook') {
const event = zWebhookMergeRequestEventSchema.parse(req.body);
await handleMergeRequest(event);
}
res.status(200).send('OK');
} catch (error) {
if (error instanceof z.ZodError) {
console.error('Invalid webhook payload:', error.errors);
res.status(400).json({ error: 'Invalid payload' });
}
}
});3. Safe transformations to internal models
import { zMergeRequestSchema } from '@gitbeaker/zod';
// Transform to internal model with validation
const InternalMRSchema = zMergeRequestSchema.transform((mr) => ({
id: mr.id,
title: mr.title,
author: mr.author.username,
status: mr.state === 'merged' ? 'completed' : 'pending',
createdAt: new Date(mr.created_at),
}));
const mrs = await api.MergeRequests.all({ projectId: 123 });
const internalMRs = mrs.map(mr => InternalMRSchema.parse(mr));4. Integration with tRPC or other type-safe frameworks
import { zProjectSchema } from '@gitbeaker/zod';
import { initTRPC } from '@trpc/server';
const t = initTRPC.create();
export const appRouter = t.router({
getProject: t.procedure
.input(z.object({ id: z.number() }))
.output(zProjectSchema)
.query(async ({ input }) => {
const project = await api.Projects.show(input.id);
return zProjectSchema.parse(project);
}),
});Checklist
- I have checked that this is not a duplicate issue.
- I have read the documentation.