{"id":18317891,"url":"https://github.com/idiocc/idio","last_synced_at":"2025-11-07T06:04:28.482Z","repository":{"id":57117949,"uuid":"186269475","full_name":"idiocc/idio","owner":"idiocc","description":"@Goa/Koa Web Server Bundled With Essential Middleware, SSR And Router.","archived":false,"fork":false,"pushed_at":"2020-03-12T08:35:55.000Z","size":5212,"stargazers_count":2,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-10-21T19:59:17.821Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"https://www.idio.cc","language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"agpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/idiocc.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2019-05-12T15:06:49.000Z","updated_at":"2020-03-12T08:35:58.000Z","dependencies_parsed_at":"2022-08-23T09:31:06.520Z","dependency_job_id":null,"html_url":"https://github.com/idiocc/idio","commit_stats":null,"previous_names":[],"tags_count":25,"template":false,"template_full_name":null,"purl":"pkg:github/idiocc/idio","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fidio","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fidio/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fidio/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fidio/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/idiocc","download_url":"https://codeload.github.com/idiocc/idio/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fidio/sbom","scorecard":{"id":481419,"data":{"date":"2025-08-11","repo":{"name":"github.com/idiocc/idio","commit":"3a2d15b29889205da6f74ffd410e7030c91ac3c4"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3.4,"checks":[{"name":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/nodejs.yml:1","Info: no jobLevel write permissions found"],"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":10,"reason":"no dangerous workflow patterns detected","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:15: update your workflow using https://app.stepsecurity.io/secureworkflow/idiocc/idio/nodejs.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/nodejs.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/idiocc/idio/nodejs.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned"],"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: GNU Affero General Public License v3.0: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-19T16:44:30.716Z","repository_id":57117949,"created_at":"2025-08-19T16:44:30.716Z","updated_at":"2025-08-19T16:44:30.716Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":283136766,"owners_count":26785489,"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","status":"online","status_checked_at":"2025-11-07T02:00:06.343Z","response_time":61,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":[],"created_at":"2024-11-05T18:07:47.992Z","updated_at":"2025-11-07T06:04:28.455Z","avatar_url":"https://github.com/idiocc.png","language":"JavaScript","funding_links":["https://opencollective.com/nodetools"],"categories":[],"sub_categories":[],"readme":"# @idio/idio\n\n[![npm version](https://badge.fury.io/js/%40idio%2Fidio.svg)](https://www.npmjs.com/package/@idio/idio)\n![Node.js CI](https://github.com/idiocc/idio/workflows/Node.js%20CI/badge.svg)\n\n\u003ca href=\"https://github.com/idiocc/idio\"\u003e\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/logo.svg?sanitize=true\" width=\"150\" align=\"left\"\u003e\u003c/a\u003e\n\n`@idio/idio` contains Koa's fork called Goa \u0026mdash; web server compiled with _Closure Compiler_ so that its source code is optimised and contains only 1 external dependency (`mime-db`). Idio adds essential middleware to Goa for session, static files, CORS and compression and includes the router. As the project grows, more middleware will be added and optimised.\n\nThis is a production-ready server that puts all components together for the ease of use, while providing great developer experience using JSDoc annotations for auto-completions. _Idio_ is not a framework, but a library that enables **idiomatic** usage and compilation of the server and middleware.\n\n\u003cp align=\"center\"\u003e\n  \u003ca href=\"https://www.idio.cc\"\u003e\u003cimg alt=\"Developer-Friendly Suggestions For Middleware\" src=\"app2.gif\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\n```console\nidio~:$ \\\nyarn add @idio/idio\nnpm install @idio/idio\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/0.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Example Apps\n\nThere are some example apps that you can look at.\n\n1. [File Upload](https://github.com/art-deco/file-upload.artdeco.app): a front-end + back-end application for uploading photos. [Demo](https://file-upload.artdeco.app/) requires GitHub authorisation without any scope permissions to enable session middleware showcase.\n1. [Akashic.Page](https://github.com/art-deco/akashic.page): a service for managing email and web-push subscriptions, with JS widgets and Mongo database connection.\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/1.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Table Of Contents\n\n- [Example Apps](#example-apps)\n- [Table Of Contents](#table-of-contents)\n- [API](#api)\n- [`async idio(middlewareConfig=, config=): !Idio`](#async-idiomiddlewareconfig-middlewareconfigconfig-config-idio)\n  * [`MiddlewareConfig`](#type-middlewareconfig)\n  * [`Config`](#type-config)\n  * [`Idio`](#type-idio)\n  * [\u003ccode\u003eConfiguredMiddleware\u003c/code\u003e](#type-configuredmiddleware)\n- [Middleware](#middleware)\n  * [Static](#static)\n  * [Session](#session)\n  * [CORS](#cors)\n  * [Compression](#compression)\n  * [File Upload](#file-upload)\n  * [Front End](#front-end)\n- [Additional Middleware](#additional-middleware)\n- [Custom Middleware](#custom-middleware)\n- [Router Set-up](#router-set-up)\n- [SSR](#ssr)\n- [NeoLuddite.Dev](#neoludditedev)\n  * [`NeoLudditeOptions`](#type-neoludditeoptions)\n- [WebSocket](#websocket)\n- [Copyright \u0026 License](#copyright--license)\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/2.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n\n## API\n\nThe package is available by importing its default function and named components:\n\n```js\nimport idio, { Keygrip, Router } from '@idio/idio'\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/3.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## \u003ccode\u003easync \u003cins\u003eidio\u003c/ins\u003e(\u003c/code\u003e\u003csub\u003e\u003cbr/\u003e\u0026nbsp;\u0026nbsp;`middlewareConfig=: !MiddlewareConfig,`\u003cbr/\u003e\u0026nbsp;\u0026nbsp;`config=: !Config,`\u003cbr/\u003e\u003c/sub\u003e\u003ccode\u003e): \u003ci\u003e!Idio\u003c/i\u003e\u003c/code\u003e\nStart the server. Sets the `proxy` property to `true` when the NODE_ENV is equal to _production_.\n\n - \u003ckbd\u003emiddlewareConfig\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e\u003ca href=\"#type-middlewareconfig\" title=\"Middleware configuration for the `idio` server.\"\u003e!MiddlewareConfig\u003c/a\u003e\u003c/code\u003e\u003c/em\u003e (optional): The middleware configuration for the `idio` server.\n - \u003ckbd\u003econfig\u003c/kbd\u003e \u003cem\u003e\u003ccode\u003e\u003ca href=\"#type-config\" title=\"Server configuration object.\"\u003e!Config\u003c/a\u003e\u003c/code\u003e\u003c/em\u003e (optional): The server configuration object.\n\nThe app can be stopped with an async `.destroy` method implemented on it that closes all connections.\n\n\nThere are multiple items for middleware configuration:\n\n__\u003ca name=\"type-middlewareconfig\"\u003e`MiddlewareConfig`\u003c/a\u003e extends FnMiddlewareConfig__: Middleware configuration for the `idio` server.\n\n\n|    Name    |                                                                                                                                                                                 Type                                                                                                                                                                                 |                                                                                                                                                                                                              Description                                                                                                                                                                                                               |\n| ---------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| static     | \u003cem\u003e(\u003ca href=\"https://github.com/idiocc/idio/wiki/Static#type-staticoptions\" title=\"Top-level options when setting up static middleware.\"\u003e!StaticOptions\u003c/a\u003e \\| !Array\u0026lt;\u003ca href=\"https://github.com/idiocc/idio/wiki/Static#type-staticoptions\" title=\"Top-level options when setting up static middleware.\"\u003e!StaticOptions\u003c/a\u003e\u0026gt;)\u003c/em\u003e                          | _Static_ middleware options.                                                                                                                                                                                                                                                                                                                                                                                                           |\n| compress   | \u003cem\u003e(boolean \\| [!CompressOptions](https://github.com/idiocc/idio/wiki/Compression#type-compressoptions))\u003c/em\u003e                                                                                                                                                                                                                                                       | _Compression_ middleware options.                                                                                                                                                                                                                                                                                                                                                                                                      |\n| session    | \u003cem\u003e\u003ca href=\"https://github.com/idiocc/idio/wiki/Session#type-sessionoptions\" title=\"Options for the session that extend the session config.\"\u003e!SessionOptions\u003c/a\u003e\u003c/em\u003e                                                                                                                                                                                               | _Session_ middleware options.                                                                                                                                                                                                                                                                                                                                                                                                          |\n| cors       | \u003cem\u003e[!CorsOptions](https://github.com/idiocc/idio/wiki/Cors#type-corsoptions)\u003c/em\u003e                                                                                                                                                                                                                                                                                   | _CORS_ middleware options.                                                                                                                                                                                                                                                                                                                                                                                                             |\n| form       | \u003cem\u003e\u003ca href=\"https://github.com/idiocc/idio/wiki/Form-Data#type-formdataoptions\" title=\"Options for Form Data (and file uploads) streams handling.\"\u003e!FormDataOptions\u003c/a\u003e\u003c/em\u003e                                                                                                                                                                                        | _Form Data_ middleware options for receiving file uploads and form submissions.                                                                                                                                                                                                                                                                                                                                                        |\n| frontend   | \u003cem\u003e\u003ca href=\"https://github.com/idiocc/idio/wiki/Front-End#type-frontendoptions\" title=\"Options for the frontend.\"\u003e!FrontEndOptions\u003c/a\u003e\u003c/em\u003e                                                                                                                                                                                                                         | _Front End_ middleware allows to serve source code from `node_modules` and transpile JSX.                                                                                                                                                                                                                                                                                                                                              |\n| neoluddite | \u003cem\u003e\u003ca href=\"https://github.com/idiocc/idio#type-neoludditeoptions\" title=\"Options for the neoluddite.dev client.\"\u003e!NeoLudditeOptions\u003c/a\u003e\u003c/em\u003e                                                                                                                                                                                                                       | Records the usage of middleware to compensate their developers' intellectual work.                                                                                                                                                                                                                                                                                                                                                     |\n| csrfCheck  | \u003cem\u003e\u003ca href=\"https://github.com/idiocc/idio/wiki/Additional Middleware#type-csrfcheckoptions\" title=\"Options for validating a csrf token.\"\u003e!CsrfCheckOptions\u003c/a\u003e\u003c/em\u003e                                                                                                                                                                                                | Enables the check for the presence of session with `csrf` property, and whether it matches the token from either `ctx.request.body` or `ctx.query`.                                                                                                                                                                                                                                                                                    |\n| github     | \u003cem\u003e(\u003ca href=\"https://github.com/idiocc/idio/wiki/Additional Middleware#type-githuboptions\" title=\"Options for GitHub OAuth.\"\u003e!GitHubOptions\u003c/a\u003e \\| !Array\u0026lt;\u003ca href=\"https://github.com/idiocc/idio/wiki/Additional Middleware#type-githuboptions\" title=\"Options for GitHub OAuth.\"\u003e!GitHubOptions\u003c/a\u003e\u0026gt;)\u003c/em\u003e                                                  | Sets up a route for GitHub OAuth authentication. The returned middleware will be installed on the `app` automatically so it doesn't need to be passed to the router.                                                                                                                                                                                                                                                                   |\n| jsonErrors | \u003cem\u003e(boolean \\| \u003ca href=\"https://github.com/idiocc/idio/wiki/Additional Middleware#type-jsonerrorsoptions\" title=\"Options for serving errors via JSON.\"\u003e!JSONErrorsOptions\u003c/a\u003e \\| !Array\u0026lt;\u003ca href=\"https://github.com/idiocc/idio/wiki/Additional Middleware#type-jsonerrorsoptions\" title=\"Options for serving errors via JSON.\"\u003e!JSONErrorsOptions\u003c/a\u003e\u0026gt;)\u003c/em\u003e | Tries all downstream middleware, and if an error was caught, serves a JSON response with `error` and `stack` properties (only if `exposeStack` is set to true). Client errors with status code _4xx_ (or that start with `!`) will have full message, but server errors with status code _5xx_ will only be served as `{ error: 'internal server error '}` and the app will emit an error via `app.emit('error')` so that it's logged. |\n| jsonBody   | \u003cem\u003e(boolean \\| \u003ca href=\"https://github.com/idiocc/idio/wiki/Additional Middleware#type-jsonbodyoptions\" title=\"Options for json body parsing.\"\u003e!JSONBodyOptions\u003c/a\u003e)\u003c/em\u003e                                                                                                                                                                                           | Allows to parse incoming JSON request and store the result in `ctx.request.body`. Throws 400 when the request cannot be parsed.                                                                                                                                                                                                                                                                                                        |\n| logarithm  | \u003cem\u003e\u003ca href=\"https://github.com/idiocc/idio/wiki/Additional Middleware#type-logarithmoptions\" title=\"Options for logarithm.\"\u003e!LogarithmOptions\u003c/a\u003e\u003c/em\u003e                                                                                                                                                                                                              | Options to record hits in _ElasticSearch_.                                                                                                                                                                                                                                                                                                                                                                                             |\n\nThe types for starting the server include the address, port and router configuration.\n\n__\u003ca name=\"type-config\"\u003e`Config`\u003c/a\u003e__: Server configuration object.\n\n\n|  Name  |                                                                   Type                                                                    |              Description               |  Default  |\n| ------ | ----------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------- | --------- |\n| port   | \u003cem\u003enumber\u003c/em\u003e                                                                                                                           | The port on which to start the server. | `5000`    |\n| host   | \u003cem\u003estring\u003c/em\u003e                                                                                                                           | The host on which to listen.           | `0.0.0.0` |\n| router | \u003cem\u003e\u003ca href=\"https://github.com/idiocc/goa-router/wiki/Home#type-routerconfig\" title=\"Config for the router.\"\u003e!_goa.RouterConfig\u003c/a\u003e\u003c/em\u003e | The configuration for the router.      | -         |\n\nAfter the app is started, it can be accessed from the return type.\n\n__\u003ca name=\"type-idio\"\u003e`Idio`\u003c/a\u003e__: The return type of the idio.\n\n\n|      Name       |                                                                                                                    Type                                                                                                                    |                                                                                                            Description                                                                                                             |\n| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| __url*__        | \u003cem\u003estring\u003c/em\u003e                                                                                                                                                                                                                            | The URL on which the server was started, such as `http://localhost:5000`.                                                                                                                                                          |\n| __server*__     | \u003cem\u003e\u003ca href=\"https://nodejs.org/api/http.html#http_class_http_server\" title=\"An HTTP server that extends net.Server to handle network requests.\"\u003e\u003cimg src=\".documentary/type-icons/node-even.png\" alt=\"Node.JS Docs\"\u003e!http.Server\u003c/a\u003e\u003c/em\u003e | The server instance.                                                                                                                                                                                                               |\n| __app*__        | \u003cem\u003e\u003ca href=\"https://github.com/idiocc/idio/wiki/Home#type-application\" title=\"The application with some additions.\"\u003e!Application\u003c/a\u003e\u003c/em\u003e                                                                                                 | The Goa application instance (with additional `.destroy` method).                                                                                                                                                                  |\n| __middleware*__ | \u003cem\u003e\u003ca href=\"#type-configuredmiddleware\" title=\"Idio-specific properties of the middleware object.\"\u003e!ConfiguredMiddleware\u003c/a\u003e\u003c/em\u003e                                                                                                         | An object with configured middleware functions, which can be installed manually using `app.use`, or `router.use`. The context will be a standard Goa context with certain properties set by bundled middleware such as `.session`. |\n| __router*__     | \u003cem\u003e\u003ca href=\"https://github.com/idiocc/idio/wiki/Router#type-router\" title=\"The router decorated with HTTP method properties.\"\u003e!Router\u003c/a\u003e\u003c/em\u003e                                                                                            | The router instance.                                                                                                                                                                                                               |\n\nAll middleware can be accessed from the `middleware` property, so that it can be installed on individual basis on specific routes, if it's not used app-wise.\n\n\u003cdetails\u003e\n \u003csummary\u003e\u003cstrong\u003e\u003ca name=\"type-configuredmiddleware\"\u003e\u003ccode\u003eConfiguredMiddleware\u003c/code\u003e\u003c/a\u003e extends MiddlewareObject\u003c/strong\u003e: Idio-specific properties of the middleware object.\u003c/summary\u003e\n\n|    Name    |                                                                                                                                                                                                                     Type                                                                                                                                                                                                                      |                                Description                                |\n| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------------------------------------------------------------------- |\n| form       | \u003cem\u003e\u003ca href=\"https://github.com/idiocc/idio/wiki/Form-Data#type-formdata\" title=\"An instance to create middleware.\"\u003e!_multipart.FormData\u003c/a\u003e\u003c/em\u003e                                                                                                                                                                                                                                                                                             | An instance of the form data class that can be used to create middleware. |\n| session    | \u003cem\u003e\u003ca href=\"https://github.com/idiocc/idio/wiki/Home#middlewarectx-contextnext-function-promisevoid\" title=\"The function to handle requests which can be installed with the `.use` method.\"\u003e!Middleware\u003c/a\u003e\u003c/em\u003e                                                                                                                                                                                                                             | The session middleware to be installed on individual routes.              |\n| frontend   | \u003cem\u003e\u003ca href=\"https://github.com/idiocc/idio/wiki/Home#middlewarectx-contextnext-function-promisevoid\" title=\"The function to handle requests which can be installed with the `.use` method.\"\u003e!Middleware\u003c/a\u003e\u003c/em\u003e                                                                                                                                                                                                                             | The frontend middleware.                                                  |\n| csrfCheck  | \u003cem\u003e\u003ca href=\"https://github.com/idiocc/idio/wiki/Home#middlewarectx-contextnext-function-promisevoid\" title=\"The function to handle requests which can be installed with the `.use` method.\"\u003e!Middleware\u003c/a\u003e\u003c/em\u003e                                                                                                                                                                                                                             | Configured CSRF check middleware.                                         |\n| jsonErrors | \u003cem\u003e(\u003ca href=\"https://github.com/idiocc/idio/wiki/Home#middlewarectx-contextnext-function-promisevoid\" title=\"The function to handle requests which can be installed with the `.use` method.\"\u003e!Middleware\u003c/a\u003e \\| !Array\u0026lt;\u003ca href=\"https://github.com/idiocc/idio/wiki/Home#middlewarectx-contextnext-function-promisevoid\" title=\"The function to handle requests which can be installed with the `.use` method.\"\u003e!Middleware\u003c/a\u003e\u0026gt;)\u003c/em\u003e | Middleware to server errors as JSON.                                      |\n\u003c/details\u003e\n\nThe example below starts a simple server with session and custom middleware, which is installed (used) automatically because it's defined as a function.\n\n\u003ctable\u003e\n\u003ctr\u003e\u003cth\u003e\u003ca href=\"example/index.js\"\u003eSource\u003c/a\u003e\u003c/th\u003e\u003cth\u003eOutput\u003c/th\u003e\n\u003c/tr\u003e\u003ctr\u003e\n\u003ctd\u003e\n\n```js\nconst { url, app,\n  middleware: { session, form },\n  router,\n} = await idio({\n  // Developers' payment scheme neoluddite.dev\n  neoluddite: {\n    env: process.env.NODE_ENV,\n    key: '0799b7f0-d2c7-4903-a531-00c8092c2911',\n    app: 'idio.example',\n  },\n  // Idio's bundled middleware.\n  session: {\n    algorithm: 'sha512',\n    keys: ['hello', 'world'],\n    prefix: 'example-',\n  },\n  static: {\n    use: true,\n    root: 'upload',\n  },\n  form: {\n    config: {\n      dest: 'upload',\n    },\n  },\n  // Any middleware function to be use app-wise.\n  async middleware(ctx, next) {\n    console.log('//', ctx.method, ctx.path)\n    await next()\n  },\n})\napp.use(router.routes())\nrouter.get('/', session, (ctx) =\u003e {\n  ctx.body = 'hello world'\n})\nrouter.post('/upload', session, async (ctx, next) =\u003e {\n  if (!ctx.session.user) {\n    ctx.status = 403\n    ctx.body = 'you must sign in to upload'\n    return\n  }\n  await next()\n}, form.single('/upload'), (ctx) =\u003e {\n  // db.create({\n  //  user: ctx.session.id,\n  //  file: ctx.req.file.path,\n  // })\n  ctx.body = 'Thanks for the upload. Link: ' +\n    `${url}/${ctx.file.filename}`\n})\n```\n\u003c/td\u003e\n\u003ctd\u003e\n\n```\nhttp://localhost:5000\n// GET /\nhello world\n```\n\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/4.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Middleware\n\nIdio's advantage is that is has the essential middleware, that was compiled together with the server, so that the packages are reused and memory footprint is low.\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/5.svg?sanitize=true\" width=\"25\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n### Static\n\n\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/static.svg?sanitize=true\" align=\"left\" height=\"100\"\u003e\u003ckbd\u003e🗂 [Explore Static Middleware Configuration](../../wiki/Static)\u003c/kbd\u003e\n\nUsed to serve static files, such as stylesheets, images, videos, html and everything else. Will perform mime-type lookup to serve the correct content-type in the returned header.\n\n\u003ctable\u003e\n\u003ctr\u003e\u003cth\u003e\u003ca href=\"example/static.js\"\u003eStatic\u003c/a\u003e \u003ca href=\"example/static2.js\"\u003esource\u003c/a\u003e\u003c/th\u003e\u003cth\u003eThe Output\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n```js\nconst { url, app } = await idio({\n  static: {\n    root: 'example', use: true,\n  },\n```\n\n```js\n// or multiple locations\n  static: [{\n    root: ['example'], use: true,\n  }, {\n    root: ['wiki'], use: true,\n  }],\n}, { port: null })\n```\n\u003c/td\u003e\n\u003ctd\u003e\n\n```css\n/** http://localhost:57537/app.css */ \n\nbody {\n  font-size: larger;\n}\n```\n\n\n\n\n\u003ctr\u003e\n\u003ctd colspan=\"2\"\u003e\n\n\u003cdetails\u003e\n\u003csummary\u003eShow Response Headers\u003c/summary\u003e\n\n```http\nContent-Length: 29\nLast-Modified: Thu, 18 Jul 2019 14:34:31 GMT\nCache-Control: max-age=0\nContent-Type: text/css; charset=utf-8\nDate: Thu, 05 Mar 2020 13:30:57 GMT\nConnection: close\n```\n\n\n\n```http\nContent-Length: 114\nLast-Modified: Sat, 28 Dec 2019 18:07:31 GMT\nCache-Control: max-age=0\nContent-Type: image/svg+xml\nDate: Thu, 05 Mar 2020 13:30:59 GMT\nConnection: close\n```\n\u003c/details\u003e\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/6.svg?sanitize=true\" width=\"25\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n### Session\n\n\u003cimg src=\"./doc/session.svg?sanitize=true\" align=\"right\" height=\"100\"\u003e\u003ckbd\u003e👳‍♂️[Explore Session Middleware Configuration](../../wiki/Session)\u003c/kbd\u003e\n\nAllows to store data in the `.session` property of the context. The session is serialised and placed in cookies. When the request contains the cookie, the session will be restored and validated (if signed) against the key.\n\n\u003ctable\u003e\n\u003ctr\u003e\u003cth\u003e\u003ca href=\"example/session.js\"\u003eSession Config\u003c/a\u003e\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n```js\nconst { url, app } = await idio({\n  session: { use: true, keys:\n    ['hello', 'world'], algorithm: 'sha512' },\n  async middleware(ctx, next) {\n    if (ctx.session.user)\n      ctx.body = 'welcome back '\n        + ctx.session.user\n    else {\n      ctx.session.user = 'u'\n        + (Math.random() * 1000).toFixed(1)\n      ctx.body = 'hello new user'\n    }\n    await next()\n  },\n})\n```\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\nThe session data is encrypted with \u003ccode\u003ebase64\u003c/code\u003e and signed by default, unless the \u003ccode\u003e.signed\u003c/code\u003e option is set to false. Signing means that the signature will contain the hash which will be validated server-side, to ensure that the session data was not modified by the client. The default algorithm for signing is \u003ccode\u003esha1\u003c/code\u003e, but it can be easily changed to a more secure \u003ccode\u003esha512\u003c/code\u003e.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd\u003e\n\n```js\n// GET /\n\"hello new user\"\n/* set-cookie */\n[\n  {\n    name: 'koa:sess',\n    value: 'eyJ1c2VyIjoidTg2LjciLCJfZXhwaXJlIjoxNTgzNTAxNDU5ODQzLCJfbWF4QWdlIjo4NjQwMDAwMH0=',\n    path: '/',\n    expires: 'Fri, 06 Mar 2020 13:30:59 GMT',\n    httponly: true\n  },\n  {\n    name: 'koa:sess.sig',\n    value: '5hRueSOyLuhp6nZvOi4TcziXNiADlaIhE6fJHruR-I8cGtEVDYCgNe9t3LS0SyV-SEN1kPa8ZwIz-a91GWPw-A',\n    path: '/',\n    expires: 'Fri, 06 Mar 2020 13:30:59 GMT',\n    httponly: true\n  }\n]\n// GET /\n\"welcome back u86.7\"\n```\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/7.svg?sanitize=true\" width=\"25\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n### CORS\n\n\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/cors.svg?sanitize=true\" align=\"left\" height=\"100\"\u003e\u003ckbd\u003e👮‍♀️[Explore CORS Middleware Configuration](../../wiki/Cors)\u003c/kbd\u003e\n\nTo enable dynamic communication between clients and the server via JavaScript requests from the browser, the server must respond with `Access-Control-Allow-Origin` header that sets the appropriate allowed _Origin_. This middleware is easy to use on production and development environments.\n\n\u003ctable\u003e\n\u003ctr\u003e\u003cth\u003e\u003ca href=\"example/cors.js\"\u003eCORS source\u003c/a\u003e\u003c/th\u003e\u003cth\u003eThe Output\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n```js\nconst { NODE_ENV } = process.env\n\nconst { url, app } = await idio({\n  async example(ctx, next) {\n    console.log('//', ctx.method,\n      ctx.path, 'from', ctx.get('Origin'))\n\n    ctx.body = 'hello world'\n    await next()\n  },\n  cors: {\n    use: true,\n    origin: NODE_ENV == 'production' ?\n      'http://prod.com' : null,\n    allowMethods: ['GET', 'POST'],\n  },\n})\n```\n\u003c/td\u003e\n\u003ctd\u003e\n\n```js\n// GET / from https://3rd.party\n{\n  vary: 'Origin',\n  'access-control-allow-origin': 'http://prod.com',\n  date: 'Thu, 05 Mar 2020 13:31:01 GMT',\n  connection: 'close'\n}\n\n// GET / from http://prod.com\n{\n  vary: 'Origin',\n  'access-control-allow-origin': 'http://prod.com',\n  date: 'Thu, 05 Mar 2020 13:31:01 GMT',\n  connection: 'close'\n}\n\n// OPTIONS / from http://prod.com\n{\n  vary: 'Origin',\n  'access-control-allow-origin': 'http://prod.com',\n  'access-control-allow-methods': 'GET,POST',\n  date: 'Thu, 05 Mar 2020 13:31:01 GMT',\n  connection: 'close'\n}\n```\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/8.svg?sanitize=true\" width=\"25\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n### Compression\n\n\u003ca href=\"../../wiki/compression\"\u003e\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/compress.svg?sanitize=true\" align=\"right\" height=\"100\"\u003e\u003c/a\u003e\n\u003ckbd\u003e🗜[Explore Compression Middleware Configuration](../../wiki/Compression)\u003c/kbd\u003e\n\nWhen the body of the response is non-empty, it can be compressed using `gzip` algorithm. This allows to save data transmitted over the network. The default threshold is `1024` bytes, since below that the benefits of compression are lost as the compressed response might end up being even larger.\n\n\u003ctable\u003e\n\u003ctr\u003e\u003cth\u003e\u003ca href=\"example/compression.js\"\u003eCompression source\u003c/a\u003e\u003c/th\u003e\u003cth\u003eThe Output\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n```js\nconst { url, app } = await idio({\n  async serve(ctx, next) {\n    console.log('//',\n      ctx.method, ctx.path)\n\n    ctx.body = packageJson\n    await next()\n  },\n  compress: {\n    use: true,\n  },\n})\n```\n\u003c/td\u003e\n\u003ctd\u003e\n\n```js\n// GET /\n{\n  'content-type': 'application/json; charset=utf-8',\n  vary: 'Accept-Encoding',\n  'content-encoding': 'gzip',\n  date: 'Thu, 05 Mar 2020 13:31:01 GMT',\n  connection: 'close',\n  'transfer-encoding': 'chunked'\n}\n```\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/9.svg?sanitize=true\" width=\"25\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n### File Upload\n\n\u003ca href=\"../../wiki/Form-Data\"\u003e\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/multer.svg?sanitize=true\" align=\"left\" height=\"100\"\u003e\u003c/a\u003e\n\u003ckbd\u003e🖼[Explore Form Data Middleware Configuration](../../wiki/Form-Data)\u003c/kbd\u003e\n\nBrowser will submit forms and send files using `multipart/form-data` type of request. It will put all fields of the form together and stream them to the server, sending pairs of keys/values as well as files when they were attached. The _Form Data_ middleware is the **[Multer](https://github.com/expressjs/multer)** middleware specifically rewritten for Koa that can handle file uploads.\n\n\u003ctable\u003e\n\u003ctr\u003e\u003cth\u003e\u003ca href=\"example/upload.js\"\u003eFile Upload source\u003c/a\u003e\u003c/th\u003e\u003cth\u003eThe Output\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n```js\nconst { url, app, router, middleware: {\n  form,\n} } = await idio({\n  form: {\n    dest: 'example/upload',\n  },\n})\napp.use(router.routes())\nrouter.post('/example',\n  form.single('bio'),\n  (ctx) =\u003e {\n    delete ctx.file.stream\n    ctx.body = { file: ctx.file,\n      body: ctx.request.body }\n  }\n)\n```\n\u003c/td\u003e\n\u003ctd\u003e\n\n```js\n{\n  file: {\n    fieldname: 'bio',\n    originalname: 'bio.txt',\n    encoding: '7bit',\n    mimetype: 'application/octet-stream',\n    destination: 'example/upload',\n    filename: '106e5',\n    path: 'example/upload/106e5',\n    size: 29\n  },\n  body: { hello: 'world' }\n}\n```\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/10.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n### Front End\n\n\u003ca href=\"../../wiki/Front-End\"\u003e\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/frontend.svg?sanitize=true\" align=\"right\" height=\"100\"\u003e\u003c/a\u003e\n\u003ckbd\u003e🌐[Explore Front End Middleware Configuration](../../wiki/Front-End)\u003c/kbd\u003e\n\nWeb applications are always full stack and involve both back-end together with front-end. Whereas all previously described middleware was for the server only, the front-end middleware facilitates browser development, as it allows to serve source code from the `node_modules` directory and transpile JSX. Modern browsers support modules, but JavaScript needs to be patched to rename imports like\n```js\n// was\nimport X from 'package-name'\n// becomes\nimport X from '/node_modules/package-name/src/index.mjs'\n```\nThis is achieved by resolving the `module` field from `package.json` of served packages (with fallback to the `main` field, but in that case `require` statements will not work).\n\n\u003ctable\u003e\n\u003ctr\u003e\u003cth\u003e\u003ca href=\"example/frontend/index.js\"\u003eConfiguration\u003c/a\u003e\u003c/th\u003e\u003cth\u003e\u003ca href=\"example/frontend/example.jsx\"\u003eJSX Component\u003c/a\u003e\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n```js\nconst { url, app } = await idio({\n  frontend: {\n    use: true,\n    directory: 'example/frontend',\n  },\n})\n```\n\n\u003c/td\u003e\n\u003ctd\u003e\n\n```jsx\nimport { render, Component } from 'preact'\n\nclass MyComp extends Component {\n  render() {\n    return (\u003cdiv className=\"example\"\u003e\n      Hello World!\n    \u003c/div\u003e)\n  }\n}\n\nrender(MyComp, document.body)\n```\n\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd colspan=\"2\"\u003e\nUsing the simple configuration from above, and a JSX file, the browser will receive the following patched source code. The middleware will also look for requests that start with the \u003ccode\u003e/node_modules\u003c/code\u003e path, and serve them also. The pragma (\u003ccode\u003eimport { h } from 'preact'\u003c/code\u003e) is also added automatically, but it can be configured.\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003ctr\u003e\n\u003ctd colspan=\"2\"\u003e\n\n```js\nimport { h } from '/node_modules/preact/dist/preact.mjs'\nimport { render, Component } from '/node_modules/preact/dist/preact.mjs'\n\nclass MyComp extends Component {\n  render() {\n    return (h('div',{className:\"example\"},\n      `Hello World!`\n    ))\n  }\n}\n\nrender(MyComp, document.body)\n```\n\u003c/td\u003e\n\u003c/tr\u003e\n\u003c/table\u003e\n\nThe idea here is to provide a basic mechanism to serve front-end JavaScript code, without inventing any module systems, adapting to _CommonJS_, or transpiling old features. We simply want to execute our modern code and browsers are more than capable to do that, without us having to run complex build systems on the development code. Our simple JSX parser is not rocket science either and works perfectly well without building ASTs (but check for minor limitations in Wiki).\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/11.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Additional Middleware\n\nThere are some small bits of middleware that can be used in server as well, but which are not essential to its functioning. They are listed in \u003ckbd\u003e📖 [Wiki](../../wiki/Additional_Middleware)\u003c/kbd\u003e.\n\n- `csrfCheck`: Ensures that the `csrf` token from session matches one in the request.\n- `jsonErrors`: Allows to serve errors as _JSON_, which is useful for APIs.\n- `jsonBody`: Parses requests with the `application/json` content type into `ctx.request.body`.\n- `logarithm`: Record hits in _ElasticSearch_.\n- `github`: Sets up _GitHub_ OAuth routes.\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/12.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Custom Middleware\n\nWhen required to add any other middleware in the application not included in the _Idio_ bundle, it can be done in several ways.\n\n1. Passing the middleware function as part of the \u003ca href=\"#type-middlewareconfig\" title=\"Middleware configuration for the `idio` server.\"\u003e_MiddlewareConfig_\u003c/a\u003e. It will be automatically installed to be used by the _Application_. All middleware will be installed in order it is found in the _MiddlewareConfig_.\n    ```js\n    import idio from '@idio/idio'\n    \n    const APIServer = async (port) =\u003e {\n      const { url } = await idio({\n        // 1. Add logging middleware.\n        async log(ctx, next) {\n          await next()\n          console.log(' --\u003e API: %s %s %s', ctx.method, ctx.url, ctx.status)\n        },\n        // 2. Add always used error middleware.\n        async error(ctx, next) {\n          try {\n            await next()\n          } catch (err) {\n            ctx.status = 403\n            ctx.body = err.message\n          }\n        },\n        // 3. Add validation middleware.\n        async validateKey(ctx, next) {\n          if (ctx.query.key !== 'app-secret')\n            throw new Error('Wrong API key.')\n          ctx.body = 'ok'\n          await next()\n        },\n      }, { port })\n      return url\n    }\n    \n    export default APIServer\n    ```\n    ```\n    Started API server at: http://localhost:5005\n     --\u003e API: GET / 403\n     --\u003e API: GET /?key=app-secret 200\n    ```\n2. Passing a configuration object as part of the _MiddlewareConfig_ that includes the `middlewareConstructor` property which will receive the reference to the `app`. Other properties such as `conf` and `use` will be used in the same way as when setting up bundled middleware: setting `use` to `true` will result in the middleware being used for every request, and the `config` will be passed to the constructor.\n    ```js\n    import rqt from 'rqt'\n    import idio from '@idio/idio'\n    import APIServer from './api-server'\n    \n    const ProxyServer = async (port) =\u003e {\n      // 1. Start the API server.\n      const API = await APIServer(5001)\n      console.log('API server started at %s', API)\n    \n      // 2. Start a proxy server to the API.\n      const { url } = await idio({\n        async log(ctx, next) {\n          await next()\n          console.log(' --\u003e Proxy: %s %s %s', ctx.method, ctx.url, ctx.status)\n        },\n        api: {\n          use: true,\n          async middlewareConstructor(app, config) {\n            // e.g., read from a virtual network\n            app.context.SECRET = await Promise.resolve('app-secret')\n    \n            /** @type {import('@typedefs/goa').Middleware} */\n            const fn = async (ctx, next) =\u003e {\n              const { path } = ctx\n              const res = await rqt(`${config.API}${path}?key=${ctx.SECRET}`)\n              ctx.body = res\n              await next()\n            }\n            return fn\n          },\n          config: {\n            API,\n          },\n        },\n      }, { port })\n      return url\n    }\n    ```\n    ```\n    API server started at http://localhost:5001\n    Proxy started at http://localhost:5002\n     --\u003e API: GET /?key=app-secret 200\n     --\u003e Proxy: GET / 200\n    ```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/13.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## Router Set-up\n\nAfter the _Application_ and _Router_ instances are obtained after starting the server as the `app` and `router` properties of the \u003ca href=\"#type-idio\" title=\"The return type of the idio.\"\u003ereturned object\u003c/a\u003e, the router can be configured to respond to custom paths. This can be done by assigning configured middleware from the map and standalone middleware, and calling the `use` method on the _Application_ instance.\n\n```js\nimport { collect } from 'catchment'\nimport idio from '@idio/idio'\n\nconst Server = async () =\u003e {\n  const {\n    url, router, app, middleware: { pre, post, bodyparser },\n  } = await idio({\n    // 1. Configure middlewares via middlewareConstructor without installing them.\n    pre: {\n      middlewareConstructor() {\n        return async function(ctx, next) {\n          console.log('  \u003c-- %s %s',\n            ctx.request.method,\n            ctx.request.path,\n          )\n          await next()\n        }\n      },\n    },\n    post: {\n      middlewareConstructor() {\n        return async function(ctx, next) {\n          console.log('  --\u003e %s %s %s',\n            ctx.request.method,\n            ctx.request.path,\n            ctx.response.status,\n          )\n          await next()\n        }\n      },\n    },\n    bodyparser: {\n      middlewareConstructor() {\n        return async (ctx, next) =\u003e {\n          let body = await collect(ctx.req)\n          if (ctx.is('application/json')) {\n            body = JSON.parse(body)\n          }\n          ctx.request.body = body\n          await next()\n        }\n      },\n    },\n  }, { port: 5003 })\n\n  // 2. Setup router with the bodyparser and path-specific middleware.\n  router.post('/example',\n    pre,\n    bodyparser,\n    async (ctx, next) =\u003e {\n      ctx.body = {\n        ok: true,\n        request: ctx.request.body,\n      }\n      await next()\n    },\n    post,\n  )\n  app.use(router.routes())\n  return url\n}\n```\n\n\u003ctable\u003e\n\u003ctr\u003e\u003cth\u003eLogging\u003c/th\u003e\u003cth\u003eResponse\u003c/th\u003e\u003c/tr\u003e\n\u003ctr\u003e\u003ctd\u003e\n\n```\nPage available at: http://localhost:5003\n  \u003c-- POST /example\n  --\u003e POST /example 200\n```\n\u003c/td\u003e\n\u003ctd\u003e\n\n```js\n// server response:\n{ ok: true, request: { hello: 'world' } }\n```\n\u003c/td\u003e\u003c/tr\u003e\n\u003c/table\u003e\n\nAlso checkout the [_Router_ package](https://github.com/idiocc/router) that allows to automatically initialise routes from a given directory, and watch for changes in them during development. This means you don't have to refresh the server manually after a change to a route.\n\n```js\nconst w = await initRoutes(router, 'routes', {\n  middleware,\n})\nif (process.env.NODE_ENV == 'prod') watchRoutes(w)\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/14.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## SSR\n\n_Idio_ supports Server-Side rendering of JSX components ([same restrictions](https://github.com/idiocc/idio/wiki/Front-End#todo--jsx-limitations) apply as for front-end). You can easily mark up your back-end pages using full-scale HTML, or basic placeholders in which you can then render your front-end app.\n\n```jsx\nimport idio, { render } from '@idio/idio'\n\nconst { url, app, router } = await idio()\nrouter.get('/', (ctx) =\u003e {\n  ctx.body = render(\u003chtml\u003e\n    \u003chead\u003e\n      \u003ctitle\u003eExample\u003c/title\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n      Hello World!\n    \u003c/body\u003e\n  \u003c/html\u003e, {\n    addDoctype: true,\n    pretty: true,\n  })\n})\napp.use(router.routes())\n```\n\n```html\n\u003c!doctype html\u003e\n\u003chtml\u003e\n  \u003chead\u003e\u003ctitle\u003eExample\u003c/title\u003e\u003c/head\u003e\n  \u003cbody\u003eHello World!\u003c/body\u003e\n\u003c/html\u003e\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/15.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## NeoLuddite.Dev\n\nThis web server integrates with [NeoLuddite](https://neoluddite.dev): the package monetary reward scheme. It's currently in beta, and this section will be relevant when it's open to the public.\n\nEvery time you invoke certain functionality in a package somebody has written (e.g., `koa-static` for static files, `koa-session` for creation of session), via _Idio_, your usage will be counted and your balance in _Ludds_ on the neoluddite server will be transferred to the software engineer as a reward for his/her intellectual work. Contact license@neoluddite.dev for any requests.\n\n```js\nconst { url, app,\n  middleware: { session, form },\n  router,\n} = await idio({\n  // Developers' payment scheme neoluddite.dev\n  neoluddite: {\n    env: process.env.NODE_ENV,\n    key: '0799b7f0-d2c7-4903-a541-10d8092c2911',\n    app: 'idio.example',\n  },\n  // ...\n}\n```\n\nThe usage will be billed for apps running in production mode, therefore the `env` variable is needed. Setting the `app` has no effect but allows to break down statistics by web application on the portal. See the license section for more info.\n\n\u003ca href=\"https://neoluddite.dev\"\u003e\u003cimg src=\"doc/ludds.png\"\u003e\u003c/a\u003e\n\n__\u003ca name=\"type-neoludditeoptions\"\u003e`NeoLudditeOptions`\u003c/a\u003e__: Options for the neoluddite.dev client.\n\n\n|   Name   |      Type       |                                               Description                                                |         Default          |\n| -------- | --------------- | -------------------------------------------------------------------------------------------------------- | ------------------------ |\n| __key*__ | \u003cem\u003estring\u003c/em\u003e | The API key received from the app.                                                                       | -                        |\n| env      | \u003cem\u003estring\u003c/em\u003e | The environment (e.g., `dev`/`staging`). The production env must be indicated as `prod` which is billed. | -                        |\n| host     | \u003cem\u003estring\u003c/em\u003e | The hostname of the server.                                                                              | `https://neoluddite.dev` |\n| app      | \u003cem\u003estring\u003c/em\u003e | The name of the application.                                                                             | -                        |\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/16.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n## WebSocket\n\nWe've implemented a library to upgrade requests into _WebSocket_ connections. You can read more at the actual [package page](https://github.com/idiocc/websocket). _Idio_ simply exports this method via its API. You need to configure it yourself.\n\n```js\nimport idio, { websocket } from '@idio/idio'\n\nconst { url, app, server } = await idio()\n// clients stores current connections against ID\nconst clients = websocket(server, {\n  onConnect(clientId) {\n    // the value is a function to send messages\n    clients[clientId]('intro-event', 'Hello Client!')\n  },\n})\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/17.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e\n\n\n\n## Copyright \u0026 License\n\nGNU Affero General Public License v3.0\n\nAffero GPL means that you're not allowed to use this web server on the web unless you release the source code for your application. This is a restrictive license which has the purpose of defending Open Source work and its creators.\n\nTo be able to use the server, just set up a monthly payment on [Open Collective](https://opencollective.com/nodetools) for any amount of your choice.\n\nAll original work on middleware and _Koa_ are under MIT license. See [Goa Page](https://github.com/idiocc/goa/) for the list of packages and modules used in compilation of the Goa server, and the [`package.json`](/package.json) file for dependencies of this project (todo: create wiki page w/ licenses table).\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth\u003e\n      \u003ca href=\"https://www.artd.eco\"\u003e\n        \u003cimg width=\"100\" src=\"https://raw.githubusercontent.com/wrote/wrote/master/images/artdeco.png\"\n          alt=\"Art Deco\"\u003e\n      \u003c/a\u003e\n    \u003c/th\u003e\n    \u003cth\u003e© \u003ca href=\"https://www.artd.eco\"\u003eArt Deco™\u003c/a\u003e for \u003ca href=\"https://idio.cc\"\u003eIdio\u003c/a\u003e 2020\u003c/th\u003e\n    \u003cth\u003e\n      \u003ca href=\"https://idio.cc\"\u003e\n        \u003cimg src=\"https://avatars3.githubusercontent.com/u/40834161?s=100\" width=\"100\" alt=\"Idio\"\u003e\n      \u003c/a\u003e\n    \u003c/th\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\n  \u003cimg src=\"/.documentary/section-breaks/-1.svg?sanitize=true\"\u003e\n\u003c/a\u003e\u003c/p\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidiocc%2Fidio","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fidiocc%2Fidio","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidiocc%2Fidio/lists"}