@jeniex/utils 1.0.12 → 1.0.14

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/node/index.cjs CHANGED
@@ -42,24 +42,67 @@ async function sleep(milliSeconds) {
42
42
  });
43
43
  }
44
44
 
45
+ /**
46
+ * Get a list of files that are present in the provided folder path.
47
+ * If the provided folder path does not exists, it will return an empty array.
48
+ */
49
+ async function listFiles({ folderPath, getFullPath, filter }) {
50
+ if (fs.existsSync(folderPath) === false) {
51
+ return [];
52
+ }
53
+ const entries = await fsp.readdir(folderPath, {
54
+ withFileTypes: true,
55
+ });
56
+ const files = entries
57
+ .filter((entry) => entry.isDirectory() === false)
58
+ .map((fileEntry) => {
59
+ if (getFullPath === true) {
60
+ return path.join(folderPath, fileEntry.name);
61
+ }
62
+ return fileEntry.name;
63
+ });
64
+ if (filter === undefined) {
65
+ return files;
66
+ }
67
+ return files.filter((fileName) => {
68
+ const fileExtension = path.extname(fileName);
69
+ return filter.includes(fileExtension);
70
+ });
71
+ }
72
+
73
+ /**
74
+ * Get a list of folders that are present in the provided folder path.
75
+ * If the provided folder path does not exists, an error will be thrown.
76
+ */
45
77
  async function listFolders({ folderPath, getFullPath }) {
46
78
  if (fs.existsSync(folderPath) === false) {
47
79
  throw new Error('The provided folder path does not exist!');
48
80
  }
49
- const items = await fsp.readdir(folderPath, {
81
+ const entries = await fsp.readdir(folderPath, {
50
82
  withFileTypes: true,
51
83
  });
52
- const folders = items
53
- .filter((item) => item.isDirectory() === true)
54
- .map((folderItem) => {
55
- if (getFullPath === undefined) {
56
- return folderItem.name;
84
+ const folders = entries
85
+ .filter((entry) => entry.isDirectory() === true)
86
+ .map((folderEntry) => {
87
+ if (getFullPath === true) {
88
+ return path.join(folderPath, folderEntry.name);
57
89
  }
58
- return path.join(folderPath, folderItem.name);
90
+ return folderEntry.name;
59
91
  });
60
92
  return folders;
61
93
  }
62
94
 
95
+ async function removeFiles({ folderPath, filter }) {
96
+ const nestedFilePathPattern = `${path.resolve('./')}\\`;
97
+ if (!folderPath.startsWith(nestedFilePathPattern)) {
98
+ throw new Error('Files are outside or at the root of the project folder.');
99
+ }
100
+ const filesPaths = await listFiles({ folderPath, getFullPath: true, filter });
101
+ for (const filePath of filesPaths) {
102
+ await fsp.unlink(filePath);
103
+ }
104
+ }
105
+
63
106
  exports.asserted = asserted;
64
107
  exports.ensureJoin = ensureJoin;
65
108
  exports.isFalsy = isFalsy;
@@ -67,6 +110,8 @@ exports.isNotNullish = isNotNullish;
67
110
  exports.isNullish = isNullish;
68
111
  exports.isString = isString;
69
112
  exports.isTruthy = isTruthy;
113
+ exports.listFiles = listFiles;
70
114
  exports.listFolders = listFolders;
71
115
  exports.noop = noop;
116
+ exports.removeFiles = removeFiles;
72
117
  exports.sleep = sleep;
package/node/index.d.ts CHANGED
@@ -15,10 +15,37 @@ declare function sleep(milliSeconds: number): Promise<void>;
15
15
  type Nullable<T> = T | null | undefined;
16
16
  type Fn<T = void, U = any> = (param?: U) => T;
17
17
 
18
- interface ListFoldersOpt {
18
+ interface ListBaseOpt {
19
+ /** The absolute path of the target folder. */
19
20
  folderPath: string;
20
21
  getFullPath?: boolean;
21
22
  }
23
+ interface ListFoldersOpt extends ListBaseOpt {
24
+ }
25
+ interface ListFilesOpt extends ListBaseOpt {
26
+ /**
27
+ * If provided, only files with these extensions will be processed.
28
+ *
29
+ * @example
30
+ * ['.css', '.html'];
31
+ */
32
+ filter?: string[];
33
+ }
34
+ interface RemoveFilesOpt extends Omit<ListFilesOpt, 'getFullPath'> {
35
+ }
36
+
37
+ /**
38
+ * Get a list of files that are present in the provided folder path.
39
+ * If the provided folder path does not exists, it will return an empty array.
40
+ */
41
+ declare function listFiles({ folderPath, getFullPath, filter }: ListFilesOpt): Promise<string[]>;
42
+
43
+ /**
44
+ * Get a list of folders that are present in the provided folder path.
45
+ * If the provided folder path does not exists, an error will be thrown.
46
+ */
22
47
  declare function listFolders({ folderPath, getFullPath }: ListFoldersOpt): Promise<string[]>;
23
48
 
24
- export { Fn, Nullable, asserted, ensureJoin, isFalsy, isNotNullish, isNullish, isString, isTruthy, listFolders, noop, sleep };
49
+ declare function removeFiles({ folderPath, filter }: RemoveFilesOpt): Promise<void>;
50
+
51
+ export { Fn, Nullable, asserted, ensureJoin, isFalsy, isNotNullish, isNullish, isString, isTruthy, listFiles, listFolders, noop, removeFiles, sleep };
package/node/index.js CHANGED
@@ -40,22 +40,65 @@ async function sleep(milliSeconds) {
40
40
  });
41
41
  }
42
42
 
43
+ /**
44
+ * Get a list of files that are present in the provided folder path.
45
+ * If the provided folder path does not exists, it will return an empty array.
46
+ */
47
+ async function listFiles({ folderPath, getFullPath, filter }) {
48
+ if (fs.existsSync(folderPath) === false) {
49
+ return [];
50
+ }
51
+ const entries = await fsp.readdir(folderPath, {
52
+ withFileTypes: true,
53
+ });
54
+ const files = entries
55
+ .filter((entry) => entry.isDirectory() === false)
56
+ .map((fileEntry) => {
57
+ if (getFullPath === true) {
58
+ return path.join(folderPath, fileEntry.name);
59
+ }
60
+ return fileEntry.name;
61
+ });
62
+ if (filter === undefined) {
63
+ return files;
64
+ }
65
+ return files.filter((fileName) => {
66
+ const fileExtension = path.extname(fileName);
67
+ return filter.includes(fileExtension);
68
+ });
69
+ }
70
+
71
+ /**
72
+ * Get a list of folders that are present in the provided folder path.
73
+ * If the provided folder path does not exists, an error will be thrown.
74
+ */
43
75
  async function listFolders({ folderPath, getFullPath }) {
44
76
  if (fs.existsSync(folderPath) === false) {
45
77
  throw new Error('The provided folder path does not exist!');
46
78
  }
47
- const items = await fsp.readdir(folderPath, {
79
+ const entries = await fsp.readdir(folderPath, {
48
80
  withFileTypes: true,
49
81
  });
50
- const folders = items
51
- .filter((item) => item.isDirectory() === true)
52
- .map((folderItem) => {
53
- if (getFullPath === undefined) {
54
- return folderItem.name;
82
+ const folders = entries
83
+ .filter((entry) => entry.isDirectory() === true)
84
+ .map((folderEntry) => {
85
+ if (getFullPath === true) {
86
+ return path.join(folderPath, folderEntry.name);
55
87
  }
56
- return path.join(folderPath, folderItem.name);
88
+ return folderEntry.name;
57
89
  });
58
90
  return folders;
59
91
  }
60
92
 
61
- export { asserted, ensureJoin, isFalsy, isNotNullish, isNullish, isString, isTruthy, listFolders, noop, sleep };
93
+ async function removeFiles({ folderPath, filter }) {
94
+ const nestedFilePathPattern = `${path.resolve('./')}\\`;
95
+ if (!folderPath.startsWith(nestedFilePathPattern)) {
96
+ throw new Error('Files are outside or at the root of the project folder.');
97
+ }
98
+ const filesPaths = await listFiles({ folderPath, getFullPath: true, filter });
99
+ for (const filePath of filesPaths) {
100
+ await fsp.unlink(filePath);
101
+ }
102
+ }
103
+
104
+ export { asserted, ensureJoin, isFalsy, isNotNullish, isNullish, isString, isTruthy, listFiles, listFolders, noop, removeFiles, sleep };
@@ -0,0 +1,31 @@
1
+ type ListChoice = number | string;
2
+ type CheckboxValue = boolean | number | string;
3
+ interface CheckboxChoice {
4
+ name: number | string;
5
+ value?: CheckboxValue;
6
+ checked?: boolean;
7
+ disabled?: boolean | string;
8
+ }
9
+
10
+ /**
11
+ * Shows the user a list of options to multi-select from.
12
+ */
13
+ declare function checkbox(message: string, choices: CheckboxChoice[]): Promise<CheckboxValue[]>;
14
+
15
+ /**
16
+ * Gets the user confirmation.
17
+ * @param defaultAnswer Defaults to false which is no.
18
+ */
19
+ declare function confirm(message: string, defaultAnswer?: boolean): Promise<boolean>;
20
+
21
+ /**
22
+ * Gets the user input if provided, otherwise throws an error.
23
+ */
24
+ declare function input(message: string): Promise<string>;
25
+
26
+ /**
27
+ * Shows the user a list of options to select from.
28
+ */
29
+ declare function list(message: string, choices: (ListChoice)[]): Promise<ListChoice>;
30
+
31
+ export { CheckboxChoice, checkbox, confirm, input, list };
@@ -0,0 +1,86 @@
1
+ import inquirer from 'inquirer';
2
+
3
+ /**
4
+ * Shows the user a list of options to multi-select from.
5
+ */
6
+ async function checkbox(message, choices) {
7
+ const { selectedChoices } = await inquirer.prompt([
8
+ {
9
+ type: 'checkbox',
10
+ message,
11
+ name: 'selectedChoices',
12
+ loop: false,
13
+ choices,
14
+ async validate(answer) {
15
+ if (answer.length === 0) {
16
+ return 'You must choose at least one choice!';
17
+ }
18
+ return true;
19
+ },
20
+ },
21
+ ]);
22
+ return selectedChoices;
23
+ }
24
+
25
+ /**
26
+ * Gets the user confirmation.
27
+ * @param defaultAnswer Defaults to false which is no.
28
+ */
29
+ async function confirm(message, defaultAnswer = false) {
30
+ const { confirmValue } = await inquirer.prompt([
31
+ {
32
+ type: 'confirm',
33
+ name: 'confirmValue',
34
+ message,
35
+ default: defaultAnswer,
36
+ },
37
+ ]);
38
+ // Extra checking as if the values are of type `any`.
39
+ if (typeof confirmValue !== 'boolean') {
40
+ throw new TypeError('Something went wrong!');
41
+ }
42
+ return confirmValue;
43
+ }
44
+
45
+ function isFalsy(object) {
46
+ return Boolean(object) === false;
47
+ }
48
+
49
+ /**
50
+ * Gets the user input if provided, otherwise throws an error.
51
+ */
52
+ async function input(message) {
53
+ const { inputValue } = await inquirer.prompt([
54
+ {
55
+ type: 'input',
56
+ name: 'inputValue',
57
+ message,
58
+ },
59
+ ]);
60
+ // Extra checking as if the values are of type `any`.
61
+ if (isFalsy(inputValue) || typeof inputValue !== 'string') {
62
+ throw new Error('No input was provided!');
63
+ }
64
+ return inputValue;
65
+ }
66
+
67
+ /**
68
+ * Shows the user a list of options to select from.
69
+ */
70
+ async function list(message, choices) {
71
+ const { selectedChoice } = await inquirer.prompt([
72
+ {
73
+ type: 'list',
74
+ name: 'selectedChoice',
75
+ message,
76
+ choices,
77
+ loop: false,
78
+ },
79
+ ]);
80
+ if (typeof selectedChoice !== 'string' && typeof selectedChoice !== 'number') {
81
+ throw new TypeError('Something went wrong!');
82
+ }
83
+ return selectedChoice;
84
+ }
85
+
86
+ export { checkbox, confirm, input, list };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jeniex/utils",
3
- "version": "1.0.12",
3
+ "version": "1.0.14",
4
4
  "author": "JenieX",
5
5
  "homepage": "https://github.com/JenieX/utils",
6
6
  "type": "module",
@@ -17,6 +17,10 @@
17
17
  "types": "./node/index.d.ts",
18
18
  "import": "./node/index.js",
19
19
  "require": "./node/index.cjs"
20
+ },
21
+ "./node/inquirer": {
22
+ "types": "./node/inquirer/index.d.ts",
23
+ "import": "./node/inquirer/index.js"
20
24
  }
21
25
  },
22
26
  "files": [
@@ -32,11 +36,14 @@
32
36
  "@commitlint/config-conventional": "^17.7.0",
33
37
  "@jeniex/eslint-config": "^0.0.3",
34
38
  "@rollup/plugin-typescript": "^11.1.3",
39
+ "@types/inquirer": "^9.0.3",
35
40
  "@types/node": "^20.5.7",
36
41
  "@violentmonkey/types": "^0.1.5",
42
+ "inquirer": "^9.2.11",
37
43
  "rollup": "^3.28.0",
38
44
  "rollup-plugin-dts": "^5.3.1",
39
- "tslib": "^2.6.2"
45
+ "tslib": "^2.6.2",
46
+ "tsx": "^3.12.8"
40
47
  },
41
48
  "publishConfig": {
42
49
  "access": "public"