typeshi 1.7.18 → 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.
@@ -810,22 +810,3 @@ function getSourceString(fileName, func, funcInfo, startLine, endLine) {
810
810
  let funcName = typeof func === 'string' ? func : func.name;
811
811
  return `[${fileName}.${funcName}(${(0, typeValidation_1.isNonEmptyString)(funcInfo) ? ` ${funcInfo} ` : ''})${lineNumberText}]`;
812
812
  }
813
- // isEnumArgumentOptions,
814
- // isEnumObject,
815
- // isObjectArgumentOptions,
816
- // const validate = {
817
- // stringArgument,
818
- // multipleStringArguments,
819
- // numericStringArgument,
820
- // booleanArgument,
821
- // numberArgument,
822
- // arrayArgument,
823
- // enumArgument,
824
- // objectArgument,
825
- // functionArgument,
826
- // existingPathArgument,
827
- // existingDirectoryArgument,
828
- // existingFileArgument,
829
- // multipleExistingFileArguments
830
- // }
831
- // export default validate;
@@ -107,20 +107,20 @@ function autoFormatLogsOnExit(filePaths) {
107
107
  * @returns `void`
108
108
  */
109
109
  function formatDebugLogFile(inputPath, outputPath) {
110
- validate.existingPathArgument(`logging.formatDebugLogFile`, { inputPath });
111
- // Generate output path if not provided
112
- if (!outputPath) {
113
- const parsedPath = node_path_1.default.parse(inputPath);
114
- outputPath = node_path_1.default.join(parsedPath.dir, `${parsedPath.name}.FORMATTED${parsedPath.ext}`);
115
- }
110
+ const source = getSourceString(__filename, formatAllDebugLogs.name);
116
111
  try {
112
+ validate.existingPathArgument(source, { inputPath });
113
+ if (!outputPath) { // Generate output path if not provided
114
+ const parsedPath = node_path_1.default.parse(inputPath);
115
+ outputPath = node_path_1.default.join(parsedPath.dir, `${parsedPath.name}.FORMATTED${parsedPath.ext}`);
116
+ }
117
117
  const fileContent = fs.readFileSync(inputPath, 'utf-8');
118
118
  const formattedContent = formatLogContent(fileContent);
119
119
  fs.writeFileSync(outputPath, formattedContent, { encoding: 'utf-8' });
120
120
  // mlog.info(`[formatDebugLogFile()] Formatted log file saved to '${outputPath}'`);
121
121
  }
122
122
  catch (error) {
123
- setupLog_1.typeshiLogger.error('[formatDebugLogFile()] Error formatting log file:', error);
123
+ setupLog_1.typeshiLogger.error(`${source} Error formatting log file:'`, error);
124
124
  throw error;
125
125
  }
126
126
  }
@@ -130,7 +130,7 @@ function formatDebugLogFile(inputPath, outputPath) {
130
130
  * @returns `string` - the formatted content
131
131
  */
132
132
  function formatLogContent(content) {
133
- const lines = content.split('\n');
133
+ const lines = content.split('\n'); //.map(s=>applyStripOptions(s, {char: `"`}));
134
134
  const formattedLines = [];
135
135
  let currentJsonObject = '';
136
136
  let insideJsonObject = false;
@@ -1,5 +1,5 @@
1
- import { StringCaseOptions, StringPadOptions, StringStripOptions, CleanStringOptions } from "../regex";
2
- import { FileData, FileExtension } from "./types/Io";
1
+ import { DEP_StringCaseOptions, DEP_StringStripOptions, DEP_CleanStringOptions, DEP_StringPadOptions } from "../regex";
2
+ import { DirectoryFileOptions, FileData, FileExtension } from "./types/Io";
3
3
  import { DelimiterCharacterEnum } from "./types";
4
4
  /** checks if `pathString (value)` points to an existing directory */
5
5
  export declare function isDirectory(value: any): value is string;
@@ -95,7 +95,7 @@ export declare function getCsvRows(arg1: FileData | string): Promise<Record<stri
95
95
  * @param valueColumn `string` - the column name whose contents will be used as values in the dictionary.
96
96
  * @returns **`dict`** `Record<string, string>`
97
97
  */
98
- export declare function getOneToOneDictionary(arg1: string | Record<string, any>[] | FileData, keyColumn: string, valueColumn: string, keyOptions?: CleanStringOptions, valueOptions?: CleanStringOptions, requireIncludeAllRows?: boolean): Promise<Record<string, string>>;
98
+ export declare function getOneToOneDictionary(arg1: string | Record<string, any>[] | FileData, keyColumn: string, valueColumn: string, keyOptions?: DEP_CleanStringOptions, valueOptions?: DEP_CleanStringOptions, requireIncludeAllRows?: boolean): Promise<Record<string, string>>;
99
99
  /**
100
100
  * @param arg1 `string | FileData | Record<string, any>[]` - the `filePath` to a CSV file or an array of rows.
101
101
  * @param columnName `string` - the column name whose values will be returned.
@@ -124,8 +124,8 @@ export declare function handleFileArgument(arg1: string | FileData | Record<stri
124
124
  * - `if true`, returned array elements are of form: `path.basename(file)`
125
125
  * - `if false`, returned array elements are of form: `path.join(dir, file)`
126
126
  * @param targetExtensions `string[] (optional)` - array of file extensions to filter files by.
127
- * - `If` not provided, all files in the directory will be returned.
128
- * - `If` provided, only files with extensions matching the array will be returned.
127
+ * - `if undefined`, all files in the directory will be returned.
128
+ * - `if defined`, only files with extensions matching the array will be returned.
129
129
  * @returns **`targetFiles`** `string[]` array of file paths
130
130
  */
131
131
  export declare function getDirectoryFiles(dir: string, basenameOnly: boolean, ...targetExtensions: string[]): string[];
@@ -133,21 +133,38 @@ export declare function getDirectoryFiles(dir: string, basenameOnly: boolean, ..
133
133
  * `sync`
134
134
  * @param dir `string` path to target directory
135
135
  * @param targetExtensions `string[] (optional)` - array of file extensions to filter files by.
136
- * - `If` not provided, all files in the directory will be returned.
137
- * - `If` provided, only files with extensions matching the array will be returned.
136
+ * - `if undefined`, all files in the directory will be returned.
137
+ * - `if defined`, only files with extensions matching the array will be returned.
138
138
  * @returns **`targetFiles`** `string[]` array of `full` file paths
139
139
  */
140
140
  export declare function getDirectoryFiles(dir: string, ...targetExtensions: string[]): string[];
141
+ /**
142
+ * `sync`
143
+ * @param dir `string` path to target directory
144
+ * @param options {@link DirectoryFileOptions}
145
+ * = `{ basenameOnly?: boolean, recursive?: boolean, targetExtensions?: string[] }`
146
+ * @param options.basenameOnly `boolean (optional)` `default` = `false`
147
+ * - `if true`, returned array elements are of form: `path.basename(file)`
148
+ * - `if false`, returned array elements are of form: `path.join(dir, file)`
149
+ * @param options.recursive `boolean (optional)` `default` = `false`
150
+ * - `true` - get files from `dir` and all of its subdirectories
151
+ * - `false` - only get files from `dir` (i.e. direct descendants of `dir`)
152
+ * @param options.targetExtensions `string[] (optional)` - array of file extensions to filter files by.
153
+ * - `if undefined`, all files in the directory will be returned.
154
+ * - `if defined`, only files with extensions matching the array will be returned.
155
+ * @returns **`targetFiles`** `string[]` array of file paths
156
+ */
157
+ export declare function getDirectoryFiles(dir: string, options: DirectoryFileOptions): string[];
141
158
  /**
142
159
  * @param dataSource `string | FileData | Record<string, any>[]`
143
160
  * @param keyColumn `string`
144
161
  * @param valueColumn `string`
145
- * @param keyOptions {@link CleanStringOptions} `(optional)`
146
- * @param valueOptions {@link CleanStringOptions}`(optional)`
162
+ * @param keyOptions {@link DEP_CleanStringOptions} `(optional)`
163
+ * @param valueOptions {@link DEP_CleanStringOptions}`(optional)`
147
164
  * @param sheetName `string`
148
165
  * @returns **`dict`** `Promise<Record<string, string[]>>`
149
166
  */
150
- export declare function getOneToManyDictionary(dataSource: string | FileData | Record<string, any>[], keyColumn: string, valueColumn: string, keyOptions?: CleanStringOptions, valueOptions?: CleanStringOptions, sheetName?: string): Promise<Record<string, string[]>>;
167
+ export declare function getOneToManyDictionary(dataSource: string | FileData | Record<string, any>[], keyColumn: string, valueColumn: string, keyOptions?: DEP_CleanStringOptions, valueOptions?: DEP_CleanStringOptions, sheetName?: string): Promise<Record<string, string[]>>;
151
168
  /**
152
169
  * @deprecated `use `{@link getOneToManyDictionary}
153
170
  * @param filePath `string`
@@ -155,19 +172,19 @@ export declare function getOneToManyDictionary(dataSource: string | FileData | R
155
172
  * @param keyColumn `string`
156
173
  * @param valueColumn `string`
157
174
  * @param options - {@link ParseOneToManyOptions}
158
- * = `{ keyStripOptions`?: {@link StringStripOptions}, `valueStripOptions`?: {@link StringStripOptions}, keyCaseOptions`?: {@link StringCaseOptions}, `valueCaseOptions`?: {@link StringCaseOptions}, `keyPadOptions`?: {@link StringPadOptions}, `valuePadOptions`?: {@link StringPadOptions} `}`
159
- * - {@link StringStripOptions} = `{ char`: `string`, `escape`?: `boolean`, `stripLeftCondition`?: `(s: string, ...args: any[]) => boolean`, `leftArgs`?: `any[]`, `stripRightCondition`?: `(s: string, ...args: any[]) => boolean`, `rightArgs`?: `any[] }`
160
- * - {@link StringCaseOptions} = `{ toUpper`?: `boolean`, `toLower`?: `boolean`, `toTitle`?: `boolean }`
175
+ * = `{ keyStripOptions`?: {@link DEP_StringStripOptions}, `valueStripOptions`?: {@link DEP_StringStripOptions}, keyCaseOptions`?: {@link StringCaseOptions}, `valueCaseOptions`?: {@link StringCaseOptions}, `keyPadOptions`?: {@link StringPadOptions}, `valuePadOptions`?: {@link StringPadOptions} `}`
176
+ * - {@link DEP_StringStripOptions} = `{ char`: `string`, `escape`?: `boolean`, `stripLeftCondition`?: `(s: string, ...args: any[]) => boolean`, `leftArgs`?: `any[]`, `stripRightCondition`?: `(s: string, ...args: any[]) => boolean`, `rightArgs`?: `any[] }`
177
+ * - {@link DEP_StringCaseOptions} = `{ toUpper`?: `boolean`, `toLower`?: `boolean`, `toTitle`?: `boolean }`
161
178
  * - {@link StringPadOptions} = `{ padLength`: `number`, `padChar`?: `string`, `padLeft`?: `boolean`, `padRight`?: `boolean }`
162
179
  * @returns **`dict`** `Record<string, Array<string>>` — key-value pairs where key is from `keyColumn` and value is an array of values from `valueColumn`
163
180
  */
164
181
  export declare function parseExcelForOneToMany(filePath: string, sheetName: string, keyColumn: string, valueColumn: string, options?: {
165
- keyStripOptions?: StringStripOptions;
166
- valueStripOptions?: StringStripOptions;
167
- keyCaseOptions?: StringCaseOptions;
168
- valueCaseOptions?: StringCaseOptions;
169
- keyPadOptions?: StringPadOptions;
170
- valuePadOptions?: StringPadOptions;
182
+ keyStripOptions?: DEP_StringStripOptions;
183
+ valueStripOptions?: DEP_StringStripOptions;
184
+ keyCaseOptions?: DEP_StringCaseOptions;
185
+ valueCaseOptions?: DEP_StringCaseOptions;
186
+ keyPadOptions?: DEP_StringPadOptions;
187
+ valuePadOptions?: DEP_StringPadOptions;
171
188
  }): Record<string, Array<string>>;
172
189
  /**
173
190
  * @deprecated -> use {@link getOneToManyDictionary}
@@ -176,18 +193,18 @@ export declare function parseExcelForOneToMany(filePath: string, sheetName: stri
176
193
  * @param valueColumn `string`
177
194
  * @param delimiter {@link DelimiterCharacters} | `string`
178
195
  * @param options {@link ParseOneToManyOptions}
179
- * = `{ keyCaseOptions`?: {@link StringCaseOptions}, `valueCaseOptions`?: {@link StringCaseOptions}, `keyPadOptions`?: {@link StringPadOptions}, `valuePadOptions`?: {@link StringPadOptions} `}`
180
- * - {@link StringCaseOptions} = `{ toUpper`?: `boolean`, `toLower`?: `boolean`, `toTitle`?: `boolean }`
196
+ * = `{ keyCaseOptions`?: {@link DEP_StringCaseOptions}, `valueCaseOptions`?: {@link DEP_StringCaseOptions}, `keyPadOptions`?: {@link StringPadOptions}, `valuePadOptions`?: {@link StringPadOptions} `}`
197
+ * - {@link DEP_StringCaseOptions} = `{ toUpper`?: `boolean`, `toLower`?: `boolean`, `toTitle`?: `boolean }`
181
198
  * - {@link StringPadOptions} = `{ padLength`: `number`, `padChar`?: `string`, `padLeft`?: `boolean`, `padRight`?: `boolean }`
182
199
  * @returns `Record<string, Array<string>>` - key-value pairs where key is from `keyColumn` and value is an array of values from `valueColumn`
183
200
  */
184
201
  export declare function parseCsvForOneToMany(filePath: string, keyColumn: string, valueColumn: string, delimiter?: DelimiterCharacterEnum | string, options?: {
185
- keyStripOptions?: StringStripOptions;
186
- valueStripOptions?: StringStripOptions;
187
- keyCaseOptions?: StringCaseOptions;
188
- valueCaseOptions?: StringCaseOptions;
189
- keyPadOptions?: StringPadOptions;
190
- valuePadOptions?: StringPadOptions;
202
+ keyStripOptions?: DEP_StringStripOptions;
203
+ valueStripOptions?: DEP_StringStripOptions;
204
+ keyCaseOptions?: DEP_StringCaseOptions;
205
+ valueCaseOptions?: DEP_StringCaseOptions;
206
+ keyPadOptions?: DEP_StringPadOptions;
207
+ valuePadOptions?: DEP_StringPadOptions;
191
208
  }): Record<string, Array<string>>;
192
209
  export interface CsvValidationOptions {
193
210
  allowEmptyRows?: boolean;
@@ -446,8 +446,8 @@ async function getOneToOneDictionary(arg1, keyColumn, valueColumn, keyOptions, v
446
446
  config_1.typeshiLogger.warn(msg);
447
447
  continue;
448
448
  }
449
- const key = (0, regex_1.clean)(String(row[keyColumn]), keyOptions);
450
- const value = (0, regex_1.clean)(String(row[valueColumn]), valueOptions);
449
+ const key = (0, regex_1.DEP_clean)(String(row[keyColumn]), keyOptions);
450
+ const value = (0, regex_1.DEP_clean)(String(row[valueColumn]), valueOptions);
451
451
  if (!key || !value) {
452
452
  let msg = [`${source} Row @ index ${i} missing key or value.`,
453
453
  ` keyColumn: '${keyColumn}' in row ? ${keyColumn in row}`,
@@ -573,23 +573,29 @@ async function handleFileArgument(arg1, invocationSource, requiredHeaders = [],
573
573
  /**
574
574
  * `sync`
575
575
  * @param dir `string` path to target directory
576
- * @param arg2 `boolean (optional)` `default` = `false`
576
+ * @param arg2 `boolean (optional)` (`basenameOnly`) `default` = `false`
577
577
  * - `if true`, returned array elements are of form: `path.basename(file)`
578
578
  * - `if false`, returned array elements are of form: `path.join(dir, file)`
579
579
  * @param targetExtensions `string[] (optional)` - array of file extensions to filter files by.
580
- * - `If` not provided, all files in the directory will be returned.
581
- * - `If` provided, only files with extensions matching the array will be returned.
580
+ * - `if undefined`, all files in the directory will be returned.
581
+ * - `if defined` provided, only files with extensions matching the array will be returned.
582
582
  * @returns **`targetFiles`** `string[]` array of file paths
583
583
  */
584
584
  function getDirectoryFiles(dir, arg2, ...targetExtensions) {
585
585
  const source = (0, logging_1.getSourceString)(__filename, getDirectoryFiles.name);
586
586
  let basenameOnly = false;
587
+ let recursive = false;
587
588
  if ((0, typeValidation_1.isBoolean)(arg2)) {
588
589
  basenameOnly = arg2;
589
590
  }
590
591
  else if ((0, typeValidation_1.isNonEmptyString)(arg2)) {
591
592
  targetExtensions = [arg2, ...targetExtensions];
592
593
  }
594
+ else if ((0, types_1.isDirectoryFileOptions)(arg2)) {
595
+ basenameOnly = arg2.basenameOnly ?? basenameOnly;
596
+ targetExtensions = arg2.targetExtensions ?? [];
597
+ recursive = arg2.recursive ?? false;
598
+ }
593
599
  const targetFiles = [];
594
600
  try {
595
601
  validate.existingDirectoryArgument(source, { dir });
@@ -601,11 +607,23 @@ function getDirectoryFiles(dir, arg2, ...targetExtensions) {
601
607
  targetExtensions[i] = `.${ext}`;
602
608
  }
603
609
  }
604
- targetFiles.push(...fs_1.default.readdirSync(dir)
610
+ const dirContent = fs_1.default.readdirSync(dir);
611
+ targetFiles.push(...dirContent
605
612
  .filter(f => (0, typeValidation_1.isNonEmptyArray)(targetExtensions)
606
613
  ? (0, regex_1.stringEndsWithAnyOf)(f, targetExtensions, regex_1.RegExpFlagsEnum.IGNORE_CASE)
607
614
  : fs_1.default.statSync(node_path_1.default.join(dir, f)).isFile() // get all files in dir, regardless of extension
608
615
  ).map(f => basenameOnly ? f : node_path_1.default.join(dir, f)));
616
+ if (recursive) {
617
+ const childDirs = dirContent
618
+ .filter(c => isDirectory(node_path_1.default.join(dir, c)))
619
+ .map(c => node_path_1.default.join(dir, c));
620
+ for (let childDir of childDirs) {
621
+ targetFiles.push(...getDirectoryFiles(childDir, {
622
+ basenameOnly, recursive, targetExtensions
623
+ }));
624
+ }
625
+ }
626
+ return targetFiles;
609
627
  }
610
628
  catch (error) {
611
629
  config_1.typeshiLogger.error([`${source} Error retrieving directory files, returning empty array`,
@@ -616,14 +634,13 @@ function getDirectoryFiles(dir, arg2, ...targetExtensions) {
616
634
  ].join(config_1.INDENT_LOG_LINE));
617
635
  return [];
618
636
  }
619
- return targetFiles;
620
637
  }
621
638
  /**
622
639
  * @param dataSource `string | FileData | Record<string, any>[]`
623
640
  * @param keyColumn `string`
624
641
  * @param valueColumn `string`
625
- * @param keyOptions {@link CleanStringOptions} `(optional)`
626
- * @param valueOptions {@link CleanStringOptions}`(optional)`
642
+ * @param keyOptions {@link DEP_CleanStringOptions} `(optional)`
643
+ * @param valueOptions {@link DEP_CleanStringOptions}`(optional)`
627
644
  * @param sheetName `string`
628
645
  * @returns **`dict`** `Promise<Record<string, string[]>>`
629
646
  */
@@ -631,18 +648,18 @@ async function getOneToManyDictionary(dataSource, keyColumn, valueColumn, keyOpt
631
648
  const source = (0, logging_1.getSourceString)(__filename, getOneToManyDictionary.name);
632
649
  validate.multipleStringArguments(source, { keyColumn, valueColumn });
633
650
  if (keyOptions)
634
- validate.objectArgument(source, { keyOptions, isCleanStringOptions: regex_1.isCleanStringOptions });
651
+ validate.objectArgument(source, { keyOptions, DEP_isCleanStringOptions: regex_1.DEP_isCleanStringOptions });
635
652
  if (valueOptions)
636
- validate.objectArgument(source, { valueOptions, isCleanStringOptions: regex_1.isCleanStringOptions });
653
+ validate.objectArgument(source, { valueOptions, DEP_isCleanStringOptions: regex_1.DEP_isCleanStringOptions });
637
654
  const rows = await handleFileArgument(dataSource, source, [keyColumn, valueColumn], sheetName);
638
655
  const dict = {};
639
656
  for (let i = 0; i < rows.length; i++) {
640
657
  let row = rows[i];
641
- let key = (0, regex_1.clean)(row[keyColumn], keyOptions).trim().replace(/\.$/, '');
658
+ let key = (0, regex_1.DEP_clean)(row[keyColumn], keyOptions).trim().replace(/\.$/, '');
642
659
  if (!dict[key]) {
643
660
  dict[key] = [];
644
661
  }
645
- let value = (0, regex_1.clean)(row[valueColumn], valueOptions).trim().replace(/\.$/, '');
662
+ let value = (0, regex_1.DEP_clean)(row[valueColumn], valueOptions).trim().replace(/\.$/, '');
646
663
  if (!dict[key].includes(value)) {
647
664
  dict[key].push(value);
648
665
  }
@@ -656,9 +673,9 @@ async function getOneToManyDictionary(dataSource, keyColumn, valueColumn, keyOpt
656
673
  * @param keyColumn `string`
657
674
  * @param valueColumn `string`
658
675
  * @param options - {@link ParseOneToManyOptions}
659
- * = `{ keyStripOptions`?: {@link StringStripOptions}, `valueStripOptions`?: {@link StringStripOptions}, keyCaseOptions`?: {@link StringCaseOptions}, `valueCaseOptions`?: {@link StringCaseOptions}, `keyPadOptions`?: {@link StringPadOptions}, `valuePadOptions`?: {@link StringPadOptions} `}`
660
- * - {@link StringStripOptions} = `{ char`: `string`, `escape`?: `boolean`, `stripLeftCondition`?: `(s: string, ...args: any[]) => boolean`, `leftArgs`?: `any[]`, `stripRightCondition`?: `(s: string, ...args: any[]) => boolean`, `rightArgs`?: `any[] }`
661
- * - {@link StringCaseOptions} = `{ toUpper`?: `boolean`, `toLower`?: `boolean`, `toTitle`?: `boolean }`
676
+ * = `{ keyStripOptions`?: {@link DEP_StringStripOptions}, `valueStripOptions`?: {@link DEP_StringStripOptions}, keyCaseOptions`?: {@link StringCaseOptions}, `valueCaseOptions`?: {@link StringCaseOptions}, `keyPadOptions`?: {@link StringPadOptions}, `valuePadOptions`?: {@link StringPadOptions} `}`
677
+ * - {@link DEP_StringStripOptions} = `{ char`: `string`, `escape`?: `boolean`, `stripLeftCondition`?: `(s: string, ...args: any[]) => boolean`, `leftArgs`?: `any[]`, `stripRightCondition`?: `(s: string, ...args: any[]) => boolean`, `rightArgs`?: `any[] }`
678
+ * - {@link DEP_StringCaseOptions} = `{ toUpper`?: `boolean`, `toLower`?: `boolean`, `toTitle`?: `boolean }`
662
679
  * - {@link StringPadOptions} = `{ padLength`: `number`, `padChar`?: `string`, `padLeft`?: `boolean`, `padRight`?: `boolean }`
663
680
  * @returns **`dict`** `Record<string, Array<string>>` — key-value pairs where key is from `keyColumn` and value is an array of values from `valueColumn`
664
681
  */
@@ -672,8 +689,8 @@ function parseExcelForOneToMany(filePath, sheetName, keyColumn, valueColumn, opt
672
689
  const jsonData = xlsx_1.default.utils.sheet_to_json(sheet);
673
690
  const dict = {};
674
691
  jsonData.forEach(row => {
675
- let key = (0, regex_1.clean)(String(row[keyColumn]), keyStripOptions, keyCaseOptions, keyPadOptions).trim().replace(/\.$/, '');
676
- let val = (0, regex_1.clean)(String(row[valueColumn]), valueStripOptions, valueCaseOptions, valuePadOptions).trim().replace(/\.$/, '');
692
+ let key = (0, regex_1.DEP_clean)(String(row[keyColumn]), keyStripOptions, keyCaseOptions, keyPadOptions).trim().replace(/\.$/, '');
693
+ let val = (0, regex_1.DEP_clean)(String(row[valueColumn]), valueStripOptions, valueCaseOptions, valuePadOptions).trim().replace(/\.$/, '');
677
694
  if (!dict[key]) {
678
695
  dict[key] = [];
679
696
  }
@@ -695,8 +712,8 @@ function parseExcelForOneToMany(filePath, sheetName, keyColumn, valueColumn, opt
695
712
  * @param valueColumn `string`
696
713
  * @param delimiter {@link DelimiterCharacters} | `string`
697
714
  * @param options {@link ParseOneToManyOptions}
698
- * = `{ keyCaseOptions`?: {@link StringCaseOptions}, `valueCaseOptions`?: {@link StringCaseOptions}, `keyPadOptions`?: {@link StringPadOptions}, `valuePadOptions`?: {@link StringPadOptions} `}`
699
- * - {@link StringCaseOptions} = `{ toUpper`?: `boolean`, `toLower`?: `boolean`, `toTitle`?: `boolean }`
715
+ * = `{ keyCaseOptions`?: {@link DEP_StringCaseOptions}, `valueCaseOptions`?: {@link DEP_StringCaseOptions}, `keyPadOptions`?: {@link StringPadOptions}, `valuePadOptions`?: {@link StringPadOptions} `}`
716
+ * - {@link DEP_StringCaseOptions} = `{ toUpper`?: `boolean`, `toLower`?: `boolean`, `toTitle`?: `boolean }`
700
717
  * - {@link StringPadOptions} = `{ padLength`: `number`, `padChar`?: `string`, `padLeft`?: `boolean`, `padRight`?: `boolean }`
701
718
  * @returns `Record<string, Array<string>>` - key-value pairs where key is from `keyColumn` and value is an array of values from `valueColumn`
702
719
  */
@@ -719,8 +736,8 @@ function parseCsvForOneToMany(filePath, keyColumn, valueColumn, delimiter = type
719
736
  for (let i = 1; i < lines.length; i++) {
720
737
  const line = lines[i].split(delimiter).map(col => col.trim());
721
738
  if (line.length > 1) {
722
- let key = (0, regex_1.clean)(line[keyIndex], keyStripOptions, keyCaseOptions, keyPadOptions);
723
- let val = (0, regex_1.clean)(line[valueIndex], valueStripOptions, valueCaseOptions, valuePadOptions);
739
+ let key = (0, regex_1.DEP_clean)(line[keyIndex], keyStripOptions, keyCaseOptions, keyPadOptions);
740
+ let val = (0, regex_1.DEP_clean)(line[valueIndex], valueStripOptions, valueCaseOptions, valuePadOptions);
724
741
  if (!dict[key]) {
725
742
  dict[key] = [];
726
743
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @file src/utils/io/types/typeGuards.ts
3
3
  */
4
- import { FileData, NodeLeaves, NodeStructure, RowDictionary, RowSourceMetaData, WriteJsonOptions } from "..";
4
+ import { FileData, NodeLeaves, NodeStructure, DirectoryFileOptions, RowDictionary, RowSourceMetaData, WriteJsonOptions } from ".";
5
5
  /**
6
6
  * @param value `any`
7
7
  * @returns **`isRowSourceMetaData`** `boolean`
@@ -29,3 +29,4 @@ export declare function isWriteJsonOptions(value: any): value is WriteJsonOption
29
29
  * - **`false`** `otherwise`.
30
30
  */
31
31
  export declare function isFileData(value: any): value is FileData;
32
+ export declare function isDirectoryFileOptions(value: unknown): value is DirectoryFileOptions;
@@ -9,6 +9,7 @@ exports.isNodeStructure = isNodeStructure;
9
9
  exports.isNodeLeaves = isNodeLeaves;
10
10
  exports.isWriteJsonOptions = isWriteJsonOptions;
11
11
  exports.isFileData = isFileData;
12
+ exports.isDirectoryFileOptions = isDirectoryFileOptions;
12
13
  const typeValidation_1 = require("../../typeValidation");
13
14
  /**
14
15
  * @param value `any`
@@ -36,26 +37,21 @@ function isRowDictionary(value) {
36
37
  && typeof value[key] === 'object' && !Array.isArray(value[key])));
37
38
  }
38
39
  function isNodeStructure(value) {
39
- return (value && typeof value === 'object'
40
- && !Array.isArray(value)
41
- && Object.keys(value).length > 0
42
- && Object.entries(value).every(([key, value]) => typeof key === 'string'
43
- && (isNodeStructure(value) || isNodeLeaves(value))));
40
+ const candidate = value;
41
+ return ((0, typeValidation_1.isObject)(candidate)
42
+ && Object.entries(candidate).every(([k, v]) => (0, typeValidation_1.isNonEmptyString)(k) && (isNodeLeaves(v) || isNodeStructure(v))));
44
43
  }
45
44
  function isNodeLeaves(value) {
46
45
  return ((Array.isArray(value) && value.every(v => typeof v === 'number'))
47
46
  || isRowDictionary(value));
48
47
  }
49
48
  function isWriteJsonOptions(value) {
50
- return (value && typeof value === 'object'
51
- && !Array.isArray(value)
52
- && value.data !== undefined
53
- && (typeof value.data === 'object' || typeof value.data === 'string')
54
- && (0, typeValidation_1.isNonEmptyString)(value.filePath)
55
- && (value.indent === undefined
56
- || (typeof value.indent === 'number' && value.indent >= 0))
57
- && (value.enableOverwrite === undefined
58
- || typeof value.enableOverwrite === 'boolean'));
49
+ const candidate = value;
50
+ return ((0, typeValidation_1.isObject)(candidate)
51
+ && (typeof candidate.data === 'string' || (0, typeValidation_1.isObject)(candidate.data))
52
+ && (0, typeValidation_1.isNonEmptyString)(candidate.filePath)
53
+ && typeValidation_1.isUndefinedOr.positiveInteger(candidate.indent)
54
+ && typeValidation_1.isUndefinedOr.boolean(candidate.enableOverwrite));
59
55
  }
60
56
  /**
61
57
  * @consideration `FILE_NAME_WITH_EXTENSION_PATTERN = /^[^/\\:*?"<>|]+(\.[^/\\:*?"<>|]+)$/`
@@ -67,9 +63,15 @@ function isWriteJsonOptions(value) {
67
63
  * - **`false`** `otherwise`.
68
64
  */
69
65
  function isFileData(value) {
70
- return (value && typeof value === 'object'
71
- && (0, typeValidation_1.hasKeys)(value, ['fileName', 'fileContent'])
72
- && (0, typeValidation_1.isNonEmptyString)(value.fileName)
73
- // && fileNamePattern.test(value.fileName)
74
- && (0, typeValidation_1.isNonEmptyString)(value.fileContent));
66
+ const candidate = value;
67
+ return ((0, typeValidation_1.isObject)(candidate)
68
+ && (0, typeValidation_1.isNonEmptyString)(candidate.fileName)
69
+ && (0, typeValidation_1.isNonEmptyString)(candidate.fileContent));
70
+ }
71
+ function isDirectoryFileOptions(value) {
72
+ const candidate = value;
73
+ return ((0, typeValidation_1.isObject)(candidate, false)
74
+ && typeValidation_1.isOptional.stringArray(candidate.targetExtensions)
75
+ && typeValidation_1.isOptional.boolean(candidate.basenameOnly)
76
+ && typeValidation_1.isOptional.boolean(candidate.recursive));
75
77
  }
@@ -1,7 +1,7 @@
1
1
  /**
2
2
  * @file src/utils/io/Io.ts
3
3
  */
4
- import { StringCaseOptions, StringPadOptions, StringStripOptions } from "../../regex/index";
4
+ import { DEP_StringCaseOptions, StringPadOptions, DEP_StringStripOptions } from "../../regex/index";
5
5
  export type WriteJsonOptions = {
6
6
  data: Record<string, any> | string;
7
7
  filePath: string;
@@ -26,7 +26,7 @@ export type RowDictionary = {
26
26
  [rowIndex: number]: Record<string, any>;
27
27
  };
28
28
  /**
29
- * @deprecated use `CleanStringOptions` instead
29
+ * @deprecated
30
30
  * @typedefn **`ParseOneToManyOptions`**
31
31
  * @property {StringStripOptions} keyStripOptions - options for stripping characters from the key
32
32
  * @property {StringStripOptions} valueStripOptions - options for stripping characters from the value
@@ -35,15 +35,15 @@ export type RowDictionary = {
35
35
  * @property {StringPadOptions} keyPadOptions - options for padding values read from the `keyColumn`
36
36
  * @property {StringPadOptions} valuePadOptions - options for padding values read from the `valueColumn`
37
37
  *
38
- * - {@link StringStripOptions} = `{ char: string, escape?: boolean, stripLeftCondition?: (s: string, ...args: any[]) => boolean, leftArgs?: any[], stripRightCondition?: (s: string, ...args: any[]) => boolean, rightArgs?: any[] }`
39
- * - {@link StringCaseOptions} = `{ toUpper: boolean, toLower: boolean, toTitle: boolean }`
38
+ * - {@link DEP_StringStripOptions} = `{ char: string, escape?: boolean, stripLeftCondition?: (s: string, ...args: any[]) => boolean, leftArgs?: any[], stripRightCondition?: (s: string, ...args: any[]) => boolean, rightArgs?: any[] }`
39
+ * - {@link DEP_StringCaseOptions} = `{ toUpper: boolean, toLower: boolean, toTitle: boolean }`
40
40
  * - {@link StringPadOptions} = `{ padLength: number, padChar: string, padLeft: boolean, padRight: boolean }`
41
41
  */
42
42
  export type ParseOneToManyOptions = {
43
- keyStripOptions?: StringStripOptions;
44
- valueStripOptions?: StringStripOptions;
45
- keyCaseOptions?: StringCaseOptions;
46
- valueCaseOptions?: StringCaseOptions;
43
+ keyStripOptions?: DEP_StringStripOptions;
44
+ valueStripOptions?: DEP_StringStripOptions;
45
+ keyCaseOptions?: DEP_StringCaseOptions;
46
+ valueCaseOptions?: DEP_StringCaseOptions;
47
47
  keyPadOptions?: StringPadOptions;
48
48
  valuePadOptions?: StringPadOptions;
49
49
  };
@@ -51,3 +51,25 @@ export type ParseOneToManyOptions = {
51
51
  * common file extensions handled as input/output
52
52
  */
53
53
  export type FileExtension = '.csv' | '.tsv' | '.txt' | '.json' | '.xlsx' | '.xls' | '.xml' | '.yaml' | '.yml';
54
+ /**
55
+ * @interface **`DirectoryFileOptions`** `getDirectoryFiles(parentDir: string, options: DirectoryFileOptions)`
56
+ */
57
+ export interface DirectoryFileOptions {
58
+ /**
59
+ * - `true` - returned array elements are of form: `path.basename(file)`
60
+ * - `false` - returned array elements are of form: `path.join(dir, file)` (i.e. complete file paths)
61
+ * */
62
+ basenameOnly?: boolean;
63
+ /**
64
+ * `default` = `false`
65
+ * - `true` - get files in the `parentDir` and all of its subdirectories
66
+ * - `false` - only get files in the `parentDir`
67
+ * */
68
+ recursive?: boolean;
69
+ /**
70
+ * `(optional)` - array of file extensions to filter files by.
71
+ * - `If` not provided, all files in the directory will be returned.
72
+ * - `If` provided, only files with extensions matching those in the array will be returned.
73
+ * */
74
+ targetExtensions?: string[];
75
+ }
@@ -0,0 +1,79 @@
1
+ /**
2
+ * @file src/utils/regex/Str.ts
3
+ */
4
+ import { stringStartsWithAnyOf, stringEndsWithAnyOf, stringContainsAnyOf, equivalentAlphanumericStrings } from "./stringOperations";
5
+ import { applyCaseOptions, applyReplaceParams, clean as cleanString, applyStripOptions, applyPadOptions } from "./cleaning";
6
+ export declare class Str {
7
+ /**
8
+ * @param s `string`
9
+ * @param prefixes `string | string[] | RegExp` possible starting string(s).
10
+ * @param flags `RegExpFlagsEnum[] (Optional)` regex flags to use when creating the {@link RegExp} object. see {@link RegExpFlagsEnum}
11
+ * @returns **`true`** if the string starts with any of the prefixes, **`false`** otherwise.
12
+ */
13
+ static startsWith: typeof stringStartsWithAnyOf;
14
+ /**
15
+ * Checks if a string ends with any of the specified suffixes.
16
+ * @param s `string`
17
+ * @param suffixes `string | string[] | RegExp` possible ending strings.
18
+ * @param flags `RegExpFlagsEnum[] (Optional)` regex flags to use when creating the {@link RegExp} object. see {@link RegExpFlagsEnum}
19
+ * @returns **`true`** if the string ends with any of the suffixes, **`false`** otherwise.
20
+ */
21
+ static endsWith: typeof stringEndsWithAnyOf;
22
+ /**
23
+ * @param s `string`
24
+ * @param substrings `string | string[] | RegExp`
25
+ * @param flags `RegExpFlagsEnum[] (Optional)` regex flags to use when creating the {@link RegExp} object. see {@link RegExpFlagsEnum}
26
+ * @returns **`true`** if the string contains any of the substrings, **`false`** otherwise.
27
+ */
28
+ static contains: typeof stringContainsAnyOf;
29
+ /**
30
+ * Ignores case by default:
31
+ * - converts `s1` & `s2` to lowercase and removes all non-alphanumeric characters from both strings,
32
+ * - sorts the characters in both strings,
33
+ * - then compares the two strings for equivalence.
34
+ * @param s1 `string`
35
+ * @param s2 `string`
36
+ * @param tolerance `number` - a number between 0 and 1, default is `0.90`
37
+ * @returns **`boolean`**
38
+ * - **`true`** `if` the two alphanumeric strings are equivalent,
39
+ * - **`false`** `otherwise`.
40
+ */
41
+ static equivalentAlphanumeric: typeof equivalentAlphanumericStrings;
42
+ /**
43
+ * @param s `string`
44
+ * @param options {@link StringCleanOptions} `(optional)`
45
+ * @param options.useDefault `boolean (optional)` `default` = `true`
46
+ * - `if true` - calls `s.trim()` and replaces `/\s{2,}/g` with single space, `/\.{2,}/g` with single period, and `/,{2,}/g` with single comma
47
+ * *before* proceeding with remaining operations
48
+ * @returns **`s`** `string` = the modified string after applying operations specified in `options`
49
+ */
50
+ static clean: typeof cleanString;
51
+ /**
52
+ * @param s `string`
53
+ * @param caseOptions {@link StringCaseEnum} = 'upper' | 'lower' | 'title'
54
+ * @returns **`s`** `string` with case option applied
55
+ */
56
+ static toCase: typeof applyCaseOptions;
57
+ /**
58
+ * @param s `string`
59
+ * @param options {@link StringPadOptions}
60
+ * @param options.side `'left' | 'right' | 'both'`
61
+ * - `left` -> use `s.padStart()`
62
+ * - `right` -> use `s.padEnd()`
63
+ * - `both` -> apply half padding to both sides
64
+ * @returns **`s`** `string` padded to length = `options.maxLength`
65
+ */
66
+ static pad: typeof applyPadOptions;
67
+ /**
68
+ * @param s `string`
69
+ * @param replaceParams `Array<`{@link StringReplaceParams}`>`
70
+ * @returns **`s`** `string` with replace options applied
71
+ */
72
+ static replace: typeof applyReplaceParams;
73
+ /**
74
+ * @param s `string`
75
+ * @param options {@link StringStripOptions} = `{ char?: string, left?: StringStripCondition, right?: StringStripCondition }`
76
+ * @returns **`s`**
77
+ */
78
+ static strip: typeof applyStripOptions;
79
+ }