Skip to content

Commit

Permalink
more formatters, types and validators
Browse files Browse the repository at this point in the history
  • Loading branch information
ogroppo committed Feb 19, 2024
1 parent 32d7b99 commit 892c35f
Show file tree
Hide file tree
Showing 19 changed files with 129 additions and 23 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.44.0

### Minor Changes

- randomObject isFile and many more

## 0.43.0

### Minor Changes
Expand Down
18 changes: 12 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@ Contributions always welcome!
- `isArray()`
- `isBoolean()`
- `isBrowser()` to detect if you are on the browser
- `isBuffer()`
- `isClient()` to detect if you are ont the browser/client
- `isEmail()` this is a relaxed check, use your own validation if you need to be strict
-`isEmpty()` to check for empty object, empty array, empty string, null or undefined
- `isEmptyString()` trims the string and checks if something is left
- `isEmptyArray()`
- `isEmptyObject()`
- `isFile()`
- `isFunction()`
- `isJsDate()` if it's a **valid** javascript's Date
- `isFutureDate()`
Expand Down Expand Up @@ -98,6 +100,7 @@ Contributions always welcome!

### Formatters

- `formatCamelCase()`
- `formatNumber()` 1000 => "1,000" or "1K" or 0.112 => "11.2%"
- `stringToUnicode()` "hello" => "\u0068\u0065\u006c\u006c\u006f"
- `stringToCSSUnicode()` "hello" => "\000068\000065\00006c\00006c\00006f" use this for CSS
Expand Down Expand Up @@ -127,6 +130,7 @@ These functions are optimized for low entropy random data generation useful for
- `randomEnumValue()` enum FRUIT { APPLE = 1, PEAR = 3 } => 3
- `randomFile()`
- `randomFloat()`
- `randomObject()`
- `randomHandle()` useful for social identifiers, or slugs
- `randomHexColor()`
- `randomHexValue()`
Expand All @@ -149,6 +153,7 @@ These functions are optimized for low entropy random data generation useful for
- `randomPhoneNumber()`
- `randomString()`
- `randomUUID()` lightweight uuid generation, passing UUID validation
- `randomValue()`
- `randomWord()`

### Checks
Expand All @@ -167,20 +172,21 @@ Checks are functions that throw an error, if the validation fails
- `MaybePromiseOrValue<>`
- `MaybePromiseOrValueArray<>`
- `NonUndefined`
- `Key`
- `ObjectKey<>`
- `ObjectKeys<>`
- `ObjectValue<>`
- `ObjectValues<>`
- `ObjectEntry<>`
- `ObjectEntries<>`
-`PlainObject` use this instead of `Record<,>` or `extends object`, also makes sure it's not an array
- `Point`
- `PrismaSelect<>`
- `HashMap<>`
- `HashMapKey`
- `NumberMap`
- `StringMap`
- `BoolMap`
- `TrueMap`
- `BoolMap`
- `NumberMap`
- `StringMap`
- `TrueMap`
- `VoidFn`

## Development

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.43.0",
"version": "0.44.0",
"description": "Everything you need for Dev",
"main": "./dist/index.js",
"module": "./dist/index.mjs",
Expand Down
7 changes: 7 additions & 0 deletions src/formatters/formatCamelCase.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export const formatCamelCase = (str: string) => {
return str
.toLowerCase()
.replace(/[-_\s]([a-z\d])(\w*)/g, function replacer(_m, p1, p2) {
return p1.toUpperCase() + p2;
});
};
3 changes: 2 additions & 1 deletion src/formatters/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
export * from "./formatCamelCase";
export * from "./formatNumber";
export * from "./stringToUnicode";
export * from "./stringToCSSUnicode";
export * from "./stringToUnicode";
2 changes: 1 addition & 1 deletion src/helpers/serialize.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import { PlainObject } from "../types";

/**
* Serialize plain object to a deterministic string,
* Serialize shallow object to a deterministic string,
* for nested objects use [json-stable-stringify](https://www.npmjs.com/package/json-stable-stringify)
*
* @example
Expand Down
9 changes: 9 additions & 0 deletions src/random/randomObject.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
import { describe, it, expect } from "@jest/globals";
import { keysLength } from "../helpers";
import { randomObject } from "./randomObject";

describe(`randomObject`, () => {
it(`works`, () => {
expect(keysLength(randomObject())).toBeGreaterThan(0);
});
});
19 changes: 19 additions & 0 deletions src/random/randomObject.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import { array } from "../helpers";
import { PlainObject } from "../types";
import { randomInt } from "./randomInt";
import { randomValue } from "./randomValue";
import { randomNoun } from "./randomWord";

export const randomObject = ({ maxDepth = 5 }: { maxDepth?: number } = {}) => {
const getRandomObject = (depth: number): PlainObject => {
if (depth >= maxDepth) return {};

const keys = array(randomInt(1, 5), randomNoun);
return keys.reduce((partial, key) => {
partial[key] = randomValue() || getRandomObject(depth + 1);
return partial;
}, {} as PlainObject);
};

return getRandomObject(0);
};
16 changes: 16 additions & 0 deletions src/random/randomValue.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
import { randomArrayItem } from "./randomArrayItem";
import { randomBool } from "./randomBool";
import { randomDate } from "./randomDate";
import { randomInt } from "./randomInt";
import { randomString } from "./randomString";

export const randomValue = () => {
return randomArrayItem([
randomBool(),
randomString(),
randomInt(),
randomDate(),
undefined,
null,
]);
};
1 change: 1 addition & 0 deletions src/types/Function.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export type VoidFn = () => void;
13 changes: 7 additions & 6 deletions src/types/HashMap.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,8 @@
import { Key } from "./Object";

// I don't like the Dict keyword, but it's a possibility...
export type HashMapKey = string | number | symbol;
export type HashMap<T> = Record<HashMapKey, T>;
export type NumberMap = Record<HashMapKey, number>;
export type StringMap = Record<HashMapKey, string>;
export type BoolMap = Record<HashMapKey, boolean>;
export type TrueMap = Record<HashMapKey, true>;
export type HashMap<T> = Record<Key, T>;
export type NumberMap = Record<Key, number>;
export type StringMap = Record<Key, string>;
export type BoolMap = Record<Key, boolean>;
export type TrueMap = Record<Key, true>;
5 changes: 3 additions & 2 deletions src/types/Object.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
export type Key = string | number | symbol;
export type ObjectKey<T> = keyof T;
export type ObjectKeys<T> = ObjectKey<T>[];
export type ObjectValue<T> = T[keyof T];
export type ObjectValues<T> = ObjectValue<T>[];
// ObjectEntry needed?
export type ObjectEntries<T> = { [K in keyof T]: [K, T[K]] }[keyof T][];
export type ObjectEntry<T> = { [K in keyof T]: [K, T[K]] }[keyof T];
export type ObjectEntries<T> = ObjectEntry<T>[];
10 changes: 9 additions & 1 deletion src/types/PlainObject.ts
Original file line number Diff line number Diff line change
@@ -1 +1,9 @@
export type PlainObject = Record<string | symbol, any> & { length?: never }; // Excludes arrays
import { Key } from "./Object";

/**
* A plain object is an object that is not an array, does not have a length property, and is not a function.
* Would have been nice to call it just Object, but that's already taken by the built-in type.
*/
export type PlainObject<T = any> = Record<Key, T> & {
length?: never;
}; // Excludes arrays
2 changes: 2 additions & 0 deletions src/validators/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,11 @@ export * from "./isArray";
export * from "./isArrayIncluded";
export * from "./isBoolean";
export * from "./isBrowser";
export * from "./isBuffer";
export * from "./isClient";
export * from "./isEmail";
export * from "./isEmpty";
export * from "./isFile";
export * from "./isFunction";
export * from "./isFutureDate";
export * from "./isJsDate";
Expand Down
15 changes: 15 additions & 0 deletions src/validators/isBuffer.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { describe, expect, test } from "@jest/globals";
import { isBuffer } from "./isBuffer";

describe("isBuffer", () => {
test("mixed", async () => {
const buffer = Buffer.from("test");
expect(isBuffer(buffer)).toBe(true);

const arraybuffer = new Uint8Array([1, 2, 3]).buffer;
expect(isBuffer(arraybuffer)).toBe(false);

const notBuffer = { byteLength: 3, slice: () => {} };
expect(isBuffer(notBuffer)).toBe(false);
});
});
11 changes: 11 additions & 0 deletions src/validators/isBuffer.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import { isFunction } from "./isFunction";
import { isValue } from "./isValue";

export const isBuffer = (val?: any): boolean => {
return (
isValue(val) &&
isValue(val.constructor) &&
isFunction(val.constructor.isBuffer) &&
val.constructor.isBuffer(val)
);
};
2 changes: 2 additions & 0 deletions src/validators/isFile.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const isFile = (arg?: any): arg is File =>
Object.prototype.toString.call(arg) === "[object File]";
7 changes: 3 additions & 4 deletions src/validators/isKey.ts
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
export const isKey = <T extends object>(
key: string | number | symbol,
obj: T
): key is keyof T =>
import { Key } from "../types/Object";

export const isKey = <T extends object>(key: Key, obj: T): key is keyof T =>
obj.hasOwnProperty(key) && // makes sure the prop is not in the prototype chain
obj.propertyIsEnumerable(key); // makes sure the prop is not a getter/setter
4 changes: 3 additions & 1 deletion src/validators/isObject.ts
Original file line number Diff line number Diff line change
@@ -1,2 +1,4 @@
export const isObject = <T>(arg?: any): arg is Record<string, T> =>
import { PlainObject } from "../types";

export const isObject = <T>(arg?: any): arg is PlainObject<T> =>
Object.prototype.toString.call(arg) === "[object Object]";

0 comments on commit 892c35f

Please sign in to comment.