reposer 1.1.1 โ†’ 1.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: d2d182e993a62366b11a0717b1493ac0d5cdc3eb7919b2943d24991361e02aae
4
- data.tar.gz: 8ef47495a5f872a344f9e435d3144b0d3c3dfb1dfbc314b6bb59d04d86ba40f5
3
+ metadata.gz: f0dac6cfdb3aabf4d7ac21336a8418b2ccc4d5915f461741d5fda5d2e1c3249e
4
+ data.tar.gz: 40af3f7d39bf3d483c8746f94a6f8cc2dc458cd828aaa0c915f19feaea6bd208
5
5
  SHA512:
6
- metadata.gz: 67f272b0d8c59d178839833edca2e7bcdb4f01e69c4a29703ea06683a9d978481bc2b5223fdf6805a25d8752bb8de24cdd3d8447ec6d8744c437b01d757e08e6
7
- data.tar.gz: 72d427439970c77e660ac48894df1cc0e5cb4ec7a250297467db547ef3893228bdcec7da90d2ffcd4f2ccf596148356548606fe116ba0b3ac92db4841cb40b9f
6
+ metadata.gz: 6987ccdfcf352db9513bf43dd633423cf436b6552e473f044e9e4458aa1123967d854797bd58edf313d1330509345750d07aa7639c8ed14f17592943bd21b796
7
+ data.tar.gz: a2459ea73a170297b74f4ef5487a4486ed674c0af182332cfb3ea0a642634f4f1462a37a2bb95433197f1e3686e19b7638e8dc1ee4fc86fcb5722f63f366996d
data/CHANGELOG.md CHANGED
@@ -7,6 +7,59 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
+ ## [1.3.0] - 2025-11-21
11
+
12
+ ### Added
13
+ - **License Preview**: License type now displayed in repository preview before creation
14
+ - **Language-Specific Project Files**: Automatic generation of boilerplate project files
15
+ - **Go**: `go.mod` and `.gitignore`
16
+ - **Python**: `requirements.txt` and `.gitignore` (with framework-specific dependencies for Django, Flask, FastAPI)
17
+ - **JavaScript/TypeScript**: `package.json`, `tsconfig.json` (TypeScript only), and `.gitignore`
18
+ - **Ruby**: `Gemfile` and `.gitignore` (with framework-specific gems for Rails, Sinatra)
19
+ - **Rust**: `Cargo.toml` and `.gitignore`
20
+ - **Java**: `pom.xml` (Spring Boot projects) and `.gitignore`
21
+ - **.NET**: `.gitignore`
22
+ - **PHP**: `composer.json` (with framework-specific dependencies for Laravel, Symfony) and `.gitignore`
23
+ - All generated files are automatically committed to the new repository
24
+
25
+ ## [1.2.0] - 2025-11-21
26
+
27
+ ### Added
28
+ - **20 Topics Generation**: AI now generates up to 20 relevant topics/tags instead of 5-8
29
+ - Enhanced topic generation for comprehensive repository tagging
30
+ - Includes language ecosystem, framework, architecture, deployment, and best practices topics
31
+ - Fallback template generates intelligent topics based on language, framework, and purpose
32
+ - **Emoji Support**: Automatic emoji inclusion for visual appeal
33
+ - Repository descriptions now include at least 2 relevant emojis
34
+ - README generation includes emojis in headers and sections
35
+ - Language-specific emojis (๐Ÿ’Ž Ruby, ๐Ÿ Python, โšก JavaScript, etc.)
36
+ - Purpose-based emojis (๐ŸŒ API, ๐Ÿ“Š Data, ๐Ÿค– AI/ML, etc.)
37
+ - **License Selection**: Interactive license type selection
38
+ - Support for MIT, Apache 2.0, GPL 3.0, BSD 3-Clause, MPL 2.0, Unlicense
39
+ - Custom/Other license option
40
+ - License passed through to GitHub repository creation
41
+ - README generation includes selected license
42
+
43
+ ### Fixed
44
+ - **GitHub Authentication**: Improved GitHub client token handling
45
+ - Now properly reads from `GITHUB_TOKEN` environment variable
46
+ - Better error messages for authentication failures
47
+ - Enhanced error handling for repository creation
48
+ - Support for GitHub API license templates
49
+ - **Topic Limits**: Removed artificial 8-topic limit, now supports up to 20
50
+ - **Context Propagation**: License now properly propagated through generation pipeline
51
+
52
+ ### Enhanced
53
+ - **AI Providers**: Both Gemini and Ollama providers updated
54
+ - Better prompts for emoji and topic generation
55
+ - License-aware README generation
56
+ - Improved formatting and structure
57
+ - **Fallback Templates**: Enhanced template-based generation
58
+ - More intelligent topic selection based on project characteristics
59
+ - Language ecosystem topics (npm, bundler, cargo, etc.)
60
+ - Framework-related topics (web, api, microservices, etc.)
61
+ - Purpose-based topic detection (ai, data, testing, security, etc.)
62
+
10
63
  ## [1.1.0] - 2025-01-20
11
64
 
12
65
  ### Changed - Gem Renamed
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- reposer (1.1.1)
4
+ reposer (1.2.0)
5
5
  faraday (~> 2.0)
6
6
  octokit (~> 6.0)
7
7
  ostruct (~> 0.6)
data/README.md CHANGED
@@ -16,14 +16,17 @@ Reposer is an intelligent CLI tool that uses AI to create GitHub repositories wi
16
16
  - **๐Ÿค– AI-Generated Content**: Multiple AI providers (Gemini, Ollama) or template-based fallback
17
17
  - **๐ŸŽฏ Smart Context Awareness**: Understands project purpose from name, language, and framework
18
18
  - **๐Ÿ”ง Interactive CLI**: Guided prompts for missing information with beautiful UI
19
- - **๐Ÿ“ Professional READMEs**: Creates comprehensive, well-structured documentation
20
- - **๐Ÿท๏ธ Intelligent Topics**: Generates relevant tags and topics automatically
19
+ - **๐Ÿ“ Professional READMEs**: Creates comprehensive, well-structured documentation with emojis
20
+ - **๐Ÿท๏ธ 20 Intelligent Topics**: Generates up to 20 relevant tags and topics automatically
21
+ - **๐Ÿ˜Š Emoji Support**: Automatic emoji inclusion in descriptions and READMEs for visual appeal
22
+ - **๐Ÿ“„ License Selection**: Interactive license picker (MIT, Apache, GPL, BSD, MPL, Unlicense)
23
+ - **๐Ÿ—‚๏ธ Language-Specific Project Files**: Auto-generates boilerplate files (go.mod, package.json, requirements.txt, etc.)
21
24
  - **๐Ÿ‘๏ธ Preview Mode**: See generated content before creating repository
22
25
  - **๐Ÿ” Secure Configuration**: Encrypted storage of API keys and tokens
23
- - **โšก Multi-Language Support**: Built-in support for 10+ programming languages
26
+ - **โšก Multi-Language Support**: Built-in support for 15+ programming languages
24
27
  - **๐ŸŽจ Framework Intelligence**: Recognizes and suggests popular frameworks
25
28
  - **๐Ÿค– Flexible AI Integration**: Choose between Gemini, Ollama, or template-based generation
26
- - **๐Ÿงช 96.63% Test Coverage**: Production-ready with comprehensive testing
29
+ - **๐Ÿงช 90%+ Test Coverage**: Production-ready with comprehensive testing
27
30
 
28
31
  ## ๐Ÿค– AI Provider Options
29
32
 
@@ -106,14 +109,17 @@ reposer create api-server --language go --framework gin --private
106
109
  # Preview before creating
107
110
  reposer create ai-chatbot --language python --framework fastapi --dry-run
108
111
 
112
+ # Specify license type
113
+ reposer create api-server --language go --framework gin --license apache-2.0
114
+
109
115
  # Custom description and topics
110
116
  reposer create data-processor \
111
117
  --language python \
112
118
  --description "High-performance data processing pipeline" \
113
119
  --topics ml,data,etl,python
114
120
 
115
- # Framework-specific project
116
- reposer create blog-api --language ruby --framework rails --private
121
+ # Framework-specific project with custom license
122
+ reposer create blog-api --language ruby --framework rails --license gpl-3.0 --private
117
123
  ```
118
124
 
119
125
  ### Interactive Experience
@@ -122,26 +128,29 @@ $ reposer create awesome-api
122
128
  ๐ŸŽฏ Reposer - AI Repository Creator
123
129
  ========================================
124
130
  Primary programming language: ruby
125
- Framework/Library: Rails
131
+ Framework/Library: Rails
132
+ Choose a license: MIT License (Permissive, most popular)
126
133
  What will this project do? A REST API for user management
127
134
 
128
135
  ๐Ÿ“‹ Generated Repository Content
129
136
  ----------------------------------------
130
137
  Name: awesome-api
131
- Description: A Ruby Rails project for user management
132
- Topics: ruby, rails, api, web, rest
138
+ Description: ๐Ÿš€ A Ruby Rails REST API for user management ๐Ÿ’Ž
139
+ Topics: ruby, rails, api, rest, web, backend, database, authentication,
140
+ mvc, ruby-on-rails, sinatra, bundler, gem, postgresql, redis,
141
+ jwt, oauth, microservices, docker, kubernetes
133
142
 
134
143
  README Preview:
135
- # Awesome Api
144
+ # ๐Ÿ’Ž Awesome Api
136
145
 
137
- A Ruby Rails project for user management with comprehensive
146
+ ๐Ÿš€ A Ruby Rails project for user management with comprehensive
138
147
  API endpoints and authentication.
139
148
 
140
- ## Features
141
- - User authentication and authorization
142
- - RESTful API design
143
- - Database integration
144
- - Comprehensive test coverage
149
+ ## โœจ Features
150
+ - ๐Ÿ› ๏ธ User authentication and authorization
151
+ - ๐ŸŒ RESTful API design
152
+ - ๐Ÿ“Š Database integration
153
+ - โœ… Comprehensive test coverage
145
154
 
146
155
  Create repository? (Y/n) y
147
156
  โœ… Repository created successfully!
@@ -197,16 +206,18 @@ Create a new repository with AI assistance.
197
206
  - `--language LANG` - Primary programming language
198
207
  - `--framework FRAMEWORK` - Framework or library to use
199
208
  - `--description TEXT` - Custom description override
209
+ - `--license LICENSE` - License type (mit, apache-2.0, gpl-3.0, bsd-3-clause, mpl-2.0, unlicense)
200
210
  - `--private` - Create private repository (default: public)
201
- - `--topics TOPIC1,TOPIC2` - Custom topics/tags
211
+ - `--topics TOPIC1,TOPIC2` - Custom topics/tags (up to 20)
202
212
  - `--dry-run` - Preview without creating
203
213
  - `--template URL` - Use repository template
204
214
 
205
215
  **Examples:**
206
216
  ```bash
207
- repose create web-app --language typescript --framework react
208
- repose create microservice --language go --private --dry-run
209
- repose create ml-model --language python --topics ml,ai,data-science
217
+ reposer create web-app --language typescript --framework react
218
+ reposer create microservice --language go --license apache-2.0 --private
219
+ reposer create ml-model --language python --topics ml,ai,data-science --dry-run
220
+ reposer create api-server --language ruby --framework rails --license gpl-3.0
210
221
  ```
211
222
 
212
223
  ### `repose configure`
@@ -472,6 +483,7 @@ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file
472
483
 
473
484
  ## ๐Ÿท๏ธ Version History
474
485
 
486
+ - **v1.2.0** (2025-11-21): Major upgrade with emoji support, 20-topic generation, license selection, and improved GitHub authentication
475
487
  - **v1.1.0** (2025-01-20): Published as `repo-composer` (gem name change), AI provider integration (Gemini + Ollama) with 96.63% test coverage
476
488
  - **v1.0.0** (2025-11-07): Production release with 98.39% test coverage (as `repose`)
477
489
  - **v0.1.0** (2024-11-07): Initial release with core functionality
data/exe/repo-composer ADDED
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ require_relative "../lib/repose"
5
+
6
+ Repose::CLI.start(ARGV)
@@ -121,33 +121,38 @@ module Repose
121
121
 
122
122
  def build_description_prompt(context)
123
123
  <<~PROMPT
124
- Generate a concise, professional GitHub repository description (max 100 characters) for:
124
+ Generate a concise, professional GitHub repository description (max 120 characters) for:
125
125
 
126
126
  Repository name: #{context[:name]}
127
127
  Language: #{context[:language]}
128
128
  Framework: #{context[:framework]}
129
129
  Purpose: #{context[:purpose]}
130
130
 
131
- Return only the description text, no quotes or extra formatting.
131
+ IMPORTANT: Include at least 2 relevant emojis that represent the project's purpose or technology.
132
+ Example format: "๐Ÿš€ Fast API server for data processing ๐Ÿ“Š"
133
+
134
+ Return only the description text with emojis, no quotes or extra formatting.
132
135
  PROMPT
133
136
  end
134
137
 
135
138
  def build_topics_prompt(context)
136
139
  <<~PROMPT
137
- Generate 5-8 relevant GitHub topics (keywords) for this repository:
140
+ Generate 20 relevant GitHub topics (keywords) for this repository:
138
141
 
139
142
  Repository name: #{context[:name]}
140
143
  Language: #{context[:language]}
141
144
  Framework: #{context[:framework]}
142
145
  Purpose: #{context[:purpose]}
143
146
 
144
- Return topics as comma-separated lowercase words (e.g., javascript, react, api, nodejs).
145
- No quotes, no explanations, just the comma-separated list.
147
+ Include topics for: language, framework, use-case, architecture, deployment, testing, best practices.
148
+ Return topics as comma-separated lowercase words (e.g., javascript, react, api, nodejs, docker, ci-cd).
149
+ No quotes, no explanations, just the comma-separated list of 20 topics.
146
150
  PROMPT
147
151
  end
148
152
 
149
153
  def build_readme_prompt(context)
150
154
  title = context[:name].split(/[-_]/).map(&:capitalize).join(" ")
155
+ license = context[:license] || "MIT"
151
156
 
152
157
  <<~PROMPT
153
158
  Generate a comprehensive README.md for a GitHub repository with these details:
@@ -156,17 +161,18 @@ module Repose
156
161
  Language: #{context[:language]}
157
162
  Framework: #{context[:framework]}
158
163
  Purpose: #{context[:purpose]}
164
+ License: #{license}
159
165
 
160
- Include these sections:
161
- - Title and brief description
162
- - Features (3-5 bullet points)
163
- - Installation instructions (language-specific)
164
- - Usage examples with code blocks
165
- - Contributing guidelines
166
- - License (MIT)
166
+ Include these sections with relevant emojis:
167
+ - Title with emoji and brief description with emojis
168
+ - โœจ Features section (3-5 bullet points with emojis)
169
+ - ๐Ÿš€ Installation instructions (language-specific)
170
+ - ๐Ÿ’ป Usage examples with code blocks
171
+ - ๐Ÿค Contributing guidelines
172
+ - ๐Ÿ“„ License (#{license})
167
173
 
168
- Use proper Markdown formatting. Be concise and professional.
169
- Return only the README content, no extra commentary.
174
+ Use proper Markdown formatting with emojis throughout for visual appeal.
175
+ Be concise and professional. Return only the README content, no extra commentary.
170
176
  PROMPT
171
177
  end
172
178
 
@@ -185,8 +191,8 @@ module Repose
185
191
  # Split by commas and clean up
186
192
  topics = text.split(",").map(&:strip).map(&:downcase)
187
193
 
188
- # Remove duplicates and limit to 8
189
- topics.uniq.first(8)
194
+ # Remove duplicates and limit to 20
195
+ topics.uniq.first(20)
190
196
  end
191
197
  end
192
198
  end
@@ -132,32 +132,37 @@ module Repose
132
132
 
133
133
  def build_description_prompt(context)
134
134
  <<~PROMPT
135
- Generate a concise GitHub repository description (max 100 characters) for:
135
+ Generate a concise GitHub repository description (max 120 characters) for:
136
136
 
137
137
  Repository: #{context[:name]}
138
138
  Language: #{context[:language]}
139
139
  Framework: #{context[:framework]}
140
140
  Purpose: #{context[:purpose]}
141
141
 
142
- Return ONLY the description text with no quotes or formatting.
142
+ IMPORTANT: Include at least 2 relevant emojis that represent the project.
143
+ Example: "๐Ÿš€ Fast API server for data processing ๐Ÿ“Š"
144
+
145
+ Return ONLY the description text with emojis, no quotes or formatting.
143
146
  PROMPT
144
147
  end
145
148
 
146
149
  def build_topics_prompt(context)
147
150
  <<~PROMPT
148
- Generate 5-8 GitHub topics for:
151
+ Generate 20 GitHub topics for:
149
152
 
150
153
  Repository: #{context[:name]}
151
154
  Language: #{context[:language]}
152
155
  Framework: #{context[:framework]}
153
156
  Purpose: #{context[:purpose]}
154
157
 
155
- Return ONLY comma-separated lowercase keywords (e.g., python, api, docker, cli).
158
+ Include topics for: language, framework, use-case, architecture, deployment, testing.
159
+ Return ONLY comma-separated lowercase keywords (e.g., python, api, docker, cli, testing, ci-cd).
156
160
  PROMPT
157
161
  end
158
162
 
159
163
  def build_readme_prompt(context)
160
164
  title = context[:name].split(/[-_]/).map(&:capitalize).join(" ")
165
+ license = context[:license] || "MIT"
161
166
 
162
167
  <<~PROMPT
163
168
  Create a GitHub README.md for:
@@ -166,17 +171,18 @@ module Repose
166
171
  Language: #{context[:language]}
167
172
  Framework: #{context[:framework]}
168
173
  Purpose: #{context[:purpose]}
174
+ License: #{license}
169
175
 
170
- Include:
171
- - Title (# #{title})
172
- - Brief description
173
- - Features (3-5 bullet points)
174
- - Installation (#{context[:language]}-specific commands)
175
- - Usage with code examples
176
- - Contributing
177
- - MIT License
176
+ Include sections with emojis:
177
+ - Title with emoji (# ๐Ÿš€ #{title})
178
+ - Brief description with emojis
179
+ - โœจ Features (3-5 bullet points with emojis)
180
+ - ๐Ÿš€ Installation (#{context[:language]}-specific commands)
181
+ - ๐Ÿ’ป Usage with code examples
182
+ - ๐Ÿค Contributing
183
+ - ๐Ÿ“„ License (#{license})
178
184
 
179
- Use proper Markdown. Return ONLY the README content.
185
+ Use proper Markdown with emojis. Return ONLY the README content.
180
186
  PROMPT
181
187
  end
182
188
 
@@ -196,8 +202,8 @@ module Repose
196
202
  # Extract comma-separated values
197
203
  topics = text.split(",").map(&:strip).map(&:downcase)
198
204
 
199
- # Remove duplicates, filter out empty, limit to 8
200
- topics.reject(&:empty?).uniq.first(8)
205
+ # Remove duplicates, filter out empty, limit to 20
206
+ topics.reject(&:empty?).uniq.first(20)
201
207
  end
202
208
  end
203
209
  end
@@ -16,7 +16,10 @@ module Repose
16
16
  name: context[:name],
17
17
  description: generate_description(context),
18
18
  topics: generate_topics(context),
19
- readme: generate_readme(context)
19
+ readme: generate_readme(context),
20
+ license: context[:license],
21
+ language: context[:language],
22
+ framework: context[:framework]
20
23
  }
21
24
  end
22
25
 
@@ -93,40 +96,84 @@ module Repose
93
96
  end
94
97
 
95
98
  def generate_fallback_description(context)
96
- # Fallback description generation without AI
97
- base_desc = "A #{context[:language]}"
99
+ # Fallback description generation without AI - with emojis
100
+ emoji = select_emoji_for_language(context[:language])
101
+ purpose_emoji = select_emoji_for_purpose(context[:purpose])
102
+
103
+ base_desc = "#{emoji} A #{context[:language]}"
98
104
  base_desc += " #{context[:framework]}" if context[:framework]
99
105
  base_desc += " project"
100
106
  base_desc += " for #{context[:purpose]}" if context[:purpose] && !context[:purpose].empty?
107
+ base_desc += " #{purpose_emoji}" if purpose_emoji
101
108
 
102
109
  base_desc.capitalize
103
110
  end
104
111
 
105
112
  def generate_fallback_topics(context)
106
- # Basic topic generation without AI
113
+ # Enhanced topic generation without AI - generate up to 20 relevant topics
107
114
  topics = []
108
115
  topics << context[:language].downcase if context[:language]
109
116
  topics << context[:framework].downcase if context[:framework]
110
117
 
111
- # Add some common topics based on name patterns
118
+ # Language ecosystem topics
119
+ language_topics = language_ecosystem_topics(context[:language])
120
+ topics.concat(language_topics)
121
+
122
+ # Framework-specific topics
123
+ if context[:framework]
124
+ framework_topics = framework_related_topics(context[:framework])
125
+ topics.concat(framework_topics)
126
+ end
127
+
128
+ # Add topics based on name patterns
112
129
  name_lower = context[:name].downcase
113
130
  topics << "api" if name_lower.include?("api")
114
- topics << "web" if name_lower.include?("web") || context[:framework]&.downcase&.include?("rails")
131
+ topics << "rest" if name_lower.include?("api") || name_lower.include?("rest")
132
+ topics << "graphql" if name_lower.include?("graphql")
133
+ topics << "web" if name_lower.include?("web") || context[:framework]&.downcase&.match?(/(rails|django|flask|express)/)
115
134
  topics << "cli" if name_lower.include?("cli") || name_lower.include?("command")
116
135
  topics << "tool" if name_lower.include?("tool") || name_lower.include?("util")
136
+ topics << "library" if name_lower.include?("lib")
137
+ topics << "microservice" if name_lower.include?("micro") || name_lower.include?("service")
138
+ topics << "automation" if name_lower.include?("auto") || name_lower.include?("script")
139
+ topics << "devops" if name_lower.include?("devops") || name_lower.include?("deploy")
140
+ topics << "docker" if name_lower.include?("docker") || name_lower.include?("container")
141
+ topics << "kubernetes" if name_lower.include?("k8s") || name_lower.include?("kube")
142
+
143
+ # Purpose-based topics
144
+ if context[:purpose]
145
+ purpose_lower = context[:purpose].downcase
146
+ topics << "ai" if purpose_lower.match?(/(ai|artificial|intelligence|ml|machine|learning)/)
147
+ topics << "data" if purpose_lower.match?(/(data|analytics|etl)/)
148
+ topics << "testing" if purpose_lower.match?(/(test|qa|quality)/)
149
+ topics << "monitoring" if purpose_lower.match?(/(monitor|observ|metric)/)
150
+ topics << "security" if purpose_lower.match?(/(secur|auth|encrypt)/)
151
+ end
152
+
153
+ # General best practice topics
154
+ topics.concat(["opensource", "development", "best-practices"])
117
155
 
118
- topics.uniq.first(8)
156
+ topics.uniq.first(20)
119
157
  end
120
158
 
121
159
  def generate_fallback_readme(context)
122
160
  title = context[:name].split(/[-_]/).map(&:capitalize).join(" ")
161
+ emoji = select_emoji_for_language(context[:language])
162
+ license = context[:license] || "MIT"
123
163
 
124
164
  <<~README
125
- # #{title}
165
+ # #{emoji} #{title}
126
166
 
127
- A #{context[:language]} #{context[:framework] ? "#{context[:framework]} " : ""}project#{context[:purpose] && !context[:purpose].empty? ? " for #{context[:purpose]}" : ""}.
167
+ ๐Ÿš€ A #{context[:language]} #{context[:framework] ? "#{context[:framework]} " : ""}project#{context[:purpose] && !context[:purpose].empty? ? " for #{context[:purpose]}" : ""}.
128
168
 
129
- ## Installation
169
+ ## โœจ Features
170
+
171
+ - ๐Ÿ› ๏ธ Modern #{context[:language]} development
172
+ #{context[:framework] ? "- ๐Ÿ›๏ธ Built with #{context[:framework]}" : ""}
173
+ - ๐Ÿ“š Comprehensive documentation
174
+ - โœ… Production-ready code
175
+
176
+ ## ๐Ÿš€ Installation
130
177
 
131
178
  ```bash
132
179
  git clone https://github.com/yourusername/#{context[:name]}.git
@@ -135,20 +182,20 @@ module Repose
135
182
 
136
183
  #{language_specific_install_instructions(context[:language])}
137
184
 
138
- ## Usage
185
+ ## ๐Ÿ’ป Usage
139
186
 
140
187
  More documentation coming soon!
141
188
 
142
- ## Contributing
189
+ ## ๐Ÿค Contributing
143
190
 
144
191
  1. Fork the repository
145
192
  2. Create a feature branch
146
193
  3. Make your changes
147
194
  4. Submit a pull request
148
195
 
149
- ## License
196
+ ## ๐Ÿ“„ License
150
197
 
151
- This project is licensed under the MIT License.
198
+ This project is licensed under the #{license} License.
152
199
  README
153
200
  end
154
201
 
@@ -168,5 +215,92 @@ module Repose
168
215
  ""
169
216
  end
170
217
  end
218
+
219
+ def select_emoji_for_language(language)
220
+ emojis = {
221
+ "ruby" => "๐Ÿ’Ž",
222
+ "python" => "๐Ÿ",
223
+ "javascript" => "โšก",
224
+ "typescript" => "๐Ÿ“˜",
225
+ "go" => "๐Ÿš€",
226
+ "rust" => "๐Ÿฆ€",
227
+ "java" => "โ˜•",
228
+ "kotlin" => "๐ŸŽฏ",
229
+ "swift" => "๐ŸŽ",
230
+ "php" => "๐Ÿ˜",
231
+ "c" => "โš™๏ธ",
232
+ "c++" => "โš™๏ธ",
233
+ "c#" => "๐Ÿ’ ",
234
+ "scala" => "๐ŸŽธ",
235
+ "mojo" => "๐Ÿ”ฅ"
236
+ }
237
+ emojis[language&.downcase] || "๐Ÿš€"
238
+ end
239
+
240
+ def select_emoji_for_purpose(purpose)
241
+ return nil unless purpose && !purpose.empty?
242
+
243
+ purpose_lower = purpose.downcase
244
+ if purpose_lower.match?(/(api|rest|graphql)/)
245
+ "๐ŸŒ"
246
+ elsif purpose_lower.match?(/(data|analytics|etl)/)
247
+ "๐Ÿ“Š"
248
+ elsif purpose_lower.match?(/(ai|ml|machine|learning)/)
249
+ "๐Ÿค–"
250
+ elsif purpose_lower.match?(/(web|website|frontend)/)
251
+ "๐ŸŽจ"
252
+ elsif purpose_lower.match?(/(cli|command|terminal)/)
253
+ "๐Ÿ’ป"
254
+ elsif purpose_lower.match?(/(test|testing|qa)/)
255
+ "โœ…"
256
+ elsif purpose_lower.match?(/(deploy|devops|automation)/)
257
+ "โš™๏ธ"
258
+ elsif purpose_lower.match?(/(monitor|observ|metric)/)
259
+ "๐Ÿ“ˆ"
260
+ elsif purpose_lower.match?(/(secur|auth|encrypt)/)
261
+ "๐Ÿ”"
262
+ elsif purpose_lower.match?(/(game|gaming)/)
263
+ "๐ŸŽฎ"
264
+ elsif purpose_lower.match?(/(chat|message|communication)/)
265
+ "๐Ÿ’ฌ"
266
+ else
267
+ "โœจ"
268
+ end
269
+ end
270
+
271
+ def language_ecosystem_topics(language)
272
+ topics_map = {
273
+ "ruby" => ["gem", "bundler", "rails", "ruby-on-rails"],
274
+ "python" => ["pip", "pypi", "django", "flask"],
275
+ "javascript" => ["npm", "nodejs", "webpack", "babel"],
276
+ "typescript" => ["npm", "nodejs", "webpack", "types"],
277
+ "go" => ["golang", "modules", "concurrent"],
278
+ "rust" => ["cargo", "crates", "systems-programming"],
279
+ "java" => ["maven", "gradle", "jvm", "spring"],
280
+ "kotlin" => ["gradle", "jvm", "android"],
281
+ "swift" => ["cocoapods", "spm", "ios"],
282
+ "php" => ["composer", "laravel", "symfony"],
283
+ "c#" => ["dotnet", "nuget", "asp-net"],
284
+ "scala" => ["sbt", "jvm", "functional"]
285
+ }
286
+ topics_map[language&.downcase] || []
287
+ end
288
+
289
+ def framework_related_topics(framework)
290
+ framework_lower = framework&.downcase
291
+ topics = []
292
+
293
+ # Web frameworks
294
+ topics.concat(["web", "mvc", "backend"]) if framework_lower&.match?(/(rails|django|flask|express|spring)/)
295
+ topics.concat(["web", "frontend", "spa"]) if framework_lower&.match?(/(react|vue|angular)/)
296
+
297
+ # API frameworks
298
+ topics.concat(["api", "rest", "microservices"]) if framework_lower&.match?(/(fastapi|gin|echo|actix)/)
299
+
300
+ # Full-stack frameworks
301
+ topics.concat(["fullstack", "ssr"]) if framework_lower&.match?(/(next|nuxt)/)
302
+
303
+ topics
304
+ end
171
305
  end
172
306
  end
data/lib/repose/cli.rb CHANGED
@@ -20,6 +20,7 @@ module Repose
20
20
  Examples:
21
21
  $ repose create my-awesome-project
22
22
  $ repose create web-scraper --language ruby --framework rails
23
+ $ repose create api-server --license apache-2.0
23
24
  DESC
24
25
  option :language, type: :string, desc: "Primary programming language"
25
26
  option :framework, type: :string, desc: "Framework or library to use"
@@ -27,6 +28,7 @@ module Repose
27
28
  option :private, type: :boolean, default: false, desc: "Create private repository"
28
29
  option :template, type: :string, desc: "Repository template to use"
29
30
  option :topics, type: :array, desc: "Custom topics/tags"
31
+ option :license, type: :string, desc: "License type (mit, apache-2.0, gpl-3.0, bsd-3-clause, unlicense, etc.)"
30
32
  option :dry_run, type: :boolean, default: false, desc: "Preview without creating"
31
33
  def create(name = nil)
32
34
  pastel = Pastel.new
@@ -102,12 +104,13 @@ module Repose
102
104
  language: options[:language],
103
105
  framework: options[:framework],
104
106
  description: options[:description],
105
- topics: options[:topics] || []
107
+ topics: options[:topics] || [],
108
+ license: options[:license]
106
109
  }
107
110
 
108
111
  # Interactive prompts for missing context
109
112
  unless context[:language]
110
- languages = %w[c c++ c# go java javascript kotlin mojo php python ruby rust scala typescript]
113
+ languages = %w[c c++ c# go java javascript kotlin mojo php python ruby rust scala swift typescript]
111
114
  context[:language] = prompt.select("Primary programming language:", languages, per_page: 14)
112
115
  end
113
116
 
@@ -119,6 +122,24 @@ module Repose
119
122
  end
120
123
  end
121
124
 
125
+ # License selection
126
+ unless context[:license]
127
+ licenses = [
128
+ { name: "MIT License (Permissive, most popular)", value: "mit" },
129
+ { name: "Apache 2.0 (Permissive with patent grant)", value: "apache-2.0" },
130
+ { name: "GPL 3.0 (Copyleft, strong)", value: "gpl-3.0" },
131
+ { name: "BSD 3-Clause (Permissive)", value: "bsd-3-clause" },
132
+ { name: "Mozilla Public License 2.0", value: "mpl-2.0" },
133
+ { name: "Unlicense (Public Domain)", value: "unlicense" },
134
+ { name: "Other/Custom", value: "other" }
135
+ ]
136
+ context[:license] = prompt.select("Choose a license:", licenses)
137
+
138
+ if context[:license] == "other"
139
+ context[:license] = prompt.ask("Enter license name:", default: "MIT")
140
+ end
141
+ end
142
+
122
143
  # Additional context
123
144
  context[:purpose] = prompt.ask("What will this project do? (optional):")
124
145
 
@@ -134,7 +155,13 @@ module Repose
134
155
  "java" => ["Spring Boot", "Quarkus", "Micronaut"],
135
156
  "go" => ["Gin", "Echo", "Fiber", "Chi"],
136
157
  "rust" => ["Actix", "Axum", "Warp", "Rocket"],
137
- "swift" => ["Vapor", "Perfect", "Kitura"]
158
+ "swift" => ["Vapor", "Perfect", "Kitura"],
159
+ "php" => ["Laravel", "Symfony", "CodeIgniter", "CakePHP"],
160
+ "c#" => [".NET Core", "ASP.NET", "Blazor"],
161
+ "c++" => ["Qt", "Boost", "Poco"],
162
+ "c" => ["GTK", "libuv", "SDL2"],
163
+ "scala" => ["Play", "Akka", "Lagom"],
164
+ "kotlin" => ["Ktor", "Spring Boot", "Micronaut"]
138
165
  }
139
166
 
140
167
  frameworks[language] || []
@@ -146,6 +173,7 @@ module Repose
146
173
 
147
174
  puts pastel.bold("Name: ") + content[:name]
148
175
  puts pastel.bold("Description: ") + content[:description]
176
+ puts pastel.bold("License: ") + (content[:license] || "MIT").upcase
149
177
  puts pastel.bold("Topics: ") + content[:topics].join(", ")
150
178
 
151
179
  puts "\n" + pastel.bold("README Preview:")
@@ -164,10 +192,35 @@ module Repose
164
192
  description: content[:description],
165
193
  private: options[:private],
166
194
  topics: content[:topics],
167
- readme: content[:readme]
195
+ readme: content[:readme],
196
+ license: content[:license]
168
197
  )
169
198
 
170
199
  spinner.success("โœ…")
200
+
201
+ # Create language-specific project files
202
+ project_files = ProjectFilesGenerator.generate(
203
+ language: content[:language],
204
+ framework: content[:framework],
205
+ name: name
206
+ )
207
+
208
+ if project_files.any?
209
+ file_spinner = TTY::Spinner.new("[:spinner] Adding project files...", format: :dots)
210
+ file_spinner.auto_spin
211
+
212
+ project_files.each do |file_path, file_content|
213
+ github_client.create_file(
214
+ repo.full_name,
215
+ file_path,
216
+ "Add #{file_path}",
217
+ file_content
218
+ )
219
+ end
220
+
221
+ file_spinner.success("โœ…")
222
+ end
223
+
171
224
  puts pastel.green("Repository created successfully!")
172
225
  puts pastel.cyan("๐Ÿ”— #{repo.html_url}")
173
226
  rescue => e
@@ -5,20 +5,35 @@ require "octokit"
5
5
  module Repose
6
6
  class GitHubClient
7
7
  def initialize
8
- @client = Octokit::Client.new(access_token: Repose.config.github_token)
8
+ token = Repose.config.github_token || ENV["GITHUB_TOKEN"]
9
+
10
+ raise Errors::ConfigurationError, "GitHub token not configured. Set GITHUB_TOKEN environment variable or run 'repose configure'" if token.nil? || token.empty?
11
+
12
+ @client = Octokit::Client.new(access_token: token)
13
+ @client.auto_paginate = true
9
14
  end
10
15
 
11
- def create_repository(name:, description:, private: false, topics: [], readme: nil)
12
- # Create the repository
13
- repo = @client.create_repository(name, {
16
+ def create_repository(name:, description:, private: false, topics: [], readme: nil, license: nil)
17
+ # Create the repository with license template if specified
18
+ repo_options = {
14
19
  description: description,
15
20
  private: private,
16
- auto_init: false # We'll create our own README
17
- })
21
+ auto_init: false, # We'll create our own README
22
+ has_issues: true,
23
+ has_wiki: true,
24
+ has_projects: true
25
+ }
26
+
27
+ # Add license template if specified
28
+ if license && !license.empty?
29
+ repo_options[:license_template] = normalize_license_key(license)
30
+ end
31
+
32
+ repo = @client.create_repository(name, repo_options)
18
33
 
19
34
  # Add topics if provided
20
35
  if topics.any?
21
- @client.replace_all_topics(repo.full_name, topics.map(&:downcase))
36
+ @client.replace_all_topics(repo.full_name, topics.map(&:downcase).uniq)
22
37
  end
23
38
 
24
39
  # Create README if provided
@@ -26,27 +41,71 @@ module Repose
26
41
  @client.create_contents(
27
42
  repo.full_name,
28
43
  "README.md",
29
- "Initial README",
44
+ "Initial commit: Add README",
30
45
  readme,
31
- branch: repo.default_branch
46
+ branch: repo.default_branch || "main"
32
47
  )
33
48
  end
34
49
 
35
50
  repo
51
+ rescue Octokit::Unauthorized => e
52
+ raise Errors::AuthenticationError, "GitHub authentication failed. Check your token permissions: #{e.message}"
53
+ rescue Octokit::UnprocessableEntity => e
54
+ raise Errors::GitHubError, "Repository creation failed (repository may already exist): #{e.message}"
36
55
  rescue Octokit::Error => e
37
56
  raise Errors::GitHubError, "GitHub API error: #{e.message}"
38
57
  end
39
58
 
40
59
  def repository_exists?(name)
41
- @client.repository?("#{@client.user.login}/#{name}")
60
+ username = @client.user.login
61
+ @client.repository?("#{username}/#{name}")
42
62
  rescue Octokit::NotFound
43
63
  false
64
+ rescue Octokit::Unauthorized => e
65
+ raise Errors::AuthenticationError, "GitHub authentication failed: #{e.message}"
44
66
  end
45
67
 
46
68
  def user_info
47
69
  @client.user
70
+ rescue Octokit::Unauthorized => e
71
+ raise Errors::AuthenticationError, "Failed to authenticate with GitHub. Check your token: #{e.message}"
48
72
  rescue Octokit::Error => e
49
73
  raise Errors::GitHubError, "Failed to fetch user info: #{e.message}"
50
74
  end
75
+
76
+ def create_file(repo_name, path, message, content)
77
+ @client.create_contents(
78
+ repo_name,
79
+ path,
80
+ message,
81
+ content
82
+ )
83
+ rescue Octokit::UnprocessableEntity => e
84
+ # File might already exist, skip it
85
+ puts "Skipping #{path} (already exists)"
86
+ rescue Octokit::Error => e
87
+ raise Errors::GitHubError, "Failed to create file #{path}: #{e.message}"
88
+ end
89
+
90
+ private
91
+
92
+ def normalize_license_key(license)
93
+ # GitHub API uses specific license keys
94
+ license_map = {
95
+ "mit" => "mit",
96
+ "apache" => "apache-2.0",
97
+ "apache-2.0" => "apache-2.0",
98
+ "gpl" => "gpl-3.0",
99
+ "gpl-3.0" => "gpl-3.0",
100
+ "bsd" => "bsd-3-clause",
101
+ "bsd-3-clause" => "bsd-3-clause",
102
+ "mpl" => "mpl-2.0",
103
+ "mpl-2.0" => "mpl-2.0",
104
+ "unlicense" => "unlicense"
105
+ }
106
+
107
+ normalized = license_map[license.downcase] || license.downcase
108
+ normalized
109
+ end
51
110
  end
52
111
  end
@@ -0,0 +1,418 @@
1
+ require 'json'
2
+
3
+ module Repose
4
+ class ProjectFilesGenerator
5
+ def self.generate(language:, framework:, name:)
6
+ files = {}
7
+
8
+ case language&.downcase
9
+ when 'go', 'golang'
10
+ files.merge!(generate_go_files(name))
11
+ when 'python'
12
+ files.merge!(generate_python_files(framework))
13
+ when 'javascript', 'typescript', 'node.js', 'nodejs'
14
+ files.merge!(generate_javascript_files(name, language))
15
+ when 'ruby'
16
+ files.merge!(generate_ruby_files(framework))
17
+ when 'rust'
18
+ files.merge!(generate_rust_files(name))
19
+ when 'java'
20
+ files.merge!(generate_java_files(name, framework))
21
+ when 'c#', 'csharp', 'dotnet', '.net'
22
+ files.merge!(generate_dotnet_files(name))
23
+ when 'php'
24
+ files.merge!(generate_php_files(framework))
25
+ end
26
+
27
+ files
28
+ end
29
+
30
+ private
31
+
32
+ def self.generate_go_files(name)
33
+ module_path = "github.com/user/#{name}"
34
+
35
+ {
36
+ 'go.mod' => <<~GO_MOD,
37
+ module #{module_path}
38
+
39
+ go 1.21
40
+
41
+ require (
42
+ \t// Add your dependencies here
43
+ )
44
+ GO_MOD
45
+ '.gitignore' => <<~GITIGNORE
46
+ # Binaries for programs and plugins
47
+ *.exe
48
+ *.exe~
49
+ *.dll
50
+ *.so
51
+ *.dylib
52
+
53
+ # Test binary, built with `go test -c`
54
+ *.test
55
+
56
+ # Output of the go coverage tool
57
+ *.out
58
+
59
+ # Dependency directories
60
+ vendor/
61
+
62
+ # Go workspace file
63
+ go.work
64
+ GITIGNORE
65
+ }
66
+ end
67
+
68
+ def self.generate_python_files(framework)
69
+ files = {
70
+ 'requirements.txt' => <<~REQUIREMENTS,
71
+ # Add your dependencies here
72
+ # Example:
73
+ # requests>=2.31.0
74
+ # flask>=3.0.0
75
+ REQUIREMENTS
76
+ '.gitignore' => <<~GITIGNORE
77
+ # Byte-compiled / optimized / DLL files
78
+ __pycache__/
79
+ *.py[cod]
80
+ *$py.class
81
+
82
+ # Virtual environments
83
+ venv/
84
+ env/
85
+ ENV/
86
+ .venv
87
+
88
+ # Distribution / packaging
89
+ dist/
90
+ build/
91
+ *.egg-info/
92
+
93
+ # IDEs
94
+ .idea/
95
+ .vscode/
96
+ *.swp
97
+ *.swo
98
+
99
+ # Testing
100
+ .pytest_cache/
101
+ .coverage
102
+ htmlcov/
103
+ GITIGNORE
104
+ }
105
+
106
+ if framework&.downcase&.include?('django')
107
+ files['requirements.txt'] = "django>=4.2.0\ndjango-environ>=0.11.0\npsycopg2-binary>=2.9.0\n"
108
+ elsif framework&.downcase&.include?('flask')
109
+ files['requirements.txt'] = "flask>=3.0.0\nflask-cors>=4.0.0\npython-dotenv>=1.0.0\n"
110
+ elsif framework&.downcase&.include?('fastapi')
111
+ files['requirements.txt'] = "fastapi>=0.104.0\nuvicorn[standard]>=0.24.0\npydantic>=2.5.0\n"
112
+ end
113
+
114
+ files
115
+ end
116
+
117
+ def self.generate_javascript_files(name, language)
118
+ is_typescript = language&.downcase&.include?('typescript')
119
+
120
+ package_json = {
121
+ name: name,
122
+ version: '1.0.0',
123
+ description: '',
124
+ main: is_typescript ? 'dist/index.js' : 'index.js',
125
+ scripts: {
126
+ test: 'echo "Error: no test specified" && exit 1'
127
+ },
128
+ keywords: [],
129
+ author: '',
130
+ license: 'MIT'
131
+ }
132
+
133
+ if is_typescript
134
+ package_json[:scripts][:build] = 'tsc'
135
+ package_json[:scripts][:dev] = 'ts-node src/index.ts'
136
+ package_json[:devDependencies] = {
137
+ typescript: '^5.3.0',
138
+ '@types/node': '^20.10.0',
139
+ 'ts-node': '^10.9.0'
140
+ }
141
+ end
142
+
143
+ files = {
144
+ 'package.json' => JSON.pretty_generate(package_json),
145
+ '.gitignore' => <<~GITIGNORE
146
+ # Dependencies
147
+ node_modules/
148
+
149
+ # Production
150
+ dist/
151
+ build/
152
+
153
+ # Environment
154
+ .env
155
+ .env.local
156
+
157
+ # Logs
158
+ logs/
159
+ *.log
160
+ npm-debug.log*
161
+
162
+ # IDEs
163
+ .idea/
164
+ .vscode/
165
+ *.swp
166
+
167
+ # OS
168
+ .DS_Store
169
+ Thumbs.db
170
+ GITIGNORE
171
+ }
172
+
173
+ if is_typescript
174
+ files['tsconfig.json'] = JSON.pretty_generate({
175
+ compilerOptions: {
176
+ target: 'ES2020',
177
+ module: 'commonjs',
178
+ lib: ['ES2020'],
179
+ outDir: './dist',
180
+ rootDir: './src',
181
+ strict: true,
182
+ esModuleInterop: true,
183
+ skipLibCheck: true,
184
+ forceConsistentCasingInFileNames: true
185
+ },
186
+ include: ['src/**/*'],
187
+ exclude: ['node_modules']
188
+ }, indent: ' ')
189
+ end
190
+
191
+ files
192
+ end
193
+
194
+ def self.generate_ruby_files(framework)
195
+ gemfile = if framework&.downcase&.include?('rails')
196
+ <<~GEMFILE
197
+ source 'https://rubygems.org'
198
+ ruby '~> 3.2'
199
+
200
+ gem 'rails', '~> 7.1'
201
+ gem 'pg', '~> 1.5'
202
+ gem 'puma', '~> 6.0'
203
+
204
+ group :development, :test do
205
+ gem 'rspec-rails'
206
+ gem 'rubocop'
207
+ end
208
+ GEMFILE
209
+ elsif framework&.downcase&.include?('sinatra')
210
+ <<~GEMFILE
211
+ source 'https://rubygems.org'
212
+ ruby '~> 3.2'
213
+
214
+ gem 'sinatra', '~> 3.1'
215
+ gem 'sinatra-contrib', '~> 3.1'
216
+ gem 'puma', '~> 6.0'
217
+
218
+ group :development, :test do
219
+ gem 'rspec'
220
+ gem 'rack-test'
221
+ gem 'rubocop'
222
+ end
223
+ GEMFILE
224
+ else
225
+ <<~GEMFILE
226
+ source 'https://rubygems.org'
227
+ ruby '~> 3.2'
228
+
229
+ # Add your dependencies here
230
+
231
+ group :development, :test do
232
+ gem 'rspec'
233
+ gem 'rubocop'
234
+ end
235
+ GEMFILE
236
+ end
237
+
238
+ {
239
+ 'Gemfile' => gemfile,
240
+ '.gitignore' => <<~GITIGNORE
241
+ # Bundler
242
+ .bundle/
243
+ vendor/bundle/
244
+
245
+ # Logs
246
+ log/*.log
247
+ tmp/
248
+
249
+ # Database
250
+ *.sqlite3
251
+ *.db
252
+
253
+ # Environment
254
+ .env
255
+ .env.local
256
+
257
+ # IDEs
258
+ .idea/
259
+ .vscode/
260
+ *.swp
261
+ GITIGNORE
262
+ }
263
+ end
264
+
265
+ def self.generate_rust_files(name)
266
+ {
267
+ 'Cargo.toml' => <<~CARGO_TOML,
268
+ [package]
269
+ name = "#{name.tr('-', '_')}"
270
+ version = "0.1.0"
271
+ edition = "2021"
272
+
273
+ [dependencies]
274
+ # Add your dependencies here
275
+ CARGO_TOML
276
+ '.gitignore' => <<~GITIGNORE
277
+ # Build output
278
+ /target/
279
+ Cargo.lock
280
+
281
+ # IDE
282
+ .idea/
283
+ .vscode/
284
+ *.swp
285
+ GITIGNORE
286
+ }
287
+ end
288
+
289
+ def self.generate_java_files(name, framework)
290
+ files = {
291
+ '.gitignore' => <<~GITIGNORE
292
+ # Compiled class files
293
+ *.class
294
+ target/
295
+ out/
296
+
297
+ # Package files
298
+ *.jar
299
+ *.war
300
+ *.ear
301
+
302
+ # IDE
303
+ .idea/
304
+ .vscode/
305
+ *.iml
306
+ .project
307
+ .classpath
308
+ .settings/
309
+
310
+ # Build tools
311
+ .gradle/
312
+ build/
313
+ GITIGNORE
314
+ }
315
+
316
+ if framework&.downcase&.include?('spring')
317
+ files['pom.xml'] = <<~POM_XML
318
+ <?xml version="1.0" encoding="UTF-8"?>
319
+ <project xmlns="http://maven.apache.org/POM/4.0.0"
320
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
321
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0
322
+ http://maven.apache.org/xsd/maven-4.0.0.xsd">
323
+ <modelVersion>4.0.0</modelVersion>
324
+
325
+ <groupId>com.example</groupId>
326
+ <artifactId>#{name}</artifactId>
327
+ <version>0.1.0</version>
328
+
329
+ <parent>
330
+ <groupId>org.springframework.boot</groupId>
331
+ <artifactId>spring-boot-starter-parent</artifactId>
332
+ <version>3.2.0</version>
333
+ </parent>
334
+
335
+ <dependencies>
336
+ <dependency>
337
+ <groupId>org.springframework.boot</groupId>
338
+ <artifactId>spring-boot-starter-web</artifactId>
339
+ </dependency>
340
+ </dependencies>
341
+ </project>
342
+ POM_XML
343
+ end
344
+
345
+ files
346
+ end
347
+
348
+ def self.generate_dotnet_files(name)
349
+ {
350
+ '.gitignore' => <<~GITIGNORE
351
+ # Build output
352
+ bin/
353
+ obj/
354
+
355
+ # User-specific files
356
+ *.suo
357
+ *.user
358
+ *.userosscache
359
+ *.sln.docstates
360
+
361
+ # NuGet
362
+ *.nupkg
363
+ *.snupkg
364
+ packages/
365
+
366
+ # IDE
367
+ .vs/
368
+ .vscode/
369
+ GITIGNORE
370
+ }
371
+ end
372
+
373
+ def self.generate_php_files(framework)
374
+ composer_json = {
375
+ name: 'vendor/package',
376
+ description: '',
377
+ type: 'project',
378
+ require: {
379
+ 'php': '>=8.1'
380
+ },
381
+ 'require-dev': {
382
+ 'phpunit/phpunit': '^10.0'
383
+ },
384
+ autoload: {
385
+ 'psr-4': {
386
+ 'App\\': 'src/'
387
+ }
388
+ }
389
+ }
390
+
391
+ if framework&.downcase&.include?('laravel')
392
+ composer_json[:require]['laravel/framework'] = '^10.0'
393
+ elsif framework&.downcase&.include?('symfony')
394
+ composer_json[:require]['symfony/framework-bundle'] = '^6.4'
395
+ end
396
+
397
+ {
398
+ 'composer.json' => JSON.pretty_generate(composer_json, indent: ' '),
399
+ '.gitignore' => <<~GITIGNORE
400
+ # Dependencies
401
+ /vendor/
402
+
403
+ # Environment
404
+ .env
405
+ .env.local
406
+
407
+ # Logs
408
+ *.log
409
+
410
+ # IDE
411
+ .idea/
412
+ .vscode/
413
+ *.swp
414
+ GITIGNORE
415
+ }
416
+ end
417
+ end
418
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Repose
4
- VERSION = "1.1.1"
4
+ VERSION = "1.3.0"
5
5
  end
data/lib/repose.rb CHANGED
@@ -6,6 +6,7 @@ require_relative "repose/github_client"
6
6
  require_relative "repose/ai_generator"
7
7
  require_relative "repose/config"
8
8
  require_relative "repose/errors"
9
+ require_relative "repose/project_files_generator"
9
10
 
10
11
  module Repose
11
12
  class << self
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reposer
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.1.1
4
+ version: 1.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wesley Scholl
@@ -144,6 +144,7 @@ files:
144
144
  - demo.rb
145
145
  - demo_ai_providers.rb
146
146
  - demo_interactive.rb
147
+ - exe/repo-composer
147
148
  - exe/repose
148
149
  - exe/reposer
149
150
  - lib/repose.rb
@@ -154,6 +155,7 @@ files:
154
155
  - lib/repose/config.rb
155
156
  - lib/repose/errors.rb
156
157
  - lib/repose/github_client.rb
158
+ - lib/repose/project_files_generator.rb
157
159
  - lib/repose/version.rb
158
160
  - recreate_repo.rb
159
161
  - setup_github_repo.rb