zowwu

The easiest way to create a RESTful endpoints.

Usage no npm install needed!

<script type="module">
  import zowwu from 'https://cdn.skypack.dev/zowwu';
</script>

README

Logo

it's never been easier to create a REST api

folder and filename based routing service

Report Bug Β· Request Feature Β· Donate


Node.js CI LICENCE

Table of Contents
  1. About The Project
  2. Getting Started
  3. Roadmap
  4. Contributing
  5. License
  6. Contact
  7. Acknowledgements

About The Project

Just don't waste any time. If you're building a project, you probably have a clean folder structure anyway. Zowwu uses the folder structure and automatically creates your API endpoints based on polka from it.

The project is still in progress. Support is greatly appreciated.

Logo

Installation

  1. Install Package
    npm install zowwu
    
    or
    yarn add zowwu
    

Usage

Server

   ./index.js
const loader = require("zowwu");

loader().then((app) => {
  app.listen(3000, (err) => {
    if (err) throw err;
    console.log(`> Running on localhost:3000`);
  });
});

Create your folders or files

   ./api/comments/index.js  -> http://localhost:3000/comments
   ./api/comments/deeper/index.js  -> http://localhost:3000/comments/deeper
   ./api/articles/index.js  -> http://localhost:3000/comments
   ./api/...

or

   ./api/comments.js  -> http://localhost:3000/comments
   ./api/articles.js  -> http://localhost:3000/articles
   ./api/...
module.exports = {
  routes: [
    {
      action: async (req, res, next) => {
        res.json({ status: "Hello world" });
      },
    },
  ],
};

πŸͺ„ Now your routes are automatically created based on the file names and/or folder structure

Route Options

module.exports = {
  routes: [
    {
      // path: path of the route
      // - type: String
      // - default: '/'
      path: '/',
      // method: method
      // - type: String
      // - default: 'GET'
      // - available: 'GET', 'HEAD', 'PATCH', 'OPTIONS', 'CONNECT', 'DELETE', 'TRACE', 'POST', 'PUT'
      method: 'GET',
      // Before Handler
      // - type: Function | Array
      before: async (req, res, next) => ...,
      // Main Handler
      // - type: String
      action: async (req, res, next) => ...
    },
  ],
};

The supported route pattern types are:

  • static (/messages)
  • named parameters (/messages/:id)
  • optional parameters (/messages/:id?)
  • suffixed parameters (/movies/:title.mp4, movies/:title.(mp4|mov))
  • any match / wildcards (/messages/*)

Not supported pattern types are (if folder-specific is to be created):

  • deep nested parameters (/messages/:id/books/:title)
  • deep optional parameters (/messages/:id?/books/:title?)

However, within the route option (module.exports.routes) these route methods are possible. πŸ“„ For more information - polka based on trouter.

Now you can query

 curl http://localhost:3000/articles
 curl http://localhost:3000/comments
 ...

πŸ‘©β€πŸ”§ Available options:

const loader = require("zowwu");

loader({
  // entry: the folder where routes are scanned for
  // - type: String
  // - default: 'api'
  entry: 'api',
   // debug: it shows you the generated routes on load
  // - type: Boolean
   // - default: false
  debug: true,
  // pluginPath: the folder where plugins are scanned for
  // - type: String
  // - default 'plugins'
  pluginPath: 'plugins',
  // register: Initialize external modules. Similar to app.use(module)
  // - type: Array
  // - default: []
  register: []
}).then(app => // return the polkajs instance

Middlewares (Endpoint specific)

function one(req, res, next) {
  console.log("world...");
  next();
}

function two(req, res, next) {
  console.log("...needs better demo πŸ˜”");
  next();
}

module.exports = {
  before: [one, two],
  routes: [
    {
      action: async (req, res, next) => {
        // Get Posts
        res.json([{ title: "Post..." }]);
      },
    },
    {
      path: "/:id",
      action: async (req, res, next) => {
        // Get Posts
        res.json([{ title: `Hello ${req.params}` }]);
      },
    },
    {
      method: "POST",
      path: "/",
      action: async (req, res, next) => {
        // Create Post
        res.end("Create Post...");
      },
    },
  ],
};

Middlewares (Route specific)

function one(req, res, next) {
  console.log("world...");
  next();
}

function two(req, res, next) {
  console.log("...needs better demo πŸ˜”");
  next();
}

module.exports = {
  routes: [
    {
      before: [one, two],
      action: async (req, res, next) => {
        // Get Posts
        res.json([{ title: "Post..." }]);
      },
    },
    {
      method: "POST",
      path: "/",
      before: two,
      action: async (req, res, next) => {
        // Create Post
        res.end("Create Post...");
      },
    },
  ],
};

Plugins

Plugins work like normal routes. For example, you can provide the authentication function as a plugin or other functions.

Create your folders or files

   ./plugins/myplugin.js
   or
   ./plugins/myplugin/index.js
   ./plugins/...

Note: With the plug-ins, you cannot go deeper into the folder structure.

// ./plugins/myplugin.js  or  ./plugins/myplugin/index.js
module.exports = {
  routes: [
    {
      action: async (req, res, next) => {
        res.json({ status: "Hello plugin" });
      },
    },
  ],
};
// ./api/myroute.js
module.exports = {
  routes: [
    {
      plugin: "myplugin",
    },
    {
      path: "/:id",
      action: async (req, res, next) => {
        res.json({ status: req.params.id });
      },
    },
  ],
};

🀟 You can still add your middlewares here or overwrite the plugins:

// ./api/myroute.js
module.exports = {
  routes: [
    {
      plugin: "myplugin",
      before: async (req, res, next) => {
        console.log("before.. but after plugin function");
        next();
      },
      action: async (req, res, next) => {
        res.json({ status: "overwrite plugin" });
      },
    },
    {
      path: "/:id",
      action: async (req, res, next) => {
        res.json({ status: req.params.id });
      },
    },
  ],
};

Modules

Modules can be initialized using the register array.

const loader = require("zowwu");
const { json } = require("body-parser");

loader({ register: [json()] }).then((app) => {
  app.listen(3000, (err) => {
    if (err) throw err;
    console.log(`> Running on localhost:3000`);
  });
});

Roadmap

See the open issues for a list of proposed features (and known issues).

Contributing

Contributions are what make the open source community such an amazing place to be learn, inspire, and create. Any contributions you make are greatly appreciated.

  1. Fork the Project
  2. Create your Feature Branch (git checkout -b feature/AmazingFeature)
  3. Commit your Changes (git commit -m 'Add some AmazingFeature')
  4. Push to the Branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

License

Distributed under the MIT License. See LICENSE for more information.

Contact

Tayfun GΓΌlcan - Twitter LinkedIn

Acknowledgements