# Xpresser Params Loader

GIT (opens new window) | NPM (opens new window) | DEMO

This plugin provides a middleware generator for requiring/loading url params

# Already installed? Jump to Usage

# About

Most urls in every large application includes parameters (params for short). For example:

# Example Urls
/user/:username
/post/:postId

:username and :postId are params.

Loading these params and finding what they represent can be done in controllers. For example:

// A controller action
function indexPage(http) {
  const {username} = http.params;
  if (!username) return http.status(404).send(`Username is required!`);
  // use param
}

The above method becomes lengthy and redundant overtime as we need to repeat the same code for every single controller action.

With the params-loader plugin we can generate a middleware that will load params and save the loaded params to http.state

# Middleware Process

  • Check if param is defined or return notFound
  • if load function is defined:
    • Call it, if it throws an error, return loadError else hold result.
    • Check if load result value is undefined and return notFound
    • Save load result to http.state
  • Save param original value to http.state.

# Installation

npm install @xpresser/params-loader
# Or
yarn add @xpresser/params-loader

# Plugins.json

Add npm://@xpresser/params to your plugins.json, if you don't have one then create a new one in your backend folder.

{
   "npm://@xpresser/params-loader": true 
}

# Add Types

Add this to your xpresser.d.ts file.

import "@xpresser/params-loader/CustomRequestEngine";

# Define Params

Using the example urls defined above.
Assuming we have a file in our middleware directory ParamsMiddleware.(js|ts)

The example above shows how to register the username and postId params.

username is renamed to user and postId is renamed to post.

Below is a table that shows the options of each param and their descriptions.

# Param Options

Option Required Description
notFound NO if param is not found in http.params OR Param exists but has a falsy value before or after load, this function will be called.
as NO Custom name of the param to be saved to http.state
addToBoot NO Add param to the boot state using http.addToBoot()
load NO Function to load the param.
loadError NO Function to handle error if load expects an error to be thrown.

# Type Definition

import {Http} from "xpresser/types/http";

type Options = {
    notFound?: (http: Http, value: any) => any;
    as?: string;
    addToBoot?: boolean;
    load?: (value: any, http: Http) => any;
    loadError?: (http: Http, error: Error) => any;
};

# Register Middleware

Just like every other middleware, you can register it while routing using router.path() routes or in controller middleware.

# Via Route Path

router.path('/user/:username', () => {
    router.get("=index")
    router.post("=update")
}).middleware("Params.username")

The Param.username middleware will be applied to all routes with prefix /user/:username.

# Via Controller

const AppController = {
    middlewares: {
        "Params.username": ["getUser"],
        "Params.postId": ["getPost"]
    }
}

The above simply means that

  • Params.username middleware will be applied to all actions in its array value e.g getUser.
  • Params.postId middleware will be applied to all actions in its array value e.g getPost.

# Accessing Loaded Params

This plugin also extends xpresser's RequestEngine to add a few helper methods to the current request instance.

# loadedParam()

Get a loaded parameter.

# loadedParams()

Get all the loaded params or pick specified param if pick exists as 1st argument.

# hasLoadedParam()

Check if a request has a param loaded.

// let assume `postId` is an optional param and may not be loaded.
function getPost(http){
    if(!http.hasLoadedParam()){
        return // all posts
    }
    
    // else return post
    return http.loadedParam('post');
}

# addLoadedParam()

Add a param to the loaded params. This may be useful if you are loading some parameters manually and want to add them to the loaded params.

// Assming we have a custom middleware loading some parameters
async function fileId(http) {
  const {fileId} = http.params
  
  // do some checks and loading if needed for example
  const file = await File.findOne({id: fileId})
  
  // add to loaded Params
  http.addLoadedParam("file", fileId) 
  
  return http.next();
} 

# Demo