Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
23 changes: 23 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@ Returns an array of property names that are functions or methods.
### `isEmpty(value)`
Checks if a value is considered empty (undefined, null, or empty string).

### `isClassOrSubclassOf(childClass, parentClass)`
Checks if one class is the same as or a subclass of another class.

---

## 🚀 Examples
Expand Down Expand Up @@ -79,6 +82,26 @@ const dataOnly = omit(employee, ['id', ...methods(employee)]);
const cleanData = pick(employee, properties(employee));
// Result: { id: 1, name: 'John', department: 'Engineering' }
```

### Class Inheritance Checking

```ts
import { isClassOrSubclassOf } from '@agape/util';

class Animal {}
class Dog extends Animal {}
class Cat extends Animal {}
class Vehicle {}
class Car extends Vehicle {}
class SportsCar extends Car {}

// Check class relationships
isClassOrSubclassOf(Dog, Animal); // true
isClassOrSubclassOf(Cat, Animal); // true
isClassOrSubclassOf(Animal, Animal); // true (same class)
isClassOrSubclassOf(Animal, Dog); // false
isClassOrSubclassOf(SportsCar, Vehicle); // true (indirect inheritance)
```
---

## 📚 Documentation
Expand Down
7 changes: 4 additions & 3 deletions package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@agape/util",
"version": "0.1.1",
"version": "0.2.0",
"description": "util management utilities with global state",
"main": "./cjs/index.js",
"module": "./es2020/index.js",
Expand All @@ -20,8 +20,9 @@
"keywords": [
"agape",
"util",
"i18n",
"internationalization"
"pick",
"omit",
"object"
],
"es2020": "./es2020/index.js",
"exports": {
Expand Down
307 changes: 1 addition & 306 deletions src/index.spec.ts
Original file line number Diff line number Diff line change
@@ -1,199 +1,5 @@
/* eslint-disable @typescript-eslint/no-explicit-any */
import { isEmpty, omit, pick, properties, methods } from './index';

describe('isEmpty', () => {
it('should return true for undefined', () => {
expect(isEmpty(undefined)).toBe(true);
});

it('should return true for null', () => {
expect(isEmpty(null)).toBe(true);
});

it('should return true for empty string', () => {
expect(isEmpty('')).toBe(true);
});

it('should return false for non-empty string', () => {
expect(isEmpty('hello')).toBe(false);
});

it('should return false for zero', () => {
expect(isEmpty(0)).toBe(false);
});

it('should return false for false boolean', () => {
expect(isEmpty(false)).toBe(false);
});

it('should return false for empty array', () => {
expect(isEmpty([])).toBe(false);
});

it('should return false for empty object', () => {
expect(isEmpty({})).toBe(false);
});

it('should return false for whitespace string', () => {
expect(isEmpty(' ')).toBe(false);
});
});

describe('omit', () => {
const testObject = {
id: 1,
name: 'John',
email: 'john@example.com',
password: 'secret',
age: 30,
city: 'New York'
};

it('should omit single property', () => {
const result = omit(testObject, ['password']);
expect(result).toEqual({
id: 1,
name: 'John',
email: 'john@example.com',
age: 30,
city: 'New York'
});
expect(result).not.toHaveProperty('password');
});

it('should omit multiple properties', () => {
const result = omit(testObject, ['password', 'email', 'age']);
expect(result).toEqual({
id: 1,
name: 'John',
city: 'New York'
});
expect(result).not.toHaveProperty('password');
expect(result).not.toHaveProperty('email');
expect(result).not.toHaveProperty('age');
});

it('should return same object when no properties to omit', () => {
const result = omit(testObject, []);
expect(result).toEqual(testObject);
});

it('should handle non-existent properties gracefully', () => {
const result = omit(testObject, ['nonExistent' as keyof typeof testObject]);
expect(result).toEqual(testObject);
});

it('should handle dynamic array', () => {
const keysToOmit: (keyof typeof testObject)[] = ['password', 'email'];
const result = omit(testObject, keysToOmit);
expect(result).toEqual({
id: 1,
name: 'John',
age: 30,
city: 'New York'
});
});

it('should handle empty object', () => {
const result = omit({} as any, ['anyKey']);
expect(result).toEqual({});
});

it('should handle object with undefined values', () => {
const obj = { a: 1, b: undefined, c: 3 };
const result = omit(obj, ['b']);
expect(result).toEqual({ a: 1, c: 3 });
});

it('should handle object with null values', () => {
const obj = { a: 1, b: null, c: 3 };
const result = omit(obj, ['b']);
expect(result).toEqual({ a: 1, c: 3 });
});

it('should preserve original object', () => {
const original = { ...testObject };
omit(testObject, ['password']);
expect(testObject).toEqual(original);
});
});

describe('pick', () => {
const testObject = {
id: 1,
name: 'John',
email: 'john@example.com',
password: 'secret',
age: 30,
city: 'New York'
};

it('should pick single property', () => {
const result = pick(testObject, ['name']);
expect(result).toEqual({ name: 'John' });
});

it('should pick multiple properties', () => {
const result = pick(testObject, ['id', 'name', 'email']);
expect(result).toEqual({
id: 1,
name: 'John',
email: 'john@example.com'
});
});

it('should return empty object when no properties specified', () => {
const result = pick(testObject, []);
expect(result).toEqual({});
});

it('should handle non-existent properties gracefully', () => {
const result = pick(testObject, ['nonExistent' as keyof typeof testObject]);
expect(result).toEqual({});
});

it('should handle duplicate properties (last wins)', () => {
const result = pick(testObject, ['name', 'name', 'name']);
expect(result).toEqual({ name: 'John' });
});

it('should handle dynamic array', () => {
const keysToPick: (keyof typeof testObject)[] = ['id', 'name'];
const result = pick(testObject, keysToPick);
expect(result).toEqual({
id: 1,
name: 'John'
});
});

it('should handle empty object', () => {
const result = pick({} as any, ['anyKey']);
expect(result).toEqual({});
});

it('should handle object with undefined values', () => {
const obj = { a: 1, b: undefined, c: 3 };
const result = pick(obj, ['b']);
expect(result).toEqual({ b: undefined });
});

it('should handle object with null values', () => {
const obj = { a: 1, b: null, c: 3 };
const result = pick(obj, ['b']);
expect(result).toEqual({ b: null });
});

it('should preserve original object', () => {
const original = { ...testObject };
pick(testObject, ['name']);
expect(testObject).toEqual(original);
});

it('should handle all properties', () => {
const result = pick(testObject, ['id', 'name', 'email', 'password', 'age', 'city']);
expect(result).toEqual(testObject);
});
});
import { omit, pick, properties, methods } from './index';

describe('TypeScript type safety', () => {
interface User {
Expand Down Expand Up @@ -241,117 +47,6 @@ describe('TypeScript type safety', () => {
});
});

describe('properties', () => {
it('should return only non-function properties', () => {
const obj = {
id: 1,
name: 'John',
getFullName() { return this.name; },
calculateSalary() { return 50000; },
age: 30
};

const result = properties(obj);
expect(result).toEqual(['id', 'name', 'age']);
});

it('should return empty array for object with only methods', () => {
const obj = {
method1() { return 'test'; },
method2() { return 42; }
};

const result = properties(obj);
expect(result).toEqual([]);
});

it('should return all properties for object with no methods', () => {
const obj = {
id: 1,
name: 'John',
age: 30
};

const result = properties(obj);
expect(result).toEqual(['id', 'name', 'age']);
});

it('should handle empty object', () => {
const result = properties({});
expect(result).toEqual([]);
});

it('should handle object with mixed property types', () => {
const obj = {
string: 'hello',
number: 42,
boolean: true,
array: [1, 2, 3],
object: { nested: true },
null: null,
undefined: undefined,
method() { return 'test'; },
arrow: () => 'arrow'
};

const result = properties(obj);
expect(result).toEqual(['string', 'number', 'boolean', 'array', 'object', 'null', 'undefined']);
});
});

describe('methods', () => {
it('should return only function properties', () => {
const obj = {
id: 1,
name: 'John',
getFullName() { return this.name; },
calculateSalary() { return 50000; },
age: 30
};

const result = methods(obj);
expect(result).toEqual(['getFullName', 'calculateSalary']);
});

it('should return empty array for object with no methods', () => {
const obj = {
id: 1,
name: 'John',
age: 30
};

const result = methods(obj);
expect(result).toEqual([]);
});

it('should return all methods for object with only methods', () => {
const obj = {
method1() { return 'test'; },
method2() { return 42; }
};

const result = methods(obj);
expect(result).toEqual(['method1', 'method2']);
});

it('should handle empty object', () => {
const result = methods({});
expect(result).toEqual([]);
});

it('should handle arrow functions', () => {
const obj = {
id: 1,
regularMethod() { return 'regular'; },
arrowMethod: () => 'arrow',
notAFunction: 'string'
};

const result = methods(obj);
expect(result).toEqual(['regularMethod', 'arrowMethod']);
});
});

describe('Integration with omit and pick', () => {
const employee = {
id: 1,
Expand Down
Loading