Utilizing a LoopBack4 Interceptor to access repositories within the application

I am looking to improve the functionality of an Interceptor within my LoopBack4 application. Currently, the Interceptor simply displays the start and end of a controller method call on the command line, as outlined in this documentation.

Here is how my Log-Interceptor currently looks:

export const Log: Interceptor = async (invocationCtx, next) => {
    // Wait until the interceptor/method chain returns
    const req = await invocationCtx.get(RestBindings.Http.REQUEST);

    try
    {
        const stackinfo = 'Class: ' + invocationCtx.targetClass.name + ' | Method: ' + invocationCtx.methodName + " | Request IPs: " + req.ips.concat(', ');

        logger.trace('Starting - ' + stackinfo);

        const result = await next();
        const res = await invocationCtx.get(RestBindings.Http.RESPONSE);

        logger.trace('Ending - ' + stackinfo + ' | Response Status Code: ' + res.statusCode);

        return result;
    }
    catch (e)
    {
        logger.error(e);
        throw e;
    }
};

Now I would like to enhance this Interceptor to also log additional statistics data into my MySQL-Datasource. My challenge lies in figuring out how to access the repository within the interceptor. Should I inject the Repository, and if so, what is the correct way to do that? Alternatively, are there better methods to achieve this goal?

Answer №1

If you want to access repositories within your interceptors, you can do so by using `invocationCtx.target` as shown below:

const exampleInterceptor: Interceptor = async (invocationCtx, next) => {
  const exampleRepo = invocationCtx.target.exampleRepository;
  const anotherExampleRepo = invocationCtx.target.anotherExampleRepository;
};

This method assumes that you have added corresponding @repository decorators in the controller where the interceptor is being used. This approach works for both class-level and method-level interceptors.

@intercept(exampleInterceptor)
export class ExampleController {
  constructor(
    @repository(ExampleRepository)
    public exampleRepository: ExampleRepository,
    @repository(AnotherExampleRepository)
    public anotherExampleRepository: AnotherExampleRepository
  ) {}
}

If you have any other suggestions or recommendations on how to achieve this, please feel free to share them!

Answer №2

After some exploration, I managed to come up with a workaround:

  1. Establish a new service:
export class StatisticService
{
    constructor(
        @repository(StatisticRecordRepository) public statisticsRepository: StatisticRecordRepository
    ) {}


    async increment(key: string, addend = 1): Promise<void>
    {
        const existing = await this.statisticsRepository.findOne({where: {StatsKey: key}});
        if(existing !== null)
        {
            // @ts-ignore
            existing.Counter = existing.Counter + addend;
            existing.UpdateTs = (new Date()).toISOString();
            await this.statisticsRepository.update(existing);
        }
        else
        {
            await this.statisticsRepository.create(new StatisticRecord({
                                                                           StatsKey: key,
                                                                           Counter:  addend
                                                                       }));
        }
    }
}


export const StatisticsServiceBindings = {
    VALUE: BindingKey.create<StatisticService>("services.StatisticsService")
};
  1. Register the service in the Application constructor:
this.bind(StatisticsServiceBindings.VALUE).toClass(StatisticService);
  1. Retrieve and implement the Service in the Log-Interceptor:
const stats = await invocationCtx.get(StatisticsServiceBindings.VALUE);
stats.increment(invocationCtx.targetClass.name + '::' + invocationCtx.methodName + ' [' + res.statusCode + ']');

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Error occurs when attempting to write to a Node stream after it has already

I'm experimenting with streaming to upload and download files. Here is a simple file download route that unzips my compressed file and sends it via stream: app.get('/file', (req, res) => { fs.createReadStream('./upload/compres ...

Is it possible to retrieve a union type property as an array of values in order to conduct a flexible type validation process?

Currently, my code looks something like this: interface Apple { type: 'Apple' } interface Banana { type: 'Banana' } interface Coconut { type: 'Coconut' } type Fruit = Apple | Banana | Coconut type AppleOrBanana = App ...

Retrieve properly formatted text from the editor.document using the VSCode API

I have been working on creating a personalized VSCode extension that can export the current selected file contents as a PDF. Although PrintCode exists, it does not fit my specific needs. The snippet of code I am currently using is: const editor = vscode.w ...

The speed of the OpenLayers web application is significantly hindered when accessed from a mobile device using Android

Although it may seem like a common question that should be closed, I have reached a roadblock and cannot find a solution. I hope to provide enough details to make this question suitable for SO. I am currently working on an OpenLayers web application that ...

Determine the size of the resulting zip file with NodeJs

I am currently utilizing NodeJs (expressJs) along with the archiver module to stream a zip file directly to the client without storing the final ZIP file on the server (streaming zip serving). However, one issue I am facing is that I am unable to retrieve ...

Explain the object type that is returned when a function accepts either an array of object keys or an object filled with string values

I've written a function called getParameters that can take either an array of parameter names or an object as input. The purpose of this function is to fetch parameter values based on the provided parameter names and return them in a key-value object ...

Executing several asynchronous functions in Angular 2

I am currently developing a mobile app and focusing on authentication. In order to display data to the user on my home page, I need to connect to various endpoints on an API that I have created. Although all endpoints return the correct data when tested i ...

"Can you explain the functioning of this Node.js middleware when it doesn't require any

Currently, I am utilizing a function created by another individual for express and passport, which defines the middleware in the following manner: function isLoggedIn(req, res, next) { if (req.isAuthenticated()){ return next(); } els ...

The use of `super` in Typescript is not returning the expected value

Trying to retrieve the name from the extended class is causing an error: Property 'name' does not exist on type 'Employee'. class Person { #name:string; getName(){ return this.#name; } constructor(name:string){ ...

You cannot add properties to an object within an async function

I am attempting to include a fileUrl property in the order object within an async function, but I am unable to make it work properly. My expectation is for the order object to contain a fileUrl property once added, but unfortunately, it does not seem to b ...

Executing a node.js script with a click of a button

Hello, I have recently started learning about node.js. I am currently working on connecting with an API using express/node.js along with EJS templating. My goal is to send some information from the browser to the API. Right now, I can successfully push d ...

Error in Node.js: the function "myFunction" is not defined

Utilizing the fcm-node package to facilitate sending notifications from the Express API route to the app via a registration token. The function being used is as follows: const FCM = require('fcm-node'); const serverKey = ... const fcm = new FCM( ...

Guide to effectively running unit tests on an Express 4 server using Jest

Seeking to gain a deeper understanding, I am experimenting with this straightforward setup code for an Express server (version 4): server.js import express from 'express'; import router from './routes'; const app = express ...

Unable to modify the value of an object variable generated from a query in JavaScript, ExpressJS, and MongoDB

Here is the code snippet I've been working on: let addSubmissions = await Submission.find({"type": "add-information"}, (err) => { if(err) { console.log(err) req.flash('error', 'No "add submissions" were found&apo ...

What is the process for changing the name of an element in Angular 2?

I'm feeling a bit lost here ... I need to implement the feature that allows users to edit the name of an element by simply clicking on a button. These elements are all stored in the Storage system. How can I achieve this in my current setup? File: ho ...

Encountering issues with SSL websocket connection after updating node to version 20.10 (previously on 14.7) and socket.io to version 4.7.2 (previously on 1.4.36)

I've hit a wall and could really use some fresh perspectives... My task involves managing code that sets up a secure websocket using Express. The original socket.io libraries were v1, which I have upgraded to v4 along with Node 20.10 (previously 14.7 ...

AngularYelp: Node Integration for Enhanced Functionality

Embarking on a new learning journey here, so please bear with me... Discovered node-yelp while browsing Yelp's API docs. Check it out here. // Request API access: http://www.yelp.com/developers/getting_started/api_access var Yelp = require('yel ...

Encountering error when using require() with Firebase in Express

I am facing an issue with my Express application while attempting to connect it to Firebase. Currently, my console is showing an error message: C:\Users\Tyler\Desktop\Dev\food-bank\app.cjs:19 const firebase = initializeApp(fi ...

Signature in TypeScript for a function that augments the number of elements in a tuple

Can a type-aware declaration be written in Typescript for a function that takes a tuple and returns a new one with an appended item, without using function overload? In short, I need a function that performs the following: [T1, T2, ... Tn] + U => [T1 ...

Creating and sharing a project in Typescript

My typescript project tends to have its code scattered across multiple files during development. Is there a recommended method for packaging this project into a single js and d.ts file for distribution? ...