{"id":25526035,"url":"https://github.com/rikilele/kyuko","last_synced_at":"2025-04-11T04:51:21.574Z","repository":{"id":48453755,"uuid":"382645299","full_name":"rikilele/kyuko","owner":"rikilele","description":"Fast and easy http framework for Deno Deploy 🦕","archived":false,"fork":false,"pushed_at":"2021-11-08T09:49:38.000Z","size":211,"stargazers_count":18,"open_issues_count":3,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-22T12:08:01.035Z","etag":null,"topics":["deno","denodeploy","express","http","typescript"],"latest_commit_sha":null,"homepage":"https://deno.land/x/kyuko","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rikilele.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2021-07-03T15:13:42.000Z","updated_at":"2022-10-13T12:23:32.000Z","dependencies_parsed_at":"2022-09-15T03:22:00.937Z","dependency_job_id":null,"html_url":"https://github.com/rikilele/kyuko","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rikilele%2Fkyuko","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rikilele%2Fkyuko/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rikilele%2Fkyuko/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rikilele%2Fkyuko/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rikilele","download_url":"https://codeload.github.com/rikilele/kyuko/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248345289,"owners_count":21088243,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deno","denodeploy","express","http","typescript"],"created_at":"2025-02-19T21:15:56.305Z","updated_at":"2025-04-11T04:51:21.553Z","avatar_url":"https://github.com/rikilele.png","language":"TypeScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"[![ci](https://github.com/rikilele/kyuko/actions/workflows/ci.yml/badge.svg)](https://github.com/rikilele/kyuko/actions/workflows/ci.yml)\n[![GitHub release (latest by date)](https://img.shields.io/github/v/release/rikilele/kyuko)](https://github.com/rikilele/kyuko/releases)\n[![deno doc](https://doc.deno.land/badge.svg)](https://doc.deno.land/https/deno.land/x/kyuko/mod.ts)\n\n\u003e Fast and easy http framework for Deno Deploy 🦕\n\nKyuko is an ultra-light http framework for apps hosted on\n[Deno Deploy](https://deno.com/deploy).\n\nIt aims to provide developers with a similar experience to using\n[Express](https://expressjs.com/),\n[hence its name](https://translate.google.com/?sl=ja\u0026tl=en\u0026text=%E6%80%A5%E8%A1%8C\u0026op=translate\u0026hl=en).\n\n**Table of Contents**\n\n- [Hello World](#hello-world) and [Usage](#usage) to get started quickly\n- [Philosophy](#philosophy) to learn more about the apps Kyuko serves well\n- [Guide](#guide) to read an in-depth introduction on how to use Kyuko\n\n# Hello World\n\nDeployed at https://kyuko.deno.dev\n\n```js\nimport { Kyuko } from \"https://deno.land/x/kyuko/mod.ts\";\n\nconst app = new Kyuko();\n\napp.get(\"/\", (req, res) =\u003e {\n  res.send(\"Hello World!\");\n});\n\napp.get(\"/:name\", (req, res) =\u003e {\n  res.send(`Hello ${req.params.name}!`);\n});\n\napp.listen();\n```\n\n# Usage\n\nTo run your Kyuko app locally using `deployctl`:\n\n```sh\ndeployctl run --libs=\"\" your_kyuko_app.ts\n```\n\n# Philosophy\n\nKyuko is an http framework for Deno Deploy that aims to be **`fast`** and\n**`easy`**.\n\n### Fast\n\nKyuko provides the bare minimum functionality of an http framework: routing,\napplication-level middleware, and error handling. By focusing on what is only\nabsolutely necessary, Kyuko powers apps that are **`fast`** by default.\n\n### Easy\n\nKyuko offers a set of functionality that is light and well-documented, saving\ndevelopers from having to guess what is happening from outside a black box.\nPredictability makes Kyuko a framework that is extremely **`easy`** to adopt.\n\n# Guide\n\nFor the API reference, visit the Kyuko\n[Deno Doc](https://doc.deno.land/https/deno.land/x/kyuko/mod.ts).\n\n## Table of Contents\n\n1. [Routing](#routing)\n1. [Middleware](#middleware)\n1. [Error Handling](#error-handling)\n1. [Event Lifecycle](#event-lifecycle)\n\n## Routing\n\nFrom [Express](https://expressjs.com/en/starter/basic-routing.html):\n\n\u003e **_Routing_** refers to determining how an application responds to a client\n\u003e request to a particular endpoint, which is [a path] and a specific HTTP\n\u003e request method (GET, POST, and so on).\n\nKyuko allows developers to register a route handler to a route path in the\nfollowing manner:\n\n```js\napp.METHOD(PATH, HANDLER);\n```\n\nWhere:\n\n- `app` is an instance of\n  [`Kyuko`](https://doc.deno.land/https/deno.land/x/kyuko/mod.ts#Kyuko)\n- `METHOD` is an http request method in lowercase\n- `PATH` is a valid [route path](#route-paths)\n- `HANDLER` is the\n  [`KyukoRouteHandler`](https://doc.deno.land/https/deno.land/x/kyuko/mod.ts#KyukoRouteHandler)\n  executed when the route is matched\n\nOnly a single route handler is registered for a specific route path. When\nmultiple handlers are registered under the same route path via `app.METHOD()`,\nthe last route handler will be registered.\n\n### Route Paths\n\nRoute paths define endpoints at which requests can be made. They consist of\nsegments that can either be concrete or a wildcard. In the following example,\n`users` is a concrete segment, while `:userId` is a wildcard segment. The\nexample will handle GET requests that are sent to `\"/users/Alice\"`, but not\nrequests that are sent to `\"/\"`, `\"/users\"`, `\"/users/Alice/friends\"`, etc.\n\n```js\napp.get(\"/users/:userId\", (req, res) =\u003e {\n  const { userId } = req.params;\n  res.send(`Hello ${userId}!`);\n});\n```\n\nResponse:\n\n```\nHello Alice!\n```\n\nKyuko only officially supports route paths that consist of\n[unreserved characters](https://datatracker.ietf.org/doc/html/rfc3986#section-2.3).\nThe behavior for when a route path consisting of other characters is registered\nis undefined.\n\n### Slashes in Paths\n\n- Recurring leading slashes will be merged and considered as one slash\n- Recurring slashes that appear mid-path will contribute to empty paths\n- A single trailing slash will be ignored\n\nFor more detail, refer to\n[RFC3986](https://datatracker.ietf.org/doc/html/rfc3986).\n\n**[↑ back to top](#guide)**\n\n## Middleware\n\nKyuko allows developers to register application-level middleware in the\nfollowing manner:\n\n```js\napp.use(MIDDLEWARE);\n```\n\nWhere:\n\n- `app` is an instance of\n  [`Kyuko`](https://doc.deno.land/https/deno.land/x/kyuko/mod.ts#Kyuko)\n- `MIDDLEWARE` is the\n  [`KyukoMiddleware`](https://doc.deno.land/https/deno.land/x/kyuko/mod.ts#KyukoMiddleware)\n  that is run on each request\n\nMultiple middleware can be registered on a Kyuko application. Middleware are\nalways called in order of registration, and will all run until completion unless\nan error is thrown.\n\nMiddleware functions can perform the following tasks:\n\n- Execute any code\n- Make changes to the request and response objects\n- Send a response\n- Defer logic until after route handling\n\n### Sending Responses\n\nTake note of the following points when choosing to send responses in middleware:\n\n1. Check `res.wasSent()` beforehand to make sure that no other middleware have\n   sent a response already\n1. The route handler that was assigned to the request **will not run** if a\n   middleware responds early\n\n**[↑ back to top](#guide)**\n\n## Error Handling\n\nKyuko allows developers to register application-level error handlers in the\nfollowing manner:\n\n```js\napp.error(HANDLER);\n```\n\nWhere:\n\n- `app` is an instance of\n  [`Kyuko`](https://doc.deno.land/https/deno.land/x/kyuko/mod.ts#Kyuko)\n- `HANDLER` is the\n  [`KyukoErrorHandler`](https://doc.deno.land/https/deno.land/x/kyuko/mod.ts#KyukoErrorHandler)\n  that is run when errors are thrown\n\nLike middleware, multiple error handlers can be registered on a Kyuko\napplication. Error handlers are called when an error is thrown during execution\nof middleware or a route handler. Error handlers are called in order of\nregistration, and will all run until completion unless an error is thrown from\nthe error handlers.\n\nError handlers can perform the following tasks:\n\n- Execute any code\n- Make changes to the error, request, and response objects\n- Send a response\n\n### Sending Responses\n\nCheck `res.wasSent()` before sending a response from an error handler to make\nsure that a response wasn't sent already.\n\n**[↑ back to top](#guide)**\n\n## Event Lifecycle\n\nHere is a very simple Deno Deploy script:\n\n```js\naddEventListener(\"fetch\", (event) =\u003e {\n  const response = new Response(\"Hello World!\");\n  event.respondWith(response);\n});\n```\n\nAs shown, a simple Deno Deploy script essentially receives fetch events, and\ncreates responses to respond with.\n\nKyuko adds routing, middleware, and error handling to the event lifecycle. Here\nare the specific steps taken, when an event is first received until the event is\nresponded to within a Kyuko app:\n\n---\n\n1. **`[SETUP]` Extraction of request information**\n\n   The `req` object is created from the `event` received. The url path of the\n   request is also extracted from the request information, for use in the next\n   step.\n\n1. **`[ROUTING]` Finding a route handler**\n\n   A registered route path is matched from the request url path, and is used to\n   determine the route handler. If no registered route paths match the request\n   url path, a default handler that returns a 404 Not Found is selected to\n   handle the request. A custom default handler can be registered via\n   `app.default()`.\n\n   \u003e Note: only **one** route handler is chosen for each request.\n\n1. **`[SETUP`] Creation of `req.params` and `req.query`**\n\n   If a registered route path was found, the `req.params` object is populated to\n   contain pairs of wildcard segments to corresponding url path segments.\n\n1. **`[MIDDLEWARE]` Running middleware**\n\n   Middleware registered via `app.use()` are run in this step. The middleware\n   are given access to the `req` and `res` objects, and are free to modify them\n   as needed. All middleware will run in order of registration and until\n   completion, unless an error is thrown.\n\n   Middleware also can choose to `defer()` logic until after the\n   `[ROUTE HANDLING]` step is completed.\n\n   A middleware can choose to respond early to an event by calling `res.send()`,\n   `res.redirect()`, etc. In that case, the `[ROUTE HANDLING]` step will not be\n   taken, and skips over to the `[DEFERRED HANDLERS]` step.\n\n1. **`[ROUTE HANDLING]` Running the route handler**\n\n   The **one** route handler that was chosen in the `[ROUTING]` step will be\n   executed in this step. The route handler will not run however, if\n\n   - A middleware chose to respond early\n   - A middleware threw an error AND the error handler responded early\n\n1. **`[DEFERRED HANDLERS]` Runs deferred handlers**\n\n   Logic that is deferred in the `[MIDDLEWARE]` are run in this step. The logic\n   will be handled LIFO, and will all run until completion unless an error is\n   thrown. A deferred logic can also choose to respond (late) to the request.\n\n1. **`[ERROR HANDLING]` Handling errors**\n\n   This step is run only if an error was thrown during the `[MIDDLEWARE]`,\n   `[ROUTE HANDLING]`, or `[DEFERRED HANDLERS]` steps. Error handlers registered\n   via `app.error()` are run in order of registration and until completion. They\n   are given access to the `err` thrown and the `req` and `res` objects, and are\n   free to modify them as needed.\n\n   Error handlers can choose to respond to the request by calling `res.send()`,\n   `res.redirect()`, etc. If not, a 500 Internal Server Error is used as a\n   default response.\n\n---\n\n**[↑ back to top](#guide)**\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frikilele%2Fkyuko","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frikilele%2Fkyuko","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frikilele%2Fkyuko/lists"}