Skip to content

Conversation

GunnerTeh
Copy link
Collaborator

@GunnerTeh GunnerTeh commented Jul 15, 2025

Summary by CodeRabbit

  • Documentation
    • Marked "Initial Set Up" and "Basics" checklist items as completed in the README.
  • New Features
    • Added numerous object and array helper utilities for common data operations.
    • Added string and number utilities for type checks, conversions, arithmetic and basic parsing.
  • Chores
    • Upgraded Jest dev dependency to a newer version.
  • Settings
    • Made ESLint auto-fix-on-save behavior more explicit.

Copy link

coderabbitai bot commented Jul 15, 2025

Walkthrough

Checked two README checklist items, changed VS Code ESLint save mode to "explicit", implemented many object/array and string/number utility functions in kata exercises, and bumped the Jest devDependency from ^26.2.2 to ^30.0.5.

Changes

Cohort / File(s) Change Summary
Documentation
README.md
Marked checklist items "Initial Set Up" and "Basics" as checked ([x])
Editor Configuration
.vscode/settings.json
Changed editor.codeActionsOnSave ESLint fix mode from true to "explicit"
Objects & Arrays Kata
3-JSKata/1-objects-and-arrays/kata.js
Implemented many object and array helper functions (getGreeting, ageOneYear, makeObject, getPropertyValue, addName, deleteProperty, returnErrorIfFalsy, getKeys, getValues, makeArrayOfItem, makeArrayOfItems, hasItem, getItemAtIndex, replaceItemAtIndex, insertItemAtIndex, deleteItemAtIndex, deleteItem). Declarations for zipObject, unzipObject, findOneByProperty, and findAll remain.
Strings & Numbers Utilities
3-JSKata/2-strings-and-numbers/utilities.js
Implemented getType, isNumber, toNumber, isStringNumber, add, addStrings, addStringsOrNumbers, isEmail, countIf. filterStringsWithCommas and splitStringByCommas remain exported/placeholders.
Package Configuration
3-JSKata/package.json
Bumped Jest devDependency from ^26.2.2 to ^30.0.5

Sequence Diagram(s)

(No sequence diagram generated — changes are implementations of utility functions and configuration edits, not a new or modified control flow between components.)

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Pre-merge checks and finishing touches

❌ Failed checks (1 warning, 1 inconclusive)
Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. You can run @coderabbitai generate docstrings to improve docstring coverage.
Title Check ❓ Inconclusive The title “Completed first task” is too generic and fails to convey the substantive work in this changeset, which includes implementing multiple object/array and string/number utility functions, updating ESLint settings, marking off README tasks, and bumping the Jest version. It does not highlight the primary change from the developer’s perspective or give future readers clear context. A more descriptive title would make it easier to understand the PR’s scope at a glance. Please revise the title to clearly summarize the main changes, for example “Implement JS Kata utilities (objects, arrays, strings), update ESLint settings and README checklist.”
✅ Passed checks (1 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch DavidLi-main

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

…back (stopped at "Stand in line") Moving on to task 3
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (1)
.vscode/settings.json (1)

8-10: "explicit" stops auto-fixing on save — confirm this is intended and VS Code ≥ 1.78 is in use
Switching source.fixAll.eslint from the boolean true to the string "explicit" means ESLint fixes are not executed automatically on save; they only run when the user explicitly invokes the “Fix all” code action.
• If you still want auto-fix-on-save, use "always" (or revert to true).
"explicit" requires relatively recent VS Code versions; older setups will silently ignore it.
Please verify that this behaviour change and version requirement match team expectations.

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 69dfab0 and edd7a32.

📒 Files selected for processing (2)
  • .vscode/settings.json (1 hunks)
  • README.md (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • README.md

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
3-JSKata/1-objects-and-arrays/kata.js (1)

13-21: Consider making the function more flexible.

The function correctly increments the age by 1, but it hardcodes name and email properties. The specification only mentions incrementing the age property. Consider whether these hardcoded values are intentional for specific tests, or if the function should preserve/copy other properties from the input object.

If you want a more flexible implementation that preserves existing properties:

 function ageOneYear(obj) {
-  const newObj = {
-    name: 'Mickey Mouse',
-    age: obj.age + 1,
-    email: '[email protected]',
-  }
-
-  return newObj
+  return {
+    ...obj,
+    age: obj.age + 1
+  }
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between edd7a32 and 37ac66a.

⛔ Files ignored due to path filters (1)
  • 3-JSKata/package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (2)
  • 3-JSKata/1-objects-and-arrays/kata.js (1 hunks)
  • 3-JSKata/package.json (1 hunks)
✅ Files skipped from review due to trivial changes (1)
  • 3-JSKata/package.json
🔇 Additional comments (1)
3-JSKata/1-objects-and-arrays/kata.js (1)

7-9: LGTM! Simple and correct implementation.

The function correctly concatenates 'Hello ' with the name parameter as specified. Consider adding input validation if you want to handle edge cases like undefined or null values for the name parameter.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🧹 Nitpick comments (1)
3-JSKata/1-objects-and-arrays/kata.js (1)

45-51: Consider using object spread syntax for cleaner code.

The implementation is correct but could be simplified as hinted in the comment. Consider using spread syntax for more concise code:

-function addName(obj, name) {
-  const objectAddName = Object.assign({}, obj)
-
-  objectAddName.name = name
-
-  return objectAddName
-}
+function addName(obj, name) {
+  return { ...obj, name }
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 6bf1074 and 80496f1.

📒 Files selected for processing (1)
  • 3-JSKata/1-objects-and-arrays/kata.js (1 hunks)
🔇 Additional comments (6)
3-JSKata/1-objects-and-arrays/kata.js (6)

7-9: LGTM!

Simple and correct string concatenation implementation that meets the requirements.


13-21: LGTM with note on hardcoded values.

The implementation correctly increments the age property. Note that this function hardcodes name and email properties rather than preserving them from the input object - ensure this behavior aligns with the kata requirements.


28-34: LGTM!

Correct implementation using computed property syntax to create dynamic property names. The previous issue with literal property names has been properly addressed.


38-40: LGTM!

Correct and concise implementation for dynamic property value access.


56-62: LGTM!

Correct implementation using Object.assign for copying and the delete operator to remove the property as suggested in the comment.


76-78: LGTM!

Correct and concise use of Object.keys() to return an array of object property names.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (1)
3-JSKata/1-objects-and-arrays/kata.js (1)

68-72: Fix falsy value check logic.

The current implementation still has the same issues identified in the previous review:

  1. Uses loose equality == which only checks against false, missing other falsy values (0, "", null, undefined, NaN)
  2. Doesn't explicitly handle the truthy case

Apply this diff to fix the falsy check:

 function returnErrorIfFalsy(val) {
-  if (val == false) {
+  if (!val) {
     return new Error('Oh no, an error!')
   }
 }
🧹 Nitpick comments (3)
3-JSKata/1-objects-and-arrays/kata.js (3)

45-51: Consider using object spread syntax for cleaner code.

The implementation is correct, but could be simplified using modern JavaScript syntax.

Consider this more concise approach:

 function addName(obj, name) {
-  const objectAddName = Object.assign({}, obj)
-
-  objectAddName.name = name
-
-  return objectAddName
+  return {
+    ...obj,
+    name: name
+  }
 }

56-62: Consider using destructuring for cleaner property deletion.

The implementation is correct, but could be modernized using destructuring assignment.

Consider this more modern approach:

 function deleteProperty(obj, key) {
-  const objectDeleteProperty = Object.assign({}, obj)
-
-  delete objectDeleteProperty[key]
-
-  return objectDeleteProperty
+  const { [key]: deleted, ...rest } = obj
+  return rest
 }

93-101: Consider using Array.fill() for better performance.

The implementation is correct, but can be simplified and optimized using built-in array methods.

Consider this more efficient approach:

 function makeArrayOfItem(item, length) {
-  const myArray = []
-
-  for (let i = 0; i < length; i++) {
-    myArray.push(item)
-  }
-
-  return myArray
+  return new Array(length).fill(item)
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 80496f1 and e26acd0.

📒 Files selected for processing (1)
  • 3-JSKata/1-objects-and-arrays/kata.js (2 hunks)
🔇 Additional comments (6)
3-JSKata/1-objects-and-arrays/kata.js (6)

7-9: LGTM!

Simple and correct implementation that meets the requirements.


28-34: LGTM!

The previous issue with literal property names has been correctly fixed. The function now properly uses dynamic property assignment with bracket notation.


38-40: LGTM!

Correct implementation using bracket notation for dynamic property access.


76-78: LGTM!

Perfect implementation using the standard Object.keys() method.


82-84: LGTM!

Perfect implementation using the standard Object.values() method.


105-107: LGTM!

Excellent use of rest parameters with a clear understanding comment. This is the optimal implementation.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (2)
3-JSKata/1-objects-and-arrays/kata.js (2)

13-21: Fix hardcoded property values.

The function still hardcodes name and email properties instead of copying them from the original object, which will overwrite existing values with fixed data.

Apply this diff to properly copy all properties and only modify the age:

 function ageOneYear(obj) {
-  const newObj = {
-    name: 'Mickey Mouse',
-    age: obj.age + 1,
-    email: '[email protected]',
-  }
-
-  return newObj
+  return {
+    ...obj,
+    age: obj.age + 1
+  }
 }

68-72: Fix falsy value check logic.

The current implementation still has the issues identified previously:

  1. Uses loose equality == which only checks against false, missing other falsy values (0, "", null, undefined, NaN)
  2. Doesn't explicitly handle the truthy case

Apply this diff to fix the falsy check:

 function returnErrorIfFalsy(val) {
-  if (val == false) {
+  if (!val) {
     return new Error('Oh no, an error!')
   }
+  return val
 }
🧹 Nitpick comments (3)
3-JSKata/1-objects-and-arrays/kata.js (3)

45-51: Consider using spread syntax as suggested in the comment.

While your implementation is correct, you can make it more concise using the spread syntax as mentioned in the comment:

 function addName(obj, name) {
-  const objectAddName = Object.assign({}, obj)
-
-  objectAddName.name = name
-
-  return objectAddName
+  return {
+    ...obj,
+    name: name
+  }
 }

93-101: Consider a more concise implementation.

While your loop-based approach works correctly, you can use Array.from() or Array.fill() for a more concise solution:

 function makeArrayOfItem(item, length) {
-  const myArray = []
-
-  for (let i = 0; i < length; i++) {
-    myArray.push(item)
-  }
-
-  return myArray
+  return Array(length).fill(item)
 }

136-168: Multiple functions are not implemented.

The following functions have empty implementations:

  • replaceItemAtIndex (line 136)
  • insertItemAtIndex (line 140)
  • deleteItemAtIndex (line 144)
  • deleteItem (line 147)
  • zipObject (line 152)
  • unzipObject (line 157)
  • findOneByProperty (line 164)
  • findAll (line 168)

These functions need to be implemented to complete the kata exercises.

Would you like me to help implement these functions or open issues to track their implementation?

📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e26acd0 and 09c2476.

📒 Files selected for processing (1)
  • 3-JSKata/1-objects-and-arrays/kata.js (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
3-JSKata/1-objects-and-arrays/kata.js (2)
3-JSKata/1-objects-and-arrays/1-tests/addName.test.js (2)
  • name (5-5)
  • obj (6-8)
3-JSKata/1-objects-and-arrays/1-tests/hasItem.test.js (2)
  • arr (5-5)
  • arr (16-16)
🪛 Biome (2.1.2)
3-JSKata/1-objects-and-arrays/kata.js

[error] 113-113: This code will never be reached ...

... because either this statement ...

... or this statement will return from the function beforehand

(lint/correctness/noUnreachable)

🔇 Additional comments (7)
3-JSKata/1-objects-and-arrays/kata.js (7)

7-9: Function implementation looks good.

The getGreeting function correctly concatenates the greeting string with the provided name.


28-34: Good fix for dynamic property creation.

The function now correctly uses bracket notation to create an object with a dynamic property name, addressing the previous issue.


38-40: Property access implementation is correct.

The function properly uses bracket notation to access and return the property value.


56-62: Correct implementation of property deletion.

The function properly creates a copy of the object and uses the delete operator to remove the specified property.


76-78: Correct usage of Object.keys().

The function properly returns an array of the object's property names.


82-84: Correct usage of Object.values().

The function properly returns an array of the object's values.


105-107: Correct use of rest parameters.

The function properly uses rest parameters to capture all arguments into an array. Good explanatory comment.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 3

♻️ Duplicate comments (2)
3-JSKata/1-objects-and-arrays/kata.js (2)

111-119: Critical logic error: function returns false prematurely.


123-130: Incorrect index validation logic.

🧹 Nitpick comments (3)
3-JSKata/1-objects-and-arrays/kata.js (3)

44-50: Consider using spread operator for consistency.

While your implementation is correct, you could simplify it using the spread operator for better readability:

 function addName(obj, name) {
-  const objectAddName = Object.assign({}, obj)
-
-  objectAddName.name = name
-
-  return objectAddName
+  return { ...obj, name }
 }

55-61: Consider using destructuring for a cleaner approach.

Your implementation is correct, but you could use object destructuring with rest syntax for a more modern approach:

 function deleteProperty(obj, key) {
-  const objectDeleteProperty = Object.assign({}, obj)
-
-  delete objectDeleteProperty[key]
-
-  return objectDeleteProperty
+  const { [key]: _, ...rest } = obj
+  return rest
 }

92-100: Consider using Array methods for cleaner code.

Your implementation works correctly, but you could simplify it using Array.from() or new Array().fill():

 function makeArrayOfItem(item, length) {
-  const myArray = []
-
-  for (let i = 0; i < length; i++) {
-    myArray.push(item)
-  }
-
-  return myArray
+  return new Array(length).fill(item)
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 09c2476 and a611c88.

📒 Files selected for processing (1)
  • 3-JSKata/1-objects-and-arrays/kata.js (2 hunks)
🧰 Additional context used
🪛 Biome (2.1.2)
3-JSKata/1-objects-and-arrays/kata.js

[error] 112-112: This code will never be reached ...

... because either this statement ...

... or this statement will return from the function beforehand

(lint/correctness/noUnreachable)

🔇 Additional comments (7)
3-JSKata/1-objects-and-arrays/kata.js (7)

7-9: LGTM!

The greeting function is implemented correctly.


13-20: Great fix!

The implementation correctly uses the spread operator to preserve all original properties while only incrementing the age. This properly addresses the previous concern about hardcoded values.


27-33: Well done!

The implementation correctly uses bracket notation for dynamic property assignment, properly addressing the previous issue with literal property names.


37-39: LGTM!

Correct implementation of property access.


75-77: LGTM!

Correct use of Object.keys().


81-83: LGTM!

Correct use of Object.values().


104-106: Excellent use of rest parameters!

Clean and correct implementation.

Comment on lines +135 to +146
function replaceItemAtIndex(arr, idx, item) {
const tempArray = []

for (let i = 0; i < arr.length; i++) {
tempArray[i] = arr[i]
if (arr[i] == arr[idx]) {
tempArray[i] = item
}
}

return tempArray
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix index comparison logic.

The function incorrectly compares array values instead of indices, which could replace multiple elements with the same value.

 function replaceItemAtIndex(arr, idx, item) {
-  const tempArray = []
-
-  for (let i = 0; i < arr.length; i++) {
-    tempArray[i] = arr[i]
-    if (arr[i] == arr[idx]) {
-      tempArray[i] = item
-    }
-  }
-
-  return tempArray
+  const newArr = [...arr]
+  if (idx >= 0 && idx < arr.length) {
+    newArr[idx] = item
+  }
+  return newArr
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function replaceItemAtIndex(arr, idx, item) {
const tempArray = []
for (let i = 0; i < arr.length; i++) {
tempArray[i] = arr[i]
if (arr[i] == arr[idx]) {
tempArray[i] = item
}
}
return tempArray
}
function replaceItemAtIndex(arr, idx, item) {
const newArr = [...arr]
if (idx >= 0 && idx < arr.length) {
newArr[idx] = item
}
return newArr
}
🤖 Prompt for AI Agents
In 3-JSKata/1-objects-and-arrays/kata.js around lines 135 to 146, the function
replaceItemAtIndex incorrectly compares array values instead of indices in the
loop, causing multiple replacements if values match. Fix this by changing the
condition to compare the current index i with the target index idx, so only the
element at idx is replaced with item.

Comment on lines +150 to +161
function insertItemAtIndex(arr, item, idx) {
const tempArray = []

for (let i = 0; i < arr.length; i++) {
tempArray[i] = arr[i]
if (i == idx) {
tempArray.splice(i, 0, item)
}
}

return tempArray
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Fix array insertion logic.

The current implementation modifies the array during iteration and doesn't correctly handle insertion. Use array methods for a cleaner solution:

 function insertItemAtIndex(arr, item, idx) {
-  const tempArray = []
-
-  for (let i = 0; i < arr.length; i++) {
-    tempArray[i] = arr[i]
-    if (i == idx) {
-      tempArray.splice(i, 0, item)
-    }
-  }
-
-  return tempArray
+  return [...arr.slice(0, idx), item, ...arr.slice(idx)]
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function insertItemAtIndex(arr, item, idx) {
const tempArray = []
for (let i = 0; i < arr.length; i++) {
tempArray[i] = arr[i]
if (i == idx) {
tempArray.splice(i, 0, item)
}
}
return tempArray
}
function insertItemAtIndex(arr, item, idx) {
return [...arr.slice(0, idx), item, ...arr.slice(idx)]
}
🤖 Prompt for AI Agents
In 3-JSKata/1-objects-and-arrays/kata.js lines 150 to 161, the current
insertItemAtIndex function incorrectly modifies the array during iteration and
does not insert the item properly. To fix this, avoid modifying the array inside
the loop; instead, create a new array by slicing the original array up to the
index, then add the new item, and finally concatenate the remaining elements
from the original array after the index. Return this new array as the result.

…th function deleteItem.moving on to strings and numbers
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (5)
3-JSKata/1-objects-and-arrays/kata.js (5)

67-71: Add explicit return for truthy values.

The falsy check is correct, but the function returns undefined for truthy values. Consider adding an explicit return statement:

 function returnErrorIfFalsy(val) {
   if (!val) {
     return new Error('Oh no, an error!')
   }
+  return val
 }

111-119: Critical logic error: function returns false prematurely.

The function returns false immediately if the first element doesn't match, preventing it from checking the remaining elements. This makes most of the loop unreachable.

Apply this diff to fix the logic:

 function hasItem(arr, item) {
-  for (let i = 0; i < arr.length; i++) {
-    if (arr[i] == item) {
-      return true
-    } else {
-      return false
-    }
-  }
+  return arr.includes(item)
 }

Alternatively, if you prefer to keep the loop approach:

 function hasItem(arr, item) {
   for (let i = 0; i < arr.length; i++) {
     if (arr[i] == item) {
       return true
-    } else {
-      return false
     }
   }
+  return false
 }

135-146: Fix index comparison logic.

The function incorrectly compares array values instead of indices, which could replace multiple elements with the same value.

 function replaceItemAtIndex(arr, idx, item) {
-  const tempArray = []
-
-  for (let i = 0; i < arr.length; i++) {
-    tempArray[i] = arr[i]
-    if (arr[i] == arr[idx]) {
-      tempArray[i] = item
-    }
-  }
-
-  return tempArray
+  const newArr = [...arr]
+  if (idx >= 0 && idx < arr.length) {
+    newArr[idx] = item
+  }
+  return newArr
 }

150-161: Fix array insertion logic.

The current implementation modifies the array during iteration and doesn't correctly handle insertion. Use array methods for a cleaner solution:

 function insertItemAtIndex(arr, item, idx) {
-  const tempArray = []
-
-  for (let i = 0; i < arr.length; i++) {
-    tempArray[i] = arr[i]
-    if (i == idx) {
-      tempArray.splice(i, 0, item)
-    }
-  }
-
-  return tempArray
+  return [...arr.slice(0, idx), item, ...arr.slice(idx)]
 }

123-130: Simplify index validation logic.

While your implementation works, it's unnecessarily complex. Simply validate the index bounds:

 function getItemAtIndex(arr, idx) {
-  for (let i = 0; i < arr.length; i++) {
-    if (i == idx) {
-      return arr[i]
-    }
-  }
-  return new Error()
+  if (idx >= 0 && idx < arr.length) {
+    return arr[idx]
+  }
+  return new Error('Index out of bounds')
 }
🧹 Nitpick comments (3)
3-JSKata/1-objects-and-arrays/kata.js (3)

44-50: Consider using spread syntax for consistency.

While your implementation is correct, you could simplify it using the spread syntax as suggested in the comment:

-function addName(obj, name) {
-  const objectAddName = Object.assign({}, obj)
-
-  objectAddName.name = name
-
-  return objectAddName
-}
+function addName(obj, name) {
+  return { ...obj, name }
+}

55-61: Consider using destructuring for cleaner code.

Your implementation works correctly. For a more modern approach:

-function deleteProperty(obj, key) {
-  const objectDeleteProperty = Object.assign({}, obj)
-
-  delete objectDeleteProperty[key]
-
-  return objectDeleteProperty
-}
+function deleteProperty(obj, key) {
+  const { [key]: _, ...rest } = obj
+  return rest
+}

92-100: Consider using Array methods for cleaner code.

Your implementation works correctly. For a more concise approach:

-function makeArrayOfItem(item, length) {
-  const myArray = []
-
-  for (let i = 0; i < length; i++) {
-    myArray.push(item)
-  }
-
-  return myArray
-}
+function makeArrayOfItem(item, length) {
+  return Array(length).fill(item)
+}
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between a611c88 and 77542a2.

📒 Files selected for processing (1)
  • 3-JSKata/1-objects-and-arrays/kata.js (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
3-JSKata/1-objects-and-arrays/kata.js (2)
3-JSKata/1-objects-and-arrays/1-tests/addName.test.js (2)
  • name (5-5)
  • obj (6-8)
3-JSKata/1-objects-and-arrays/1-tests/hasItem.test.js (2)
  • arr (5-5)
  • arr (16-16)
🪛 Biome (2.1.2)
3-JSKata/1-objects-and-arrays/kata.js

[error] 112-112: This code will never be reached ...

... because either this statement ...

... or this statement will return from the function beforehand

(lint/correctness/noUnreachable)

🔇 Additional comments (6)
3-JSKata/1-objects-and-arrays/kata.js (6)

7-9: Implementation looks good!

The greeting function correctly concatenates the string as expected.


13-20: Well implemented with proper object cloning!

The function correctly uses the spread operator to preserve all original properties while only incrementing the age, addressing previous concerns about hardcoded values.


27-33: Correct dynamic property implementation!

The function properly uses bracket notation to create an object with a dynamic key.


37-39: Clean property accessor implementation!


75-83: Excellent use of built-in methods!

Both functions correctly utilize Object.keys() and Object.values().


104-106: Perfect use of rest parameters!

Comment on lines +165 to +176
function deleteItemAtIndex(arr, idx) {
const tempArray = []

for (let i = 0; i < arr.length; i++) {
tempArray[i] = arr[i]
if (i == idx) {
tempArray.splice(idx, 1)
}
}

return tempArray
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Simplify deletion logic.

The current approach modifies the array during iteration. Use a cleaner solution:

 function deleteItemAtIndex(arr, idx) {
-  const tempArray = []
-
-  for (let i = 0; i < arr.length; i++) {
-    tempArray[i] = arr[i]
-    if (i == idx) {
-      tempArray.splice(idx, 1)
-    }
-  }
-
-  return tempArray
+  return arr.filter((_, index) => index !== idx)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function deleteItemAtIndex(arr, idx) {
const tempArray = []
for (let i = 0; i < arr.length; i++) {
tempArray[i] = arr[i]
if (i == idx) {
tempArray.splice(idx, 1)
}
}
return tempArray
}
function deleteItemAtIndex(arr, idx) {
return arr.filter((_, index) => index !== idx)
}
🤖 Prompt for AI Agents
In 3-JSKata/1-objects-and-arrays/kata.js around lines 165 to 176, the function
deleteItemAtIndex modifies the array while iterating, which is inefficient and
error-prone. Instead, create a new array by filtering out the element at the
given index or use array slicing to exclude the item at idx. This will simplify
the logic and avoid modifying the array during iteration.

Comment on lines +179 to +187
function deleteItem(arr, item) {
for (let i = 0; i < arr.length; i++) {
if (arr[i] == item) {
arr.splice(i, 0, item)
}
}

return arr
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue

Critical: Function mutates input and uses incorrect splice parameters.

The function has two major issues:

  1. It mutates the original array instead of returning a new one
  2. splice(i, 0, item) inserts the item instead of removing it

Apply this fix:

 function deleteItem(arr, item) {
-  for (let i = 0; i < arr.length; i++) {
-    if (arr[i] == item) {
-      arr.splice(i, 0, item)
-    }
-  }
-
-  return arr
+  return arr.filter(el => el !== item)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function deleteItem(arr, item) {
for (let i = 0; i < arr.length; i++) {
if (arr[i] == item) {
arr.splice(i, 0, item)
}
}
return arr
}
function deleteItem(arr, item) {
return arr.filter(el => el !== item)
}
🤖 Prompt for AI Agents
In 3-JSKata/1-objects-and-arrays/kata.js around lines 179 to 187, the deleteItem
function incorrectly mutates the input array and uses splice with parameters
that insert the item instead of removing it. To fix this, avoid mutating the
original array by creating and returning a new array that excludes the specified
item, and remove the incorrect splice call that inserts the item. Use a method
like filter to return a new array without the item.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 0

🧹 Nitpick comments (2)
3-JSKata/2-strings-and-numbers/utilities.js (2)

5-11: Simplify the boolean logic.

The function works correctly but can be simplified by directly returning the boolean result of the comparison instead of using an if-else statement.

 function isNumber(thing) {
-  if (typeof thing === 'number') {
-    return true
-  } else {
-    return false
-  }
+  return typeof thing === 'number'
 }

13-15: Consider edge case handling for invalid inputs.

The toNumber function correctly uses the Number constructor for conversion. However, consider that Number(undefined) returns NaN, Number(null) returns 0, and Number("") returns 0. Depending on the kata requirements, you might want to handle these edge cases explicitly.

If stricter validation is needed, consider:

 function toNumber(str) {
+  // Consider adding validation for empty strings or null/undefined
   return Number(str)
 }
📜 Review details

Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 77542a2 and 083cd85.

📒 Files selected for processing (1)
  • 3-JSKata/2-strings-and-numbers/utilities.js (1 hunks)
🔇 Additional comments (1)
3-JSKata/2-strings-and-numbers/utilities.js (1)

1-3: Simple and correct implementation.

The getType function correctly uses the typeof operator to return the JavaScript type of the input parameter.

…ers. porbly skip isEmail. also added some other minor fixes to other functions
Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

♻️ Duplicate comments (5)
3-JSKata/1-objects-and-arrays/kata.js (5)

165-176: Simplify deletion logic.

The current approach modifies the array during iteration. Use a cleaner solution with array methods.

 function deleteItemAtIndex(arr, idx) {
-  const tempArray = []
-
-  for (let i = 0; i < arr.length; i++) {
-    tempArray[i] = arr[i]
-    if (i == idx) {
-      tempArray.splice(idx, 1)
-    }
-  }
-
-  return tempArray
+  return arr.filter((_, index) => index !== idx)
 }

112-119: Critical: Function returns false prematurely.

The function returns false immediately if the first element doesn't match, preventing it from checking the remaining elements.

Apply this diff to fix the logic:

 function hasItem(arr, item) {
   for (let i = 0; i < arr.length; i++) {
-    if (arr[i] == item) {
+    if (arr[i] === item) {
       return true
-    } else {
-      return false
     }
   }
+  return false
 }

Or use the built-in method:

 function hasItem(arr, item) {
-  for (let i = 0; i < arr.length; i++) {
-    if (arr[i] == item) {
-      return true
-    } else {
-      return false
-    }
-  }
+  return arr.includes(item)
 }

135-146: Fix index comparison logic.

The function incorrectly compares array values (arr[i] == arr[idx]) instead of indices, which will replace all elements with the same value as the element at index idx.

Apply this diff:

 function replaceItemAtIndex(arr, idx, item) {
-  const tempArray = []
-
-  for (let i = 0; i < arr.length; i++) {
-    tempArray[i] = arr[i]
-    if (arr[i] == arr[idx]) {
-      tempArray[i] = item
-    }
-  }
-
-  return tempArray
+  const newArr = [...arr]
+  if (idx >= 0 && idx < arr.length) {
+    newArr[idx] = item
+  }
+  return newArr
 }

150-161: Fix array insertion logic.

The implementation modifies the array during iteration with splice, which can lead to incorrect behavior. Use a cleaner approach with array slicing.

Apply this diff:

 function insertItemAtIndex(arr, item, idx) {
-  const tempArray = []
-
-  for (let i = 0; i < arr.length; i++) {
-    tempArray[i] = arr[i]
-    if (i == idx) {
-      tempArray.splice(i, 0, item)
-    }
-  }
-
-  return tempArray
+  return [...arr.slice(0, idx), item, ...arr.slice(idx)]
 }

179-187: Critical: Function mutates input and uses incorrect splice parameters.

The function has two major issues:

  1. It mutates the original array instead of returning a new one
  2. splice(i, 0, item) inserts the item instead of removing it (should be splice(i, 1))

Apply this fix:

 function deleteItem(arr, item) {
-  for (let i = 0; i < arr.length; i++) {
-    if (arr[i] == item) {
-      arr.splice(i, 0, item)
-    }
-  }
-
-  return arr
+  return arr.filter(el => el !== item)
 }
🧹 Nitpick comments (7)
3-JSKata/2-strings-and-numbers/utilities.js (2)

5-11: Consider simplifying the boolean return.

The logic is correct, but the if-else can be eliminated by returning the boolean expression directly.

Apply this diff to simplify:

 function isNumber(thing) {
-  if (typeof thing === 'number') {
-    return true
-  } else {
-    return false
-  }
+  return typeof thing === 'number'
 }

29-35: Specify radix in parseInt calls.

Always provide the radix parameter to parseInt to avoid unexpected behavior with certain inputs (e.g., strings starting with "0").

Apply this diff:

 function addStrings(a, b) {
-  let num1 = parseInt(a)
-  let num2 = parseInt(b)
+  let num1 = parseInt(a, 10)
+  let num2 = parseInt(b, 10)
   let num3 = num1 + num2
 
   return String(num3)
 }
3-JSKata/1-objects-and-arrays/kata.js (5)

27-33: LGTM with optional simplification.

The dynamic property issue has been correctly fixed. The implementation is clear, though it could be condensed.

For a more concise approach:

 function makeObject(key, value) {
-  const newObj = {}
-
-  newObj[key] = value
-
-  return newObj
+  return { [key]: value }
 }

44-50: LGTM with optional simplification.

The implementation correctly creates a shallow copy. For consistency with other functions in this file, consider using the spread operator.

 function addName(obj, name) {
-  const objectAddName = Object.assign({}, obj)
-
-  objectAddName.name = name
-
-  return objectAddName
+  return { ...obj, name }
 }

55-61: LGTM with optional simplification.

The implementation correctly creates a copy before deletion. For consistency, consider using the spread operator.

 function deleteProperty(obj, key) {
-  const objectDeleteProperty = Object.assign({}, obj)
-
-  delete objectDeleteProperty[key]
-
-  return objectDeleteProperty
+  const result = { ...obj }
+  delete result[key]
+  return result
 }

93-101: LGTM with optional simplification.

The loop-based approach is correct and easy to understand. For a more concise alternative, consider using Array.fill().

 function makeArrayOfItem(item, length) {
-  const myArray = []
-
-  for (let i = 0; i < length; i++) {
-    myArray.push(item)
-  }
-
-  return myArray
+  return Array(length).fill(item)
 }

123-130: Previous issue fixed, but consider simplification.

The index validation logic has been corrected. However, the loop is unnecessary since array access is O(1).

 function getItemAtIndex(arr, idx) {
-  for (let i = 0; i < arr.length; i++) {
-    if (i == idx) {
-      return arr[i]
-    }
-  }
-  return new Error()
+  if (idx >= 0 && idx < arr.length) {
+    return arr[idx]
+  }
+  return new Error('Index out of bounds')
 }
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between 083cd85 and f43bf1a.

📒 Files selected for processing (2)
  • 3-JSKata/1-objects-and-arrays/kata.js (2 hunks)
  • 3-JSKata/2-strings-and-numbers/utilities.js (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (2)
3-JSKata/2-strings-and-numbers/utilities.js (9)
3-JSKata/3-data-structures/3-tests/getType.test.js (1)
  • getType (1-1)
3-JSKata/2-strings-and-numbers/2-tests/getType.test.js (1)
  • getType (1-1)
3-JSKata/2-strings-and-numbers/2-tests/isNumber.test.js (1)
  • isNumber (1-1)
3-JSKata/2-strings-and-numbers/2-tests/toNumber.test.js (1)
  • toNumber (1-1)
3-JSKata/2-strings-and-numbers/2-tests/isStringNumber.test.js (1)
  • isStringNumber (1-1)
3-JSKata/2-strings-and-numbers/2-tests/add.test.js (1)
  • add (1-1)
3-JSKata/2-strings-and-numbers/2-tests/addStrings.test.js (1)
  • addStrings (1-1)
3-JSKata/2-strings-and-numbers/2-tests/addStringsOrNumbers.test.js (1)
  • addStringsOrNumbers (1-1)
3-JSKata/2-strings-and-numbers/2-tests/isEmail.test.js (1)
  • isEmail (1-1)
3-JSKata/1-objects-and-arrays/kata.js (2)
3-JSKata/1-objects-and-arrays/1-tests/addName.test.js (2)
  • name (5-5)
  • obj (6-8)
3-JSKata/1-objects-and-arrays/1-tests/hasItem.test.js (2)
  • arr (5-5)
  • arr (16-16)
🪛 Biome (2.1.2)
3-JSKata/2-strings-and-numbers/utilities.js

[error] 50-50: This code will never be reached ...

... because either this statement ...

... or this statement will return from the function beforehand

(lint/correctness/noUnreachable)

🔇 Additional comments (11)
3-JSKata/2-strings-and-numbers/utilities.js (4)

1-3: LGTM!

Clean implementation of getType using the typeof operator.


13-15: LGTM!

Correct use of Number() for string-to-number conversion.


17-23: Verify the intended behavior for edge cases.

The isNaN() function has quirks that may not match expectations:

  • isNaN('') returns false (empty string is coerced to 0)
  • isNaN(' ') returns false (whitespace is coerced to 0)
  • isNaN(null) returns false (null is coerced to 0)

Ensure this behavior aligns with your requirements. If you need stricter validation, consider using Number.isNaN(Number(str)) or checking typeof str === 'string' && !isNaN(str) && str.trim() !== ''.


25-27: LGTM!

The implementation correctly adds two values. Note that the + operator will concatenate if either operand is a string.

3-JSKata/1-objects-and-arrays/kata.js (7)

7-9: LGTM!

Clean string concatenation implementation.


13-20: LGTM!

The previous issue with hardcoded properties has been correctly addressed using the spread operator to preserve all properties while incrementing age.


37-39: LGTM!

Correct property access using bracket notation.


67-72: LGTM!

Both previous issues have been correctly addressed: the falsy check now uses !val, and the function explicitly returns the value for truthy inputs.


76-78: LGTM!

Correct use of Object.keys().


82-84: LGTM!

Correct use of Object.values().


105-107: LGTM!

Excellent use of rest parameters to capture all arguments as an array.

Comment on lines 37 to 47
function addStringsOrNumbers(a, b) {
let num1 = parseInt(a)
let num2 = parseInt(b)
let num3 = num1 + num2

function addStringsOrNumbers(a, b) {}
if (isNumber(a) && isNumber(b)) {
return num3
} else {
return String(num3)
}
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

Fix the type checking logic.

The function checks isNumber(a) and isNumber(b) after parsing them with parseInt, but it should check the original parameters before parsing to determine their types.

Apply this diff to fix the logic:

 function addStringsOrNumbers(a, b) {
-  let num1 = parseInt(a)
-  let num2 = parseInt(b)
-  let num3 = num1 + num2
-
   if (isNumber(a) && isNumber(b)) {
-    return num3
+    return a + b
   } else {
-    return String(num3)
+    return String(parseInt(a, 10) + parseInt(b, 10))
   }
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function addStringsOrNumbers(a, b) {
let num1 = parseInt(a)
let num2 = parseInt(b)
let num3 = num1 + num2
function addStringsOrNumbers(a, b) {}
if (isNumber(a) && isNumber(b)) {
return num3
} else {
return String(num3)
}
}
function addStringsOrNumbers(a, b) {
if (isNumber(a) && isNumber(b)) {
return a + b
} else {
return String(parseInt(a, 10) + parseInt(b, 10))
}
}
🤖 Prompt for AI Agents
In 3-JSKata/2-strings-and-numbers/utilities.js around lines 37 to 47, the
function currently calls parseInt before checking types; change the logic to
first test the original parameters with isNumber(a) and isNumber(b), then parse
them (e.g., const num1 = parseInt(a); const num2 = parseInt(b)), compute the
sum, and finally return the numeric sum if both original inputs are numbers,
otherwise return the string form of the sum; ensure no type-checking uses the
parsed values.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

♻️ Duplicate comments (2)
3-JSKata/2-strings-and-numbers/utilities.js (2)

37-47: Fix the type checking logic.

The function parses inputs before checking their types. It should check the original parameters first, then perform the appropriate operation based on their types. Additionally, missing radix parameters in parseInt calls can cause issues.

This issue was already flagged in a previous review. Please refer to the earlier comment for the suggested fix.


49-63: Critical logic error: email validation always returns false.

The condition checks if a single character equals all of '@', '.', 'c', 'o', and 'm' simultaneously, which is impossible. The function also returns on the first iteration, making the rest of the loop unreachable.

This issue was already flagged in a previous review. Please refer to the earlier comment for suggested fixes.

🧹 Nitpick comments (3)
3-JSKata/2-strings-and-numbers/utilities.js (3)

5-11: Simplify to a single return statement.

The function logic is correct but can be more concise.

Apply this diff:

 function isNumber(thing) {
-  if (typeof thing === 'number') {
-    return true
-  } else {
-    return false
-  }
+  return typeof thing === 'number'
 }

17-23: Simplify to a single return statement.

The function logic is correct but can be more concise.

Apply this diff:

 function isStringNumber(str) {
-  if (isNaN(str)) {
-    return false
-  } else {
-    return true
-  }
+  return !isNaN(str)
 }

65-74: Clarify the truthiness check.

The loose inequality != false has subtle behavior: it will exclude false but include 0, '', null, undefined, and NaN. If the intent is to count all truthy values, use a simple truthiness check. If the intent is to exclude only false, use strict inequality.

For counting truthy values (recommended):

 function countIf(array, fn) {
   let count = 0
 
   for (let i = 0; i < array.length; i++) {
-    if (fn(array[i]) != false) {
+    if (fn(array[i])) {
       count += 1
     }
   }
   return count
 }

Or for excluding only false (if that's the specific intent):

-    if (fn(array[i]) != false) {
+    if (fn(array[i]) !== false) {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

Disabled knowledge base sources:

  • Linear integration is disabled by default for public repositories

You can enable these sources in your CodeRabbit configuration.

📥 Commits

Reviewing files that changed from the base of the PR and between f43bf1a and d37edd2.

📒 Files selected for processing (1)
  • 3-JSKata/2-strings-and-numbers/utilities.js (1 hunks)
🧰 Additional context used
🧬 Code graph analysis (1)
3-JSKata/2-strings-and-numbers/utilities.js (9)
3-JSKata/2-strings-and-numbers/2-tests/getType.test.js (1)
  • getType (1-1)
3-JSKata/2-strings-and-numbers/2-tests/isNumber.test.js (1)
  • isNumber (1-1)
3-JSKata/2-strings-and-numbers/2-tests/toNumber.test.js (1)
  • toNumber (1-1)
3-JSKata/2-strings-and-numbers/2-tests/isStringNumber.test.js (1)
  • isStringNumber (1-1)
3-JSKata/2-strings-and-numbers/2-tests/add.test.js (1)
  • add (1-1)
3-JSKata/2-strings-and-numbers/2-tests/addStrings.test.js (1)
  • addStrings (1-1)
3-JSKata/2-strings-and-numbers/2-tests/addStringsOrNumbers.test.js (1)
  • addStringsOrNumbers (1-1)
3-JSKata/2-strings-and-numbers/2-tests/isEmail.test.js (1)
  • isEmail (1-1)
3-JSKata/2-strings-and-numbers/2-tests/countIf.test.js (1)
  • countIf (1-1)
🪛 Biome (2.1.2)
3-JSKata/2-strings-and-numbers/utilities.js

[error] 50-50: This code will never be reached ...

... because either this statement ...

... or this statement will return from the function beforehand

(lint/correctness/noUnreachable)

🔇 Additional comments (3)
3-JSKata/2-strings-and-numbers/utilities.js (3)

1-3: LGTM!

The implementation correctly returns the JavaScript type using typeof.


13-15: LGTM!

The implementation correctly converts the input to a number using Number().


25-27: LGTM!

The implementation correctly adds two values.

Comment on lines +29 to +35
function addStrings(a, b) {
let num1 = parseInt(a)
let num2 = parseInt(b)
let num3 = num1 + num2

function isStringNumber(str) {}
return String(num3)
}
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Add radix parameter to parseInt calls.

The parseInt function should always include a radix (base) parameter. Without it, strings with leading zeros could be interpreted as octal in older JavaScript environments, leading to unexpected results.

Apply this diff:

 function addStrings(a, b) {
-  let num1 = parseInt(a)
-  let num2 = parseInt(b)
+  let num1 = parseInt(a, 10)
+  let num2 = parseInt(b, 10)
   let num3 = num1 + num2
 
   return String(num3)
 }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
function addStrings(a, b) {
let num1 = parseInt(a)
let num2 = parseInt(b)
let num3 = num1 + num2
function isStringNumber(str) {}
return String(num3)
}
function addStrings(a, b) {
let num1 = parseInt(a, 10)
let num2 = parseInt(b, 10)
let num3 = num1 + num2
return String(num3)
}
🤖 Prompt for AI Agents
In 3-JSKata/2-strings-and-numbers/utilities.js around lines 29 to 35, the
parseInt calls omit the radix which can produce incorrect parsing for strings
with leading zeros; update both parseInt(a) and parseInt(b) to include an
explicit radix of 10 (e.g., parseInt(a, 10) and parseInt(b, 10)) so the values
are parsed as decimal before summing and returning the result as a string.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant