🔏
Azure Serverless Quickstart
  • Introduction
  • Initial Setup
    • Workstation Installs
    • Codebase
      • Directory Structure
      • User Interface Project
        • Configuring StoryBook
        • Configure Tailwind
        • Configure Craco
        • -Architectural Decision Log
      • Data Access Project
        • DDD
      • Untitled
      • Full Stack Debugging
      • Creating GitHub Project
    • Infrastructure
      • Configure Session Behavior
      • Create AAD Tenant
      • Resource Group
      • Create AAD B2C Instance
        • Identity Experience Framework
        • Configure Session Behavior
      • Storage Account & CDN
        • CDN Rules
        • Configure Azure BLOB Storage
      • App Insights
        • Create AppInsight Account
        • Apollo GraphQL App Insights Configuration
      • CosmosDB
      • Twilio SendGrid
      • KeyVault
      • Function
      • Function App Settings
      • Front Door
      • DevOps
      • Optional Items
        • Azure Data Factory
      • Azure Event Hub
    • CICD and Source Control
      • Azure DevOps
      • SonarCloud
        • Incorporate into Yaml
      • Chromatic
      • User Interface YAML
      • CICD for Data Access
        • Create Pipeline
        • Data Access YAML
  • Application Structure
    • Connect Apollo
      • Apollo Overview
      • Create Apollo Component
    • MongoDB Integration
      • Mappings
      • Directory Structure
      • Apollo Connection
      • Models
      • Queries Mutations and Subscriptions
      • Caching Reponses
    • Integrating GraphQL Tools
      • GraphQL Code Generator
    • Feature Flags
      • Flag Structure & Storage
      • Website Integration
      • Apollo Integration
      • Tips and Techniques
      • Alternative Approaches
    • React Router
    • Adding Authentication
      • Create AAD Applications
      • Configure AAD For External Identities
      • Adding MSAL And React
      • Add MSAL to the build
      • Add MSAL to ApolloClient
      • Add MSAL to ApolloServer
    • Ant Design
    • Jest Tests
  • Azure Active Directory Business-to-Consumer (AD B2C)
    • Introduction
    • How to navigate through AD B2C documentation
    • Localization
    • Abbreviations
    • Azure AD B2C Extension
  • Cognitive Search
  • Cost Analysis
  • Technical Architecture
    • Identity and Access Control
  • Adding Functionality
    • Google Analytics
      • Create Analytics
    • DAPR
      • DAPR setup
      • DAPR Services (ignore for now)
        • Identity
  • Patterns and Practices
    • Idempotent Messages
    • Pathways
    • DDD
      • Initial Setup
        • Aggregate Root
        • Entity
        • Value Object
      • Field Types
        • Primitive Types
        • Non-Primitive Types
          • Types.DocumentArray
          • PopulatedDoc
          • Custom Types
      • Example Walkthrough
  • Open Items
    • Issue Tracking
  • Helpful Resources
  • DDD
    • Page 1
  • Experimental
    • StaticWebApp
    • Azure Maps
Powered by GitBook
On this page

Was this helpful?

  1. Application Structure
  2. Integrating GraphQL Tools

GraphQL Code Generator

Introduce Type Safety for the GraphQL Schema and Documents

Need to install dependencies and dev dependencies.

/DataAccess - (Terminal / Command Propt)
npm i @graphql-tools/graphql-file-loader @graphql-tools/load @graphql-tools/load-files @graphql-tools/schema @graphql-tools/stitch graphql-scalars
npm i -D @graphql-codegen/cli @graphql-codegen/typescript @graphql-codegen/typescript-resolvers
npm i -D @graphql-codegen/introspection @graphql-codegen/typed-document-node @graphql-codegen/typescript-operations

Structure:

#inputs
/data-access
- /codegen.yml #Configuration file for GrapQL Code Generator
- /graphql
  - /context.ts #Type definition of the Context 
  - /resolvers
    - index.ts #exports all resolvers to be merged into Schema
    - /core/
      - /graphql-tools-scalars.ts #Enables Scalars to be used
      - /schema.graphql #Baseline schema
    - /**/*.reslovers.ts #GraphQL Resolvers
    - /**/*.graphql #Definitions of GraphQL Types,Queries,Mutations,Inputs
    - /types/*.ts #Definitions of TypeScript Interfaces which Match GraphQL Types


#outputs
/data-access
- /graphql
  - /generated.ts #Type file to ensure type safety for Queries/Mutations/Resolvers/Types
  - /graphql.schema.json #Introspection file to Expose all GraphQL Schema to Apollo
  
/ui/src/generated.tsx #Type file to ensure type safety for UI side Queries/Mutations/Resolvers/Types/Fragments

This is very simple context object - more details can be added later.

/data-access/graphql/context.ts
export type Context = {
  authToken: string;
}

/data-access/graphql/resolvers/index.ts
import {Resolvers} from '../generated';

import path  from 'path';
import { mergeResolvers } from '@graphql-tools/merge';
import { loadFilesSync } from '@graphql-tools/load-files';

const resolversArray = loadFilesSync(path.join(__dirname, "./**/*.resolvers.*"));

export const resolvers: Resolvers = mergeResolvers(resolversArray);

The GraphQL Tools Scalars project exposes a handful of helpful types including DateTime/Email/ObjectID. In order to make these types available we need to re-export them.

/data-access/graphql/resolvers/core/graphql-tools-scalars.ts
const { typeDefs } = require('graphql-scalars');
const { buildSchema } = require('graphql');

const scalars = typeDefs.join('\n')

module.exports = buildSchema(scalars);
/data-access/graphql/resolvers/core/schema.graphql
""" Core schema """
schema {
  query: Query
  mutation: Mutation
}

""" Base Mutation Type definition - all mutations will be defined in separate files extending this type """
type Mutation {
    """
    IGNORE: Dummy field necessary for the Mutation type to be valid
    """
    _empty:String
}

""" Base Query Type definition - , all mutations will be defined in separate files extending this type """
type Query {
    """
    IGNORE: Dummy field necessary for the Query type to be valid
    """
    _empty:String
}

""" Required to enable Apollo Cache Control """
enum CacheControlScope {
  PUBLIC
  PRIVATE
}

""" Required to enable Apollo Cache Control """
directive @cacheControl(
  maxAge: Int
  scope: CacheControlScope
  inheritMaxAge: Boolean
) on FIELD_DEFINITION | OBJECT | INTERFACE | UNION
/data-access/graphql/init/extensions/schema-builder.ts
import { loadSchemaSync } from '@graphql-tools/load';
import { addResolversToSchema, mergeSchemas } from '@graphql-tools/schema';
import { resolvers } from '../../resolvers';
import { JsonFileLoader } from '@graphql-tools/json-file-loader';
import * as Scalars from 'graphql-scalars';
import { makeExecutableSchema } from '@graphql-tools/schema';


const schema = loadSchemaSync('./graphql.schema.json', {
  loaders: [new JsonFileLoader()],
});

const appSchema = addResolversToSchema(schema,resolvers)

const scalarSchema = makeExecutableSchema({
  typeDefs:[
    ...Scalars.typeDefs,
  ],
  resolvers:{
    ...Scalars.resolvers,
  }
});

export const combinedSchema = mergeSchemas({
  schemas: [
    appSchema,
    scalarSchema,
  ]
});

YML

/data-access/codegen.yml
overwrite: true
schema: 
  - "./graphql/resolvers/core/graphql-tools-scalars.ts"
  - "./graphql/resolvers/**/**.graphql"
documents: "../ui/src/components/**/**.graphql"
generates:
  graphql/generated.ts:
    config:
      contextType: "./context#Context"
      useIndexSignature: true
      mappers:
        Category: ./resolvers/types/category#CategoryType
        Listing: ./resolvers/types/listing#ListingType
        CreateListingPayload: ./resolvers/types/create-listing-payload#CreateListingPayloadType
        Location: ./resolvers/types/location#LocationType
        Point: ./resolvers/types/point#PointType
        User: ./resolvers/types/user#UserType
      scalars:
        BigInt: any
        Byte: any
        Currency: any
        Date: Date
        DateTime: any
        Duration: any
        EmailAddress: string
        GUID: string
        HSL: any
        HSLA: any
        HexColorCode: any
        Hexadecimal: any
        IBAN: any
        IPv4: any
        IPv6: any
        ISBN: any
        ISO8601Duration: any
        JSON: any
        JSONObject: any
        JWT: any
        Latitude: any
        LocalDate: any
        LocalEndTime: any
        LocalTime: any
        Long: any
        Longitude: any
        MAC: any
        NegativeFloat: any
        NegativeInt: any
        NonEmptyString: any
        NonNegativeFloat: any
        NonNegativeInt: any
        NonPositiveFloat: any
        NonPositiveInt: any
        ObjectID: any
        PhoneNumber: any
        Port: any
        PositiveFloat: any
        PositiveInt: any
        PostalCode: any
        RGB: any
        RGBA: any
        SafeInt: any
        Time: any
        Timestamp: any
        URL: any
        USCurrency: any
        UUID: any
        UnsignedFloat: any
        UnsignedInt: any
        UtcOffset: any
        Void: any
    plugins:
      - "typescript"
      - "typescript-resolvers"
  ./graphql.schema.json:
    plugins:
      - "introspection"

  ../ui/src/generated.tsx:
    config:
      withHooks: true
      withHOC: false
      withComponent: false
    plugins:
      - "typescript"
      - "typescript-operations"
      - "typed-document-node"
hooks:
  afterAllFileWrite:
    - npx prettier --write
PreviousIntegrating GraphQL ToolsNextFeature Flags

Last updated 3 years ago

Was this helpful?