1.2.1 โ€ข Published 3 years ago

functional-flattener v1.2.1

Weekly downloads
3
License
MIT
Repository
github
Last release
3 years ago

๐Ÿช’ 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
1.2.0

3 years ago

1.2.1

3 years ago

1.1.1

3 years ago

1.1.0

3 years ago

1.0.6

3 years ago

1.0.5

3 years ago

1.0.4

3 years ago

1.0.3

3 years ago

1.0.2

3 years ago

1.0.1

3 years ago

0.0.1

3 years ago

1.0.0

3 years ago