jeudi 27 janvier 2022

JS Refactoring - Dynamic object (key, value) where value is a high order function that invokes the same function

I have a function

function addActivityToUser(
  activityData,
  userId,
  batchOrTransaction = undefined
) {
  const newActivityRef = firestore
    .collection("activity")
    .doc(userId)
    .collection("userActivity")
    .doc();

  if (batchOrTransaction) {
    return batchOrTransaction.create(newActivityRef, activityData);
  }

  return newActivityRef.create(activityData);
}

The activity data object will always looks like:

{
    type: SOME VALID ACTIVITY TYPE,
    ...custom data
}

I have all the valid activity types in a constant:

const VALID_ACTIVITY_TYPES = ["Foo", "Bar"];

I am trying to create some kind of "single source of truth" (a centralized container or something like that).

For this, I have thought about doing the following:

//
// utils/activity/constants.js
//
const VALID_ACTIVITY_TYPES = ["Foo", "Bar"];

//
// api/activity.js
//
const activity = Object.freeze({
  add:
    VALID_ACTIVITY_TYPES.reduce(
      // eslint-disable-next-line no-return-assign
      (acc, activityType) => (
        acc[activityType.toLowerCase()] = (
          activityData,
          userId,
          batchOrTransaction = undefined
        ) =>
          addActivityToUser(
            { ...activityData, type: activityType },
            userId,
            batchOrTransaction
          // eslint-disable-next-line no-sequences
          ),
        acc
      ),
      {}
    ),
  delete: deleteUserActivityById,
}); // main exportable api

function addActivityToUser( // exportable
  activityData,
  userId,
  batchOrTransaction = undefined
) {
  console.log(`Storing ${JSON.stringify(activityData, null, 2)} to ${userId}`);
}

function deleteUserActivityById() {} // exportable

//
// main.js
//
const activityData = { text: "Hello world!" };

const userId = "nSDsAip1029dnsj";

activity.add.foo(activityData, userId);

As you can see, in my solution I am dinamically creating an object which values is a high order lambda function... Is this a pattern/anti-pattern?

I don't like using the high order function which only purpose is to attach a "type" field to the activity data and return the main method... how can I refactor that? Is it possible?


My main purpose is to avoid doing

addActivityToUser({type: VALID_ACTIVITY_TYPES[0], ...}, ...);

in every single module. Instead, at least for me, this namespaced way is better:

activity.add.foo(...)

Aucun commentaire:

Enregistrer un commentaire