{"id":23366711,"url":"https://github.com/d8corp/innet-server","last_synced_at":"2025-04-10T14:04:33.768Z","repository":{"id":57118741,"uuid":"462282696","full_name":"d8corp/innet-server","owner":"d8corp","description":"Create server-side application with innet","archived":false,"fork":false,"pushed_at":"2024-05-12T12:21:08.000Z","size":2379,"stargazers_count":2,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-03-24T12:46:57.244Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"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/d8corp.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2022-02-22T12:14:02.000Z","updated_at":"2023-09-04T08:29:37.000Z","dependencies_parsed_at":"2023-11-11T21:22:12.124Z","dependency_job_id":"2098c983-2c8c-4ee6-8a72-86d1ad6e21c3","html_url":"https://github.com/d8corp/innet-server","commit_stats":{"total_commits":32,"total_committers":1,"mean_commits":32.0,"dds":0.0,"last_synced_commit":"ea6ea7790ad8df020b8b2ff38a70b70b35cfc622"},"previous_names":[],"tags_count":27,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d8corp%2Finnet-server","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d8corp%2Finnet-server/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d8corp%2Finnet-server/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/d8corp%2Finnet-server/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/d8corp","download_url":"https://codeload.github.com/d8corp/innet-server/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248231086,"owners_count":21069266,"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-12-21T14:17:22.252Z","updated_at":"2025-04-10T14:04:33.733Z","avatar_url":"https://github.com/d8corp.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"\n\u003ca href=\"https://www.npmjs.com/package/innet\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/d8corp/innet/main/logo.svg\" align=\"left\" width=\"90\" height=\"90\" alt=\"InnetJs logo by Mikhail Lysikov\"\u003e\n\u003c/a\u003e\n\n# \u0026nbsp; @innet/server\n\n\u0026nbsp;\n\n[![NPM](https://img.shields.io/npm/v/@innet/server.svg)](https://www.npmjs.com/package/@innet/server)\n[![downloads](https://img.shields.io/npm/dm/@innet/server.svg)](https://www.npmtrends.com/@innet/server)\n[![changelog](https://img.shields.io/badge/Changelog-⋮-brightgreen)](https://changelogs.xyz/@innet/server)\n[![license](https://img.shields.io/npm/l/@innet/server)](https://github.com/d8corp/innet-server/blob/main/LICENSE)\n\n## Abstract\nThis package helps to create server-side application.\n\nHere you find **JSX components on back-end side** 🎉, cms, routing, proxy, html rendering and more.\n\nBased on [innet](https://www.npmjs.com/package/innet).\n\n[![stars](https://img.shields.io/github/stars/d8corp/innet-server?style=social)](https://github.com/d8corp/innet-server/stargazers)\n[![watchers](https://img.shields.io/github/watchers/d8corp/innet-server?style=social)](https://github.com/d8corp/innet-server/watchers)\n\n## Install\nThe simplest way is using `innetjs`\n\n```shell\nnpx innetjs init my-app -t be\n```\n*change my-app to work folder name*\n\nGo into `my-app` and check `README.md`\n\n## Handler\n\nUse `server` handler to start an application.\n```typescript\nimport innet from 'innet'\nimport server from '@innet/server'\n\nimport app from './app'\n\ninnet(app, server)\n```\n\n## Server\nTo start http(s) server, use `server` element.\n\nTry it out in `app.tsx`\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      Hello World!\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nAny content inside the server will be turned back to user.\nIn this case the user will get `Hello World` on any request.\n\nUse `npm start` to run this server.\n\n### Port\nTo change the port of the web server you can use `port` prop.\n\n```typescript jsx\nexport default (\n  \u003cserver port={80}\u003e\n    \u003caction\u003e\n      Hello World!\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nor you can use `PORT` environment variable.\n\n### SSL\nTo have https connection you should provide SSL certificate.\n\n```typescript jsx\nconst ssl = {\n  key: 'local.key',\n  cert: 'local.crt'\n}\n\nexport default (\n  \u003cserver ssl={ssl}\u003e\n    \u003caction\u003e\n      Hello World!\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nor you can use `SSL_CRT` and `SSL_KEY` environment variables.\n\n### onStart\nYou can show some message or do something right after the server starts.\n```typescript jsx\nexport default (\n  \u003cserver onStart={console.log}\u003e\n    \u003caction\u003e\n      Hello World!\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\n### onError\nYou can log errors or do something else, when the server get an error.\n\n```typescript jsx\nexport default (\n  \u003cserver onError={console.error}\u003e\n    \u003caction\u003e\n      Hello World!\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\n### onRequest\nYou can log any request with `onRequest` prop.\n\n```typescript jsx\nexport default (\n  \u003cserver onRequest={console.log}\u003e\n    \u003caction\u003e\n      Hello World!\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\n### onDestroy\nYou can react on destroy the server with `onDestroy` prop.\n\n```typescript jsx\nexport default (\n  \u003cserver\n    onDestroy={() =\u003e console.log('destroy')}\u003e\n    \u003caction\u003e\n      Hello World!\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\n## HTML\nYou can use `html` element to return html content.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003chtml\u003e\n        \u003chead\u003e\n          \u003ctitle\u003eInnet App\u003c/title\u003e\n        \u003c/head\u003e\n        \u003cbody\u003e\n          Hello World!\n        \u003c/body\u003e\n      \u003c/html\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nYou can use variables to split it anyhow.\n\n```typescript jsx\nconst content = (\n  \u003chtml\u003e\n    \u003chead\u003e\n      \u003ctitle\u003eInnet App\u003c/title\u003e\n    \u003c/head\u003e\n    \u003cbody\u003e\n      Hello World!\n    \u003c/body\u003e\n  \u003c/html\u003e\n)\n\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      {content}\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\n## Header\nYou can add an HTTP header into response with `header` element.\n\n```typescript jsx\nconst content = (\n  \u003chtml.../\u003e\n) // check prev example\n\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cheader name='content-type' value='text/html'\u003e\n        {content}\n      \u003c/header\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nAlso, you can put header around the content, it works the same.\n\n```typescript jsx\nconst content = (\n  \u003chtml.../\u003e\n) // check prev example\n\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cheader name='content-type' value='text/html' /\u003e\n      {content}\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\n## File\nYou can return a file as a response.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cheader name='cache-control' value='max-age=300'\u003e\n        \u003cfile path='index.html' /\u003e\n      \u003c/header\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nIn this case `cache-control` will be equal to `max-age=300` even if the file does not exist.\n\nYou can put content into the file to apply it only if the file does exist.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cfile path='index.html'\u003e\n        \u003cheader name='cache-control' value='max-age=300' /\u003e\n      \u003c/file\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nPut `index.html` in the root of the project (`my-app` folder).\n\n## Router\nThe router helps to handle requests by route.\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003crouter\u003e\n        \u003cfile path='index.html' /\u003e\n      \u003c/router\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nThe router does nothing and returns self content.\nIt starts work only with the next props.\n\n### method\nThis property says that the content of the route should be run if the request method equals to the prop.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003crouter method='GET'\u003e\n        \u003cfile path='index.html' /\u003e\n      \u003c/router\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\n### path\nYou can set `path` to match with it.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003crouter method='GET' path='/'\u003e\n        \u003cfile path='index.html' /\u003e\n      \u003c/router\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nYou will get the `index.html` only on the root path with `GET` method.\n\nThis prop has regex like syntax, so you can set the path as you wish.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003crouter path='/user/[0-9]+'\u003e\n        \u003cfile path='index.html' /\u003e\n      \u003c/router\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nTo provide named params from url, use named capturing groups of regex.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003crouter path='/user/(?\u003cid\u003e[\\w-]+)'\u003e\n        \u003cfile path='index.html' /\u003e\n      \u003c/router\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\n### ish\nYou can react on any path which starts with provided one.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003crouter path='/test' ish\u003e\n        \u003cfile path='index.html' /\u003e\n      \u003c/router\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\n`/`, `/something`, `/test1` do not match.  \n`/test`, `/test/something` matches.\n\n### prefix\n\nYou can use a router inside another one and `prefix` helps reduce path prop.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003crouter path='/test' prefix='/test' ish\u003e\n        \u003crouter path='/'\u003e\n          \u003cfile path='index.html' /\u003e\n        \u003c/router\u003e\n        \u003crouter path='/404'\u003e\n          \u003cfile path='404.html' /\u003e\n        \u003c/router\u003e\n      \u003c/router\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nHere you can get `index.html` on `/test` and `404.html` on `/test/404`.\n\n### onMatch\n\nYou can log the requests of any router.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003crouter path='/test' onMatch={console.log}\u003e\n        \u003cfile path='index.html' /\u003e\n      \u003c/router\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\n## switch\n\nBy default,\nrouters in the same router runs one by one\nindependent to result of the previous route.\n\nTo avoid this you can use switch element.\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cswitch\u003e\n        \u003crouter path='/'\u003e\n          \u003cfile path='index.html' /\u003e\n        \u003c/router\u003e\n        \u003cfile path='404.html' /\u003e\n      \u003c/switch\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nYou will get `index.html` only on the root path,\nany other path will return `404.html`.\n\n## cms\n\nCMS helps to return files from a folder by path.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cswitch\u003e\n        \u003ccms dir='cms' /\u003e\n        \u003cfile path='404.html' /\u003e\n      \u003c/switch\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nIt will check if the file exist in cms folder then returns the file else returns `404.html`.\n\nYou can use prefix with router to handle specific path.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cswitch\u003e\n        \u003crouter path='/cms' ish\u003e\n          \u003ccms dir='cms' prefix='/cms' /\u003e\n        \u003c/router\u003e\n        \u003cfile path='404.html' /\u003e\n      \u003c/switch\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nYou can input something into `cms`, if requested file is exist then the content should be used.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cswitch\u003e\n        \u003ccms dir='cms'\u003e\n          \u003cheader name='cache-control' value='max-age=300' /\u003e\n        \u003c/cms\u003e\n        \u003cfile path='404.html' /\u003e\n      \u003c/switch\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\n## proxy\nYou can proxy request.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cswitch\u003e\n        \u003ccms dir='cms' /\u003e\n        \u003cproxy to='https://site.com' /\u003e\n      \u003c/switch\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nIn this case, if you have a file in cms folder then the file will return\nelse makes request to the `site.com`.\n\n## redirect\nYou can redirect users to another resource.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cswitch\u003e\n        \u003ccms dir='cms' /\u003e\n        \u003credirect to='https://site.com' /\u003e\n      \u003c/switch\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\n### status\nBy default, status is `301`, you can change it with `status` prop.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cswitch\u003e\n        \u003ccms dir='cms' /\u003e\n        \u003credirect to='https://site.com' status={302} /\u003e\n      \u003c/switch\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nAlso, you can use string key of status.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cswitch\u003e\n        \u003ccms dir='cms' /\u003e\n        \u003credirect to='https://site.com' status='found'/\u003e\n      \u003c/switch\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\n## Components\n\nAny component is just a function which returns content that should be run.\n\n`server.tsx`\n```typescript jsx\nexport const Server = ({ cmsPrefix }) =\u003e (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cswitch\u003e\n        \u003crouter path={cmsPrefix} ish\u003e\n          \u003ccms dir='cms' prefix={cmsPrefix} /\u003e\n        \u003c/router\u003e\n        \u003cfile path='404.html' /\u003e\n      \u003c/switch\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nand then you can use it inside `app.tsx`.\n\n```typescript jsx\nimport { Server } from './server'\n\nexport default \u003cServer cmsPrefix='/cms' /\u003e\n```\n\nYou can use it with any other functionality, for example with `html`.\n\n```typescript jsx\nimport { useChildren } from '@innet/jsx'\n\nfunction Html ({ title }) {\n  const children = useChildren()\n\n  return (\n    \u003cheader name='content-type' value='text/html'\u003e\n      \u003chtml\u003e\n      \u003chead\u003e\n        \u003ctitle\u003e{title}\u003c/title\u003e\n      \u003c/head\u003e\n      \u003cbody\u003e\n        {children}\n      \u003c/body\u003e\n      \u003c/html\u003e\n    \u003c/header\u003e\n  )\n}\n\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cHtml title='main'\u003e\n        Hello World!\n      \u003c/Html\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e  \n)\n```\n\nThe first argument is props, the second is children and the last one is a handler.\n\nYou can use components inside another component.\n\n## success\nIf you work on REST API, you can use `success` or `error` as an answer\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003csuccess /\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e  \n)\n```\n\nYou will get `204` status (`noContent`), without content.\n\nYou can provide some data to the user by children.\n```typescript jsx\nconst data = {\n  posts: []\n}\n\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003csuccess\u003e\n        {data}\n      \u003c/success\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\nYou will get `200` status (`ok`), with body equals data.\n\n### status\nYou can set status by status prop.\n\n```typescript jsx\nconst data = {\n  id: '123'\n}\n\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003csuccess status='created'\u003e\n        {data}\n      \u003c/success\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e  \n)\n```\n\nYou will get `201` status (`created`), with data as a content.\n\nYou can use a number with `status` prop.\n\n```typescript jsx\nconst data = {\n  id: '123'\n}\n\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003csuccess status={201}\u003e\n        {data}\n      \u003c/success\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e  \n)\n```\n\n## error\nYou can return an error to the user.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cerror /\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e  \n)\n```\n\nYou will get `520` status (`unknownError`).\n\nYou can provide some data to the user by children.\n\n```typescript jsx\nconst data = {\n  message: 'Some error!'\n}\n\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cerror\u003e\n        {data}\n      \u003c/error\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e  \n)\n```\n\n### status\nYou can change response status by `status` prop.\n\n```typescript jsx\nconst data = {\n  message: 'User not found!'\n}\n\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cerror status='notFound'\u003e\n        {data}\n      \u003c/error\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\nAlso, you can use a number with the status prop.\n\n```typescript jsx\nconst data = {\n  message: 'User not found!'\n}\n\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cerror status={404}\u003e\n        {data}\n      \u003c/error\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\n## cookie\nYou can set cookie by `cookie` element.\n\n```typescript jsx\nconst Login = ({ token }) =\u003e (\n  \u003ccookie key='token' value={token}\u003e\n    \u003csuccess /\u003e\n  \u003c/cookie\u003e\n)\n\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003cLogin token='test' /\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e  \n)\n```\n\nTo remove cookie just provide key without value.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003ccookie key='token'\u003e\n        \u003csuccess /\u003e\n      \u003c/cookie\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e  \n)\n```\n\n## useAction\nAction is an object which contains `request` and `response`.\nAlso, it contains a couple of fields and methods.\n\nAction available in components.\n\n```typescript jsx\nimport { useAction } from '@innet/server'\n\nfunction Test () {\n  const { req, res } = useAction()\n\n  console.log(req, res)\n}\n```\n\n### cookies\nYou can get cookies as an object from an action.\n\n```typescript jsx\nimport { useAction } from '@innet/server'\n\nfunction Cookies () {\n  const { cookies } = useAction()\n\n  return \u003csuccess\u003e{cookies}\u003c/success\u003e\n}\n```\n\n### setCookie\nYou can set cookie with action.\n\n```typescript jsx\nimport { useAction } from '@innet/server'\n\nfunction Login () {\n  const action = useAction()\n\n  action.setCookie('user', 'token')\n}\n```\n\n### path\nYou can get current path with action.\n\n```typescript jsx\nimport { useAction } from '@innet/server'\n\nfunction Path () {\n  const { path } = useAction()\n\n  return path\n}\n```\n\n### search\nYou can get current search as an object.\n\n```typescript jsx\nimport { useAction } from '@innet/server'\n\nfunction Search () {\n  const { search } = useAction()\n\n  return \u003csuccess\u003e{search}\u003c/success\u003e\n}\n```\n\n### body\nYou can parse body, and get values.\n\n```typescript jsx\nimport { useAction } from '@innet/server'\n\nasync function Body () {\n  const action = useAction()\n  \n  await action.parseBody()\n\n  return \u003csuccess\u003e{action.body}\u003c/success\u003e\n}\n```\n\n### files\nYou can get files from a user.\n\n```typescript jsx\nimport { useAction } from '@innet/server'\n\nasync function Body () {\n  const action = useAction()\n  \n  await action.parseBody()\n\n  return \u003csuccess\u003e{action.files}\u003c/success\u003e\n}\n```\n\n## useRouter\n\nYou can get router data in a component\n\n```typescript jsx\nimport { useRouter } from '@innet/server'\n\nfunction Router () {\n  const { prefix, params } = useRouter()\n\n  return \u003csuccess\u003e{{ prefix, params }}\u003c/success\u003e\n}\n```\n\nUse named capturing groups of regex in a route path prop to add the `params`.\n\n```typescript jsx\nexport default (\n  \u003cserver\u003e\n    \u003caction\u003e\n      \u003crouter path='/user/(?\u003cid\u003e[\\w-]+)'\u003e\n        \u003cRouter /\u003e\n      \u003c/router\u003e\n    \u003c/action\u003e\n  \u003c/server\u003e\n)\n```\n\nIn this case, you will get `id` equals `test` in the params on `/user/test` path.\n\n## Issues\nIf you find a bug or have a suggestion, please file an issue on [GitHub](https://github.com/d8corp/innet-server/issues).\n\n[![issues](https://img.shields.io/github/issues-raw/d8corp/innet-server)](https://github.com/d8corp/innet-server/issues)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd8corp%2Finnet-server","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fd8corp%2Finnet-server","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fd8corp%2Finnet-server/lists"}