fileNameParser.js 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. const debug = require("debug")("streamroller:fileNameParser");
  2. const ZIP_EXT = ".gz";
  3. const format = require("date-format");
  4. const DEFAULT_FILENAME_SEP = ".";
  5. module.exports = ({ file, keepFileExt, pattern, fileNameSep }) => {
  6. let FILENAME_SEP = fileNameSep || DEFAULT_FILENAME_SEP;
  7. // All these functions take two arguments: f, the filename, and p, the result placeholder
  8. // They return the filename with any matching parts removed.
  9. // The "zip" function, for instance, removes the ".gz" part of the filename (if present)
  10. const zip = (f, p) => {
  11. if (f.endsWith(ZIP_EXT)) {
  12. debug("it is gzipped");
  13. p.isCompressed = true;
  14. return f.slice(0, -1 * ZIP_EXT.length);
  15. }
  16. return f;
  17. };
  18. const __NOT_MATCHING__ = "__NOT_MATCHING__";
  19. const extAtEnd = f => {
  20. if (f.startsWith(file.name) && f.endsWith(file.ext)) {
  21. debug("it starts and ends with the right things");
  22. return f.slice(file.name.length + 1, -1 * file.ext.length);
  23. }
  24. return __NOT_MATCHING__;
  25. };
  26. const extInMiddle = f => {
  27. if (f.startsWith(file.base)) {
  28. debug("it starts with the right things");
  29. return f.slice(file.base.length + 1);
  30. }
  31. return __NOT_MATCHING__;
  32. };
  33. const dateAndIndex = (f, p) => {
  34. const items = f.split(FILENAME_SEP);
  35. let indexStr = items[items.length - 1];
  36. debug("items: ", items, ", indexStr: ", indexStr);
  37. let dateStr = f;
  38. if (indexStr !== undefined && indexStr.match(/^\d+$/)) {
  39. dateStr = f.slice(0, -1 * (indexStr.length + 1));
  40. debug(`dateStr is ${dateStr}`);
  41. if (pattern && !dateStr) {
  42. dateStr = indexStr;
  43. indexStr = "0";
  44. }
  45. } else {
  46. indexStr = "0";
  47. }
  48. try {
  49. // Two arguments for new Date() are intentional. This will set other date
  50. // components to minimal values in the current timezone instead of UTC,
  51. // as new Date(0) will do.
  52. const date = format.parse(pattern, dateStr, new Date(0, 0));
  53. if (format.asString(pattern, date) !== dateStr) return f;
  54. p.index = parseInt(indexStr, 10);
  55. p.date = dateStr;
  56. p.timestamp = date.getTime();
  57. return "";
  58. } catch (e) {
  59. //not a valid date, don't panic.
  60. debug(`Problem parsing ${dateStr} as ${pattern}, error was: `, e);
  61. return f;
  62. }
  63. };
  64. const index = (f, p) => {
  65. if (f.match(/^\d+$/)) {
  66. debug("it has an index");
  67. p.index = parseInt(f, 10);
  68. return "";
  69. }
  70. return f;
  71. };
  72. let parts = [
  73. zip,
  74. keepFileExt ? extAtEnd : extInMiddle,
  75. pattern ? dateAndIndex : index
  76. ];
  77. return filename => {
  78. let result = { filename, index: 0, isCompressed: false };
  79. // pass the filename through each of the file part parsers
  80. let whatsLeftOver = parts.reduce(
  81. (remains, part) => part(remains, result),
  82. filename
  83. );
  84. // if there's anything left after parsing, then it wasn't a valid filename
  85. return whatsLeftOver ? null : result;
  86. };
  87. };