lex-codegen 0.1.1
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 +7 -0
- data/.github/workflows/ci.yml +16 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +62 -0
- data/CHANGELOG.md +6 -0
- data/CLAUDE.md +209 -0
- data/Gemfile +13 -0
- data/LICENSE +21 -0
- data/README.md +173 -0
- data/lex-codegen.gemspec +37 -0
- data/lib/legion/extensions/codegen/client.rb +17 -0
- data/lib/legion/extensions/codegen/helpers/constants.rb +304 -0
- data/lib/legion/extensions/codegen/helpers/file_writer.rb +28 -0
- data/lib/legion/extensions/codegen/helpers/spec_generator.rb +112 -0
- data/lib/legion/extensions/codegen/helpers/template_engine.rb +39 -0
- data/lib/legion/extensions/codegen/runners/generate.rb +142 -0
- data/lib/legion/extensions/codegen/runners/template.rb +48 -0
- data/lib/legion/extensions/codegen/runners/validate.rb +123 -0
- data/lib/legion/extensions/codegen/version.rb +9 -0
- data/lib/legion/extensions/codegen.rb +20 -0
- metadata +164 -0
checksums.yaml
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
---
|
|
2
|
+
SHA256:
|
|
3
|
+
metadata.gz: 410e07dba313fed006a63a77643c2cdf1e03dbe41c17f895725ceb710f10f8fb
|
|
4
|
+
data.tar.gz: 45a9d37de9308cdfc113b3b83d0bd222b1f5879198d01fd8b8b152fbfafa83e0
|
|
5
|
+
SHA512:
|
|
6
|
+
metadata.gz: f57fbf2f6f9f899ee3cadf673ba72f5c47b58de1ad789a560aa1aaca9dedc314d9d5991f9af795ea58075c38ed6b9dc135df6ada5677de35dcd2c0add19a8972
|
|
7
|
+
data.tar.gz: 63a20b03008b9e1442b44170725615a3757222816c9ed983d33d88e6106c8a36c1d7ae3903a55e2588afaa3d1f0a5422ce19c274830843dfca4744b5bd1a273d
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push:
|
|
4
|
+
branches: [main]
|
|
5
|
+
pull_request:
|
|
6
|
+
|
|
7
|
+
jobs:
|
|
8
|
+
ci:
|
|
9
|
+
uses: LegionIO/.github/.github/workflows/ci.yml@main
|
|
10
|
+
|
|
11
|
+
release:
|
|
12
|
+
needs: ci
|
|
13
|
+
if: github.event_name == 'push' && github.ref == 'refs/heads/main'
|
|
14
|
+
uses: LegionIO/.github/.github/workflows/release.yml@main
|
|
15
|
+
secrets:
|
|
16
|
+
rubygems-api-key: ${{ secrets.RUBYGEMS_API_KEY }}
|
data/.gitignore
ADDED
data/.rspec
ADDED
data/.rubocop.yml
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
AllCops:
|
|
2
|
+
TargetRubyVersion: 3.4
|
|
3
|
+
NewCops: enable
|
|
4
|
+
SuggestExtensions: false
|
|
5
|
+
|
|
6
|
+
Layout/LineLength:
|
|
7
|
+
Max: 160
|
|
8
|
+
|
|
9
|
+
Layout/SpaceAroundEqualsInParameterDefault:
|
|
10
|
+
EnforcedStyle: space
|
|
11
|
+
|
|
12
|
+
Layout/HashAlignment:
|
|
13
|
+
EnforcedHashRocketStyle: table
|
|
14
|
+
EnforcedColonStyle: table
|
|
15
|
+
|
|
16
|
+
Metrics/MethodLength:
|
|
17
|
+
Max: 50
|
|
18
|
+
|
|
19
|
+
Metrics/ClassLength:
|
|
20
|
+
Max: 1500
|
|
21
|
+
|
|
22
|
+
Metrics/ModuleLength:
|
|
23
|
+
Max: 1500
|
|
24
|
+
|
|
25
|
+
Metrics/AbcSize:
|
|
26
|
+
Max: 60
|
|
27
|
+
|
|
28
|
+
Metrics/CyclomaticComplexity:
|
|
29
|
+
Max: 15
|
|
30
|
+
|
|
31
|
+
Metrics/PerceivedComplexity:
|
|
32
|
+
Max: 17
|
|
33
|
+
|
|
34
|
+
Style/Documentation:
|
|
35
|
+
Enabled: false
|
|
36
|
+
|
|
37
|
+
Style/SymbolArray:
|
|
38
|
+
Enabled: true
|
|
39
|
+
|
|
40
|
+
Style/FrozenStringLiteralComment:
|
|
41
|
+
Enabled: true
|
|
42
|
+
EnforcedStyle: always
|
|
43
|
+
|
|
44
|
+
Naming/FileName:
|
|
45
|
+
Enabled: false
|
|
46
|
+
|
|
47
|
+
Naming/PredicateMethod:
|
|
48
|
+
Enabled: false
|
|
49
|
+
|
|
50
|
+
Naming/PredicatePrefix:
|
|
51
|
+
Enabled: false
|
|
52
|
+
|
|
53
|
+
Gemspec/DevelopmentDependencies:
|
|
54
|
+
Enabled: false
|
|
55
|
+
|
|
56
|
+
Metrics/ParameterLists:
|
|
57
|
+
Enabled: false
|
|
58
|
+
|
|
59
|
+
Metrics/BlockLength:
|
|
60
|
+
Max: 40
|
|
61
|
+
Exclude:
|
|
62
|
+
- 'spec/**/*'
|
data/CHANGELOG.md
ADDED
data/CLAUDE.md
ADDED
|
@@ -0,0 +1,209 @@
|
|
|
1
|
+
# lex-codegen: Code Generation Engine for LegionIO
|
|
2
|
+
|
|
3
|
+
**Repository Level 3 Documentation**
|
|
4
|
+
- **Parent**: `/Users/miverso2/rubymine/legion/extensions-core/CLAUDE.md`
|
|
5
|
+
- **Grandparent**: `/Users/miverso2/rubymine/legion/CLAUDE.md`
|
|
6
|
+
|
|
7
|
+
## Purpose
|
|
8
|
+
|
|
9
|
+
Legion Extension that provides code generation for LegionIO extensions. Scaffolds complete new LEX gems from scratch, renders individual ERB templates, validates existing extension structure and configuration, and generates companion RSpec files. Used by the `legion lex create` CLI command and by agentic swarm pipelines that construct new extensions programmatically.
|
|
10
|
+
|
|
11
|
+
**GitHub**: https://github.com/LegionIO/lex-codegen
|
|
12
|
+
**License**: MIT
|
|
13
|
+
**Version**: 0.1.0
|
|
14
|
+
|
|
15
|
+
## Architecture
|
|
16
|
+
|
|
17
|
+
```
|
|
18
|
+
Legion::Extensions::Codegen
|
|
19
|
+
├── Runners/
|
|
20
|
+
│ ├── Generate # Scaffold entire extension trees; generate individual files
|
|
21
|
+
│ ├── Template # List templates, render a template, inspect required variables
|
|
22
|
+
│ └── Validate # Check extension directory structure, rubocop config, gemspec fields
|
|
23
|
+
├── Helpers/
|
|
24
|
+
│ ├── Constants # All ERB template strings + defaults (author, version, ruby, license)
|
|
25
|
+
│ ├── TemplateEngine # ERB renderer; isolates each render into a fresh binding
|
|
26
|
+
│ ├── SpecGenerator # Builds RSpec source strings for runners, clients, helpers
|
|
27
|
+
│ └── FileWriter # Writes rendered content to disk, creates directories as needed
|
|
28
|
+
└── Client # Thin wrapper; includes all three runner modules
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
No explicit actors directory. The framework auto-generates subscription actors for each runner.
|
|
32
|
+
|
|
33
|
+
## Gem Info
|
|
34
|
+
|
|
35
|
+
| Field | Value |
|
|
36
|
+
|-------|-------|
|
|
37
|
+
| Gem name | `lex-codegen` |
|
|
38
|
+
| Module | `Legion::Extensions::Codegen` |
|
|
39
|
+
| Version | `0.1.0` |
|
|
40
|
+
| Ruby | `>= 3.4` |
|
|
41
|
+
| Runtime dep | `erb` (stdlib, declared explicitly) |
|
|
42
|
+
|
|
43
|
+
## File Structure
|
|
44
|
+
|
|
45
|
+
```
|
|
46
|
+
lex-codegen/
|
|
47
|
+
├── lex-codegen.gemspec
|
|
48
|
+
├── Gemfile
|
|
49
|
+
├── lib/
|
|
50
|
+
│ └── legion/
|
|
51
|
+
│ └── extensions/
|
|
52
|
+
│ ├── codegen.rb # Entry point; requires all helpers/runners/client
|
|
53
|
+
│ └── codegen/
|
|
54
|
+
│ ├── version.rb
|
|
55
|
+
│ ├── client.rb # Client class; includes all three runner modules
|
|
56
|
+
│ ├── helpers/
|
|
57
|
+
│ │ ├── constants.rb # TEMPLATE_MAP, TEMPLATE_TYPES, all ERB strings
|
|
58
|
+
│ │ ├── template_engine.rb # TemplateEngine class (ERB renderer)
|
|
59
|
+
│ │ ├── spec_generator.rb # SpecGenerator class (RSpec source builder)
|
|
60
|
+
│ │ └── file_writer.rb # FileWriter class (disk writer)
|
|
61
|
+
│ └── runners/
|
|
62
|
+
│ ├── generate.rb # scaffold_extension, generate_file
|
|
63
|
+
│ ├── template.rb # list_templates, render_template, template_variables
|
|
64
|
+
│ └── validate.rb # validate_structure, validate_rubocop_config, validate_gemspec
|
|
65
|
+
└── spec/
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
## Key Constants
|
|
69
|
+
|
|
70
|
+
Defined in `Helpers::Constants`:
|
|
71
|
+
|
|
72
|
+
| Constant | Value |
|
|
73
|
+
|----------|-------|
|
|
74
|
+
| `TEMPLATE_TYPES` | `[:gemspec, :gemfile, :rubocop, :ci, :rspec, :gitignore, :license, :version, :entry_point, :spec_helper, :runner, :client]` |
|
|
75
|
+
| `DEFAULT_RUBY_VERSION` | `'3.4'` |
|
|
76
|
+
| `DEFAULT_LICENSE` | `'MIT'` |
|
|
77
|
+
| `DEFAULT_AUTHOR` | `'Esity'` |
|
|
78
|
+
| `DEFAULT_EMAIL` | `'matthewdiverson@gmail.com'` |
|
|
79
|
+
| `DEFAULT_GEM_VERSION` | `'0.1.0'` |
|
|
80
|
+
| `TEMPLATE_MAP` | Hash mapping each symbol in `TEMPLATE_TYPES` to its ERB string |
|
|
81
|
+
|
|
82
|
+
Defined in `Runners::Template`:
|
|
83
|
+
|
|
84
|
+
| Constant | Value |
|
|
85
|
+
|----------|-------|
|
|
86
|
+
| `TEMPLATE_REQUIRED_VARS` | Hash mapping each template type to its required variable keys |
|
|
87
|
+
|
|
88
|
+
Defined in `Runners::Validate`:
|
|
89
|
+
|
|
90
|
+
| Constant | Value |
|
|
91
|
+
|----------|-------|
|
|
92
|
+
| `REQUIRED_FILES` | `['Gemfile', '.rubocop.yml', 'spec/spec_helper.rb']` |
|
|
93
|
+
| `REQUIRED_RUBOCOP_KEYS` | `['AllCops', 'Layout/LineLength', 'Metrics/MethodLength', 'Style/FrozenStringLiteralComment']` |
|
|
94
|
+
| `REQUIRED_GEMSPEC_FIELDS` | `['name', 'version', 'authors', 'email', 'summary', 'description', 'homepage', 'license']` |
|
|
95
|
+
|
|
96
|
+
## Runners
|
|
97
|
+
|
|
98
|
+
### Generate (`Runners::Generate`)
|
|
99
|
+
|
|
100
|
+
`extend self` — all methods callable on the module directly.
|
|
101
|
+
|
|
102
|
+
**`scaffold_extension(name:, module_name:, description:, category: :cognition, helpers: [], runner_methods: [], base_path: nil, **)`**
|
|
103
|
+
- Creates a complete extension directory tree at `<base_path>/lex-<name>/`
|
|
104
|
+
- Writes: gemspec, Gemfile, .rubocop.yml, .github/workflows/ci.yml, .rspec, .gitignore, LICENSE, version.rb, entry point, spec_helper, client, one file per helper, one runner file + one runner spec per `runner_methods` entry, client_spec
|
|
105
|
+
- `helpers` accepts either plain strings (helper name) or hashes `{ name:, methods: [] }`
|
|
106
|
+
- `runner_methods` accepts hashes with `:name` and `:params` keys; each becomes one runner module and one spec file
|
|
107
|
+
- Returns `{ success: true, path:, files_created:, name: }` or `{ success: false, error: }`
|
|
108
|
+
|
|
109
|
+
**`generate_file(template_type:, output_path:, variables: {}, **)`**
|
|
110
|
+
- Renders a single named template and writes it to `output_path`
|
|
111
|
+
- Creates parent directories via `FileUtils.mkdir_p`
|
|
112
|
+
- Returns `{ success: true, path:, bytes: }` or `{ success: false, error: }`
|
|
113
|
+
|
|
114
|
+
### Template (`Runners::Template`)
|
|
115
|
+
|
|
116
|
+
`extend self` — all methods callable on the module directly.
|
|
117
|
+
|
|
118
|
+
**`list_templates(**)`**
|
|
119
|
+
- Returns `{ success: true, templates: <array of 12 template type symbols> }`
|
|
120
|
+
|
|
121
|
+
**`render_template(template_type:, variables: {}, **)`**
|
|
122
|
+
- Renders the named template with provided variables
|
|
123
|
+
- Returns `{ success: true, content:, template_type: }` or `{ success: false, error: }`
|
|
124
|
+
|
|
125
|
+
**`template_variables(template_type:, **)`**
|
|
126
|
+
- Returns the list of required variable keys for the given template type
|
|
127
|
+
- Returns `{ success: true, template_type:, required_variables: [] }` or `{ success: false, error: }`
|
|
128
|
+
|
|
129
|
+
### Validate (`Runners::Validate`)
|
|
130
|
+
|
|
131
|
+
`extend self` — all methods callable on the module directly.
|
|
132
|
+
|
|
133
|
+
**`validate_structure(path:, **)`**
|
|
134
|
+
- Checks for required files: Gemfile, .rubocop.yml, spec/spec_helper.rb, *.gemspec, lib entry point, version.rb
|
|
135
|
+
- Returns `{ valid:, missing: [], present: [] }` or adds `:error` key on ArgumentError
|
|
136
|
+
|
|
137
|
+
**`validate_rubocop_config(path:, **)`**
|
|
138
|
+
- Parses `.rubocop.yml` and checks for required top-level keys
|
|
139
|
+
- Verifies `AllCops/TargetRubyVersion` equals `DEFAULT_RUBY_VERSION` (`'3.4'`)
|
|
140
|
+
- Returns `{ valid:, issues: [] }`
|
|
141
|
+
|
|
142
|
+
**`validate_gemspec(path:, **)`**
|
|
143
|
+
- Reads the `*.gemspec` file and checks for required field names via string inclusion
|
|
144
|
+
- Also checks for `rubygems_mfa_required` metadata and `required_ruby_version`
|
|
145
|
+
- Returns `{ valid:, issues: [], path: }`
|
|
146
|
+
|
|
147
|
+
## Helpers
|
|
148
|
+
|
|
149
|
+
### TemplateEngine
|
|
150
|
+
|
|
151
|
+
Class. No persistent state.
|
|
152
|
+
|
|
153
|
+
**`render(template_type, variables = {})`**
|
|
154
|
+
- Looks up `TEMPLATE_MAP[template_type.to_sym]`, raises `ArgumentError` on unknown type
|
|
155
|
+
- Delegates to `render_string`
|
|
156
|
+
|
|
157
|
+
**`render_string(template_string, variables = {})`**
|
|
158
|
+
- Renders an arbitrary ERB string with `trim_mode: '-'`
|
|
159
|
+
- Each variable becomes a method on a fresh `Object` context — no shared state between renders
|
|
160
|
+
|
|
161
|
+
### SpecGenerator
|
|
162
|
+
|
|
163
|
+
Class. No persistent state.
|
|
164
|
+
|
|
165
|
+
**`generate_runner_spec(module_name:, runner_name:, methods: [])`**
|
|
166
|
+
- Returns RSpec source as a string; one `describe` block per method, tests `respond_to` and `{ success: }` key presence
|
|
167
|
+
|
|
168
|
+
**`generate_client_spec(module_name:, runner_name: nil, methods: [])`**
|
|
169
|
+
- Returns RSpec source as a string; tests `instantiates successfully` and `responds_to` each method
|
|
170
|
+
|
|
171
|
+
**`generate_helper_spec(module_name:, helper_name:, methods: [])`**
|
|
172
|
+
- Returns RSpec source as a string; tests instantiation and `responds_to` each method
|
|
173
|
+
|
|
174
|
+
### FileWriter
|
|
175
|
+
|
|
176
|
+
Class. Initialized with `base_path:`.
|
|
177
|
+
|
|
178
|
+
**`write(relative_path, content)`**
|
|
179
|
+
- Resolves `File.join(@base_path, relative_path)`, creates parent directories, writes content
|
|
180
|
+
- Returns `{ path:, bytes: }`
|
|
181
|
+
|
|
182
|
+
**`write_all(files)`**
|
|
183
|
+
- Accepts a hash of `{ relative_path => content }` and calls `write` for each
|
|
184
|
+
- Returns array of `{ path:, bytes: }` results
|
|
185
|
+
|
|
186
|
+
## Integration Points
|
|
187
|
+
|
|
188
|
+
- **`legion lex create`** CLI command calls `scaffold_extension` to bootstrap new extension repos
|
|
189
|
+
- **`lex-swarm-github`** swarm pipeline uses codegen to produce runner and spec files during automated extension construction
|
|
190
|
+
- **`lex-exec`** is the natural companion: codegen produces the files, exec runs `bundle install` and `bundle exec rspec` against the output
|
|
191
|
+
|
|
192
|
+
## Development Notes
|
|
193
|
+
|
|
194
|
+
- All runners use `extend self`; methods are callable on the module directly without instantiation
|
|
195
|
+
- The `Client` class includes all three runner modules, making all runner methods available on a `Client.new` instance
|
|
196
|
+
- `TemplateEngine#binding_with` creates a fresh `Object` subcontext for each render; variable names become singleton methods, not local variables — ERB must reference them without `@` prefix
|
|
197
|
+
- `scaffold_extension` accepts `category:` but does not use it (marked with `Lint/UnusedMethodArgument`); present for future routing support
|
|
198
|
+
- `generate_client_spec` accepts `runner_name:` but does not use it (same reason)
|
|
199
|
+
- Validate methods check file existence by string inclusion on file content, not by loading/evaluating the gemspec
|
|
200
|
+
|
|
201
|
+
```bash
|
|
202
|
+
bundle install
|
|
203
|
+
bundle exec rspec # 82 examples, 0 failures
|
|
204
|
+
bundle exec rubocop # 0 offenses
|
|
205
|
+
```
|
|
206
|
+
|
|
207
|
+
---
|
|
208
|
+
|
|
209
|
+
**Maintained By**: Matthew Iverson (@Esity)
|
data/Gemfile
ADDED
data/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2024 Matthew Iverson
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
data/README.md
ADDED
|
@@ -0,0 +1,173 @@
|
|
|
1
|
+
# lex-codegen
|
|
2
|
+
|
|
3
|
+
Code generation engine for LegionIO extensions. Scaffolds complete `lex-*` gem trees from scratch, renders individual ERB templates, validates existing extension structure, and generates companion RSpec files. Used by the `legion lex create` CLI command and by agentic swarm pipelines.
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
Add to your Gemfile or gemspec:
|
|
8
|
+
|
|
9
|
+
```ruby
|
|
10
|
+
gem 'lex-codegen'
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Or install directly:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
gem install lex-codegen
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Usage
|
|
20
|
+
|
|
21
|
+
### Scaffold a complete extension
|
|
22
|
+
|
|
23
|
+
```ruby
|
|
24
|
+
require 'legion/extensions/codegen'
|
|
25
|
+
|
|
26
|
+
client = Legion::Extensions::Codegen::Client.new(base_path: '/path/to/output')
|
|
27
|
+
|
|
28
|
+
result = client.scaffold_extension(
|
|
29
|
+
name: 'myextension',
|
|
30
|
+
module_name: 'Myextension',
|
|
31
|
+
description: 'Does something useful',
|
|
32
|
+
helpers: ['config'],
|
|
33
|
+
runner_methods: [
|
|
34
|
+
{ name: 'run_job', params: ['job_id:'] },
|
|
35
|
+
{ name: 'check_status', params: ['job_id:', 'verbose: false'] }
|
|
36
|
+
]
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
result[:success] # => true
|
|
40
|
+
result[:path] # => '/path/to/output/lex-myextension'
|
|
41
|
+
result[:files_created] # => 15
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
This writes a fully structured gem including gemspec, Gemfile, .rubocop.yml, GitHub Actions CI workflow, .rspec, .gitignore, LICENSE, version.rb, entry point, client, helpers, runners, and RSpec files for all of the above.
|
|
45
|
+
|
|
46
|
+
### Generate a single file
|
|
47
|
+
|
|
48
|
+
```ruby
|
|
49
|
+
result = client.generate_file(
|
|
50
|
+
template_type: :runner,
|
|
51
|
+
output_path: '/tmp/myrunner.rb',
|
|
52
|
+
variables: {
|
|
53
|
+
module_name: 'Myextension',
|
|
54
|
+
gem_name_underscored: 'myextension',
|
|
55
|
+
runner_class: 'RunJob',
|
|
56
|
+
methods: [{ name: 'run_job', params: ['job_id:'] }]
|
|
57
|
+
}
|
|
58
|
+
)
|
|
59
|
+
|
|
60
|
+
result[:bytes] # => number of bytes written
|
|
61
|
+
```
|
|
62
|
+
|
|
63
|
+
### Render a template to a string (without writing to disk)
|
|
64
|
+
|
|
65
|
+
```ruby
|
|
66
|
+
runner = Legion::Extensions::Codegen::Runners::Template
|
|
67
|
+
|
|
68
|
+
content = runner.render_template(
|
|
69
|
+
template_type: :version,
|
|
70
|
+
variables: { module_name: 'Myextension', gem_version: '0.1.0' }
|
|
71
|
+
)
|
|
72
|
+
|
|
73
|
+
puts content[:content]
|
|
74
|
+
# frozen_string_literal: true
|
|
75
|
+
# module Legion::Extensions::Myextension; VERSION = '0.1.0'; end
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### List available templates
|
|
79
|
+
|
|
80
|
+
```ruby
|
|
81
|
+
runner.list_templates
|
|
82
|
+
# => { success: true, templates: [:gemspec, :gemfile, :rubocop, :ci, :rspec, :gitignore,
|
|
83
|
+
# :license, :version, :entry_point, :spec_helper, :runner, :client] }
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
### Inspect required variables for a template
|
|
87
|
+
|
|
88
|
+
```ruby
|
|
89
|
+
runner.template_variables(template_type: :gemspec)
|
|
90
|
+
# => { success: true, template_type: :gemspec,
|
|
91
|
+
# required_variables: [:gem_name, :module_name, :description, :author, :email,
|
|
92
|
+
# :ruby_version, :license, :extra_deps] }
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
### Validate an existing extension
|
|
96
|
+
|
|
97
|
+
```ruby
|
|
98
|
+
validator = Legion::Extensions::Codegen::Runners::Validate
|
|
99
|
+
|
|
100
|
+
# Check directory structure
|
|
101
|
+
validator.validate_structure(path: '/path/to/lex-myextension')
|
|
102
|
+
# => { valid: true, missing: [], present: ['Gemfile', '.rubocop.yml', ...] }
|
|
103
|
+
|
|
104
|
+
# Check rubocop config
|
|
105
|
+
validator.validate_rubocop_config(path: '/path/to/lex-myextension')
|
|
106
|
+
# => { valid: true, issues: [] }
|
|
107
|
+
|
|
108
|
+
# Check gemspec fields
|
|
109
|
+
validator.validate_gemspec(path: '/path/to/lex-myextension')
|
|
110
|
+
# => { valid: true, issues: [], path: '/path/to/lex-myextension/lex-myextension.gemspec' }
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
### Generate spec files directly
|
|
114
|
+
|
|
115
|
+
```ruby
|
|
116
|
+
spec_gen = Legion::Extensions::Codegen::Helpers::SpecGenerator.new
|
|
117
|
+
|
|
118
|
+
# Runner spec
|
|
119
|
+
puts spec_gen.generate_runner_spec(
|
|
120
|
+
module_name: 'Myextension',
|
|
121
|
+
runner_name: 'run_job',
|
|
122
|
+
methods: [{ name: 'run_job', params: ['job_id:'] }]
|
|
123
|
+
)
|
|
124
|
+
|
|
125
|
+
# Client spec
|
|
126
|
+
puts spec_gen.generate_client_spec(module_name: 'Myextension')
|
|
127
|
+
|
|
128
|
+
# Helper spec
|
|
129
|
+
puts spec_gen.generate_helper_spec(
|
|
130
|
+
module_name: 'Myextension',
|
|
131
|
+
helper_name: 'config',
|
|
132
|
+
methods: [{ name: 'load', params: [] }]
|
|
133
|
+
)
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
## Available Templates
|
|
137
|
+
|
|
138
|
+
| Template | Generates |
|
|
139
|
+
|----------|-----------|
|
|
140
|
+
| `gemspec` | `lex-name.gemspec` |
|
|
141
|
+
| `gemfile` | `Gemfile` with gemspec + test group |
|
|
142
|
+
| `rubocop` | `.rubocop.yml` with LegionIO defaults |
|
|
143
|
+
| `ci` | `.github/workflows/ci.yml` (calls shared reusable workflow) |
|
|
144
|
+
| `rspec` | `.rspec` with `--format documentation` |
|
|
145
|
+
| `gitignore` | `.gitignore` with standard Ruby entries |
|
|
146
|
+
| `license` | `LICENSE` (MIT) |
|
|
147
|
+
| `version` | `lib/legion/extensions/<name>/version.rb` |
|
|
148
|
+
| `entry_point` | `lib/legion/extensions/<name>.rb` |
|
|
149
|
+
| `spec_helper` | `spec/spec_helper.rb` with Legion::Logging stub |
|
|
150
|
+
| `runner` | One runner module with stubbed methods |
|
|
151
|
+
| `client` | `Client` class including runner modules |
|
|
152
|
+
|
|
153
|
+
## Defaults
|
|
154
|
+
|
|
155
|
+
| Setting | Default |
|
|
156
|
+
|---------|---------|
|
|
157
|
+
| Ruby version | `3.4` |
|
|
158
|
+
| License | `MIT` |
|
|
159
|
+
| Author | `Esity` |
|
|
160
|
+
| Email | `matthewdiverson@gmail.com` |
|
|
161
|
+
| Gem version | `0.1.0` |
|
|
162
|
+
|
|
163
|
+
## Development
|
|
164
|
+
|
|
165
|
+
```bash
|
|
166
|
+
bundle install
|
|
167
|
+
bundle exec rspec
|
|
168
|
+
bundle exec rubocop
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
## License
|
|
172
|
+
|
|
173
|
+
MIT. See [LICENSE](LICENSE).
|
data/lex-codegen.gemspec
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'lib/legion/extensions/codegen/version'
|
|
4
|
+
|
|
5
|
+
Gem::Specification.new do |spec|
|
|
6
|
+
spec.name = 'lex-codegen'
|
|
7
|
+
spec.version = Legion::Extensions::Codegen::VERSION
|
|
8
|
+
spec.authors = ['Esity']
|
|
9
|
+
spec.email = ['matthewdiverson@gmail.com']
|
|
10
|
+
|
|
11
|
+
spec.summary = 'Legion::Extensions::Codegen'
|
|
12
|
+
spec.description = 'Code generation engine for LegionIO extensions'
|
|
13
|
+
spec.homepage = 'https://github.com/LegionIO/lex-codegen'
|
|
14
|
+
spec.license = 'MIT'
|
|
15
|
+
spec.required_ruby_version = '>= 3.4'
|
|
16
|
+
|
|
17
|
+
spec.metadata['homepage_uri'] = spec.homepage
|
|
18
|
+
spec.metadata['source_code_uri'] = 'https://github.com/LegionIO/lex-codegen'
|
|
19
|
+
spec.metadata['changelog_uri'] = 'https://github.com/LegionIO/lex-codegen'
|
|
20
|
+
spec.metadata['documentation_uri'] = 'https://github.com/LegionIO/lex-codegen'
|
|
21
|
+
spec.metadata['bug_tracker_uri'] = 'https://github.com/LegionIO/lex-codegen/issues'
|
|
22
|
+
spec.metadata['rubygems_mfa_required'] = 'true'
|
|
23
|
+
|
|
24
|
+
spec.files = Dir.chdir(File.expand_path(__dir__)) do
|
|
25
|
+
`git ls-files -z`.split("\x0").reject { |f| f.match(%r{^(test|spec|features)/}) }
|
|
26
|
+
end
|
|
27
|
+
spec.require_paths = ['lib']
|
|
28
|
+
|
|
29
|
+
spec.add_dependency 'erb'
|
|
30
|
+
|
|
31
|
+
spec.add_development_dependency 'rake'
|
|
32
|
+
spec.add_development_dependency 'rspec', '~> 3.13'
|
|
33
|
+
spec.add_development_dependency 'rspec_junit_formatter'
|
|
34
|
+
spec.add_development_dependency 'rubocop', '~> 1.75'
|
|
35
|
+
spec.add_development_dependency 'rubocop-rspec'
|
|
36
|
+
spec.add_development_dependency 'simplecov'
|
|
37
|
+
end
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Codegen
|
|
6
|
+
class Client
|
|
7
|
+
include Runners::Generate
|
|
8
|
+
include Runners::Template
|
|
9
|
+
include Runners::Validate
|
|
10
|
+
|
|
11
|
+
def initialize(base_path: ::Dir.pwd)
|
|
12
|
+
@base_path = base_path
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
17
|
+
end
|