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 +4 -4
- data/CHANGELOG.md +53 -0
- data/Gemfile.lock +1 -1
- data/README.md +32 -20
- data/exe/repo-composer +6 -0
- data/lib/repose/ai/gemini_provider.rb +22 -16
- data/lib/repose/ai/ollama_provider.rb +21 -15
- data/lib/repose/ai_generator.rb +148 -14
- data/lib/repose/cli.rb +57 -4
- data/lib/repose/github_client.rb +69 -10
- data/lib/repose/project_files_generator.rb +418 -0
- data/lib/repose/version.rb +1 -1
- data/lib/repose.rb +1 -0
- metadata +3 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: f0dac6cfdb3aabf4d7ac21336a8418b2ccc4d5915f461741d5fda5d2e1c3249e
|
|
4
|
+
data.tar.gz: 40af3f7d39bf3d483c8746f94a6f8cc2dc458cd828aaa0c915f19feaea6bd208
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
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
|
|
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
|
-
- **๐งช
|
|
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
|
|
132
|
-
Topics: ruby, rails, api, web,
|
|
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
|
-
|
|
208
|
-
|
|
209
|
-
|
|
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
|
@@ -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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
145
|
-
|
|
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 (
|
|
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
|
|
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
|
|
189
|
-
topics.uniq.first(
|
|
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
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
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
|
-
-
|
|
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
|
|
200
|
-
topics.reject(&:empty?).uniq.first(
|
|
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
|
data/lib/repose/ai_generator.rb
CHANGED
|
@@ -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
|
-
|
|
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
|
-
#
|
|
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
|
-
#
|
|
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 << "
|
|
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(
|
|
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
|
-
##
|
|
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
|
|
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
|
data/lib/repose/github_client.rb
CHANGED
|
@@ -5,20 +5,35 @@ require "octokit"
|
|
|
5
5
|
module Repose
|
|
6
6
|
class GitHubClient
|
|
7
7
|
def initialize
|
|
8
|
-
|
|
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
|
-
|
|
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.
|
|
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
|
data/lib/repose/version.rb
CHANGED
data/lib/repose.rb
CHANGED
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.
|
|
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
|