Hacktoberfest 2026: những issue maintainer đã đánh dấu cho tháng Mười, đang mở và phù hợp người mới. Xem issue Hacktoberfest

🏗️ Refactor architecture to improve maintainability

Đang mở
#67 0 bình luận 0 reaction 0 người được giao Xem trên GitHub

Chưa có ai nhận issue này.

Đánh giá

Độ khó
5/5
Thời gian dự kiến
Hơn một tuần
Mức phù hợp với người mới
30/100
Loại issue
Tái cấu trúc
Độ rõ ràng
Khá rõ ràng
Mức độ hoạt động
Đình trệ
Công nghệ
git, javascript
Lĩnh vực
cli, tooling

Hướng nghiên cứu

Bắt đầu bằng cách đọc index.js, utils/sanitizeCommitMessage.js và phần 1 của claudedocs/quality-analysis-report.md để lập bản đồ các trách nhiệm hiện tại. Hãy so sánh cấu trúc đó với bố cục src/ được đề xuất và các giai đoạn triển khai trước khi thực hiện thay đổi. Công việc được xem là hoàn tất khi các tiêu chí chấp nhận đã nêu được đáp ứng, các bài kiểm thử hiện có đều chạy thành công và CLI vẫn tương thích ngược.

Do mô hình lập chỉ mục viết ra từ nội dung của issue.

Mô tả

architecture high-priority refactoring

Problem

The current architecture has all logic in a single 389-line index.js file with multiple responsibilities, making it difficult to maintain and test.

Current issues:

  • Single file handles: CLI routing, OpenAI API, config I/O, git operations, user prompts
  • Global mutable state (openai, model, language, apiKey)
  • gitExtension() function is 202 lines (lines 184-386)
  • gptCommit() mixes business logic with I/O operations
  • Hard to test components in isolation

Current Structure

index.js (389 lines)
  ├─ Global variables (state)
  ├─ saveConfig() / loadConfig()
  ├─ maskApiKey()
  ├─ getGitSummary()
  ├─ gptCommit()
  └─ gitExtension() (CLI setup)
utils/
  └─ sanitizeCommitMessage.js

Proposed Modular Structure

src/
  ├─ index.js                    # Entry point (~50 lines)
  ├─ cli/
  │   ├─ commands/
  │   │   ├─ commit.js          # Commit command handler
  │   │   ├─ model.js           # Model selection command
  │   │   ├─ language.js        # Language selection command
  │   │   ├─ prefix.js          # Prefix toggle command
  │   │   ├─ apiKey.js          # API key management command
  │   │   └─ config.js          # Config display command
  │   └─ index.js               # CLI setup with Commander
  ├─ services/
  │   ├─ OpenAIService.js       # OpenAI API interactions
  │   ├─ GitService.js          # Git operations
  │   └─ ConfigService.js       # Configuration management
  ├─ prompts/
  │   ├─ modelSelection.js      # Model selection prompt
  │   ├─ languageSelection.js   # Language selection prompt
  │   ├─ confirmCommit.js       # Commit confirmation prompt
  │   └─ apiKeyPrompts.js       # API key prompts
  └─ utils/
      ├─ sanitizeCommitMessage.js
      └─ validators.js          # Input validation utilities
Example Refactoring

Before (index.js - mixed concerns):

const gptCommit = async () => {
  const gitSummary = await getGitSummary()
  if (!gitSummary) {
    console.log('No changes to commit. Commit canceled.')
    process.exit(0)
  }

  const messages = [ /* ... */ ]
  const parameters = { /* ... */ }
  const response = await openai.chat.completions.create(parameters)
  const message = response.choices[0].message.content.trim()
  const sanitizedMessage = sanitizeCommitMessage(message)

  const confirm = await prompts({ /* ... */ })
  if (confirm.value) {
    execSync(`git commit -m "${sanitizedMessage}"`)
    console.log('Committed with the suggested message.')
  } else {
    console.log('Commit canceled.')
  }
}

After (separation of concerns):

// src/services/OpenAIService.js
export class OpenAIService {
  constructor(apiKey, model, language) {
    this.openai = new OpenAI({ apiKey })
    this.model = model
    this.language = language
  }

  async generateCommitMessage(gitDiff, usePrefix) {
    const messages = this.buildMessages(gitDiff, usePrefix)
    const response = await this.callWithRetry({ 
      model: this.model, 
      messages 
    })
    return response.choices[0].message.content.trim()
  }

  buildMessages(gitDiff, usePrefix) { /* ... */ }
  async callWithRetry(params, retries = 3) { /* ... */ }
}

// src/services/GitService.js
export class GitService {
  async getStagedDiff() {
    const { stdout } = await exec(
      "git diff --cached -- . ':(exclude)*lock.json' ':(exclude)*lock.yaml'"
    )
    return stdout.trim() || null
  }

  async commit(message) {
    execSync(`git commit -m "${message}"`)
  }
}

// src/cli/commands/commit.js
export async function commitCommand(config) {
  const gitService = new GitService()
  const openaiService = new OpenAIService(
    config.apiKey, 
    config.model, 
    config.language
  )

  const gitDiff = await gitService.getStagedDiff()
  if (!gitDiff) {
    console.log('No changes to commit.')
    return
  }

  const message = await openaiService.generateCommitMessage(
    gitDiff, 
    config.prefixEnabled
  )
  const sanitized = sanitizeCommitMessage(message)

  if (await confirmCommitPrompt(sanitized)) {
    await gitService.commit(sanitized)
    console.log('✅ Committed successfully.')
  } else {
    console.log('Commit canceled.')
  }
}

Benefits

  • ✅ Single Responsibility: Each module has one clear purpose
  • ✅ Testability: Easy to test components in isolation
  • ✅ Maintainability: Easier to locate and modify functionality
  • ✅ Scalability: Simple to add new commands and features
  • ✅ Reusability: Services can be reused across commands
  • ✅ State Management: Eliminate global mutable state

Implementation Plan

Phase 1: Extract Services (Week 1)
  • Create src/services/OpenAIService.js
  • Create src/services/GitService.js
  • Create src/services/ConfigService.js
  • Add tests for each service
  • Update index.js to use services
Phase 2: Extract Commands (Week 2)
  • Create src/cli/commands/ directory
  • Extract each command to separate file
  • Add tests for command handlers
  • Update CLI setup to use command files
Phase 3: Extract Prompts (Week 3)
  • Create src/prompts/ directory
  • Extract prompt logic from commands
  • Add tests for prompts
  • Update commands to use prompt modules
Phase 4: Cleanup (Week 4)
  • Remove global state from index.js
  • Update all imports and exports
  • Run full test suite
  • Update documentation
  • Verify backward compatibility

Acceptance Criteria

  • index.js reduced to < 100 lines (entry point only)
  • Each service/command file < 200 lines
  • No global mutable state
  • 100% test coverage for new services
  • All existing tests pass
  • No breaking changes to CLI interface

Priority

High - Enables future development and maintenance

Related

Quality analysis report: claudedocs/quality-analysis-report.md section 1

Migration Notes

  • Maintain backward compatibility during refactoring
  • Use feature flags if needed for gradual rollout
  • Document breaking changes clearly
  • Update CLAUDE.md with new architecture
Ngôn ngữ chính
JavaScript
Star
36
Fork
3
Chỉ số merge pull request
Không có pull request nào được merge trong 30 ngày

Chuẩn bị môi trường

Dự án này không cung cấp dev container, Dockerfile hay hướng dẫn đóng góp, nên bạn cần tự thiết lập môi trường: hãy bắt đầu từ README và xem hướng dẫn đóng góp lần đầu của chúng tôi để biết các bước chung.

Bắt đầu từ đâu

  1. Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
  2. Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
  3. Fork repository và làm thay đổi trên một nhánh.
  4. Mở pull request có tham chiếu số hiệu của issue.

Issue khác của laststance/git-gpt-commit

Tất cả issue của laststance/git-gpt-commit

Issue tương tự

Thêm issue về JavaScript

Nhận issue mới trong hộp thư của bạn

Bản tóm tắt ngắn những issue GitHub phù hợp với người mới.