Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Macros #91

Merged
merged 55 commits into from
Jun 23, 2024
Merged

Macros #91

merged 55 commits into from
Jun 23, 2024

Conversation

joshuawright11
Copy link
Member

@joshuawright11 joshuawright11 commented Jun 20, 2024

Now with Macros!

Adds a few macros to streamline building with Alchemy.

Routing

Use @{METHOD} to generate a route handler that automatically pulls function parameters from incoming requests and converts the return type to a response. Annotating your Application or Controller will automatically register the handlers, or you can access them via $nameOfTheFunction.

@Application
struct App {
    
    @POST("/user")
    func createUser(email: String, password: String) async throws -> User {
        // create user with parsed `email & `password`
    }
}

Automatically validate parameters with @Validate and a library (Coming Soon™️) of built in validators.

@Controller
struct UserController {
    
    @PATCH("/email")
    func updateEmail(@Validate(.email) email: String) async throws {
        // email is valid!
    }
}

Jobs

Quickly create a background job with just a function (global or static). Use the $ prefix to refer to the job.

@Job
func sendInvoice(email: String) async throws {
    ...
}

// run in foreground
try await sendInvoice(email: "[email protected]") 

// run as a background job
try await $sendInvoice(email: "[email protected]").dispatch()

Rune

Define models with the @Model macro.

@Model
struct User {
    var id: UUID
    var email: String
    var name: String
}

This unlocks some major quality of life improvements including type safe, KeyPath-based query builders which are Coming Soon™️

Relationships

Relationships look similar but get some powerful quality of life improvements including better join column inference, CRUD functions, and the ability to be defined in extensions.

struct Todo {
    var id: Int
    var name: String
    var isDone = false
   
    @BelongsToMany var tags: [Tag]
}

extension User {
    @HasMany var tags: [Tag]
}

// eager load with `$relationship`
User.query().with(\.$todos)

// chain relationships for nested loads (this loads todos & tags)
User.query().with(\.$todos.$tags)

// associates a todo with a user
let todo = Todo(name: "do laundry")
try await user.$todos.connect(todo)

If loaded, relationships are automatically encoded from route handlers.

@GET("/todos")
func getTodos() -> [Todo] {
    try await Todo.with(\.$tags).all()
}
[
    {
        "id": 1,
        "name": "Build great backends with Alchemy",
        "tags": [
            {
                "id": 1,
                "name": "Coding"
            },
            {
                "id": 2,
                "name": "Extremely Fun"
            }
        ]
    },
    {
        "id": 2,
        "name": "Make cookies",
        "tags": [
            {
                "id": 3,
                "name": "Cooking"
            }
        ]
    }
]

@joshuawright11 joshuawright11 merged commit eaa8e94 into main Jun 23, 2024
2 checks passed
@joshuawright11 joshuawright11 deleted the macros branch June 23, 2024 14:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant