Skip to main content
Loading...

More TypeScript Posts

const getFollowers = async (req: Request, res: Response) => {
  try {
    const username = req.params.username || '';

    const user = await User.findUnique({
      where: { username },
      include: { followedBy: true },
    });

    if (!user) {
      res.status(404).json({
        error: 'User could not be found',
      });
      return;
    }

    const followers = user.followedBy.map(followedBy => {
      return {
        followerId: followedBy.followerId,
      };
    });

    const followersCount = followers.length;

    res.json({ followersCount: followersCount, followers });
  } catch (error) {
    console.error('getFollowers() error: ', error);
    res.status(500).json({
      error: `There was an error fetching followers for user with username "${req.params.username}", please try again later`,
    });
  }
};

const getFollowing = async (req: Request, res: Response) => {
  try {
    const username = req.params.username || '';

    const user = await User.findUnique({
      where: { username },
      include: { following: true },
    });

    if (!user) {
      res.status(404).json({
        error: 'User could not be found',
      });
      return;
    }

    const following = user.following.map(following => {
      return {
        followingId: following.followingId,
      };
    });

    const followingCount = following.length;

    res.json({ followingCount: followingCount, following });
  } catch (error) {
    console.error('getFollowing() error: ', error);
    res.status(500).json({
      error: `There was an error fetching who is following "${req.params.username}", please try again later`,
    });
  }
};

const followUser = async (req: Request, res: Response) => {
  try {
    const username = req.params.username || '';

    const user = await User.findUnique({
      where: { username },
    });

    if (!user) {
      res.status(404).json({
        error: 'User could not be found',
      });
      return;
    }

    // dont allow a user to follow themselves
    if (req.user.id === user.id) {
      res.status(400).json({ error: 'You cannot follow yourself' });
      return;
    }

    //check if a follow relationship already exists
    const followrelationship = await prisma.follows.findUnique({
      where: {
        followerId_followingId: {
          followerId: req.user.id,
          followingId: user.id,
        },
      },
    });

    // check if the follow relationship already exists
    if (followrelationship) {
      res.status(400).json({ error: 'You are already following this user' });
      return;
    }

    // create the follow relationship
    const follow = await prisma.follows.create({
      data: {
        followerId: req.user.id,
        followingId: user.id,
      },
    });

    res.json({ follow });
  } catch (error) {
    console.error('followUser() error: ', error);
    res.status(500).json({
      error: `There was an error following "${req.params.username}", please try again later`,
    });
  }
};

const unfollowUser = async (req: Request, res: Response) => {
  try {
    const username = req.params.username || '';

    const user = await User.findUnique({
      where: { username },
    });

    if (!user) {
      res.status(404).json({
        error: 'User could not be found',
      });
      return;
    }

    // dont allow a user to unfollow themselves
    if (req.user.id === user.id) {
      res.status(400).json({ error: 'You cannot unfollow yourself' });
      return;
    }

    //check if a follow relationship already exists
    const followrelationship = await prisma.follows.findUnique({
      where: {
        followerId_followingId: {
          followerId: req.user.id,
          followingId: user.id,
        },
      },
    });

    // check if the follow relationship already exists
    if (!followrelationship) {
      res.status(400).json({ error: 'You are not following this user' });
      return;
    }

    // delete the follow relationship
    const follow = await prisma.follows.delete({
      where: {
        followerId_followingId: {
          followerId: req.user.id,
          followingId: user.id,
        },
      },
    });

    res.json({ follow });
  } catch (error) {
    console.error('unfollowUser() error: ', error);
    res.status(500).json({
      error: `There was an error unfollowing "${req.params.username}", please try again later`,
    });
  }
};
//Retries maxRetries number of times, meaning that if you have 0, then it'll run the function once.
async function retryPromise<T>(
  promiseFn: () => Promise<T>, 
  maxRetries = 3, 
  delayOffset = 0, 
  delayRandomRange = 0
): Promise<T> {

  return new Promise<T>((resolve, reject) => {
    promiseFn()
      .then(resolve, (error: any) => { //On error
        if (maxRetries <= 0) {
          return reject(error);
        } else {
          if(delayRandomRange * Math.random() + delayOffset < 1.0){
            return retryPromise(promiseFn, maxRetries - 1, delayOffset, delayRandomRange).then(resolve, reject);
          }else{
            return new Promise<T>((resolveTwo, rejectTwo) => {
              setTimeout(() => {
                return retryPromise(promiseFn, maxRetries - 1, delayOffset, delayRandomRange).then(resolveTwo, rejectTwo);
              }, delayRandomRange * Math.random() + delayOffset);
            }).then(resolve, reject);
          }
        }
      });
  });
}

//Returns a function that will fail numTimes times, then will return aValue
function functionThatReturnsAFunctionThatFailsACoupleTimes(numTimes: number, aValue: any): () => Promise<any> {
  return async function(){
    if(numTimes == 0){
      return aValue;
    }
    numTimes--;
    throw false;
  };
}

const SMALL_NUMBER = 10;

function testTest(failNumberOfTimes: number){

  let functionThatFailsACoupleTimes = functionThatReturnsAFunctionThatFailsACoupleTimes(failNumberOfTimes, true);

  //Test my test
  for(let i = 0; i < (failNumberOfTimes * 2); ++i){
    function evalTest(val: any){
      let testTestFailedReason = "";
      if(val === undefined){
        testTestFailedReason = "Test test returned undefined for some reason.";
      }
      if((i + 1) > failNumberOfTimes){
        if(val === true){
          //We're good
        }else{
          testTestFailedReason = "Test test didn't return true when it should have.";
        }
      }else{
        if(val === false){
          //We're good
        }else{
          testTestFailedReason = "Test test didn't return false when it should have.";
        }
      }
      testTestFailedReason = testTestFailedReason || "Test test passed test case";
      console.log(testTestFailedReason, "at index", i, "where the function returned", val);
    }
    functionThatFailsACoupleTimes().then(evalTest, evalTest)
  };
}

testTest(SMALL_NUMBER);

let testCaseCounter = 1;

const throwsNoError = [
  (val: any) => {
    if(val == true){
      console.log("Passed test case " + testCaseCounter++);
    }else{
      console.error("Unexpected return value", val);
    }
  },
  () => {
    console.error("It wasn't supposed to fail!")
  }
]

const throwsError = [
  (val: any) => {
    console.error("It wasn't supposed to succeed!", val);
  },
  (val: any) => {
    if(val == false){
      console.log("Passed test case " + testCaseCounter++);
    }else{
      console.error("Unexpected return value", val);
    }
  }
];

//Runs SMALL_NUMBER times, because SMALL_NUMBER - 1 is the number of retries after the first one
let functionThatFailsACoupleTimes = functionThatReturnsAFunctionThatFailsACoupleTimes(SMALL_NUMBER - 1, true);

retryPromise(functionThatFailsACoupleTimes, SMALL_NUMBER - 1).then(...throwsNoError)

functionThatFailsACoupleTimes = functionThatReturnsAFunctionThatFailsACoupleTimes(SMALL_NUMBER - 1, true);

//Runs SMALL_NUMBER - 1 times, because SMALL_NUMBER - 2 is the number of retries after the first one
retryPromise(functionThatFailsACoupleTimes, SMALL_NUMBER - 2).then(...throwsError)

//Testing the delay. You'll have to wait a bit too.

functionThatFailsACoupleTimes = functionThatReturnsAFunctionThatFailsACoupleTimes(SMALL_NUMBER - 1, true);

//Runs SMALL_NUMBER times, because SMALL_NUMBER - 1 is the number of retries after the first one
retryPromise(functionThatFailsACoupleTimes, SMALL_NUMBER - 1, 500, 500).then(...throwsNoError)

functionThatFailsACoupleTimes = functionThatReturnsAFunctionThatFailsACoupleTimes(SMALL_NUMBER - 1, true);

//Runs SMALL_NUMBER - 1 times, because SMALL_NUMBER - 2 is the number of retries after the first one
retryPromise(functionThatFailsACoupleTimes, SMALL_NUMBER - 2, 500, 500).then(...throwsError)