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

@beardedtim/cruddy

v0.0.5

Published

A CRUD server builder

Downloads

1

Readme

Cruddy

Overview

cruddy is a tool to help build CRUD interfaces with JSON Schema validation.

Usage

You can find a working demo at demo.js but you will have to ensure that your DB is working or use the docker-compose file in this repo. How to do that is beyond this package's forte.

const { createServer } = require('@beardedtim/cruddy')

const server = createServer({
  /**
   * A configuration object that describes the types of our data
   */
  config: {
    // How this service will log and explain itself
    serviceName: 'CRUDDY_EXAMPLE',
    apiPrefix: '/api',
    // Where are we serving static content from?
    staticDir: 'public',
    // Path to the directory that holds all templates
    templateDir: './views',
    // What type of templating engine are you using?
    templateType: 'pug',
    domains: {
      // The name to add to the api
      users: {
        schemas: {
          // We can format the input and output of our requests
          // using the formatters block inside of schemas of the
          // domain
          formatters: {
            /**
             * This is the same keys as the schemas of create, readOne, readMany, update, destroy
             * and each key has an input and output function
             */
            create: {
              // This is given the Request object
              input: async req => {
                const { password, ...user } = req
                const hashed = await hashPassword(password)

                return {
                  ...user,
                  password: hashed
                }
              }
            },
            readMany: {
              output: users => ...
            },
            update: {
              // This is given whatever the DB call would return
              // since it's an update, it will be a single user
              output: user => ({
                ...user,
                some_formatted_key: true
              })
            }
          }
          // Create Read Update Destroy schemas.
          // All schemas default to accepting _anything_
          create: {
            /**
             * Some JSON Schema describing the body expected
             * for create
             */
          },
          readMany: {
            /**
             * Some JSON Schema describing the query expected
             * for readMany
             */
          },
          readOne: {
            /**
             * Some JSON Schema describing the query expected
             * for readOne
             */
          },
          update: {
            /**
             * Some JSON Schema describing the body expected
             * for update
             */
          },
          destroy: {
            /**
             * Some JSON Schema describing the query expected
             * for delete
             */
          },
          /**
           * Sometimes we only want to return certain keys from this
           * item. This allows us to set that. It can be a single key
           * or an array of keys. '*' means all keys
           *
           * We don't want to return the email _EVER_ from the API
           * so we create a list of keys that we want to return
           */
          keys: ['id', 'email', 'created_at', 'last_updated']
        },

        views: {
          // Create Read Update Destroy views.
          create: {
            /**
             * Some View Schema describing the body expected
             * for create
             */
          },
          readOne: {
            /**
             * Some View Schema describing the query expected
             * for reading one item
             */
          },
          readMany: {
            /**
             * Some View Schema describing the query expected
             * for reading many items
             */
          },
          update: {
            /**
             * Some View Schema describing the body expected
             * for update
             */
          },
          destroy: {
            /**
             * Some View Schema describing the query expected
             * for delete
             */
          }
        }
      }
    }
  },
  /**
   * The pages that we want to serve that aren't based
   * on CRUD
   */
  pages: {
    template: 'some-template',
    path: '/',
    data: context => Promise.resolve({})
  },
  /**
   * The configuration object for the DB. Currently gets passed
   * as-is to Knex
   */
  db: {
    client: 'postgres',
    // You can also use a string here if you have the URL
    // postgres://hello.com:2345/something
    connection: {
      host: 'abc.com',
      port: 5432,
      user: 'username',
      password: '123!',
      database: 'enough'
    }
  },
  /**
   * Any middleware that we want to be ran before any of the handlers
   * but after the global middleware such as CORS/Helmet/etc
   */
  preware: [],
  /**
   * Any middleware that we want to be ran after all the other handlers
   */
  postware: [],
  /**
   * How you want to format any errors before sending them to the client
   */
  onError: () => {},
  /**
   * How you want to format any data before sending it to the client
   */
  onSuccess: () => {}
})

server.listen(5000, () => server.log.info('Service has started'))

Exposed Routes

Given a domain object of

const domain = {
  users: {
    schemas: {},
    views: {}
  },
  posts: {
    schemas: {},
    views: {}
  }
}

this tooling will create the following routes:

# View Specific
GET /users
GET /users/create
GET /users/:id
GET /users/:id/edit
GET /users/:id/destroy

GET /posts
GET /posts/create
GET /posts/:id
GET /posts/:id/edit
GET /posts/:id/destroy


# API Specific
GET /api/users
POST /api/users
GET /api/users/:id
PATCH /api/users/:id
DELETE /api/users/:id

GET /api/posts
POST /api/posts
GET /api/posts/:id
PATCH /api/posts/:id
DELETE /api/posts/:id

It will ensure that the body (for patch or post requests) or query (for all other requests) of the requests passes the schema for the API endpoints called out by the schemas key. It will also call the templates called out by views key.

It will return the keys per the configuration in the schema OR allow you to select keys via the query args. However, you can choose not to allow the keys query arg via the JSON Schema