### Create a 'Hello World' Jazzy Application Source: https://canermastan.github.io/jazzyframework/en/installation Define a simple route handler for the root path and start the Jazzy server on port 8080. This code requires the 'jazzy' import. ```nim import jazzy # Define a simple route handler proc home(ctx: Context) = ctx.text("Hello Jazzy!") # Register the route Route.get("/", home) # Serve on port 8080 Jazzy.serve(8080) ``` -------------------------------- ### Install Jazzy via Nimble Source: https://canermastan.github.io/jazzyframework/en/installation Use this command to install the Jazzy framework using the Nim package manager, Nimble. Ensure Nim version 2.0.0 or higher is installed. ```bash nimble install jazzy ``` -------------------------------- ### Define Basic GET and POST Routes Source: https://canermastan.github.io/jazzyframework/en/routing Use closures for simple route definitions. All route handlers must be async. ```nim import jazzy # Basic GET route Route.get("/", proc(ctx: Context) {.async.} = ctx.text("Welcome Home") ) # POST route Route.post("/users", proc(ctx: Context) {.async.} = ctx.status(201).text("User Created") ) ``` -------------------------------- ### Implement Type-Safe Configuration Accessor Source: https://canermastan.github.io/jazzyframework/en/configuration For type safety, wrap `getConfig` in your own procedures to parse and return configuration values with specific types. This example shows how to get the application port as an integer. ```nim proc getPort*(): int = try: getConfig("APP_PORT").parseInt except: 8080 ``` -------------------------------- ### Define Environment Variables Source: https://canermastan.github.io/jazzyframework/en/configuration Place your application's configuration variables in a .env file in the project root. These variables are automatically loaded when the application starts. ```env APP_PORT=8080 JWT_SECRET=secret-key DATABASE_URL=app.db ``` -------------------------------- ### Jazzy Server Output Source: https://canermastan.github.io/jazzyframework/en/installation This is the expected output message when the Jazzy server starts successfully, indicating the address it is running on. ```text 🎷 Jazzy is dancing on http://localhost:8080 ``` -------------------------------- ### Apply Guard and Custom RBAC Middleware Source: https://canermastan.github.io/jazzyframework/en/authentication Combine the standard 'guard' middleware with custom middleware like 'adminOnly' within a Route group to protect specific paths. This example groups '/admin' routes, requiring both authentication and admin privileges. ```nim import jazzy/auth/middlewares import middlewares/auth_middleware Route.groupPath("/admin", @[guard, adminOnly]): Route.get("/dashboard", adminDashboard) Route.delete("/users/:id", deleteUser) ``` -------------------------------- ### Connect to Database Source: https://canermastan.github.io/jazzyframework/en/database Initialize the database connection in your application module. ```nim import jazzy connectDB("app.db") ``` -------------------------------- ### Run the Jazzy Application Source: https://canermastan.github.io/jazzyframework/en/installation Compile and run the 'app.nim' file using the Nim compiler with the '-r' flag for immediate execution. ```bash nim c -r app.nim ``` -------------------------------- ### Implement Service Pattern Source: https://canermastan.github.io/jazzyframework/en/controllers Delegate complex business logic to external service modules to keep controller code thin. ```nim import ../services/auth_service proc login*(ctx: Context) {.async.} = let email = ctx.input("email") let password = ctx.input("password") # Delegate complex logic to service let token = auth_service.attemptLogin(email, password) if token.len > 0: ctx.json(%*{"token": token}) else: ctx.status(401).json(%*{"error": "Invalid credentials"}) ``` -------------------------------- ### Handle File Uploads Source: https://canermastan.github.io/jazzyframework/en/controllers Access uploaded files via ctx.file and save them using standard file I/O operations. ```nim import std/os proc uploadAvatar*(ctx: Context) {.async.} = let file = ctx.file("avatar") if file.filename.len == 0: ctx.status(400).text("No file uploaded") return # Save the file content writeFile("public/uploads/" & file.filename, file.content) ctx.text("File uploaded successfully: " & file.filename) ``` -------------------------------- ### Access Input with input() Helper Source: https://canermastan.github.io/jazzyframework/en/requests Use the `input()` helper to retrieve values from query string parameters or the JSON body. It supports optional default values. ```nim proc store(ctx: Context) = # Works for /store?name=Jazzy OR {"name": "Jazzy"} let name = ctx.input("name") # With a default value let role = ctx.input("role", "guest") ctx.text("Hello " & name) ``` -------------------------------- ### Register Controllers in Router Source: https://canermastan.github.io/jazzyframework/en/controllers Import the controller module and map procedures to specific HTTP routes. ```nim import jazzy import controllers/user_controller Route.get("/users/:id", user_controller.show) Route.post("/users", user_controller.create) ``` -------------------------------- ### Execute Raw SQL Source: https://canermastan.github.io/jazzyframework/en/database Bypass the query builder for complex operations by using the underlying driver. ```nim import jazzy/db/database import tiny_sqlite let conn = getConn() for row in conn.iterate("SELECT u.name, p.title FROM users u JOIN posts p ON u.id = p.user_id"): echo row[0].strVal, " wrote ", row[1].strVal ``` -------------------------------- ### Access Configuration Values Source: https://canermastan.github.io/jazzyframework/en/configuration Import the jazzy module and use the `getConfig` function to retrieve environment variable values anywhere in your application. ```nim import jazzy let secret = getConfig("JWT_SECRET") ``` -------------------------------- ### Define Route with Dynamic Parameters Source: https://canermastan.github.io/jazzyframework/en/routing Capture dynamic segments of a URI using the ':' syntax. Captured values are available in `ctx.request.params`. ```nim Route.get("/users/:id", proc(ctx: Context) {.async.} = let userId = ctx.request.params.getOrDefault("id") ctx.text("Showing user profile for ID: " & userId) ) Route.get("/posts/:postId/comments/:commentId", proc(ctx: Context) {.async.} = let postId = ctx.request.params.getOrDefault("postId") let commentId = ctx.request.params.getOrDefault("commentId") ctx.text("Post " & postId & ", Comment " & commentId) ) ``` -------------------------------- ### Handle Preflight Requests Automatically Source: https://canermastan.github.io/jazzyframework/en/cors Demonstrates how the middleware intercepts OPTIONS preflight requests for defined routes. ```Nim Route.group(cors(allowedOrigin = "https://myfrontend.com")): Route.post("/submit", proc(ctx: Context) {.async.} = ctx.text("Data submitted!") ) ``` -------------------------------- ### Advanced Response Scenarios Source: https://canermastan.github.io/jazzyframework/en/responses Handling redirects, file downloads, and empty responses. ```APIDOC ## Advanced Responses ### Description Handling redirects, file downloads via Content-Disposition, and 204 No Content responses. ### Methods - Redirect: Set status 301/302 and Location header. - Download: Set Content-Type and Content-Disposition header. - Empty: Use status 204. ### Request Example ```nim # Redirect ctx.status(301).header("Location", "/new-home").text("Redirecting...") # Download ctx.header("Content-Type", "text/csv").header("Content-Disposition", "attachment; filename=\"report.csv\"").text(csvContent) # No Content ctx.status(204).text("") ``` ``` -------------------------------- ### Available Router Methods Source: https://canermastan.github.io/jazzyframework/en/routing Jazzy supports all standard HTTP verbs for defining routes. ```nim Route.get("/posts", listPosts) Route.post("/posts", createPost) Route.put("/posts/:id", updatePost) Route.patch("/posts/:id", patchPost) Route.delete("/posts/:id", deletePost) Route.options("/posts", handleOptions) ``` -------------------------------- ### Query Builder Chaining Source: https://canermastan.github.io/jazzyframework/en/database Multiple where calls are combined using AND logic. ```nim DB.table("users") .where("active", 1) .where("role", "admin") .get() # SELECT * FROM users WHERE active = 1 AND role = 'admin' ``` -------------------------------- ### Define a Controller Module Source: https://canermastan.github.io/jazzyframework/en/controllers Controllers must be Nim modules with procedures marked as {.async.}. These procedures handle requests by interacting with the Context object. ```nim import jazzy # Display a user profile proc show*(ctx: Context) {.async.} = let id = ctx.request.params.getOrDefault("id") # Fetch user from database let user = DB.table("users").where("id", id).first() ctx.json(%*{ "id": id, "user": user, "role": "member" }) # Create a new user proc create*(ctx: Context) {.async.} = let email = ctx.input("email") let password = ctx.input("password") # Hash the password let hashedPassword = hashPassword(password) # Insert the new user into the database let newId = DB.table("users").insert(%*{ "email": email, "password": hashedPassword, "role": "user" }) ctx.status(201).text("Created") ``` -------------------------------- ### Create Custom Admin Role Middleware Source: https://canermastan.github.io/jazzyframework/en/authentication Implement custom middleware like 'adminOnly' to enforce role-based access control. This middleware first checks for authentication and then verifies if the user's role is 'admin'. ```nim import jazzy let adminOnly*: MiddlewareProc = proc(ctx: Context, next: HandlerProc) {.async.} = # First, ensure they are logged in if not ctx.check(): ctx.status(401).json(%*{"error": "Unauthorized"}) return # Check Role let user = ctx.user().get() if user.hasKey("role") and user["role"].getStr == "admin": # User is Admin, proceed await next(ctx) else: # User is logged in but forbidden ctx.status(403).json(%*{"error": "Forbidden: Admins only"}) ``` -------------------------------- ### Response Methods Source: https://canermastan.github.io/jazzyframework/en/responses Methods for sending different content types like text, HTML, and JSON. ```APIDOC ## Sending Responses ### Description Methods to send plain text, HTML, or JSON responses. ### Methods - `ctx.text(string)`: Sends plain text (Content-Type: text/plain). - `ctx.html(string)`: Sends raw HTML (Content-Type: text/html). - `ctx.json(object)`: Sends JSON (Content-Type: application/json). ### Request Example ```nim ctx.text("pong") ctx.html("
Fast & Simple.
") ``` -------------------------------- ### Perform HTTP Redirect Source: https://canermastan.github.io/jazzyframework/en/responses Redirects a user by setting the status to 301 or 302 and providing a Location header. ```nim proc oldPage*(ctx: Context) {.async.} = # Redirect to the new homepage ctx.status(301) .header("Location", "/new-home") .text("Redirecting...") ``` -------------------------------- ### Force File Download Source: https://canermastan.github.io/jazzyframework/en/responses Forces a browser to download a response by setting the Content-Disposition header. ```nim proc downloadReport*(ctx: Context) {.async.} = let csvContent = "id,name\n1,Jazzy\n2,Nim" ctx.header("Content-Type", "text/csv") .header("Content-Disposition", "attachment; filename=\"report.csv\"") .text(csvContent) ``` -------------------------------- ### Read Request Headers Source: https://canermastan.github.io/jazzyframework/en/controllers Access request headers through the ctx.request.headers object to implement custom logic. ```nim proc debugInfo*(ctx: Context) {.async.} = if ctx.request.headers.hasKey("X-Debug-Mode"): ctx.text("Debug mode enabled") else: ctx.text("Normal mode") ``` -------------------------------- ### Fetch All Rows Source: https://canermastan.github.io/jazzyframework/en/database Retrieve all records from a specified table as a JsonNode array. ```nim let users = DB.table("users").get() # Returns a JsonNode (JArray) of objects ``` -------------------------------- ### Route Grouping with Path Prefixing Source: https://canermastan.github.io/jazzyframework/en/routing Group routes under a common URI prefix, useful for API versioning. ```nim Route.groupPath("/api/v1"): Route.get("/users", listUsers) # matches /api/v1/users Route.get("/posts", listPosts) # matches /api/v1/posts ``` -------------------------------- ### Nested Route Groups and Combinations Source: https://canermastan.github.io/jazzyframework/en/routing Nest route groups to create complex API structures, combining path prefixes and middleware. ```nim # Admin Routes: /admin/... Route.groupPath("/admin", guard): # Protected by 'guard' (Login check) # Dashboard Route.get("/dashboard", adminDashboard) # System Management: /admin/system/... Route.groupPath("/system"): Route.get("/logs", viewLogs) Route.delete("/cache", clearCache) ``` -------------------------------- ### Set Custom HTTP Headers Source: https://canermastan.github.io/jazzyframework/en/responses Chains the header method to define custom HTTP headers for the response. ```nim proc caching*(ctx: Context) {.async.} = ctx.header("Cache-Control", "no-cache") .status(200) .text("Fresh Content") ``` -------------------------------- ### Limit Results Source: https://canermastan.github.io/jazzyframework/en/database Restrict the number of returned records using the limit method. ```nim # Get the top 10 recent posts let posts = DB.table("posts").limit(10).get() ``` -------------------------------- ### Access User Data from JWT Payload Source: https://canermastan.github.io/jazzyframework/en/authentication Within protected routes, use ctx.check() to verify authentication status and ctx.user() to retrieve the JWT payload. This allows you to access user information like ID and role. ```nim proc getProfile*(ctx: Context) {.async.} = if ctx.check(): # Returns true if authenticated let user = ctx.user().get() # Returns Option[JsonNode] ctx.json(user) else: ctx.status(401).text("Who are you?") ``` -------------------------------- ### Apply Default CORS Middleware Source: https://canermastan.github.io/jazzyframework/en/cors Applies default CORS settings to a group of routes, allowing all origins and common HTTP methods. ```Nim import jazzy import jazzy/core/middlewares # Apply default CORS to all routes in this group Route.group(cors()): Route.get("/api/data", proc(ctx: Context) {.async.} = ctx.json(%*{"status": "success"}) ) ``` -------------------------------- ### Return JSON Data Source: https://canermastan.github.io/jazzyframework/en/controllers Use the ctx.json method to send structured JSON responses for API endpoints. ```nim proc apiIndex*(ctx: Context) {.async.} = ctx.json(%*{ "version": "1.0", "status": "healthy", "timestamp": 123456789 }) ``` -------------------------------- ### Send Empty Response Source: https://canermastan.github.io/jazzyframework/en/responses Sends a 204 No Content response, typically used for successful DELETE operations. ```nim proc deleteUser*(ctx: Context) {.async.} = # ... perform deletion ... ctx.status(204).text("") ``` -------------------------------- ### Set JWT Secret Key Source: https://canermastan.github.io/jazzyframework/en/authentication Configure your application's JWT secret key by setting the JWT_SECRET environment variable in your .env file. Ensure the key is a long, random string for security. ```env JWT_SECRET=super-secure-random-string-at-least-32-chars ``` -------------------------------- ### Fetch Single Row Source: https://canermastan.github.io/jazzyframework/en/database Retrieve the first record matching the criteria as a JsonNode object or JNull. ```nim let user = DB.table("users").where("id", 1).first() # Returns a JsonNode (JObject) or JNull if not found ``` -------------------------------- ### Protect Routes with Guard Middleware Source: https://canermastan.github.io/jazzyframework/en/authentication Apply the 'guard' middleware to routes that require a valid JWT token for access. This ensures that only authenticated users can reach protected endpoints. ```nim import jazzy/auth/middlewares Route.group(guard): Route.get("/profile", getProfile) ``` -------------------------------- ### Set HTTP Status Code Source: https://canermastan.github.io/jazzyframework/en/responses Chains the status method before sending content to define the HTTP response code. ```nim proc create*(ctx: Context) {.async.} = # Resource created ctx.status(201).json(%*{"id": 10}) ``` -------------------------------- ### Send JSON Response Source: https://canermastan.github.io/jazzyframework/en/responses Sends a JSON object or array with a Content-Type of application/json. ```nim proc api*(ctx: Context) {.async.} = ctx.json(%*{ "status": "success", "data": [1, 2, 3] }) ``` -------------------------------- ### Count Records Source: https://canermastan.github.io/jazzyframework/en/database Retrieve the count of records, optionally filtered by a where clause. ```nim let totalUsers = DB.table("users").count() let activeUsers = DB.table("users").where("active", 1).count() ``` -------------------------------- ### Send Plain Text Response Source: https://canermastan.github.io/jazzyframework/en/responses Sends a plain text response with a default Content-Type of text/plain. ```nim proc ping*(ctx: Context) {.async.} = ctx.text("pong") ``` -------------------------------- ### Insert Data Source: https://canermastan.github.io/jazzyframework/en/database Insert a new record using a JsonNode, returning the new row ID. ```nim let newUserId = DB.table("users").insert(%*{ "username": "caner", "email": "jcanermastan@gmail.com", "created_at": "2023-10-27" }) ``` -------------------------------- ### Input Validation with Jazzy's Engine Source: https://canermastan.github.io/jazzyframework/en/requests Validate input data against a set of rules. If validation fails, Jazzy automatically returns a 422 Unprocessable Entity response. The `data` variable will contain the validated `JsonNode` if successful. ```nim proc register(ctx: Context) = let data = ctx.validate(%*{ "username": "required|min:3|max:20", "email": "required|string", "age": "int|min:18" }) # If we reach here, validation PASSED. # 'data' contains the validated JsonNode. let user = DB.table("users").insert(data) ctx.json(%*{"status": "success", "id": user}) ``` -------------------------------- ### Type-Safe Body Parsing with bodyAs() Source: https://canermastan.github.io/jazzyframework/en/requests Parse incoming JSON data directly into a typed object using `bodyAs()`. This ensures type safety for structured JSON input. ```nim type UserDto = object username: string age: int proc create(ctx: Context) = let dto = ctx.bodyAs(UserDto) # dto.username and dto.age are now typed values! echo dto.username ``` -------------------------------- ### Delete Data Source: https://canermastan.github.io/jazzyframework/en/database Remove records matching the where clause. Warning: omitting where will wipe the table. ```nim DB.table("users").where("id", 5).delete() ``` -------------------------------- ### Customize CORS Allowed Origins Source: https://canermastan.github.io/jazzyframework/en/cors Restricts CORS access to a specific origin by passing the allowedOrigin parameter to the middleware. ```Nim # Restrict to a specific origin Route.group(cors(allowedOrigin = "https://example.com")): Route.get("/custom", proc(ctx: Context) {.async.} = ctx.text("custom") ) ``` -------------------------------- ### Update Data Source: https://canermastan.github.io/jazzyframework/en/database Modify existing records. Updates affect all rows matching the where clause. ```nim # Deactivate user #5 DB.table("users") .where("id", 5) .update(%*{"active": 0}) # Mark all users as verified DB.table("users").update(%*{"verified": 1}) ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.