1

I want to know which file called the class:

database.ts

class Database {
    constructor() {
        console.log(`This class was called by ${super()}`);
    }
}

server.ts

import Database from 'database.ts';
new Database(); // The constructor would print "This class was called by server.ts"

Of course the way I presented by using "super()" doesn't work, but which way does ? I could not find an answer for this question. Is it possible to do such thing ?

Dr4kk0nnys
  • 697
  • 7
  • 13
  • 1
    It's suspicious that you need this kind of information in the first place. What for? Especially Javascript is often packed for deployment, which somewhat removes any information about "files", so… – deceze Feb 08 '21 at 16:16
  • I'm using mongo db, and I'm using a utils folder that holds other files, and within this files I have a database.ts. I'm calling the database class from a lot of different files, some are failing to connect for whatever reason. And I need to know which ones. – Dr4kk0nnys Feb 08 '21 at 16:18
  • A Database class shouldn't connect or not connect based on what "file" it was "called from"… Are these "files" being run in different *processes* or machines, which would make a difference to connecting to a database? Or do those files pass different *parameters* to the class which causes it to connect differently? – deceze Feb 08 '21 at 16:21
  • In the register file it passes some information's to gather the cluster for the register. In the login file it passes the login information to gather inside the collection, the user with such credentials – Dr4kk0nnys Feb 08 '21 at 16:23
  • Are you looking to setup error logging in server side? This approach seems weird though – Suraj Rao Feb 08 '21 at 16:24
  • Not exactly, It would be a way to debug hundreds of files which are failing to connect to the database, and the answer I've left bellow does work to identify such files, but we're talking about almost 300 files calling this class. It would be impractical to do this for every one. In the mongo db information I have close to 200 connections. I suspect it has something to do with the parameters, but with a closer debug, it shouldn't have anything to do with the parameters – Dr4kk0nnys Feb 08 '21 at 16:26

3 Answers3

3

Log the superclass name

You can log the name of the superclass like this:

Object.getPrototypeOf(Object.getPrototypeOf(foo)).constructor.name;

see https://stackoverflow.com/a/44251889/675721

Logging the superclass name will not show you which file called instantiated your class, however.

Log the calling file

To do this you should create an log an error.

class Database {
    constructor() {
        const a = new Error();
        console.log(a);
    }
}

This will give you a stack trace with all of the file names.

Error
    at REPL39:1:23
    at Script.runInThisContext (vm.js:132:18)
    at REPLServer.defaultEval (repl.js:479:29)
    at bound (domain.js:430:14)
    at REPLServer.runBound [as eval] (domain.js:443:12)
    at REPLServer.onLine (repl.js:809:10)
    at REPLServer.emit (events.js:326:22)
    at REPLServer.EventEmitter.emit (domain.js:486:12)
    at REPLServer.Interface._onLine (readline.js:337:10)
    at REPLServer.Interface._line (readline.js:666:8)

Debugger

Neither of these is really the best approach - you should use a debugger to set a breakpoint when the class is instantiated or when the database isn't working and look around to see what is different.

Codebling
  • 10,764
  • 2
  • 38
  • 66
  • 1
    I mean, it's not the prettiest way to solve it, but it sure as fuck solves my problem with the debugging. One thing I'm going to change is try to create a custom error to see if I can have even more details of the files. – Dr4kk0nnys Feb 08 '21 at 16:35
  • 1
    If you really want to dig into this, there are libraries that will make the stacktrace analysis easier, like https://www.stacktracejs.com/. I think debugging is the best way to get to the crux of your issue, however. From experience, I know that mucking around debugging Database connections is really not fun. Good luck! – Codebling Feb 08 '21 at 16:38
2

It isn't strictly a typescript question. There is no simple way to do this but you can hack around with the stack trace I believe. On that way you can find out where your class has been instantiated even if your application is packaged and the file name information is lost. The stack trace can be obtained by processing the callee property of the constructor's arguments. E.g. see this question for a possible solution. I.e.

function stacktrace() { 
  function st2(f) {
    return !f ? [] : 
        st2(f.caller).concat([f.toString().split('(')[0].substring(9) + '(' + f.arguments.join(',') + ')']);
  }
  return st2(arguments.callee.caller);
}

But you can make your own version of this function what returns the stack as an array. I assume from the comments on the question you would like to store the caller in the class and log it in case of error so storing the trace as an object might suit your needs better.

Then just call this function from the Database class constructor.

Zoltan Magyar
  • 874
  • 1
  • 6
  • 19
  • It does make a lot of sense, but in my usage I would only use to make a debugging section, as it would not be on the final working version of the project. Is there an easier way ? I mean, I won't have a packaged application just yet – Dr4kk0nnys Feb 08 '21 at 16:31
  • I assume you are using node. There you can get the current file name as ```require('path').basename(__filename);``` but it will return the current file name only. You can pass that in to your constructor when your Database class is instantiated. However it would be an overkill for debugging purpose IMO. – Zoltan Magyar Feb 08 '21 at 16:35
  • Actually you are on an interesting train of thought -- looking at the `module.parent` will tell you which file `require()`'d it, but only the first time it gets required, so not that useful (also this property is deprecated) – Codebling Feb 08 '21 at 16:40
0

Of course I could add a parameter to the constructor. But is there another way ?

class Database() {
    constructor(fileLocation: string) {
        console.log(`This file was called by ${fileLocation}`);
    }
}
Dr4kk0nnys
  • 697
  • 7
  • 13