@el-j/magic-helix-core 4.0.0-beta.2 → 4.0.0-beta.4

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.
Files changed (165) hide show
  1. package/dist/index-B88j4AyE.js +13 -0
  2. package/dist/index-B88j4AyE.js.map +1 -0
  3. package/dist/index-CY-pQbuu.cjs +2 -0
  4. package/dist/index-CY-pQbuu.cjs.map +1 -0
  5. package/dist/index.cjs +75 -1
  6. package/dist/index.cjs.map +1 -1
  7. package/dist/index.d.ts +0 -1
  8. package/dist/index.mjs +2214 -51
  9. package/dist/index.mjs.map +1 -1
  10. package/dist/pattern-combiner.d.ts +1 -1
  11. package/dist/plugin-loader.d.ts +2 -1
  12. package/package.json +4 -4
  13. package/dist/BasePlugin-6wv0hYJ9.js +0 -98
  14. package/dist/BasePlugin-6wv0hYJ9.js.map +0 -1
  15. package/dist/BasePlugin-odQJAKA-.cjs +0 -2
  16. package/dist/BasePlugin-odQJAKA-.cjs.map +0 -1
  17. package/dist/builtin-plugins/base/BasePlugin.d.ts +0 -69
  18. package/dist/builtin-plugins/cpp/index.d.ts +0 -46
  19. package/dist/builtin-plugins/csharp/index.d.ts +0 -20
  20. package/dist/builtin-plugins/go/index.d.ts +0 -23
  21. package/dist/builtin-plugins/index.d.ts +0 -16
  22. package/dist/builtin-plugins/java/index.d.ts +0 -22
  23. package/dist/builtin-plugins/nodejs/index.d.ts +0 -44
  24. package/dist/builtin-plugins/php/index.d.ts +0 -20
  25. package/dist/builtin-plugins/python/index.d.ts +0 -27
  26. package/dist/builtin-plugins/ruby/index.d.ts +0 -20
  27. package/dist/builtin-plugins/rust/index.d.ts +0 -53
  28. package/dist/builtin-plugins/swift/index.d.ts +0 -22
  29. package/dist/default_templates/angular/angular-core.md +0 -19
  30. package/dist/default_templates/architecture/codeowners.md +0 -123
  31. package/dist/default_templates/architecture/monorepo.md +0 -146
  32. package/dist/default_templates/architecture/nx.md +0 -122
  33. package/dist/default_templates/architecture/turborepo.md +0 -114
  34. package/dist/default_templates/ci/github-actions.md +0 -268
  35. package/dist/default_templates/ci/gitlab-ci.md +0 -330
  36. package/dist/default_templates/containers/docker-multistage.md +0 -120
  37. package/dist/default_templates/containers/kubernetes-deploy.md +0 -210
  38. package/dist/default_templates/devops/docker-compose.md +0 -111
  39. package/dist/default_templates/devops/docker-dockerfile.md +0 -94
  40. package/dist/default_templates/devops/github-actions.md +0 -160
  41. package/dist/default_templates/devops/gitlab-ci.md +0 -210
  42. package/dist/default_templates/dotnet/framework-aspnetcore.md +0 -205
  43. package/dist/default_templates/dotnet/framework-blazor.md +0 -271
  44. package/dist/default_templates/dotnet/lang-csharp.md +0 -162
  45. package/dist/default_templates/generic/lang-typescript.md +0 -57
  46. package/dist/default_templates/generic/state-redux.md +0 -21
  47. package/dist/default_templates/generic/state-rxjs.md +0 -6
  48. package/dist/default_templates/generic/style-mui.md +0 -23
  49. package/dist/default_templates/generic/style-tailwind.md +0 -76
  50. package/dist/default_templates/generic/test-cypress.md +0 -21
  51. package/dist/default_templates/generic/test-jest.md +0 -20
  52. package/dist/default_templates/generic/test-playwright.md +0 -21
  53. package/dist/default_templates/generic/test-vitest.md +0 -131
  54. package/dist/default_templates/go/lang-go.md +0 -571
  55. package/dist/default_templates/java/build-gradle.md +0 -102
  56. package/dist/default_templates/java/build-maven.md +0 -86
  57. package/dist/default_templates/java/framework-spring-boot.md +0 -179
  58. package/dist/default_templates/java/lang-java.md +0 -78
  59. package/dist/default_templates/java/lang-kotlin.md +0 -88
  60. package/dist/default_templates/meta/magic-helix-meta.md +0 -213
  61. package/dist/default_templates/meta/meta-debug.md +0 -459
  62. package/dist/default_templates/meta/meta-implement.md +0 -450
  63. package/dist/default_templates/meta/meta-roadmap.md +0 -265
  64. package/dist/default_templates/nestjs/nestjs-core.md +0 -7
  65. package/dist/default_templates/patterns/architecture/clean-architecture.md +0 -469
  66. package/dist/default_templates/patterns/architecture/dependency-injection.md +0 -517
  67. package/dist/default_templates/patterns/architecture/domain-driven-design.md +0 -621
  68. package/dist/default_templates/patterns/architecture/layered-architecture.md +0 -382
  69. package/dist/default_templates/patterns/architecture/repository-pattern.md +0 -408
  70. package/dist/default_templates/patterns/domain-expertise/nextjs-rules.md +0 -115
  71. package/dist/default_templates/patterns/domain-expertise/react-patterns.md +0 -181
  72. package/dist/default_templates/patterns/domain-expertise/server-components.md +0 -212
  73. package/dist/default_templates/patterns/domain-expertise/shadcn-ui.md +0 -52
  74. package/dist/default_templates/patterns/domain-expertise/tailwind-patterns.md +0 -52
  75. package/dist/default_templates/patterns/environment/container-awareness.md +0 -17
  76. package/dist/default_templates/patterns/environment/ide-features.md +0 -17
  77. package/dist/default_templates/patterns/environment/os-commands.md +0 -17
  78. package/dist/default_templates/patterns/organization/heading-hierarchy.md +0 -103
  79. package/dist/default_templates/patterns/organization/sequential-workflows.md +0 -102
  80. package/dist/default_templates/patterns/organization/xml-rule-groups.md +0 -64
  81. package/dist/default_templates/patterns/reasoning/agent-loop.md +0 -151
  82. package/dist/default_templates/patterns/reasoning/confirmation-gates.md +0 -141
  83. package/dist/default_templates/patterns/reasoning/dependency-analysis.md +0 -132
  84. package/dist/default_templates/patterns/reasoning/one-tool-per-iteration.md +0 -152
  85. package/dist/default_templates/patterns/reasoning/preview-before-action.md +0 -194
  86. package/dist/default_templates/patterns/reasoning/reflection-checkpoints.md +0 -166
  87. package/dist/default_templates/patterns/reasoning/result-verification.md +0 -157
  88. package/dist/default_templates/patterns/reasoning/subtask-breakdown.md +0 -131
  89. package/dist/default_templates/patterns/reasoning/thinking-tags.md +0 -100
  90. package/dist/default_templates/patterns/role-definition/capability-declarations.md +0 -72
  91. package/dist/default_templates/patterns/role-definition/expert-identity.md +0 -45
  92. package/dist/default_templates/patterns/role-definition/scope-boundaries.md +0 -61
  93. package/dist/default_templates/patterns/safety/code-safety-rules.md +0 -17
  94. package/dist/default_templates/patterns/safety/credential-handling.md +0 -17
  95. package/dist/default_templates/patterns/safety/destructive-warnings.md +0 -17
  96. package/dist/default_templates/patterns/safety/refusal-messages.md +0 -17
  97. package/dist/default_templates/patterns/tone/adaptive-tone.md +0 -17
  98. package/dist/default_templates/patterns/tone/concise-communication.md +0 -17
  99. package/dist/default_templates/patterns/tone/forbidden-phrases.md +0 -17
  100. package/dist/default_templates/patterns/tool-guidelines/function-schemas.md +0 -143
  101. package/dist/default_templates/patterns/tool-guidelines/parameter-examples.md +0 -137
  102. package/dist/default_templates/patterns/tool-guidelines/usage-policies.md +0 -105
  103. package/dist/default_templates/php/framework-laravel.md +0 -112
  104. package/dist/default_templates/php/lang-php.md +0 -94
  105. package/dist/default_templates/python/lang-python.md +0 -508
  106. package/dist/default_templates/react/react-core.md +0 -677
  107. package/dist/default_templates/react/react-zustand.md +0 -7
  108. package/dist/default_templates/ruby/framework-rails.md +0 -309
  109. package/dist/default_templates/ruby/framework-sinatra.md +0 -227
  110. package/dist/default_templates/ruby/lang-ruby.md +0 -216
  111. package/dist/default_templates/rust/lang-rust.md +0 -89
  112. package/dist/default_templates/swift/framework-vapor.md +0 -352
  113. package/dist/default_templates/swift/lang-swift.md +0 -291
  114. package/dist/default_templates/vue/style-primevue.md +0 -6
  115. package/dist/default_templates/vue/style-quasar.md +0 -22
  116. package/dist/default_templates/vue/vue-core.md +0 -108
  117. package/dist/default_templates/vue/vue-pinia.md +0 -5
  118. package/dist/index-0GK4RlUx.js +0 -1748
  119. package/dist/index-0GK4RlUx.js.map +0 -1
  120. package/dist/index-AkVwRl-r.js +0 -92
  121. package/dist/index-AkVwRl-r.js.map +0 -1
  122. package/dist/index-B6BeG1yT.cjs +0 -68
  123. package/dist/index-B6BeG1yT.cjs.map +0 -1
  124. package/dist/index-B8pyjKdF.js +0 -94
  125. package/dist/index-B8pyjKdF.js.map +0 -1
  126. package/dist/index-BQ6v041y.js +0 -13
  127. package/dist/index-BQ6v041y.js.map +0 -1
  128. package/dist/index-Baxb1vI_.js +0 -210
  129. package/dist/index-Baxb1vI_.js.map +0 -1
  130. package/dist/index-Bg8DD8ku.js +0 -216
  131. package/dist/index-Bg8DD8ku.js.map +0 -1
  132. package/dist/index-BqTqxCpG.cjs +0 -89
  133. package/dist/index-BqTqxCpG.cjs.map +0 -1
  134. package/dist/index-Bv4Q1Pr7.cjs +0 -33
  135. package/dist/index-Bv4Q1Pr7.cjs.map +0 -1
  136. package/dist/index-CN8J45Nc.cjs +0 -24
  137. package/dist/index-CN8J45Nc.cjs.map +0 -1
  138. package/dist/index-CPbv2Od1.js +0 -62
  139. package/dist/index-CPbv2Od1.js.map +0 -1
  140. package/dist/index-Cf-MC6Al.js +0 -63
  141. package/dist/index-Cf-MC6Al.js.map +0 -1
  142. package/dist/index-DDPXXXDy.cjs +0 -19
  143. package/dist/index-DDPXXXDy.cjs.map +0 -1
  144. package/dist/index-DO30AzDe.cjs +0 -19
  145. package/dist/index-DO30AzDe.cjs.map +0 -1
  146. package/dist/index-DkvW5yBY.js +0 -2249
  147. package/dist/index-DkvW5yBY.js.map +0 -1
  148. package/dist/index-Dn1ehjIj.cjs +0 -80
  149. package/dist/index-Dn1ehjIj.cjs.map +0 -1
  150. package/dist/index-DqHvgoXJ.cjs +0 -19
  151. package/dist/index-DqHvgoXJ.cjs.map +0 -1
  152. package/dist/index-K39pdw94.cjs +0 -31
  153. package/dist/index-K39pdw94.cjs.map +0 -1
  154. package/dist/index-OT2XAJkc.js +0 -117
  155. package/dist/index-OT2XAJkc.js.map +0 -1
  156. package/dist/index-TPAX4XKg.cjs +0 -30
  157. package/dist/index-TPAX4XKg.cjs.map +0 -1
  158. package/dist/index-WmVSB57y.js +0 -107
  159. package/dist/index-WmVSB57y.js.map +0 -1
  160. package/dist/index-mYXvc3Fs.js +0 -68
  161. package/dist/index-mYXvc3Fs.js.map +0 -1
  162. package/dist/index-nioXOg4m.cjs +0 -76
  163. package/dist/index-nioXOg4m.cjs.map +0 -1
  164. package/dist/index-okhY3fWD.cjs +0 -2
  165. 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