Skip to content

Commit

Permalink
add 3rd party helpers (no deps)
Browse files Browse the repository at this point in the history
  • Loading branch information
ogroppo committed Feb 5, 2024
1 parent 047990b commit 32d7b99
Show file tree
Hide file tree
Showing 21 changed files with 188 additions and 17 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,11 @@
# deverything

## 0.43.0

### Minor Changes

- add 3rd party helpers (no deps)

## 0.42.2

### Patch Changes
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "deverything",
"version": "0.42.2",
"version": "0.43.0",
"description": "Everything you need for Dev",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
Expand Down
21 changes: 21 additions & 0 deletions src/helpers/cyclicalItem.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
import { describe, expect, test } from "@jest/globals";
import { cyclicalItem } from "./cyclicalItem";

describe("cyclicalItem", () => {
test("works", async () => {
expect(cyclicalItem([], 0)).toBe(undefined);
expect(cyclicalItem([], 1)).toBe(undefined);
});

test("works", async () => {
expect(cyclicalItem([1], 0)).toBe(1);
expect(cyclicalItem([1], 1)).toBe(1);
});

test("works", async () => {
expect(cyclicalItem([1, 2, 3], 0)).toBe(1);
expect(cyclicalItem([1, 2, 3], 2)).toBe(3);
expect(cyclicalItem([1, 2, 3], 3)).toBe(1);
expect(cyclicalItem([1, 2, 3], 30)).toBe(1);
});
});
6 changes: 6 additions & 0 deletions src/helpers/cyclicalItem.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
/**
* @returns element from array at index, if index is greater than array length, it will loop back to the start of the array
*/
export const cyclicalItem = <T>(array: T[], index: number): T => {
return array[index % array.length];
};
5 changes: 3 additions & 2 deletions src/helpers/firstKey.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import { PlainObject } from "../types";
import { ObjectKey, PlainObject } from "../types";
import { getKeys } from "./getKeys";

export const firstKey = (arg: PlainObject): string => getKeys(arg)[0];
export const firstKey = <T extends PlainObject>(arg: T): ObjectKey<T> =>
getKeys(arg)[0];
5 changes: 3 additions & 2 deletions src/helpers/firstValue.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { PlainObject } from "../types";
import { ObjectValue, PlainObject } from "../types";

export const firstValue = (arg: PlainObject): any => Object.values(arg)[0];
export const firstValue = <T extends PlainObject>(arg: T): ObjectValue<T> =>
Object.values(arg)[0];
8 changes: 2 additions & 6 deletions src/helpers/getKeys.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,12 @@ import { describe, expect, test } from "@jest/globals";
import { getKeys } from "./getKeys";

describe("getKeys", () => {
test("{}", async () => {
test("constructors", async () => {
expect(getKeys(new Date())).toStrictEqual([]);
expect(getKeys(Date)).toStrictEqual([]);
expect(getKeys(Function)).toStrictEqual([]);
expect(getKeys(new Function())).toStrictEqual([]);
expect(getKeys(new Object())).toStrictEqual([]);
expect(getKeys(new Array())).toStrictEqual([]);
});

test("keys", async () => {
test("objects", async () => {
expect(getKeys({ a: 1, b: 2 })).toStrictEqual(["a", "b"]);
expect(getKeys({ [Symbol.for("1")]: 1, b: 2 })).toStrictEqual([
"b",
Expand Down
12 changes: 7 additions & 5 deletions src/helpers/getKeys.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
export const getKeys = (arg: object) => {
return Object.keys(arg).concat(getEnumerableOwnPropertySymbols(arg));
import { ObjectKeys, PlainObject } from "../types";

export const getKeys = <T extends PlainObject>(obj: T): ObjectKeys<T> => {
return Object.keys(obj).concat(getEnumerableOwnPropertySymbols(obj));
};

// Object.keys does not return enumerable symbols
export const getEnumerableOwnPropertySymbols = (arg: object): any[] => {
export const getEnumerableOwnPropertySymbols = (obj: object): any[] => {
return Object.getOwnPropertySymbols
? Object.getOwnPropertySymbols(arg).filter(function (symbol) {
return Object.propertyIsEnumerable.call(arg, symbol);
? Object.getOwnPropertySymbols(obj).filter(function (symbol) {
return Object.propertyIsEnumerable.call(obj, symbol);
})
: [];
};
2 changes: 2 additions & 0 deletions src/helpers/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ export * from "./arrayIntersection";
export * from "./capitalize";
export * from "./clamp";
export * from "./cleanSpaces";
export * from "./cyclicalItem";
export * from "./dir";
export * from "./enumKeys";
export * from "./enumValues";
Expand All @@ -18,6 +19,7 @@ export * from "./keysLength";
export * from "./last";
export * from "./lastIndex";
export * from "./merge";
export * from "./mergeArrays";
export * from "./moveToFirst";
export * from "./moveToLast";
export * from "./normalizeNumber";
Expand Down
13 changes: 13 additions & 0 deletions src/helpers/mergeArrays.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { describe, expect, test } from "@jest/globals";
import { mergeArrays } from "./mergeArrays";

describe("mergeArrays", () => {
test("array", async () => {
expect(mergeArrays([], [])).toStrictEqual([]);
expect(mergeArrays([1, 2, 3], [1])).toStrictEqual([1, 2, 3]);
expect(mergeArrays([1, 2, 3, 3], [1, 3])).toStrictEqual([1, 2, 3, 3]);
expect(mergeArrays([1, 2, 3, 3], [1, 3, 4, 4])).toStrictEqual([
1, 2, 3, 3, 4, 4,
]);
});
});
11 changes: 11 additions & 0 deletions src/helpers/mergeArrays.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* @description Merge two arrays, unique values, no options
* @example mergeArrays([1,2,3], [2,3,4]) => [1,2,3,4]
*/
export const mergeArrays = (arrayA: any[], arrayB: any[]) => {
return arrayA.concat(
arrayB.filter((item) => {
return !arrayA.includes(item); // TODO: use isSame for objects
})
);
};
4 changes: 3 additions & 1 deletion src/index.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
export * from "./checks";
export * from "./formatters";
export * from "./helpers";
export * from "./math";
export * from "./prisma";
export * from "./random";
export * from "./trpc";
export * from "./types";
export * from "./validators";
export * from "./formatters";
1 change: 1 addition & 0 deletions src/math/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,5 @@ export * from "./average";
export * from "./max";
export * from "./min";
export * from "./multiply";
export * from "./percentageChange";
export * from "./sum";
31 changes: 31 additions & 0 deletions src/math/percentageChange.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
import { describe, expect, test } from "@jest/globals";
import { percentageChange } from "./percentageChange";

describe("percentageChange", () => {
test("simple", async () => {
expect(
percentageChange({
current: 10,
previous: 12,
})
).toBe(-16.67);
expect(
percentageChange({
current: 0,
previous: 12,
})
).toBe(0);
expect(
percentageChange({
current: 0,
previous: 0,
})
).toBe(0);
expect(
percentageChange({
current: 99,
previous: 0,
})
).toBe(0);
});
});
16 changes: 16 additions & 0 deletions src/math/percentageChange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { isPositiveInt } from "../validators";

export const percentageChange = ({
previous,
current,
}: {
previous: number;
current: number;
}): number => {
if (!isPositiveInt(previous) || !isPositiveInt(current)) return 0;
if (current === 0 && previous === 0) return 0;
if (current === 0 && previous !== 0) return -100;
if (current !== 0 && previous === 0) return 100;
const perChange = ((current - previous) * 100) / previous;
return parseFloat(perChange.toFixed(2));
};
18 changes: 18 additions & 0 deletions src/prisma/checkIsPrismaRefMissingError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
/**
* Useful for no-op queries where you want to make sure the error is a unique constraint error.
* @example
* try {
* await query();
* } catch (e) {
* checkIsPrismaUniqueConstraintError(e);
* // carry on with other stuff, it is a unique constraint error
* }
* @link https://www.prisma.io/docs/concepts/components/prisma-client/handling-exceptions-and-errors
* @link https://www.prisma.io/docs/reference/api-reference/error-reference#p2002
*/
export const checkIsPrismaRefMissingError = (error: Error) => {
if (!isPrismaRefMissingError(error)) throw error;
};

export const isPrismaRefMissingError = (error: Error & { code?: string }) =>
error.code === "P2025";
19 changes: 19 additions & 0 deletions src/prisma/checkIsPrismaUniqueConstraintError.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
/**
* Useful for no-op queries where you want to make sure the error is a unique constraint error.
* @example
* try {
* await query();
* } catch (e) {
* checkIsPrismaUniqueConstraintError(e);
* // carry on with other stuff, it is a unique constraint error
* }
* @link https://www.prisma.io/docs/concepts/components/prisma-client/handling-exceptions-and-errors
* @link https://www.prisma.io/docs/reference/api-reference/error-reference#p2002
*/
export const checkIsPrismaUniqueConstraintError = (error: Error) => {
if (!isPrismaUniqueConstraintError(error)) throw error;
};

export const isPrismaUniqueConstraintError = (
error: Error & { code?: string }
) => error.code === "P2002";
1 change: 1 addition & 0 deletions src/prisma/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./prismaDateRange";
16 changes: 16 additions & 0 deletions src/prisma/prismaDateRange.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { parseDate } from "../helpers/parseDate";
import { DateRange } from "../types/Date";

export const prismaDateRange = ({ startDate, endDate }: DateRange) => {
const gte = parseDate(startDate);
const lt = parseDate(endDate);

if (!gte || !lt) {
throw new Error("prismaDateRange: Invalid date range");
}

return {
gte,
lt,
};
};
7 changes: 7 additions & 0 deletions src/trpc/formatTrpcInputQueryString.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
import { PlainObject } from "../types";

export const formatTrpcInputQueryString = (input: PlainObject) => {
return new URLSearchParams({
input: JSON.stringify(input),
});
};
1 change: 1 addition & 0 deletions src/trpc/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from "./formatTrpcInputQueryString";

0 comments on commit 32d7b99

Please sign in to comment.