From f092069cc9ff7e21df4eca9f4182a121832dab42 Mon Sep 17 00:00:00 2001 From: Gil Barbara Date: Tue, 17 Oct 2023 23:13:15 -0300 Subject: [PATCH] Refactor exports - modularize code --- README.md | 2 +- package.json | 27 ++++- src/exports.ts | 39 +++++++ src/helpers.ts | 64 ++++++++++++ src/index.ts | 241 ++++++++++++------------------------------- src/types.ts | 8 ++ test/exports.spec.ts | 5 +- vitest.config.ts | 2 + 8 files changed, 210 insertions(+), 178 deletions(-) create mode 100644 src/exports.ts create mode 100644 src/helpers.ts create mode 100644 src/types.ts diff --git a/README.md b/README.md index 9770570..9eaac61 100644 --- a/README.md +++ b/README.md @@ -24,7 +24,7 @@ is.string('value'); // true You can also import any checker individually since 1.0 ```ts -import { isString } from 'is-lite'; +import { isString } from 'is-lite/exports'; isString('value'); // true ``` diff --git a/package.json b/package.json index 4aab0b9..6acd913 100644 --- a/package.json +++ b/package.json @@ -28,12 +28,23 @@ ".": { "import": "./dist/index.mjs", "require": "./dist/index.js" + }, + "./exports": { + "import": "./dist/exports.mjs", + "require": "./dist/exports.js" } }, "files": [ "dist", "src" ], + "typesVersions": { + "*": { + "exports": [ + "dist/exports.d.ts" + ] + } + }, "types": "dist/index.d.ts", "sideEffects": false, "devDependencies": { @@ -72,17 +83,19 @@ "prepare": "husky install" }, "tsup": { + "bundle": true, "cjsInterop": true, "dts": true, "entry": [ - "src/index.ts" + "src/index.ts", + "src/exports.ts" ], "format": [ "cjs", "esm" ], "sourcemap": true, - "splitting": true + "splitting": false }, "eslintConfig": { "extends": [ @@ -100,6 +113,16 @@ "name": "esm", "path": "./dist/index.mjs", "limit": "1.5 kB" + }, + { + "name": "exports-commonjs", + "path": "./dist/exports.js", + "limit": "2 kB" + }, + { + "name": "exports-esm", + "path": "./dist/exports.mjs", + "limit": "2 kB" } ] } diff --git a/src/exports.ts b/src/exports.ts new file mode 100644 index 0000000..baccc4c --- /dev/null +++ b/src/exports.ts @@ -0,0 +1,39 @@ +/* eslint-disable @typescript-eslint/ban-types */ +import is from './index'; + +export const isArray = is.array; +export const isArrayOf = is.arrayOf; +export const isAsyncGeneratorFunction = is.asyncGeneratorFunction; +export const isAsyncFunction = is.asyncFunction; +export const isBigInt = is.bigint; +export const isBoolean = is.boolean; +export const isDate = is.date; +export const isDefined = is.defined; +export const isDomElement = is.domElement; +export const isEmpty = is.empty; +export const isError = is.error; +export const isFunction = is.function; +export const isGenerator = is.generator; +export const isGeneratorFunction = is.generatorFunction; +export const isInstanceOf = is.instanceOf; +export const isIterable = is.iterable; +export const isMap = is.map; +export const isNan = is.nan; +export const isNull = is.null; +export const isNullOrUndefined = is.nullOrUndefined; +export const isNumber = is.number; +export const isNumericString = is.numericString; +export const isObject = is.object; +export const isOneOf = is.oneOf; +export const isPlainFunction = is.plainFunction; +export const isPlainObject = is.plainObject; +export const isPrimitive = is.primitive; +export const isPromise = is.promise; +export const isPropertyOf = is.propertyOf; +export const isRegexp = is.regexp; +export const isSet = is.set; +export const isString = is.string; +export const isSymbol = is.symbol; +export const isUndefined = is.undefined; +export const isWeakMap = is.weakMap; +export const isWeakSet = is.weakSet; diff --git a/src/helpers.ts b/src/helpers.ts new file mode 100644 index 0000000..d1de425 --- /dev/null +++ b/src/helpers.ts @@ -0,0 +1,64 @@ +/* eslint-disable @typescript-eslint/ban-types */ +import type { ObjectTypes, Primitive, PrimitiveTypes } from './types'; + +export const objectTypes = [ + 'Array', + 'ArrayBuffer', + 'AsyncFunction', + 'AsyncGenerator', + 'AsyncGeneratorFunction', + 'Date', + 'Error', + 'Function', + 'Generator', + 'GeneratorFunction', + 'HTMLElement', + 'Map', + 'Object', + 'Promise', + 'RegExp', + 'Set', + 'WeakMap', + 'WeakSet', +] as const; + +export const primitiveTypes = [ + 'bigint', + 'boolean', + 'null', + 'number', + 'string', + 'symbol', + 'undefined', +] as const; + +export function getObjectType(value: unknown): ObjectTypes | undefined { + const objectTypeName = Object.prototype.toString.call(value).slice(8, -1); + + if (/HTML\w+Element/.test(objectTypeName)) { + return 'HTMLElement'; + } + + if (isObjectType(objectTypeName)) { + return objectTypeName; + } + + return undefined; +} + +export function isObjectOfType(type: string) { + return (value: unknown): value is T => getObjectType(value) === type; +} + +export function isObjectType(name: unknown): name is ObjectTypes { + return objectTypes.includes(name as ObjectTypes); +} + +export function isOfType(type: string) { + // eslint-disable-next-line valid-typeof + return (value: unknown): value is T => typeof value === type; +} + +export function isPrimitiveType(name: unknown): name is PrimitiveTypes { + return primitiveTypes.includes(name as PrimitiveTypes); +} diff --git a/src/index.ts b/src/index.ts index ce52b0c..dada09e 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,4 +1,7 @@ /* eslint-disable @typescript-eslint/ban-types */ +import { getObjectType, isObjectOfType, isOfType, isPrimitiveType } from './helpers'; +import type { Class, PlainObject, Primitive, TypeName } from './types'; + const DOM_PROPERTIES_TO_CHECK: Array = [ 'innerHTML', 'ownerDocument', @@ -7,78 +10,48 @@ const DOM_PROPERTIES_TO_CHECK: Array = [ 'nodeValue', ]; -const objectTypes = [ - 'Array', - 'ArrayBuffer', - 'AsyncFunction', - 'AsyncGenerator', - 'AsyncGeneratorFunction', - 'Date', - 'Error', - 'Function', - 'Generator', - 'GeneratorFunction', - 'HTMLElement', - 'Map', - 'Object', - 'Promise', - 'RegExp', - 'Set', - 'WeakMap', - 'WeakSet', -] as const; - -const primitiveTypes = [ - 'bigint', - 'boolean', - 'null', - 'number', - 'string', - 'symbol', - 'undefined', -] as const; - -export type Class = new (...arguments_: any[]) => T; -export type ObjectTypes = (typeof objectTypes)[number]; -export type PlainObject = Record; -export type Primitive = null | undefined | string | number | boolean | symbol | bigint; -export type PrimitiveTypes = (typeof primitiveTypes)[number]; -export type TypeName = ObjectTypes | PrimitiveTypes; - -export function getObjectType(value: unknown): ObjectTypes | undefined { - const objectTypeName = Object.prototype.toString.call(value).slice(8, -1); - - if (/HTML\w+Element/.test(objectTypeName)) { - return 'HTMLElement'; +function is(value: unknown): TypeName { + if (value === null) { + return 'null'; } - if (isObjectType(objectTypeName)) { - return objectTypeName; + switch (typeof value) { + case 'bigint': + return 'bigint'; + case 'boolean': + return 'boolean'; + case 'number': + return 'number'; + case 'string': + return 'string'; + case 'symbol': + return 'symbol'; + case 'undefined': + return 'undefined'; + default: } - return undefined; -} + if (is.array(value)) { + return 'Array'; + } -export function isObjectOfType(type: string) { - return (value: unknown): value is T => getObjectType(value) === type; -} + if (is.plainFunction(value)) { + return 'Function'; + } -export function isObjectType(name: unknown): name is ObjectTypes { - return objectTypes.includes(name as ObjectTypes); -} + const tagType = getObjectType(value); -export function isOfType(type: string) { - // eslint-disable-next-line valid-typeof - return (value: unknown): value is T => typeof value === type; -} + if (tagType) { + return tagType; + } + /* c8 ignore next 3 */ -export function isPrimitiveType(name: unknown): name is PrimitiveTypes { - return primitiveTypes.includes(name as PrimitiveTypes); + return 'Object'; } -export const { isArray } = Array; +is.array = Array.isArray; -export const isArrayOf = (target: unknown[], predicate: (v: unknown) => boolean): boolean => { +is.arrayOf = (target: unknown[], predicate: (v: unknown) => boolean): boolean => { if (!is.array(target) && !is.function(predicate)) { return false; } @@ -86,24 +59,22 @@ export const isArrayOf = (target: unknown[], predicate: (v: unknown) => boolean) return target.every(d => predicate(d)); }; -export const isAsyncGeneratorFunction = ( - value: unknown, -): value is (...arguments_: any[]) => Promise => +is.asyncGeneratorFunction = (value: unknown): value is (...arguments_: any[]) => Promise => getObjectType(value) === 'AsyncGeneratorFunction'; -export const isAsyncFunction = isObjectOfType('AsyncFunction'); +is.asyncFunction = isObjectOfType('AsyncFunction'); -export const isBigInt = isOfType('bigint'); +is.bigint = isOfType('bigint'); -export const isBoolean = (value: unknown): value is boolean => { +is.boolean = (value: unknown): value is boolean => { return value === true || value === false; }; -export const isDate = isObjectOfType('Date'); +is.date = isObjectOfType('Date'); -export const isDefined = (value: unknown): boolean => !is.undefined(value); +is.defined = (value: unknown): boolean => !is.undefined(value); -export const isDomElement = (value: unknown): value is HTMLElement => { +is.domElement = (value: unknown): value is HTMLElement => { return ( is.object(value) && !is.plainObject(value) && @@ -113,7 +84,7 @@ export const isDomElement = (value: unknown): value is HTMLElement => { ); }; -export const isEmpty = (value: unknown): boolean => { +is.empty = (value: unknown): boolean => { return ( (is.string(value) && value.length === 0) || (is.array(value) && value.length === 0) || @@ -123,11 +94,11 @@ export const isEmpty = (value: unknown): boolean => { ); }; -export const isError = isObjectOfType('Error'); +is.error = isObjectOfType('Error'); -export const isFunction = isOfType('function'); +is.function = isOfType('function'); -export const isGenerator = (value: unknown): value is Generator => { +is.generator = (value: unknown): value is Generator => { return ( is.iterable(value) && is.function((value as IterableIterator).next) && @@ -135,9 +106,9 @@ export const isGenerator = (value: unknown): value is Generator => { ); }; -export const isGeneratorFunction = isObjectOfType('GeneratorFunction'); +is.generatorFunction = isObjectOfType('GeneratorFunction'); -export const isInstanceOf = (instance: unknown, class_: Class): instance is T => { +is.instanceOf = (instance: unknown, class_: Class): instance is T => { if (!instance || !(class_ as Class)) { return false; } @@ -145,39 +116,39 @@ export const isInstanceOf = (instance: unknown, class_: Class): instance i return Object.getPrototypeOf(instance) === class_.prototype; }; -export const isIterable = (value: unknown): value is IterableIterator => { +is.iterable = (value: unknown): value is IterableIterator => { return ( !is.nullOrUndefined(value) && is.function((value as IterableIterator)[Symbol.iterator]) ); }; -export const isMap = isObjectOfType>('Map'); +is.map = isObjectOfType>('Map'); -export const isNan = (value: unknown): boolean => { +is.nan = (value: unknown): boolean => { return Number.isNaN(value as number); }; -export const isNull = (value: unknown): value is null => { +is.null = (value: unknown): value is null => { return value === null; }; -export const isNullOrUndefined = (value: unknown): value is null | undefined => { +is.nullOrUndefined = (value: unknown): value is null | undefined => { return is.null(value) || is.undefined(value); }; -export const isNumber = (value: unknown): value is number => { +is.number = (value: unknown): value is number => { return isOfType('number')(value) && !is.nan(value); }; -export const isNumericString = (value: unknown): value is string => { +is.numericString = (value: unknown): value is string => { return is.string(value) && (value as string).length > 0 && !Number.isNaN(Number(value)); }; -export const isObject = (value: unknown): value is object => { +is.object = (value: unknown): value is object => { return !is.nullOrUndefined(value) && (is.function(value) || typeof value === 'object'); }; -export const isOneOf = (target: unknown[], value: any): boolean => { +is.oneOf = (target: unknown[], value: any): boolean => { if (!is.array(target)) { return false; } @@ -186,9 +157,9 @@ export const isOneOf = (target: unknown[], value: any): boolean => { return target.indexOf(value) > -1; }; -export const isPlainFunction = isObjectOfType('Function'); +is.plainFunction = isObjectOfType('Function'); -export const isPlainObject = (value: unknown): value is PlainObject => { +is.plainObject = (value: unknown): value is PlainObject => { if (getObjectType(value) !== 'Object') { return false; } @@ -198,12 +169,12 @@ export const isPlainObject = (value: unknown): value is PlainObject => { return prototype === null || prototype === Object.getPrototypeOf({}); }; -export const isPrimitive = (value: unknown): value is Primitive => +is.primitive = (value: unknown): value is Primitive => is.null(value) || isPrimitiveType(typeof value); -export const isPromise = isObjectOfType>('Promise'); +is.promise = isObjectOfType>('Promise'); -export const isPropertyOf = ( +is.propertyOf = ( target: PlainObject, key: string, predicate?: (v: unknown) => boolean, @@ -221,94 +192,18 @@ export const isPropertyOf = ( return is.defined(value); }; -export const isRegexp = isObjectOfType('RegExp'); - -export const isSet = isObjectOfType>('Set'); - -export const isString = isOfType('string'); - -export const isSymbol = isOfType('symbol'); +is.regexp = isObjectOfType('RegExp'); -export const isUndefined = isOfType('undefined'); +is.set = isObjectOfType>('Set'); -export const isWeakMap = isObjectOfType>('WeakMap'); +is.string = isOfType('string'); -export const isWeakSet = isObjectOfType>('WeakSet'); +is.symbol = isOfType('symbol'); -function is(value: unknown): TypeName { - if (value === null) { - return 'null'; - } +is.undefined = isOfType('undefined'); - switch (typeof value) { - case 'bigint': - return 'bigint'; - case 'boolean': - return 'boolean'; - case 'number': - return 'number'; - case 'string': - return 'string'; - case 'symbol': - return 'symbol'; - case 'undefined': - return 'undefined'; - default: - } - - if (is.array(value)) { - return 'Array'; - } - - if (is.plainFunction(value)) { - return 'Function'; - } - - const tagType = getObjectType(value); - - if (tagType) { - return tagType; - } - /* c8 ignore next 3 */ - - return 'Object'; -} +is.weakMap = isObjectOfType>('WeakMap'); -is.array = isArray; -is.arrayOf = isArrayOf; -is.asyncGeneratorFunction = isAsyncGeneratorFunction; -is.asyncFunction = isAsyncFunction; -is.bigint = isBigInt; -is.boolean = isBoolean; -is.date = isDate; -is.defined = isDefined; -is.domElement = isDomElement; -is.empty = isEmpty; -is.error = isError; -is.function = isFunction; -is.generator = isGenerator; -is.generatorFunction = isGeneratorFunction; -is.instanceOf = isInstanceOf; -is.iterable = isIterable; -is.map = isMap; -is.nan = isNan; -is.null = isNull; -is.nullOrUndefined = isNullOrUndefined; -is.number = isNumber; -is.numericString = isNumericString; -is.object = isObject; -is.oneOf = isOneOf; -is.plainFunction = isPlainFunction; -is.plainObject = isPlainObject; -is.primitive = isPrimitive; -is.promise = isPromise; -is.propertyOf = isPropertyOf; -is.regexp = isRegexp; -is.set = isSet; -is.string = isString; -is.symbol = isSymbol; -is.undefined = isUndefined; -is.weakMap = isWeakMap; -is.weakSet = isWeakSet; +is.weakSet = isObjectOfType>('WeakSet'); export default is; diff --git a/src/types.ts b/src/types.ts new file mode 100644 index 0000000..6cf223a --- /dev/null +++ b/src/types.ts @@ -0,0 +1,8 @@ +import { objectTypes, primitiveTypes } from './helpers'; + +export type Class = new (...arguments_: any[]) => T; +export type ObjectTypes = (typeof objectTypes)[number]; +export type PlainObject = Record; +export type Primitive = null | undefined | string | number | boolean | symbol | bigint; +export type PrimitiveTypes = (typeof primitiveTypes)[number]; +export type TypeName = ObjectTypes | PrimitiveTypes; diff --git a/test/exports.spec.ts b/test/exports.spec.ts index 4cd8389..c9de15e 100644 --- a/test/exports.spec.ts +++ b/test/exports.spec.ts @@ -1,6 +1,7 @@ import { ClassTest, tagNames, types } from './__fixtures'; -import is, { +import is from '../src'; +import { isArray, isArrayOf, isAsyncFunction, @@ -37,7 +38,7 @@ import is, { isUndefined, isWeakMap, isWeakSet, -} from '../src'; +} from '../src/exports'; describe('isArray', () => { types.forEach(d => { diff --git a/vitest.config.ts b/vitest.config.ts index 3480709..2821b29 100644 --- a/vitest.config.ts +++ b/vitest.config.ts @@ -4,6 +4,8 @@ export default defineConfig({ test: { coverage: { all: true, + include: ['src/**/*.ts'], + exclude: ['src/types.ts'], statements: 90, branches: 90, functions: 90,