|
1 | 1 | const fs = require('fs-extra') |
2 | | -import {CLIError} from '@oclif/errors' |
3 | | - |
4 | | -const utils = { |
5 | | - readTextFile: async (file: any) => { |
6 | | - return new Promise(async (resolve, reject) => { |
7 | | - try { |
8 | | - if (!fs.existsSync(file)) { |
9 | | - return reject('ENOENT: no such file or directory, ' + file) |
10 | | - } |
11 | | - let fileBuffer = await fs.readFile(file) |
12 | | - if (fileBuffer) { |
13 | | - // If the data starts with BOM, we know it is UTF |
14 | | - if (fileBuffer[0] === 0xEF && fileBuffer[1] === 0xBB && fileBuffer[2] === 0xBF) { |
15 | | - // EF BB BF UTF-8 with BOM |
16 | | - fileBuffer = fileBuffer.slice(3) |
17 | | - } else if (fileBuffer[0] === 0xFF && fileBuffer[1] === 0xFE && fileBuffer[2] === 0x00 && fileBuffer[3] === 0x00) { |
18 | | - // FF FE 00 00 UTF-32, little-endian BOM |
19 | | - fileBuffer = fileBuffer.slice(4) |
20 | | - } else if (fileBuffer[0] === 0x00 && fileBuffer[1] === 0x00 && fileBuffer[2] === 0xFE && fileBuffer[3] === 0xFF) { |
21 | | - // 00 00 FE FF UTF-32, big-endian BOM |
22 | | - fileBuffer = fileBuffer.slice(4) |
23 | | - } else if (fileBuffer[0] === 0xFE && fileBuffer[1] === 0xFF && fileBuffer[2] === 0x00 && fileBuffer[3] === 0x00) { |
24 | | - // FE FF 00 00 UCS-4, unusual octet order BOM (3412) |
25 | | - fileBuffer = fileBuffer.slice(4) |
26 | | - } else if (fileBuffer[0] === 0x00 && fileBuffer[1] === 0x00 && fileBuffer[2] === 0xFF && fileBuffer[3] === 0xFE) { |
27 | | - // 00 00 FF FE UCS-4, unusual octet order BOM (2143) |
28 | | - fileBuffer = fileBuffer.slice(4) |
29 | | - } else if (fileBuffer[0] === 0xFF && fileBuffer[1] === 0xFE) { |
30 | | - // FF FE UTF-16, little endian BOM |
31 | | - fileBuffer = fileBuffer.slice(2) |
32 | | - } else if (fileBuffer[0] === 0xFE && fileBuffer[1] === 0xFF) { |
33 | | - // FE FF UTF-16, big endian BOM |
34 | | - fileBuffer = fileBuffer.slice(2) |
35 | | - } |
36 | | - } |
37 | | - return resolve(fileBuffer.toString('utf8').replace(/\0/g, '')) |
38 | | - } catch (err) { |
39 | | - if (err.message.match(/ENOENT: no such file or directory/)) { |
40 | | - return reject(new CLIError(err.message)) |
41 | | - } |
| 2 | +const path = require('path') |
| 3 | +import {CLIError} from './clierror' |
42 | 4 |
|
43 | | - return reject(`Invalid Input. Sorry, unable to parse file: ${err}`) |
| 5 | +async function readTextFile(file: any): Promise<string> { |
| 6 | + return new Promise(async (resolve, reject) => { |
| 7 | + try { |
| 8 | + if (!fs.existsSync(file)) { |
| 9 | + return reject('ENOENT: no such file or directory, ' + file) |
| 10 | + } |
| 11 | + let fileBuffer = await fs.readFile(file) |
| 12 | + if (fileBuffer) { |
| 13 | + // If the data starts with BOM, we know it is UTF |
| 14 | + if (fileBuffer[0] === 0xEF && fileBuffer[1] === 0xBB && fileBuffer[2] === 0xBF) { |
| 15 | + // EF BB BF UTF-8 with BOM |
| 16 | + fileBuffer = fileBuffer.slice(3) |
| 17 | + } else if (fileBuffer[0] === 0xFF && fileBuffer[1] === 0xFE && fileBuffer[2] === 0x00 && fileBuffer[3] === 0x00) { |
| 18 | + // FF FE 00 00 UTF-32, little-endian BOM |
| 19 | + fileBuffer = fileBuffer.slice(4) |
| 20 | + } else if (fileBuffer[0] === 0x00 && fileBuffer[1] === 0x00 && fileBuffer[2] === 0xFE && fileBuffer[3] === 0xFF) { |
| 21 | + // 00 00 FE FF UTF-32, big-endian BOM |
| 22 | + fileBuffer = fileBuffer.slice(4) |
| 23 | + } else if (fileBuffer[0] === 0xFE && fileBuffer[1] === 0xFF && fileBuffer[2] === 0x00 && fileBuffer[3] === 0x00) { |
| 24 | + // FE FF 00 00 UCS-4, unusual octet order BOM (3412) |
| 25 | + fileBuffer = fileBuffer.slice(4) |
| 26 | + } else if (fileBuffer[0] === 0x00 && fileBuffer[1] === 0x00 && fileBuffer[2] === 0xFF && fileBuffer[3] === 0xFE) { |
| 27 | + // 00 00 FF FE UCS-4, unusual octet order BOM (2143) |
| 28 | + fileBuffer = fileBuffer.slice(4) |
| 29 | + } else if (fileBuffer[0] === 0xFF && fileBuffer[1] === 0xFE) { |
| 30 | + // FF FE UTF-16, little endian BOM |
| 31 | + fileBuffer = fileBuffer.slice(2) |
| 32 | + } else if (fileBuffer[0] === 0xFE && fileBuffer[1] === 0xFF) { |
| 33 | + // FE FF UTF-16, big endian BOM |
| 34 | + fileBuffer = fileBuffer.slice(2) |
| 35 | + } |
44 | 36 | } |
45 | | - }) |
| 37 | + return resolve(fileBuffer.toString('utf8').replace(/\0/g, '')) |
| 38 | + } catch (err) { |
| 39 | + if (err.message.match(/ENOENT: no such file or directory/)) { |
| 40 | + return reject(new CLIError(err.message)) |
| 41 | + } |
| 42 | + |
| 43 | + return reject(`Invalid Input. Sorry, unable to parse file: ${err}`) |
| 44 | + } |
| 45 | + }) |
| 46 | +} |
| 47 | + |
| 48 | +function validatePath(outputPath: string, defaultFileName: string, forceWrite = false): string { |
| 49 | + let completePath = path.resolve(outputPath) |
| 50 | + const containingDir = path.dirname(completePath) |
| 51 | + |
| 52 | + // If the cointaining folder doesnt exist |
| 53 | + if (!fs.existsSync(containingDir)) throw new CLIError(`Containing directory path doesn't exist: ${containingDir}`) |
| 54 | + |
| 55 | + const baseElement = path.basename(completePath) |
| 56 | + const pathAlreadyExist = fs.existsSync(completePath) |
| 57 | + |
| 58 | + // If the last element in the path is a file |
| 59 | + if (baseElement.includes('.')) { |
| 60 | + return pathAlreadyExist && !forceWrite ? enumerateFileName(completePath) : completePath |
46 | 61 | } |
| 62 | + |
| 63 | + // If the last element in the path is a folder |
| 64 | + if (!pathAlreadyExist) throw new CLIError(`Target directory path doesn't exist: ${completePath}`) |
| 65 | + completePath = path.join(completePath, defaultFileName) |
| 66 | + return fs.existsSync(completePath) && !forceWrite ? enumerateFileName(completePath) : completePath |
| 67 | +} |
| 68 | + |
| 69 | +function enumerateFileName(filePath: string): string { |
| 70 | + const fileName = path.basename(filePath) |
| 71 | + const containingDir = path.dirname(filePath) |
| 72 | + |
| 73 | + if (!fs.existsSync(containingDir)) throw new CLIError(`Containing directory path doesn't exist: ${containingDir}`) |
| 74 | + |
| 75 | + const extension = path.extname(fileName) |
| 76 | + const baseName = path.basename(fileName, extension) |
| 77 | + let nextNumber = 0 |
| 78 | + let newPath = '' |
| 79 | + |
| 80 | + do { |
| 81 | + newPath = path.join(containingDir, baseName + `(${++nextNumber})` + extension) |
| 82 | + } while (fs.existsSync(newPath)) |
| 83 | + |
| 84 | + return newPath |
47 | 85 | } |
48 | 86 |
|
49 | | -export default utils |
| 87 | +export default { |
| 88 | + readTextFile, |
| 89 | + validatePath |
| 90 | +} |
0 commit comments