CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-nestjs--graphql

GraphQL integration for the NestJS framework enabling developers to build GraphQL APIs using decorators and TypeScript

Pending
Quality

Pending

Does it follow best practices?

Impact

Pending

No eval scenarios have been run

SecuritybySnyk

Pending

The risk profile of this skill

Overview
Eval results
Files

type-system.mddocs/

Type System and Utilities

Type transformation utilities, custom scalar definitions, and helper functions for creating complex GraphQL types. This module provides powerful tools for manipulating GraphQL types, creating unions and enums, and extending the GraphQL type system with custom scalars.

Capabilities

Type Transformation Utilities

Helper functions for creating derivative types from existing GraphQL types, similar to TypeScript utility types.

/**
 * Creates a partial version of a GraphQL type where all fields are optional
 * @param classRef - Reference to the base class
 * @param decorator - Optional decorator to apply to the new type
 * @returns New type class with all optional fields
 */
function PartialType<T>(
  classRef: Type<T>, 
  decorator?: ClassDecorator
): Type<Partial<T>>;

/**
 * Creates a new type with only selected fields from the base type
 * @param classRef - Reference to the base class
 * @param keys - Array of field names to include
 * @param decorator - Optional decorator to apply to the new type
 * @returns New type class with only selected fields
 */
function PickType<T, K extends keyof T>(
  classRef: Type<T>, 
  keys: readonly K[], 
  decorator?: ClassDecorator
): Type<Pick<T, K>>;

/**
 * Creates a new type with specified fields omitted from the base type
 * @param classRef - Reference to the base class
 * @param keys - Array of field names to omit
 * @param decorator - Optional decorator to apply to the new type
 * @returns New type class with omitted fields removed
 */
function OmitType<T, K extends keyof T>(
  classRef: Type<T>, 
  keys: readonly K[], 
  decorator?: ClassDecorator
): Type<Omit<T, K>>;

/**
 * Creates an intersection type combining fields from two types
 * @param classARef - Reference to the first class
 * @param classBRef - Reference to the second class
 * @param decorator - Optional decorator to apply to the new type
 * @returns New type class combining both input types
 */
function IntersectionType<A, B>(
  classARef: Type<A>, 
  classBRef: Type<B>, 
  decorator?: ClassDecorator
): Type<A & B>;

Usage Examples:

import { ObjectType, InputType, Field, PartialType, PickType, OmitType, IntersectionType } from "@nestjs/graphql";

// Base types
@ObjectType()
class User {
  @Field()
  id: string;
  
  @Field()
  name: string;
  
  @Field()
  email: string;
  
  @Field()
  createdAt: Date;
}

@InputType()
class CreateUserInput {
  @Field()
  name: string;
  
  @Field()
  email: string;
  
  @Field({ nullable: true })
  bio?: string;
}

// Partial type - all fields optional
@InputType()
class UpdateUserInput extends PartialType(CreateUserInput) {}
// Results in: { name?: string; email?: string; bio?: string; }

// Pick type - select specific fields
@ObjectType()
class UserSummary extends PickType(User, ['id', 'name'] as const) {}
// Results in: { id: string; name: string; }

// Omit type - exclude specific fields
@ObjectType()
class PublicUser extends OmitType(User, ['email'] as const) {}
// Results in: { id: string; name: string; createdAt: Date; }

// Intersection type - combine multiple types
@InputType()
class UserPreferences {
  @Field()
  theme: string;
  
  @Field()
  notifications: boolean;
}

@InputType()
class UserWithPreferences extends IntersectionType(
  CreateUserInput,
  UserPreferences
) {}
// Results in: CreateUserInput & UserPreferences combined

Union and Enum Type Creation

Functions for creating GraphQL union types and registering TypeScript enums as GraphQL enums.

/**
 * Creates a GraphQL union type from multiple object types
 * @param options - Configuration options for the union type
 * @returns GraphQL union type definition
 */
function createUnionType(options: UnionOptions): GraphQLUnionType;

/**
 * Registers a TypeScript enum as a GraphQL enum type
 * @param enumObject - The TypeScript enum object to register
 * @param options - Configuration options for the enum type
 */
function registerEnumType(enumObject: object, options: EnumOptions): void;

/**
 * Options for creating union types
 */
interface UnionOptions {
  /** Name of the union type */
  name: string;
  /** Array of types that can be part of the union */
  types: () => readonly [Function, ...Function[]];
  /** Function to resolve which concrete type an object represents */
  resolveType?: (value: any) => Function | string | Promise<Function | string>;
  /** Description for the union type */
  description?: string;
}

/**
 * Options for registering enum types
 */
interface EnumOptions {
  /** Name of the GraphQL enum type */
  name: string;
  /** Description for the enum type */
  description?: string;
  /** Custom values mapping for enum entries */
  valuesMap?: Record<string, EnumValueConfig>;
}

interface EnumValueConfig {
  /** Custom value for the enum entry */
  value?: any;
  /** Description for the enum entry */
  description?: string;
  /** Deprecation reason */
  deprecationReason?: string;
}

Usage Examples:

import { ObjectType, Field, createUnionType, registerEnumType } from "@nestjs/graphql";

// Define types for union
@ObjectType()
class User {
  @Field()
  id: string;
  
  @Field()
  name: string;
}

@ObjectType()
class Post {
  @Field()
  id: string;
  
  @Field()
  title: string;
}

// Create union type
const SearchResult = createUnionType({
  name: 'SearchResult',
  types: () => [User, Post] as const,
  resolveType: (value) => {
    if (value.name) return User;
    if (value.title) return Post;
    return null;
  },
});

// TypeScript enum
enum UserRole {
  ADMIN = 'admin',
  USER = 'user',
  MODERATOR = 'moderator',
}

// Register enum with GraphQL
registerEnumType(UserRole, {
  name: 'UserRole',
  description: 'User role in the system',
  valuesMap: {
    ADMIN: {
      description: 'System administrator with full access',
    },
    USER: {
      description: 'Regular user with limited access',
    },
    MODERATOR: {
      description: 'Content moderator with intermediate access',
      deprecationReason: 'Use ADMIN role instead',
    },
  },
});

// Usage in GraphQL types
@ObjectType()
class User {
  @Field()
  id: string;
  
  @Field(() => UserRole)
  role: UserRole;
}

Built-in Scalar Types

Pre-defined GraphQL scalar types for common data formats.

/**
 * GraphQL scalar type for ISO 8601 DateTime strings
 * Serializes JavaScript Date objects to ISO string format
 */
export const GraphQLISODateTime: GraphQLScalarType;

/**
 * GraphQL scalar type for Unix timestamps
 * Serializes JavaScript Date objects to Unix timestamp numbers
 */
export const GraphQLTimestamp: GraphQLScalarType;

/**
 * GraphQL Int scalar type (re-export from graphql package)
 */
export const Int: GraphQLScalarType;

/**
 * GraphQL Float scalar type (re-export from graphql package)
 */
export const Float: GraphQLScalarType;

/**
 * GraphQL ID scalar type (re-export from graphql package)
 */
export const ID: GraphQLScalarType;

Usage Examples:

import { ObjectType, Field, GraphQLISODateTime, GraphQLTimestamp, Int, Float, ID } from "@nestjs/graphql";

@ObjectType()
class Event {
  @Field(() => ID)
  id: string;
  
  @Field()
  title: string;
  
  @Field(() => GraphQLISODateTime)
  createdAt: Date; // Serialized as "2023-12-01T10:30:00.000Z"
  
  @Field(() => GraphQLTimestamp)
  updatedAt: Date; // Serialized as 1701423000000
  
  @Field(() => Int)
  attendeeCount: number;
  
  @Field(() => Float)
  rating: number;
}

Custom Scalar Creation

Tools for creating custom GraphQL scalar types with validation and serialization.

/**
 * Interface for implementing custom GraphQL scalars
 */
interface GraphQLScalarTypeConfig<TInternal, TExternal> {
  name: string;
  description?: string;
  
  /** Serialize internal value to external representation */
  serialize(value: TInternal): TExternal;
  
  /** Parse external value from variables */
  parseValue(value: TExternal): TInternal;
  
  /** Parse external value from AST literal */
  parseLiteral(ast: ValueNode, variables?: Record<string, any>): TInternal;
}

/**
 * Base class for implementing custom scalars with the @Scalar decorator
 */
abstract class CustomScalar<T, K> {
  /** Human-readable description of the scalar */
  description?: string;
  
  /** Serialize internal value to external representation */
  abstract serialize(value: T): K;
  
  /** Parse external value from GraphQL variables */
  abstract parseValue(value: K): T;
  
  /** Parse external value from AST literal in queries */
  abstract parseLiteral(ast: ValueNode): T;
}

Custom Scalar Examples:

import { Scalar, CustomScalar } from "@nestjs/graphql";
import { GraphQLError } from "graphql";
import { ValueNode, Kind } from "graphql/language";

// Email scalar with validation
@Scalar('Email', () => String)
export class EmailScalar implements CustomScalar<string, string> {
  description = 'Email custom scalar type';

  serialize(value: string): string {
    if (!this.isValidEmail(value)) {
      throw new GraphQLError('Value must be a valid email address');
    }
    return value;
  }

  parseValue(value: string): string {
    if (!this.isValidEmail(value)) {
      throw new GraphQLError('Value must be a valid email address');
    }
    return value;
  }

  parseLiteral(ast: ValueNode): string {
    if (ast.kind !== Kind.STRING) {
      throw new GraphQLError('Email must be a string');
    }
    
    if (!this.isValidEmail(ast.value)) {
      throw new GraphQLError('Value must be a valid email address');
    }
    
    return ast.value;
  }

  private isValidEmail(email: string): boolean {
    const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
    return emailRegex.test(email);
  }
}

// URL scalar
@Scalar('URL', () => String)
export class URLScalar implements CustomScalar<string, string> {
  description = 'URL custom scalar type';

  serialize(value: string): string {
    return this.validateURL(value);
  }

  parseValue(value: string): string {
    return this.validateURL(value);
  }

  parseLiteral(ast: ValueNode): string {
    if (ast.kind !== Kind.STRING) {
      throw new GraphQLError('URL must be a string');
    }
    return this.validateURL(ast.value);
  }

  private validateURL(url: string): string {
    try {
      new URL(url);
      return url;
    } catch {
      throw new GraphQLError('Value must be a valid URL');
    }
  }
}

// Usage in types
@ObjectType()
class User {
  @Field()
  id: string;
  
  @Field(() => EmailScalar)
  email: string;
  
  @Field(() => URLScalar, { nullable: true })
  website?: string;
}

Type Helper Interfaces

Utility interfaces and types for advanced type manipulation.

/**
 * Helper type for field definitions
 */
type FieldType = string | number | boolean | Date | any[];

/**
 * Type reference for GraphQL schema elements
 */
type GqlTypeReference = Function | object | symbol | [Function | object | symbol];

/**
 * Class type reference with constructor
 */
type Type<T = any> = new (...args: any[]) => T;

/**
 * Function type for defining return types in decorators
 */
type ReturnTypeFunc = (returns?: void) => Function | object | symbol;

/**
 * Type for class decorators that can be applied to GraphQL types
 */
type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;

/**
 * Options for scalar type mappings in schema building
 */
interface ScalarsTypeMap {
  /** TypeScript/JavaScript type constructor */
  type: Function;
  /** Corresponding GraphQL scalar type */
  scalar: GraphQLScalarType;
}

/**
 * Configuration for complexity analysis
 */
interface Complexity {
  /** Maximum query complexity allowed */
  maximumComplexity: number;
  /** Custom complexity function */
  createComplexityLimitRule?: (maximumComplexity: number) => any;
}

docs

federation.md

index.md

module-configuration.md

resolvers.md

schema-building.md

schema-decorators.md

services.md

subscriptions.md

type-system.md

tile.json