Skip to content

MaxKim-J/functional-flattener

Folders and files

NameName
Last commit message
Last commit date

Latest commit

Β 

History

80 Commits
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 
Β 

Repository files navigation

πŸͺ’ functional-flattener

npm npm GitHub Release Date GitHub license

Modify JS object functionally and precisely

Install

Install from the NPM repository using yarn or npm:

npm i functional-flattener
yarn add functional-flattener

About

fucntional-flattenerλŠ” JS의 Arrayκ°€ map, filter λ“±μ˜ Array.prototype λ©”μ„œλ“œλ₯Ό μ΄μš©ν•˜μ—¬ μˆ˜μ •λ  수 μžˆλŠ” 것과 같은 μ›λ¦¬λ‘œ, ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ„ 톡해 JS Objectλ₯Ό μˆ˜μ •ν•˜κΈ° μœ„ν•΄ λ§Œλ“€μ–΄μ‘ŒμŠ΅λ‹ˆλ‹€. JS Objectλ₯Ό 개발자의 μ˜λ„μ— 맞게 μˆ˜μ •ν•  수 μžˆλ„λ‘ ν•˜λŠ” λͺ‡ κ°€μ§€μ˜ λ©”μ†Œλ“œλ“€κ³Ό, ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°μ—μ„œ μ˜κ°μ„ 받은 λ©”μ†Œλ“œ 체이닝을 μ§€μ›ν•©λ‹ˆλ‹€.

Pros

1. Effective Data Adapting

Casing

  • μ„œλ²„μ™€ ν΄λΌμ΄μ–ΈνŠΈ μ•±μ˜ κ΅¬ν˜„ μ–Έμ–΄κ°€ λ‹€λ₯Έλ° μ„œλ²„μ—μ„œ λ”°λ‘œ μ²˜λ¦¬ν•˜μ§€ μ•Šμ€ κ²½μš°μ— HTTPμš”μ²­μ„ ν•΄μ„œ 받은 JSON 객체의 key값이 JSμ—μ„œ 주둜 μ‚¬μš©ν•˜λŠ” μΉ΄λ©œμΌ€μ΄μŠ€κ°€ μ•„λ‹Œ λ‹€λ₯Έ μΌ€μ΄μŠ€μΌ κ²½μš°κ°€ μžˆμŠ΅λ‹ˆλ‹€(Django의 κ²½μš°λŠ” μŠ€λ„€μ΄ν¬ μΌ€μ΄μŠ€)
  • Node기반 ν΄λΌμ΄μ–ΈνŠΈμ—μ„œ ESLintλ₯Ό μ μš©μ€‘μ΄λΌλ©΄, μΉ΄λ©œμΌ€μ΄μŠ€κ°€ μ•„λ‹Œ λ‹€λ₯Έ μΌ€μ΄μŠ€μ˜ ν‚€λ₯Ό μ°Έμ‘°ν•˜λŠ” 것 λ§ŒμœΌλ‘œλ„ μ—λŸ¬κ°€ λ°œμƒν•©λ‹ˆλ‹€. λ”°λΌμ„œ JSON 객체의 ν‚€λ₯Ό μΌκ΄„μ μœΌλ‘œ 케이싱할 수 μžˆλŠ” 도ꡬ가 ν•„μš”ν•©λ‹ˆλ‹€.
  • functional-flattenerλŠ” 객체의 λͺ¨λ“  keyλ₯Ό μΌκ΄„μ μœΌλ‘œ 카멜, μŠ€λ„€μ΄ν¬ μΌ€μ΄μŠ€λ‘œ casingν•˜λŠ” λ©”μ†Œλ“œλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.

Data Adapting(flattening)

  • HTTP μš”μ²­μ„ 톡해 JSON 객체λ₯Ό λ°›μ•˜μ„ λ•Œ ν•΄λ‹Ή 객체λ₯Ό ν΄λΌμ΄μ–ΈνŠΈ μ•±μ—μ„œ μ“°κΈ° 쒋도둝 μˆ˜μ •μ„ ν•΄μ•Όν•˜λŠ” 상황이 μžˆμŠ΅λ‹ˆλ‹€.
  • TravelFlan FEνŒ€μ—μ„œλŠ” μ΄λ ‡κ²Œ μ„œλ²„λ‘œλΆ€ν„° 응닡받은 객체λ₯Ό ν΄λΌμ΄μ–ΈνŠΈμ˜ use-case에 맞게 μˆ˜μ •ν•˜λŠ” μˆœμˆ˜ν•¨μˆ˜λ₯Ό flattener 라고 λͺ…λͺ…ν•˜κ³ , κ΄€μŠ΅μ μœΌλ‘œ μ‚¬μš©ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.
  • functional-flattenerλŠ” μœ„μ—μ„œ μ–ΈκΈ‰ν•œ 일괄적인 μΌ€μ΄μ‹±λΏλ§Œ μ•„λ‹ˆλΌ 객체λ₯Ό 효과적으둜 μˆ˜μ •ν•  수 μžˆλŠ” λ©”μ†Œλ“œλ“€μ„ μ œκ³΅ν•˜λ©°, λ©”μ†Œλ“œ 체이닝을 톡해 객체가 μˆ˜μ •λ˜λŠ” 과정듀을 효과적으둜 μ μš©ν•  수 있게 ν–ˆμŠ΅λ‹ˆλ‹€.

2. Economic Typing

const mockData = {
  userId: 12424,
  userName: 'max',
  userAge: 25,
  userProfile: {
    userProfileText: 'I Love Zebra',
    userFavoriteAnimal: { id: 3, animalName: 'vulture' },
    userFriends: [
      { id: 12324, name: 'julie', favoriteAnimal: { id: 0, animalName: 'tiger' } },
      { id: 11424, name: 'michael', favoriteAnimal: { id: 1, animalName: 'lion' } },
      { id: 18924, name: 'shawn', favoriteAnimal: { id: 2, animalName: 'monkey' } },
    ],
  },
}

function flattener(data) {
  const { userId, userName, userAge, userProfile } = data

  const processedUserName = `Hi! I am ${userName}`
  const processedUserProfile = {
    ...userProfile,
    userFriends: userProfile.userFriends.map((friend) => {
      ...friend,
      name: `I am your friend name ${friend.name}.`
    })
  } 

  return {
    userId,
    userName : processedUserName,
    userAge,
    userProfile: processedUserProfile
  }
}
  • λͺ…λ Ήν˜• ν”„λ‘œκ·Έλž˜λ°μœΌλ‘œ 객체λ₯Ό 일일히 풀어헀쳐 μƒˆλ‘œμš΄ 객체λ₯Ό λ§Œλ“€μ–΄ λ¦¬ν„΄ν•˜λŠ” μ‹μ˜ imperative flattener의 λ‘œμ§μ€ μž₯ν™©ν•˜κ³ , 가독성에도 쒋지 μ•ŠμŠ΅λ‹ˆλ‹€.
  • 상황에 따라 μ „μ²˜λ¦¬κ°€ ν•„μš” μ—†λŠ” 객체의 킀와 ν”„λ‘œνΌν‹°λ₯Ό 타이핑할 μˆ˜λ„ 있고, 타이핑해야할 λ³€μˆ˜λ„ λŠ˜μ–΄λ‚  수 μžˆμŠ΅λ‹ˆλ‹€.
  • ν•¨μˆ˜ν˜• ν”„λ‘œκ·Έλž˜λ°κ³Ό λ©”μ„œλ“œ 체이닝을 μ μš©ν•˜λ©΄ 객체 전체λ₯Ό ν’€μ–΄ν—€μΉ  ν•„μš” 없이 μ „μ²˜λ¦¬κ°€ ν•„μš”ν•œ ν”„λ‘œνΌν‹°μ—λ§Œ 접근이 κ°€λŠ₯ν•©λ‹ˆλ‹€.

API(v1.0.0~)

1. FlattenTarget Class

  • flattening에 ν•„μš”ν•œ λ©”μ†Œλ“œλ₯Ό μ œκ³΅ν•˜λŠ” ν΄λž˜μŠ€μž…λ‹ˆλ‹€.
  • λ©€λ²„λ³€μˆ˜λ‘œ μΈμŠ€ν„΄μŠ€ μƒμ„±μ‹œμ— νŒŒλΌλ―Έν„°λ‘œ μ œκ³΅ν•΄μ•Ό ν•˜λŠ” Target Objectλ₯Ό 가지고 μžˆμŠ΅λ‹ˆλ‹€.
  • 이 클래슀의 λͺ¨λ“  λ©”μ†Œλ“œλ“€μ€ μˆœμˆ˜ν•˜κ²Œ μƒˆλ‘œμš΄ FlattenTarget 클래슀의 μΈμŠ€ν„΄μŠ€λ₯Ό λ¦¬ν„΄ν•˜κΈ° λ•Œλ¬Έμ—, λ©”μ†Œλ“œ 체이닝이 κ°€λŠ₯ν•©λ‹ˆλ‹€. returnResult() λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•΄μ•Όλ§Œ 일반 객체λ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.

2. flattener()

flattener({
  userId: 12424,
  userName: 'max',
  userAge: 25,
})//...λ‹€λ₯Έ λ©”μ†Œλ“œλ“€μ„ μ²΄μ΄λ‹ν•©λ‹ˆλ‹€. 
  • FlattenTarget μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€μ–΄ λ¦¬ν„΄ν•˜λŠ” νŒ©ν† λ¦¬ ν•¨μˆ˜μž…λ‹ˆλ‹€. 라이브러리λ₯Ό μ΄μš©ν•΄ 객체λ₯Ό λ³€κ²½ν•˜λŠ” ν–‰μœ„μ˜ μ‹œμž‘μ μ΄ λ˜λŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€.
  • FlattenTarget μΈμŠ€ν„΄μŠ€λ₯Ό λ¦¬ν„΄ν•˜κΈ° λ•Œλ¬Έμ—, λ°”λ‘œ FlattenTarget 클래슀의 λ©”μ†Œλ“œλ“€μ„ 체이닝할 수 μžˆμŠ΅λ‹ˆλ‹€.
  • 인자둜 μžλ°”μŠ€ν¬λ¦½νŠΈ 객체λ₯Ό λ°›μŠ΅λ‹ˆλ‹€.

3. case()

const result = flattener({
  user_id: 12424,
  user_name: 'Max',
  user_age: 25,
// casingOption은 camelκ³Ό snakeλ₯Ό μ§€μ›ν•©λ‹ˆλ‹€.
}).case({to:'camel'}).returnResult()

// Result will be { userId: 12424, userName: 'Max', userAge: 25 }
  • case λ©”μ†Œλ“œλŠ” target 객체의 keyλ₯Ό μΌκ΄„μ μœΌλ‘œ μΌ€μ΄μ‹±ν•˜λŠ” λ©”μ†Œλ“œμž…λ‹ˆλ‹€.
  • 인자둜 casingOption 객체λ₯Ό λ°›μŠ΅λ‹ˆλ‹€. 객체의 to ν”„λ‘œνΌν‹°λ‘œ 'camel' ν˜Ήμ€ 'snake' μ˜΅μ…˜μ„ μ£Όμ–΄ 객체의 λͺ¨λ“  ν‚€μ˜ 케이싱을 μΌκ΄„μ μœΌλ‘œ λ°”κΏ€ 수 μžˆμŠ΅λ‹ˆλ‹€.
  • 이미 객체의 keyκ°€ casingOptionμ—μ„œ λͺ…μ‹œλœ 케이싱이라면, ν•΄λ‹Ή keyλ₯Ό λ¬΄μ‹œν•©λ‹ˆλ‹€.

4. changeKey()

const result = flattener({
  userId: 12424,
  userName: 'Max',
  userAge: 25,
  userProfile: {
    userIntroduce: 'Hi! My name is Max',
    userFavoriteAnimal: 'zebra',
  }
// changeKeyPlan의 keyλŠ” κΈ°μ‘΄ target의 key, valueλŠ” μƒˆλ‘œμš΄ keyμž…λ‹ˆλ‹€.
// 객체 ν”„λ‘œνΌν‹°μ˜ keyλ₯Ό λ°”κΎΈκ³  싢을 경우, ':'을 μ΄μš©ν•©λ‹ˆλ‹€.
}).changeKey({
  userAge:'userCurrentName',
  'userProfile:userInfo': {
    userFavoriteAnimal: 'userAnimal'
  }
}).returnResult()

/* 
Result will be
{ 
  userId: 12424, 
  userName: 'Max', 
  userCurrentAge: 25,
  userInfo: {
    userIntroduce: 'Hi! My name is Max',
    userAnimal: 'zebra',
  }
}
*/
  • 이미 μ‘΄μž¬ν•˜λŠ” 객체 ν”„λ‘œνΌν‹°μ˜ keyλ₯Ό, λ©”μ†Œλ“œμ— λ„˜κΈ°λŠ” changeKeyPlan νŒŒλΌλ―Έν„°μ— λͺ…μ‹œλœ κ°’μœΌλ‘œ λ°”κΏ‰λ‹ˆλ‹€.
  • changeKeyPlan은 객체이며 κΈ°λ³Έμ μœΌλ‘œλŠ” ꡐ체할 target의 keyλ₯Ό plan의 key둜, μƒˆλ‘œμš΄ keyλ₯Ό λ¬Έμžμ—΄ κ°’μœΌλ‘œ κ°€μ§‘λ‹ˆλ‹€.
  • λ‹€λ§Œ λ°”λ€Œμ–΄μ•Όν•  target의 νŠΉμ • keyκ°€ 객체λ₯Ό κ°’μœΌλ‘œ 가진닀면, λ¬Έμžμ—΄ 값을 λͺ…μ‹œν•΄μ€„ 수 μ—†κΈ° λ•Œλ¬Έμ— 콜둠(:)을 μ‚¬μš©ν•˜μ—¬ ꡐ체할 target의 킀와 ν•¨κ»˜ μƒˆλ‘œμš΄ ν‚€λ₯Ό λͺ…μ‹œν•΄μ€„ 수 μžˆμŠ΅λ‹ˆλ‹€.
  • TypeScript μ‚¬μš©μ‹œ ChangeKeyPlan νƒ€μž…μ„ μ°Έμ‘°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

5. process()

const result = flattener({
  userId: 12424,
  userName: 'Max',
  userAge: 25,
  userProfile: {
    userIntroduce: 'I love zebra.',
    userFavoriteAnimal: 'zebra',
  }
}).process((target:Target) => ({
  userId: 10000,
  userAge: (age:number) => `${age} years old`,
  userProfile: {
    userIntroduce: (text:string) => `Hello! My name is ${target.userName}. ${text}`,
  },
})).returnResult()

/* 
Result will be
{ 
  userId: 10000 
  userName: 'Max', 
  userAge: '25 years old',
  userProfile: {
    userIntroduce: 'Hello! My name is Max. I love zebra.',
    userFavoriteAnimal: 'zebra',
  }
}
*/
  • 이미 μ‘΄μž¬ν•˜λŠ” 객체 ν”„λ‘œνΌν‹°λ“€μ˜ 값을 λ©”μ†Œλ“œμ— λ„˜κΈ°λŠ” processPlan νŒŒλΌλ―Έν„°μ— λͺ…μ‹œλœ κ°’μœΌλ‘œ κ°€κ³΅ν•˜κ±°λ‚˜, λͺ…μ‹œλœ ν•¨μˆ˜λ₯Ό μ‹€ν–‰ν•œ κ°’μœΌλ‘œ κ°€κ³΅ν•˜λŠ” λ©”μ†Œλ“œμž…λ‹ˆλ‹€.
  • processPlan νŒŒλΌλ―Έν„°λŠ” target objectλ₯Ό 인자둜 λ°›λŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€. 이 ν•¨μˆ˜κ°€ λ¦¬ν„΄ν•˜λŠ” 객체의 ν”„λ‘œνΌν‹°λ“€μ€ target objectλ₯Ό μ°Έμ‘°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • processPlanν•¨μˆ˜κ°€ λ¦¬ν„΄ν•˜λŠ” 객체 ν”„λ‘œνΌν‹°μ˜ κ°’μœΌλ‘œλŠ” κΈ°μ‘΄ target 객체 ν”„λ‘œνΌν‹°κ°€ 가진 값을 인자둜 ν•˜λŠ” 콜백 ν•¨μˆ˜ λ˜λŠ” νŠΉμ • 값을 λͺ…μ‹œν•  수 μžˆμŠ΅λ‹ˆλ‹€. 콜백 ν•¨μˆ˜μΌλ•ŒλŠ” κΈ°μ‘΄ target 객체 ν”„λ‘œνΌν‹°μ˜ 값에 콜백 ν•¨μˆ˜λ₯Ό μ μš©ν•΄ κ°€κ³΅ν•œ κ°’μœΌλ‘œ λ°”λ€Œλ©°, νŠΉμ • κ°’μΌλ•ŒλŠ” target의 값에 overwriteλ©λ‹ˆλ‹€.
  • processPlan 객체 ν”„λ‘œνΌν‹°μ˜ keyλ‘œλŠ” target object에 이미 μ‘΄μž¬ν•˜λŠ” key만 λͺ…μ‹œν•  수 μžˆμŠ΅λ‹ˆλ‹€. 그렇지 μ•Šμ€ keyλŠ” λ¬΄μ‹œν•©λ‹ˆλ‹€.
  • target object에 이미 μ‘΄μž¬ν•˜λŠ” ν”„λ‘œνΌν‹°λ§Œ processν•  수 있기 λ•Œλ¬Έμ— 객체에 μƒˆλ‘œμš΄ ν”„λ‘œνΌν‹°λ₯Ό μΆ”κ°€ν•˜κ³  μ‹Άλ‹€λ©΄ augment λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•΄μ•Ό ν•©λ‹ˆλ‹€.
  • process λ©”μ†Œλ“œμ—μ„œ μ—¬λŸ¬ 객체 ν”„λ‘œνΌν‹°λ“€μ˜ λ³€ν™”λŠ” μ„œλ‘œ λ…λ¦½μ μž…λ‹ˆλ‹€. processPlan객체의 κ°’μœΌλ‘œ λ„˜κΈ΄ 콜백 ν•¨μˆ˜λŠ” 이미 process된 객체의 ν”„λ‘œνΌν‹°λ₯Ό μ°Έμ‘°ν•˜μ§€ μ•Šκ³  μ›λž˜ target 객체의 ν”„λ‘œνΌν‹°μ˜ κ°’λ§Œμ„ μ°Έμ‘°ν•©λ‹ˆλ‹€.

6. augment()

const result = flattener({
  userId: 12424,
  userName: 'Max',
  userAge: 25,
  userProfile: {
    userProfileText: 'My Name is Max.',
    userFavoriteAnimal: 'zebra',
  }
}).augment((target:Target) => {
  const { userProfileText, userFavoriteAnimal } = target.userProfile
  return {
    isUserAdult: target.userAge > 19
    userProfile: {
      userIntroduce: `${userProfileText} My favorite animal is ${userFavoriteAnimal}.`,
    }
  },
}).returnResult()

/*
Result will be
{ 
  userId: 10000 
  userName: 'Max', 
  userAge: 25,
  isUserAdult: true,
  userProfile: {
    userProfileText: 'My Name is Max.',
    userFavoriteAnimal: 'zebra',
    userIntroduce: 'My name is Max. My favorite animal is zebra.',
  }
}
*/
  • target 객체에 μƒˆλ‘œμš΄ ν”„λ‘œνΌν‹°λ₯Ό μ‚½μž…ν•˜μ—¬ 객체λ₯Ό μ¦κ°•μ‹œν‚€λŠ” λ©”μ†Œλ“œμž…λ‹ˆλ‹€.
  • augmentPlan νŒŒλΌλ―Έν„°λŠ” target objectλ₯Ό 인자둜 λ°›λŠ” ν•¨μˆ˜μž…λ‹ˆλ‹€. 이 ν•¨μˆ˜κ°€ λ¦¬ν„΄ν•˜λŠ” 객체의 ν”„λ‘œνΌν‹°λ“€μ€ target objectλ₯Ό μ°Έμ‘°ν•  수 μžˆμŠ΅λ‹ˆλ‹€.
  • augmentPlan 객체의 값은 ν•¨μˆ˜λ₯Ό κ°€μ§ˆ 수 μ—†μŠ΅λ‹ˆλ‹€. target 객체에 μƒˆλ‘­κ²Œ μΆ”κ°€λ˜λŠ” ν”„λ‘œνΌν‹°λŠ” νŠΉμ • κ°’μ΄κ±°λ‚˜, target objectλ§Œμ„ μ°Έμ‘°ν•˜μ—¬ λ§Œλ“€μ–΄μ Έμ•Ό ν•©λ‹ˆλ‹€.
  • augmentPlan κ°μ²΄μ—λŠ” κΈ°μ‘΄ target objectμ—λŠ” μ—†λŠ” μƒˆλ‘œμš΄ key κ°’λ§Œ ν¬ν•¨ν•˜λŠ” 것을 ꢌμž₯ν•©λ‹ˆλ‹€. augment() λ©”μ†Œλ“œκ°€ 증강에 μ΄ˆμ μ„ λ§žμΆ”κ³  μžˆμ–΄μ„œ κ·Έλ ‡μŠ΅λ‹ˆλ‹€. plan 객체에 κΈ°μ‘΄ key값을 μ‚¬μš©ν•΄ μƒˆλ‘œμš΄ 값을 λ„˜κ²¨μ£ΌλŠ” λ°©μ‹μœΌλ‘œ 객체λ₯Ό μˆ˜μ •ν•  μˆ˜λŠ” μžˆμ§€λ§Œ, μ΄λŠ” 이미 '가곡'에 μ’€ 더 초점이 맞좰져 μžˆλŠ” process() λ©”μ„œλ“œμ—μ„œλ„ κ°€λŠ₯ν•œ λ™μž‘μž…λ‹ˆλ‹€.

7. remove()

const result = flattener({
  userId: 12424,
  userName: 'Max',
  userAge: 25,
  userProfile: {
    userProfileText: 'My Name is Max.',
    userFavoriteAnimal: 'zebra',
    userImage : {
      mobile: '/image/12424/mobile',
      desktop: '/image/12424/desktop',
    }
  }
}).remove([
  'userId',
  'userProfile.userProfileText',
  'userProfile.userProfileImage.mobile',
]).returnResult()

/*
Result will be
{ 
  userName: 'Max', 
  userAge: 25,
  userProfile: {
    userProfileText: 'My Name is Max.',
    userFavoriteAnimal: 'zebra',
    userImage : {
      desktop: '/image/12424/desktop',
    }
  }
}
*/
  • target 객체의 ν”„λ‘œνΌν‹°λ₯Ό μ‚­μ œν•˜μ—¬ 객체λ₯Ό μΆ•μ†Œμ‹œν‚€λŠ” λ©”μ†Œλ“œμž…λ‹ˆλ‹€.
  • removePlan은 λ¬Έμžμ—΄λ‘œ 이루어진 배열이며, λ„νŠΈ μ—°μ‚°μž(.)λ₯Ό 톡해 μ œκ±°ν•  객체의 ν”„λ‘œνΌν‹°λ₯Ό ν‘œν˜„ν•©λ‹ˆλ‹€.

8. returnResult()

  • μœ„ λ‹€λ₯Έ λ©”μ†Œλ“œλ“€μ˜ μ˜ˆμ‹œμ—μ„œ λ³Ό 수 μžˆλ“―, returnResult() λ©”μ†Œλ“œλŠ” FlattenTarget μΈμŠ€ν„΄μŠ€μ—μ„œ 변경이 λλ‚œ target objectλ₯Ό λ°˜ν™˜ν•©λ‹ˆλ‹€.
  • μžλ°”μŠ€ν¬λ¦½νŠΈ λ³€μˆ˜μ— 변경이 μ™„λ£Œλœ 객체λ₯Ό 담을 λ•ŒλŠ” κΌ­ 이 λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•΄ FlattenTarget μΈμŠ€ν„΄μŠ€μ—μ„œ 일반 μžλ°”μŠ€ν¬λ¦½νŠΈ 객체인 target objectλ₯Ό λ°˜ν™˜ν•΄μ•Ό ν•©λ‹ˆλ‹€.
  • flatten() ν•¨μˆ˜κ°€ 객체의 μˆ˜μ •μ„ μ‹œμž‘ν•˜λŠ” μ§„μž…μ μ΄λΌλ©΄, returnResult()λŠ” μˆ˜μ •μ„ λ§ˆλ¬΄λ¦¬ν•˜λŠ” λ©”μ†Œλ“œμž…λ‹ˆλ‹€.

Full Example

import { flattener, Target } from 'functional-flattener'

const mockData = {
  user_id: 12424,
  user_name: 'max',
  user_age: 25,
  user_profile: {
    user_profile_text: 'I Love Zebra',
    user_favorite_animal: { id: 3, animal_name: 'vulture' },
    userProfileImage: {
      mobile: '/image/12424/mobile',
      desktop: '/image/12424/desktop',
    },
    user_friends: [
      { id: 12324, name: 'julie', favorite_animal: { id: 0, animal_name: 'tiger' } },
      { id: 11424, name: 'michael', favorite_animal: { id: 1, animal_name: 'lion' } },
      { id: 18924, name: 'shawn', favorite_animal: { id: 2, animal_name: 'monkey' } },
    ],
  },
}

const processPlan = (target:Target) => ({
  userId: (id:number) => id + 10000,
  userProfile: {
    userProfileText: (text:string) => `Hello! My name is ${target.userName}. ${text}`,
    userFriends: (friends:Friend[]) => friends.map(
      (friend:Friend) => ({ ...friend, name: `${friend.name} the ${friend.favoriteAnimal.animalName}` }),
    ),
  },
})

const augmentPlan = (target:Target) => ({
  isRecentSignUser: target.userId > 10000,
  isUserAdult: target.userAge > 19,
  userProfile: {
    userFriendsFavoriteAnimals: target.userProfile.userFriends.map(
      (friend:Friend) => friend.favoriteAnimal.animalName,
    ),
  },
})

const removePlan = [
  'userId',
  'userProfile.userProfileImage.mobile',
]

const changePlan = {
  userAge: 'userCurrentAge',
  'userProfile:userCurrentProfile': {
    userProfileText: 'userIntroduce',
    'userFavoriteAnimal:userAnimal': {
      animalName: 'name',
    },
  },
}

const result = flattener(mockData).case({ to: 'camel' })
  .process(processPlan)
  .augment(augmentPlan)
  .remove(removePlan)
  .returnResult()

FYI

λ©”μ†Œλ“œ 적용 μˆœμ„œ

λ”±νžˆ 따라야 ν•˜λŠ” λ©”μ†Œλ“œ 적용 μˆœμ„œλŠ” μ—†μ§€λ§Œ, flatten() ν•¨μˆ˜λ‘œ FlattenTarget μΈμŠ€ν„΄μŠ€λ₯Ό λ§Œλ“€κ³  λ‚œ 직후에 casing()λ©”μ†Œλ“œλ₯Ό λ¨Όμ € μ μš©ν•˜λŠ” 것을 μΆ”μ²œν•©λ‹ˆλ‹€. ESLintλ₯Ό μ‚¬μš©ν•œλ‹€λ©΄, μΆ”ν›„ μ μš©ν•  process() ν˜Ήμ€ augment() λ©”μ†Œλ“œμ˜ 인자둜 μ“°μ΄λŠ” plan 객체에 카멜 μΌ€μ΄μŠ€κ°€ μ•„λ‹Œ λ‹€λ₯Έ μΌ€μ΄μŠ€μ˜ keyλ₯Ό μ‚¬μš©ν•˜λŠ” 것 λ§ŒμœΌλ‘œλ„ μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚€κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

process() λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•  λ•Œ, λ°°μ—΄ μ•ˆμ˜ κ°μ²΄λŠ” μ–΄λ–»κ²Œ modify ν•˜λ‚˜μš”?

const mockData = {
  userFriends: [
    { id: 12324, name: 'julie', favoriteAnimal: { id: 0, animalName: 'tiger' } },
    { id: 11424, name: 'michael', favoriteAnimal: { id: 1, animalName: 'lion' } },
    { id: 18924, name: 'shawn', favoriteAnimal: { id: 2, animalName: 'monkey' } },
  ],
}

const processPlan = (target:Target) => ({
  userFriends: (friends:Friend[]) => friends.map(
    (friend:Friend) => ({ ...friend, name: `${friend.name} the ${friend.favoriteAnimal.animalName}` }),
  )},
)

const result = flattener(mockData)
  .process(processPlan)
  .returnResult()

λ°°μ—΄ μ•ˆμ˜ 객체λ₯Ό μˆ˜μ •ν•˜κ³  싢을 λ•ŒλŠ” 배열을 μˆ˜μ •ν•˜λŠ” 콜백 ν•¨μˆ˜λ₯Ό λ„˜κΈ°λ˜ μˆ˜μ •ν•œ μƒˆ 배열을 λ°˜ν™˜ν•˜λŠ” mapμ΄λ‚˜ filter와 같은 λ©”μ†Œλ“œλ₯Ό μ‚¬μš©ν•˜λŠ” 것을 ꢌμž₯ν•©λ‹ˆλ‹€.

ToDo

  1. Add FlattenTarget.prototype.modify() : This method can modify target object according to modify plan. Modify() will be a superset method of process, changeKey, augment and remove method. It will be going to operate those method`s modification all at once.
  2. Add README.md written in English
  3. Add More Detail error handling
  4. Add More test cases

Contribution

  • Anyone can open a pull request or issues. Just ensure passing every existing tests suites in ./lib/test dir.
  • There is github action to verify that all test suites are passed when pull reqeust is opened.
  • MIT License

About

πŸͺ’ Modify JS object functionally and precisely.

Resources

License

Stars

Watchers

Forks

Packages

No packages published