| const debug = require("debug")("streamroller:fileNameParser"); |
| const FILENAME_SEP = "."; |
| const ZIP_EXT = ".gz"; |
| const format = require("date-format"); |
| |
| module.exports = ({ file, keepFileExt, pattern }) => { |
| // All these functions take two arguments: f, the filename, and p, the result placeholder |
| // They return the filename with any matching parts removed. |
| // The "zip" function, for instance, removes the ".gz" part of the filename (if present) |
| const zip = (f, p) => { |
| if (f.endsWith(ZIP_EXT)) { |
| debug("it is gzipped"); |
| p.isCompressed = true; |
| return f.slice(0, -1 * ZIP_EXT.length); |
| } |
| return f; |
| }; |
| |
| const __NOT_MATCHING__ = "__NOT_MATCHING__"; |
| |
| const extAtEnd = f => { |
| if (f.startsWith(file.name) && f.endsWith(file.ext)) { |
| debug("it starts and ends with the right things"); |
| return f.slice(file.name.length + 1, -1 * file.ext.length); |
| } |
| return __NOT_MATCHING__; |
| }; |
| |
| const extInMiddle = f => { |
| if (f.startsWith(file.base)) { |
| debug("it starts with the right things"); |
| return f.slice(file.base.length + 1); |
| } |
| return __NOT_MATCHING__; |
| }; |
| |
| const dateAndIndex = (f, p) => { |
| const items = f.split(FILENAME_SEP); |
| let indexStr = items[items.length - 1]; |
| debug("items: ", items, ", indexStr: ", indexStr); |
| let dateStr = f; |
| if (indexStr !== undefined && indexStr.match(/^\d+$/)) { |
| dateStr = f.slice(0, -1 * (indexStr.length + 1)); |
| debug(`dateStr is ${dateStr}`); |
| if (pattern && !dateStr) { |
| dateStr = indexStr; |
| indexStr = "0"; |
| } |
| } else { |
| indexStr = "0"; |
| } |
| |
| try { |
| // Two arguments for new Date() are intentional. This will set other date |
| // components to minimal values in the current timezone instead of UTC, |
| // as new Date(0) will do. |
| const date = format.parse(pattern, dateStr, new Date(0, 0)); |
| if (format.asString(pattern, date) !== dateStr) return f; |
| p.index = parseInt(indexStr, 10); |
| p.date = dateStr; |
| p.timestamp = date.getTime(); |
| return ""; |
| } catch (e) { |
| //not a valid date, don't panic. |
| debug(`Problem parsing ${dateStr} as ${pattern}, error was: `, e); |
| return f; |
| } |
| }; |
| |
| const index = (f, p) => { |
| if (f.match(/^\d+$/)) { |
| debug("it has an index"); |
| p.index = parseInt(f, 10); |
| return ""; |
| } |
| return f; |
| }; |
| |
| let parts = [ |
| zip, |
| keepFileExt ? extAtEnd : extInMiddle, |
| pattern ? dateAndIndex : index |
| ]; |
| |
| return filename => { |
| let result = { filename, index: 0, isCompressed: false }; |
| // pass the filename through each of the file part parsers |
| let whatsLeftOver = parts.reduce( |
| (remains, part) => part(remains, result), |
| filename |
| ); |
| // if there's anything left after parsing, then it wasn't a valid filename |
| return whatsLeftOver ? null : result; |
| }; |
| }; |