patrick204nqh/dev_suite

View on GitHub
README.md

Summary

Maintainability
Test Coverage
# DevSuite

[![Gem Version](https://img.shields.io/gem/v/dev_suite?color=blue)](https://rubygems.org/gems/dev_suite)
[![Gem Downloads](https://img.shields.io/gem/dt/dev_suite?color=blue)](https://rubygems.org/gems/dev_suite)
[![Maintainability](https://api.codeclimate.com/v1/badges/fd83689d39e0f24663fa/maintainability)](https://codeclimate.com/github/patrick204nqh/dev_suite/maintainability)
[![Test Coverage](https://api.codeclimate.com/v1/badges/fd83689d39e0f24663fa/test_coverage)](https://codeclimate.com/github/patrick204nqh/dev_suite/test_coverage)
[![Quality Gate Status](https://sonarcloud.io/api/project_badges/measure?project=patrick204nqh_dev_suite&metric=alert_status)](https://sonarcloud.io/summary/overall?id=patrick204nqh_dev_suite)
[![Dependencies Status](https://badges.depfu.com/badges/84fefb47a5b99ea19afd20a2aae22e3e/overview.svg)](https://depfu.com/github/patrick204nqh/dev_suite?project_id=44065)
[![Known Vulnerabilities](https://snyk.io/test/github/patrick204nqh/dev_suite/badge.svg)](https://snyk.io/test/github/patrick204nqh/dev_suite)

Welcome to DevSuite! This gem provides a suite of utilities for developers to enhance their productivity.

## Installation

Add this line to your application's Gemfile:

```ruby
gem 'dev_suite'
```

And then execute:

```sh
$ bundle install
```

Or install it yourself as:

```sh
$ gem install dev_suite
```

## Usage

To use DevSuite, require it in your Ruby code:

```ruby
require 'dev_suite'
```

### Example Usage

```ruby
# Example of using a utility from DevSuite
DevSuite::SomeUtility.do_something
```

### CLI Commands

DevSuite also provides a command-line interface for various utilities. Below are some general commands:

| Command            | Description                         |
|--------------------|-------------------------------------|
| `devsuite version` | Displays the version of DevSuite    |
| `devsuite help`    | Shows help information for commands |

## Features Overview

### Performance Analysis
Analyze the performance of Ruby code blocks, capturing metrics like execution time and memory usage.

<details>
  <summary>Show more</summary>
  
  **How to Use**:
  ```ruby
  DevSuite::Performance.analyze(description: "Example Analysis") do
    sum = 0
    1_000_000.times { |i| sum += i }
    sum
  end
  ```

  **Sample Output**:
  ```
| Metric              | Value            |
|---------------------|------------------|
| Description         | Example Analysis |
| Total Time (s)      | 0.056238         |
| User CPU Time (s)   | 0.055662         |
| System CPU Time (s) | 0.000097         |
| Memory Before (MB)  | 25.39            |
| Memory After (MB)   | 25.42            |
| Memory Used (MB)    | 0.03             |
  ```
</details>

### Directory Tree Visualization
Visualize the file structure of directories and subdirectories to better understand project organization.

<details>
  <summary>Show more</summary>
  
  **How to Use**:
  ```ruby
  # Define the directory path
  base_path = "/path/to/your/directory"

  # Execute the visualization
  DevSuite::DirectoryTree.visualize(base_path)
  ```

  **CLI Command**:
  DevSuite also provides a command-line interface for directory tree visualization. Use the following command to print the directory tree of the specified path:

  ```sh
  $ devsuite tree [PATH] [OPTIONS]
  ```

  **CLI Options**:
  
  Below is a table describing the available options for the `devsuite tree` command:

  | Option          | Description                                      | Example Usage                                  |
  |-----------------|--------------------------------------------------|------------------------------------------------|
  | `--depth`, `-d` | Limit the depth of the directory tree displayed. | `$ devsuite tree /path --depth 2`              |
  | `--skip-hidden` | Skip hidden files and directories.               | `$ devsuite tree /path --skip-hidden`          |
  | `--skip-types`  | Exclude files of specific types.                 | `$ devsuite tree /path --skip-types .log .tmp` |

  **Configuration Guide**:
  Customize the visualization by setting configuration options:
  ```ruby
  DevSuite::DirectoryTree::Config.configure do |config|
    config.settings.set(:skip_hidden, true)
    # ...
  end
  ```

  **Configuration Options**:
| Setting        | Description                                       | Example Values           |
|----------------|---------------------------------------------------|--------------------------|
| `:skip_hidden` | Skips hidden files and directories.               | `true`, `false`          |
| `:max_depth`   | Limits the depth of the directory tree displayed. | `1`, `2`, `3`, ...       |
| `:skip_types`  | Excludes files of specific types.                 | `['.log', '.tmp']`, `[]` |

  **Sample Output**:
  ```
  /path/to/your/directory/
  ├── project/
  │   ├── src/
  │   │   ├── main.rb
  │   │   └── helper.rb
  │   └── spec/
  │       └── main_spec.rb
  ├── doc/
  │   └── README.md
  └── test/
      └── test_helper.rb
  ```
</details>

### Request Logging
Log detailed HTTP requests and responses across different adapters like Net::HTTP and Faraday for debugging and monitoring

<details>
  <summary>Show more</summary>
  
  **How to Use**:
  ```ruby
  DevSuite::RequestLogger.with_logging do 
    # Make an HTTP request using Net::HTTP
    uri = URI('https://jsonplaceholder.typicode.com/posts')
    response = Net::HTTP.get(uri)
  end
  ```

  **Configuration Guide**:
  Customize the request logging behavior by setting configuration options:
  ```ruby
  DevSuite::RequestLogger::Config.configure do |config|
    config.adapters = [:net_http]
    config.settings.set(:log_level, :debug)
    config.settings.set(:log_headers, true)
    config.settings.set(:log_cookies, true)
    config.settings.set(:log_body, true)
  end
  ```

  **Configuration Options**:
  
  Below is a table describing the general configuration options available:

  | Setting        | Description                                           | Default Value | Example Values                     |
  |----------------|-------------------------------------------------------|---------------|------------------------------------|
  | `:adapters`    | List of adapters for which logging is enabled.        | `[:net_http]` | `[:net_http, :faraday]`            |

  **Settings Options**:

  The `settings` key allows you to customize various logging behaviors. Below is a table describing these settings:

  | Setting        | Description                                           | Default Value | Example Values                     |
  |----------------|-------------------------------------------------------|---------------|------------------------------------|
  | `:log_level`   | Set the logging level.                                | `:debug`      | `:info`, `:debug`, `:warn`, `:error` |
  | `:log_headers` | Enable or disable logging of HTTP headers.            | `true`        | `true`, `false`                    |
  | `:log_cookies` | Enable or disable logging of cookies.                 | `true`        | `true`, `false`                    |
  | `:log_body`    | Enable or disable logging of HTTP bodies.             | `true`        | `true`, `false`                    |

  **Sample Output**:
  ```bash
[DEBUG] 🚀 Net::HTTP Request: GET https://jsonplaceholder.typicode.com/posts
[DEBUG] 📄 Headers: {"accept-encoding"=>"gzip;q=1.0,deflate;q=0.6,identity;q=0.3", "accept"=>"*/*", "user-agent"=>"Ruby", "host"=>"jsonplaceholder.typicode.com"}
[DEBUG] 🍪 Cookies: None
[DEBUG] ✅ Net::HTTP Response: 200 OK
[DEBUG] 📄 Headers: {"date"=>"Wed, 21 Aug 2024 10:33:59 GMT", "content-type"=>"application/json; charset=utf-8", "transfer-encoding"=>"chunked", "connection"=>"keep-alive", "report-to"=>"{\"group\":\"heroku-nel\",\"max_age\":3600,\"endpoints\":[{\"url\":\"https://nel.heroku.com/reports?ts=1723379558&sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d&s=LYnyHXQQqBH310%2FAbzjH0MN%2BaFoA6Ntqh94a3%2F5J54E%3D\"}]}", "reporting-endpoints"=>"heroku-nel=https://nel.heroku.com/reports?ts=1723379558&sid=e11707d5-02a7-43ef-b45e-2cf4d2036f7d&s=LYnyHXQQqBH310%2FAbzjH0MN%2BaFoA6Ntqh94a3%2F5J54E%3D", "nel"=>"{\"report_to\":\"heroku-nel\",\"max_age\":3600,\"success_fraction\":0.005,\"failure_fraction\":0.05,\"response_headers\":[\"Via\"]}", "x-powered-by"=>"Express", "x-ratelimit-limit"=>"1000", "x-ratelimit-remaining"=>"999", "x-ratelimit-reset"=>"1723379596", "vary"=>"Origin, Accept-Encoding", "access-control-allow-credentials"=>"true", "cache-control"=>"max-age=43200", "pragma"=>"no-cache", "expires"=>"-1", "x-content-type-options"=>"nosniff", "etag"=>"W/\"6b80-Ybsq/K6GwwqrYkAsFxqDXGC7DoM\"", "via"=>"1.1 vegur", "cf-cache-status"=>"HIT", "age"=>"4620", "server"=>"cloudflare", "cf-ray"=>"8b69f7d4ad941fa4-HKG", "alt-svc"=>"h3=\":443\"; ma=86400"}
[DEBUG] 💻 Response Body: [
  {
    "userId": 1,
    "id": 1,
    "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
    "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
  },
  ...
]
  ```
</details>

### Workflow Engine
Manage complex workflows consisting of multiple sequential steps, including handling data between steps and supporting dynamic operations like conditionals, loops, and parallel execution.

<details>
  <summary>Show more</summary>

  **How to Use**:
  ```ruby
  workflow = DevSuite::Workflow.create_engine(initial_context)

  # Define steps
  step1 = DevSuite::Workflow.create_step("Step 1") do |ctx|
    ctx.update({ result: "Step 1 Complete" })
  end

  step2 = DevSuite::Workflow.create_step("Step 2") do |ctx|
    puts "Previous Result: #{ctx.get(:result)}"
    ctx.update({ result: "Step 2 Complete" })
  end

  # Chain steps together
  workflow.step(step1).step(step2)

  # Execute workflow
  workflow.execute
  ```

  **Chaining Steps**:
  You can chain multiple steps together to create a workflow:
  ```ruby
  workflow = DevSuite::Workflow.create_engine(initial_context)
  
  step1 = DevSuite::Workflow.create_step("Step 1") { |ctx| ctx.update({ data: 'Data from Step 1' }) }
  step2 = DevSuite::Workflow.create_step("Step 2") { |ctx| puts "Received: #{ctx.get(:data)}" }

  workflow.step(step1)
          .step(step2)
          .execute
  ```

  **Data Handling**:
  Each step in the workflow has access to a shared context, where you can store and retrieve data:
  ```ruby
  workflow = DevSuite::Workflow.create_engine({ some_key: 'initial_value' })

  step1 = DevSuite::Workflow.create_step("Step 1") do |ctx|
    # Retrieve data
    puts ctx.get(:some_key)  # Output: initial_value
    # Set data
    ctx.update({ new_key: 'new_value' })
  end

  step2 = DevSuite::Workflow.create_step("Step 2") do |ctx|
    # Use updated data
    puts ctx.get(:new_key)  # Output: new_value
  end

  workflow.step(step1).step(step2).execute
  ```

  **Conditional Execution**:
  Conditionally execute steps based on logic defined in the workflow context:
  ```ruby
  conditional_step = DevSuite::Workflow.create_conditional_step("Conditional Step", condition: ->(ctx) { ctx.get(:result) == "Step 1 Complete" }) do |ctx|
    puts "Condition met! Executing conditional step."
    ctx.update({ result: "Conditional Step Executed" })
  end

  workflow.step(conditional_step).execute
  ```

  **Parallel Execution**:
  You can execute multiple steps in parallel:
  ```ruby
  parallel_step = DevSuite::Workflow.create_parallel_step("Parallel Step") do |ctx|
    [
      ->(ctx) { ctx.update({ task1: "Task 1 done" }) },
      ->(ctx) { ctx.update({ task2: "Task 2 done" }) }
    ]
  end

  workflow.step(parallel_step).execute
  ```

  **Save and Load Context**:
  Save the workflow's context to a file and reload it for later use:
  ```ruby
  # Saving context to a YAML file
  workflow = DevSuite::Workflow.create_engine({ user: 'John' })
  workflow.step(DevSuite::Workflow.create_step("Example") { |ctx| ctx.update({ status: 'completed' }) })
  workflow.execute

  File.open('context.yml', 'w') { |file| file.write(YAML.dump(workflow.context.data)) }

  # Loading context from a YAML file
  loaded_data = YAML.load_file('context.yml')
  workflow = DevSuite::Workflow.create_engine(loaded_data)
  ```

  **Looping**:
  You can loop steps in the workflow, for instance, if you need to repeat a step multiple times:
  ```ruby
  loop_step = DevSuite::Workflow.create_loop_step("Repeat 5 Times", iterations: 5) do |ctx|
    count = ctx.get(:count) || 0
    ctx.update({ count: count + 1 })
    puts "Iteration: #{ctx.get(:count)}"
  end

  workflow.step(loop_step).execute
  ```

  **Using the Store**:
  By default, the workflow context provides access to an integrated store via ctx.store. You can save and retrieve data across steps:
  ```ruby
  # Using the store in the workflow
  workflow = DevSuite::Workflow.create_engine(
    {},
    driver: :file,
    path: "tmp/workflow.yml",
  )
  step = DevSuite::Workflow.create_step("Store Example") do |ctx|
    ctx.store.set(:step_result, "Step 1 Completed")
  end

  workflow.step(step).execute

  # Fetch data from the store
  puts ctx.store.fetch(:step_result)  # Output: Step 1 Completed
  ```

  **Sample Output**:
  ```bash
  Step 1 executed: result => Step 1 Complete
  Step 2 executed: Previous Result: Step 1 Complete
  Task 1 done
  Task 2 done
  Iteration: 1
  Iteration: 2
  ...
  Condition met! Executing conditional step.
  Store contains: { name: "John Doe", age: 30 }
  Step 1 Completed
  ```

</details>

### Method Tracer
Trace all method calls within a specific block of code, including optional logging of parameters, results, and execution time. This feature is useful for debugging, profiling, and understanding the flow of method calls in your code.

<details>
  <summary>Show more</summary>
  
  **How to Use**:
  ```ruby
  # Sample class for demonstration
  class MathOperations
    def add(a, b)
      multiply(a, b) + 3
    end

    def multiply(a, b)
      a * b
    end

    def greet(name)
      "Hello, #{name}!"
    end
  end

  # Using MethodTracer to trace method calls
  DevSuite::MethodTracer.trace(show_params: true, show_results: true, show_execution_time: true) do
    math = MathOperations.new
    result = math.add(5, 3)
    puts result
    
    greeting = math.greet("Ruby")
    puts greeting  # Should print the greeting
  end
  ```

  **Configuration Guide**:
  Customize the method tracing behavior by setting configuration options:
  ```ruby
  DevSuite::MethodTracer.trace(
    show_params: true,
    show_results: true,
    show_execution_time: true,
    max_depth: 2
  ) do
    # Code block to trace
  end
  ```

  **Configuration Options**:
  
  Below is a table describing the available options for `MethodTracer`:

  | Option               | Description                                         | Default Value | Example Values            |
  |----------------------|-----------------------------------------------------|---------------|---------------------------|
  | `:show_params`       | Enables logging of method parameters.               | `false`       | `true`, `false`           |
  | `:show_results`      | Logs the return values of the methods.              | `false`       | `true`, `false`           |
  | `:show_execution_time` | Logs the execution time for each method.          | `false`       | `true`, `false`           |
  | `:max_depth`         | Limits the depth of method calls to log.            | `nil`         | `1`, `2`, `3`, ...        |

  **Sample Output**:
  ```bash
   🚀 #depth:1 > MathOperations#add at (irb):2 (5, 3)
      🚀 #depth:2 > MathOperations#multiply at (irb):6 (5, 3)
      🏁 #depth:2 < MathOperations#multiply #=> 15 at (irb):8 in 0.02ms
   🏁 #depth:1 < MathOperations#add #=> 23 at (irb):4 in 7.35ms
   🚀 #depth:1 > MathOperations#greet at (irb):10 ("Ruby")
   🏁 #depth:1 < MathOperations#greet #=> "Hello, Ruby!" at (irb):12 in 0.02ms
Hello, Ruby!
```

  **Tips**:

  Use `max_depth` to Limit Tracing: If you have deeply nested method calls, use the `max_depth` option to limit the depth of tracing. This can help reduce the amount of log output and focus on the most relevant parts of your code. A recommended value for `max_depth` is between `2` and `5`, depending on the complexity of your code.
</details>

## Development

After checking out the repo, run `bin/setup`for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run:

```sh
$ bundle exec rake install
```

To release a new version, update the version number in `version.rb`, and then run:

```sh
$ bundle exec rake release
```

This will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).



## Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/patrick204nqh/dev_suite. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/patrick204nqh/dev_suite/blob/master/CODE_OF_CONDUCT.md).

## License

The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).

## Code of Conduct

Everyone interacting in the DevSuite project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/patrick204nqh/dev_suite/blob/master/CODE_OF_CONDUCT.md).