Ontwerp een Geavanceerd GraphQL Schema met Geavanceerde Foutafhandeling en Validatie
description
Met deze prompt kan de gebruiker een GraphQL schema ontwerpen dat niet alleen functioneel is, maar ook robuust en veilig dankzij geavanceerde foutafhandeling en data validatie. Dit helpt problemen vroegtijdig te identificeren, voorkomt ongeldige data en zorgt voor duidelijke fouten terugkoppeling naar de client, wat de betrouwbaarheid en gebruikerservaring van de API aanzienlijk verbetert.
prompt
Help me een geavanceerd GraphQL schema te ontwerpen waarin robuuste foutafhandeling en data validatie centraal staan. Mijn domein is: <beschrijf je domein of toepassingsgebied>. Ik wil ondersteuning voor: <specificeer gewenste validatie me ...
try_prompt
generate_helper
disclaimerOnPageApi
tags
ai_answers
provider: openai
model: gpt-4.1-nano
Natuurlijk! Hieronder vind je een voorbeeld van een geavanceerd GraphQL-schema voor jouw E-commerce domein, waarbij robuuste foutafhandeling, data-validatie, custom directives en middleware worden geïntegreerd.
### 1. Structuur en principes
- **Custom directive voor e-mail validatie** (`@validateEmail`)
- **Middleware voor authenticatie** (bijvoorbeeld: token-verificatie)
- **Duidelijke foutmeldingen** met gestandaardiseerd formaat
- **Input-validatie** binnen de schema definities
- **Gebruik van enums en scalar types** voor data-integriteit
---
### 2. Voorbeeld schema
```graphql
# Scalar types voor validatie
scalar Email
# Custom directive voor email validatie
directive @validateEmail on INPUT_FIELD_DEFINITION
# User type
type User {
id: ID!
name: String!
email: Email!
address: String
createdAt: String!
}
# Product type
type Product {
id: ID!
name: String!
description: String
price: Float!
stock: Int!
}
# Order status enum
enum OrderStatus {
PENDING
COMPLETED
CANCELLED
}
# Order type
type Order {
id: ID!
user: User!
products: [Product!]!
totalPrice: Float!
status: OrderStatus!
createdAt: String!
}
# Error type voor consistente foutmeldingen
type Error {
code: String!
message: String!
details: String
}
# Mutatie result voor foutafhandeling
union MutationResult = User | Error
# Query en Mutatie definities
type Query {
getUser(id: ID!): UserResult
getProduct(id: ID!): ProductResult
getOrder(id: ID!): OrderResult
}
type Mutation {
registerUser(input: RegisterUserInput!): UserResult
createOrder(input: CreateOrderInput!): OrderResult
}
# Input types met validatie directives
input RegisterUserInput {
name: String!
email: String! @validateEmail
address: String
}
input CreateOrderInput {
userId: ID!
productIds: [ID!]!
}
# Result types met foutafhandeling
type UserResult {
user: User
error: Error
}
type ProductResult {
product: Product
error: Error
}
type OrderResult {
order: Order
error: Error
}
```
---
### 3. Implementatie voorbeelden
#### a) Custom directive voor e-mail validatie
```graphql
directive @validateEmail on INPUT_FIELD_DEFINITION
```
De implementatie op serverzijde (bijvoorbeeld in Apollo Server):
```js
const { SchemaDirectiveVisitor } = require('apollo-server');
const validator = require('validator');
class ValidateEmailDirective extends SchemaDirectiveVisitor {
visitInputFieldDefinition(field) {
const { resolve = (x) => x } = field;
field.resolve = async function (source, args, context, info) {
const value = args[field.name];
if (!validator.isEmail(value)) {
throw new Error(`Ongeldig e-mailadres: ${value}`);
}
return resolve.call(this, source, args, context, info);
};
}
}
```
#### b) Middleware voor authenticatie
Bijvoorbeeld in Apollo Server:
```js
const authMiddleware = async ({ req }) => {
const token = req.headers.authorization || '';
// Verifieer token
const user = verifyToken(token);
if (!user) {
throw new Error('Authenticatie vereist');
}
return { user };
};
const server = new ApolloServer({
typeDefs,
resolvers,
context: authMiddleware,
});
```
#### c) Duidelijke foutafhandeling in resolvers
```js
const resolvers = {
Query: {
getUser: async (_, { id }) => {
try {
const user = await findUserById(id);
if (!user) {
return { error: { code: "404", message: "Gebruiker niet gevonden" } };
}
return { user };
} catch (err) {
return { error: { code: "500", message: "Serverfout", details: err.message } };
}
},
// vergelijkbaar voor andere queries
},
Mutation: {
registerUser: async (_, { input }) => {
try {
// Data validatie wordt automatisch afgehandeld door directive
const newUser = await createUser(input);
return { user: newUser };
} catch (err) {
return { error: { code: "400", message: "Registratie mislukt", details: err.message } };
}
},
createOrder: async (_, { input }, context) => {
try {
// Authenticatie check
if (!context.user) {
return { error: { code: "401", message: "Niet geautoriseerd" } };
}
// Data validatie / controle
const { userId, productIds } = input;
// Controle op bestaande gebruiker en producten
const userExists = await findUserById(userId);
if (!userExists) {
return { error: { code: "404", message: "Gebruiker niet gevonden" } };
}
const products = await findProductsByIds(productIds);
if (products.length !== productIds.length) {
return { error: { code: "404", message: "Een of meer producten niet gevonden" } };
}
// Order aanmaken
const order = await createOrder({ userId, productIds });
return { order };
} catch (err) {
return { error: { code: "500", message: "Order aanmaken mislukt", details: err.message } };
}
},
},
};
```
---
### Samenvatting
- Met custom directives zoals `@validateEmail` wordt data validatie op schema-niveau afgedwongen.
- Middleware controleert authenticatie en autorisatie vóór resolvers.
- Foutmeldingen worden gestandaardiseerd via een `Error` type en union-resultaten, wat leidt tot consistente foutafhandeling.
- Validaties en foutafhandelingsmechanismen zorgen voor data-integriteit en gebruiksvriendelijke foutmeldingen.
Indien je nog verdere uitbreidingen of specifieke implementatie details wenst, laat het gerust weten!
provider: deepseek
model: deepseek-chat
Zeker, hier is een geavanceerd GraphQL schema-ontwerp voor een e-commerce platform met robuuste foutafhandeling en validatie:
## Schema Definitie
```graphql
# Custom Directives
directive @auth(requires: Role = USER) on FIELD_DEFINITION
directive @email on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
directive @validate(min: Int, max: Int) on ARGUMENT_DEFINITION | INPUT_FIELD_DEFINITION
# Enums
enum Role {
USER
ADMIN
}
enum OrderStatus {
PENDING
PROCESSING
SHIPPED
DELIVERED
CANCELLED
}
# Scalars voor betere validatie
scalar EmailAddress
scalar PositiveInt
scalar DateTime
scalar Price
# Error Types voor consistente foutafhandeling
interface Error {
message: String!
code: String!
}
type ValidationError implements Error {
message: String!
code: String!
field: String!
}
type AuthenticationError implements Error {
message: String!
code: String!
}
type AuthorizationError implements Error {
message: String!
code: String!
requiredRole: Role!
}
# Response Types met error handling
type UserResponse {
user: User
errors: [Error!]
}
type ProductResponse {
product: Product
errors: [Error!]
}
type OrderResponse {
order: Order
errors: [Error!]
}
# Main Types
type User {
id: ID!
email: EmailAddress!
name: String! @validate(min: 2, max: 50)
role: Role!
orders: [Order!]!
createdAt: DateTime!
updatedAt: DateTime!
}
type Product {
id: ID!
name: String! @validate(min: 2, max: 100)
description: String!
price: Price!
stock: PositiveInt!
category: String!
createdAt: DateTime!
updatedAt: DateTime!
}
type Order {
id: ID!
user: User!
items: [OrderItem!]!
total: Price!
status: OrderStatus!
createdAt: DateTime!
updatedAt: DateTime!
}
type OrderItem {
product: Product!
quantity: PositiveInt!
price: Price!
}
# Input Types
input CreateUserInput {
email: EmailAddress! @email
name: String! @validate(min: 2, max: 50)
password: String! @validate(min: 8)
}
input UpdateProductInput {
id: ID!
name: String @validate(min: 2, max: 100)
price: Price
stock: PositiveInt
}
input CreateOrderInput {
userId: ID!
items: [OrderItemInput!]!
}
input OrderItemInput {
productId: ID!
quantity: PositiveInt! @validate(min: 1, max: 100)
}
# Queries
type Query {
# Gebruikers queries
getUser(id: ID!): UserResponse @auth
getUsers: [User!]! @auth(requires: ADMIN)
# Product queries
getProduct(id: ID!): ProductResponse
getProducts(category: String): [Product!]!
# Bestelling queries
getOrder(id: ID!): OrderResponse @auth
getUserOrders(userId: ID!): [Order!]! @auth
}
# Mutations
type Mutation {
# Gebruiker mutaties
createUser(input: CreateUserInput!): UserResponse
updateUser(id: ID!, input: UpdateUserInput!): UserResponse @auth
# Product mutaties
createProduct(input: CreateProductInput!): ProductResponse @auth(requires: ADMIN)
updateProduct(input: UpdateProductInput!): ProductResponse @auth(requires: ADMIN)
# Bestelling mutaties
createOrder(input: CreateOrderInput!): OrderResponse @auth
updateOrderStatus(id: ID!, status: OrderStatus!): OrderResponse @auth
cancelOrder(id: ID!): OrderResponse @auth
}
```
## Implementatie Voorbeelden
### 1. Custom Email Directive Implementatie
```javascript
// email-directive.js
const { GraphQLError } = require('graphql');
const emailDirective = {
email: {
visitArgumentDefinition(argument) {
this.ensureString(argument);
argument.type = new GraphQLNonNull(GraphQLString);
},
visitInputFieldDefinition(field) {
this.ensureString(field);
field.type = new GraphQLNonNull(GraphQLString);
}
}
};
function validateEmail(email) {
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
if (!emailRegex.test(email)) {
throw new GraphQLError('Ongeldig e-mailformaat', {
extensions: {
code: 'INVALID_EMAIL',
field: 'email'
}
});
}
}
```
### 2. Authentication Middleware
```javascript
// auth-middleware.js
const authMiddleware = async (resolve, root, args, context, info) => {
const authDirective = info.parentType.getFields()[info.fieldName].astNode.directives
.find(d => d.name.value === 'auth');
if (authDirective) {
if (!context.user) {
throw new GraphQLError('Niet geauthenticeerd', {
extensions: {
code: 'UNAUTHENTICATED',
http: { status: 401 }
}
});
}
const requiresRole = authDirective.arguments?.find(arg => arg.name.value === 'requires')?.value.value;
if (requiresRole && context.user.role !== requiresRole) {
throw new GraphQLError('Onvoldoende rechten', {
extensions: {
code: 'FORBIDDEN',
requiredRole: requiresRole,
http: { status: 403 }
}
});
}
}
return resolve(root, args, context, info);
};
```
### 3. Error Formatter voor Consistente Foutmeldingen
```javascript
// error-formatter.js
const formatError = (error) => {
const { message, extensions } = error;
const baseError = {
message,
code: extensions?.code || 'INTERNAL_ERROR'
};
switch (extensions?.code) {
case 'VALIDATION_ERROR':
return {
...baseError,
field: extensions.field
};
case 'UNAUTHENTICATED':
return { ...baseError };
case 'FORBIDDEN':
return {
...baseError,
requiredRole: extensions.requiredRole
};
default:
return {
message: 'Er is een interne serverfout opgetreden',
code: 'INTERNAL_ERROR'
};
}
};
```
### 4. Resolver Implementatie met Foutafhandeling
```javascript
// user-resolvers.js
const userResolvers = {
Mutation: {
createUser: async (_, { input }, { dataSources }) => {
try {
// Validatie
if (input.password.length < 8) {
throw new GraphQLError('Wachtwoord moet minimaal 8 tekens bevatten', {
extensions: {
code: 'VALIDATION_ERROR',
field: 'password'
}
});
}
const existingUser = await dataSources.users.findByEmail(input.email);
if (existingUser) {
throw new GraphQLError('E-mailadres is al in gebruik', {
extensions: {
code: 'DUPLICATE_EMAIL'
}
});
}
const user = await dataSources.users.create(input);
return { user, errors: null };
} catch (error) {
if (error instanceof GraphQLError) {
return { user: null, errors: [error] };
}
throw error;
}
}
}
};
```
## Gebruik in Apollo Server
```javascript
// server.js
const { ApolloServer } = require('apollo-server');
const { makeExecutableSchema } = require('@graphql-tools/schema');
const schema = makeExecutableSchema({
typeDefs,
resolvers,
schemaDirectives: {
auth: AuthDirective,
email: EmailDirective,
validate: ValidateDirective
}
});
const server = new ApolloServer({
schema,
plugins: [{
requestDidStart() {
return {
didEncounterErrors({ errors }) {
errors.forEach(error => {
console.error('GraphQL Error:', error);
});
}
};
}
}],
formatError,
context: ({ req }) => {
const token = req.headers.authorization || '';
const user = getUserFromToken(token);
return { user, dataSources };
}
});
```
Dit ontwerp biedt:
1. **Robuuste validatie** via custom directives
2. **Consistente foutafhandeling** met gestructureerde error responses
3. **Beveiliging** via authentication middleware
4. **Data-integriteit** door strikte input validatie
5. **Schaalbaarheid** door modulaire opzet
De implementatie zorgt voor duidelijke foutmeldingen en voorkomt dat ongeldige data in het systeem terechtkomt.
error: Generation failed [deepseek] prompt_id=2207 locale=fr err=DeepSeek connection/timeout | Generation failed [deepseek] prompt_id=2207 locale=pt err=DeepSeek connection/timeout