@el-j/magic-helix-core 4.0.0-beta.2 → 4.0.0-beta.3
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.
- package/dist/index-B88j4AyE.js +13 -0
- package/dist/index-B88j4AyE.js.map +1 -0
- package/dist/index-CY-pQbuu.cjs +2 -0
- package/dist/index-CY-pQbuu.cjs.map +1 -0
- package/dist/index.cjs +75 -1
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.ts +0 -1
- package/dist/index.mjs +2234 -51
- package/dist/index.mjs.map +1 -1
- package/dist/pattern-combiner.d.ts +1 -1
- package/dist/plugin-loader.d.ts +2 -1
- package/package.json +4 -4
- package/dist/BasePlugin-6wv0hYJ9.js +0 -98
- package/dist/BasePlugin-6wv0hYJ9.js.map +0 -1
- package/dist/BasePlugin-odQJAKA-.cjs +0 -2
- package/dist/BasePlugin-odQJAKA-.cjs.map +0 -1
- package/dist/builtin-plugins/base/BasePlugin.d.ts +0 -69
- package/dist/builtin-plugins/cpp/index.d.ts +0 -46
- package/dist/builtin-plugins/csharp/index.d.ts +0 -20
- package/dist/builtin-plugins/go/index.d.ts +0 -23
- package/dist/builtin-plugins/index.d.ts +0 -16
- package/dist/builtin-plugins/java/index.d.ts +0 -22
- package/dist/builtin-plugins/nodejs/index.d.ts +0 -44
- package/dist/builtin-plugins/php/index.d.ts +0 -20
- package/dist/builtin-plugins/python/index.d.ts +0 -27
- package/dist/builtin-plugins/ruby/index.d.ts +0 -20
- package/dist/builtin-plugins/rust/index.d.ts +0 -53
- package/dist/builtin-plugins/swift/index.d.ts +0 -22
- package/dist/default_templates/angular/angular-core.md +0 -19
- package/dist/default_templates/architecture/codeowners.md +0 -123
- package/dist/default_templates/architecture/monorepo.md +0 -146
- package/dist/default_templates/architecture/nx.md +0 -122
- package/dist/default_templates/architecture/turborepo.md +0 -114
- package/dist/default_templates/ci/github-actions.md +0 -268
- package/dist/default_templates/ci/gitlab-ci.md +0 -330
- package/dist/default_templates/containers/docker-multistage.md +0 -120
- package/dist/default_templates/containers/kubernetes-deploy.md +0 -210
- package/dist/default_templates/devops/docker-compose.md +0 -111
- package/dist/default_templates/devops/docker-dockerfile.md +0 -94
- package/dist/default_templates/devops/github-actions.md +0 -160
- package/dist/default_templates/devops/gitlab-ci.md +0 -210
- package/dist/default_templates/dotnet/framework-aspnetcore.md +0 -205
- package/dist/default_templates/dotnet/framework-blazor.md +0 -271
- package/dist/default_templates/dotnet/lang-csharp.md +0 -162
- package/dist/default_templates/generic/lang-typescript.md +0 -57
- package/dist/default_templates/generic/state-redux.md +0 -21
- package/dist/default_templates/generic/state-rxjs.md +0 -6
- package/dist/default_templates/generic/style-mui.md +0 -23
- package/dist/default_templates/generic/style-tailwind.md +0 -76
- package/dist/default_templates/generic/test-cypress.md +0 -21
- package/dist/default_templates/generic/test-jest.md +0 -20
- package/dist/default_templates/generic/test-playwright.md +0 -21
- package/dist/default_templates/generic/test-vitest.md +0 -131
- package/dist/default_templates/go/lang-go.md +0 -571
- package/dist/default_templates/java/build-gradle.md +0 -102
- package/dist/default_templates/java/build-maven.md +0 -86
- package/dist/default_templates/java/framework-spring-boot.md +0 -179
- package/dist/default_templates/java/lang-java.md +0 -78
- package/dist/default_templates/java/lang-kotlin.md +0 -88
- package/dist/default_templates/meta/magic-helix-meta.md +0 -213
- package/dist/default_templates/meta/meta-debug.md +0 -459
- package/dist/default_templates/meta/meta-implement.md +0 -450
- package/dist/default_templates/meta/meta-roadmap.md +0 -265
- package/dist/default_templates/nestjs/nestjs-core.md +0 -7
- package/dist/default_templates/patterns/architecture/clean-architecture.md +0 -469
- package/dist/default_templates/patterns/architecture/dependency-injection.md +0 -517
- package/dist/default_templates/patterns/architecture/domain-driven-design.md +0 -621
- package/dist/default_templates/patterns/architecture/layered-architecture.md +0 -382
- package/dist/default_templates/patterns/architecture/repository-pattern.md +0 -408
- package/dist/default_templates/patterns/domain-expertise/nextjs-rules.md +0 -115
- package/dist/default_templates/patterns/domain-expertise/react-patterns.md +0 -181
- package/dist/default_templates/patterns/domain-expertise/server-components.md +0 -212
- package/dist/default_templates/patterns/domain-expertise/shadcn-ui.md +0 -52
- package/dist/default_templates/patterns/domain-expertise/tailwind-patterns.md +0 -52
- package/dist/default_templates/patterns/environment/container-awareness.md +0 -17
- package/dist/default_templates/patterns/environment/ide-features.md +0 -17
- package/dist/default_templates/patterns/environment/os-commands.md +0 -17
- package/dist/default_templates/patterns/organization/heading-hierarchy.md +0 -103
- package/dist/default_templates/patterns/organization/sequential-workflows.md +0 -102
- package/dist/default_templates/patterns/organization/xml-rule-groups.md +0 -64
- package/dist/default_templates/patterns/reasoning/agent-loop.md +0 -151
- package/dist/default_templates/patterns/reasoning/confirmation-gates.md +0 -141
- package/dist/default_templates/patterns/reasoning/dependency-analysis.md +0 -132
- package/dist/default_templates/patterns/reasoning/one-tool-per-iteration.md +0 -152
- package/dist/default_templates/patterns/reasoning/preview-before-action.md +0 -194
- package/dist/default_templates/patterns/reasoning/reflection-checkpoints.md +0 -166
- package/dist/default_templates/patterns/reasoning/result-verification.md +0 -157
- package/dist/default_templates/patterns/reasoning/subtask-breakdown.md +0 -131
- package/dist/default_templates/patterns/reasoning/thinking-tags.md +0 -100
- package/dist/default_templates/patterns/role-definition/capability-declarations.md +0 -72
- package/dist/default_templates/patterns/role-definition/expert-identity.md +0 -45
- package/dist/default_templates/patterns/role-definition/scope-boundaries.md +0 -61
- package/dist/default_templates/patterns/safety/code-safety-rules.md +0 -17
- package/dist/default_templates/patterns/safety/credential-handling.md +0 -17
- package/dist/default_templates/patterns/safety/destructive-warnings.md +0 -17
- package/dist/default_templates/patterns/safety/refusal-messages.md +0 -17
- package/dist/default_templates/patterns/tone/adaptive-tone.md +0 -17
- package/dist/default_templates/patterns/tone/concise-communication.md +0 -17
- package/dist/default_templates/patterns/tone/forbidden-phrases.md +0 -17
- package/dist/default_templates/patterns/tool-guidelines/function-schemas.md +0 -143
- package/dist/default_templates/patterns/tool-guidelines/parameter-examples.md +0 -137
- package/dist/default_templates/patterns/tool-guidelines/usage-policies.md +0 -105
- package/dist/default_templates/php/framework-laravel.md +0 -112
- package/dist/default_templates/php/lang-php.md +0 -94
- package/dist/default_templates/python/lang-python.md +0 -508
- package/dist/default_templates/react/react-core.md +0 -677
- package/dist/default_templates/react/react-zustand.md +0 -7
- package/dist/default_templates/ruby/framework-rails.md +0 -309
- package/dist/default_templates/ruby/framework-sinatra.md +0 -227
- package/dist/default_templates/ruby/lang-ruby.md +0 -216
- package/dist/default_templates/rust/lang-rust.md +0 -89
- package/dist/default_templates/swift/framework-vapor.md +0 -352
- package/dist/default_templates/swift/lang-swift.md +0 -291
- package/dist/default_templates/vue/style-primevue.md +0 -6
- package/dist/default_templates/vue/style-quasar.md +0 -22
- package/dist/default_templates/vue/vue-core.md +0 -108
- package/dist/default_templates/vue/vue-pinia.md +0 -5
- package/dist/index-0GK4RlUx.js +0 -1748
- package/dist/index-0GK4RlUx.js.map +0 -1
- package/dist/index-AkVwRl-r.js +0 -92
- package/dist/index-AkVwRl-r.js.map +0 -1
- package/dist/index-B6BeG1yT.cjs +0 -68
- package/dist/index-B6BeG1yT.cjs.map +0 -1
- package/dist/index-B8pyjKdF.js +0 -94
- package/dist/index-B8pyjKdF.js.map +0 -1
- package/dist/index-BQ6v041y.js +0 -13
- package/dist/index-BQ6v041y.js.map +0 -1
- package/dist/index-Baxb1vI_.js +0 -210
- package/dist/index-Baxb1vI_.js.map +0 -1
- package/dist/index-Bg8DD8ku.js +0 -216
- package/dist/index-Bg8DD8ku.js.map +0 -1
- package/dist/index-BqTqxCpG.cjs +0 -89
- package/dist/index-BqTqxCpG.cjs.map +0 -1
- package/dist/index-Bv4Q1Pr7.cjs +0 -33
- package/dist/index-Bv4Q1Pr7.cjs.map +0 -1
- package/dist/index-CN8J45Nc.cjs +0 -24
- package/dist/index-CN8J45Nc.cjs.map +0 -1
- package/dist/index-CPbv2Od1.js +0 -62
- package/dist/index-CPbv2Od1.js.map +0 -1
- package/dist/index-Cf-MC6Al.js +0 -63
- package/dist/index-Cf-MC6Al.js.map +0 -1
- package/dist/index-DDPXXXDy.cjs +0 -19
- package/dist/index-DDPXXXDy.cjs.map +0 -1
- package/dist/index-DO30AzDe.cjs +0 -19
- package/dist/index-DO30AzDe.cjs.map +0 -1
- package/dist/index-DkvW5yBY.js +0 -2249
- package/dist/index-DkvW5yBY.js.map +0 -1
- package/dist/index-Dn1ehjIj.cjs +0 -80
- package/dist/index-Dn1ehjIj.cjs.map +0 -1
- package/dist/index-DqHvgoXJ.cjs +0 -19
- package/dist/index-DqHvgoXJ.cjs.map +0 -1
- package/dist/index-K39pdw94.cjs +0 -31
- package/dist/index-K39pdw94.cjs.map +0 -1
- package/dist/index-OT2XAJkc.js +0 -117
- package/dist/index-OT2XAJkc.js.map +0 -1
- package/dist/index-TPAX4XKg.cjs +0 -30
- package/dist/index-TPAX4XKg.cjs.map +0 -1
- package/dist/index-WmVSB57y.js +0 -107
- package/dist/index-WmVSB57y.js.map +0 -1
- package/dist/index-mYXvc3Fs.js +0 -68
- package/dist/index-mYXvc3Fs.js.map +0 -1
- package/dist/index-nioXOg4m.cjs +0 -76
- package/dist/index-nioXOg4m.cjs.map +0 -1
- package/dist/index-okhY3fWD.cjs +0 -2
- package/dist/index-okhY3fWD.cjs.map +0 -1
|
@@ -1,216 +0,0 @@
|
|
|
1
|
-
# Ruby Language Instructions
|
|
2
|
-
|
|
3
|
-
## Project Type
|
|
4
|
-
- Language: Ruby
|
|
5
|
-
- Package Manager: Bundler (Gemfile)
|
|
6
|
-
- Framework: {Rails|Sinatra|None}
|
|
7
|
-
|
|
8
|
-
## Build Commands
|
|
9
|
-
|
|
10
|
-
```bash
|
|
11
|
-
bundle install # Install dependencies
|
|
12
|
-
bundle exec ruby app.rb # Run application
|
|
13
|
-
bundle exec rake test # Run tests
|
|
14
|
-
bundle update # Update dependencies
|
|
15
|
-
```
|
|
16
|
-
|
|
17
|
-
## Code Conventions
|
|
18
|
-
|
|
19
|
-
### Ruby Style
|
|
20
|
-
```ruby
|
|
21
|
-
# Use descriptive variable names
|
|
22
|
-
user_name = "John Doe"
|
|
23
|
-
users = User.where(active: true)
|
|
24
|
-
|
|
25
|
-
# Prefer blocks and enumerables
|
|
26
|
-
users.each do |user|
|
|
27
|
-
puts user.name
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# Use symbols for hash keys
|
|
31
|
-
options = { name: "John", age: 30 }
|
|
32
|
-
|
|
33
|
-
# Prefer string interpolation
|
|
34
|
-
puts "Hello, #{user.name}!"
|
|
35
|
-
```
|
|
36
|
-
|
|
37
|
-
### Classes and Modules
|
|
38
|
-
```ruby
|
|
39
|
-
class User
|
|
40
|
-
attr_accessor :name, :email
|
|
41
|
-
attr_reader :id
|
|
42
|
-
|
|
43
|
-
def initialize(name:, email:)
|
|
44
|
-
@name = name
|
|
45
|
-
@email = email
|
|
46
|
-
@id = SecureRandom.uuid
|
|
47
|
-
end
|
|
48
|
-
|
|
49
|
-
def full_profile
|
|
50
|
-
"#{name} <#{email}>"
|
|
51
|
-
end
|
|
52
|
-
end
|
|
53
|
-
|
|
54
|
-
module Authenticatable
|
|
55
|
-
def authenticate(password)
|
|
56
|
-
# authentication logic
|
|
57
|
-
end
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
class Admin < User
|
|
61
|
-
include Authenticatable
|
|
62
|
-
end
|
|
63
|
-
```
|
|
64
|
-
|
|
65
|
-
### Blocks and Procs
|
|
66
|
-
```ruby
|
|
67
|
-
# Block
|
|
68
|
-
numbers.map { |n| n * 2 }
|
|
69
|
-
|
|
70
|
-
# Multiline block
|
|
71
|
-
numbers.each do |n|
|
|
72
|
-
puts n
|
|
73
|
-
log_number(n)
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Proc
|
|
77
|
-
double = ->(x) { x * 2 }
|
|
78
|
-
double.call(5) # => 10
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
## Testing with RSpec
|
|
82
|
-
|
|
83
|
-
```ruby
|
|
84
|
-
# spec/models/user_spec.rb
|
|
85
|
-
require 'rails_helper'
|
|
86
|
-
|
|
87
|
-
RSpec.describe User, type: :model do
|
|
88
|
-
describe '#full_profile' do
|
|
89
|
-
it 'returns formatted name and email' do
|
|
90
|
-
user = User.new(name: 'John', email: 'john@example.com')
|
|
91
|
-
expect(user.full_profile).to eq('John <john@example.com>')
|
|
92
|
-
end
|
|
93
|
-
end
|
|
94
|
-
|
|
95
|
-
describe 'validations' do
|
|
96
|
-
it { should validate_presence_of(:name) }
|
|
97
|
-
it { should validate_presence_of(:email) }
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
```
|
|
101
|
-
|
|
102
|
-
## Docker Optimization
|
|
103
|
-
|
|
104
|
-
### Multi-stage Dockerfile
|
|
105
|
-
```dockerfile
|
|
106
|
-
FROM ruby:3.2-alpine AS builder
|
|
107
|
-
WORKDIR /app
|
|
108
|
-
|
|
109
|
-
# Install build dependencies
|
|
110
|
-
RUN apk add --no-cache build-base postgresql-dev
|
|
111
|
-
|
|
112
|
-
# Install gems
|
|
113
|
-
COPY Gemfile Gemfile.lock ./
|
|
114
|
-
RUN bundle config --local deployment true && \
|
|
115
|
-
bundle config --local without development:test && \
|
|
116
|
-
bundle install -j4
|
|
117
|
-
|
|
118
|
-
# Runtime stage
|
|
119
|
-
FROM ruby:3.2-alpine
|
|
120
|
-
WORKDIR /app
|
|
121
|
-
|
|
122
|
-
# Install runtime dependencies
|
|
123
|
-
RUN apk add --no-cache postgresql-client tzdata
|
|
124
|
-
|
|
125
|
-
# Copy installed gems
|
|
126
|
-
COPY --from=builder /usr/local/bundle /usr/local/bundle
|
|
127
|
-
COPY . .
|
|
128
|
-
|
|
129
|
-
# Non-root user
|
|
130
|
-
RUN adduser -D -u 1000 appuser && chown -R appuser /app
|
|
131
|
-
USER appuser
|
|
132
|
-
|
|
133
|
-
EXPOSE 3000
|
|
134
|
-
CMD ["bundle", "exec", "puma", "-C", "config/puma.rb"]
|
|
135
|
-
```
|
|
136
|
-
|
|
137
|
-
### Docker Compose
|
|
138
|
-
```yaml
|
|
139
|
-
services:
|
|
140
|
-
web:
|
|
141
|
-
build: .
|
|
142
|
-
ports:
|
|
143
|
-
- "3000:3000"
|
|
144
|
-
environment:
|
|
145
|
-
- DATABASE_URL=postgresql://postgres:password@db/myapp
|
|
146
|
-
- REDIS_URL=redis://redis:6379/0
|
|
147
|
-
depends_on:
|
|
148
|
-
- db
|
|
149
|
-
- redis
|
|
150
|
-
|
|
151
|
-
db:
|
|
152
|
-
image: postgres:15-alpine
|
|
153
|
-
environment:
|
|
154
|
-
POSTGRES_PASSWORD: password
|
|
155
|
-
volumes:
|
|
156
|
-
- postgres_data:/var/lib/postgresql/data
|
|
157
|
-
|
|
158
|
-
redis:
|
|
159
|
-
image: redis:7-alpine
|
|
160
|
-
volumes:
|
|
161
|
-
- redis_data:/data
|
|
162
|
-
|
|
163
|
-
volumes:
|
|
164
|
-
postgres_data:
|
|
165
|
-
redis_data:
|
|
166
|
-
```
|
|
167
|
-
|
|
168
|
-
## Dependency Management
|
|
169
|
-
|
|
170
|
-
```bash
|
|
171
|
-
# Add a gem
|
|
172
|
-
bundle add puma
|
|
173
|
-
|
|
174
|
-
# Remove a gem
|
|
175
|
-
bundle remove old_gem
|
|
176
|
-
|
|
177
|
-
# Update specific gem
|
|
178
|
-
bundle update rails
|
|
179
|
-
|
|
180
|
-
# Check for outdated gems
|
|
181
|
-
bundle outdated
|
|
182
|
-
|
|
183
|
-
# Audit for security vulnerabilities
|
|
184
|
-
bundle audit
|
|
185
|
-
```
|
|
186
|
-
|
|
187
|
-
## Performance Tips
|
|
188
|
-
|
|
189
|
-
- Use `pluck` instead of `map` for database queries
|
|
190
|
-
- Eager load associations to avoid N+1 queries
|
|
191
|
-
- Use background jobs (Sidekiq) for slow operations
|
|
192
|
-
- Cache expensive operations
|
|
193
|
-
- Use `find_each` for large datasets
|
|
194
|
-
- Profile with rack-mini-profiler
|
|
195
|
-
- Use Ruby 3.x for YJIT performance improvements
|
|
196
|
-
|
|
197
|
-
## Security
|
|
198
|
-
|
|
199
|
-
- Always use strong parameters in Rails
|
|
200
|
-
- Use `SecureRandom` for tokens
|
|
201
|
-
- Validate user input
|
|
202
|
-
- Use parameterized queries (ActiveRecord does this)
|
|
203
|
-
- Keep dependencies updated with `bundle audit`
|
|
204
|
-
- Set secure headers
|
|
205
|
-
- Use HTTPS in production
|
|
206
|
-
|
|
207
|
-
## Common Gems
|
|
208
|
-
|
|
209
|
-
- **puma**: Web server
|
|
210
|
-
- **sidekiq**: Background jobs
|
|
211
|
-
- **rspec**: Testing framework
|
|
212
|
-
- **rubocop**: Linter
|
|
213
|
-
- **devise**: Authentication
|
|
214
|
-
- **cancancan**: Authorization
|
|
215
|
-
- **kaminari**: Pagination
|
|
216
|
-
- **jbuilder**: JSON API builder
|
|
@@ -1,89 +0,0 @@
|
|
|
1
|
-
# Rust Development Guidelines
|
|
2
|
-
|
|
3
|
-
## Overview
|
|
4
|
-
This project uses Rust. Follow Rust idioms, ownership rules, and best practices.
|
|
5
|
-
|
|
6
|
-
## Code Style
|
|
7
|
-
- Use `rustfmt` for automatic code formatting
|
|
8
|
-
- Follow the [Rust API Guidelines](https://rust-lang.github.io/api-guidelines/)
|
|
9
|
-
- Use `clippy` for linting: `cargo clippy`
|
|
10
|
-
- Keep functions small and focused
|
|
11
|
-
- Use descriptive variable names
|
|
12
|
-
|
|
13
|
-
## Ownership & Borrowing
|
|
14
|
-
- Follow Rust's ownership rules strictly
|
|
15
|
-
- Prefer borrowing (`&T`) over taking ownership when possible
|
|
16
|
-
- Use `&mut T` for mutable borrows
|
|
17
|
-
- Avoid unnecessary `.clone()` calls
|
|
18
|
-
- Use `Cow<'_, T>` for conditional ownership
|
|
19
|
-
|
|
20
|
-
## Error Handling
|
|
21
|
-
- Use `Result<T, E>` for operations that can fail
|
|
22
|
-
- Use the `?` operator for error propagation
|
|
23
|
-
- Create custom error types using `thiserror` crate
|
|
24
|
-
- Avoid `unwrap()` and `expect()` in production code
|
|
25
|
-
- Provide meaningful error messages
|
|
26
|
-
|
|
27
|
-
## Types & Traits
|
|
28
|
-
- Use strong typing and avoid `String` everywhere
|
|
29
|
-
- Implement common traits (`Debug`, `Clone`, `PartialEq`) when appropriate
|
|
30
|
-
- Use `derive` macros for automatic implementations
|
|
31
|
-
- Define traits for shared behavior
|
|
32
|
-
- Use generics for code reuse
|
|
33
|
-
|
|
34
|
-
## Cargo Commands
|
|
35
|
-
- Build: `cargo build` (debug) or `cargo build --release` (optimized)
|
|
36
|
-
- Run: `cargo run`
|
|
37
|
-
- Test: `cargo test`
|
|
38
|
-
- Check: `cargo check` (faster than build for syntax checking)
|
|
39
|
-
- Format: `cargo fmt`
|
|
40
|
-
- Lint: `cargo clippy`
|
|
41
|
-
- Doc: `cargo doc --open`
|
|
42
|
-
|
|
43
|
-
## Project Structure
|
|
44
|
-
- `src/main.rs` - Binary entry point
|
|
45
|
-
- `src/lib.rs` - Library entry point
|
|
46
|
-
- `src/bin/` - Additional binaries
|
|
47
|
-
- `tests/` - Integration tests
|
|
48
|
-
- `benches/` - Benchmarks
|
|
49
|
-
- `examples/` - Example code
|
|
50
|
-
|
|
51
|
-
## Dependencies
|
|
52
|
-
- Add dependencies in `Cargo.toml`
|
|
53
|
-
- Use semantic versioning
|
|
54
|
-
- Run `cargo update` to update dependencies
|
|
55
|
-
- Check for outdated deps: `cargo outdated`
|
|
56
|
-
|
|
57
|
-
## Testing
|
|
58
|
-
- Write unit tests in the same file: `#[cfg(test)] mod tests { ... }`
|
|
59
|
-
- Write integration tests in `tests/` directory
|
|
60
|
-
- Use `assert!`, `assert_eq!`, `assert_ne!` macros
|
|
61
|
-
- Run specific tests: `cargo test test_name`
|
|
62
|
-
- Run with output: `cargo test -- --nocapture`
|
|
63
|
-
|
|
64
|
-
## Async/Await
|
|
65
|
-
- Use `tokio` or `async-std` for async runtime
|
|
66
|
-
- Mark async functions with `async fn`
|
|
67
|
-
- Use `.await` to wait for futures
|
|
68
|
-
- Use `#[tokio::main]` or `#[async_std::main]` for async main
|
|
69
|
-
|
|
70
|
-
## Documentation
|
|
71
|
-
- Use `///` for public API documentation
|
|
72
|
-
- Use `//!` for module-level documentation
|
|
73
|
-
- Include examples in doc comments
|
|
74
|
-
- Run `cargo doc` to generate documentation
|
|
75
|
-
- Use `#[doc = "..."]` for advanced docs
|
|
76
|
-
|
|
77
|
-
## Performance
|
|
78
|
-
- Profile before optimizing: use `cargo flamegraph`
|
|
79
|
-
- Use release builds for benchmarks: `cargo bench`
|
|
80
|
-
- Avoid unnecessary allocations
|
|
81
|
-
- Use iterators instead of loops when appropriate
|
|
82
|
-
- Consider using `rayon` for parallel processing
|
|
83
|
-
|
|
84
|
-
## Common Patterns
|
|
85
|
-
- Builder pattern for complex constructors
|
|
86
|
-
- Newtype pattern for type safety
|
|
87
|
-
- Use `match` for exhaustive pattern matching
|
|
88
|
-
- Use `if let` for simple pattern matching
|
|
89
|
-
- Use `Option<T>` instead of null
|
|
@@ -1,352 +0,0 @@
|
|
|
1
|
-
# Vapor Framework Instructions
|
|
2
|
-
|
|
3
|
-
## Server-Side Swift Web Framework
|
|
4
|
-
|
|
5
|
-
Vapor is a modern, high-performance web framework for Swift.
|
|
6
|
-
|
|
7
|
-
## Project Structure
|
|
8
|
-
```
|
|
9
|
-
Sources/
|
|
10
|
-
├── App/
|
|
11
|
-
│ ├── Controllers/
|
|
12
|
-
│ ├── Models/
|
|
13
|
-
│ ├── Migrations/
|
|
14
|
-
│ ├── configure.swift
|
|
15
|
-
│ └── routes.swift
|
|
16
|
-
└── Run/
|
|
17
|
-
└── main.swift
|
|
18
|
-
Tests/
|
|
19
|
-
└── AppTests/
|
|
20
|
-
Package.swift
|
|
21
|
-
```
|
|
22
|
-
|
|
23
|
-
## Basic Application
|
|
24
|
-
|
|
25
|
-
### configure.swift
|
|
26
|
-
```swift
|
|
27
|
-
import Vapor
|
|
28
|
-
import Fluent
|
|
29
|
-
import FluentPostgresDriver
|
|
30
|
-
|
|
31
|
-
public func configure(_ app: Application) async throws {
|
|
32
|
-
// Database
|
|
33
|
-
app.databases.use(
|
|
34
|
-
.postgres(
|
|
35
|
-
hostname: Environment.get("DATABASE_HOST") ?? "localhost",
|
|
36
|
-
port: Environment.get("DATABASE_PORT").flatMap(Int.init) ?? 5432,
|
|
37
|
-
username: Environment.get("DATABASE_USERNAME") ?? "postgres",
|
|
38
|
-
password: Environment.get("DATABASE_PASSWORD") ?? "",
|
|
39
|
-
database: Environment.get("DATABASE_NAME") ?? "vapor"
|
|
40
|
-
),
|
|
41
|
-
as: .psql
|
|
42
|
-
)
|
|
43
|
-
|
|
44
|
-
// Migrations
|
|
45
|
-
app.migrations.add(CreateUser())
|
|
46
|
-
|
|
47
|
-
try await app.autoMigrate()
|
|
48
|
-
|
|
49
|
-
// Routes
|
|
50
|
-
try routes(app)
|
|
51
|
-
}
|
|
52
|
-
```
|
|
53
|
-
|
|
54
|
-
### routes.swift
|
|
55
|
-
```swift
|
|
56
|
-
import Vapor
|
|
57
|
-
|
|
58
|
-
func routes(_ app: Application) throws {
|
|
59
|
-
app.get { req in
|
|
60
|
-
"Welcome to Vapor!"
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
app.get("hello", ":name") { req -> String in
|
|
64
|
-
let name = req.parameters.get("name")!
|
|
65
|
-
return "Hello, \(name)!"
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
try app.register(collection: UserController())
|
|
69
|
-
}
|
|
70
|
-
```
|
|
71
|
-
|
|
72
|
-
## Models with Fluent ORM
|
|
73
|
-
|
|
74
|
-
```swift
|
|
75
|
-
import Fluent
|
|
76
|
-
import Vapor
|
|
77
|
-
|
|
78
|
-
final class User: Model, Content {
|
|
79
|
-
static let schema = "users"
|
|
80
|
-
|
|
81
|
-
@ID(key: .id)
|
|
82
|
-
var id: UUID?
|
|
83
|
-
|
|
84
|
-
@Field(key: "name")
|
|
85
|
-
var name: String
|
|
86
|
-
|
|
87
|
-
@Field(key: "email")
|
|
88
|
-
var email: String
|
|
89
|
-
|
|
90
|
-
@Children(for: \.$user)
|
|
91
|
-
var posts: [Post]
|
|
92
|
-
|
|
93
|
-
init() {}
|
|
94
|
-
|
|
95
|
-
init(id: UUID? = nil, name: String, email: String) {
|
|
96
|
-
self.id = id
|
|
97
|
-
self.name = name
|
|
98
|
-
self.email = email
|
|
99
|
-
}
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
// Migration
|
|
103
|
-
struct CreateUser: AsyncMigration {
|
|
104
|
-
func prepare(on database: Database) async throws {
|
|
105
|
-
try await database.schema("users")
|
|
106
|
-
.id()
|
|
107
|
-
.field("name", .string, .required)
|
|
108
|
-
.field("email", .string, .required)
|
|
109
|
-
.unique(on: "email")
|
|
110
|
-
.create()
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
func revert(on database: Database) async throws {
|
|
114
|
-
try await database.schema("users").delete()
|
|
115
|
-
}
|
|
116
|
-
}
|
|
117
|
-
```
|
|
118
|
-
|
|
119
|
-
## Controllers
|
|
120
|
-
|
|
121
|
-
```swift
|
|
122
|
-
import Vapor
|
|
123
|
-
|
|
124
|
-
struct UserController: RouteCollection {
|
|
125
|
-
func boot(routes: RoutesBuilder) throws {
|
|
126
|
-
let users = routes.grouped("api", "users")
|
|
127
|
-
users.get(use: index)
|
|
128
|
-
users.get(":id", use: show)
|
|
129
|
-
users.post(use: create)
|
|
130
|
-
users.put(":id", use: update)
|
|
131
|
-
users.delete(":id", use: delete)
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
func index(req: Request) async throws -> [User] {
|
|
135
|
-
try await User.query(on: req.db).all()
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
func show(req: Request) async throws -> User {
|
|
139
|
-
guard let user = try await User.find(req.parameters.get("id"), on: req.db) else {
|
|
140
|
-
throw Abort(.notFound)
|
|
141
|
-
}
|
|
142
|
-
return user
|
|
143
|
-
}
|
|
144
|
-
|
|
145
|
-
func create(req: Request) async throws -> User {
|
|
146
|
-
let user = try req.content.decode(User.self)
|
|
147
|
-
try await user.save(on: req.db)
|
|
148
|
-
return user
|
|
149
|
-
}
|
|
150
|
-
|
|
151
|
-
func update(req: Request) async throws -> User {
|
|
152
|
-
guard let user = try await User.find(req.parameters.get("id"), on: req.db) else {
|
|
153
|
-
throw Abort(.notFound)
|
|
154
|
-
}
|
|
155
|
-
|
|
156
|
-
let updateData = try req.content.decode(User.self)
|
|
157
|
-
user.name = updateData.name
|
|
158
|
-
user.email = updateData.email
|
|
159
|
-
try await user.save(on: req.db)
|
|
160
|
-
return user
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
func delete(req: Request) async throws -> HTTPStatus {
|
|
164
|
-
guard let user = try await User.find(req.parameters.get("id"), on: req.db) else {
|
|
165
|
-
throw Abort(.notFound)
|
|
166
|
-
}
|
|
167
|
-
try await user.delete(on: req.db)
|
|
168
|
-
return .noContent
|
|
169
|
-
}
|
|
170
|
-
}
|
|
171
|
-
```
|
|
172
|
-
|
|
173
|
-
## Middleware
|
|
174
|
-
|
|
175
|
-
```swift
|
|
176
|
-
import Vapor
|
|
177
|
-
|
|
178
|
-
struct LogMiddleware: AsyncMiddleware {
|
|
179
|
-
func respond(to request: Request, chainingTo next: AsyncResponder) async throws -> Response {
|
|
180
|
-
request.logger.info("\(request.method) \(request.url.path)")
|
|
181
|
-
let response = try await next.respond(to: request)
|
|
182
|
-
request.logger.info("Response: \(response.status.code)")
|
|
183
|
-
return response
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
|
|
187
|
-
// Register middleware
|
|
188
|
-
app.middleware.use(LogMiddleware())
|
|
189
|
-
```
|
|
190
|
-
|
|
191
|
-
## Authentication
|
|
192
|
-
|
|
193
|
-
```swift
|
|
194
|
-
import Vapor
|
|
195
|
-
import Fluent
|
|
196
|
-
|
|
197
|
-
final class User: Model, Content, Authenticatable {
|
|
198
|
-
// ... model definition
|
|
199
|
-
|
|
200
|
-
static func authenticator() -> Authenticator {
|
|
201
|
-
return BearerAuthenticator()
|
|
202
|
-
}
|
|
203
|
-
}
|
|
204
|
-
|
|
205
|
-
// Protected route
|
|
206
|
-
let protected = app.grouped(User.authenticator())
|
|
207
|
-
protected.get("protected") { req -> String in
|
|
208
|
-
let user = try req.auth.require(User.self)
|
|
209
|
-
return "Hello, \(user.name)!"
|
|
210
|
-
}
|
|
211
|
-
```
|
|
212
|
-
|
|
213
|
-
## Validation
|
|
214
|
-
|
|
215
|
-
```swift
|
|
216
|
-
import Vapor
|
|
217
|
-
|
|
218
|
-
struct CreateUserRequest: Content, Validatable {
|
|
219
|
-
var name: String
|
|
220
|
-
var email: String
|
|
221
|
-
|
|
222
|
-
static func validations(_ validations: inout Validations) {
|
|
223
|
-
validations.add("name", as: String.self, is: !.empty)
|
|
224
|
-
validations.add("email", as: String.self, is: .email)
|
|
225
|
-
}
|
|
226
|
-
}
|
|
227
|
-
|
|
228
|
-
func create(req: Request) async throws -> User {
|
|
229
|
-
try CreateUserRequest.validate(content: req)
|
|
230
|
-
let userData = try req.content.decode(CreateUserRequest.self)
|
|
231
|
-
// ...
|
|
232
|
-
}
|
|
233
|
-
```
|
|
234
|
-
|
|
235
|
-
## Testing
|
|
236
|
-
|
|
237
|
-
```swift
|
|
238
|
-
import XCTVapor
|
|
239
|
-
@testable import App
|
|
240
|
-
|
|
241
|
-
final class UserTests: XCTestCase {
|
|
242
|
-
var app: Application!
|
|
243
|
-
|
|
244
|
-
override func setUp() async throws {
|
|
245
|
-
app = Application(.testing)
|
|
246
|
-
try await configure(app)
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
override func tearDown() async throws {
|
|
250
|
-
app.shutdown()
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
func testGetUsers() async throws {
|
|
254
|
-
try await app.test(.GET, "api/users") { res in
|
|
255
|
-
XCTAssertEqual(res.status, .ok)
|
|
256
|
-
let users = try res.content.decode([User].self)
|
|
257
|
-
XCTAssertGreaterThan(users.count, 0)
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
func testCreateUser() async throws {
|
|
262
|
-
let user = User(name: "John", email: "john@example.com")
|
|
263
|
-
|
|
264
|
-
try await app.test(.POST, "api/users", beforeRequest: { req in
|
|
265
|
-
try req.content.encode(user)
|
|
266
|
-
}, afterResponse: { res in
|
|
267
|
-
XCTAssertEqual(res.status, .ok)
|
|
268
|
-
let created = try res.content.decode(User.self)
|
|
269
|
-
XCTAssertEqual(created.name, "John")
|
|
270
|
-
})
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
```
|
|
274
|
-
|
|
275
|
-
## Docker Production Setup
|
|
276
|
-
|
|
277
|
-
```dockerfile
|
|
278
|
-
FROM swift:5.9-jammy AS build
|
|
279
|
-
WORKDIR /app
|
|
280
|
-
|
|
281
|
-
COPY Package.swift Package.resolved ./
|
|
282
|
-
RUN swift package resolve
|
|
283
|
-
|
|
284
|
-
COPY . .
|
|
285
|
-
RUN swift build -c release --static-swift-stdlib
|
|
286
|
-
|
|
287
|
-
FROM ubuntu:22.04
|
|
288
|
-
WORKDIR /app
|
|
289
|
-
|
|
290
|
-
RUN apt-get update && apt-get install -y \
|
|
291
|
-
libcurl4 \
|
|
292
|
-
libxml2 \
|
|
293
|
-
ca-certificates \
|
|
294
|
-
&& rm -rf /var/lib/apt/lists/*
|
|
295
|
-
|
|
296
|
-
COPY --from=build /app/.build/release/Run ./Run
|
|
297
|
-
|
|
298
|
-
RUN useradd -m -u 1000 vapor
|
|
299
|
-
USER vapor
|
|
300
|
-
|
|
301
|
-
EXPOSE 8080
|
|
302
|
-
ENV VAPOR_ENV=production
|
|
303
|
-
|
|
304
|
-
ENTRYPOINT ["./Run"]
|
|
305
|
-
CMD ["serve", "--hostname", "0.0.0.0", "--port", "8080"]
|
|
306
|
-
```
|
|
307
|
-
|
|
308
|
-
## Environment Configuration
|
|
309
|
-
|
|
310
|
-
```swift
|
|
311
|
-
import Vapor
|
|
312
|
-
|
|
313
|
-
func configure(_ app: Application) async throws {
|
|
314
|
-
switch app.environment {
|
|
315
|
-
case .production:
|
|
316
|
-
app.logger.logLevel = .warning
|
|
317
|
-
case .development:
|
|
318
|
-
app.logger.logLevel = .debug
|
|
319
|
-
default:
|
|
320
|
-
break
|
|
321
|
-
}
|
|
322
|
-
|
|
323
|
-
// Database URL from environment
|
|
324
|
-
if let databaseURL = Environment.get("DATABASE_URL") {
|
|
325
|
-
try app.databases.use(.postgres(url: databaseURL), as: .psql)
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
```
|
|
329
|
-
|
|
330
|
-
## Performance Tips
|
|
331
|
-
|
|
332
|
-
- Use async/await throughout
|
|
333
|
-
- Leverage connection pooling
|
|
334
|
-
- Implement caching where appropriate
|
|
335
|
-
- Use database indexes
|
|
336
|
-
- Profile with Instruments
|
|
337
|
-
- Enable release optimizations
|
|
338
|
-
- Use EventLoopFuture batching for multiple operations
|
|
339
|
-
- Implement pagination for large datasets
|
|
340
|
-
|
|
341
|
-
## Best Practices
|
|
342
|
-
|
|
343
|
-
- Use proper error handling with `Abort`
|
|
344
|
-
- Validate user input
|
|
345
|
-
- Implement authentication/authorization
|
|
346
|
-
- Use migrations for database schema changes
|
|
347
|
-
- Write comprehensive tests
|
|
348
|
-
- Use environment variables for configuration
|
|
349
|
-
- Implement health check endpoints
|
|
350
|
-
- Log appropriately
|
|
351
|
-
- Use middlewares for cross-cutting concerns
|
|
352
|
-
- Keep controllers thin, logic in services
|