1.0.0 โ€ข Published 3 years ago

vercel-serverless-routes v1.0.0

Weekly downloads
-
License
MIT
Repository
github
Last release
3 years ago

Vercel Serverless Routes :traffic_light:

Code Quality Status

Build Status Coverage Status

vercel-serverless-routes Banner

Description :clipboard:

A helper to build Vercel routes vercel.json from another folder and files, and other nomenclature.

Also it provides some custom functions to use as defaults in some projects, such as:

  • When the endpoint is wrong and the API doesn't exists, and throw a custom message. See Cannot Found API
  • When the project is only APIs, and no fronted, and API that render a nice index page if the user only access to the base URL. See Index API

This two "APIs" I use as defaults in my Vercel projects, so i decided to make a generic ones and do not repeated it everywhere, you can use it.

Why? :grey_question:

When multiples endpoints/API are being added to vercel.json file, it makes too long to be read and it is not easy to find the right one or organize, or add a new one. So I need to split it in several files to group them by some relationship.

Also, if the endpoint needs to have a path param for routing REGEX must be used, and pass it through query params to the handler. BORING!.

So i decided to generate this package to split the routes into multiple .js or .json files, and having and alternative to define the APIs endpoints and handlers, to make easier use path params.

Synergy :zap:

This package is created to use it with the following packages:

Building routes :hammer:

You must run in your terminal, in the root folder of your project:

npx vercel-serverless-routes

This will create a vercel.json file with the routes.

Recommendation :bulb:

For building routes it must executes before deploying to Vercel, in most cases before pushing the branch into repository, and in local env before running the CLI.

So, you can add to your package.json:

"scripts": {
    ...,
    "build-routes": "npx vercel-serverless-routes",
    "dev": "npm run build-routes; vercel dev",
  }

Defining an endpoint ๐Ÿ”—

Every endpoint for every route will be added to the base URL of your vercel project:

  • https://your-project-name.vercel.app/ENDPOINT

Vercel Native ๐Ÿ”บ

If you use the vercel nomenclature, it will be valid and any changes will be reflected in the vercel.json file.

{
    "src": "/example/native", // The API ENDPOINT
    "methods": ["GET", "POST"], // The methods allowed
    "dest": "/api/example" // The relative path to the function handler
}

There a lot more options. See Vercel docs.

It makes you create this URL

  • GET/ https://your-project-name.vercel.app/example/native
  • POST/ https://your-project-name.vercel.app/example/native

And uses a function handler in: ./root/api/example

REMEMBER: The handlers are recommended to be in ./root/api/* folder.

New Alternative ๐Ÿ†•

But you can use my alternative:

  • path: The endpoint path. STRING. REQUIRED
    • Must start with '/'.
    • Path Params can be defined with '{SOME_NAME}'.
    • A prefix will be added: /api/.
  • method: The HTTP Method. STRING. OPTIONAL FOR GET
    • If nothing is passed, be default it will be a GET request.
    • Despite Vercel can handle multiple ones, with this form it define individually, this is to have individual functions for each API.
  • controller: A custom path to the API function handler. STRING. OPTIONAL
    • Must NOT start with '/'.
    • A prefix will be added: /api/.

Using this fields it will generate a path to the function handler into ./root/api/ folder.

Example 1

[
    {
        "path": "/example/{id}",
        "methods": "POST"
    }
]

It makes you create this URL:

  • POST/ https://your-project-name.vercel.app/api/example/1
  • POST/ https://your-project-name.vercel.app/api/example/617d89e0eb5815550438e57c
  • ETC..

And uses a function handler in: ./root/api/example/get?pathIds.id=$id

Example 2

[
    {
        "path": "/example"
    }
]

It makes you create this URL:

  • GET/ https://your-project-name.vercel.app/api/example

And uses a function handler in: ./root/api/example/list

Example 3

[
    {
        "path": "/example/{id}/custom/{customId}"
    }
]

It makes you create this URL:

  • GET/ https://your-project-name.vercel.app/api/example/1/custom/2
  • ETC...

And uses a function handler in: ./root/api/example/get?pathIds.id=$id&pathIds.customId=$customId

Example 4

[
    {
        "path": "/example/custom/{customId}",
        "method": "delete",
        "controller": "example-delete"
    }
]

It makes you create this URL:

  • GET/ https://your-project-name.vercel.app/api/example/custom/2
  • ETC...

And uses a function handler in: ./root/api/example-delete?pathIds.customId=$customId

Customize

  • --endpointPrefix: to change the prefix in endpoint.
    • Default is api.
  • --baseSrc: to change the base path of the function handler.
    • Default is api.
    • NOT RECOMMENDED TO CHANGE.
  • --pathParamId: to change the path parameters identifier.
    • Default is {\w+}.
    • It will be use with Regex. Be careful.

Example

npx vercel-serverless-routes --baseSrc src --endpointPrefix my-api --pathParamId :id
[
    {
        "path": "/example/:id/custom/:customId"
    }
]

It makes you create this URL:

  • GET/ https://your-project-name.vercel.app/my-api/example/1/custom/2
  • ETC...

And uses a function handler in: ./root/src/example/get?pathIds.id=$id&pathIds.customId=$customId

Routes files ๐Ÿ“

The new files must be in ./root/routes/index.js, it must export an array of objects.

// in ./root/routes/index.js
'use strict';

const exampleFunctions = require('./example.json');
const customFunctions = require('./custom.js');

module.exports = [
    ...exampleFunctions,
    ...customFunctions
];

Customize

  • --routesPath: to change the folder of the routes file.
    • Default is routes.

Example

npx vercel-serverless-routes --routesPath endpoints

The files must be in ./root/endpoints/index.js

Extra API โญ

To use it must install the package in your project:

npm install vercel-serverless-routes

Not Use It

Both API can be deactivated using

npx vercel-serverless-routes --useNotFound false --useIndex false

Change file

Also your files can be relocated.

npx vercel-serverless-routes --index extra/index --notFound extra/not-found

By default it are located in ./root/api/index.js and ./root/api/not-found.js

Not Found Api

It is an API that matches any endpoint that is not found (/.*) and returns

  • statusCode: 404
  • body: { message: 'Cannot find API', error: { url, method } }

Example 1

const { handler } = require('vercel-serverless-api');
const { CannotFoundAPI } = require('vercel-serverless-routes');

module.exports = (...args) => handler(CannotFoundAPI, ...args);

Example 2

const { handler } = require('vercel-serverless-api');
const { CannotFoundAPI } = require('vercel-serverless-routes');

class CustomNotFound extends CannotFoundAPI {

    getStatusCode() {
		return 402;
	}

    formatError() {
		return {
			suggestion: 'Check the documentation'
		};
	}
}

module.exports = (...args) => handler(CustomNotFound, ...args);

Index Api

The API have an Template already set up, and have default values, you can see the results examples here.

But you can change the default values. See Example 2.

Example 1

const { handler } = require('vercel-serverless-api');
const { IndexAPI } = require('vercel-serverless-routes');

module.exports = (...args) => handler(IndexAPI, ...args);

Example 2

const { handler } = require('vercel-serverless-api');
const { IndexAPI } = require('vercel-serverless-routes');

class CustomIndex extends IndexAPI {

    static get githubUser() {
		return {
            projectName: 'vercel-test',
            user: 'gastonpereyra',
            owner: 'Gastรณn Pereyra'
        };
	}

	static get colors() {
		return {
            brand: '303031',
            hover: '303031',
            background: '303031',
            disclaimer: '303031',
            footerLine: '303031'
        };
	}

	static get messages() {
        return {
            banner: 'https://image.png',
            location: 'Buenos Aires',
            finalMessage: 'Test it!'
        }
    }
}

module.exports = (...args) => handler(CustomIndex, ...args);

Bug :bug:

Report Here

Idea :bulb:

Tell me