Skip to content

Commit 3f0a66e

Browse files
authored
Merge pull request #28 from bartstc/chore/remove-lodash
chore: replace lodash with ramda
2 parents e09e552 + 597ce07 commit 3f0a66e

11 files changed

Lines changed: 243 additions & 67 deletions

File tree

eslint.config.mjs

Lines changed: 3 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -149,27 +149,12 @@ export default config(
149149
"no-restricted-imports": [
150150
"error",
151151
{
152-
patterns: ["lodash/**", "lodash/fp/**", "react-router"],
152+
patterns: ["react-router"],
153153
paths: [
154-
{
155-
message: `Please use import { method } from "lodash-es" instead.`,
156-
name: "lodash",
157-
},
158-
{
159-
importNames: ["chain"],
160-
message:
161-
"Avoid using chain since it is non tree-shakable. Try out flow instead.",
162-
name: "lodash-es",
163-
},
164154
{
165155
importNames: ["default"],
166-
message: `Instead of default import, please use import { method } from "lodash-es" instead.`,
167-
name: "lodash-es",
168-
},
169-
{
170-
message:
171-
"Avoid using chain since it is non tree-shakable. Try out flow instead.",
172-
name: "lodash-es/chain",
156+
message: `Instead of default import, please use import { method } from "ramda" instead.`,
157+
name: "ramda",
173158
},
174159
],
175160
},

package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -30,8 +30,8 @@
3030
"i18next-http-backend": "3.0.2",
3131
"i18next-localstorage-backend": "4.2.0",
3232
"ky": "0.33.3",
33-
"lodash-es": "4.17.21",
3433
"query-string": "8.2.0",
34+
"ramda": "^0.31.3",
3535
"react": "19.1.0",
3636
"react-dom": "19.1.0",
3737
"react-error-boundary": "3.1.4",
@@ -49,7 +49,7 @@
4949
"@storybook/test-runner": "0.23.0",
5050
"@testing-library/jest-dom": "6.6.3",
5151
"@testing-library/react": "16.0.0",
52-
"@types/lodash-es": "4.17.12",
52+
"@types/ramda": "^0.30.2",
5353
"@types/react": "19.1.8",
5454
"@types/react-dom": "19.1.6",
5555
"@types/testing-library__jest-dom": "5.14.9",

pnpm-lock.yaml

Lines changed: 42 additions & 24 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/features/auth/infrastructure/getUser.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { omit } from "lodash-es";
1+
import { omit } from "ramda";
22

33
import type { IUser } from "@/features/auth/types/IUser";
44
import { httpService } from "@/lib/http";
@@ -9,5 +9,5 @@ export const getUser = () => {
99
// mocking current user and its cartId by passing id=1
1010
return httpService
1111
.get<IUserDto>("users/1")
12-
.then((res) => ({ ...(omit(res, "password") as IUser), cartId: 1 }));
12+
.then((res) => ({ ...(omit(["password"], res) as IUser), cartId: 1 }));
1313
};

src/lib/buildUrl.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import { isEmpty } from "lodash-es";
21
import queryString from "query-string";
32

3+
import { isEmpty } from "@/lib/isEmpty";
44
import type { IQueryParams } from "@/types/IQueryParams";
55

66
export const buildUrl = <Params = IQueryParams>(

src/lib/compose.ts

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
/* eslint-disable @typescript-eslint/no-unsafe-call */
2+
/* eslint-disable @typescript-eslint/no-unsafe-function-type */
3+
/* eslint-disable @typescript-eslint/no-unsafe-return */
4+
5+
import type { ComponentClass, ComponentType } from "react";
6+
7+
/**
8+
* Enhances a React component by composing it with higher-order components.
9+
*
10+
* @param component - The base component to enhance.
11+
* @param higherOrderComponents - An array of HoCs to apply to the base component.
12+
* @returns A new component that includes the specified enhancements.
13+
*/
14+
15+
type ComponentEnhancer<TInnerProps, TOutterProps> = (
16+
component: ComponentType<TInnerProps>
17+
) => ComponentClass<TOutterProps>;
18+
19+
export function compose<TInnerProps, TOutterProps>(
20+
...higherOrderComponents: Function[]
21+
): ComponentEnhancer<TInnerProps, TOutterProps> {
22+
return higherOrderComponents.reduce(
23+
(composedComponent, nextEnhancer) =>
24+
(...componentProps: unknown[]) =>
25+
composedComponent(nextEnhancer(...componentProps)),
26+
(arg: unknown) => arg
27+
) as ComponentEnhancer<TInnerProps, TOutterProps>;
28+
}

src/lib/get.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { describe, it, expect } from "vitest";
2+
3+
import { get } from "./get";
4+
5+
describe("get", () => {
6+
it("should return the value at the given path", () => {
7+
const obj = { a: { b: { c: 1 } } };
8+
expect(get(obj, "a.b.c")).toBe(1);
9+
});
10+
11+
it("should return undefined if the path does not exist", () => {
12+
const obj = { a: { b: { c: 1 } } };
13+
expect(get(obj, "a.b.d")).toBeUndefined();
14+
});
15+
16+
it("should handle array indices", () => {
17+
const obj = { a: { b: [1, 2, 3] } };
18+
expect(get(obj, "a.b.1")).toBe(2);
19+
});
20+
21+
it("should handle complex paths", () => {
22+
const obj = { a: { b: [{ c: 1 }, { c: 2 }, { c: 3 }] } };
23+
expect(get(obj, "a.b.1.c")).toBe(2);
24+
});
25+
});

src/lib/get.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { lensPath, view, split } from "ramda";
2+
3+
export const get = <TResult, TObject, TPath extends string>(
4+
obj: TObject,
5+
path: TPath
6+
): TResult => {
7+
const pathArray = split(/[[\].]/, path);
8+
const lens = lensPath(pathArray);
9+
return view(lens, obj) as TResult;
10+
};

src/lib/isEmpty.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
import { either, isNil, isEmpty as _isEmpty } from "ramda";
2+
3+
export const isEmpty = either(isNil, _isEmpty);

0 commit comments

Comments
 (0)