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.
- package/dist/utils/argumentValidation.js +0 -19
- package/dist/utils/io/logging.js +8 -8
- package/dist/utils/io/reading.d.ts +44 -27
- package/dist/utils/io/reading.js +39 -22
- package/dist/utils/io/types/Io.TypeGuards.d.ts +2 -1
- package/dist/utils/io/types/Io.TypeGuards.js +21 -19
- package/dist/utils/io/types/Io.d.ts +30 -8
- package/dist/utils/regex/Str.d.ts +79 -0
- package/dist/utils/regex/Str.js +83 -0
- package/dist/utils/regex/cleaning.d.ts +70 -37
- package/dist/utils/regex/cleaning.js +217 -57
- package/dist/utils/regex/configureParameters.d.ts +3 -3
- package/dist/utils/regex/entity.js +3 -3
- package/dist/utils/regex/index.d.ts +1 -0
- package/dist/utils/regex/index.js +1 -0
- package/dist/utils/regex/phone.js +1 -1
- package/dist/utils/regex/stringOperations.d.ts +0 -37
- package/dist/utils/regex/stringOperations.js +16 -46
- package/dist/utils/regex/types/StringOptions.TypeGuards.d.ts +20 -0
- package/dist/utils/regex/types/StringOptions.TypeGuards.js +77 -0
- package/dist/utils/regex/types/StringOptions.d.ts +65 -21
- package/dist/utils/regex/types/StringOptions.js +11 -1
- package/dist/utils/regex/types/index.d.ts +1 -1
- package/dist/utils/regex/types/index.js +1 -1
- package/dist/utils/typeValidation.d.ts +50 -13
- package/dist/utils/typeValidation.js +60 -14
- package/package.json +1 -1
- package/dist/utils/regex/types/typeGuards.d.ts +0 -12
- package/dist/utils/regex/types/typeGuards.js +0 -15
|
@@ -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;
|
package/dist/utils/io/logging.js
CHANGED
|
@@ -107,20 +107,20 @@ function autoFormatLogsOnExit(filePaths) {
|
|
|
107
107
|
* @returns `void`
|
|
108
108
|
*/
|
|
109
109
|
function formatDebugLogFile(inputPath, outputPath) {
|
|
110
|
-
|
|
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(
|
|
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 {
|
|
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?:
|
|
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
|
-
* - `
|
|
128
|
-
* - `
|
|
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
|
-
* - `
|
|
137
|
-
* - `
|
|
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
|
|
146
|
-
* @param valueOptions {@link
|
|
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?:
|
|
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
|
|
159
|
-
* - {@link
|
|
160
|
-
* - {@link
|
|
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?:
|
|
166
|
-
valueStripOptions?:
|
|
167
|
-
keyCaseOptions?:
|
|
168
|
-
valueCaseOptions?:
|
|
169
|
-
keyPadOptions?:
|
|
170
|
-
valuePadOptions?:
|
|
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
|
|
180
|
-
* - {@link
|
|
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?:
|
|
186
|
-
valueStripOptions?:
|
|
187
|
-
keyCaseOptions?:
|
|
188
|
-
valueCaseOptions?:
|
|
189
|
-
keyPadOptions?:
|
|
190
|
-
valuePadOptions?:
|
|
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;
|
package/dist/utils/io/reading.js
CHANGED
|
@@ -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.
|
|
450
|
-
const value = (0, regex_1.
|
|
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
|
-
* - `
|
|
581
|
-
* - `
|
|
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
|
-
|
|
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
|
|
626
|
-
* @param valueOptions {@link
|
|
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,
|
|
651
|
+
validate.objectArgument(source, { keyOptions, DEP_isCleanStringOptions: regex_1.DEP_isCleanStringOptions });
|
|
635
652
|
if (valueOptions)
|
|
636
|
-
validate.objectArgument(source, { valueOptions,
|
|
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.
|
|
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.
|
|
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
|
|
660
|
-
* - {@link
|
|
661
|
-
* - {@link
|
|
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.
|
|
676
|
-
let val = (0, regex_1.
|
|
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
|
|
699
|
-
* - {@link
|
|
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.
|
|
723
|
-
let val = (0, regex_1.
|
|
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
|
-
|
|
40
|
-
|
|
41
|
-
&& Object.
|
|
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
|
-
|
|
51
|
-
|
|
52
|
-
&&
|
|
53
|
-
&& (
|
|
54
|
-
&&
|
|
55
|
-
&& (
|
|
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
|
-
|
|
71
|
-
|
|
72
|
-
&& (0, typeValidation_1.isNonEmptyString)(
|
|
73
|
-
|
|
74
|
-
|
|
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 {
|
|
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
|
|
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
|
|
39
|
-
* - {@link
|
|
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?:
|
|
44
|
-
valueStripOptions?:
|
|
45
|
-
keyCaseOptions?:
|
|
46
|
-
valueCaseOptions?:
|
|
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
|
+
}
|