feat(core): add infrastructure layer services

Add infrastructure implementations:
- BaseRepository with in-memory storage
- GitService for git operations using simple-git
- CodeParser for JS/TS parsing using tree-sitter
This commit is contained in:
imfozilbek
2025-11-23 21:43:40 +05:00
parent 2d54538d81
commit 6e24fe6ba8
4 changed files with 140 additions and 0 deletions

View File

@@ -0,0 +1,42 @@
import simpleGit, { SimpleGit, SimpleGitOptions } from 'simple-git';
/**
* Git operations service using simple-git
*/
export class GitService {
private readonly git: SimpleGit;
constructor(baseDir: string, options?: Partial<SimpleGitOptions>) {
this.git = simpleGit(baseDir, options);
}
public async clone(repoUrl: string, localPath: string): Promise<void> {
await this.git.clone(repoUrl, localPath);
}
public async status(): Promise<string> {
const statusSummary = await this.git.status();
return JSON.stringify(statusSummary, null, 2);
}
public async log(maxCount: number = 10): Promise<string> {
const logResult = await this.git.log({ maxCount });
return JSON.stringify(logResult, null, 2);
}
public async add(files: string | string[]): Promise<void> {
await this.git.add(files);
}
public async commit(message: string): Promise<void> {
await this.git.commit(message);
}
public async push(remote: string = 'origin', branch: string = 'main'): Promise<void> {
await this.git.push(remote, branch);
}
public async pull(remote: string = 'origin', branch: string = 'main'): Promise<void> {
await this.git.pull(remote, branch);
}
}

View File

@@ -0,0 +1,3 @@
export * from './repositories/BaseRepository';
export * from './git/GitService';
export * from './parsers/CodeParser';

View File

@@ -0,0 +1,56 @@
import Parser from 'tree-sitter';
import JavaScript from 'tree-sitter-javascript';
import TypeScript from 'tree-sitter-typescript';
/**
* Code parser service using tree-sitter
*/
export class CodeParser {
private readonly parser: Parser;
constructor() {
this.parser = new Parser();
}
public parseJavaScript(code: string): Parser.Tree {
this.parser.setLanguage(JavaScript);
return this.parser.parse(code);
}
public parseTypeScript(code: string): Parser.Tree {
this.parser.setLanguage(TypeScript.typescript);
return this.parser.parse(code);
}
public parseTsx(code: string): Parser.Tree {
this.parser.setLanguage(TypeScript.tsx);
return this.parser.parse(code);
}
public extractFunctions(tree: Parser.Tree): string[] {
const functions: string[] = [];
const cursor = tree.walk();
const visit = (): void => {
const node = cursor.currentNode;
if (
node.type === 'function_declaration' ||
node.type === 'arrow_function' ||
node.type === 'function_expression'
) {
functions.push(node.text);
}
if (cursor.gotoFirstChild()) {
do {
visit();
} while (cursor.gotoNextSibling());
cursor.gotoParent();
}
};
visit();
return functions;
}
}

View File

@@ -0,0 +1,39 @@
import { BaseEntity } from '../../domain/entities/BaseEntity';
import { IRepository } from '../../domain/repositories/IRepository';
/**
* Abstract base repository implementation
* Provides common repository functionality
*/
export abstract class BaseRepository<T extends BaseEntity> implements IRepository<T> {
protected readonly items: Map<string, T> = new Map();
public async findById(id: string): Promise<T | null> {
return this.items.get(id) ?? null;
}
public async findAll(): Promise<T[]> {
return Array.from(this.items.values());
}
public async save(entity: T): Promise<T> {
this.items.set(entity.id, entity);
return entity;
}
public async update(entity: T): Promise<T> {
if (!this.items.has(entity.id)) {
throw new Error(`Entity with id ${entity.id} not found`);
}
this.items.set(entity.id, entity);
return entity;
}
public async delete(id: string): Promise<boolean> {
return this.items.delete(id);
}
public async exists(id: string): Promise<boolean> {
return this.items.has(id);
}
}