docit 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +26 -0
- data/CONTRIBUTING.md +1 -1
- data/README.md +61 -6
- data/app/controllers/docit/ui_controller.rb +16 -4
- data/lib/docit/ai/anthropic_client.rb +57 -0
- data/lib/docit/ai/autodoc_runner.rb +168 -0
- data/lib/docit/ai/client.rb +23 -0
- data/lib/docit/ai/configuration.rb +66 -0
- data/lib/docit/ai/doc_writer.rb +120 -0
- data/lib/docit/ai/gap_detector.rb +54 -0
- data/lib/docit/ai/groq_client.rb +55 -0
- data/lib/docit/ai/openai_client.rb +55 -0
- data/lib/docit/ai/prompt_builder.rb +124 -0
- data/lib/docit/ai/scaffold_generator.rb +140 -0
- data/lib/docit/ai/tag_injector.rb +52 -0
- data/lib/docit/ai.rb +13 -0
- data/lib/docit/version.rb +1 -1
- data/lib/docit.rb +2 -0
- data/lib/generators/docit/ai_setup/ai_setup_generator.rb +106 -0
- data/lib/generators/docit/install/install_generator.rb +178 -3
- data/lib/tasks/docit.rake +19 -0
- metadata +25 -10
- data/.github/workflows/ci.yml +0 -30
|
@@ -1,11 +1,19 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "io/console"
|
|
4
|
+
|
|
3
5
|
module Docit
|
|
4
6
|
module Generators
|
|
5
7
|
class InstallGenerator < Rails::Generators::Base
|
|
6
|
-
desc "Creates a Docit initializer
|
|
8
|
+
desc "Creates a Docit initializer, mounts the engine, and sets up documentation"
|
|
7
9
|
source_root File.expand_path("templates", __dir__)
|
|
8
10
|
|
|
11
|
+
PROVIDER_OPTIONS = {
|
|
12
|
+
"1" => "openai",
|
|
13
|
+
"2" => "anthropic",
|
|
14
|
+
"3" => "groq"
|
|
15
|
+
}.freeze
|
|
16
|
+
|
|
9
17
|
def copy_initializer
|
|
10
18
|
template "initializer.rb", "config/initializers/docit.rb"
|
|
11
19
|
end
|
|
@@ -14,15 +22,182 @@ module Docit
|
|
|
14
22
|
route 'mount Docit::Engine => "/api-docs"'
|
|
15
23
|
end
|
|
16
24
|
|
|
17
|
-
def
|
|
25
|
+
def ask_doc_mode
|
|
26
|
+
say ""
|
|
27
|
+
say "How would you like to set up your API documentation?", :green
|
|
28
|
+
say " 1. AI automatic docs (generate docs using AI)"
|
|
29
|
+
say " 2. Manual docs (create scaffolded placeholders to fill in)"
|
|
30
|
+
say " 3. Skip for now, I'll do it myself (just set up the engine and initializer)"
|
|
31
|
+
say ""
|
|
32
|
+
|
|
33
|
+
@doc_mode = ask_choice("Enter choice (1-3):", %w[1 2 3])
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def setup_docs
|
|
37
|
+
case @doc_mode
|
|
38
|
+
when "1"
|
|
39
|
+
run_ai_setup
|
|
40
|
+
when "2"
|
|
41
|
+
run_manual_scaffold
|
|
42
|
+
else
|
|
43
|
+
print_skip_instructions
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
def run_ai_setup
|
|
50
|
+
say ""
|
|
51
|
+
say "--- AI Documentation Setup ---", :yellow
|
|
52
|
+
say ""
|
|
53
|
+
|
|
54
|
+
provider = prompt_provider
|
|
55
|
+
api_key = prompt_api_key(provider)
|
|
56
|
+
save_ai_configuration(provider, api_key)
|
|
57
|
+
update_gitignore
|
|
58
|
+
|
|
59
|
+
say ""
|
|
60
|
+
say "Scanning project for undocumented endpoints...", :yellow
|
|
61
|
+
say ""
|
|
62
|
+
|
|
63
|
+
runner = Docit::Ai::AutodocRunner.new(output: shell_output)
|
|
64
|
+
runner.run
|
|
65
|
+
|
|
66
|
+
say ""
|
|
67
|
+
say "Docit installed and AI docs generated!", :green
|
|
68
|
+
say ""
|
|
69
|
+
say "Next steps:"
|
|
70
|
+
say " 1. Review generated doc files in app/docs/"
|
|
71
|
+
say " 2. Edit config/initializers/docit.rb to customize settings"
|
|
72
|
+
say " 3. Start your server and visit /api-docs"
|
|
73
|
+
say ""
|
|
74
|
+
say "To regenerate docs later:"
|
|
75
|
+
say " rails docit:autodoc"
|
|
76
|
+
say ""
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def run_manual_scaffold
|
|
80
|
+
say ""
|
|
81
|
+
say "--- Manual Documentation Setup ---", :yellow
|
|
82
|
+
say ""
|
|
83
|
+
say "Scanning project for endpoints...", :yellow
|
|
84
|
+
say ""
|
|
85
|
+
|
|
86
|
+
scaffold = Docit::Ai::ScaffoldGenerator.new(output: shell_output)
|
|
87
|
+
scaffold.run
|
|
88
|
+
|
|
89
|
+
say ""
|
|
90
|
+
say "Docit installed with doc scaffolds!", :green
|
|
91
|
+
say ""
|
|
92
|
+
say "Next steps:"
|
|
93
|
+
say " 1. Fill in the TODO placeholders in your doc files under app/docs/"
|
|
94
|
+
say " 2. Edit config/initializers/docit.rb to customize settings"
|
|
95
|
+
say " 3. Start your server and visit /api-docs"
|
|
96
|
+
say ""
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def print_skip_instructions
|
|
18
100
|
say ""
|
|
19
101
|
say "Docit installed successfully!", :green
|
|
20
102
|
say ""
|
|
21
103
|
say "Next steps:"
|
|
22
104
|
say " 1. Edit config/initializers/docit.rb to customize your API docs"
|
|
23
|
-
say " 2. Add swagger_doc blocks
|
|
105
|
+
say " 2. Add swagger_doc blocks or create doc files under app/docs/"
|
|
24
106
|
say " 3. Visit /api-docs to see your Swagger UI"
|
|
25
107
|
say ""
|
|
108
|
+
say "You can set up docs later with:"
|
|
109
|
+
say " rails generate docit:ai_setup # configure AI provider"
|
|
110
|
+
say " rails docit:autodoc # generate docs with AI"
|
|
111
|
+
say ""
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def prompt_provider
|
|
115
|
+
say "Select your AI provider:"
|
|
116
|
+
say " 1. OpenAI"
|
|
117
|
+
say " 2. Anthropic"
|
|
118
|
+
say " 3. Groq (free tier available)"
|
|
119
|
+
say ""
|
|
120
|
+
|
|
121
|
+
choice = ask_choice("Enter choice (1-3):", PROVIDER_OPTIONS.keys)
|
|
122
|
+
provider = PROVIDER_OPTIONS[choice]
|
|
123
|
+
|
|
124
|
+
say "Selected: #{provider.capitalize}", :green
|
|
125
|
+
provider
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
def prompt_api_key(provider)
|
|
129
|
+
loop do
|
|
130
|
+
api_key = ask_secret("Enter your #{provider.capitalize} API key:")
|
|
131
|
+
return api_key if api_key.empty? == false
|
|
132
|
+
|
|
133
|
+
say "API key cannot be blank.", :red
|
|
134
|
+
end
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def save_ai_configuration(provider, api_key)
|
|
138
|
+
model = Docit::Ai::Configuration::DEFAULT_MODELS[provider]
|
|
139
|
+
Docit::Ai::Configuration.save(
|
|
140
|
+
provider: provider,
|
|
141
|
+
model: model,
|
|
142
|
+
api_key: api_key
|
|
143
|
+
)
|
|
144
|
+
say "Saved AI configuration to .docit_ai.yml", :green
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def update_gitignore
|
|
148
|
+
gitignore = Rails.root.join(".gitignore")
|
|
149
|
+
if !(File.exist?(gitignore))
|
|
150
|
+
say "Warning: .gitignore not found. Add .docit_ai.yml manually to avoid committing your API key.", :yellow
|
|
151
|
+
return
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
content = File.read(gitignore)
|
|
155
|
+
return if content.include?(".docit_ai.yml")
|
|
156
|
+
|
|
157
|
+
File.open(gitignore, "a") do |f|
|
|
158
|
+
f.puts "" unless content.end_with?("\n")
|
|
159
|
+
f.puts "# Docit AI configuration (contains API key)"
|
|
160
|
+
f.puts ".docit_ai.yml"
|
|
161
|
+
end
|
|
162
|
+
say "Added .docit_ai.yml to .gitignore", :green
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
def ask_choice(prompt, choices)
|
|
166
|
+
loop do
|
|
167
|
+
choice = ask(prompt).to_s.strip
|
|
168
|
+
return choice if choices.include?(choice)
|
|
169
|
+
|
|
170
|
+
say "Invalid choice. Please enter #{choices.join(', ')}.", :red
|
|
171
|
+
end
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def ask_secret(prompt)
|
|
175
|
+
if $stdin.respond_to?(:noecho) && $stdin.tty?
|
|
176
|
+
shell.say(prompt, nil, false)
|
|
177
|
+
value = $stdin.noecho(&:gets).to_s.strip
|
|
178
|
+
shell.say("")
|
|
179
|
+
value
|
|
180
|
+
else
|
|
181
|
+
ask(prompt).to_s.strip
|
|
182
|
+
end
|
|
183
|
+
end
|
|
184
|
+
|
|
185
|
+
def shell_output
|
|
186
|
+
@shell_output ||= ShellOutput.new(shell)
|
|
187
|
+
end
|
|
188
|
+
|
|
189
|
+
class ShellOutput
|
|
190
|
+
def initialize(shell)
|
|
191
|
+
@shell = shell
|
|
192
|
+
end
|
|
193
|
+
|
|
194
|
+
def puts(msg = "")
|
|
195
|
+
@shell.say(msg)
|
|
196
|
+
end
|
|
197
|
+
|
|
198
|
+
def print(msg)
|
|
199
|
+
@shell.say(msg, nil, false)
|
|
200
|
+
end
|
|
26
201
|
end
|
|
27
202
|
end
|
|
28
203
|
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
namespace :docit do
|
|
4
|
+
desc "Generate documentation for undocumented API endpoints using AI"
|
|
5
|
+
task :autodoc, [:controller] => :environment do |_t, args|
|
|
6
|
+
dry_run = ENV.fetch("DRY_RUN", "0") == "1" || ARGV.include?("--dry-run")
|
|
7
|
+
controller_filter = args[:controller]
|
|
8
|
+
|
|
9
|
+
runner = Docit::Ai::AutodocRunner.new(
|
|
10
|
+
controller_filter: controller_filter,
|
|
11
|
+
dry_run: dry_run
|
|
12
|
+
)
|
|
13
|
+
|
|
14
|
+
runner.run
|
|
15
|
+
rescue Docit::Error => e
|
|
16
|
+
warn e.message
|
|
17
|
+
exit 1
|
|
18
|
+
end
|
|
19
|
+
end
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: docit
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- S13G
|
|
@@ -23,9 +23,9 @@ dependencies:
|
|
|
23
23
|
- - ">="
|
|
24
24
|
- !ruby/object:Gem::Version
|
|
25
25
|
version: '7.0'
|
|
26
|
-
description:
|
|
27
|
-
|
|
28
|
-
|
|
26
|
+
description: Write OpenAPI 3.0.3 documentation for Rails APIs with clean controller
|
|
27
|
+
DSL macros, separate doc modules, and optional AI-assisted doc generation for undocumented
|
|
28
|
+
endpoints.
|
|
29
29
|
email:
|
|
30
30
|
- siegdomain1@gmail.com
|
|
31
31
|
executables: []
|
|
@@ -35,7 +35,6 @@ files:
|
|
|
35
35
|
- ".github/ISSUE_TEMPLATE/bug_report.md"
|
|
36
36
|
- ".github/ISSUE_TEMPLATE/feature_request.md"
|
|
37
37
|
- ".github/PULL_REQUEST_TEMPLATE.md"
|
|
38
|
-
- ".github/workflows/ci.yml"
|
|
39
38
|
- CHANGELOG.md
|
|
40
39
|
- CODE_OF_CONDUCT.md
|
|
41
40
|
- CONTRIBUTING.md
|
|
@@ -45,6 +44,18 @@ files:
|
|
|
45
44
|
- app/controllers/docit/ui_controller.rb
|
|
46
45
|
- config/routes.rb
|
|
47
46
|
- lib/docit.rb
|
|
47
|
+
- lib/docit/ai.rb
|
|
48
|
+
- lib/docit/ai/anthropic_client.rb
|
|
49
|
+
- lib/docit/ai/autodoc_runner.rb
|
|
50
|
+
- lib/docit/ai/client.rb
|
|
51
|
+
- lib/docit/ai/configuration.rb
|
|
52
|
+
- lib/docit/ai/doc_writer.rb
|
|
53
|
+
- lib/docit/ai/gap_detector.rb
|
|
54
|
+
- lib/docit/ai/groq_client.rb
|
|
55
|
+
- lib/docit/ai/openai_client.rb
|
|
56
|
+
- lib/docit/ai/prompt_builder.rb
|
|
57
|
+
- lib/docit/ai/scaffold_generator.rb
|
|
58
|
+
- lib/docit/ai/tag_injector.rb
|
|
48
59
|
- lib/docit/builders/parameter_builder.rb
|
|
49
60
|
- lib/docit/builders/request_body_builder.rb
|
|
50
61
|
- lib/docit/builders/response_builder.rb
|
|
@@ -58,17 +69,20 @@ files:
|
|
|
58
69
|
- lib/docit/schema_definition.rb
|
|
59
70
|
- lib/docit/schema_generator.rb
|
|
60
71
|
- lib/docit/version.rb
|
|
72
|
+
- lib/generators/docit/ai_setup/ai_setup_generator.rb
|
|
61
73
|
- lib/generators/docit/install/install_generator.rb
|
|
62
74
|
- lib/generators/docit/install/templates/initializer.rb
|
|
75
|
+
- lib/tasks/docit.rake
|
|
63
76
|
- sig/docit.rbs
|
|
64
|
-
homepage: https://github.com/S13G/
|
|
77
|
+
homepage: https://github.com/S13G/docit
|
|
65
78
|
licenses:
|
|
66
79
|
- MIT
|
|
67
80
|
metadata:
|
|
68
|
-
homepage_uri: https://github.com/S13G/
|
|
69
|
-
source_code_uri: https://github.com/S13G/
|
|
70
|
-
changelog_uri: https://github.com/S13G/
|
|
81
|
+
homepage_uri: https://github.com/S13G/docit
|
|
82
|
+
source_code_uri: https://github.com/S13G/docit
|
|
83
|
+
changelog_uri: https://github.com/S13G/docit/blob/main/CHANGELOG.md
|
|
71
84
|
documentation_uri: https://rubydoc.info/gems/docit
|
|
85
|
+
bug_tracker_uri: https://github.com/S13G/docit/issues
|
|
72
86
|
rubygems_mfa_required: 'true'
|
|
73
87
|
rdoc_options: []
|
|
74
88
|
require_paths:
|
|
@@ -86,5 +100,6 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
86
100
|
requirements: []
|
|
87
101
|
rubygems_version: 4.0.3
|
|
88
102
|
specification_version: 4
|
|
89
|
-
summary: Decorator-style
|
|
103
|
+
summary: Decorator-style OpenAPI documentation for Rails with inline DSL, doc modules,
|
|
104
|
+
and AI-assisted scaffolding.
|
|
90
105
|
test_files: []
|
data/.github/workflows/ci.yml
DELETED
|
@@ -1,30 +0,0 @@
|
|
|
1
|
-
name: CI
|
|
2
|
-
|
|
3
|
-
on:
|
|
4
|
-
push:
|
|
5
|
-
branches: [main]
|
|
6
|
-
pull_request:
|
|
7
|
-
branches: [main]
|
|
8
|
-
|
|
9
|
-
jobs:
|
|
10
|
-
test:
|
|
11
|
-
runs-on: ubuntu-latest
|
|
12
|
-
strategy:
|
|
13
|
-
fail-fast: false
|
|
14
|
-
matrix:
|
|
15
|
-
ruby-version: ["3.2", "3.3", "3.4"]
|
|
16
|
-
|
|
17
|
-
steps:
|
|
18
|
-
- uses: actions/checkout@v4
|
|
19
|
-
|
|
20
|
-
- name: Set up Ruby ${{ matrix.ruby-version }}
|
|
21
|
-
uses: ruby/setup-ruby@v1
|
|
22
|
-
with:
|
|
23
|
-
ruby-version: ${{ matrix.ruby-version }}
|
|
24
|
-
bundler-cache: true
|
|
25
|
-
|
|
26
|
-
- name: Run tests
|
|
27
|
-
run: bundle exec rspec
|
|
28
|
-
|
|
29
|
-
- name: Run linter
|
|
30
|
-
run: bundle exec rubocop
|