diff --git a/packages/ipuaro/CHANGELOG.md b/packages/ipuaro/CHANGELOG.md index 811fa1c..2a006ec 100644 --- a/packages/ipuaro/CHANGELOG.md +++ b/packages/ipuaro/CHANGELOG.md @@ -5,6 +5,24 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [0.3.1] - 2025-11-30 + +### Added + +- **VERSION export** - Package version is now exported from index.ts, automatically read from package.json via `createRequire` + +### Changed + +- 🔄 **Refactored ASTParser** - Reduced complexity and nesting depth: + - Extracted `extractClassHeritage()`, `parseHeritageClause()`, `findTypeIdentifier()`, `collectImplements()` helper methods + - Max nesting depth reduced from 5 to 4 +- 🔄 **Refactored RedisStorage** - Removed unnecessary type parameter from `parseJSON()` method + +### Quality + +- ✅ **Zero lint warnings** - All ESLint warnings resolved +- ✅ **All 321 tests pass** + ## [0.3.0] - 2025-11-30 - Indexer ### Added diff --git a/packages/ipuaro/package.json b/packages/ipuaro/package.json index 88ccd4f..c42804d 100644 --- a/packages/ipuaro/package.json +++ b/packages/ipuaro/package.json @@ -1,6 +1,6 @@ { "name": "@samiyev/ipuaro", - "version": "0.3.0", + "version": "0.3.1", "description": "Local AI agent for codebase operations with infinite context feeling", "author": "Fozilbek Samiyev ", "license": "MIT", diff --git a/packages/ipuaro/src/index.ts b/packages/ipuaro/src/index.ts index d12e3fd..dd60024 100644 --- a/packages/ipuaro/src/index.ts +++ b/packages/ipuaro/src/index.ts @@ -4,6 +4,11 @@ * Main entry point for the library. */ +import { createRequire } from "node:module" + +const require = createRequire(import.meta.url) +const pkg = require("../package.json") as { version: string } + // Domain exports export * from "./domain/index.js" @@ -17,4 +22,4 @@ export * from "./shared/index.js" export * from "./infrastructure/index.js" // Version -export const VERSION = "0.2.0" +export const VERSION = pkg.version diff --git a/packages/ipuaro/src/infrastructure/indexer/ASTParser.ts b/packages/ipuaro/src/infrastructure/indexer/ASTParser.ts index 7af18f5..e1ee2d2 100644 --- a/packages/ipuaro/src/infrastructure/indexer/ASTParser.ts +++ b/packages/ipuaro/src/infrastructure/indexer/ASTParser.ts @@ -306,38 +306,7 @@ export class ASTParser { } } - let extendsName: string | undefined - const implementsList: string[] = [] - - for (const child of node.children) { - if (child.type === NodeType.CLASS_HERITAGE) { - for (const clause of child.children) { - if (clause.type === NodeType.EXTENDS_CLAUSE) { - const typeNode = clause.children.find( - (c) => - c.type === NodeType.TYPE_IDENTIFIER || - c.type === NodeType.IDENTIFIER, - ) - extendsName = typeNode?.text - } else if (clause.type === NodeType.IMPLEMENTS_CLAUSE) { - for (const impl of clause.children) { - if ( - impl.type === NodeType.TYPE_IDENTIFIER || - impl.type === NodeType.IDENTIFIER - ) { - implementsList.push(impl.text) - } - } - } - } - } else if (child.type === NodeType.EXTENDS_CLAUSE) { - const typeNode = child.children.find( - (c) => c.type === NodeType.TYPE_IDENTIFIER || c.type === NodeType.IDENTIFIER, - ) - extendsName = typeNode?.text - } - } - + const { extendsName, implementsList } = this.extractClassHeritage(node) const isAbstract = node.children.some((c) => c.type === NodeType.ABSTRACT) ast.classes.push({ @@ -353,6 +322,56 @@ export class ASTParser { }) } + private extractClassHeritage(node: SyntaxNode): { + extendsName: string | undefined + implementsList: string[] + } { + let extendsName: string | undefined + const implementsList: string[] = [] + + for (const child of node.children) { + if (child.type === NodeType.CLASS_HERITAGE) { + this.parseHeritageClause(child, (ext) => (extendsName = ext), implementsList) + } else if (child.type === NodeType.EXTENDS_CLAUSE) { + extendsName = this.findTypeIdentifier(child) + } + } + + return { extendsName, implementsList } + } + + private parseHeritageClause( + heritage: SyntaxNode, + setExtends: (name: string) => void, + implementsList: string[], + ): void { + for (const clause of heritage.children) { + if (clause.type === NodeType.EXTENDS_CLAUSE) { + const typeId = this.findTypeIdentifier(clause) + if (typeId) { + setExtends(typeId) + } + } else if (clause.type === NodeType.IMPLEMENTS_CLAUSE) { + this.collectImplements(clause, implementsList) + } + } + } + + private findTypeIdentifier(node: SyntaxNode): string | undefined { + const typeNode = node.children.find( + (c) => c.type === NodeType.TYPE_IDENTIFIER || c.type === NodeType.IDENTIFIER, + ) + return typeNode?.text + } + + private collectImplements(clause: SyntaxNode, list: string[]): void { + for (const impl of clause.children) { + if (impl.type === NodeType.TYPE_IDENTIFIER || impl.type === NodeType.IDENTIFIER) { + list.push(impl.text) + } + } + } + private extractMethod(node: SyntaxNode): MethodInfo { const nameNode = node.childForFieldName(FieldName.NAME) const params = this.extractParameters(node) diff --git a/packages/ipuaro/src/infrastructure/storage/RedisStorage.ts b/packages/ipuaro/src/infrastructure/storage/RedisStorage.ts index e4d9539..4227888 100644 --- a/packages/ipuaro/src/infrastructure/storage/RedisStorage.ts +++ b/packages/ipuaro/src/infrastructure/storage/RedisStorage.ts @@ -25,7 +25,7 @@ export class RedisStorage implements IStorage { if (!data) { return null } - return this.parseJSON(data, "FileData") + return this.parseJSON(data, "FileData") as FileData } async setFile(path: string, data: FileData): Promise { @@ -44,7 +44,7 @@ export class RedisStorage implements IStorage { const result = new Map() for (const [path, value] of Object.entries(data)) { - const parsed = this.parseJSON(value, "FileData") + const parsed = this.parseJSON(value, "FileData") as FileData | null if (parsed) { result.set(path, parsed) } @@ -64,7 +64,7 @@ export class RedisStorage implements IStorage { if (!data) { return null } - return this.parseJSON(data, "FileAST") + return this.parseJSON(data, "FileAST") as FileAST } async setAST(path: string, ast: FileAST): Promise { @@ -83,7 +83,7 @@ export class RedisStorage implements IStorage { const result = new Map() for (const [path, value] of Object.entries(data)) { - const parsed = this.parseJSON(value, "FileAST") + const parsed = this.parseJSON(value, "FileAST") as FileAST | null if (parsed) { result.set(path, parsed) } @@ -98,7 +98,7 @@ export class RedisStorage implements IStorage { if (!data) { return null } - return this.parseJSON(data, "FileMeta") + return this.parseJSON(data, "FileMeta") as FileMeta } async setMeta(path: string, meta: FileMeta): Promise { @@ -117,7 +117,7 @@ export class RedisStorage implements IStorage { const result = new Map() for (const [path, value] of Object.entries(data)) { - const parsed = this.parseJSON(value, "FileMeta") + const parsed = this.parseJSON(value, "FileMeta") as FileMeta | null if (parsed) { result.set(path, parsed) } @@ -133,7 +133,7 @@ export class RedisStorage implements IStorage { return new Map() } - const parsed = this.parseJSON<[string, unknown[]][]>(data, "SymbolIndex") + const parsed = this.parseJSON(data, "SymbolIndex") as [string, unknown[]][] | null if (!parsed) { return new Map() } @@ -157,10 +157,10 @@ export class RedisStorage implements IStorage { } } - const parsed = this.parseJSON<{ + const parsed = this.parseJSON(data, "DepsGraph") as { imports: [string, string[]][] importedBy: [string, string[]][] - }>(data, "DepsGraph") + } | null if (!parsed) { return { @@ -190,7 +190,7 @@ export class RedisStorage implements IStorage { if (!data) { return null } - return this.parseJSON(data, "ProjectConfig") + return this.parseJSON(data, "ProjectConfig") } async setProjectConfig(key: string, value: unknown): Promise { @@ -225,9 +225,9 @@ export class RedisStorage implements IStorage { return this.client.getClient() } - private parseJSON(data: string, type: string): T | null { + private parseJSON(data: string, type: string): unknown { try { - return JSON.parse(data) as T + return JSON.parse(data) as unknown } catch (error) { const message = error instanceof Error ? error.message : "Unknown error" throw IpuaroError.parse(`Failed to parse ${type}: ${message}`) diff --git a/packages/ipuaro/tsconfig.json b/packages/ipuaro/tsconfig.json index 3a21b1c..1e53ebb 100644 --- a/packages/ipuaro/tsconfig.json +++ b/packages/ipuaro/tsconfig.json @@ -11,6 +11,7 @@ "declarationMap": true, "sourceMap": true, "strict": true, + "resolveJsonModule": true, "skipLibCheck": true, "esModuleInterop": true, "resolvePackageJsonExports": true,