mirror of
https://github.com/johndoe6345789/metabuilder.git
synced 2026-04-24 13:54:57 +00:00
docs: shared,script,packages (1 files)
This commit is contained in:
648
packages/shared/seed/SCRIPT_JSON_DOCSTRINGS.md
Normal file
648
packages/shared/seed/SCRIPT_JSON_DOCSTRINGS.md
Normal file
@@ -0,0 +1,648 @@
|
||||
# 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)
|
||||
Reference in New Issue
Block a user