or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

colors.mddata-formats.mddate-time.mdfinancial.mdgeographic.mdidentifiers.mdindex.mdnetwork.mdnumeric.mdspecialized.mdstring-text.mdutilities.md
tile.json

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.