diff --git a/.github/workflows/jsdoc-automation.yml b/.github/workflows/jsdoc-automation.yml index d487b08fe4..b5983fba96 100644 --- a/.github/workflows/jsdoc-automation.yml +++ b/.github/workflows/jsdoc-automation.yml @@ -10,7 +10,7 @@ on: root_directory: description: 'Only scans files in this directory (relative to repository root, e.g., packages/core/src)' required: true - default: 'packages/core/src/test_resources' + default: 'packages/plugin-near/' type: string excluded_directories: description: 'Directories to exclude from scanning (comma-separated, relative to root_directory)' diff --git a/packages/plugin-near/src/actions/swap.ts b/packages/plugin-near/src/actions/swap.ts index f11f6b134f..289d9478af 100644 --- a/packages/plugin-near/src/actions/swap.ts +++ b/packages/plugin-near/src/actions/swap.ts @@ -39,6 +39,7 @@ async function checkStorageBalance( } } +// TODO: add functionality to support multiple networks async function swapToken( runtime: IAgentRuntime, inputTokenId: string, diff --git a/scripts/jsdoc-automation/src/AIService.ts b/scripts/jsdoc-automation/src/AIService.ts index 2f7d7b8225..95a77aede6 100644 --- a/scripts/jsdoc-automation/src/AIService.ts +++ b/scripts/jsdoc-automation/src/AIService.ts @@ -1,5 +1,6 @@ import { ChatOpenAI } from "@langchain/openai"; import dotenv from 'dotenv'; +import { ASTQueueItem, EnvUsage, OrganizedDocs, PluginDocumentation, TodoItem, TodoSection } from "./types/index.js"; dotenv.config(); @@ -11,7 +12,7 @@ export class AIService { /** * Constructor for initializing the ChatOpenAI instance. - * + * * @throws {Error} If OPENAI_API_KEY environment variable is not set. */ constructor() { @@ -36,9 +37,230 @@ export class AIService { } } + public async generatePluginDocumentation({ + existingDocs, + packageJson, + readmeContent, + todoItems, + envUsages + }: { + existingDocs: ASTQueueItem[]; + packageJson: any; + readmeContent?: string; + todoItems: TodoItem[]; + envUsages: EnvUsage[]; + }): Promise { + const organizedDocs = this.organizeDocumentation(existingDocs); + + const [overview, installation, configuration, usage, apiRef, troubleshooting, todoSection] = await Promise.all([ + this.generateOverview(organizedDocs, packageJson), + this.generateInstallation(packageJson), + this.generateConfiguration(envUsages), + this.generateUsage(organizedDocs, packageJson), + this.generateApiReference(organizedDocs), + this.generateTroubleshooting(organizedDocs, packageJson), + this.generateTodoSection(todoItems) + ]); + + return { + overview, + installation, + configuration, + usage, + apiReference: apiRef, + troubleshooting, + todos: todoSection.todos + }; + } + + // should be moved to utils + private organizeDocumentation(docs: ASTQueueItem[]): OrganizedDocs { + return docs.reduce((acc: OrganizedDocs, doc) => { + // Use nodeType to determine the category + switch (doc.nodeType) { + case 'ClassDeclaration': + acc.classes.push(doc); + break; + case 'MethodDefinition': + case 'TSMethodSignature': + acc.methods.push(doc); + break; + case 'TSInterfaceDeclaration': + acc.interfaces.push(doc); + break; + case 'TSTypeAliasDeclaration': + acc.types.push(doc); + break; + } + return acc; + }, { classes: [], methods: [], interfaces: [], types: [] }); + } + + private async generateOverview(docs: OrganizedDocs, packageJson: any): Promise { + const prompt = `Generate a comprehensive overview for a plugin/package based on the following information: + + Package name: ${packageJson.name} + Package description: ${packageJson.description} + Main classes: + ${docs.classes.map(c => `${c.name}: ${c.jsDoc}`).join('\n')} + Key interfaces: + ${docs.interfaces.map(i => `${i.name}: ${i.jsDoc}`).join('\n')} + + Generate a clear, concise overview that explains: + 1. The purpose of this plugin + 2. Its main features and capabilities + 3. When and why someone would use it + 4. Any key dependencies or requirements + + Format the response in markdown.`; + + return await this.generateComment(prompt); + } + + private async generateInstallation(packageJson: any): Promise { + const prompt = `Generate installation instructions for the following package: + + Package name: ${packageJson.name} + Dependencies: ${JSON.stringify(packageJson.dependencies || {}, null, 2)} + Peer dependencies: ${JSON.stringify(packageJson.peerDependencies || {}, null, 2)} + + Include: + 1. Package manager commands - we are using pnpm + 2. Any prerequisite installations + 4. Verification steps to ensure successful installation + + Format the response in markdown.`; + + return await this.generateComment(prompt); + } + + private async generateConfiguration(envUsages: EnvUsage[]): Promise { + const prompt = `Generate configuration documentation based on these environment variable usages: + ${envUsages.map(item => ` + Environment Variable: ${item.code} + Full Context: ${item.fullContext} + `).join('\n')} + Create comprehensive configuration documentation that: + 1. Lists all required environment variables + 2. Explains the purpose of each variable + 3. Provides example values where possible + + Inform the user that the configuration is done in the .env file. + And to ensure the .env is set in the .gitignore file so it is not committed to the repository. + + Format the response in markdown with proper headings and code blocks.`; + + return await this.generateComment(prompt); + } + + private async generateUsage(docs: OrganizedDocs, packageJson: any): Promise { + const prompt = `Generate usage examples based on the following API documentation: + + Classes: + ${docs.classes.map(c => `${c.className}: ${c.jsDoc}`).join('\n')} + + Methods: + ${docs.methods.map(m => `${m.methodName}: ${m.jsDoc}`).join('\n')} + + Create: + 1. Basic usage example + 2. Common use cases with Code snippets demonstrating key features + + Format the response in markdown with code examples.`; + + return await this.generateComment(prompt); + } + + private async generateApiReference(docs: OrganizedDocs): Promise { + const prompt = `Generate API reference documentation based on: + + Classes: + ${docs.classes.map(c => `${c.name}: ${c.jsDoc}`).join('\n')} + Methods: + ${docs.methods.map(m => `${m.name}: ${m.jsDoc}`).join('\n')} + Interfaces: + ${docs.interfaces.map(i => `${i.name}: ${i.jsDoc}`).join('\n')} + Types: + ${docs.types.map(t => `${t.name}: ${t.jsDoc}`).join('\n')} + + Create a comprehensive API reference including: + 1. Class descriptions and methods + 2. Method signatures and parameters + 3. Return types and values + 4. Interface definitions + 5. Type definitions + 6. Examples for complex APIs + + Format the response in markdown with proper headings and code blocks.`; + + return await this.generateComment(prompt); + } + + /** + * Generates troubleshooting guide based on documentation and common patterns + */ + private async generateTroubleshooting(docs: OrganizedDocs, packageJson: any): Promise { + const prompt = `Generate a troubleshooting guide based on: + + Package dependencies: ${JSON.stringify(packageJson.dependencies || {}, null, 2)} + Error handling in methods: + ${docs.methods + .filter(m => m.jsDoc?.toLowerCase().includes('error') || m.jsDoc?.toLowerCase().includes('throw')) + .map(m => `${m.methodName}: ${m.jsDoc}`) + .join('\n')} + + Create a troubleshooting guide including: + 1. Common issues and their solutions + 2. Error messages and their meaning + 3. Debugging tips + 4. Configuration problems + 5. Compatibility issues + 6. Performance optimization + 7. FAQ section + + Format the response in markdown with clear headings and code examples where relevant.`; + + return await this.generateComment(prompt); + } + + /** + * Generates TODO section documentation from found TODO comments + */ + private async generateTodoSection(todoItems: TodoItem[]): Promise { + if (todoItems.length === 0) { + return { + todos: "No TODOs found in the codebase.", + todoCount: 0 + }; + } + + const prompt = `Generate a TODO section for documentation based on these TODO items: + ${todoItems.map(item => ` + TODO Comment: ${item.comment} + Code Context: ${item.fullContext} + `).join('\n')} + Create a section that: + 1. Lists all TODOs in a clear, organized way + 2. Groups related TODOs if any + 3. Provides context about what needs to be done + 4. Suggests priority based on the code context + 5. Includes the file location for reference + Format the response in markdown with proper headings and code blocks.`; + + const todos = await this.generateComment(prompt); + return { + todos, + todoCount: todoItems.length + }; + } + + + + + /** * Handle API errors by logging the error message and throwing the error. - * + * * @param {Error} error The error object to handle * @returns {void} */ diff --git a/scripts/jsdoc-automation/src/DocumentationGenerator.ts b/scripts/jsdoc-automation/src/DocumentationGenerator.ts index 1503e62524..a9256ef83f 100644 --- a/scripts/jsdoc-automation/src/DocumentationGenerator.ts +++ b/scripts/jsdoc-automation/src/DocumentationGenerator.ts @@ -3,12 +3,13 @@ import { TypeScriptParser } from './TypeScriptParser.js'; import { JsDocAnalyzer } from './JsDocAnalyzer.js'; import { JsDocGenerator } from './JsDocGenerator.js'; import type { TSESTree } from '@typescript-eslint/types'; -import { ASTQueueItem, FullModeFileChange, PrModeFileChange } from './types/index.js'; +import { ASTQueueItem, EnvUsage, FullModeFileChange, PrModeFileChange, TodoItem } from './types/index.js'; import { GitManager } from './GitManager.js'; import fs from 'fs'; import { Configuration } from './Configuration.js'; import path from 'path'; import { AIService } from './AIService.js'; +import { PluginDocumentationGenerator } from './PluginDocumentationGenerator.js'; /** * Class representing a Documentation Generator. @@ -19,8 +20,9 @@ export class DocumentationGenerator { public existingJsDocQueue: ASTQueueItem[] = []; private hasChanges: boolean = false; private fileContents: Map = new Map(); - private branchName: string = ''; + public branchName: string = ''; private fileOffsets: Map = new Map(); + private typeScriptFiles: string[] = []; /** * Constructor for initializing the object with necessary dependencies. @@ -41,8 +43,10 @@ export class DocumentationGenerator { public jsDocGenerator: JsDocGenerator, public gitManager: GitManager, public configuration: Configuration, - public aiService: AIService - ) { } + public aiService: AIService, + ) { + this.typeScriptFiles = this.directoryTraversal.traverse(); + } /** * Asynchronously generates JSDoc comments for the TypeScript files based on the given pull request number or full mode. @@ -50,7 +54,7 @@ export class DocumentationGenerator { * @param pullNumber - Optional. The pull request number to generate JSDoc comments for. * @returns A promise that resolves once the JSDoc generation process is completed. */ - public async generate(pullNumber?: number): Promise { + public async generate(pullNumber?: number): Promise<{ documentedItems: ASTQueueItem[], branchName: string | undefined }> { let fileChanges: PrModeFileChange[] | FullModeFileChange[] = []; this.fileOffsets.clear(); @@ -137,6 +141,10 @@ export class DocumentationGenerator { comment = await this.jsDocGenerator.generateComment(queueItem); } await this.updateFileWithJSDoc(queueItem.filePath, comment, queueItem.startLine); + + queueItem.jsDoc = comment; + this.existingJsDocQueue.push(queueItem); + this.hasChanges = true; } @@ -162,6 +170,10 @@ export class DocumentationGenerator { }); } } + return { + documentedItems: this.existingJsDocQueue, + branchName: this.branchName + }; } /** @@ -316,4 +328,30 @@ export class DocumentationGenerator { ### 🤖 Generated by Documentation Bot This is an automated PR created by the documentation generator tool.`; } + + /** + * Analyzes TODOs and environment variables in the code + */ + public async analyzeCodebase(): Promise<{ todoItems: TodoItem[], envUsages: EnvUsage[] }> { + const todoItems: TodoItem[] = []; + const envUsages: EnvUsage[] = []; + + for (const filePath of this.typeScriptFiles) { + const ast = this.typeScriptParser.parse(filePath); + if (!ast) continue; + + const sourceCode = fs.readFileSync(filePath, 'utf-8'); + + // Find TODOs + this.jsDocAnalyzer.findTodoComments(ast, ast.comments || [], sourceCode); + todoItems.push(...this.jsDocAnalyzer.todoItems); + + // Find env usages + this.jsDocAnalyzer.findEnvUsages(ast, sourceCode); + envUsages.push(...this.jsDocAnalyzer.envUsages); + } + + return { todoItems, envUsages }; + } + } \ No newline at end of file diff --git a/scripts/jsdoc-automation/src/JsDocAnalyzer.ts b/scripts/jsdoc-automation/src/JsDocAnalyzer.ts index 223d1893b4..85d46ac2bb 100644 --- a/scripts/jsdoc-automation/src/JsDocAnalyzer.ts +++ b/scripts/jsdoc-automation/src/JsDocAnalyzer.ts @@ -1,6 +1,6 @@ import type { TSESTree } from '@typescript-eslint/types'; import { TypeScriptParser } from './TypeScriptParser.js'; -import { ASTQueueItem } from './types/index.js'; +import { ASTQueueItem, EnvUsage, TodoItem } from './types/index.js'; type AST_NODE_TYPES = { ClassDeclaration: 'ClassDeclaration'; @@ -156,6 +156,8 @@ export class JsDocAnalyzer { public missingJsDocNodes: TSESTree.Node[] = []; + public todoItems: TodoItem[] = []; + public envUsages: EnvUsage[] = []; /** * Constructor for initializing a new instance. @@ -387,4 +389,274 @@ export class JsDocAnalyzer { return methods; } + + + /** + * Finds TODO comments in the code and their associated nodes + * @param ast - The AST to analyze + * @param comments - Array of comments to search through + * @param sourceCode - The original source code + */ + public findTodoComments(ast: TSESTree.Program, comments: TSESTree.Comment[], sourceCode: string): void { + this.todoItems = []; + + comments.forEach(comment => { + if (!comment.loc) return; + + const commentText = comment.value.toLowerCase(); + if (commentText.includes('todo')) { + try { + // Find the nearest node after the comment + const nearestNode = this.findNearestNode(ast, comment.loc.end.line); + if (nearestNode && nearestNode.loc) { + // Find the containing function/class/block + const containingBlock = this.findContainingBlock(nearestNode); + + // Extract the actual code associated with the TODO + const code = this.extractNodeCode(sourceCode, nearestNode); + + // Extract the full context (entire function/class/block) + const fullContext = containingBlock && containingBlock.loc + ? this.extractNodeCode(sourceCode, containingBlock) + : code; + + this.todoItems.push({ + comment: comment.value.trim(), + code, + fullContext, + node: nearestNode, + location: comment.loc, + contextLocation: containingBlock?.loc || comment.loc + }); + } + } catch (error) { + console.error('Error processing TODO comment:', error); + // Continue processing other comments even if one fails + } + } + }); +} + +/** + * Finds the containing block (function/class/interface declaration) for a node + */ +private findContainingBlock(node: TSESTree.Node): TSESTree.Node | undefined { + let current = node; + while (current.parent) { + if ( + current.parent.type === 'FunctionDeclaration' || + current.parent.type === 'ClassDeclaration' || + current.parent.type === 'TSInterfaceDeclaration' || + current.parent.type === 'MethodDefinition' || + current.parent.type === 'ArrowFunctionExpression' || + current.parent.type === 'FunctionExpression' + ) { + return current.parent; + } + current = current.parent; + } + return undefined; +} + +/** + * Finds environment variable usage in the code + * @param ast - The AST to analyze + * @param sourceCode - The original source code + */ +public findEnvUsages(ast: TSESTree.Program, sourceCode: string): void { + this.envUsages = []; + + const findEnvReferences = (node: TSESTree.Node) => { + if (!node.loc) return; + + // Check for process.env + if ( + node.type === 'MemberExpression' && + node.object.type === 'Identifier' && + node.object.name === 'process' && + node.property.type === 'Identifier' && + node.property.name === 'env' + ) { + // Get the parent statement/expression for context + const contextNode = this.findParentStatement(node); + // Get the containing function/block for full context + const containingBlock = this.findContainingBlock(node); + + // Add logging to debug + console.log('Found process.env at line:', node.loc.start.line); + console.log('Context node type:', contextNode?.type); + console.log('Containing block type:', containingBlock?.type); + + // Get just the process.env reference + const code = this.extractNodeCode(sourceCode, node); + + // Get the full line by using the line number directly + const lines = sourceCode.split('\n'); + const context = lines[node.loc.start.line - 1]; + + // Get the entire function/block containing this env usage + const fullContext = containingBlock ? this.extractFullContext(sourceCode, containingBlock) : context; + + this.envUsages.push({ + code, + context, + fullContext, + node, + location: node.loc, + contextLocation: containingBlock?.loc || node.loc + }); + } + + // Continue traversing + Object.keys(node).forEach(key => { + const child = node[key as keyof TSESTree.Node]; + if (child && typeof child === 'object') { + if (Array.isArray(child)) { + child.forEach(item => { + if (item && typeof item === 'object') { + findEnvReferences(item as TSESTree.Node); + } + }); + } else { + findEnvReferences(child as TSESTree.Node); + } + } + }); + }; + + findEnvReferences(ast); +} + +/** + * Extracts the actual source code for a given node + */ +private extractNodeCode(sourceCode: string, node: TSESTree.Node): string { + if (!node.loc) { + return ''; + } + + const lines = sourceCode.split('\n'); + const startLine = node.loc.start.line - 1; + const endLine = node.loc.end.line; + + if (startLine < 0 || endLine > lines.length) { + return ''; + } + + // Handle single-line case + if (startLine === endLine - 1) { + const line = lines[startLine]; + return line.slice(node.loc.start.column, node.loc.end.column); + } + + // Handle multi-line case + const result = []; + for (let i = startLine; i < endLine; i++) { + let line = lines[i]; + if (i === startLine) { + line = line.slice(node.loc.start.column); + } else if (i === endLine - 1) { + line = line.slice(0, node.loc.end.column); + } + result.push(line); + } + return result.join('\n'); +} + +/** + * Extracts the full context including any variable declarations and surrounding code + */ +private extractFullContext(sourceCode: string, node: TSESTree.Node): string { + if (!node.loc) return ''; + + const lines = sourceCode.split('\n'); + const startLine = node.loc.start.line - 1; + const endLine = node.loc.end.line; + + if (startLine < 0 || endLine > lines.length) { + return ''; + } + + // Get the complete lines for the entire block/function + return lines.slice(startLine, endLine).join('\n'); +} + +/** + * Finds the parent statement or expression node + */ +// prettyr sure this isnt needed, directly access code rather +private findParentStatement(node: TSESTree.Node): TSESTree.Node | undefined { + let current = node; + while (current.parent) { + // Add more statement types that could contain process.env + if ( + current.parent.type === 'VariableDeclaration' || + current.parent.type === 'ExpressionStatement' || + current.parent.type === 'AssignmentExpression' || + current.parent.type === 'ReturnStatement' || + current.parent.type === 'IfStatement' || + current.parent.type === 'LogicalExpression' || + current.parent.type === 'BinaryExpression' || + current.parent.type === 'Property' || + current.parent.type === 'ObjectExpression' || + current.parent.type === 'MemberExpression' + ) { + return current.parent; + } + // Add logging to see what types we're encountering + console.log('Parent node type:', current.parent.type); + current = current.parent; + } + return undefined; +} + +/** + * Finds the nearest node after a specific line number + */ +private findNearestNode(ast: TSESTree.Program, lineNumber: number): TSESTree.Node | undefined { + let nearestNode: TSESTree.Node | undefined; + let smallestDistance = Infinity; + + const traverse = (node: TSESTree.Node | null) => { + if (!node) return; + + // Check if the node has a location + if (node.loc) { + const distance = node.loc.start.line - lineNumber; + if (distance > 0 && distance < smallestDistance) { + smallestDistance = distance; + nearestNode = node; + } + } + + // Safely traverse child nodes + if ('body' in node) { + const body = Array.isArray(node.body) ? node.body : [node.body]; + body.forEach((child: TSESTree.Node) => { + if (child && typeof child === 'object') { + traverse(child as TSESTree.Node); + } + }); + } + + // Handle specific node types + if ('declarations' in node && Array.isArray(node.declarations)) { + node.declarations.forEach((decl: TSESTree.Node) => traverse(decl)); + } + + if ('declaration' in node && node.declaration) { + traverse(node.declaration); + } + + // Handle other properties that might contain nodes + ['consequent', 'alternate', 'init', 'test', 'update'].forEach(prop => { + if (prop in node && node[prop as keyof typeof node]) { + traverse(node[prop as keyof typeof node] as TSESTree.Node); + } + }); + }; + + traverse(ast); + return nearestNode; +} } \ No newline at end of file diff --git a/scripts/jsdoc-automation/src/PluginDocumentationGenerator.ts b/scripts/jsdoc-automation/src/PluginDocumentationGenerator.ts new file mode 100644 index 0000000000..279be8decb --- /dev/null +++ b/scripts/jsdoc-automation/src/PluginDocumentationGenerator.ts @@ -0,0 +1,83 @@ +import { ASTQueueItem, PluginDocumentation, TodoItem, EnvUsage } from './types/index.js'; +import { AIService } from './AIService.js'; +import { GitManager } from './GitManager.js'; +import { Configuration } from './Configuration.js'; +import fs from 'fs'; +import path from 'path'; + +/** + * Generates comprehensive plugin documentation based on existing JSDoc comments + */ +export class PluginDocumentationGenerator { + constructor( + private aiService: AIService, + private gitManager: GitManager, + private configuration: Configuration + ) { } + + /** + * Generates comprehensive plugin documentation + * @param {ASTQueueItem[]} existingDocs - Queue of documented items + * @param {string} branchName - Current git branch name + * @param {TodoItem[]} todoItems - List of TODO items found in the codebase + * @param {EnvUsage[]} envUsages - List of environment variable usages + */ + public async generate( + existingDocs: ASTQueueItem[], + branchName?: string, + todoItems: TodoItem[] = [], + envUsages: EnvUsage[] = [] + ): Promise { + // Read package.json + const packageJsonPath = path.join(this.configuration.absolutePath, 'package.json'); + const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf-8')); + + // Read existing README if it exists + const readmePath = path.join(this.configuration.absolutePath, 'README.md'); + const readmeContent = fs.existsSync(readmePath) + ? fs.readFileSync(readmePath, 'utf-8') + : undefined; + + // Generate documentation + const documentation = await this.aiService.generatePluginDocumentation({ + existingDocs, + packageJson, + readmeContent, + todoItems, + envUsages + }); + + // Generate and write markdown + const markdownContent = this.generateMarkdownContent(documentation); + fs.writeFileSync(readmePath, markdownContent); + + // Commit if we're in a branch + if (branchName) { + await this.gitManager.commitFile( + branchName, + 'README-automated.md', + markdownContent, + 'docs: Update plugin documentation' + ); + } + } + + private generateMarkdownContent(docs: PluginDocumentation & { todos: string }): string { + return `# Plugin Documentation +## Overview and Purpose +${docs.overview} +## Installation +${docs.installation} +## Configuration +${docs.configuration} +## Usage Examples +${docs.usage} +## API Reference +${docs.apiReference} +## Common Issues & Troubleshooting +${docs.troubleshooting} +## TODO Items +${docs.todos} +`; + } +} \ No newline at end of file diff --git a/scripts/jsdoc-automation/src/index.ts b/scripts/jsdoc-automation/src/index.ts index b3156e0608..d5d2647278 100644 --- a/scripts/jsdoc-automation/src/index.ts +++ b/scripts/jsdoc-automation/src/index.ts @@ -6,6 +6,7 @@ import { DocumentationGenerator } from './DocumentationGenerator.js'; import { Configuration } from './Configuration.js'; import { AIService } from './AIService.js'; import { GitManager } from './GitManager.js'; +import { PluginDocumentationGenerator } from './PluginDocumentationGenerator.js'; /** * Main function for generating documentation. @@ -59,6 +60,29 @@ async function main() { aiService ); + const pluginDocGenerator = new PluginDocumentationGenerator( + aiService, + gitManager, + configuration + ); + + const { todoItems, envUsages } = await documentationGenerator.analyzeCodebase(); + + // Generate JSDoc documentation first + const { documentedItems, branchName } = await documentationGenerator.generate( + configuration.repository.pullNumber + ); + + if (branchName) { // Only generate plugin docs if we have JSDoc changes + // Then generate plugin documentation on the same branch + await pluginDocGenerator.generate( + documentedItems, + branchName, // Use the same branch as JSDoc changes + todoItems, + envUsages + ); + } + // Generate documentation await documentationGenerator.generate(configuration.repository.pullNumber); } catch (error) { diff --git a/scripts/jsdoc-automation/src/types/index.ts b/scripts/jsdoc-automation/src/types/index.ts index 238403b4ae..e2fd9be1b4 100644 --- a/scripts/jsdoc-automation/src/types/index.ts +++ b/scripts/jsdoc-automation/src/types/index.ts @@ -1,3 +1,5 @@ +import { TSESTree } from "@typescript-eslint/types"; + export interface ASTQueueItem { name: string; filePath: string; @@ -26,4 +28,56 @@ export interface PrModeFileChange extends FullModeFileChange { deletions: number; changes: number; contents_url: string; +} + +export interface OrganizedDocs { + classes: ASTQueueItem[]; + methods: ASTQueueItem[]; + interfaces: ASTQueueItem[]; + types: ASTQueueItem[]; +} + +export interface TodoSection { + todos: string; + todoCount: number; +} + +export interface TodoItem { + comment: string; + code: string; + fullContext: string; + node: TSESTree.Node; + location: { + start: { line: number; column: number }; + end: { line: number; column: number }; + }; + contextLocation: { + start: { line: number; column: number }; + end: { line: number; column: number }; + }; +} + +export interface EnvUsage { + code: string; + context: string; + fullContext: string; + node: TSESTree.Node; + location: { + start: { line: number; column: number }; + end: { line: number; column: number }; + }; + contextLocation: { + start: { line: number; column: number }; + end: { line: number; column: number }; + }; +} + +export interface PluginDocumentation { + overview: string; + installation: string; + configuration: string; + usage: string; + apiReference: string; + troubleshooting: string; + todos: string; } \ No newline at end of file