fileNameParser.js 2.8 KB

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