@hypernym/utils 1.2.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE.txt CHANGED
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2023 Hypernym Studio, Ivo Dolenc
3
+ Copyright (c) 2023 Ivo Dolenc, Hypernym Studio
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
package/README.md CHANGED
@@ -4,25 +4,19 @@ A collection of reusable utilities.
4
4
 
5
5
  <sub><a href="https://github.com/hypernym-studio/utils">Repository</a> | <a href="https://www.npmjs.com/package/@hypernym/utils">Package</a> | <a href="https://github.com/hypernym-studio/utils/releases">Releases</a> | <a href="https://github.com/hypernym-studio/utils/discussions">Discussions</a></sub>
6
6
 
7
+ ```sh
8
+ npm i -D @hypernym/utils
9
+ ```
10
+
7
11
  ## Features
8
12
 
9
- - Supports CJS & ESM
10
13
  - TypeScript friendly
11
14
  - Fully tree-shakeable
12
15
  - No dependencies
13
16
 
14
- ## Installation
15
-
16
- ```sh
17
- npm i -D @hypernym/utils
18
- ```
19
-
20
17
  ## Usage
21
18
 
22
19
  ```ts
23
- // CJS
24
- const { isNull, isString, ... } = require('@hypernym/utils')
25
-
26
20
  // ESM & TS
27
21
  import { isNull, isString, ... } from '@hypernym/utils'
28
22
 
package/dist/index.mjs CHANGED
@@ -31,15 +31,4 @@ const isNodeListEmpty = (v) => isNodeList(v) && v.length === 0;
31
31
  const isHtmlCollection = (v) => v instanceof HTMLCollection;
32
32
  const isHtmlCollectionEmpty = (v) => isHtmlCollection(v) && v.length === 0;
33
33
 
34
- function formatBytes(bytes, options) {
35
- const decimals = options?.decimals || 2;
36
- const units = ["B", "KB", "MB", "GB", "TB"];
37
- if (bytes === 0)
38
- return `0 B`;
39
- const k = 1024;
40
- const dm = decimals < 0 ? 0 : decimals;
41
- const i = Math.floor(Math.log(bytes) / Math.log(k));
42
- return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${units[i]}`;
43
- }
44
-
45
- export { formatBytes, isArray, isArrayEmpty, isBigint, isBoolean, isBrowser, isDate, isElement, isError, isFunction, isHtmlCollection, isHtmlCollectionEmpty, isInfinity, isMap, isNaNValue, isNodeList, isNodeListEmpty, isNull, isNumber, isObject, isObjectEmpty, isPrimitive, isRegExp, isSet, isString, isStringEmpty, isSymbol, isURL, isUndefined, noop, toString };
34
+ export { isArray, isArrayEmpty, isBigint, isBoolean, isBrowser, isDate, isElement, isError, isFunction, isHtmlCollection, isHtmlCollectionEmpty, isInfinity, isMap, isNaNValue, isNodeList, isNodeListEmpty, isNull, isNumber, isObject, isObjectEmpty, isPrimitive, isRegExp, isSet, isString, isStringEmpty, isSymbol, isURL, isUndefined, noop, toString };
@@ -1,77 +1,7 @@
1
- import { access, constants, readdir, stat } from 'node:fs/promises';
2
- import { resolve, basename, parse } from 'node:path';
1
+ import { access, constants } from 'node:fs/promises';
3
2
 
4
3
  async function exists(path) {
5
4
  return await access(path, constants.F_OK).then(() => true).catch(() => false);
6
5
  }
7
6
 
8
- async function getDirStats(path, options) {
9
- const dirPath = resolve(path);
10
- const dirFiles = await readdir(dirPath);
11
- const dirBase = basename(dirPath);
12
- let dirStats = [];
13
- const subdirList = [];
14
- const fileList = [];
15
- let dirSize = 0;
16
- let dirIndex = 0;
17
- let fileIndex = -1;
18
- let subdirIndex = -1;
19
- for (const file of dirFiles) {
20
- const filePath = resolve(path, file);
21
- const fileStat = await stat(filePath);
22
- if (fileStat.isDirectory()) {
23
- subdirIndex++;
24
- subdirList.push({
25
- index: subdirIndex,
26
- path: filePath,
27
- base: file
28
- });
29
- if (options?.recursive) {
30
- const stats = await getDirStats(filePath);
31
- const updateDirStats = { ...stats[0], ...{ index: dirIndex++ } };
32
- dirStats = [...dirStats, updateDirStats];
33
- }
34
- } else {
35
- const { base, name, ext } = parse(file);
36
- const { size } = fileStat;
37
- fileIndex++;
38
- dirSize += size;
39
- fileList.push({
40
- index: fileIndex,
41
- path: filePath,
42
- base,
43
- name,
44
- ext,
45
- size
46
- });
47
- }
48
- }
49
- dirStats.push({
50
- index: dirIndex,
51
- path: dirPath,
52
- base: dirBase,
53
- size: dirSize,
54
- subdirs: subdirList,
55
- files: fileList
56
- });
57
- return dirStats;
58
- }
59
-
60
- async function getDirFiles(path, options) {
61
- const dirPath = resolve(path);
62
- const dirFiles = await readdir(dirPath, { withFileTypes: true });
63
- let fileList = [];
64
- for (const file of dirFiles) {
65
- const filePath = resolve(path, file.name);
66
- if (file.isDirectory()) {
67
- if (options?.recursive) {
68
- fileList = [...fileList, ...await getDirFiles(filePath)];
69
- }
70
- } else {
71
- fileList.push(filePath);
72
- }
73
- }
74
- return fileList;
75
- }
76
-
77
- export { exists, getDirFiles, getDirStats };
7
+ export { exists };
@@ -142,16 +142,7 @@ type IsAny<T> = 0 extends 1 & T ? true : false;
142
142
  */
143
143
  type IsNever<T> = [T] extends [never] ? true : false;
144
144
 
145
- /**
146
- * Converts bytes to a _human-readable_ size and appends a units suffix.
147
- */
148
- declare function formatBytes(bytes: number, options?: FormatBytesOptions): string;
149
-
150
- interface FormatBytesOptions {
151
- decimals?: number;
152
- }
153
-
154
- type OptionsDeep = {
145
+ type PartialOptions = {
155
146
  /**
156
147
  * Enables recursive mode for arrays and tuples.
157
148
  *
@@ -159,33 +150,40 @@ type OptionsDeep = {
159
150
  */
160
151
  readonly arrays?: boolean;
161
152
  };
162
-
163
153
  /**
164
154
  * Constructs a type by recursively setting all properties as optional.
165
155
  *
166
156
  * Use `Partial<T>` for one level.
167
157
  */
168
- type PartialDeep<T, Options extends OptionsDeep = {
158
+ type PartialDeep<T, Options extends PartialOptions = {
169
159
  arrays: true;
170
160
  }> = T extends BuiltIn ? T | undefined : T extends Map<infer K, infer V> ? Map<PartialDeep<K, Options>, PartialDeep<V, Options>> : T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<PartialDeep<K, Options>, PartialDeep<V, Options>> : T extends WeakMap<infer K, infer V> ? WeakMap<PartialDeep<K, Options>, PartialDeep<V, Options>> : T extends Set<infer V> ? Set<PartialDeep<V, Options>> : T extends ReadonlySet<infer V> ? ReadonlySet<PartialDeep<V, Options>> : T extends WeakSet<infer V> ? WeakSet<PartialDeep<V, Options>> : T extends Promise<infer V> ? Promise<PartialDeep<V, Options>> : T extends (...args: any[]) => unknown ? T | undefined : T extends object ? T extends ReadonlyArray<infer V> ? Options['arrays'] extends true ? V[] extends T ? readonly V[] extends T ? ReadonlyArray<PartialDeep<V, Options>> : Array<PartialDeep<V, Options>> : PartialObjectDeep<T, Options> : T | undefined : PartialObjectDeep<T, Options> : unknown;
171
- type PartialObjectDeep<T extends object, Options extends OptionsDeep = {
161
+ type PartialObjectDeep<T extends object, Options extends PartialOptions = {
172
162
  arrays: true;
173
163
  }> = {
174
164
  [K in keyof T]?: PartialDeep<T[K], Options>;
175
165
  };
176
166
 
167
+ type RequiredOptions = {
168
+ /**
169
+ * Enables recursive mode for arrays and tuples.
170
+ *
171
+ * @default true
172
+ */
173
+ readonly arrays?: boolean;
174
+ };
177
175
  /**
178
176
  * Constructs a type by recursively setting all properties as required.
179
177
  *
180
178
  * Use `Required<T>` for one level.
181
179
  */
182
- type RequiredDeep<T, Options extends OptionsDeep = {
180
+ type RequiredDeep<T, Options extends RequiredOptions = {
183
181
  arrays: true;
184
182
  }> = T extends BuiltIn ? Exclude<T, undefined> : T extends Map<infer K, infer V> ? Map<RequiredDeep<K, Options>, RequiredDeep<V, Options>> : T extends ReadonlyMap<infer K, infer V> ? ReadonlyMap<RequiredDeep<K, Options>, RequiredDeep<V, Options>> : T extends WeakMap<infer K, infer V> ? WeakMap<RequiredDeep<K, Options>, RequiredDeep<V, Options>> : T extends Set<infer V> ? Set<RequiredDeep<V, Options>> : T extends ReadonlySet<infer V> ? ReadonlySet<RequiredDeep<V, Options>> : T extends WeakSet<infer V> ? WeakSet<RequiredDeep<V, Options>> : T extends Promise<infer V> ? Promise<RequiredDeep<V, Options>> : T extends (...args: any[]) => unknown ? Exclude<T, undefined> : T extends object ? T extends ReadonlyArray<infer V> ? Options['arrays'] extends true ? V[] extends T ? readonly V[] extends T ? ReadonlyArray<RequiredDeep<Exclude<V, undefined>, Options>> : Array<RequiredDeep<Exclude<V, undefined>, Options>> : RequiredObjectDeep<T, Options> : Exclude<T, undefined> : RequiredObjectDeep<T, Options> : unknown;
185
- type RequiredObjectDeep<T extends object, Options extends OptionsDeep = {
183
+ type RequiredObjectDeep<T extends object, Options extends RequiredOptions = {
186
184
  arrays: true;
187
185
  }> = {
188
186
  [K in keyof T]-?: RequiredDeep<T[K], Options>;
189
187
  };
190
188
 
191
- export { BuiltIn, FormatBytesOptions, IsAny, IsNever, IsNull, OptionsDeep, PartialDeep, Primitive, RequiredDeep, formatBytes, isArray, isArrayEmpty, isBigint, isBoolean, isBrowser, isDate, isElement, isError, isFunction, isHtmlCollection, isHtmlCollectionEmpty, isInfinity, isMap, isNaNValue, isNodeList, isNodeListEmpty, isNull, isNumber, isObject, isObjectEmpty, isPrimitive, isRegExp, isSet, isString, isStringEmpty, isSymbol, isURL, isUndefined, noop, toString };
189
+ export { type BuiltIn, type IsAny, type IsNever, type IsNull, type PartialDeep, type Primitive, type RequiredDeep, isArray, isArrayEmpty, isBigint, isBoolean, isBrowser, isDate, isElement, isError, isFunction, isHtmlCollection, isHtmlCollectionEmpty, isInfinity, isMap, isNaNValue, isNodeList, isNodeListEmpty, isNull, isNumber, isObject, isObjectEmpty, isPrimitive, isRegExp, isSet, isString, isStringEmpty, isSymbol, isURL, isUndefined, noop, toString };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Checks if the file exists.
3
+ */
4
+ declare function exists(path: string): Promise<boolean>;
5
+
6
+ export { exists };
package/package.json CHANGED
@@ -1,34 +1,25 @@
1
1
  {
2
2
  "name": "@hypernym/utils",
3
- "version": "1.2.0",
3
+ "version": "2.0.0",
4
4
  "author": "Hypernym Studio",
5
- "maintainers": [
6
- "Ivo Dolenc (https://github.com/ivodolenc)"
7
- ],
8
5
  "description": "A collection of reusable utilities.",
9
6
  "license": "MIT",
10
- "funding": "https://github.com/sponsors/ivodolenc",
11
7
  "repository": "hypernym-studio/utils",
12
8
  "homepage": "https://github.com/hypernym-studio/utils",
9
+ "funding": "https://github.com/sponsors/ivodolenc",
13
10
  "type": "module",
14
- "main": "./dist/index.cjs",
15
- "module": "./dist/index.mjs",
16
- "types": "./dist/index.d.ts",
17
11
  "exports": {
18
12
  ".": {
19
- "types": "./dist/index.d.ts",
20
- "import": "./dist/index.mjs",
21
- "require": "./dist/index.cjs"
13
+ "types": "./dist/types/index.d.ts",
14
+ "import": "./dist/index.mjs"
22
15
  },
23
16
  "./node": {
24
- "types": "./dist/node/index.d.ts",
25
- "import": "./dist/node/index.mjs",
26
- "require": "./dist/node/index.cjs"
17
+ "types": "./dist/types/node/index.d.ts",
18
+ "import": "./dist/node/index.mjs"
27
19
  }
28
20
  },
29
21
  "files": [
30
- "dist",
31
- "*.d.ts"
22
+ "dist"
32
23
  ],
33
24
  "keywords": [
34
25
  "typescript",
@@ -42,32 +33,26 @@
42
33
  "scripts": {
43
34
  "dev": "vite playgrounds/client",
44
35
  "dev:node": "vite-node -w playgrounds/node/main.ts",
45
- "build": "rollup -c ./.config/rollup.config.js",
36
+ "build": "rolli",
37
+ "bump": "bummp",
46
38
  "test:types": "vitest -c ./.config/vitest.config.ts typecheck",
47
- "prepublishOnly": "npm run build",
48
- "format": "prettier --write .",
49
- "lint": "eslint .",
50
- "fix": "eslint --fix ."
39
+ "lint": "ESLINT_USE_FLAT_CONFIG=true eslint -c .config/eslint.config.js .",
40
+ "lint:fix": "ESLINT_USE_FLAT_CONFIG=true eslint -c .config/eslint.config.js --fix .",
41
+ "format": "prettier --config .config/prettier.config.js --write .",
42
+ "prepublishOnly": "npm run build"
51
43
  },
52
44
  "devDependencies": {
53
- "@hypernym/eslint-config": "^1.0.1",
54
- "@hypernym/prettier-config": "^1.0.1",
55
- "@types/node": "^20.4.1",
56
- "eslint": "^8.44.0",
57
- "prettier": "^2.8.8",
58
- "rollup": "^3.26.2",
59
- "rollup-plugin-dts": "^5.3.0",
60
- "rollup-plugin-esbuild": "^5.0.0",
61
- "typescript": "^5.0.4",
62
- "vite": "^4.4.3",
63
- "vite-node": "^0.33.0",
64
- "vitest": "^0.33.0"
65
- },
66
- "publishConfig": {
67
- "access": "public"
68
- },
69
- "eslintConfig": {
70
- "extends": "./.config/eslint.config.cjs"
71
- },
72
- "prettier": "@hypernym/prettier-config"
45
+ "@hypernym/eslint-config": "^2.0.0",
46
+ "@hypernym/prettier-config": "^2.0.0",
47
+ "@hypernym/tsconfig": "^1.0.1",
48
+ "@types/node": "^20.6.2",
49
+ "bummp": "^0.2.0",
50
+ "eslint": "^8.49.0",
51
+ "prettier": "^3.0.3",
52
+ "rolli": "^0.6.1",
53
+ "typescript": "^5.1.6",
54
+ "vite": "^4.4.9",
55
+ "vite-node": "^0.34.4",
56
+ "vitest": "^0.34.4"
57
+ }
73
58
  }
package/dist/index.cjs DELETED
@@ -1,77 +0,0 @@
1
- 'use strict';
2
-
3
- const noop = () => {
4
- };
5
- const toString = (v) => Object.prototype.toString.call(v).slice(8, -1);
6
-
7
- const isBrowser = typeof window !== "undefined";
8
- const isNull = (v) => v === null;
9
- const isUndefined = (v) => typeof v === "undefined";
10
- const isString = (v) => typeof v === "string";
11
- const isStringEmpty = (v) => isString(v) && v.trim().length === 0;
12
- const isBoolean = (v) => typeof v === "boolean";
13
- const isNumber = (v) => typeof v === "number" && !isNaN(v);
14
- const isArray = (v) => Array.isArray(v);
15
- const isArrayEmpty = (v) => isArray(v) && v.length === 0;
16
- const isObject = (v) => toString(v) === "Object";
17
- const isObjectEmpty = (v) => isObject(v) && Object.keys(v).length === 0;
18
- const isFunction = (v) => v instanceof Function;
19
- const isNaNValue = (v) => typeof v === "number" && isNaN(v);
20
- const isRegExp = (v) => v instanceof RegExp;
21
- const isMap = (v) => v instanceof Map;
22
- const isSet = (v) => v instanceof Set;
23
- const isSymbol = (v) => toString(v) === "Symbol";
24
- const isDate = (v) => v instanceof Date && !isNaN(v.valueOf());
25
- const isBigint = (v) => typeof v === "bigint";
26
- const isInfinity = (v) => v === Infinity || v === -Infinity;
27
- const isURL = (v) => v instanceof URL;
28
- const isError = (v) => v instanceof Error;
29
- const isPrimitive = (v) => isString(v) || isNumber(v) || isBigint(v) || isBoolean(v) || isSymbol(v) || isNull(v) || isUndefined(v);
30
- const isElement = (v) => v instanceof Element;
31
- const isNodeList = (v) => v instanceof NodeList;
32
- const isNodeListEmpty = (v) => isNodeList(v) && v.length === 0;
33
- const isHtmlCollection = (v) => v instanceof HTMLCollection;
34
- const isHtmlCollectionEmpty = (v) => isHtmlCollection(v) && v.length === 0;
35
-
36
- function formatBytes(bytes, options) {
37
- const decimals = options?.decimals || 2;
38
- const units = ["B", "KB", "MB", "GB", "TB"];
39
- if (bytes === 0)
40
- return `0 B`;
41
- const k = 1024;
42
- const dm = decimals < 0 ? 0 : decimals;
43
- const i = Math.floor(Math.log(bytes) / Math.log(k));
44
- return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${units[i]}`;
45
- }
46
-
47
- exports.formatBytes = formatBytes;
48
- exports.isArray = isArray;
49
- exports.isArrayEmpty = isArrayEmpty;
50
- exports.isBigint = isBigint;
51
- exports.isBoolean = isBoolean;
52
- exports.isBrowser = isBrowser;
53
- exports.isDate = isDate;
54
- exports.isElement = isElement;
55
- exports.isError = isError;
56
- exports.isFunction = isFunction;
57
- exports.isHtmlCollection = isHtmlCollection;
58
- exports.isHtmlCollectionEmpty = isHtmlCollectionEmpty;
59
- exports.isInfinity = isInfinity;
60
- exports.isMap = isMap;
61
- exports.isNaNValue = isNaNValue;
62
- exports.isNodeList = isNodeList;
63
- exports.isNodeListEmpty = isNodeListEmpty;
64
- exports.isNull = isNull;
65
- exports.isNumber = isNumber;
66
- exports.isObject = isObject;
67
- exports.isObjectEmpty = isObjectEmpty;
68
- exports.isPrimitive = isPrimitive;
69
- exports.isRegExp = isRegExp;
70
- exports.isSet = isSet;
71
- exports.isString = isString;
72
- exports.isStringEmpty = isStringEmpty;
73
- exports.isSymbol = isSymbol;
74
- exports.isURL = isURL;
75
- exports.isUndefined = isUndefined;
76
- exports.noop = noop;
77
- exports.toString = toString;
@@ -1,81 +0,0 @@
1
- 'use strict';
2
-
3
- var promises = require('node:fs/promises');
4
- var node_path = require('node:path');
5
-
6
- async function exists(path) {
7
- return await promises.access(path, promises.constants.F_OK).then(() => true).catch(() => false);
8
- }
9
-
10
- async function getDirStats(path, options) {
11
- const dirPath = node_path.resolve(path);
12
- const dirFiles = await promises.readdir(dirPath);
13
- const dirBase = node_path.basename(dirPath);
14
- let dirStats = [];
15
- const subdirList = [];
16
- const fileList = [];
17
- let dirSize = 0;
18
- let dirIndex = 0;
19
- let fileIndex = -1;
20
- let subdirIndex = -1;
21
- for (const file of dirFiles) {
22
- const filePath = node_path.resolve(path, file);
23
- const fileStat = await promises.stat(filePath);
24
- if (fileStat.isDirectory()) {
25
- subdirIndex++;
26
- subdirList.push({
27
- index: subdirIndex,
28
- path: filePath,
29
- base: file
30
- });
31
- if (options?.recursive) {
32
- const stats = await getDirStats(filePath);
33
- const updateDirStats = { ...stats[0], ...{ index: dirIndex++ } };
34
- dirStats = [...dirStats, updateDirStats];
35
- }
36
- } else {
37
- const { base, name, ext } = node_path.parse(file);
38
- const { size } = fileStat;
39
- fileIndex++;
40
- dirSize += size;
41
- fileList.push({
42
- index: fileIndex,
43
- path: filePath,
44
- base,
45
- name,
46
- ext,
47
- size
48
- });
49
- }
50
- }
51
- dirStats.push({
52
- index: dirIndex,
53
- path: dirPath,
54
- base: dirBase,
55
- size: dirSize,
56
- subdirs: subdirList,
57
- files: fileList
58
- });
59
- return dirStats;
60
- }
61
-
62
- async function getDirFiles(path, options) {
63
- const dirPath = node_path.resolve(path);
64
- const dirFiles = await promises.readdir(dirPath, { withFileTypes: true });
65
- let fileList = [];
66
- for (const file of dirFiles) {
67
- const filePath = node_path.resolve(path, file.name);
68
- if (file.isDirectory()) {
69
- if (options?.recursive) {
70
- fileList = [...fileList, ...await getDirFiles(filePath)];
71
- }
72
- } else {
73
- fileList.push(filePath);
74
- }
75
- }
76
- return fileList;
77
- }
78
-
79
- exports.exists = exists;
80
- exports.getDirFiles = getDirFiles;
81
- exports.getDirStats = getDirStats;
@@ -1,49 +0,0 @@
1
- /**
2
- * Checks if the file exists.
3
- */
4
- declare function exists(path: string): Promise<boolean>;
5
-
6
- /**
7
- * Scans the specified directory and gets details for each subdirectory and file.
8
- *
9
- * By default, recursive mode is disabled so only one level is scanned.
10
- */
11
- declare function getDirStats(path: string, options?: DirStatsOptions): Promise<DirStats[]>;
12
-
13
- interface SubdirDetails {
14
- index: number;
15
- path: string;
16
- base: string;
17
- }
18
- interface FileDetails {
19
- index: number;
20
- path: string;
21
- base: string;
22
- name: string;
23
- ext: string;
24
- size: number;
25
- }
26
- interface DirStats {
27
- index: number;
28
- path: string;
29
- base: string;
30
- size: number;
31
- subdirs: SubdirDetails[];
32
- files: FileDetails[];
33
- }
34
- interface DirStatsOptions {
35
- recursive?: boolean;
36
- }
37
-
38
- /**
39
- * Scans the specified directory and returns a list of all files.
40
- *
41
- * By default, recursive mode is disabled so only one level is scanned.
42
- */
43
- declare function getDirFiles(path: string, options?: DirFilesOptions): Promise<string[]>;
44
-
45
- interface DirFilesOptions {
46
- recursive?: boolean;
47
- }
48
-
49
- export { DirFilesOptions, DirStats, DirStatsOptions, exists, getDirFiles, getDirStats };
package/node.d.ts DELETED
@@ -1 +0,0 @@
1
- export * from './dist/node'