slogan3

Ontwerp een Geavanceerd GraphQL-schema met Geautomatiseerde Data Normalisatie en Consistentiebeheer

description

Met deze prompt kun je een GraphQL-schema ontwerpen dat automatisch data normaliseert en consistentie bewaakt, waardoor je API betrouwbaarder, schaalbaarder en onderhoudsvriendelijker wordt. Dit lost problemen op rondom data-inconsistenties en maakt het eenvoudiger om complexe datasets te beheren zonder duplicatie of conflicten. De prompt biedt concrete voorbeelden en best practices, beter dan generieke schema-ontwerpen die deze automatisering missen.

prompt

Help me een geavanceerd GraphQL-schema te ontwerpen dat geautomatiseerde data normalisatie en consistentiebeheer ondersteunt binnen mijn domein: <beschrijf je domein of toepassingsgebied>. Ik wil functies zoals: <specificeer gewens ...

try_prompt

generate_helper
disclaimerOnPageApi

ai_answers

provider: openai
model: gpt-4.1-nano
Hier is een geavanceerd GraphQL-schema dat automatische normalisatie en consistentiebeheer in jouw social media platform ondersteunt. Het schema bevat custom scalars en resolvers die zorgen voor datakwaliteit, schaalbaarheid en fouttolerantie. ### 1. Belangrijkste ontwerpprincipes - **Normalisatie bij invoer:** Gebruik custom scalars en resolvers om telefoonnummers te normaliseren naar internationaal formaat en e-mails naar kleine letters. - **Schema-uitbreiding:** Voeg input types en mutaties toe om datakwaliteit te waarborgen bij creatie en update. - **Flexibiliteit en schaalbaarheid:** Schematiseer entiteiten en scheid validatie van businesslogica via resolvers. - **Foutafhandeling:** Gebruik uitgebreide foutmeldingen en fallback-mechanismen. --- ### 2. GraphQL-schema ontwerp ```graphql # Custom scalar voor telefoonnummers scalar PhoneNumber # Custom scalar voor e-mailadressen scalar Email # User type type User { id: ID! username: String! email: Email! phone: PhoneNumber createdAt: String! updatedAt: String! } # Bericht type type Post { id: ID! author: User! content: String! createdAt: String! comments: [Comment!]! } # Reactie type type Comment { id: ID! author: User! content: String! createdAt: String! } # Query type type Query { getUser(id: ID!): User getPost(id: ID!): Post listUsers: [User!]! listPosts: [Post!]! } # Input types voor mutaties input CreateUserInput { username: String! email: Email! phone: PhoneNumber } input UpdateUserInput { email: Email phone: PhoneNumber } # Mutatie type type Mutation { createUser(input: CreateUserInput!): User! updateUser(id: ID!, input: UpdateUserInput!): User! createPost(authorId: ID!, content: String!): Post! addComment(postId: ID!, authorId: ID!, content: String!): Comment! } ``` --- ### 3. Normalisatie en validatie in resolvers - **Email:** Convert naar kleine letters voordat opgeslagen. - **Telefoonnummer:** Normaliseer naar internationaal formaat (bijvoorbeeld +31..., +49..., etc.) met behulp van een bibliotheek zoals `libphonenumber`. **Voorbeeld resolver voor createUser:** ```javascript const { parsePhoneNumberFromString } = require('libphonenumber-js'); const resolvers = { Email: { serialize(value) { return value.toLowerCase(); // Normaliseer naar kleine letters }, parseValue(value) { // Validatie kan hier worden toegevoegd return value.toLowerCase(); } }, PhoneNumber: { serialize(value) { return value; // Al genormaliseerd }, parseValue(value) { const phoneNumber = parsePhoneNumberFromString(value); if (!phoneNumber || !phoneNumber.isValid()) { throw new Error('Ongeldig telefoonnummer'); } return phoneNumber.formatInternational(); // Normaliseer } }, Mutation: { createUser: (_, { input }) => { const email = input.email.toLowerCase(); let phone = null; if (input.phone) { const phoneNumber = parsePhoneNumberFromString(input.phone); if (!phoneNumber || !phoneNumber.isValid()) { throw new Error('Ongeldig telefoonnummer'); } phone = phoneNumber.formatInternational(); } // Sla op in database met genormaliseerde waarden const newUser = { id: generateID(), username: input.username, email, phone, createdAt: new Date().toISOString(), updatedAt: new Date().toISOString() }; // ... database opslaan return newUser; }, updateUser: (_, { id, input }) => { // Fetch bestaande user const user = getUserById(id); if (!user) throw new Error('Gebruiker niet gevonden'); if (input.email) { user.email = input.email.toLowerCase(); } if (input.phone) { const phoneNumber = parsePhoneNumberFromString(input.phone); if (!phoneNumber || !phoneNumber.isValid()) { throw new Error('Ongeldig telefoonnummer'); } user.phone = phoneNumber.formatInternational(); } user.updatedAt = new Date().toISOString(); // ... database update return user; } } }; ``` --- ### 4. Toelichting op ontwerpkeuzes - **Data kwaliteit:** Door gebruik te maken van custom scalars en preprocessing in resolvers, wordt de datakwaliteit gewaarborgd. E-mails worden altijd in kleine letters opgeslagen, telefoonnummers worden genormaliseerd, wat consistentie en correcte data-invoer garandeert. - **Schaalbaarheid:** Scheiding van validatie (resolvers) en data opslag maakt het mogelijk om eenvoudig te schalen en te integreren met verschillende databronnen. De schematische scheiding zorgt voor beheersbaarheid in complexe API-omgevingen. - **Fouttolerantie:** Door uitgebreide validatie en foutmeldingen wordt het systeem robuust; ongeldige data wordt afgewezen met duidelijke foutmeldingen, wat debugging en datakwaliteit verbetert. - **Flexibiliteit:** Het gebruik van input types en mutaties maakt het mogelijk om complexe workflows te ondersteunen zonder dat de API onnodig ingewikkeld wordt. --- ### Samenvatting Dit schema zorgt voor automatische datanormalisatie via custom scalars en resolvers, ondersteunt schaalbare en fouttolerante data-invoer, en bevordert datakwaliteit binnen je social media platform. Door deze aanpak te volgen, blijft je API robuust en consistent, zelfs in complexe omgevingen.
provider: deepseek
model: deepseek-chat
Zeker, ik help je met een geavanceerd GraphQL-schema voor een sociaal media platform. Hieronder vind je een uitgebreid ontwerp met automatische data-normalisatie en consistentiebeheer. --- ### **GraphQL Schema Ontwerp** ```graphql # Basis types scalar PhoneNumber scalar EmailAddress scalar DateTime type User { id: ID! username: String! email: EmailAddress! phone: PhoneNumber profile: UserProfile posts: [Post!]! createdAt: DateTime! updatedAt: DateTime! } type UserProfile { displayName: String! avatar: String bio: String } type Post { id: ID! author: User! content: String! media: [String!] reactions: [Reaction!]! comments: [Comment!]! createdAt: DateTime! updatedAt: DateTime! } type Comment { id: ID! post: Post! author: User! content: String! reactions: [Reaction!]! createdAt: DateTime! } type Reaction { id: ID! type: ReactionType! user: User! createdAt: DateTime! } enum ReactionType { LIKE LOVE HAHA WOW SAD ANGRY } # Input types met validatie input CreateUserInput { username: String! email: String! phone: String profile: UserProfileInput } input UpdateUserInput { username: String email: String phone: String profile: UserProfileInput } input UserProfileInput { displayName: String! avatar: String bio: String } input CreatePostInput { content: String! media: [String!] } # Queries & Mutations type Query { getUser(id: ID!): User getPost(id: ID!): Post getUserPosts(userId: ID!): [Post!]! searchUsers(query: String!): [User!]! } type Mutation { createUser(input: CreateUserInput!): User! updateUser(id: ID!, input: UpdateUserInput!): User! createPost(userId: ID!, input: CreatePostInput!): Post! addReaction(postId: ID!, type: ReactionType!): Reaction! addComment(postId: ID!, content: String!): Comment! } ``` --- ### **Custom Scalars & Normalisatie** ```javascript // Voorbeeld implementatie (Node.js/Apollo) const { GraphQLScalarType } = require('graphql'); const { parsePhoneNumberFromString } = require('libphonenumber-js'); const PhoneNumber = new GraphQLScalarType({ name: 'PhoneNumber', description: 'Telefoonnummer in E.164 formaat', serialize(value) { // Validatie bij uitgaande data if (!isValidPhoneNumber(value)) { throw new Error('Ongeldig telefoonnummer formaat'); } return value; }, parseValue(value) { // Normalisatie bij inkomende data const phoneNumber = parsePhoneNumberFromString(value, 'NL'); if (!phoneNumber || !phoneNumber.isValid()) { throw new Error('Ongeldig telefoonnummer'); } return phoneNumber.format('E.164'); } }); const EmailAddress = new GraphQLScalarType({ name: 'EmailAddress', description: 'Geverifieerd e-mailadres in lowercase', serialize(value) { return value; }, parseValue(value) { const normalizedEmail = value.toLowerCase().trim(); if (!isValidEmail(normalizedEmail)) { throw new Error('Ongeldig e-mailadres'); } return normalizedEmail; } }); ``` --- ### **Data Consistentie Laag** ```javascript // Data Consistency Manager class DataConsistencyManager { constructor() { this.normalizers = { phone: this.normalizePhone, email: this.normalizeEmail }; } normalizePhone(phone) { const parsed = parsePhoneNumberFromString(phone, 'NL'); return parsed?.isValid() ? parsed.format('E.164') : null; } normalizeEmail(email) { return email.toLowerCase().trim(); } async ensureConsistency(input, context) { const normalized = { ...input }; // Automatische normalisatie if (normalized.phone) { normalized.phone = this.normalizePhone(normalized.phone); } if (normalized.email) { normalized.email = this.normalizeEmail(normalized.email); } // Duplicate prevention await this.checkUniqueness(normalized, context); return normalized; } async checkUniqueness(data, context) { if (data.email) { const existing = await context.db.user.findUnique({ where: { email: data.email } }); if (existing) throw new Error('E-mailadres already in use'); } } } ``` --- ### **Resolvers met Foutafhandeling** ```javascript const resolvers = { Mutation: { createUser: async (_, { input }, context) => { try { // Data normalisatie & consistentie check const normalizedInput = await context.consistencyManager.ensureConsistency(input, context); // Transactionele operatie return await context.db.$transaction(async (tx) => { const user = await tx.user.create({ data: { ...normalizedInput, profile: input.profile ? { create: input.profile } : undefined }, include: { profile: true } }); // Audit log await tx.auditLog.create({ data: { action: 'USER_CREATED', userId: user.id, metadata: { input: normalizedInput } } }); return user; }); } catch (error) { // Gestructureerde foutafhandeling context.logger.error('User creation failed', { error, input }); throw new Error(`Gebruikersaanmaak mislukt: ${error.message}`); } } } }; ``` --- ### **Ontwerp Keuzes & Voordelen** #### **1. Datakwaliteit** - **Automatische Normalisatie**: Telefoonnummers en e-mails worden gestandaardiseerd bij invoer - **Validatie op Schema-niveau**: Custom scalars garanderen geldige dataformaten - **Unieke Constraints**: Database-level constraints voorkomen duplicates #### **2. Schaalbaarheid** - **Efficiente Queries**: Geneste relaties minimaliseren N+1 query problemen - **Cursor-based Pagination**: Kan eenvoudig worden toegevoegd voor lijsten - **Caching-strategie**: GraphQL responses zijn ideaal voor CDN-caching #### **3. Fouttolerantie** - **Transactionele Operaties**: Gehele operaties of geen (atomiciteit) - **Gestructureerde Foutafhandeling**: Consistente error responses - **Circuit Breaker Pattern**: Kan worden geïmplementeerd voor externe services #### **4. Onderhoudbaarheid** - **Schema First Design**: Duidelijke contracten tussen frontend en backend - **Modular Design**: Normalisatie-logica is centrale verantwoordelijkheid - **Uitbreidbaarheid**: Nieuwe velden kunnen eenvoudig normalisatie-regels krijgen --- ### **Aanbevolen Patronen** 1. **DataLoader voor N+1 Problemen**: ```javascript const userLoader = new DataLoader(async (userIds) => { const users = await context.db.user.findMany({ where: { id: { in: userIds } } }); return userIds.map(id => users.find(user => user.id === id)); }); ``` 2. **Audit Logging voor Traceerbaarheid**: ```graphql type AuditLog { id: ID! action: String! userId: ID metadata: JSON createdAt: DateTime! } ``` 3. **Rate Limiting**: ```javascript // Implementatie aan de resolver-level voor abuse prevention ``` Dit ontwerp biedt een robuuste foundation die datakwaliteit garandeert terwijl het schaalbaar en onderhoudbaar blijft in complexe API-omgevingen. De automatische normalisatie zorgt voor consistente data zonder extra client-logica, terwijl de foutafhandeling betrouwbare operaties garandeert.