Files
metabuilder/packages/shared/seed/SCRIPT_JSON_DOCSTRINGS.md
2025-12-31 13:39:47 +00:00

16 KiB

JSON Script Docstring Specification

Overview

JSON scripts support JSDoc-style docstrings embedded directly in JSON format. Docstrings provide:

  • Function documentation - What the function does, parameters, return values
  • Type information - Parameter types, return types, generic constraints
  • Usage examples - Code samples showing how to use functions
  • Metadata - Version, author, deprecation warnings, etc.

Docstring Format

Docstrings are added to functions, constants, and types using a docstring property:

{
  "name": "calculateArea",
  "docstring": {
    "summary": "Calculates the area of a rectangle",
    "description": "Takes width and height and returns the area. Values are clamped to prevent overflow.",
    "params": [
      {
        "name": "width",
        "type": "number",
        "description": "Width of the rectangle in pixels"
      },
      {
        "name": "height",
        "type": "number",
        "description": "Height of the rectangle in pixels"
      }
    ],
    "returns": {
      "type": "number",
      "description": "Area in square pixels, clamped between 0 and 1000"
    },
    "examples": [
      {
        "title": "Basic usage",
        "code": "const area = calculateArea(10, 20); // Returns 200"
      },
      {
        "title": "Large values are clamped",
        "code": "const area = calculateArea(100, 100); // Returns 1000 (clamped)"
      }
    ],
    "throws": [
      {
        "type": "TypeError",
        "description": "If width or height are not numbers"
      }
    ],
    "see": ["multiply", "clamp"],
    "since": "1.0.0",
    "deprecated": false
  },
  "params": [...],
  "body": [...]
}

Docstring Properties

Required Fields

summary (string)

Short one-line description of what the function does.

  • Keep to 80 characters or less
  • No period at the end
  • Use present tense ("Calculates..." not "Calculate...")
{
  "summary": "Validates user input against a set of rules"
}

Optional Fields

description (string)

Detailed multi-line description providing context, behavior, edge cases.

{
  "description": "Validates form input by checking:\n- Name is not empty\n- Age is between 0 and 120\n- Email matches RFC 5322 format\n\nReturns a ValidationResult with errors keyed by field name."
}

params (array)

Parameter documentation - one entry per parameter.

{
  "params": [
    {
      "name": "input",
      "type": "FormInput",
      "description": "Form data to validate",
      "optional": false,
      "default": null
    },
    {
      "name": "strict",
      "type": "boolean",
      "description": "Whether to use strict validation rules",
      "optional": true,
      "default": false
    }
  ]
}

Fields:

  • name (string, required) - Parameter name
  • type (string, optional) - Type annotation
  • description (string, required) - What the parameter is for
  • optional (boolean, optional) - Whether parameter is optional
  • default (any, optional) - Default value if not provided

returns (object)

Return value documentation.

{
  "returns": {
    "type": "ValidationResult",
    "description": "Object with 'valid' boolean and 'errors' object"
  }
}

Fields:

  • type (string, optional) - Return type
  • description (string, required) - What is returned

examples (array)

Usage examples showing how to call the function.

{
  "examples": [
    {
      "title": "Valid input",
      "code": "const result = validateInput({name: 'John', age: 30});\n// result.valid === true"
    },
    {
      "title": "Invalid input",
      "code": "const result = validateInput({name: '', age: -5});\n// result.errors === {name: '...', age: '...'}"
    }
  ]
}

Fields:

  • title (string, required) - Short description of the example
  • code (string, required) - Example code snippet

throws (array)

Exceptions that can be thrown.

{
  "throws": [
    {
      "type": "TypeError",
      "description": "If input is not an object"
    },
    {
      "type": "ValidationError",
      "description": "If validation fails in strict mode"
    }
  ]
}

Fields:

  • type (string, required) - Exception type
  • description (string, required) - When it's thrown

see (array of strings)

Related functions or documentation to reference.

{
  "see": ["isNotEmpty", "validateRange", "FormInput"]
}

since (string)

Version when function was added.

{
  "since": "1.2.0"
}

deprecated (boolean | object)

Whether function is deprecated and what to use instead.

{
  "deprecated": {
    "version": "2.0.0",
    "reason": "Use validateFormData instead",
    "alternative": "validateFormData"
  }
}

Or simply:

{
  "deprecated": true
}

author (string)

Function author.

{
  "author": "John Doe <john@example.com>"
}

version (string)

Current version of the function.

{
  "version": "1.3.0"
}

tags (array of strings)

Categorization tags.

{
  "tags": ["validation", "forms", "user-input"]
}

internal (boolean)

Whether function is internal-only (not part of public API).

{
  "internal": true
}

Complete Example

{
  "id": "validate_input_fn",
  "name": "validateInput",
  "exported": true,
  "docstring": {
    "summary": "Validates form input against a set of rules",
    "description": "Validates user input by checking:\n- Name is not empty\n- Age is between 0 and 120\n- Email matches RFC 5322 format\n\nReturns a ValidationResult with errors keyed by field name.",
    "params": [
      {
        "name": "input",
        "type": "FormInput",
        "description": "Form data containing name, age, and email fields"
      },
      {
        "name": "strict",
        "type": "boolean",
        "description": "If true, throws on validation failure instead of returning errors",
        "optional": true,
        "default": false
      }
    ],
    "returns": {
      "type": "ValidationResult",
      "description": "Object with 'valid' boolean and 'errors' object containing field-specific error messages"
    },
    "examples": [
      {
        "title": "Valid input",
        "code": "const result = validateInput({\n  name: 'John Doe',\n  age: 30,\n  email: 'john@example.com'\n});\n// result.valid === true\n// result.errors === {}"
      },
      {
        "title": "Invalid input",
        "code": "const result = validateInput({\n  name: '',\n  age: 200,\n  email: 'not-an-email'\n});\n// result.valid === false\n// result.errors === {\n//   name: 'Name is required',\n//   age: 'Age must be between 0 and 120',\n//   email: 'Invalid email format'\n// }"
      },
      {
        "title": "Strict mode",
        "code": "try {\n  validateInput({name: ''}, true);\n} catch (e) {\n  // Throws ValidationError\n}"
      }
    ],
    "throws": [
      {
        "type": "TypeError",
        "description": "If input is not an object"
      },
      {
        "type": "ValidationError",
        "description": "If validation fails and strict mode is enabled"
      }
    ],
    "see": ["isNotEmpty", "validateRange", "isValidEmail", "FormInput", "ValidationResult"],
    "since": "1.0.0",
    "author": "MetaBuilder Team",
    "tags": ["validation", "forms", "user-input"],
    "version": "1.2.0",
    "deprecated": false
  },
  "params": [
    {
      "name": "input",
      "type": "FormInput"
    },
    {
      "name": "strict",
      "type": "boolean",
      "optional": true,
      "default": false
    }
  ],
  "returnType": "ValidationResult",
  "body": [...]
}

Constant Docstrings

Constants can also have docstrings:

{
  "constants": [
    {
      "id": "max_retries",
      "name": "MAX_RETRIES",
      "value": 3,
      "exported": true,
      "docstring": {
        "summary": "Maximum number of retry attempts for failed requests",
        "description": "After this many retries, the request will fail permanently. Set to 0 to disable retries.",
        "since": "1.0.0",
        "see": ["retryRequest", "RETRY_DELAY"]
      }
    }
  ]
}

Type Docstrings

Types in types.json can have docstrings:

{
  "types": [
    {
      "id": "validation_result",
      "name": "ValidationResult",
      "type": "object",
      "exported": true,
      "docstring": {
        "summary": "Result of input validation operation",
        "description": "Contains validation status and error messages for each invalid field.",
        "examples": [
          {
            "title": "Valid result",
            "code": "{ valid: true, errors: {} }"
          },
          {
            "title": "Invalid result",
            "code": "{ valid: false, errors: { name: 'Name is required' } }"
          }
        ],
        "see": ["validateInput", "ValidationErrors"],
        "since": "1.0.0"
      },
      "properties": {
        "valid": {
          "type": "boolean",
          "required": true,
          "description": "Whether input passed validation"
        },
        "errors": {
          "type": "ValidationErrors",
          "description": "Error messages keyed by field name"
        }
      }
    }
  ]
}

Generating Documentation

Docstrings can be extracted to generate:

1. Markdown Documentation

# validateInput

Validates form input against a set of rules

## Description

Validates user input by checking:
- Name is not empty
- Age is between 0 and 120
- Email matches RFC 5322 format

Returns a ValidationResult with errors keyed by field name.

## Parameters

- **input** (`FormInput`) - Form data containing name, age, and email fields
- **strict** (`boolean`, optional, default: `false`) - If true, throws on validation failure instead of returning errors

## Returns

`ValidationResult` - Object with 'valid' boolean and 'errors' object containing field-specific error messages

## Examples

### Valid input
\`\`\`javascript
const result = validateInput({
  name: 'John Doe',
  age: 30,
  email: 'john@example.com'
});
// result.valid === true
// result.errors === {}
\`\`\`

### Invalid input
\`\`\`javascript
const result = validateInput({
  name: '',
  age: 200,
  email: 'not-an-email'
});
// result.valid === false
\`\`\`

## Throws

- `TypeError` - If input is not an object
- `ValidationError` - If validation fails and strict mode is enabled

## See Also

- isNotEmpty
- validateRange
- isValidEmail
- FormInput
- ValidationResult

## Version

1.2.0 (since 1.0.0)

2. TypeScript Definitions

/**
 * Validates form input against a set of rules
 *
 * Validates user input by checking:
 * - Name is not empty
 * - Age is between 0 and 120
 * - Email matches RFC 5322 format
 *
 * @param input - Form data containing name, age, and email fields
 * @param strict - If true, throws on validation failure instead of returning errors
 * @returns Object with 'valid' boolean and 'errors' object containing field-specific error messages
 * @throws {TypeError} If input is not an object
 * @throws {ValidationError} If validation fails and strict mode is enabled
 * @since 1.0.0
 * @version 1.2.0
 * @see isNotEmpty
 * @see validateRange
 */
export function validateInput(
  input: FormInput,
  strict?: boolean
): ValidationResult;

3. Storybook Integration

Docstrings can automatically generate Storybook documentation:

export const ValidateInputStory: Story = {
  name: 'validateInput',
  parameters: {
    docs: {
      description: {
        story: 'Validates form input against a set of rules\n\n' +
               'Validates user input by checking:\n' +
               '- Name is not empty\n' +
               '- Age is between 0 and 120'
      }
    }
  },
  argTypes: {
    input: {
      description: 'Form data containing name, age, and email fields',
      type: { name: 'object', required: true }
    },
    strict: {
      description: 'If true, throws on validation failure',
      type: { name: 'boolean', required: false },
      defaultValue: false
    }
  }
}

Runtime Integration

JavaScript/TypeScript

The script executor can expose docstrings via a metadata API:

import { getDocstring } from './script_executor.js'

const doc = getDocstring(scriptJson, 'validateInput')
console.log(doc.summary)
console.log(doc.params)
console.log(doc.examples)

Lua

local executor = require('script_executor')
local doc = executor.get_docstring(script, 'validateInput')
print(doc.summary)

Best Practices

DO

  • Write clear summaries - One line, present tense, under 80 chars
  • Document all parameters - Even if types are obvious
  • Provide examples - Show common use cases and edge cases
  • Link related functions - Use see to cross-reference
  • Keep descriptions current - Update docs when code changes
  • Use proper formatting - Newlines, bullets, code blocks

DON'T

  • Repeat type information - Types are already in params/returnType
  • Write obvious docs - "Gets the name" for getName() is useless
  • Use jargon - Explain acronyms and domain terms
  • Forget examples - Code samples are worth 1000 words
  • Leave deprecated functions - Mark with deprecated or remove

Schema Validation

Docstrings should validate against JSON Schema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "properties": {
    "summary": { "type": "string", "maxLength": 200 },
    "description": { "type": "string" },
    "params": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["name", "description"],
        "properties": {
          "name": { "type": "string" },
          "type": { "type": "string" },
          "description": { "type": "string" },
          "optional": { "type": "boolean" },
          "default": {}
        }
      }
    },
    "returns": {
      "type": "object",
      "required": ["description"],
      "properties": {
        "type": { "type": "string" },
        "description": { "type": "string" }
      }
    },
    "examples": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["title", "code"],
        "properties": {
          "title": { "type": "string" },
          "code": { "type": "string" }
        }
      }
    },
    "throws": {
      "type": "array",
      "items": {
        "type": "object",
        "required": ["type", "description"],
        "properties": {
          "type": { "type": "string" },
          "description": { "type": "string" }
        }
      }
    },
    "see": { "type": "array", "items": { "type": "string" } },
    "since": { "type": "string" },
    "deprecated": { "oneOf": [
      { "type": "boolean" },
      {
        "type": "object",
        "properties": {
          "version": { "type": "string" },
          "reason": { "type": "string" },
          "alternative": { "type": "string" }
        }
      }
    ]},
    "author": { "type": "string" },
    "version": { "type": "string" },
    "tags": { "type": "array", "items": { "type": "string" } },
    "internal": { "type": "boolean" }
  },
  "required": ["summary"]
}

See Also