Comparing version 0.0.1-alpha-20230302123305-a76a7ea to 0.0.1-alpha-20230302123848-dce33a7
{ | ||
"name": "fets", | ||
"version": "0.0.1-alpha-20230302123305-a76a7ea", | ||
"version": "0.0.1-alpha-20230302123848-dce33a7", | ||
"description": "TypeScript HTTP Framework focusing on e2e type-safety, easy setup, performance & great developer experience", | ||
"sideEffects": false, | ||
"dependencies": { | ||
"@whatwg-node/fetch": "0.8.2-alpha-20230302123305-a76a7ea", | ||
"@whatwg-node/server": "0.7.2-alpha-20230302123305-a76a7ea", | ||
"@whatwg-node/fetch": "0.8.2-alpha-20230302123848-dce33a7", | ||
"@whatwg-node/server": "0.7.2-alpha-20230302123848-dce33a7", | ||
"json-schema-to-ts": "2.6.2", | ||
@@ -10,0 +10,0 @@ "openapi-types": "12.1.0", |
166
README.md
@@ -78,2 +78,17 @@ # FETS | ||
path: '/todos', | ||
schemas: { | ||
response: { | ||
200: { | ||
type: 'array', | ||
items: { | ||
type: 'object', | ||
properties: { | ||
id: { type: 'string' }, | ||
title: { type: 'string' } | ||
} | ||
} | ||
} | ||
// as const is required | ||
} as const, | ||
} | ||
handler: () => new Response('Todos Index!') | ||
@@ -114,94 +129,95 @@ }) | ||
## Example | ||
## Quick Start | ||
Let's create a basic REST API that manages users. | ||
### FETS Client | ||
```ts | ||
import { createRouter, Response } from 'fets' | ||
```typescript | ||
import { createClient, Mutable } from 'fets' | ||
import type oas from './oas' | ||
const users = [ | ||
{ id: '1', name: 'John' }, | ||
{ id: '2', name: 'Jane' } | ||
] | ||
// OpenAPI document should be exported from a TypeScript file with as const | ||
const router = createRouter() | ||
.route({ | ||
method: 'GET', | ||
path: '/users', | ||
handler: () => Response.json(users) | ||
}) | ||
// Parameters are given in the `request.params` object | ||
.route({ | ||
method: 'GET', | ||
path: '/users/:id', | ||
handler: request => { | ||
const user = users.find(user => user.id === request.params.id) | ||
const client = createClient<Mutable<oas>>({ | ||
endpoint: 'https://example.com' | ||
}) | ||
if (!user) { | ||
return new Response(null, { | ||
status: 404 | ||
}) | ||
} | ||
/* | ||
or you can import the router types if you use monorepos | ||
import type { router } from './router'; | ||
return Response.json(user) | ||
} | ||
}) | ||
.route({ | ||
method: 'DELETE', | ||
path: '/users/:id', | ||
handler: request => { | ||
const user = users.find(user => user.id === request.params.id) | ||
const client = createClient<router>({ | ||
endpoint: 'https://example.com', | ||
}); | ||
*/ | ||
if (!user) { | ||
return new Response(null, { | ||
status: 404 | ||
}) | ||
} | ||
const response = await client['/user/:id'].get({ | ||
params: { | ||
id: '1' | ||
} | ||
}) | ||
users.splice(users.indexOf(user), 1) | ||
if (!response.ok) { | ||
const errorJson = await response.json() | ||
console.error(errorJson.message) | ||
} | ||
return new Response(null, { | ||
status: 204 | ||
}) | ||
} | ||
}) | ||
// Handle JSON bodies | ||
.route({ | ||
method: 'PUT', | ||
path: '/users', | ||
handler: async request => { | ||
const body = await request.json() | ||
const user = await response.json() | ||
console.log(`User's name is ${user.name}`) | ||
``` | ||
const user = { | ||
id: String(users.length + 1), | ||
name: body.name | ||
} | ||
[See this section to learn more about the type safety on the client side](#type-safety-on-the-client-side) | ||
users.push(user) | ||
### FETS Server | ||
return Response.json(user) | ||
} | ||
}) | ||
// Handle both parameters and JSON body | ||
.route({ | ||
method: 'PATCH', | ||
path: '/users/:id', | ||
handler: async request => { | ||
const user = users.find(user => user.id === request.params.id) | ||
```typescript | ||
import { createServer } from 'node:http'; | ||
import { createRouter, FromSchema } from 'fets'; | ||
if (!user) { | ||
return new Response(null, { | ||
status: 404 | ||
}) | ||
const users = [ | ||
{ id: "1", name: 'John Doe' }, | ||
{ id: "2", name: 'Jane Doe' }, | ||
]; | ||
const router = createRouter().route({ | ||
method: 'GET', | ||
path: '/user/:id', | ||
schemas: { | ||
request: { | ||
params: { | ||
type: 'object', | ||
properties: { | ||
id: { type: 'string' } | ||
}, | ||
required: ['id'] | ||
additionalProperties: false | ||
} | ||
}, | ||
response: { | ||
200: { | ||
type: 'object', | ||
properties: { | ||
id: { type: 'string' }, | ||
name: { type: 'string' } | ||
} | ||
} as const, | ||
} | ||
}, | ||
handler: ({ params }) => { | ||
const user = users.find(user => user.id === params.id); | ||
if (!user) { | ||
return new Response(null, { | ||
status: 404 | ||
}); | ||
} | ||
return new Response(JSON.stringify(user)); | ||
} | ||
}); | ||
const body = await request.json() | ||
createServer(router).listen(3000, () => { | ||
console.log(`Swagger UI is available at http://localhost:3000/docs`) | ||
}); | ||
``` | ||
user.name = body.name | ||
[See this section to learn more about the type safety on the server side](#end-to-end-type-safety-and-validation-with-json-schema) | ||
return Response.json(user) | ||
} | ||
}) | ||
``` | ||
## Middlewares | ||
@@ -208,0 +224,0 @@ |
90007
745
+ Added@whatwg-node/fetch@0.8.2-alpha-20230302123848-dce33a7(transitive)
+ Added@whatwg-node/node-fetch@0.3.1-alpha-20230302123848-dce33a7(transitive)
+ Added@whatwg-node/server@0.7.2-alpha-20230302123848-dce33a7(transitive)
- Removed@whatwg-node/fetch@0.8.2-alpha-20230302123305-a76a7ea(transitive)
- Removed@whatwg-node/node-fetch@0.3.1-alpha-20230302123305-a76a7ea(transitive)
- Removed@whatwg-node/server@0.7.2-alpha-20230302123305-a76a7ea(transitive)
Updated@whatwg-node/fetch@0.8.2-alpha-20230302123848-dce33a7
Updated@whatwg-node/server@0.7.2-alpha-20230302123848-dce33a7