npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

vort

v0.2.2

Published

Flexible backend framework

Downloads

6

Readme

Vort backend framework

Flexible full type-safe backend framework based on express

TODO

  • [ ] tests
  • [ ] add example requests and responses
  • [x] response body zod checking
  • [x] OpenAPI params (query, path, body)

Get started

yarn add vort

Config

export const config = {
  routes: path.join(__dirname, './routes'), // routes folder
  swaggerRoute: '/swagger', // route to render swagger
}

App

import { Vort } from 'vort'
import config from './vort.config'

const app = new Vort(config)
app
  .title('Best app') // title for openapi
  .description('App for testing') // description for openapi
  .version('1.0.0') // version for openapi
  .listen(3000, () => {
    console.log('listen')
  })

Routes

Vort has file base system routing

Folder structure

routes
  - hello/
    - world.get.ts
  - here
    - another
      - get.ts
      - post.ts
    - all-methods
      - all.ts
    - all-methods
      - with-name.all.ts
  - user/
    - [user]/
      - create.post.ts

with such folder structure, will generate express routings:

GET     /hello/world
GET     /here/another
POST    /here/another

GET     /here/all-methods
POST    /here/all-methods
PUT     /here/all-methods
PATCH   /here/all-methods
DELETE  /here/all-methods
HEAD    /here/all-methods
OPTIONS /here/all-methods

GET     /here/all-methods/with-name
POST    /here/all-methods/with-name
PUT     /here/all-methods/with-name
PATCH   /here/all-methods/with-name
DELETE  /here/all-methods/with-name
HEAD    /here/all-methods/with-name
OPTIONS /here/all-methods/with-name

POST    /user/:user/create

You can add - before any file name to exclude all handlers below

routes
  - hello/
    - world.get.ts
  - here
    - -another
      - get.ts
      - post.ts
    - -all-methods
      - all.ts
    - all-methods
      - with-name.all.ts
  - user/
    - [user]/
      - create.post.ts
GET     /hello/world
POST    /user/:user/create

Typings

To use define handler use handler function

import { defineHandler, HTTPError } from 'vort'
import { z } from 'zod'

export default defineHandler()
  .description('Best handler ever') // description of handler (for openapi generator)
  .query(z.object({ name: z.string() })) // type safe query parameters
  .params(z.object({ user: z.string() })) // type safe path parameters
  .body(z.object({ hello: z.string() })) // type safe body parameters
  .output(z.string())
  .handler(async (req, res) => {
    const { name } = req.query
    //      ^ string
    const { user } = req.params
    //      ^ string
    const { hello } = req.body
    //      ^ string

    if (isError) throw new HTTPError('FORBIDDEN', 'Only admin function')
    res.send('Hello') // type checking

    res.send(3) // Error (not a string)
  })

Middlewares

To define middleware use defineMiddleware function

import { defineMiddleware } from 'vort'
import { z } from 'zod'

const isAdmin = defineMiddleware()
  .locals(
    z.object({
      isAdmin: z.boolean(),
    })
  )
  .middleware((req, res, next) => {
    const { userId } = req.query
    res.locals.isAdmin = userId === '1'
    //          ^ boolean
    next()
  })

Now isAdmin can be used in handler definition

import { defineHandler, HTTPError } from 'vort'
import { z } from 'zod'

import { isAdmin } from '@/middlewares'

export default defineHandler()
  .use(isAdmin)
  .query(z.object({ userId: z.string }))
  .handler((req, res) => {
    if (!res.locals.isAdmin) {
      //              ^ boolean
      throw new HTTPError('FORBIDDEN', 'User is not admin')
    }
  })

Modifiers

Modifier is function which can execute asyncronise way handler function to achive whole control on result, and helps to proceed errors heppens inside handler function

import { defineHandler, HTTPError } from 'vort'
import { z } from 'zod'

export default defineHandler()
  .query(z.object({ page: z.number() }))
  .output(z.array(z.string()))
  .modifier(async (_req, res, handler) => {
    try {
      await handler()
    } catch (e) {
      console.error(e)
      res.send([])
    }
  })
  .handler(async (req, res) => {
    if (req.query.page > 100) throw new HTTPError('BAD_REQUEST')
    return ['some']
  })

Swagger doc support

Add Swagger doc host on /swagger generated by zod schemas (Based on OpenAPI 3.0.0)