Creëer een Basale GraphQL Schema Validatie en Type Checking
description
Met deze prompt kan ik mijn GraphQL API robuuster maken door invoerfouten vroegtijdig te detecteren en te voorkomen. Het helpt bij het afdwingen van datatypes en validatieregels zonder complexe implementaties, wat tijd bespaart en de API betrouwbaarder maakt dan alternatieven die geen validatie integreren.
prompt
Help me een basale validatie en type checking op te zetten voor mijn GraphQL schema met de volgende details:
Schema Overzicht: <beschrijf de hoofdtypen en velden van mijn GraphQL schema>
Validatieregels: <geef de validatieregels die ik wil toepassen, bijvoorbeeld verplichte ...
try_prompt
generate_helper
disclaimerOnPageApi
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Natuurlijk! Hier is een overzicht van hoe je basis validatie en type checking kunt implementeren in je GraphQL schema voor jouw User type:
1. Gebruik van niet-blank velden (Non-Null types)
2. Validatie van het email-formaat met een custom scalar of directives
3. Voorbeeld schema met validatie en type checking
4. Uitleg en voorbeelden
---
**1. Basis Type Checking in GraphQL**
In GraphQL kun je types afdwingen door gebruik te maken van niet-Null types (`!`). Dit zorgt ervoor dat clients verplicht velden invullen.
```graphql
type User {
id: ID!
naam: String!
email: String!
}
```
Hiermee wordt afgedwongen dat `id`, `naam` en `email` altijd ingevuld moeten worden.
---
**2. Validatie voor e-mail formaat**
GraphQL heeft geen ingebouwde email-validatie, maar je kunt dit aanpakken op verschillende manieren:
- **Gebruik van custom scalars:** Maak een op maat gemaakte scalar voor e-mail met validatie.
- **Gebruik van directives:** Voeg validatie toe via schema-directives (bijvoorbeeld via schema-validators in je server).
Hier is een voorbeeld met een custom scalar:
```graphql
scalar Email
type User {
id: ID!
naam: String!
email: Email!
}
```
**Implementatie in code (bijvoorbeeld met Apollo Server in JavaScript):**
```js
const { GraphQLScalarType, Kind } = require('graphql');
const EmailScalar = new GraphQLScalarType({
name: 'Email',
description: 'Een e-mail adres scalar die validatie uitvoert',
serialize(value) {
return value; // output naar client
},
parseValue(value) {
if (typeof value !== 'string') {
throw new Error('Email moet een string zijn');
}
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(value)) {
throw new Error('Ongeldig email formaat');
}
return value; // valid email
},
parseLiteral(ast) {
if (ast.kind !== Kind.STRING) {
throw new Error('Email moet een string zijn');
}
if (!/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(ast.value)) {
throw new Error('Ongeldig email formaat');
}
return ast.value;
},
});
```
**Registeren in schema:**
```js
const typeDefs = `
scalar Email
type User {
id: ID!
naam: String!
email: Email!
}
type Query {
users: [User]
}
`;
const resolvers = {
Email: EmailScalar,
// andere resolvers
};
```
---
**3. Validatie op server niveau**
Naast type checking, kun je in je resolvers validaties toevoegen voor verplichting en datatypes. Bijvoorbeeld:
```js
Mutation: {
createUser: (_, { input }) => {
const { naam, email } = input;
if (!naam || naam.trim() === '') {
throw new Error('Naam is verplicht');
}
if (!email || email.trim() === '') {
throw new Error('Email is verplicht');
}
// Email validatie wordt gedaan door scalar
// Verder logica om gebruiker aan te maken
}
}
```
---
**4. Samenvatting**
- Gebruik `!` voor verplichte velden.
- Maak een custom scalar `Email` voor email-validatie.
- Voeg validaties toe in resolvers voor extra controle (zoals niet-lege strings).
- Overweeg schema-directives of third-party validatie libraries voor complexere validaties.
---
**Kort voorbeeld schema:**
```graphql
scalar Email
type User {
id: ID!
naam: String!
email: Email!
}
type Query {
user(id: ID!): User
}
type Mutation {
createUser(naam: String!, email: Email!): User
}
```
Met deze aanpak voorkom je dat ongeldige data wordt opgeslagen en krijg je duidelijke foutmeldingen bij invoer.
---
Heeft je nog verdere vragen of wil je een voorbeeld in een specifieke programmeertaal?
provider: deepseek
model: deepseek-chat
Hier is een uitgebreide uitleg over het opzetten van validatie en type checking voor je GraphQL schema:
## 1. GraphQL Schema Definitie
```graphql
# schema.graphql
type User {
id: ID!
naam: String!
email: String!
}
input UserInput {
naam: String!
email: String!
}
type Mutation {
createUser(input: UserInput!): User
updateUser(id: ID!, input: UserInput!): User
}
type Query {
getUser(id: ID!): User
}
```
## 2. Type Checking (Automatisch door GraphQL)
GraphQL voert automatisch type checking uit op basis van je schema:
```javascript
// Deze fouten worden automatisch afgevangen door GraphQL
// ✅ Geldige query
query {
getUser(id: "1") {
id
naam
email
}
}
// ❌ Fout: ontbrekend verplicht veld
mutation {
createUser(input: { naam: "Jan" }) {
// email ontbreekt - GraphQL geeft fout
}
}
// ❌ Fout: verkeerd type
mutation {
createUser(input: { naam: 123, email: "jan@example.com" }) {
// naam moet string zijn - GraphQL geeft fout
}
}
```
## 3. Custom Validatie Implementatie
```javascript
// validators/userValidator.js
const { UserInputError } = require('apollo-server-express');
const validateEmail = (email) => {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
return emailRegex.test(email);
};
const validateUserInput = (input) => {
const errors = [];
// Naam validatie
if (!input.naam || input.naam.trim() === '') {
errors.push('Naam is verplicht');
} else if (input.naam.length < 2) {
errors.push('Naam moet minimaal 2 karakters lang zijn');
}
// Email validatie
if (!input.email || input.email.trim() === '') {
errors.push('Email is verplicht');
} else if (!validateEmail(input.email)) {
errors.push('Ongeldig email formaat');
}
if (errors.length > 0) {
throw new UserInputError('Ongeldige gebruikersinvoer', {
errors
});
}
return input;
};
```
## 4. Resolver Implementatie met Validatie
```javascript
// resolvers/userResolver.js
const { validateUserInput } = require('./validators/userValidator');
const users = []; // Tijdelijke opslag voor demo
const userResolver = {
Query: {
getUser: (parent, { id }) => {
return users.find(user => user.id === id);
},
},
Mutation: {
createUser: (parent, { input }) => {
// Valideer invoer
const validatedInput = validateUserInput(input);
// Maak nieuwe gebruiker
const newUser = {
id: String(users.length + 1),
naam: validatedInput.naam.trim(),
email: validatedInput.email.toLowerCase().trim(),
};
users.push(newUser);
return newUser;
},
updateUser: (parent, { id, input }) => {
// Valideer invoer
const validatedInput = validateUserInput(input);
// Zoek gebruiker
const userIndex = users.findIndex(user => user.id === id);
if (userIndex === -1) {
throw new Error('Gebruiker niet gevonden');
}
// Update gebruiker
users[userIndex] = {
...users[userIndex],
naam: validatedInput.naam.trim(),
email: validatedInput.email.toLowerCase().trim(),
};
return users[userIndex];
},
},
};
module.exports = userResolver;
```
## 5. Gebruiksvoorbeelden
### Geldige Mutations:
```graphql
# ✅ Correcte invoer
mutation {
createUser(input: {
naam: "Anna Jansen",
email: "anna@voorbeeld.nl"
}) {
id
naam
email
}
}
```
### Ongeldige Mutations (worden afgevangen):
```graphql
# ❌ Ontbrekende naam
mutation {
createUser(input: {
email: "test@voorbeeld.nl"
}) {
id
}
}
# ❌ Ongeldig email formaat
mutation {
createUser(input: {
naam: "Piet",
email: "geen-email"
}) {
id
}
}
# ❌ Lege naam
mutation {
createUser(input: {
naam: "",
email: "test@voorbeeld.nl"
}) {
id
}
}
```
## 6. Foutafhandeling
```javascript
// errorHandler.js
const formatError = (err) => {
if (err.originalError instanceof UserInputError) {
return {
message: err.message,
code: 'INPUT_VALIDATION_ERROR',
details: err.extensions.errors
};
}
// Log andere fouten voor debugging
console.error('GraphQL Error:', err);
return {
message: 'Er is een interne fout opgetreden',
code: 'INTERNAL_ERROR'
};
};
```
## 7. Volledige Server Setup
```javascript
// server.js
const { ApolloServer, gql } = require('apollo-server-express');
const userResolver = require('./resolvers/userResolver');
const { formatError } = require('./errorHandler');
const typeDefs = gql`
type User {
id: ID!
naam: String!
email: String!
}
input UserInput {
naam: String!
email: String!
}
type Mutation {
createUser(input: UserInput!): User
updateUser(id: ID!, input: UserInput!): User
}
type Query {
getUser(id: ID!): User
}
`;
const server = new ApolloServer({
typeDefs,
resolvers: userResolver,
formatError,
context: ({ req }) => {
// Eventuele authenticatie/logging hier
return { user: null };
}
});
```
## Belangrijkste Voordelen:
1. **Type Safety**: GraphQL zorgt automatisch voor type checking
2. **Custom Validatie**: Extra bedrijfsregels voor email formaat en naam
3. **Duidelijke Foutmeldingen**: Gebruikers krijgen specifieke feedback
4. **Consistente Data**: Trimmen en normaliseren van invoer
5. **Schaalbaar**: Makkelijk uit te breiden met extra validatieregels
Deze implementatie voorkomt effectief fouten bij invoer en zorgt voor consistente, valide data in je applicatie.