CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/npm-graphql-scalars

A collection of scalar types not included in base GraphQL.

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

utilities.mddocs/

Utility Classes

Custom scalar creation utilities for advanced use cases. These utilities allow developers to create custom GraphQL scalar types with regex-based validation for domain-specific requirements.

Capabilities

RegularExpression Class

Base class for creating custom GraphQL scalar types with regular expression validation.

/**
 * Base class for creating custom GraphQL scalar types with regex validation
 * Extends GraphQLScalarType with regex-based validation logic
 */
class RegularExpression extends GraphQLScalarType {
  constructor(name: string, regex: RegExp, options?: RegularExpressionOptions);
}

Parameters:

  • name: The name of the custom scalar type
  • regex: Regular expression pattern for validation
  • options: Optional configuration object

RegularExpressionOptions Interface

Configuration interface for customizing RegularExpression behavior.

interface RegularExpressionOptions {
  /** Custom error message function */
  errorMessage?: RegularExpressionErrorMessageFn;
  /** Description for the scalar type */
  description?: string;
  /** Whether to only accept string values */
  stringOnly?: boolean;
}

RegularExpressionErrorMessageFn Type

Function type for generating custom error messages.

/**
 * Function type for generating custom validation error messages
 * @param r - The regular expression that failed validation
 * @param v - The value that failed validation
 * @returns Custom error message string
 */
type RegularExpressionErrorMessageFn = (r: RegExp, v: any) => string;

Usage Examples

Creating Custom Scalars

import { RegularExpression } from "graphql-scalars";

// Create a custom scalar for product codes
const GraphQLProductCode = new RegularExpression(
  "ProductCode",
  /^[A-Z]{2}-[0-9]{4}-[A-Z]{2}$/,
  {
    description: "Product code in format XX-0000-XX",
    errorMessage: (regex, value) => 
      `Product code must match format XX-0000-XX, got: ${value}`,
    stringOnly: true
  }
);

// Create a custom scalar for license plates
const GraphQLLicensePlate = new RegularExpression(
  "LicensePlate",
  /^[A-Z0-9]{1,8}$/,
  {
    description: "Vehicle license plate (1-8 alphanumeric characters)",
    stringOnly: true
  }
);

// Create a custom scalar for hex colors (alternative to built-in)
const GraphQLCustomHexColor = new RegularExpression(
  "CustomHexColor",
  /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/,
  {
    description: "Hexadecimal color code (#RGB or #RRGGBB)",
    errorMessage: (regex, value) => 
      `Invalid hex color format: ${value}. Expected #RGB or #RRGGBB`,
    stringOnly: true
  }
);

Using Custom Scalars in Schemas

import { GraphQLObjectType, GraphQLString, GraphQLSchema } from "graphql";

// Define schema using custom scalars
const ProductType = new GraphQLObjectType({
  name: "Product",
  fields: {
    id: { type: GraphQLProductCode },
    name: { type: GraphQLString },
    color: { type: GraphQLCustomHexColor },
  },
});

const VehicleType = new GraphQLObjectType({
  name: "Vehicle",
  fields: {
    licensePlate: { type: GraphQLLicensePlate },
    make: { type: GraphQLString },
    model: { type: GraphQLString },
  },
});

// Schema with type definitions
const typeDefs = `
  scalar ProductCode
  scalar LicensePlate  
  scalar CustomHexColor
  
  type Product {
    id: ProductCode!
    name: String!
    color: CustomHexColor
  }
  
  type Vehicle {
    licensePlate: LicensePlate!
    make: String!
    model: String!
  }
`;

// Resolvers map
const resolvers = {
  ProductCode: GraphQLProductCode,
  LicensePlate: GraphQLLicensePlate,
  CustomHexColor: GraphQLCustomHexColor,
};

Advanced Custom Scalars

// Social Security Number (US format)
const GraphQLSSN = new RegularExpression(
  "SSN",
  /^\d{3}-\d{2}-\d{4}$/,
  {
    description: "US Social Security Number (XXX-XX-XXXX)",
    errorMessage: (regex, value) => 
      `SSN must be in format XXX-XX-XXXX, got: ${value}`,
    stringOnly: true
  }
);

// Credit Card Number (basic format validation)
const GraphQLCreditCard = new RegularExpression(
  "CreditCard",
  /^\d{4}[\s-]?\d{4}[\s-]?\d{4}[\s-]?\d{4}$/,
  {
    description: "Credit card number (16 digits with optional spaces or dashes)",
    errorMessage: (regex, value) => 
      `Invalid credit card format: ${value}`,
    stringOnly: true
  }
);

// Stock Symbol
const GraphQLStockSymbol = new RegularExpression(
  "StockSymbol",
  /^[A-Z]{1,5}$/,
  {
    description: "Stock trading symbol (1-5 uppercase letters)",
    errorMessage: (regex, value) => 
      `Stock symbol must be 1-5 uppercase letters, got: ${value}`,
    stringOnly: true
  }
);

// Semantic Version (custom implementation)
const GraphQLCustomSemVer = new RegularExpression(
  "CustomSemVer",
  /^(\d+)\.(\d+)\.(\d+)(?:-([a-zA-Z0-9\-\.]+))?(?:\+([a-zA-Z0-9\-\.]+))?$/,
  {
    description: "Semantic version (MAJOR.MINOR.PATCH)",
    errorMessage: (regex, value) => 
      `Invalid semantic version format: ${value}. Expected MAJOR.MINOR.PATCH`,
    stringOnly: true
  }
);

Configuration Options

stringOnly Option

When stringOnly: true, the scalar will only accept string literals in GraphQL queries:

// With stringOnly: true
const GraphQLStrictCode = new RegularExpression(
  "StrictCode",
  /^[A-Z]{3}$/,
  { stringOnly: true }
);

// Valid GraphQL usage:
// mutation { createItem(code: "ABC") }

// Invalid GraphQL usage (will throw error):  
// mutation { createItem(code: 123) }

Custom Error Messages

Provide meaningful error messages for better developer experience:

const GraphQLCustomFormat = new RegularExpression(
  "CustomFormat",
  /^[A-Z]{2}-\d{4}$/,
  {
    errorMessage: (regex, value) => {
      if (typeof value !== 'string') {
        return `Expected string value, got ${typeof value}: ${value}`;
      }
      if (value.length !== 7) {
        return `Expected 7 characters (XX-0000), got ${value.length}: ${value}`;
      }
      return `Invalid format. Expected XX-0000 pattern, got: ${value}`;
    }
  }
);

GraphQL Operations

# Query using custom scalars
query GetProduct($productId: ProductCode!) {
  product(id: $productId) {
    id
    name
    color
  }
}

# Mutation with validation
mutation CreateVehicle($input: VehicleInput!) {
  createVehicle(input: $input) {
    licensePlate
    make
    model
  }
}

Variables:

{
  "productId": "AB-1234-CD",
  "input": {
    "licensePlate": "ABC123",
    "make": "Toyota",
    "model": "Camry"
  }
}

Validation Examples

// Valid values for custom scalars
const validData = {
  productCode: "AB-1234-CD",     // Matches XX-0000-XX pattern
  licensePlate: "ABC123",        // 1-8 alphanumeric characters
  hexColor: "#FF5733",           // Valid hex color
  ssn: "123-45-6789",           // Valid SSN format
  stockSymbol: "AAPL"           // 1-5 uppercase letters
};

// Invalid values (will fail validation)
const invalidData = {
  productCode: "AB-12345-CD",    // Too many digits
  licensePlate: "ABC@123",       // Special character not allowed
  hexColor: "#GG5733",           // Invalid hex characters
  ssn: "123456789",             // Missing dashes
  stockSymbol: "apple"          // Lowercase not allowed
};

Best Practices

Regex Design

  • Be Specific: Make patterns as specific as possible to prevent false positives
  • Consider Edge Cases: Test with boundary conditions and invalid inputs
  • Performance: Avoid overly complex regex patterns that could impact performance
  • Documentation: Provide clear descriptions and examples

Error Messages

  • Be Descriptive: Explain what format is expected
  • Show Examples: Include example valid values in error messages
  • User-Friendly: Write messages that non-technical users can understand

Naming Conventions

  • Descriptive Names: Use clear, descriptive names for custom scalar types
  • Consistent Prefixes: Consider using consistent prefixes for related scalars
  • Avoid Conflicts: Ensure names don't conflict with built-in GraphQL types

Common Use Cases

RegularExpression is ideal for:

  • Custom Identifiers: Company-specific ID formats, reference numbers
  • Format Validation: Specialized data formats not covered by built-in scalars
  • Domain-Specific Data: Industry-specific codes and identifiers
  • Legacy System Integration: Validating data from existing systems
  • Compliance Requirements: Meeting specific formatting standards

Limitations

  • Regex Complexity: Very complex patterns may impact performance
  • International Support: Regex may not handle all international character sets
  • Semantic Validation: Only validates format, not semantic correctness
  • Error Context: Limited error context compared to custom validation functions

Consider using specific built-in scalars when available, as they often provide better validation and error messages than custom regex-based solutions.

docs

colors.md

data-formats.md

date-time.md

financial.md

geographic.md

identifiers.md

index.md

network.md

numeric.md

specialized.md

string-text.md

utilities.md

tile.json