mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-25 22:34:56 +00:00
649 lines
16 KiB
Markdown
649 lines
16 KiB
Markdown
# 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:
|
|
|
|
```json
|
|
{
|
|
"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...")
|
|
|
|
```json
|
|
{
|
|
"summary": "Validates user input against a set of rules"
|
|
}
|
|
```
|
|
|
|
### Optional Fields
|
|
|
|
#### `description` (string)
|
|
**Detailed multi-line description** providing context, behavior, edge cases.
|
|
|
|
```json
|
|
{
|
|
"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.
|
|
|
|
```json
|
|
{
|
|
"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**.
|
|
|
|
```json
|
|
{
|
|
"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.
|
|
|
|
```json
|
|
{
|
|
"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**.
|
|
|
|
```json
|
|
{
|
|
"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.
|
|
|
|
```json
|
|
{
|
|
"see": ["isNotEmpty", "validateRange", "FormInput"]
|
|
}
|
|
```
|
|
|
|
#### `since` (string)
|
|
**Version when function was added**.
|
|
|
|
```json
|
|
{
|
|
"since": "1.2.0"
|
|
}
|
|
```
|
|
|
|
#### `deprecated` (boolean | object)
|
|
**Whether function is deprecated** and what to use instead.
|
|
|
|
```json
|
|
{
|
|
"deprecated": {
|
|
"version": "2.0.0",
|
|
"reason": "Use validateFormData instead",
|
|
"alternative": "validateFormData"
|
|
}
|
|
}
|
|
```
|
|
|
|
Or simply:
|
|
```json
|
|
{
|
|
"deprecated": true
|
|
}
|
|
```
|
|
|
|
#### `author` (string)
|
|
**Function author**.
|
|
|
|
```json
|
|
{
|
|
"author": "John Doe <john@example.com>"
|
|
}
|
|
```
|
|
|
|
#### `version` (string)
|
|
**Current version** of the function.
|
|
|
|
```json
|
|
{
|
|
"version": "1.3.0"
|
|
}
|
|
```
|
|
|
|
#### `tags` (array of strings)
|
|
**Categorization tags**.
|
|
|
|
```json
|
|
{
|
|
"tags": ["validation", "forms", "user-input"]
|
|
}
|
|
```
|
|
|
|
#### `internal` (boolean)
|
|
**Whether function is internal-only** (not part of public API).
|
|
|
|
```json
|
|
{
|
|
"internal": true
|
|
}
|
|
```
|
|
|
|
## Complete Example
|
|
|
|
```json
|
|
{
|
|
"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:
|
|
|
|
```json
|
|
{
|
|
"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:
|
|
|
|
```json
|
|
{
|
|
"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
|
|
|
|
```markdown
|
|
# 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
|
|
|
|
```typescript
|
|
/**
|
|
* 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:
|
|
|
|
```typescript
|
|
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:
|
|
|
|
```javascript
|
|
import { getDocstring } from './script_executor.js'
|
|
|
|
const doc = getDocstring(scriptJson, 'validateInput')
|
|
console.log(doc.summary)
|
|
console.log(doc.params)
|
|
console.log(doc.examples)
|
|
```
|
|
|
|
### Lua
|
|
|
|
```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:
|
|
|
|
```json
|
|
{
|
|
"$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
|
|
|
|
- [JSON Script Specification](SCRIPT_JSON_SPEC_ISSUES.md)
|
|
- [Type Definitions Guide](../../json_script_example/TYPES.md)
|
|
- [Testing Guide](../../json_script_example/tests/README.md)
|