3

I have 2 classes that depend on each other. For the sake of example, let's say that the structure is:

class AuthMiddleware {
    public authenticate() {
      // uses PostgraphileRouter here to extract some data before the authentication

      // authenticates ..

      // keeps the userId if authentication succeeded
       this.setSessionData(userId);
    }

    private setSessionData() {..}
    public getSessionData() {..}
}

class PostgraphileRouter {
  // makes a graphql query that uses AuthMiddleware.getSessionData()
}

I don't want to work with co-dependent classes, so I decided to put setSessionData() and getSessionData() in a SessionManager class and inject it to both classes.

The problem is that now I have to make setSessionData() public although I want to keep it available only to AuthMiddleware class.

  1. Is extracting common code to another class is the best practice when dealing with co-dependency?

  2. If it is, can I make some functions (such as setSessionData()) available only to specific classes?

Thanks!

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Guy Shany
  • 83
  • 5
  • I think what you are looking for is called `friend` classes in C++, which does not exist in typescript. See https://stackoverflow.com/questions/45847399/friend-class-in-typescript – Orelsanpls Sep 25 '19 at 07:17

2 Answers2

4

Is extracting common code to another class is the best practice when dealing with co-dependency?

Yes, it is common but can come down to a matter of preference and coding styles.

If it is, can I make some functions (such as setSessionData()) available only to specific classes?

interfaces can help you out here.

Example:

interface SessionDataGetter {
    getSessionData(): any;
}

interface SessionDataSetter {
    setSessionData(data: any): void;
}

class SessionManager implements SessionDataGetter, SessionDataSetter {
    getSessionData() { return null; }

    setSessionData(data: any) { }
}

class AuthMiddleware {
    // has access to both get and set
    constructor(sessionManager: SessionManager) { }
}

class PostgraphileRouter {
    // only has access to the get method
    constructor(sessionGetter: SessionDataGetter) { }
}

const sessionManager = new SessionManager();
const middleware = new AuthMiddleware(sessionManager);
// still same instance of session manager, but won't have access to setter (at least at compile time)
const router = new PostgraphileRouter(sessionManager);
Soc
  • 7,425
  • 4
  • 13
  • 30
0

An alternative to the great answer of @Soc could be to create SessionData as Observable, which can only be subscribed by the reading components.

Paflow
  • 2,030
  • 3
  • 30
  • 50