abisan-custom-library 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md ADDED
File without changes
@@ -0,0 +1,6 @@
1
+ module.exports = {
2
+ preset: 'ts-jest',
3
+ testEnvironment: 'node',
4
+ roots: ['<rootDir>/test'],
5
+ testMatch: ['**/*.test.ts']
6
+ };
package/package.json ADDED
@@ -0,0 +1,31 @@
1
+ {
2
+ "name": "abisan-custom-library",
3
+ "version": "1.0.0",
4
+ "description": "",
5
+ "main": "index.js",
6
+ "scripts": {
7
+ "test": "jest",
8
+ "coverage": "jest --coverage",
9
+ "watch": "jest --watch"
10
+
11
+ },
12
+ "repository": {
13
+ "type": "git",
14
+ "url": "git+https://github.com/Abinashini31/Custom-Library.git"
15
+ },
16
+ "keywords": [],
17
+ "author": "",
18
+ "license": "ISC",
19
+ "type": "commonjs",
20
+ "bugs": {
21
+ "url": "https://github.com/Abinashini31/Custom-Library/issues"
22
+ },
23
+ "homepage": "https://github.com/Abinashini31/Custom-Library#readme",
24
+ "devDependencies": {
25
+ "@types/jest": "^30.0.0",
26
+ "jest": "^30.3.0",
27
+ "ts-jest": "^29.4.9",
28
+ "ts-node": "^10.9.2",
29
+ "typescript": "^6.0.2"
30
+ }
31
+ }
@@ -0,0 +1,46 @@
1
+ // src/Extraction/pluck.ts
2
+
3
+ type Path = string | string[];
4
+
5
+ /**
6
+ * Polymorphic pluck:
7
+ * - "id" → simple property
8
+ * - "a.b.c" → deep path
9
+ * - ["id", "tags"] → multi-key pick
10
+ */
11
+ export function pluck<T>(path: Path, data: T[]): any[] {
12
+ if (!Array.isArray(data) || data.length === 0) return [];
13
+
14
+ if (Array.isArray(path)) {
15
+ return multiPick(path, data);
16
+ }
17
+
18
+ if (typeof path === 'string' && path.includes('.')) {
19
+ return deepPick(path, data);
20
+ }
21
+
22
+ return simplePick(path as string, data);
23
+ }
24
+
25
+ /* ------------------ Helpers ------------------ */
26
+
27
+ function simplePick<T>(key: string, data: T[]) {
28
+ return data.map(item => (item as any)?.[key]);
29
+ }
30
+
31
+ function deepPick<T>(path: string, data: T[]) {
32
+ const keys = path.split('.');
33
+
34
+ return data.map(obj =>
35
+ keys.reduce((acc: any, key) => acc?.[key], obj)
36
+ );
37
+ }
38
+
39
+ function multiPick<T>(keys: string[], data: T[]) {
40
+ return data.map(obj =>
41
+ keys.reduce((acc: any, key) => {
42
+ acc[key] = (obj as any)?.[key];
43
+ return acc;
44
+ }, {})
45
+ );
46
+ }
@@ -0,0 +1,11 @@
1
+ export function every<T>(
2
+ fn: (value: T, index: number, arr: readonly T[]) => boolean,
3
+ arr: readonly T[]
4
+ ): boolean {
5
+ for (let i = 0; i < arr.length; i++) {
6
+ if (!fn(arr[i], i, arr)) {
7
+ return false;
8
+ }
9
+ }
10
+ return true;
11
+ }
@@ -0,0 +1,16 @@
1
+ export function filter<T>(
2
+ fn: (value: T, index: number, arr: readonly T[]) => boolean,
3
+ arr: readonly T[] | null | undefined
4
+ ): T[] {
5
+ if (!arr) return [];
6
+
7
+ const result: T[] = [];
8
+
9
+ for (let i = 0; i < arr.length; i++) {
10
+ if (fn(arr[i], i, arr)) {
11
+ result.push(arr[i]);
12
+ }
13
+ }
14
+
15
+ return result;
16
+ }
@@ -0,0 +1,14 @@
1
+ export function map<T, R>(
2
+ fn: (item: T, index: number) => R,
3
+ arr: T[]
4
+ ): R[] {
5
+ if (!Array.isArray(arr)) return [];
6
+
7
+ const result: R[] = [];
8
+
9
+ for (let i = 0; i < arr.length; i++) {
10
+ result.push(fn(arr[i], i));
11
+ }
12
+
13
+ return result;
14
+ }
@@ -0,0 +1,26 @@
1
+ export function reduce<T, U>(
2
+ fn: (acc: U, val: T, index: number, arr: T[]) => U,
3
+ initial: U,
4
+ arr: T[]
5
+ ): U {
6
+ let acc = initial;
7
+
8
+ for (let i = 0; i < arr.length; i++) {
9
+ acc = fn(acc, arr[i], i, arr);
10
+ }
11
+
12
+ return acc;
13
+ }
14
+ export function reduceRight<T, U>(
15
+ fn: (acc: U, val: T, index: number, arr: T[]) => U,
16
+ initial: U,
17
+ arr: T[]
18
+ ): U {
19
+ let acc = initial;
20
+
21
+ for (let i = arr.length - 1; i >= 0; i--) {
22
+ acc = fn(acc, arr[i], i, arr);
23
+ }
24
+
25
+ return acc;
26
+ }
@@ -0,0 +1,13 @@
1
+ export function reduceRight<T, U>(
2
+ fn: (acc: U, val: T, index: number, arr: readonly T[]) => U,
3
+ initial: U,
4
+ arr: readonly T[]
5
+ ): U {
6
+ let acc = initial;
7
+
8
+ for (let i = arr.length - 1; i >= 0; i--) {
9
+ acc = fn(acc, arr[i], i, arr as T[]);
10
+ }
11
+
12
+ return acc;
13
+ }
@@ -0,0 +1,11 @@
1
+ export function some<T>(
2
+ fn: (value: T, index: number, arr: readonly T[]) => boolean,
3
+ arr: readonly T[]
4
+ ): boolean {
5
+ for (let i = 0; i < arr.length; i++) {
6
+ if (fn(arr[i], i, arr)) {
7
+ return true;
8
+ }
9
+ }
10
+ return false;
11
+ }
@@ -0,0 +1,15 @@
1
+ import { getDeep, setDeep } from './utils';
2
+
3
+ export type Lens = {
4
+ get: (obj: any) => any;
5
+ set: (value: any, obj: any) => any;
6
+ };
7
+
8
+ export function lens(path: string): Lens {
9
+ const keys = path ? path.split('.') : [];
10
+
11
+ return {
12
+ get: (obj: any) => getDeep(obj, keys),
13
+ set: (value: any, obj: any) => setDeep(obj, keys, value)
14
+ };
15
+ }
@@ -0,0 +1,5 @@
1
+ import { Lens } from './lens';
2
+
3
+ export function set(lensObj: Lens, value: any, obj: any) {
4
+ return lensObj.set(value, obj);
5
+ }
@@ -0,0 +1,16 @@
1
+ export function getDeep(obj: any, keys: string[]) {
2
+ return keys.reduce((acc, key) => acc?.[key], obj);
3
+ }
4
+
5
+ export function setDeep(obj: any, keys: string[], value: any): any {
6
+ if (keys.length === 0) return value;
7
+
8
+ const [first, ...rest] = keys;
9
+
10
+ return {
11
+ ...obj,
12
+ [first]: rest.length
13
+ ? setDeep(obj?.[first] ?? {}, rest, value)
14
+ : value
15
+ };
16
+ }
@@ -0,0 +1,5 @@
1
+ import { Lens } from './lens';
2
+
3
+ export function view(lensObj: Lens, obj: any) {
4
+ return lensObj.get(obj);
5
+ }
@@ -0,0 +1,12 @@
1
+ export function findByKeyValue<T>(
2
+ arr: T[],
3
+ key: keyof T,
4
+ value: any
5
+ ): T | undefined {
6
+ for (let i = 0; i < arr.length; i++) {
7
+ if (arr[i][key] === value) {
8
+ return arr[i];
9
+ }
10
+ }
11
+ return undefined;
12
+ }
@@ -0,0 +1,11 @@
1
+ export function findByPredicate<T>(
2
+ arr: T[],
3
+ fn: (value: T, index: number, arr: T[]) => boolean
4
+ ): T | undefined {
5
+ for (let i = 0; i < arr.length; i++) {
6
+ if (fn(arr[i], i, arr)) {
7
+ return arr[i];
8
+ }
9
+ }
10
+ return undefined;
11
+ }
package/src/index.ts ADDED
@@ -0,0 +1,15 @@
1
+ export { map } from "./Foundation/foundation/map";
2
+ export { filter } from "./Foundation/foundation/filter";
3
+ export { reduce } from "./Foundation/foundation/reduce";
4
+ export { reduceRight } from "./Foundation/foundation/reduceright";
5
+ export { some } from "./Foundation/foundation/some";
6
+ export { every } from "./Foundation/foundation/every";
7
+
8
+ export { findByPredicate } from "./Search/findByPredicate";
9
+ export { findByKeyValue } from "./Search/findByKeyValue";
10
+
11
+ export { pluck } from "./Extraction/pluck";
12
+
13
+ export { lens } from "./Lens/lens";
14
+ export { view } from "./Lens/view";
15
+ export { set } from "./Lens/set";
@@ -0,0 +1,40 @@
1
+ import { every } from "../src/Foundation/foundation/every";
2
+
3
+ describe("every", () => {
4
+ test("returns true if all elements satisfy condition", () => {
5
+ const result = every((x) => x > 0, [1, 2, 3, 4]);
6
+ expect(result).toBe(true);
7
+ });
8
+
9
+ test("returns false if any element fails condition", () => {
10
+ const result = every((x) => x > 0, [1, -2, 3]);
11
+ expect(result).toBe(false);
12
+ });
13
+
14
+ test("works with objects (all true)", () => {
15
+ const users = [
16
+ { active: true },
17
+ { active: true },
18
+ { active: true }
19
+ ];
20
+
21
+ const result = every((u) => u.active === true, users);
22
+ expect(result).toBe(true);
23
+ });
24
+
25
+ test("works with objects (one false)", () => {
26
+ const users = [
27
+ { active: true },
28
+ { active: false },
29
+ { active: true }
30
+ ];
31
+
32
+ const result = every((u) => u.active === true, users);
33
+ expect(result).toBe(false);
34
+ });
35
+
36
+ test("empty array returns true (JS behavior)", () => {
37
+ const result = every((x) => x > 0, []);
38
+ expect(result).toBe(true);
39
+ });
40
+ });
@@ -0,0 +1,45 @@
1
+
2
+ import { filter } from "../src/Foundation/foundation/filter";
3
+
4
+ describe("filter()", () => {
5
+
6
+ test("filters values correctly", () => {
7
+
8
+ const arr = [1, 2, 3, 4];
9
+
10
+ const result = filter(x => x > 2, arr);
11
+
12
+ expect(result).toEqual([3, 4]);
13
+
14
+ });
15
+
16
+ test("returns empty array if no match", () => {
17
+
18
+ const arr = [1, 2];
19
+
20
+ const result = filter(x => x > 5, arr);
21
+
22
+ expect(result).toEqual([]);
23
+
24
+ });
25
+
26
+ test("handles empty array", () => {
27
+
28
+ expect(filter(x => x, [])).toEqual([]);
29
+
30
+ });
31
+
32
+ test("does not mutate original array", () => {
33
+
34
+ const arr = [1, 2, 3];
35
+
36
+ const copy = [...arr];
37
+
38
+ filter(x => x > 1, arr);
39
+
40
+ expect(arr).toEqual(copy);
41
+
42
+ });
43
+
44
+ });
45
+
@@ -0,0 +1,29 @@
1
+ import { findByKeyValue } from "../src/Search/findByKeyValue";
2
+
3
+ describe("findByKeyValue", () => {
4
+ const users = [
5
+ { id: 1, username: "vishnu_dev", active: true },
6
+ { id: 2, username: "john_doe", active: false },
7
+ { id: 3, username: "alice", active: true }
8
+ ];
9
+
10
+ test("finds user by username", () => {
11
+ const result = findByKeyValue(users, "username", "john_doe");
12
+ expect(result).toEqual({ id: 2, username: "john_doe", active: false });
13
+ });
14
+
15
+ test("finds user by id", () => {
16
+ const result = findByKeyValue(users, "id", 3);
17
+ expect(result).toEqual({ id: 3, username: "alice", active: true });
18
+ });
19
+
20
+ test("returns undefined if key-value not found", () => {
21
+ const result = findByKeyValue(users, "username", "not_exist");
22
+ expect(result).toBeUndefined();
23
+ });
24
+
25
+ test("works with empty array", () => {
26
+ const result = findByKeyValue([], "id", 1);
27
+ expect(result).toBeUndefined();
28
+ });
29
+ });
@@ -0,0 +1,29 @@
1
+ import { findByPredicate } from "../src/Search/findByPredicate";
2
+
3
+ describe("findByPredicate", () => {
4
+ const users = [
5
+ { id: 1, username: "vishnu_dev", active: true },
6
+ { id: 2, username: "john_doe", active: false },
7
+ { id: 3, username: "alice", active: true }
8
+ ];
9
+
10
+ test("finds user by predicate match", () => {
11
+ const result = findByPredicate(users, (u) => u.id === 1);
12
+ expect(result).toEqual({ id: 1, username: "vishnu_dev", active: true });
13
+ });
14
+
15
+ test("returns undefined if no match", () => {
16
+ const result = findByPredicate(users, (u) => u.id === 999);
17
+ expect(result).toBeUndefined();
18
+ });
19
+
20
+ test("finds first active user", () => {
21
+ const result = findByPredicate(users, (u) => u.active === true);
22
+ expect(result).toEqual({ id: 1, username: "vishnu_dev", active: true });
23
+ });
24
+
25
+ test("works with empty array", () => {
26
+ const result = findByPredicate([], (u: any) => u.id === 1);
27
+ expect(result).toBeUndefined();
28
+ });
29
+ });
@@ -0,0 +1,99 @@
1
+ // test/lens.test.ts
2
+
3
+ import { lens } from '../src/Lens/lens';
4
+ import { view } from '../src/Lens/view';
5
+ import { set } from '../src/Lens/set';
6
+
7
+ describe('Lens (split modules)', () => {
8
+ const user = {
9
+ id: 1,
10
+ profile: {
11
+ settings: {
12
+ theme: 'light'
13
+ }
14
+ }
15
+ };
16
+
17
+ /* ------------------ VIEW ------------------ */
18
+
19
+ it('should view deep value', () => {
20
+ const l = lens('profile.settings.theme');
21
+
22
+ expect(view(l, user)).toBe('light');
23
+ });
24
+
25
+ it('should return undefined for missing path', () => {
26
+ const l = lens('profile.settings.lang');
27
+
28
+ expect(view(l, user)).toBeUndefined();
29
+ });
30
+
31
+ it('should handle null safely', () => {
32
+ const l = lens('a.b.c');
33
+
34
+ // @ts-ignore
35
+ expect(view(l, null)).toBeUndefined();
36
+ });
37
+
38
+ /* ------------------ SET ------------------ */
39
+
40
+ it('should update value immutably', () => {
41
+ const l = lens('profile.settings.theme');
42
+
43
+ const updated = set(l, 'dark', user);
44
+
45
+ expect(updated.profile.settings.theme).toBe('dark');
46
+ expect(user.profile.settings.theme).toBe('light'); // unchanged
47
+ });
48
+
49
+ it('should create missing path', () => {
50
+ const l = lens('profile.preferences.language');
51
+
52
+ const updated = set(l, 'en', user);
53
+
54
+ expect(updated.profile.preferences.language).toBe('en');
55
+ });
56
+
57
+ it('should not mutate original object', () => {
58
+ const copy = JSON.parse(JSON.stringify(user));
59
+
60
+ const l = lens('profile.settings.theme');
61
+ set(l, 'dark', user);
62
+
63
+ expect(user).toEqual(copy);
64
+ });
65
+
66
+ it('should preserve other fields', () => {
67
+ const l = lens('profile.settings.theme');
68
+
69
+ const updated = set(l, 'dark', user);
70
+
71
+ expect(updated.id).toBe(1);
72
+ });
73
+
74
+ it('should work with empty object', () => {
75
+ const l = lens('a.b.c');
76
+
77
+ const result = set(l, 10, {});
78
+
79
+ expect(result).toEqual({
80
+ a: { b: { c: 10 } }
81
+ });
82
+ });
83
+
84
+ /* ------------------ EMPTY PATH ------------------ */
85
+
86
+ it('should replace entire object when path is empty', () => {
87
+ const l = lens('');
88
+
89
+ const result = set(l, { x: 1 }, { a: 1 });
90
+
91
+ expect(result).toEqual({ x: 1 });
92
+ });
93
+
94
+ it('should return entire object on view when path is empty', () => {
95
+ const l = lens('');
96
+
97
+ expect(view(l, user)).toEqual(user);
98
+ });
99
+ });
@@ -0,0 +1,38 @@
1
+ import { map } from "../src/Foundation/foundation/map";
2
+
3
+ describe("map()", () => {
4
+
5
+ test("transforms values correctly", () => {
6
+ const arr = [1, 2, 3, 4];
7
+
8
+ const result = map(x => x * 2, arr);
9
+
10
+ expect(result).toEqual([2, 4, 6, 8]);
11
+ });
12
+
13
+ test("returns empty array if input is empty", () => {
14
+ const arr: number[] = [];
15
+
16
+ const result = map(x => x * 2, arr);
17
+
18
+ expect(result).toEqual([]);
19
+ });
20
+
21
+ test("does not mutate original array", () => {
22
+ const arr = [1, 2, 3];
23
+ const copy = [...arr];
24
+
25
+ map(x => x * 2, arr);
26
+
27
+ expect(arr).toEqual(copy);
28
+ });
29
+
30
+ test("passes index correctly", () => {
31
+ const arr = [10, 20, 30];
32
+
33
+ const result = map((x, i) => i, arr);
34
+
35
+ expect(result).toEqual([0, 1, 2]);
36
+ });
37
+
38
+ });
@@ -0,0 +1,87 @@
1
+ // test/pluck.test.ts
2
+
3
+ import { pluck } from '../src/Extraction/pluck';
4
+
5
+ describe('pluck utility', () => {
6
+ const data = [
7
+ { id: 1, info: { email: 'v@test.com' }, tags: ['dev'] },
8
+ { id: 2, info: { email: 'a@test.com' }, tags: ['hr'] }
9
+ ];
10
+
11
+ /* ------------------ Simple Property ------------------ */
12
+
13
+ it('should extract simple property', () => {
14
+ const result = pluck('id', data);
15
+ expect(result).toEqual([1, 2]);
16
+ });
17
+
18
+ /* ------------------ Deep Path ------------------ */
19
+
20
+ it('should extract deep path using dot notation', () => {
21
+ const result = pluck('info.email', data);
22
+ expect(result).toEqual(['v@test.com', 'a@test.com']);
23
+ });
24
+
25
+ /* ------------------ Multi Key ------------------ */
26
+
27
+ it('should extract multiple keys', () => {
28
+ const result = pluck(['id', 'tags'], data);
29
+
30
+ expect(result).toEqual([
31
+ { id: 1, tags: ['dev'] },
32
+ { id: 2, tags: ['hr'] }
33
+ ]);
34
+ });
35
+
36
+ /* ------------------ Edge Cases ------------------ */
37
+
38
+ it('should return empty array for empty input', () => {
39
+ expect(pluck('id', [])).toEqual([]);
40
+ });
41
+
42
+ it('should handle null/undefined safely', () => {
43
+ // @ts-ignore
44
+ expect(pluck('id', null)).toEqual([]);
45
+ // @ts-ignore
46
+ expect(pluck('id', undefined)).toEqual([]);
47
+ });
48
+
49
+ it('should handle missing keys gracefully', () => {
50
+ const result = pluck('nonexistent', data);
51
+ expect(result).toEqual([undefined, undefined]);
52
+ });
53
+
54
+ it('should handle deep missing paths', () => {
55
+ const result = pluck('info.phone.number', data);
56
+ expect(result).toEqual([undefined, undefined]);
57
+ });
58
+
59
+ it('should handle multi-pick with missing keys', () => {
60
+ const result = pluck(['id', 'missing'], data);
61
+
62
+ expect(result).toEqual([
63
+ { id: 1, missing: undefined },
64
+ { id: 2, missing: undefined }
65
+ ]);
66
+ });
67
+
68
+ /* ------------------ Immutability ------------------ */
69
+
70
+ it('should not mutate original data (simple)', () => {
71
+ const copy = JSON.parse(JSON.stringify(data));
72
+ pluck('id', data);
73
+ expect(data).toEqual(copy);
74
+ });
75
+
76
+ it('should not mutate original data (deep)', () => {
77
+ const copy = JSON.parse(JSON.stringify(data));
78
+ pluck('info.email', data);
79
+ expect(data).toEqual(copy);
80
+ });
81
+
82
+ it('should not mutate original data (multi)', () => {
83
+ const copy = JSON.parse(JSON.stringify(data));
84
+ pluck(['id', 'tags'], data);
85
+ expect(data).toEqual(copy);
86
+ });
87
+ });
@@ -0,0 +1,25 @@
1
+ import { reduce } from "../src/Foundation/foundation/reduce";
2
+
3
+
4
+ describe("reduce", () => {
5
+ test("sum of numbers", () => {
6
+ const result = reduce((acc, val) => acc + val, 0, [1, 2, 3, 4]);
7
+ expect(result).toBe(10);
8
+ });
9
+
10
+ test("subtract left to right", () => {
11
+ const result = reduce((acc, val) => acc - val, 100, [10, 5]);
12
+ // (100 - 10) - 5 = 85
13
+ expect(result).toBe(85);
14
+ });
15
+
16
+ test("empty array returns initial value", () => {
17
+ const result = reduce((acc, val) => acc + val, 10, []);
18
+ expect(result).toBe(10);
19
+ });
20
+
21
+ test("works with strings", () => {
22
+ const result = reduce((acc, val) => acc + val, "", ["a", "b", "c"]);
23
+ expect(result).toBe("abc");
24
+ });
25
+ });
@@ -0,0 +1,25 @@
1
+ import { reduceRight } from "../src/Foundation/foundation/reduceright";
2
+
3
+
4
+ describe("reduceRight", () => {
5
+ test("subtract right to left", () => {
6
+ const result = reduceRight((acc, val) => acc - val, 100, [10, 5]);
7
+ // (100 - 5) - 10 = 85
8
+ expect(result).toBe(85);
9
+ });
10
+
11
+ test("concatenation right to left", () => {
12
+ const result = reduceRight((acc, val) => acc + val, "", ["a", "b", "c"]);
13
+ expect(result).toBe("cba");
14
+ });
15
+
16
+ test("single element array", () => {
17
+ const result = reduceRight((acc, val) => acc + val, 10, [5]);
18
+ expect(result).toBe(15);
19
+ });
20
+
21
+ test("empty array returns initial value", () => {
22
+ const result = reduceRight((acc, val) => acc + val, 0, []);
23
+ expect(result).toBe(0);
24
+ });
25
+ });
@@ -0,0 +1,24 @@
1
+ import { some } from "../src/Foundation/foundation/some";
2
+
3
+ describe("some", () => {
4
+ test("returns true if any element matches condition", () => {
5
+ const users = [
6
+ { role: "user" },
7
+ { role: "admin" },
8
+ { role: "guest" }
9
+ ];
10
+
11
+ const result = some((u) => u.role === "admin", users);
12
+ expect(result).toBe(true);
13
+ });
14
+
15
+ test("returns false if no element matches", () => {
16
+ const result = some((x) => x > 10, [1, 2, 3]);
17
+ expect(result).toBe(false);
18
+ });
19
+
20
+ test("empty array returns false", () => {
21
+ const result = some((x) => x > 0, []);
22
+ expect(result).toBe(false);
23
+ });
24
+ });
package/tsconfig.json ADDED
@@ -0,0 +1,14 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "ES2020",
4
+ "module": "NodeNext",
5
+ "moduleResolution": "NodeNext",
6
+ "outDir": "dist",
7
+ "rootDir": "src",
8
+ "strict": true,
9
+ "esModuleInterop": true,
10
+ "skipLibCheck": true,
11
+ "types": ["jest"]
12
+ },
13
+ "include": ["src"]
14
+ }