{"id":18317902,"url":"https://github.com/idiocc/core","last_synced_at":"2025-04-09T13:51:19.886Z","repository":{"id":42114031,"uuid":"139739125","full_name":"idiocc/core","owner":"idiocc","description":"The Core Idio Web Server Functionality And Middleware.","archived":false,"fork":false,"pushed_at":"2022-12-06T15:06:52.000Z","size":501,"stargazers_count":1,"open_issues_count":2,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2025-03-18T03:41:54.371Z","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":"mit","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":"2018-07-04T15:27:12.000Z","updated_at":"2019-12-25T06:16:45.000Z","dependencies_parsed_at":"2023-01-24T02:17:08.064Z","dependency_job_id":null,"html_url":"https://github.com/idiocc/core","commit_stats":null,"previous_names":["idiojs/core"],"tags_count":13,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fcore","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fcore/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fcore/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/idiocc%2Fcore/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/idiocc","download_url":"https://codeload.github.com/idiocc/core/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248054218,"owners_count":21039951,"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":[],"created_at":"2024-11-05T18:07:49.578Z","updated_at":"2025-04-09T13:51:19.869Z","avatar_url":"https://github.com/idiocc.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"@idio/core\n===\n\n[![npm version](https://badge.fury.io/js/%40idio%2Fcore.svg)](https://npmjs.org/package/@idio/core)\n\n\u003ca href=\"https://github.com/idio/core\"\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/core` is a _Koa2_-based web server with some pre-installed middleware which facilitates quick creation of a web server with the essential functionality, such as serving static files, compression, body parsing, _etc_. It also provides full JSDoc documentation of all options for completion in IDEs. Other components such as `@idio/database`, `@idio/route` and `@idio/jsx` allow to build more complex websites (to come).\n\n```sh\nyarn add -E @idio/core\n```\n\n\u003cp align=\"center\"\u003e\n\u003ca href=\"https://idio.cc\"\u003e\u003cimg alt=\"Developer-Friendly Suggestions For Middleware\" src=\"app2.gif\"\u003e\u003c/a\u003e\n\u003c/p\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/0.svg?sanitize=true\"\u003e\u003c/a\u003e\u003c/p\u003e\n\n## Table Of Contents\n\n- [Table Of Contents](#table-of-contents)\n- [API](#api)\n- [`async core(middlewareConfig?: MiddlewareConfig, config?: Config): IdioCore`](#async-coremiddlewareconfig-middlewareconfigconfig-config-idiocore)\n  * [`MiddlewareConfig`](#type-middlewareconfig)\n  * [`Config`](#type-config)\n  * [`IdioCore`](#type-idiocore)\n- [Middleware Configuration](#middleware-configuration)\n  * [Session](#session)\n  * [File Uploads](#file-uploads)\n  * [Cross-Site Request Forgery](#cross-site-request-forgery)\n  * [Parse Body](#parse-body)\n  * [Checking Auth](#checking-auth)\n  * [Logging](#logging)\n  * [Compression](#compression)\n  * [Static Files](#static-files)\n  * [CORS](#cors)\n  * [Frontend](#frontend)\n- [Custom Middleware](#custom-middleware)\n- [Router Set-up](#router-set-up)\n- [Copyright](#copyright)\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/1.svg?sanitize=true\"\u003e\u003c/a\u003e\u003c/p\u003e\n\n## API\n\nThe package is available by importing its default function:\n\n```js\nimport idioCore from '@idio/core'\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/2.svg?sanitize=true\"\u003e\u003c/a\u003e\u003c/p\u003e\n\n## `async core(`\u003cbr/\u003e\u0026nbsp;\u0026nbsp;`middlewareConfig?: MiddlewareConfig,`\u003cbr/\u003e\u0026nbsp;\u0026nbsp;`config?: Config,`\u003cbr/\u003e`): IdioCore`\n\nThe `@idio/core` accepts 2 arguments which are the middleware configuration object and server configuration object. It is possible to start the server without any configuration, however it will do nothing, therefore it is important to add some middleware configuration.\n\n__\u003ca name=\"type-middlewareconfig\"\u003e`MiddlewareConfig`\u003c/a\u003e__: Middleware configuration for the `idio` `core` server.\n\n|    Name    |                                                                              Type                                                                               |                                                      Description                                                       |\n| ---------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------- |\n| session    | \u003cem\u003e[SessionOptions](#type-sessionoptions)\u003c/em\u003e                                                                                                                 | `session` options.                                                                                                     |\n| multer     | \u003cem\u003e[MulterOptions](#type-multeroptions)\u003c/em\u003e                                                                                                                   | `multer` options.                                                                                                      |\n| csrf       | \u003cem\u003e[CSRFOptions](#type-csrfoptions)\u003c/em\u003e                                                                                                                       | `csrf` options.                                                                                                        |\n| bodyparser | \u003cem\u003e[BodyparserOptions](#type-bodyparseroptions)\u003c/em\u003e                                                                                                           | `bodyparser` options.                                                                                                  |\n| compress   | \u003cem\u003e[CompressOptions](#type-compressoptions)\u003c/em\u003e                                                                                                               | `compress` options.                                                                                                    |\n| checkauth  | \u003cem\u003e[CheckauthOptions](#type-checkauthoptions)\u003c/em\u003e                                                                                                             | `checkauth` options.                                                                                                   |\n| logger     | \u003cem\u003e[LoggerOptions](#type-loggeroptions)\u003c/em\u003e                                                                                                                   | `logger` options.                                                                                                      |\n| static     | \u003cem\u003e[StaticOptions](#type-staticoptions)\u003c/em\u003e                                                                                                                   | `static` options.                                                                                                      |\n| cors       | \u003cem\u003e[CorsOptions](#type-corsoptions)\u003c/em\u003e                                                                                                                       | `cors` options.                                                                                                        |\n| frontend   | \u003cem\u003e\u003ca href=\"#type-frontendoptions\" title=\"Allows to serve front-end JS files and CSS as modules, including from node_modules folder.\"\u003eFrontendOptions\u003c/a\u003e\u003c/em\u003e | `frontend` options. If the option is specified, the middleware always will be used, i.e., no need to pass `use: true`. |\n\n__\u003ca name=\"type-config\"\u003e`Config`\u003c/a\u003e__: Server configuration object.\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\n---\n\nThe return type contains the _URL_, _Application_ and _Router_ instances, and the map of configured middleware, which could then be [passed to the router](#router-set-up).\n\n[`import('@goa/koa').Application`](https://github.com/idiocc/goa/blob/master/doc/TYPES.md#type-_goaapplication) __\u003ca name=\"type-_goaapplication\"\u003e`_goa.Application`\u003c/a\u003e__: An instance of the Koa application.\n\n[`import('@goa/koa').Middleware`](https://github.com/idiocc/goa/blob/master/doc/TYPES.md#type-_goamiddleware) __\u003ca name=\"type-_goamiddleware\"\u003e`_goa.Middleware`\u003c/a\u003e__: An async middleware function.\n\n[`import('koa-router').Router`](https://github.com/alexmingoia/koa-router#exp_module_koa-router--Router) __\u003ca name=\"type-koa-routerrouter\"\u003e`koa-router.Router`\u003c/a\u003e__: An instance of the Koa router.\n\n[`import('http').Server`](https://nodejs.org/api/http.html#http_class_http_server) __\u003ca name=\"type-httpserver\"\u003e`http.Server`\u003c/a\u003e__: An instance of the Node's Server class.\n\n__\u003ca name=\"type-idiocore\"\u003e`IdioCore`\u003c/a\u003e__: An object containing the url and references to the app, router and middleware.\n\n|    Name    |                                                          Type                                                           |                                             Description                                              |         Default         |\n| ---------- | ----------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ----------------------- |\n| url        | \u003cem\u003estring\u003c/em\u003e                                                                                                         | The url on which the server is accessible.                                                           | `http://localhost:5000` |\n| app        | \u003cem\u003e\u003ca href=\"#type-_goaapplication\" title=\"An instance of the Koa application.\"\u003e_goa.Application\u003c/a\u003e\u003c/em\u003e               | The `Koa` application.                                                                               | -                       |\n| router     | \u003cem\u003eRouter\u003c/em\u003e                                                                                                         | The `koa-router` instance.                                                                           | -                       |\n| server     | \u003cem\u003e\u003ca href=\"#type-httpserver\" title=\"An instance of the Node's Server class.\"\u003ehttp.Server\u003c/a\u003e\u003c/em\u003e                     | The `http` server instance.                                                                          | -                       |\n| middleware | \u003cem\u003eObject\u0026lt;string, \u003ca href=\"#type-_goamiddleware\" title=\"An async middleware function.\"\u003e_goa.Middleware\u003c/a\u003e\u0026gt;\u003c/em\u003e | The map of configured middleware functions which could then be set up to be used on a certain route. | -                       |\n\n---\n\nTo start the server, the async method needs to be called and passed the middleware and server configuration objects. For example, the following code will start a server which serves static files with enabled compression.\n\n```js\nimport idioCore from '@idio/core'\n\nconst Server = async () =\u003e {\n  const { url } = await idioCore({\n    logger: {\n      use: true,\n    },\n    static: {\n      use: true,\n      root: 'example/static',\n      mount: '/static',\n    },\n    compress: {\n      use: true,\n      config: {\n        threshold: 1024,\n      },\n    },\n  }, {\n    port: 8080,\n  })\n  console.log('File available at: %s/static/test.txt', url)\n}\n```\n```\nFile available at: http://localhost:8080/static/test.txt\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/3.svg?sanitize=true\"\u003e\u003c/a\u003e\u003c/p\u003e\n\n## Middleware Configuration\n\nThe middleware can be configured according to the `MiddlewareConfig`. `@idio/core` comes with some installed middleware as dependencies to speed up the process of creating a web server. Moreover, any custom middleware which is not part of the bundle can also be specified here (see [Custom Middleware](#custom-middleware)).\n\nEach middleware accepts the following properties:\n\n|  Property  |                                                                                                                             Description                                                                                                                             | Default |\n| ---------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------- |\n| `use` | Whether to use this middleware for every request. If not set to `true`, the configured middleware function will be included in the `middleware` property of the returned object, which can then be passed to a router configuration (not part of the `@idio/core`). | `false` |\n| `config` | Configuration object expected by the middleware constructor.                                                                                                                                                                                                        | `{}` |\n| `...props` | Any additional specific properties (see individual middleware configuration).                                                                                                                                                                                       |         |\n\n\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/4.svg?sanitize=true\" width=\"15\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ca href=\"https://github.com/koajs/session\"\u003e\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/session.svg?sanitize=true\" align=\"left\" height=\"100\"\u003e\u003c/a\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ca name=\"session\"\u003eSession\u003c/a\u003e\u003c/strong\u003e: handling sessions via cookies.\n\u003chr/\u003e\n\n__\u003ca name=\"type-sessionoptions\"\u003e`SessionOptions`\u003c/a\u003e__\n\n|   Name    |                                                  Type                                                   |                 Description                  | Default |\n| --------- | ------------------------------------------------------------------------------------------------------- | -------------------------------------------- | ------- |\n| __keys*__ | \u003cem\u003estring[]\u003c/em\u003e                                                                                       | A set of keys to be installed in `app.keys`. | -       |\n| use       | \u003cem\u003eboolean\u003c/em\u003e                                                                                        | Use this middleware for every request.       | `false` |\n| config    | \u003cem\u003e\u003ca href=\"#type-sessionconfig\" title=\"Configuration passed to `koa-session`.\"\u003eSessionConfig\u003c/a\u003e\u003c/em\u003e | `koa-session` configuration.                 | -       |\n\u003c/summary\u003e\n\n__\u003ca name=\"type-sessionconfig\"\u003e`SessionConfig`\u003c/a\u003e__: Configuration passed to `koa-session`.\n\n|   Name    |              Type              |                                                                                        Description                                                                                        |  Default   |\n| --------- | ------------------------------ | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------- |\n| key       | \u003cem\u003estring\u003c/em\u003e                | Cookie key.                                                                                                                                                                               | `koa:sess` |\n| maxAge    | \u003cem\u003e(number \\| 'session')\u003c/em\u003e | maxAge in ms with default of 1 day. `session` will result in a cookie that expires when session/browser is closed. Warning: If a session cookie is stolen, this cookie will never expire. | `86400000` |\n| overwrite | \u003cem\u003eboolean\u003c/em\u003e               | Can overwrite or not.                                                                                                                                                                     | `true`     |\n| httpOnly  | \u003cem\u003eboolean\u003c/em\u003e               | httpOnly or not.                                                                                                                                                                          | `true`     |\n| signed    | \u003cem\u003eboolean\u003c/em\u003e               | Signed or not.                                                                                                                                                                            | `true`     |\n| rolling   | \u003cem\u003eboolean\u003c/em\u003e               | Force a session identifier cookie to be set on every response. The expiration is reset to the original maxAge, resetting the expiration countdown.                                        | `false`    |\n| renew     | \u003cem\u003eboolean\u003c/em\u003e               | Renew session when session is nearly expired, so we can always keep user logged in.                                                                                                       | `false`    |\n\n\n\u003c/details\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/5.svg?sanitize=true\" width=\"15\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ca href=\"https://github.com/koa-modules/multer\"\u003e\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/multer.svg?sanitize=true\" align=\"left\" height=\"100\"\u003e\u003c/a\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ca name=\"file-uploads\"\u003eFile Uploads\u003c/a\u003e\u003c/strong\u003e: receiving files on the server.\n\u003chr/\u003e\n\n__\u003ca name=\"type-multeroptions\"\u003e`MulterOptions`\u003c/a\u003e__\n\n|  Name  |                    Type                     |              Description               | Default |\n| ------ | ------------------------------------------- | -------------------------------------- | ------- |\n| use    | \u003cem\u003eboolean\u003c/em\u003e                            | Use this middleware for every request. | `false` |\n| config | \u003cem\u003e[MulterConfig](#type-multerconfig)\u003c/em\u003e | `koa-multer` configuration.            | -       |\n\u003c/summary\u003e\n\n[`import('http').IncomingMessage`](https://nodejs.org/api/http.html#http_class_http_incomingmessage) __\u003ca name=\"type-httpincomingmessage\"\u003e`http.IncomingMessage`\u003c/a\u003e__\n\n[`import('fs').Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats) __\u003ca name=\"type-fsstats\"\u003e`fs.Stats`\u003c/a\u003e__\n\n[`import('koa-multer').StorageEngine`](https://github.com/expressjs/multer#storage) __\u003ca name=\"type-koa-multerstorageengine\"\u003e`koa-multer.StorageEngine`\u003c/a\u003e__\n\n[`import('koa-multer').File`](https://github.com/expressjs/multer#file-information.) __\u003ca name=\"type-koa-multerfile\"\u003e`koa-multer.File`\u003c/a\u003e__\n\n__\u003ca name=\"type-limits\"\u003e`Limits`\u003c/a\u003e__: [An object](https://github.com/expressjs/multer#limits) specifying the size limits.\n\n|     Name      |      Type       |                                 Description                                  |  Default   |\n| ------------- | --------------- | ---------------------------------------------------------------------------- | ---------- |\n| fieldNameSize | \u003cem\u003enumber\u003c/em\u003e | Max field name size in bytes.                                                | `100`      |\n| fieldSize     | \u003cem\u003enumber\u003c/em\u003e | Max field value size in bytes.                                               | `1024`     |\n| fields        | \u003cem\u003enumber\u003c/em\u003e | Max number of non-file fields.                                               | `Infinity` |\n| fileSize      | \u003cem\u003enumber\u003c/em\u003e | For multipart forms, the max file size in bytes.                             | `Infinity` |\n| files         | \u003cem\u003enumber\u003c/em\u003e | For multipart forms, the max number of file fields.                          | `Infinity` |\n| parts         | \u003cem\u003enumber\u003c/em\u003e | For multipart forms, the max number of parts (fields + files).               | `Infinity` |\n| headerPairs   | \u003cem\u003enumber\u003c/em\u003e | For multipart forms, the max number of header key=\u0026gt; value pairs to parse. | `2000`     |\n\n__\u003ca name=\"type-multerconfig\"\u003e`MulterConfig`\u003c/a\u003e__\n\n|     Name     |                                                                  Type                                                                  |                                           Description                                           | Default |\n| ------------ | -------------------------------------------------------------------------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------- | ------- |\n| dest         | \u003cem\u003estring\u003c/em\u003e                                                                                                                        | Where to store the files.                                                                       | -       |\n| storage      | \u003cem\u003eStorageEngine\u003c/em\u003e                                                                                                                 | Where to store the files.                                                                       | -       |\n| fileFilter   | \u003cem\u003e(req: IncomingMessage, file: File, callback: (error: (Error|null), acceptFile: boolean)) =\u003e void\u003c/em\u003e                              | [Function](https://github.com/expressjs/multer#filefilter) to control which files are accepted. | -       |\n| limits       | \u003cem\u003e\u003ca href=\"#type-limits\" title=\"[An object](https://github.com/expressjs/multer#limits) specifying the size limits.\"\u003eLimits\u003c/a\u003e\u003c/em\u003e | Limits of the uploaded data.                                                                    | -       |\n| preservePath | \u003cem\u003eboolean\u003c/em\u003e                                                                                                                       | Keep the full path of files instead of just the base name.                                      | `false` |\n\n\n\u003c/details\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/6.svg?sanitize=true\" width=\"15\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ca href=\"https://github.com/koajs/csrf\"\u003e\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/csrf.svg?sanitize=true\" align=\"left\" height=\"100\"\u003e\u003c/a\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ca name=\"cross-site-request-forgery\"\u003eCross-Site Request Forgery\u003c/a\u003e\u003c/strong\u003e: prevention against CSRF attacks.\n\u003chr/\u003e\n\n__\u003ca name=\"type-csrfoptions\"\u003e`CSRFOptions`\u003c/a\u003e__\n\n|  Name  |                  Type                   |              Description               | Default |\n| ------ | --------------------------------------- | -------------------------------------- | ------- |\n| use    | \u003cem\u003eboolean\u003c/em\u003e                        | Use this middleware for every request. | `false` |\n| config | \u003cem\u003e[CSRFConfig](#type-csrfconfig)\u003c/em\u003e | `koa-csrf` configuration.              | -       |\n\u003c/summary\u003e\n\n__\u003ca name=\"type-csrfconfig\"\u003e`CSRFConfig`\u003c/a\u003e__\n\n|              Name              |       Type        | Description |\n| ------------------------------ | ----------------- | ----------- |\n| invalidSessionSecretMessage    | \u003cem\u003estring\u003c/em\u003e   |             |\n| invalidSessionSecretStatusCode | \u003cem\u003enumber\u003c/em\u003e   |             |\n| invalidTokenMessage            | \u003cem\u003estring\u003c/em\u003e   |             |\n| invalidTokenStatusCode         | \u003cem\u003enumber\u003c/em\u003e   |             |\n| excludedMethods                | \u003cem\u003estring[]\u003c/em\u003e |             |\n| disableQuery                   | \u003cem\u003eboolean\u003c/em\u003e  |             |\n\n\n\u003c/details\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/7.svg?sanitize=true\" width=\"15\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ca href=\"https://github.com/koajs/body-parser\"\u003e\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/bodyparser.svg?sanitize=true\" align=\"left\" height=\"100\"\u003e\u003c/a\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ca name=\"parse-body\"\u003eParse Body\u003c/a\u003e\u003c/strong\u003e: parsing of data sent with requests.\n\u003chr/\u003e\n\n__\u003ca name=\"type-bodyparseroptions\"\u003e`BodyparserOptions`\u003c/a\u003e__\n\n|  Name  |                        Type                         |              Description               | Default |\n| ------ | --------------------------------------------------- | -------------------------------------- | ------- |\n| use    | \u003cem\u003eboolean\u003c/em\u003e                                    | Use this middleware for every request. | `false` |\n| config | \u003cem\u003e[BodyparserConfig](#type-bodyparserconfig)\u003c/em\u003e | `koa-bodyparser` configuration.        | -       |\n\u003c/summary\u003e\n\n[`import('koa').Context`](https://github.com/koajs/koa/blob/master/docs/api/context.md) __\u003ca name=\"type-koacontext\"\u003e`koa.Context`\u003c/a\u003e__\n\n__\u003ca name=\"type-bodyparserconfig\"\u003e`BodyparserConfig`\u003c/a\u003e__\n\n|    Name     |                            Type                             |                                                 Description                                                  |      Default       |\n| ----------- | ----------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ | ------------------ |\n| enableTypes | \u003cem\u003estring[]\u003c/em\u003e                                           | Parser will only parse when request type hits enableTypes.                                                   | `['json', 'form']` |\n| encode      | \u003cem\u003estring\u003c/em\u003e                                             | Requested encoding.                                                                                          | `utf-8`            |\n| formLimit   | \u003cem\u003estring\u003c/em\u003e                                             | Limit of the urlencoded body. If the body ends up being larger than this limit a 413 error code is returned. | `56kb`             |\n| jsonLimit   | \u003cem\u003estring\u003c/em\u003e                                             | Limit of the json body.                                                                                      | `1mb`              |\n| strict      | \u003cem\u003eboolean\u003c/em\u003e                                            | When set to true, JSON parser will only accept arrays and objects.                                           | `true`             |\n| detectJSON  | \u003cem\u003e(ctx: Context) =\u003e boolean\u003c/em\u003e                          | Custom json request detect function.                                                                         | `null`             |\n| extendTypes | \u003cem\u003e{ json: string[], form: string[], text: string[] }\u003c/em\u003e | Support extend types.                                                                                        | -                  |\n| onerror     | \u003cem\u003e(err: Error, ctx: Context) =\u003e void\u003c/em\u003e                 | Support custom error handle.                                                                                 | -                  |\n\n\n\u003c/details\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/8.svg?sanitize=true\" width=\"15\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ca href=\"#\"\u003e\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/checkauth.svg?sanitize=true\" align=\"left\" height=\"100\"\u003e\u003c/a\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ca name=\"checking-auth\"\u003eChecking Auth\u003c/a\u003e\u003c/strong\u003e: a simple function which throws if \u003ccode\u003ectx.session.user\u003c/code\u003e is not set. Non-configurable.\n\u003chr/\u003e\n\n__\u003ca name=\"type-checkauthoptions\"\u003e`CheckauthOptions`\u003c/a\u003e__\n\n| Name |       Type       |              Description               | Default |\n| ---- | ---------------- | -------------------------------------- | ------- |\n| use  | \u003cem\u003eboolean\u003c/em\u003e | Use this middleware for every request. | `false` |\n\u003c/summary\u003e\n\n\n\n\n\u003c/details\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/9.svg?sanitize=true\" width=\"15\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ca href=\"https://github.com/koajs/logger\"\u003e\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/logger.svg?sanitize=true\" align=\"left\" height=\"100\"\u003e\u003c/a\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ca name=\"logging\"\u003eLogging\u003c/a\u003e\u003c/strong\u003e: a logger of incoming requests / response times and sizes.\n\u003chr/\u003e\n\n__\u003ca name=\"type-loggeroptions\"\u003e`LoggerOptions`\u003c/a\u003e__\n\n|  Name  |                    Type                     |              Description               | Default |\n| ------ | ------------------------------------------- | -------------------------------------- | ------- |\n| use    | \u003cem\u003eboolean\u003c/em\u003e                            | Use this middleware for every request. | `false` |\n| config | \u003cem\u003e[LoggerConfig](#type-loggerconfig)\u003c/em\u003e | `koa-logger` configuration.            | -       |\n\u003c/summary\u003e\n\n__\u003ca name=\"type-loggerconfig\"\u003e`LoggerConfig`\u003c/a\u003e__\n\n|    Name     |                                              Type                                              |                                                                                       Description                                                                                       |\n| ----------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| transporter | \u003cem\u003e(str: string, args: [string, string, string, string, string, string, string]) =\u003e void\u003c/em\u003e | Param `str` is output string with ANSI Color, and you can get pure text with other modules like `strip-ansi`. Param `args` is a array by `[format, method, url, status, time, length]`. |\n\n\n\u003c/details\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/10.svg?sanitize=true\" width=\"15\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ca href=\"https://github.com/koajs/compress\"\u003e\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/compress.svg?sanitize=true\" align=\"left\" height=\"100\"\u003e\u003c/a\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ca name=\"compression\"\u003eCompression\u003c/a\u003e\u003c/strong\u003e: enabling gzip and other compression.\n\u003chr/\u003e\n\n__\u003ca name=\"type-compressoptions\"\u003e`CompressOptions`\u003c/a\u003e__\n\n|  Name  |                      Type                       |              Description               | Default |\n| ------ | ----------------------------------------------- | -------------------------------------- | ------- |\n| use    | \u003cem\u003eboolean\u003c/em\u003e                                | Use this middleware for every request. | `false` |\n| config | \u003cem\u003e[CompressConfig](#type-compressconfig)\u003c/em\u003e | `koa-compress` configuration.          | -       |\n\u003c/summary\u003e\n\n__\u003ca name=\"type-compressconfig\"\u003e`CompressConfig`\u003c/a\u003e__\n\n|    Name     |                    Type                    |                                                          Description                                                          | Default |\n| ----------- | ------------------------------------------ | ----------------------------------------------------------------------------------------------------------------------------- | ------- |\n| filter      | \u003cem\u003e(content_type: string) =\u003e boolean\u003c/em\u003e | An optional function that checks the response content type to decide whether to compress. By default, it uses `compressible`. | -       |\n| threshold   | \u003cem\u003enumber\u003c/em\u003e                            | Minimum response size in bytes to compress.                                                                                   | `1024`  |\n| flush       | \u003cem\u003enumber\u003c/em\u003e                            | Default: `zlib.constants.Z_NO_FLUSH`.                                                                                         | -       |\n| finishFlush | \u003cem\u003enumber\u003c/em\u003e                            | Default: `zlib.constants.Z_FINISH`.                                                                                           | -       |\n| chunkSize   | \u003cem\u003enumber\u003c/em\u003e                            | Default: `16*1024`.                                                                                                           | -       |\n| windowBits  | \u003cem\u003enumber\u003c/em\u003e                            | Support extend types.                                                                                                         | -       |\n| level       | \u003cem\u003enumber\u003c/em\u003e                            | Compression only.                                                                                                             | -       |\n| memLevel    | \u003cem\u003enumber\u003c/em\u003e                            | Compression only.                                                                                                             | -       |\n| strategy    | \u003cem\u003enumber\u003c/em\u003e                            | Compression only.                                                                                                             | -       |\n| dictionary  | \u003cem\u003e*\u003c/em\u003e                                 | Deflate/inflate only, empty dictionary by default.                                                                            | -       |\n\n\n\u003c/details\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/11.svg?sanitize=true\" width=\"15\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ca href=\"https://github.com/koajs/static\"\u003e\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/static.svg?sanitize=true\" align=\"left\" height=\"100\"\u003e\u003c/a\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ca name=\"static-files\"\u003eStatic Files\u003c/a\u003e\u003c/strong\u003e: serving files from filesystem.\n\u003chr/\u003e\n\n__\u003ca name=\"type-staticoptions\"\u003e`StaticOptions`\u003c/a\u003e__\n\n|   Name    |                    Type                     |                    Description                    | Default |\n| --------- | ------------------------------------------- | ------------------------------------------------- | ------- |\n| __root*__ | \u003cem\u003e(string \\| string[])\u003c/em\u003e               | Root or multiple roots from which to serve files. | -       |\n| use       | \u003cem\u003eboolean\u003c/em\u003e                            | Use this middleware for every request.            | `false` |\n| mount     | \u003cem\u003estring\u003c/em\u003e                             | Path from which to serve files.                   | `/`     |\n| maxage    | \u003cem\u003enumber\u003c/em\u003e                             | How long to cache file for.                       | `0`     |\n| config    | \u003cem\u003e[StaticConfig](#type-staticconfig)\u003c/em\u003e | `koa-static` configuration.                       | -       |\n\u003c/summary\u003e\n\n[`import('http').ServerResponse`](https://nodejs.org/api/http.html#http_class_http_serverresponse) __\u003ca name=\"type-httpserverresponse\"\u003e`http.ServerResponse`\u003c/a\u003e__\n\n`(res: ServerResponse, path: string, stats: Stats) =\u003e any` __\u003ca name=\"type-setheaders\"\u003e`SetHeaders`\u003c/a\u003e__\n\n__\u003ca name=\"type-staticconfig\"\u003e`StaticConfig`\u003c/a\u003e__\n\n|    Name    |                  Type                   |                                                                                             Description                                                                                             |   Default    |\n| ---------- | --------------------------------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ------------ |\n| maxage     | \u003cem\u003enumber\u003c/em\u003e                         | Browser cache max-age in milliseconds.                                                                                                                                                              | `0`          |\n| hidden     | \u003cem\u003eboolean\u003c/em\u003e                        | Allow transfer of hidden files.                                                                                                                                                                     | `false`      |\n| index      | \u003cem\u003estring\u003c/em\u003e                         | Default file name.                                                                                                                                                                                  | `index.html` |\n| defer      | \u003cem\u003eboolean\u003c/em\u003e                        | If `true`, serves after return next(), allowing any downstream middleware to respond first.                                                                                                         | `false`      |\n| gzip       | \u003cem\u003eboolean\u003c/em\u003e                        | Try to serve the gzipped version of a file automatically when gzip is supported by a client and if the requested file with `.gz` extension exists.                                                  | `true`       |\n| br         | \u003cem\u003eboolean\u003c/em\u003e                        | Try to serve the brotli version of a file automatically when brotli is supported by a client and if the requested file with `.br` extension exists (note, that brotli is only accepted over https). | `true`       |\n| setHeaders | \u003cem\u003e[SetHeaders](#type-setheaders)\u003c/em\u003e | Function to set custom headers on response.                                                                                                                                                         | -            |\n| extensions | \u003cem\u003eboolean\u003c/em\u003e                        | Try to match extensions from passed array to search for file when no extension is sufficed in URL. First found is served.                                                                           | `false`      |\n\n\nFor example, the below configuration will serve files from both the `static` directory of the project, and the _React.js_ dependency. When `NODE_ENV` environment variable is set to `production`, files will be cached for 10 days.\n\n```js\nimport { join, dirname } from 'path'\nimport idioCore from '@idio/core'\n\nconst STATIC = join(__dirname, 'static')\nconst REACT = join(dirname(require.resolve('react')), 'umd')\n\nconst DAY = 1000 * 60 * 60 * 24\n\nconst Static = async () =\u003e {\n  const { url } = await idioCore({\n    static: {\n      use: true,\n      root: [STATIC, REACT],\n      mount: '/scripts',\n      maxage: process.env.NODE_ENV == 'production' ? 10 * DAY : 0,\n    },\n  }, { port: 5004 })\n  return url\n}\n```\n```\nStatic server started on http://localhost:5004\n```\n\n\u003c/details\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/12.svg?sanitize=true\" width=\"15\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ca href=\"https://github.com/koajs/cors\"\u003e\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/cors.svg?sanitize=true\" align=\"left\" height=\"100\"\u003e\u003c/a\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ca name=\"cors\"\u003eCORS\u003c/a\u003e\u003c/strong\u003e: return Cross-Origin Resource Sharing headers.\n\u003chr/\u003e\n\n`import('koa').Context` __\u003ca name=\"type-koacontext\"\u003e`koa.Context`\u003c/a\u003e__\n\n__\u003ca name=\"type-corsoptions\"\u003e`CorsOptions`\u003c/a\u003e__\n\n|  Name  |                           Type                           |                                                                                                                                                                                                             Description                                                                                                                                                                                                              | Default |\n| ------ | -------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | ------- |\n| origin | \u003cem\u003estring|Array\u003cstring\u003e|((ctx: Context) =\u003e string)\u003c/em\u003e | The origin or an array of origins to accept as valid. In case of an array, the origin from the request headers will be searched in the array, and if found, it will be returned (since browsers only support a single `Access-Control-Allow-Origin` header). If a function is passed, it should return the string with the origin to set. If not passed, the request origin is returned, allowing any origin to access the resource. | -       |\n| use    | \u003cem\u003eboolean\u003c/em\u003e                                         | Use this middleware for every request.                                                                                                                                                                                                                                                                                                                                                                                               | `false` |\n| config | \u003cem\u003e[CorsConfig](#type-corsconfig)\u003c/em\u003e                  | `@koa/cors` configuration.                                                                                                                                                                                                                                                                                                                                                                                                           | -       |\n\u003c/summary\u003e\n\n__\u003ca name=\"type-corsconfig\"\u003e`CorsConfig`\u003c/a\u003e__\n\n|        Name        |                   Type                   |                      Description                       |             Default              |\n| ------------------ | ---------------------------------------- | ------------------------------------------------------ | -------------------------------- |\n| origin             | \u003cem\u003estring\u003c/em\u003e                          | `Access-Control-Allow-Origin` header value.            | `request Origin header`          |\n| allowMethods       | \u003cem\u003e(string \\| Array\u0026lt;string\u0026gt;)\u003c/em\u003e | `Access-Control-Allow-Methods` header value.           | `GET,HEAD,PUT,POST,DELETE,PATCH` |\n| exposeHeaders      | \u003cem\u003e(string \\| Array\u0026lt;string\u0026gt;)\u003c/em\u003e | `Access-Control-Expose-Headers` header value.          | -                                |\n| allowHeaders       | \u003cem\u003e(string \\| Array\u0026lt;string\u0026gt;)\u003c/em\u003e | `Access-Control-Allow-Headers` header value.           | -                                |\n| maxAge             | \u003cem\u003e(string \\| number)\u003c/em\u003e              | `Access-Control-Max-Age` header value in seconds.      | -                                |\n| credentials        | \u003cem\u003eboolean\u003c/em\u003e                         | `Access-Control-Allow-Credentials` header value.       | `false`                          |\n| keepHeadersOnError | \u003cem\u003eboolean\u003c/em\u003e                         | Add set headers to `err.header` if an error is thrown. | `false`                          |\n\n\n\u003c/details\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/13.svg?sanitize=true\" width=\"15\"\u003e\u003c/a\u003e\u003c/p\u003e\n\u003ca href=\"https://github.com/idiocc/frontend\"\u003e\u003cimg src=\"https://raw.github.com/idiocc/core/master/images/frontend.svg?sanitize=true\" align=\"left\" height=\"100\"\u003e\u003c/a\u003e\n\u003cdetails\u003e\n\u003csummary\u003e\u003cstrong\u003e\u003ca name=\"frontend\"\u003eFrontend\u003c/a\u003e\u003c/strong\u003e: serve JS and CSS files as modules for modern browsers.\n\u003chr/\u003e\n\n__\u003ca name=\"type-frontendoptions\"\u003e`FrontendOptions`\u003c/a\u003e__: Allows to serve front-end JS files and CSS as modules, including from node_modules folder.\n\n|   Name    |                      Type                       |                       Description                       |  Default   |\n| --------- | ----------------------------------------------- | ------------------------------------------------------- | ---------- |\n| directory | \u003cem\u003e(string \\| Array\u0026lt;string\u0026gt;)\u003c/em\u003e        | The directory or directories from which to serve files. | `frontend` |\n| config    | \u003cem\u003e[FrontendConfig](#type-frontendconfig)\u003c/em\u003e | `@idio/frontend` configuration.                         | -          |\n\u003c/summary\u003e\n\n__\u003ca name=\"type-frontendconfig\"\u003e`FrontendConfig`\u003c/a\u003e__\n\n|  Name  |      Type       |                                                                                                           Description                                                                                                            |           Default            |\n| ------ | --------------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------- |\n| pragma | \u003cem\u003estring\u003c/em\u003e | The pragma function to import. This enables to skip writing `h` at the beginning of each file. JSX will be transpiled to have `h` pragma, therefore to use React it's possible to do `import { createElement: h } from 'react'`. | `import { h } from 'preact'` |\n\n\n\u003c/details\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/14.svg?sanitize=true\"\u003e\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/core` bundle, it can be done in several ways.\n\n1. Passing the middleware function as part of the _MiddlewareConfig_. 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\n```js\nimport idioCore from '@idio/core'\n\n/** @typedef {import('koa').Middleware} Middleware */\n\nconst APIServer = async (port) =\u003e {\n  const { url } = await idioCore({\n    // 1. Add logging middleware.\n    /** @type {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    /** @type {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    /** @type {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\nexport default APIServer\n```\n```\nStarted API server at: http://localhost:5005\n --\u003e API: GET / 403\n --\u003e API: GET /?key=app-secret 200\n```\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\n```js\nimport rqt from 'rqt'\nimport idioCore from '@idio/core'\nimport APIServer from './api-server'\n\nconst 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 idioCore({\n    /** @type {import('koa').Middleware} */\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('koa').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```\nAPI server started at http://localhost:5001\nProxy started at http://localhost:5002\n --\u003e API: GET /?key=app-secret 200\n --\u003e Proxy: GET / 200\n```\n\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/15.svg?sanitize=true\"\u003e\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 [returned object](#type-idiocore), 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 idioCore from '@idio/core'\n\nasync function pre(ctx, next) {\n  console.log('  \u003c-- %s %s',\n    ctx.request.method,\n    ctx.request.path,\n  )\n  await next()\n}\n\nasync function post(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\nconst Server = async () =\u003e {\n  const path = '/test'\n  const {\n    url, router, app, middleware: { bodyparser },\n  } = await idioCore({\n    // 1. Configure the bodyparser without using it for each request.\n    bodyparser: {\n      config: {\n        enableTypes: ['json'],\n      },\n    },\n  }, { port: 5003 })\n\n  // 2. Setup router with the bodyparser and path-specific middleware.\n  router.post(path,\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}${path}`\n}\n```\n```\nPage available at: http://localhost:5003/test\n  \u003c-- POST /test\n  --\u003e POST /test 200\n```\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/16.svg?sanitize=true\"\u003e\u003c/a\u003e\u003c/p\u003e\n\n## Copyright\n\nMiddleware icons and logo from [Deco Dingbats NF font](https://www.1001fonts.com/decodingbats1-font.html).\n\nMiddleware types descriptions by their respective authors.\n\n\u003ctable\u003e\n  \u003ctr\u003e\n    \u003cth\u003e\n      \u003ca href=\"https://artd.eco\"\u003e\n        \u003cimg src=\"https://raw.githubusercontent.com/wrote/wrote/master/images/artdeco.png\" alt=\"Art Deco\" /\u003e\n      \u003c/a\u003e\n    \u003c/th\u003e\n    \u003cth\u003e© \u003ca href=\"https://artd.eco\"\u003eArt Deco\u003c/a\u003e for \u003ca href=\"https://idio.cc\"\u003eIdio\u003c/a\u003e 2019\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    \u003cth\u003e\n      \u003ca href=\"https://www.technation.sucks\" title=\"Tech Nation Visa\"\u003e\n        \u003cimg src=\"https://raw.githubusercontent.com/artdecoweb/www.technation.sucks/master/anim.gif\"\n          alt=\"Tech Nation Visa\" /\u003e\n      \u003c/a\u003e\n    \u003c/th\u003e\n    \u003cth\u003e\u003ca href=\"https://www.technation.sucks\"\u003eTech Nation Visa Sucks\u003c/a\u003e\u003c/th\u003e\n  \u003c/tr\u003e\n\u003c/table\u003e\n\n\u003cp align=\"center\"\u003e\u003ca href=\"#table-of-contents\"\u003e\u003cimg src=\".documentary/section-breaks/-1.svg?sanitize=true\"\u003e\u003c/a\u003e\u003c/p\u003e","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidiocc%2Fcore","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fidiocc%2Fcore","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fidiocc%2Fcore/lists"}