DOCS/Configuration

Configuration

functional-examples is configured via a config file at your project root. This guide covers every config option, the two config formats, and how to use metadata schemas for validation.

Config Formats

TypeScript (recommended)

Create functional-examples.config.ts:

import { createJavaScriptPlugin } from '@functional-examples/javascript';

export default {
  plugins: [createJavaScriptPlugin()],
  scan: {
    root: 'examples',
    exclude: ['**/node_modules/**', '**/dist/**'],
  },
};

TypeScript configs can instantiate plugins directly and benefit from type checking and IDE autocompletion.

JSON

Create functional-examples.config.json:

{
  "$schema": "./.functional-examples/schema.json",
  "scan": {
    "include": ["snippets/**/*"],
    "exclude": ["**/*.test.*", "**/*.spec.*"]
  },
  "pathMappings": [
    {
      "pattern": "**/legacy/**",
      "extractor": "meta-yml"
    }
  ],
  "metadata": {
    "type": "object",
    "properties": {
      "id": {
        "type": "string",
        "description": "Unique identifier for the example"
      },
      "title": {
        "type": "string",
        "description": "Human-readable title"
      },
      "description": {
        "type": "string",
        "description": "What this example demonstrates"
      },
      "category": {
        "type": "string",
        "enum": ["tutorial", "recipe", "reference", "advanced"],
        "description": "Example category for filtering"
      },
      "tags": {
        "type": "array",
        "items": { "type": "string" },
        "description": "Tags for search and filtering"
      }
    },
    "required": ["id", "title", "category"]
  }
}

JSON configs are useful when you don't want a build step, work with non-JS tooling, or want machine-editable configuration. Plugins are auto-detected from your package.json dependencies.

Scan Options

scan.root

Base directory for scanning, relative to the config file. Defaults to the current directory.

scan: {
  root: 'examples', // only scan under examples/
}

scan.include

Glob patterns for files to include. If omitted, all files under the root are candidates.

scan: {
  include: ['snippets/**/*', 'tutorials/**/*'],
}

scan.exclude

Glob patterns for files to exclude. Always exclude node_modules and build artifacts:

scan: {
  exclude: ['**/node_modules/**', '**/dist/**', '**/*.test.*'],
}

Path Mappings

When using multiple plugins, pathMappings route specific file patterns to specific extractors. This prevents conflicts when two extractors might both try to claim the same file.

pathMappings: [
  { pattern: 'src/**', extractor: 'javascript-extractor' },
  { pattern: 'tutorials/**', extractor: 'meta-yml' },
]

Each mapping has:

  • pattern — a glob pattern matched against relative file paths
  • extractor — the extractorName of the target extractor

Files matching a mapping are only sent to the specified extractor. Unmapped files are sent to all extractors.

Metadata Schema

You can enforce metadata standards using a JSON Schema in your config. Every scanned example's metadata is validated against it:

{
  "$schema": "./.functional-examples/schema.json",
  "scan": {
    "include": ["src/**/*"],
    "exclude": ["**/node_modules/**", "**/dist/**"]
  },
  "metadata": {
    "type": "object",
    "properties": {
      "category": {
        "type": "string",
        "description": "Category for organizing examples"
      },
      "difficulty": {
        "type": "string",
        "enum": ["beginner", "intermediate", "advanced"],
        "description": "Difficulty level"
      }
    },
    "required": ["category", "difficulty"]
  }
}

When an example's metadata doesn't match the schema, the scanner reports a validation error. Here's an example that passes validation:

// ---
// id: valid-example
// title: Valid Example
// description: This example has all required metadata fields
// category: tutorials
// difficulty: beginner
// ---

/**
 * This example passes validation because it includes
 * both `category` and `difficulty` fields.
 */
export function example() {
  console.log('This example has valid metadata!');
}

And one that fails because it's missing required fields:

// ---
// id: missing-fields
// title: Missing Required Fields
// description: This example is missing category and difficulty
// ---

/**
 * This example will produce validation errors because
 * it's missing the required `category` and `difficulty` fields.
 *
 * Run `npx functional-examples scan` to see the validation errors.
 */
export function example() {
  console.log('This example is missing required metadata!');
}

Region Config

functional-examples can extract #region / #endregion hunks from source files without any plugin. The region config block controls the marker keywords and which file extensions are recognised.

export default {
  region: {
    startTag: 'region',    // default
    endTag: 'endregion',   // default
    fileExtensionMap: {
      // override or extend the built-in map
      '.vue': [/\/\/\s*{token}\s+(\w+)/],
    },
  },
};

fileExtensionMap values can be RegExp literals (recommended in TypeScript configs) or pattern strings — the {token} placeholder is replaced with the configured startTag or endTag at scan time, and the first capturing group captures the region ID.

User-supplied entries are merged over the defaults; the defaults cover these extensions out of the box:

Config Resolution

When you call scan() or the CLI, functional-examples:

  1. Walks up from the current directory looking for functional-examples.config.ts or .json
  2. Loads the config (compiling TypeScript if needed)
  3. Resolves plugin references (for JSON configs, auto-detects from dependencies)
  4. Merges scan defaults with your overrides
  5. Returns a fully resolved config ready for scanning

You can also pass a config object directly to scanExamples() for programmatic use.