Skip to content

Instantly share code, notes, and snippets.

@stevensacks
Created August 22, 2024 10:14
Show Gist options
  • Select an option

  • Save stevensacks/43ff750e8aa55ef81fb7bd0602884a52 to your computer and use it in GitHub Desktop.

Select an option

Save stevensacks/43ff750e8aa55ef81fb7bd0602884a52 to your computer and use it in GitHub Desktop.

Revisions

  1. stevensacks created this gist Aug 22, 2024.
    20 changes: 20 additions & 0 deletions function.test.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,20 @@
    import { describe, expect, test } from 'vitest';
    import { tryCatch } from '../functions';

    describe('functions', () => {
    test('tryCatch success', async () => {
    expect(await tryCatch((value: number) => 10 / value, 5)).toEqual({
    result: 2,
    });
    });

    test('tryCatch error', async () => {
    expect(
    await tryCatch(() => {
    throw new Error('failed');
    })
    ).toEqual({
    error: new Error('failed'),
    });
    });
    });
    108 changes: 108 additions & 0 deletions object.test.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,108 @@

    import {
    convertCase,
    every,
    isNil,
    mapKeys,
    mapValues,
    md5,
    some,
    toCamelCase,
    toKebabCase,
    withValues,
    } from '../object';

    describe('object', () => {
    test('every', () => {
    const predicate = (value: any) => !!value;
    expect(every({}, predicate)).toBe(true);
    expect(every({hello: 'world'}, predicate)).toBe(true);
    expect(every({foo: 0, hello: 'world'}, predicate)).toBe(false);
    });

    test('some', () => {
    const predicate = (value: any) => !!value;
    expect(some({}, predicate)).toBe(false);
    expect(some({foo: 0, hello: 'world'}, predicate)).toBe(true);
    expect(some({hello: 0}, predicate)).toBe(false);
    });

    test('md5', () => {
    expect(md5({a: 'b'})).toBe('92eff9dda44cb8003ee13990782580ff');
    });

    test('isNil', () => {
    expect(isNil(undefined)).toBe(true);
    expect(isNil(null)).toBe(true);
    expect(isNil(1)).toBe(false);
    expect(isNil('foo')).toBe(false);
    expect(isNil({})).toBe(false);
    });

    test('mapKeys', () => {
    expect(mapKeys({bar: 'baz', foo: 'bar'}, (key) => `${key}1`)).toEqual({
    bar1: 'baz',
    foo1: 'bar',
    });
    });

    test('mapValues', () => {
    expect(
    mapValues({bar: 'baz', foo: 'bar'}, (value) => `${value}1`)
    ).toEqual({
    bar: 'baz1',
    foo: 'bar1',
    });
    });

    test('convertCase', () => {
    expect(convertCase((f) => f)).toEqual({});
    const obj = {a: [{b: 'c'}], d: {e: true}};
    expect(convertCase((f) => `${f}${f}`, obj)).toEqual({
    aa: [{bb: 'c'}],
    dd: {ee: true},
    });
    });

    test('toKebabCase', () => {
    expect(
    toKebabCase({
    nestedObject: {
    biz: 'baz',
    fizzBuzz: 5,
    },
    someValue: 'foo',
    })
    ).toEqual({
    'nested-object': {
    biz: 'baz',
    'fizz-buzz': 5,
    },
    'some-value': 'foo',
    });
    });

    test('toCamelCase', () => {
    expect(
    toCamelCase({
    'nested-object': {
    biz: 'baz',
    'fizz-buzz': 5,
    },
    'some-value': 'foo',
    })
    ).toEqual({
    nestedObject: {
    biz: 'baz',
    fizzBuzz: 5,
    },
    someValue: 'foo',
    });
    });

    test('withValues', () => {
    const obj = {a: 'b', c: '', d: false, e: null};
    expect(withValues(obj)).toEqual({a: 'b'});
    expect(withValues(obj, true)).toEqual({a: 'b', c: '', d: false});
    });
    });
    121 changes: 121 additions & 0 deletions object.ts
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,121 @@
    import {camelCase, isObject, snakeCase} from 'lodash';
    import SparkMD5 from 'spark-md5';

    export const every = (
    obj: Record<string, unknown>,
    predicate: (value: unknown) => boolean
    ): boolean => Object.values(obj).every(predicate);

    export const some = (
    obj: Record<string, unknown>,
    predicate: (value: unknown) => boolean
    ): boolean => Object.values(obj).some(predicate);

    export const md5 = (obj: Record<string, unknown>): string =>
    SparkMD5.hash(JSON.stringify(obj));

    export const isNil = (value: unknown): boolean =>
    value === null || value === undefined;

    export const deepRemoveNil = (input: unknown): unknown => {
    if (isNil(input)) {
    return;
    }

    if (Array.isArray(input)) {
    return input
    .filter((value) => !isNil(value))
    .map((value) => deepRemoveNil(value));
    }

    if (isObject(input)) {
    const keys = Object.keys(input);

    return Object.fromEntries(
    keys
    .filter((key) => !isNil((input as Record<string, unknown>)[key]))
    .map((key) => [
    key,
    deepRemoveNil((input as Record<string, unknown>)[key]),
    ])
    );
    }

    return input;
    };

    export const mapKeys = (
    obj: Record<string, unknown>,
    fn: (key: string) => string
    ): Record<string, unknown> =>
    Object.entries(obj).reduce((acc: Record<string, unknown>, [key, value]) => {
    acc[fn(key)] = value;

    return acc;
    }, {});

    export const mapValues = (
    obj: Record<string, unknown>,
    fn: (p: unknown) => unknown
    ): Record<string, unknown> =>
    Object.entries(obj).reduce((acc: Record<string, unknown>, [key, value]) => {
    acc[key] = fn(value);

    return acc;
    }, {});

    export const convertCase = (
    fn: (s: string) => string,
    obj: unknown
    ): unknown => {
    if (obj === undefined) {
    return;
    }

    if (Array.isArray(obj)) {
    return obj.map((value: unknown) => convertCase(fn, value));
    }

    if (isObject(obj)) {
    return Object.entries(obj).reduce(
    (acc: Record<string, unknown>, [key, value]) => {
    if (Array.isArray(value)) {
    acc[fn(key)] = value.map((item) =>
    isObject(item) ? convertCase(fn, item) : item
    );
    } else if (isObject(value)) {
    acc[fn(key)] = convertCase(fn, value);
    } else {
    acc[fn(key)] = value;
    }

    return acc;
    },
    {}
    );
    }

    return obj;
    };

    export const toSnakeCase = <T = unknown>(obj: unknown) =>
    obj ? (convertCase(snakeCase, obj) as T) : undefined;

    export const toCamelCase = <T = unknown>(obj: unknown) =>
    obj ? (convertCase(camelCase, obj) as T) : undefined;

    export const withValues = (
    obj: Record<string, unknown>,
    keepFalsy?: boolean,
    keepEmptyArray?: boolean
    ): Record<string, unknown> =>
    Object.entries(obj).reduce((acc: Record<string, unknown>, [key, value]) => {
    if (
    ((keepFalsy && !isNil(value)) || value) &&
    (!Array.isArray(value) || keepEmptyArray || value.length > 0)
    ) {
    acc[key] = value;
    }

    return acc;
    }, {});