const debug = require("debug")("streamroller:fileNameParser");
const ZIP_EXT = ".gz";
const format = require("date-format");
const DEFAULT_FILENAME_SEP = ".";
module.exports = ({ file, keepFileExt, pattern, fileNameSep }) => {
let FILENAME_SEP = fileNameSep || DEFAULT_FILENAME_SEP;
// 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;
};
};