or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

graphql-resolvers.mdimage-cdn-polyfill.mdindex.mdjoi-schemas.mdruntime-compatibility.mdschema-validation.md
tile.json

schema-validation.mddocs/

Schema Validation

Comprehensive plugin options validation system using Joi schemas with async support, detailed error reporting, and Gatsby-specific extensions.

Capabilities

validateOptionsSchema

Validates plugin options against a Joi schema with comprehensive error handling and warning support.

/**
 * Validates plugin options against a Joi schema
 * @param pluginSchema - Joi object schema for validation
 * @param pluginOptions - Plugin options to validate
 * @param options - Validation configuration options
 * @returns Promise with validated value and warnings
 */
function validateOptionsSchema(
  pluginSchema: ObjectSchema,
  pluginOptions: IPluginInfoOptions,
  options: {
    validateExternalRules?: boolean;
    returnWarnings?: boolean;
  } = {
    validateExternalRules: true,
    returnWarnings: true
  }
): Promise<{
  value: IPluginInfoOptions;
  warning: {
    message: string;
    details: Array<{
      message: string;
      path: Array<string>;
      type: string;
      context: Array<Record<string, unknown>>;
    }>;
  };
}>;

Usage Examples:

import { validateOptionsSchema, Joi } from "gatsby-plugin-utils";

// Define schema
const pluginSchema = Joi.object({
  apiKey: Joi.string().required().description("API key for service"),
  timeout: Joi.number().min(1000).default(5000).description("Request timeout in ms"),
  retries: Joi.number().min(0).max(5).default(3).description("Number of retry attempts"),
  enableCache: Joi.boolean().default(true).description("Enable response caching"),
  endpoints: Joi.object({
    graphql: Joi.string().uri().required(),
    rest: Joi.string().uri().optional()
  }).required()
});

// Validate options
async function validateMyPluginOptions(pluginOptions) {
  try {
    const result = await validateOptionsSchema(pluginSchema, pluginOptions, {
      validateExternalRules: true,
      returnWarnings: true
    });
    
    console.log("Validated options:", result.value);
    if (result.warning?.details?.length > 0) {
      console.warn("Validation warnings:", result.warning.details);
    }
    
    return result.value;
  } catch (error) {
    console.error("Validation failed:", error.details);
    throw error;
  }
}

// Example plugin options
const pluginOptions = {
  apiKey: "sk-1234567890",
  timeout: 3000,
  endpoints: {
    graphql: "https://api.example.com/graphql"
  }
};

const validatedOptions = await validateMyPluginOptions(pluginOptions);

testPluginOptionsSchema

Utility for testing plugin options schemas in test environments with comprehensive result reporting.

/**
 * Tests plugin options schema for validation behavior
 * @param pluginSchemaFunction - Function that returns Joi schema
 * @param pluginOptions - Options to test against schema
 * @returns Promise with detailed test results
 */
function testPluginOptionsSchema(
  pluginSchemaFunction: (args: { Joi: PluginOptionsSchemaJoi }) => ObjectSchema,
  pluginOptions: IPluginInfoOptions
): Promise<{
  errors: Array<string>;
  warnings: Array<string>;
  isValid: boolean;
  hasWarnings: boolean;
}>;

Usage Examples:

import { testPluginOptionsSchema } from "gatsby-plugin-utils";

// Test schema function
const pluginSchema = ({ Joi }) =>
  Joi.object({
    name: Joi.string().required(),
    version: Joi.string().pattern(/^\d+\.\d+\.\d+$/),
    features: Joi.array().items(Joi.string()).default([])
  });

// Test cases
describe("Plugin Options Schema", () => {
  it("should validate correct options", async () => {
    const { isValid, errors, warnings } = await testPluginOptionsSchema(
      pluginSchema,
      {
        name: "my-plugin",
        version: "1.0.0",
        features: ["feature-a", "feature-b"]
      }
    );
    
    expect(isValid).toBe(true);
    expect(errors).toHaveLength(0);
  });

  it("should fail with missing required field", async () => {
    const { isValid, errors } = await testPluginOptionsSchema(
      pluginSchema,
      {
        version: "1.0.0"
      }
    );
    
    expect(isValid).toBe(false);
    expect(errors).toContain('"name" is required');
  });

  it("should warn about unknown fields", async () => {
    const { isValid, hasWarnings, warnings } = await testPluginOptionsSchema(
      pluginSchema,
      {
        name: "my-plugin",
        version: "1.0.0",
        unknownField: "value"
      }
    );
    
    expect(isValid).toBe(true);
    expect(hasWarnings).toBe(true);
    expect(warnings).toContain('"unknownField" is not allowed');
  });
});

Validation Options

interface ValidationOptions {
  /**
   * Whether to validate external rules (default: true)
   */
  validateExternalRules?: boolean;
  
  /**
   * Whether to return warnings alongside validation results (default: true)
   */
  returnWarnings?: boolean;
}

Error Handling

The validation system provides detailed error information for debugging:

try {
  await validateOptionsSchema(schema, options);
} catch (validationError) {
  // validationError.details contains array of specific validation failures
  validationError.details.forEach(detail => {
    console.log(`Field: ${detail.path.join('.')}`);
    console.log(`Error: ${detail.message}`);
    console.log(`Type: ${detail.type}`);
  });
}

Gatsby-Specific Extensions

The validation system includes Gatsby-specific Joi extensions:

SubPlugins Validation

// Extended Joi with subPlugins validation
const Joi = require("gatsby-plugin-utils").Joi;

const schemaWithSubPlugins = Joi.object({
  plugins: Joi.subPlugins().description("Array of sub-plugins")
});

// Validates arrays of plugin references:
// ["plugin-name"] or [{ resolve: "plugin-name", options: {...} }]

Integration with gatsby-node.js

// gatsby-node.js
const { validateOptionsSchema } = require("gatsby-plugin-utils");

exports.pluginOptionsSchema = ({ Joi }) => {
  return Joi.object({
    apiToken: Joi.string().required().description("API authentication token"),
    apiUrl: Joi.string().uri().default("https://api.example.com"),
    cacheTimeout: Joi.number().min(0).default(300000)
  });
};

exports.onPreInit = async ({ reporter }, pluginOptions) => {
  try {
    const schema = exports.pluginOptionsSchema({ Joi: require("gatsby-plugin-utils").Joi });
    await validateOptionsSchema(schema, pluginOptions);
    reporter.info("Plugin options validated successfully");
  } catch (error) {
    reporter.panic("Invalid plugin options", error);
  }
};