filemail-sdk 9.0.6 → 9.0.7
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/src/downloader/downloadFolderResolver.d.ts.map +1 -1
- package/dist/src/downloader/downloadFolderResolver.js +5 -1
- package/dist/src/downloader/downloadFolderResolver.js.map +1 -1
- package/dist/src/utils/fileSystem/node/nodeFileSystemService.d.ts +1 -0
- package/dist/src/utils/fileSystem/node/nodeFileSystemService.d.ts.map +1 -1
- package/dist/src/utils/fileSystem/node/nodeFileSystemService.js +25 -1
- package/dist/src/utils/fileSystem/node/nodeFileSystemService.js.map +1 -1
- package/package.json +1 -1
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"downloadFolderResolver.d.ts","sourceRoot":"","sources":["../../../src/downloader/downloadFolderResolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,mBAAmB,MAAM,0CAA0C,CAAC;AAIhF,MAAM,CAAC,OAAO,OAAO,sBAAsB;;IAiEvC,MAAM,CAAC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,mBAAmB;
|
|
1
|
+
{"version":3,"file":"downloadFolderResolver.d.ts","sourceRoot":"","sources":["../../../src/downloader/downloadFolderResolver.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,mBAAmB,MAAM,0CAA0C,CAAC;AAIhF,MAAM,CAAC,OAAO,OAAO,sBAAsB;;IAiEvC,MAAM,CAAC,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,EAAE,mBAAmB;CAgF/E"}
|
|
@@ -93,7 +93,11 @@ export default class DownloadFolderResolver {
|
|
|
93
93
|
}
|
|
94
94
|
*/
|
|
95
95
|
// replace remaining < and > (they are used as placeholder boundaries) and other chars which are not allowed in Windows folder paths
|
|
96
|
-
result = result.replace(/<([
|
|
96
|
+
result = result.replace(/<([^:>]+)(?::([^>]*))?>/g, (_match, name) => {
|
|
97
|
+
// Remove backslashes from the captured name
|
|
98
|
+
const clean = String(name).replace(/\\/g, ``);
|
|
99
|
+
return `[missing_${clean}]`;
|
|
100
|
+
});
|
|
97
101
|
if (process.platform === `win32`)
|
|
98
102
|
result = DownloadFolderResolver.#trimFolders(result);
|
|
99
103
|
return result;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"downloadFolderResolver.js","sourceRoot":"","sources":["../../../src/downloader/downloadFolderResolver.ts"],"names":[],"mappings":"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","sourcesContent":["import SimpleDateFormatter from \"../utils/dateAndTime/simpleDateFormatter.js\";\r\nimport type GetTransferResponse from \"../utils/api/dtos/getTransferResponse.js\";\r\n\r\nconst DefaultMaxPlaceholderLength = 60;\r\n\r\nexport default class DownloadFolderResolver {\r\n static #pathFriendlyDate(date: string): string {\r\n return date\r\n .replace(/:+/g, `-`)\r\n .replace(/-+/g, `-`);\r\n }\r\n\r\n static #sanitizePathElement(value: string | null | undefined): string {\r\n if (!value)\r\n return ``;\r\n\r\n return value\r\n .replaceAll(`..\\\\`, ``)\r\n .replaceAll(`../`, ``)\r\n .replaceAll(`..`, ``)\r\n .replaceAll(`:`, ``)\r\n .replaceAll(`<`, ``)\r\n .replaceAll(`>`, ``)\r\n .replaceAll(`\\\\`, ``)\r\n .replaceAll(`/`, ``)\r\n .replace(/(\\n|\\r\\n){1,}/g, ` `);\r\n }\r\n\r\n static #getDomain(fromEmail: string | null | undefined) {\r\n if (fromEmail) {\r\n const idx = fromEmail.indexOf(`@`);\r\n if (idx > -1)\r\n return fromEmail.substring(idx + 1);\r\n }\r\n return `[missing_domain]`;\r\n }\r\n\r\n static #escapeRegExp(str: string): string {\r\n return str.replace(/[.*+?^${}()|[\\]\\\\/-]/g, `\\\\$&`);\r\n }\r\n\r\n static #placeholderRegexForSubstring = (token: string) => {\r\n // eslint-disable-next-line no-param-reassign\r\n token = this.#escapeRegExp(token);\r\n return new RegExp(`<${token}(:(.*?))?>`, `g`);\r\n };\r\n\r\n static #replacePlaceholderWithMaxLength(input: string, rx: RegExp, replaceValue: string): string {\r\n return input.replace(rx, (_0: any, _1: any, maxLength: string | undefined): string => {\r\n let substringLength = DefaultMaxPlaceholderLength;\r\n if (!!maxLength && maxLength.length > 0) {\r\n try {\r\n substringLength = parseInt(maxLength, 10);\r\n if (Number.isNaN(substringLength))\r\n substringLength = DefaultMaxPlaceholderLength;\r\n }\r\n catch {\r\n substringLength = DefaultMaxPlaceholderLength;\r\n }\r\n }\r\n\r\n const sanitized = DownloadFolderResolver.#sanitizePathElement(replaceValue);\r\n\r\n if (substringLength < 0)\r\n return sanitized.substring(sanitized.length + substringLength);\r\n\r\n return sanitized.substring(0, substringLength);\r\n });\r\n }\r\n\r\n static prepareDownloadFolder(template: string, transfer: GetTransferResponse) {\r\n let result = template;\r\n if (transfer.from) {\r\n const domain = DownloadFolderResolver.#getDomain(transfer.from);\r\n result = result\r\n .replaceAll(`<domain>`, DownloadFolderResolver.#sanitizePathElement(domain))\r\n .replaceAll(`<emailfrom>`, DownloadFolderResolver.#sanitizePathElement(transfer.from));\r\n }\r\n result = result.replaceAll(`<id>`, transfer.id);\r\n\r\n // datesent\r\n result = result.replace(/<datesent(:(.*?))?>/g, (_0: any, _1: any, dateFormatString: string | undefined): string => {\r\n const dateFormatted = SimpleDateFormatter.formatDateAndTimeLocal(transfer.sentdate, dateFormatString);\r\n return DownloadFolderResolver.#sanitizePathElement(DownloadFolderResolver.#pathFriendlyDate(dateFormatted));\r\n });\r\n\r\n if (transfer.message) {\r\n result = DownloadFolderResolver.#replacePlaceholderWithMaxLength(\r\n result,\r\n DownloadFolderResolver.#placeholderRegexForSubstring(`description`),\r\n transfer.message,\r\n );\r\n }\r\n\r\n if (transfer.subject) {\r\n result = DownloadFolderResolver.#replacePlaceholderWithMaxLength(\r\n result,\r\n DownloadFolderResolver.#placeholderRegexForSubstring(`subject`),\r\n transfer.subject,\r\n );\r\n }\r\n\r\n if (transfer.to && transfer.to.length) {\r\n result = DownloadFolderResolver.#replacePlaceholderWithMaxLength(\r\n result,\r\n DownloadFolderResolver.#placeholderRegexForSubstring(`emailto`),\r\n transfer.to.join(`,`),\r\n );\r\n }\r\n\r\n if (transfer.customfields && transfer.customfields.length) {\r\n for (const cf of transfer.customfields) {\r\n if (cf.label && cf.value) {\r\n result = DownloadFolderResolver.#replacePlaceholderWithMaxLength(\r\n result,\r\n DownloadFolderResolver.#placeholderRegexForSubstring(cf.label),\r\n cf.value,\r\n );\r\n }\r\n }\r\n }\r\n // remaining custom fields which have not bee replaced from transfer - remove them\r\n /*\r\n if (company && company.customfields && company.customfields.length) {\r\n for (const cf of company.customfields)\r\n result = result.replace(new RegExp(`<${cf.label}>`, `ig`), ``);\r\n }\r\n */\r\n\r\n // replace remaining < and > (they are used as placeholder boundaries) and other chars which are not allowed in Windows folder paths\r\n result = result.replace(/<([\\w\\s]+)(:(.*?))?>/g, `[missing_$1]`);\r\n\r\n if (process.platform === `win32`)\r\n result = DownloadFolderResolver.#trimFolders(result);\r\n\r\n return result;\r\n }\r\n\r\n static #trimFolders(template: string) {\r\n const folders = template.replaceAll(`/`, `\\\\`).split(`\\\\`);\r\n\r\n for (let i = 0; i < folders.length; i++)\r\n folders[i] = folders[i]!.trim();\r\n\r\n return folders.join(`\\\\`);\r\n }\r\n}\r\n"]}
|
|
1
|
+
{"version":3,"file":"downloadFolderResolver.js","sourceRoot":"","sources":["../../../src/downloader/downloadFolderResolver.ts"],"names":[],"mappings":"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","sourcesContent":["import SimpleDateFormatter from \"../utils/dateAndTime/simpleDateFormatter.js\";\r\nimport type GetTransferResponse from \"../utils/api/dtos/getTransferResponse.js\";\r\n\r\nconst DefaultMaxPlaceholderLength = 60;\r\n\r\nexport default class DownloadFolderResolver {\r\n static #pathFriendlyDate(date: string): string {\r\n return date\r\n .replace(/:+/g, `-`)\r\n .replace(/-+/g, `-`);\r\n }\r\n\r\n static #sanitizePathElement(value: string | null | undefined): string {\r\n if (!value)\r\n return ``;\r\n\r\n return value\r\n .replaceAll(`..\\\\`, ``)\r\n .replaceAll(`../`, ``)\r\n .replaceAll(`..`, ``)\r\n .replaceAll(`:`, ``)\r\n .replaceAll(`<`, ``)\r\n .replaceAll(`>`, ``)\r\n .replaceAll(`\\\\`, ``)\r\n .replaceAll(`/`, ``)\r\n .replace(/(\\n|\\r\\n){1,}/g, ` `);\r\n }\r\n\r\n static #getDomain(fromEmail: string | null | undefined) {\r\n if (fromEmail) {\r\n const idx = fromEmail.indexOf(`@`);\r\n if (idx > -1)\r\n return fromEmail.substring(idx + 1);\r\n }\r\n return `[missing_domain]`;\r\n }\r\n\r\n static #escapeRegExp(str: string): string {\r\n return str.replace(/[.*+?^${}()|[\\]\\\\/-]/g, `\\\\$&`);\r\n }\r\n\r\n static #placeholderRegexForSubstring = (token: string) => {\r\n // eslint-disable-next-line no-param-reassign\r\n token = this.#escapeRegExp(token);\r\n return new RegExp(`<${token}(:(.*?))?>`, `g`);\r\n };\r\n\r\n static #replacePlaceholderWithMaxLength(input: string, rx: RegExp, replaceValue: string): string {\r\n return input.replace(rx, (_0: any, _1: any, maxLength: string | undefined): string => {\r\n let substringLength = DefaultMaxPlaceholderLength;\r\n if (!!maxLength && maxLength.length > 0) {\r\n try {\r\n substringLength = parseInt(maxLength, 10);\r\n if (Number.isNaN(substringLength))\r\n substringLength = DefaultMaxPlaceholderLength;\r\n }\r\n catch {\r\n substringLength = DefaultMaxPlaceholderLength;\r\n }\r\n }\r\n\r\n const sanitized = DownloadFolderResolver.#sanitizePathElement(replaceValue);\r\n\r\n if (substringLength < 0)\r\n return sanitized.substring(sanitized.length + substringLength);\r\n\r\n return sanitized.substring(0, substringLength);\r\n });\r\n }\r\n\r\n static prepareDownloadFolder(template: string, transfer: GetTransferResponse) {\r\n let result = template;\r\n if (transfer.from) {\r\n const domain = DownloadFolderResolver.#getDomain(transfer.from);\r\n result = result\r\n .replaceAll(`<domain>`, DownloadFolderResolver.#sanitizePathElement(domain))\r\n .replaceAll(`<emailfrom>`, DownloadFolderResolver.#sanitizePathElement(transfer.from));\r\n }\r\n result = result.replaceAll(`<id>`, transfer.id);\r\n\r\n // datesent\r\n result = result.replace(/<datesent(:(.*?))?>/g, (_0: any, _1: any, dateFormatString: string | undefined): string => {\r\n const dateFormatted = SimpleDateFormatter.formatDateAndTimeLocal(transfer.sentdate, dateFormatString);\r\n return DownloadFolderResolver.#sanitizePathElement(DownloadFolderResolver.#pathFriendlyDate(dateFormatted));\r\n });\r\n\r\n if (transfer.message) {\r\n result = DownloadFolderResolver.#replacePlaceholderWithMaxLength(\r\n result,\r\n DownloadFolderResolver.#placeholderRegexForSubstring(`description`),\r\n transfer.message,\r\n );\r\n }\r\n\r\n if (transfer.subject) {\r\n result = DownloadFolderResolver.#replacePlaceholderWithMaxLength(\r\n result,\r\n DownloadFolderResolver.#placeholderRegexForSubstring(`subject`),\r\n transfer.subject,\r\n );\r\n }\r\n\r\n if (transfer.to && transfer.to.length) {\r\n result = DownloadFolderResolver.#replacePlaceholderWithMaxLength(\r\n result,\r\n DownloadFolderResolver.#placeholderRegexForSubstring(`emailto`),\r\n transfer.to.join(`,`),\r\n );\r\n }\r\n\r\n if (transfer.customfields && transfer.customfields.length) {\r\n for (const cf of transfer.customfields) {\r\n if (cf.label && cf.value) {\r\n result = DownloadFolderResolver.#replacePlaceholderWithMaxLength(\r\n result,\r\n DownloadFolderResolver.#placeholderRegexForSubstring(cf.label),\r\n cf.value,\r\n );\r\n }\r\n }\r\n }\r\n // remaining custom fields which have not bee replaced from transfer - remove them\r\n /*\r\n if (company && company.customfields && company.customfields.length) {\r\n for (const cf of company.customfields)\r\n result = result.replace(new RegExp(`<${cf.label}>`, `ig`), ``);\r\n }\r\n */\r\n\r\n // replace remaining < and > (they are used as placeholder boundaries) and other chars which are not allowed in Windows folder paths\r\n result = result.replace(/<([^:>]+)(?::([^>]*))?>/g, (_match, name) => {\r\n // Remove backslashes from the captured name\r\n const clean = String(name).replace(/\\\\/g, ``);\r\n return `[missing_${clean}]`;\r\n });\r\n\r\n if (process.platform === `win32`)\r\n result = DownloadFolderResolver.#trimFolders(result);\r\n\r\n return result;\r\n }\r\n\r\n static #trimFolders(template: string) {\r\n const folders = template.replaceAll(`/`, `\\\\`).split(`\\\\`);\r\n\r\n for (let i = 0; i < folders.length; i++)\r\n folders[i] = folders[i]!.trim();\r\n\r\n return folders.join(`\\\\`);\r\n }\r\n}\r\n"]}
|
|
@@ -9,6 +9,7 @@ export default class NodeFileSystemService implements FileSystemService {
|
|
|
9
9
|
readFileAsString(filePath: string, encoding?: BufferEncoding, abort?: AbortSignal | undefined): Promise<string>;
|
|
10
10
|
pathExists(thePath: string, checkReadWriteAccess?: boolean): Promise<boolean>;
|
|
11
11
|
createFolder(folderPath: string): Promise<void>;
|
|
12
|
+
private mkdirRecursiveSafe;
|
|
12
13
|
createFile(filePath: string, overwriteExisting: boolean, size?: number): Promise<boolean>;
|
|
13
14
|
deleteFile(filePath: string): Promise<boolean>;
|
|
14
15
|
folderIsEmpty(folderPath: string): Promise<boolean>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeFileSystemService.d.ts","sourceRoot":"","sources":["../../../../../src/utils/fileSystem/node/nodeFileSystemService.ts"],"names":[],"mappings":"AAEA,OAAO,iBAAiB,MAAM,+CAA+C,CAAC;AAC9E,OAAO,KAAK,iBAAiB,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,qBAAsB,YAAW,iBAAiB;;IAoB7D,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAM/D,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAuB,EAAE,KAAK,GAAE,WAAW,GAAG,SAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvI,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAI3D,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAuB,EAAE,KAAK,GAAE,WAAW,GAAG,SAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;IAIlI,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAY7E,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"nodeFileSystemService.d.ts","sourceRoot":"","sources":["../../../../../src/utils/fileSystem/node/nodeFileSystemService.ts"],"names":[],"mappings":"AAEA,OAAO,iBAAiB,MAAM,+CAA+C,CAAC;AAC9E,OAAO,KAAK,iBAAiB,MAAM,yBAAyB,CAAC;AAC7D,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAE/C,MAAM,CAAC,OAAO,OAAO,qBAAsB,YAAW,iBAAiB;;IAoB7D,wBAAwB,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,EAAE,CAAC;IAM/D,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAuB,EAAE,KAAK,GAAE,WAAW,GAAG,SAAqB,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvI,eAAe,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC;IAI3D,gBAAgB,CAAC,QAAQ,EAAE,MAAM,EAAE,QAAQ,GAAE,cAAuB,EAAE,KAAK,GAAE,WAAW,GAAG,SAAqB,GAAG,OAAO,CAAC,MAAM,CAAC;IAIlI,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,oBAAoB,CAAC,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAY7E,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;YAmBvC,kBAAkB;IAgC1B,UAAU,CAAC,QAAQ,EAAE,MAAM,EAAE,iBAAiB,EAAE,OAAO,EAAE,IAAI,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAiCzF,UAAU,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAU9C,aAAa,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAKnD,YAAY,CAAC,UAAU,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAIlD,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAK9C,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI3D,UAAU,CAAC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE,QAAQ,CAAC,GAAG,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,GAAG,MAAM;IAIzC,4BAA4B,CAAC,KAAK,EAAE,KAAK,GAAG,iBAAiB,GAAG,SAAS;IAOzE,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,UAAU;IAI3C,cAAc,CAAC,UAAU,EAAE,UAAU,GAAG,MAAM;IAI9C,qBAAqB,CAAC,QAAQ,EAAE,MAAM,EAAE,WAAW,EAAE,MAAM,GAAG,MAAM;CAOvE"}
|
|
@@ -56,7 +56,31 @@ export default class NodeFileSystemService {
|
|
|
56
56
|
if (dirErr && dirErr.code === `EEXIST`)
|
|
57
57
|
// EEXIST error is OK - the requested directory already exists
|
|
58
58
|
return;
|
|
59
|
-
|
|
59
|
+
await this.mkdirRecursiveSafe(folderPath);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
async mkdirRecursiveSafe(target) {
|
|
63
|
+
const foldersChain = [];
|
|
64
|
+
let currentFolder = target;
|
|
65
|
+
while (true) {
|
|
66
|
+
foldersChain.push(currentFolder);
|
|
67
|
+
const parent = path.dirname(currentFolder);
|
|
68
|
+
if (parent === currentFolder)
|
|
69
|
+
break;
|
|
70
|
+
currentFolder = parent;
|
|
71
|
+
}
|
|
72
|
+
foldersChain.reverse();
|
|
73
|
+
for (const dir of foldersChain) {
|
|
74
|
+
if (NodeFileSystemService.#isFolderTheRoot(dir))
|
|
75
|
+
continue; // the requested directory is a root directory (e.g. F:\ or /) - consider it as existing
|
|
76
|
+
try {
|
|
77
|
+
// eslint-disable-next-line no-await-in-loop
|
|
78
|
+
await fs.mkdir(dir);
|
|
79
|
+
}
|
|
80
|
+
catch (err) {
|
|
81
|
+
if (err?.code !== `EEXIST`) // EEXIST error is OK - the requested directory already exists
|
|
82
|
+
throw err;
|
|
83
|
+
}
|
|
60
84
|
}
|
|
61
85
|
}
|
|
62
86
|
async createFile(filePath, overwriteExisting, size) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"nodeFileSystemService.js","sourceRoot":"","sources":["../../../../../src/utils/fileSystem/node/nodeFileSystemService.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,aAAa,CAAC;AAC7B,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,iBAAiB,MAAM,+CAA+C,CAAC;AAI9E,MAAM,CAAC,OAAO,OAAO,qBAAqB;IACtC,MAAM,CAAC,KAAK,CAAC,iBAAiB,CAAC,MAAc,EAAE,WAA0B;QACrE,MAAM,KAAK,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC;QACvC,KAAK,MAAM,QAAQ,IAAI,KAAK,EAAE,CAAC;YAC3B,MAAM,GAAG,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YACxC,4CAA4C;YAC5C,IAAI,CAAC,MAAM,EAAE,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,WAAW,EAAE;gBAClC,4CAA4C;gBAC5C,MAAM,IAAI,CAAC,iBAAiB,CAAC,GAAG,EAAE,WAAW,CAAC,CAAC;;gBAE/C,WAAW,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC9B,CAAC;IACL,CAAC;IAED,MAAM,CAAC,gBAAgB,CAAC,MAAc;QAClC,MAAM,OAAO,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,CAAC;QACvC,MAAM,KAAK,GAAG,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,CAAC;QACtC,OAAO,KAAK,KAAK,OAAO,IAAI,KAAK,KAAK,IAAI,CAAC,GAAG,CAAC;IACnD,CAAC;IAED,KAAK,CAAC,wBAAwB,CAAC,UAAkB;QAC7C,MAAM,KAAK,GAAG,IAAI,KAAK,EAAU,CAAC;QAClC,MAAM,qBAAqB,CAAC,iBAAiB,CAAC,UAAU,EAAE,KAAK,CAAC,CAAC;QACjE,OAAO,KAAK,CAAC;IACjB,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,QAAgB,EAAE,IAAY,EAAE,WAA2B,MAAM,EAAE,QAAiC,SAAS;QACzH,MAAM,EAAE,CAAC,SAAS,CAAC,QAAQ,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,KAAK,CAAC,eAAe,CAAC,UAAkB;QACpC,OAAO,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;IACxC,CAAC;IAED,KAAK,CAAC,gBAAgB,CAAC,QAAgB,EAAE,WAA2B,MAAM,EAAE,QAAiC,SAAS;QAClH,OAAO,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,EAAE,QAAQ,EAAE,IAAI,EAAE,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,CAAC,CAAC;IAC/E,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAe,EAAE,oBAA8B;QAC5D,IAAI,CAAC;YACD,sCAAsC;YACtC,MAAM,IAAI,GAAG,oBAAoB,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,GAAG,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC;YAChG,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;YAC/B,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,MAAM,CAAC;YACH,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,UAAkB;QACjC,IAAI,qBAAqB,CAAC,gBAAgB,CAAC,UAAU,CAAC;YAClD,wFAAwF;YACxF,OAAO;QAEX,IAAI,CAAC;YACD,MAAM,EAAE,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QACpD,CAAC;QACD,OAAO,GAAG,EAAE,CAAC;YACT,MAAM,MAAM,GAAG,GAAY,CAAC;YAC5B,IAAI,MAAM,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ;gBAClC,8DAA8D;gBAC9D,OAAO;YAEX,MAAM,GAAG,CAAC;QACd,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,QAAgB,EAAE,iBAA0B,EAAE,IAAa;QACxE,uDAAuD;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QACtC,MAAM,IAAI,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAEhC,4BAA4B;QAC5B,2GAA2G;QAC3G,sGAAsG;QACtG,MAAM,QAAQ,GAAG,iBAAiB,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC;QAChD,IAAI,MAAM,GAAyB,IAAI,CAAC;QACxC,IAAI,CAAC;YACD,IAAI,CAAC;gBACD,MAAM,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,EAAE,QAAQ,CAAC,CAAC;YAC/C,CAAC;YACD,OAAO,GAAG,EAAE,CAAC;gBACT,MAAM,OAAO,GAAG,GAAY,CAAC;gBAC7B,IAAI,OAAO,IAAI,OAAO,CAAC,IAAI,KAAK,QAAQ;oBACpC,OAAO,KAAK,CAAC;gBAEjB,MAAM,GAAG,CAAC;YACd,CAAC;YAED,IAAI,CAAC,IAAI,IAAI,CAAC,CAAC,GAAG,CAAC;gBACf,MAAM,MAAM,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;YAEhC,OAAO,IAAI,CAAC;QAChB,CAAC;gBACO,CAAC;YACL,IAAI,MAAM,KAAK,IAAI;gBACf,MAAM,MAAM,CAAC,KAAK,EAAE,CAAC;QAC7B,CAAC;IACL,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,QAAgB;QAC7B,IAAI,CAAC;YACD,MAAM,EAAE,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC;YACtB,OAAO,IAAI,CAAC;QAChB,CAAC;QACD,MAAM,CAAC;YACH,OAAO,KAAK,CAAC;QACjB,CAAC;IACL,CAAC;IAED,KAAK,CAAC,aAAa,CAAC,UAAkB;QAClC,MAAM,QAAQ,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC;QAC9C,OAAO,QAAQ,CAAC,MAAM,KAAK,CAAC,CAAC;IACjC,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,UAAkB;QACjC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,CAAC,UAAU,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,KAAK,SAAS,CAAC;IACrF,CAAC;IAED,KAAK,CAAC,WAAW,CAAC,QAAgB;QAC9B,MAAM,IAAI,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;QACrC,OAAO,IAAI,CAAC,IAAI,CAAC;IACrB,CAAC;IAED,KAAK,CAAC,YAAY,CAAC,QAAgB,EAAE,IAAY;QAC7C,MAAM,EAAE,CAAC,QAAQ,CAAC,QAAQ,EAAE,IAAI,CAAC,CAAC;IACtC,CAAC;IAED,KAAK,CAAC,UAAU,CAAC,OAAe,EAAE,OAAe;QAC7C,MAAM,EAAE,CAAC,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IACtC,CAAC;IAED,QAAQ,CAAC,GAAG,KAAoB;QAC5B,OAAO,IAAI,CAAC,IAAI,CAAC,GAAG,KAAK,CAAC,CAAC;IAC/B,CAAC;IAED,4BAA4B,CAAC,KAAY;QACrC,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,QAAQ;YAChC,OAAO,iBAAiB,CAAC,QAAQ,CAAC;QAEtC,OAAO,SAAS,CAAC;IACrB,CAAC;IAED,aAAa,CAAC,QAAgB;QAC1B,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;IAChC,CAAC;IAED,cAAc,CAAC,UAAsB;QACjC,OAAO,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IACnC,CAAC;IAED,qBAAqB,CAAC,QAAgB,EAAE,WAAmB;QACvD,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC;QACpC,OAAO,IAAI,CAAC,MAAM,CAAC;YACf,GAAG,EAAE,MAAM,CAAC,GAAG;YACf,IAAI,EAAE,WAAW;SACpB,CAAC,CAAC;IACP,CAAC;CACJ","sourcesContent":["import fs from 'fs/promises';\r\nimport path from 'path';\r\nimport DownloadErrorCode from '../../../downloader/dtos/downloadErrorCode.js';\r\nimport type FileSystemService from \"../fileSystemService.js\";\r\nimport type ParsedPath from '../parsedPath.js';\r\n\r\nexport default class NodeFileSystemService implements FileSystemService {\r\n static async #readDirRecursive(folder: string, accumulator: Array<string>) {\r\n const paths = await fs.readdir(folder);\r\n for (const itemPath of paths) {\r\n const abs = path.join(folder, itemPath);\r\n // eslint-disable-next-line no-await-in-loop\r\n if ((await fs.stat(abs)).isDirectory())\r\n // eslint-disable-next-line no-await-in-loop\r\n await this.#readDirRecursive(abs, accumulator);\r\n else\r\n accumulator.push(abs);\r\n }\r\n }\r\n\r\n static #isFolderTheRoot(folder: string): boolean {\r\n const thisOne = path.normalize(folder);\r\n const oneUp = path.join(folder, `..`);\r\n return oneUp === thisOne || oneUp === path.sep;\r\n }\r\n\r\n async getAllFilePathsRecursive(folderPath: string): Promise<string[]> {\r\n const files = new Array<string>();\r\n await NodeFileSystemService.#readDirRecursive(folderPath, files);\r\n return files;\r\n }\r\n\r\n async writeFile(filePath: string, data: string, encoding: BufferEncoding = `utf8`, abort: AbortSignal | undefined = undefined): Promise<void> {\r\n await fs.writeFile(filePath, data, { encoding, flag: `w`, signal: abort });\r\n }\r\n\r\n async getAllFilePaths(folderPath: string): Promise<Array<string>> {\r\n return await fs.readdir(folderPath);\r\n }\r\n\r\n async readFileAsString(filePath: string, encoding: BufferEncoding = `utf8`, abort: AbortSignal | undefined = undefined): Promise<string> {\r\n return await fs.readFile(filePath, { encoding, flag: `r`, signal: abort });\r\n }\r\n\r\n async pathExists(thePath: string, checkReadWriteAccess?: boolean): Promise<boolean> {\r\n try {\r\n // eslint-disable-next-line no-bitwise\r\n const mode = checkReadWriteAccess ? (fs.constants.W_OK | fs.constants.R_OK) : fs.constants.F_OK;\r\n await fs.access(thePath, mode);\r\n return true;\r\n }\r\n catch {\r\n return false;\r\n }\r\n }\r\n\r\n async createFolder(folderPath: string): Promise<void> {\r\n if (NodeFileSystemService.#isFolderTheRoot(folderPath))\r\n // the requested directory is a root directory (e.g. F:\\ or /) - consider it as existing\r\n return;\r\n\r\n try {\r\n await fs.mkdir(folderPath, { recursive: true });\r\n }\r\n catch (err) {\r\n const dirErr = err as Error;\r\n if (dirErr && dirErr.code === `EEXIST`)\r\n // EEXIST error is OK - the requested directory already exists\r\n return;\r\n\r\n throw err;\r\n }\r\n }\r\n\r\n async createFile(filePath: string, overwriteExisting: boolean, size?: number): Promise<boolean> {\r\n // Check if file folder exists and create if it doesn't\r\n const folder = path.dirname(filePath);\r\n await this.createFolder(folder);\r\n\r\n // Open the file for writing\r\n // overwriteExisting === true --> 'w' creates the file (if it doesn't exist) or truncates it (if it exists)\r\n // overwriteExisting === false --> 'wx' creates the file (if it doesn't exist) or fails (if it exists)\r\n const openMode = overwriteExisting ? `w` : `wx`;\r\n let handle: fs.FileHandle | null = null;\r\n try {\r\n try {\r\n handle = await fs.open(filePath, openMode);\r\n }\r\n catch (err) {\r\n const fileErr = err as Error;\r\n if (fileErr && fileErr.code === `EEXIST`)\r\n return false;\r\n\r\n throw err;\r\n }\r\n\r\n if ((size ?? 0) > 0)\r\n await handle.truncate(size);\r\n\r\n return true;\r\n }\r\n finally {\r\n if (handle !== null)\r\n await handle.close();\r\n }\r\n }\r\n\r\n async deleteFile(filePath: string): Promise<boolean> {\r\n try {\r\n await fs.rm(filePath);\r\n return true;\r\n }\r\n catch {\r\n return false;\r\n }\r\n }\r\n\r\n async folderIsEmpty(folderPath: string): Promise<boolean> {\r\n const contents = await fs.readdir(folderPath);\r\n return contents.length === 0;\r\n }\r\n\r\n async deleteFolder(folderPath: string): Promise<boolean> {\r\n return (await fs.rm(folderPath, { recursive: true, force: true })) === undefined;\r\n }\r\n\r\n async getFileSize(filePath: string): Promise<number> {\r\n const stat = await fs.stat(filePath);\r\n return stat.size;\r\n }\r\n\r\n async truncateFile(filePath: string, size: number): Promise<void> {\r\n await fs.truncate(filePath, size);\r\n }\r\n\r\n async renameFile(oldPath: string, newPath: string): Promise<void> {\r\n await fs.rename(oldPath, newPath);\r\n }\r\n\r\n pathJoin(...paths: Array<string>): string {\r\n return path.join(...paths);\r\n }\r\n\r\n fileErrorToDownloadErrorCode(error: Error): DownloadErrorCode | undefined {\r\n if (error && error.code === `ENOSPC`)\r\n return DownloadErrorCode.DiskFull;\r\n\r\n return undefined;\r\n }\r\n\r\n parseFilePath(filePath: string): ParsedPath {\r\n return path.parse(filePath);\r\n }\r\n\r\n formatFilePath(parsedPath: ParsedPath): string {\r\n return path.format(parsedPath);\r\n }\r\n\r\n replaceFilenameInPath(filePath: string, newFileName: string): string {\r\n const parsed = path.parse(filePath);\r\n return path.format({\r\n dir: parsed.dir,\r\n base: newFileName,\r\n });\r\n }\r\n}"]}
|
|
1
|
+
{"version":3,"file":"nodeFileSystemService.js","sourceRoot":"","sources":["../../../../../src/utils/fileSystem/node/nodeFileSystemService.ts"],"names":[],"mappings":"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","sourcesContent":["import fs from 'fs/promises';\r\nimport path from 'path';\r\nimport DownloadErrorCode from '../../../downloader/dtos/downloadErrorCode.js';\r\nimport type FileSystemService from \"../fileSystemService.js\";\r\nimport type ParsedPath from '../parsedPath.js';\r\n\r\nexport default class NodeFileSystemService implements FileSystemService {\r\n static async #readDirRecursive(folder: string, accumulator: Array<string>) {\r\n const paths = await fs.readdir(folder);\r\n for (const itemPath of paths) {\r\n const abs = path.join(folder, itemPath);\r\n // eslint-disable-next-line no-await-in-loop\r\n if ((await fs.stat(abs)).isDirectory())\r\n // eslint-disable-next-line no-await-in-loop\r\n await this.#readDirRecursive(abs, accumulator);\r\n else\r\n accumulator.push(abs);\r\n }\r\n }\r\n\r\n static #isFolderTheRoot(folder: string): boolean {\r\n const thisOne = path.normalize(folder);\r\n const oneUp = path.join(folder, `..`);\r\n return oneUp === thisOne || oneUp === path.sep;\r\n }\r\n\r\n async getAllFilePathsRecursive(folderPath: string): Promise<string[]> {\r\n const files = new Array<string>();\r\n await NodeFileSystemService.#readDirRecursive(folderPath, files);\r\n return files;\r\n }\r\n\r\n async writeFile(filePath: string, data: string, encoding: BufferEncoding = `utf8`, abort: AbortSignal | undefined = undefined): Promise<void> {\r\n await fs.writeFile(filePath, data, { encoding, flag: `w`, signal: abort });\r\n }\r\n\r\n async getAllFilePaths(folderPath: string): Promise<Array<string>> {\r\n return await fs.readdir(folderPath);\r\n }\r\n\r\n async readFileAsString(filePath: string, encoding: BufferEncoding = `utf8`, abort: AbortSignal | undefined = undefined): Promise<string> {\r\n return await fs.readFile(filePath, { encoding, flag: `r`, signal: abort });\r\n }\r\n\r\n async pathExists(thePath: string, checkReadWriteAccess?: boolean): Promise<boolean> {\r\n try {\r\n // eslint-disable-next-line no-bitwise\r\n const mode = checkReadWriteAccess ? (fs.constants.W_OK | fs.constants.R_OK) : fs.constants.F_OK;\r\n await fs.access(thePath, mode);\r\n return true;\r\n }\r\n catch {\r\n return false;\r\n }\r\n }\r\n\r\n async createFolder(folderPath: string): Promise<void> {\r\n if (NodeFileSystemService.#isFolderTheRoot(folderPath))\r\n // the requested directory is a root directory (e.g. F:\\ or /) - consider it as existing\r\n return;\r\n\r\n try {\r\n await fs.mkdir(folderPath, { recursive: true });\r\n }\r\n catch (err) {\r\n const dirErr = err as Error;\r\n\r\n if (dirErr && dirErr.code === `EEXIST`)\r\n // EEXIST error is OK - the requested directory already exists\r\n return;\r\n\r\n await this.mkdirRecursiveSafe(folderPath);\r\n }\r\n }\r\n\r\n private async mkdirRecursiveSafe(target: string): Promise<void> {\r\n const foldersChain: string[] = [];\r\n\r\n let currentFolder = target;\r\n\r\n while (true) {\r\n foldersChain.push(currentFolder);\r\n\r\n const parent = path.dirname(currentFolder);\r\n\r\n if (parent === currentFolder)\r\n break;\r\n\r\n currentFolder = parent;\r\n }\r\n\r\n foldersChain.reverse();\r\n\r\n for (const dir of foldersChain) {\r\n if (NodeFileSystemService.#isFolderTheRoot(dir))\r\n continue; // the requested directory is a root directory (e.g. F:\\ or /) - consider it as existing\r\n try {\r\n // eslint-disable-next-line no-await-in-loop\r\n await fs.mkdir(dir);\r\n }\r\n catch (err: any) {\r\n if (err?.code !== `EEXIST`) // EEXIST error is OK - the requested directory already exists\r\n throw err;\r\n }\r\n }\r\n }\r\n\r\n async createFile(filePath: string, overwriteExisting: boolean, size?: number): Promise<boolean> {\r\n // Check if file folder exists and create if it doesn't\r\n const folder = path.dirname(filePath);\r\n await this.createFolder(folder);\r\n\r\n // Open the file for writing\r\n // overwriteExisting === true --> 'w' creates the file (if it doesn't exist) or truncates it (if it exists)\r\n // overwriteExisting === false --> 'wx' creates the file (if it doesn't exist) or fails (if it exists)\r\n const openMode = overwriteExisting ? `w` : `wx`;\r\n let handle: fs.FileHandle | null = null;\r\n try {\r\n try {\r\n handle = await fs.open(filePath, openMode);\r\n }\r\n catch (err) {\r\n const fileErr = err as Error;\r\n if (fileErr && fileErr.code === `EEXIST`)\r\n return false;\r\n\r\n throw err;\r\n }\r\n\r\n if ((size ?? 0) > 0)\r\n await handle.truncate(size);\r\n\r\n return true;\r\n }\r\n finally {\r\n if (handle !== null)\r\n await handle.close();\r\n }\r\n }\r\n\r\n async deleteFile(filePath: string): Promise<boolean> {\r\n try {\r\n await fs.rm(filePath);\r\n return true;\r\n }\r\n catch {\r\n return false;\r\n }\r\n }\r\n\r\n async folderIsEmpty(folderPath: string): Promise<boolean> {\r\n const contents = await fs.readdir(folderPath);\r\n return contents.length === 0;\r\n }\r\n\r\n async deleteFolder(folderPath: string): Promise<boolean> {\r\n return (await fs.rm(folderPath, { recursive: true, force: true })) === undefined;\r\n }\r\n\r\n async getFileSize(filePath: string): Promise<number> {\r\n const stat = await fs.stat(filePath);\r\n return stat.size;\r\n }\r\n\r\n async truncateFile(filePath: string, size: number): Promise<void> {\r\n await fs.truncate(filePath, size);\r\n }\r\n\r\n async renameFile(oldPath: string, newPath: string): Promise<void> {\r\n await fs.rename(oldPath, newPath);\r\n }\r\n\r\n pathJoin(...paths: Array<string>): string {\r\n return path.join(...paths);\r\n }\r\n\r\n fileErrorToDownloadErrorCode(error: Error): DownloadErrorCode | undefined {\r\n if (error && error.code === `ENOSPC`)\r\n return DownloadErrorCode.DiskFull;\r\n\r\n return undefined;\r\n }\r\n\r\n parseFilePath(filePath: string): ParsedPath {\r\n return path.parse(filePath);\r\n }\r\n\r\n formatFilePath(parsedPath: ParsedPath): string {\r\n return path.format(parsedPath);\r\n }\r\n\r\n replaceFilenameInPath(filePath: string, newFileName: string): string {\r\n const parsed = path.parse(filePath);\r\n return path.format({\r\n dir: parsed.dir,\r\n base: newFileName,\r\n });\r\n }\r\n}"]}
|