wrapper.js 2.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. const path = require('path');
  2. const picomatch = require('picomatch');
  3. const isGlob = require('is-glob');
  4. function normalizeOptions(dir, opts = {}) {
  5. const {ignore, ...rest} = opts;
  6. if (Array.isArray(ignore)) {
  7. opts = {...rest};
  8. for (const value of ignore) {
  9. if (value instanceof RegExp) {
  10. if (value.flags !== '') {
  11. throw new Error(
  12. `RegExp ignore patterns must not have flags (got /${value.source}/${value.flags}). Flags are not supported by the native matcher.`,
  13. );
  14. }
  15. if (!opts.ignoreGlobs) {
  16. opts.ignoreGlobs = [];
  17. }
  18. // The native backend uses std::regex_match (full-string match), but
  19. // callers expect JS .test() semantics (substring search). Wrapping the
  20. // source in ^[\\s\\S]*(?:…)[\\s\\S]*$ achieves that. The (?:…) group
  21. // isolates the source so leading/trailing | in the source stays contained.
  22. opts.ignoreGlobs.push(`^[\\s\\S]*(?:${value.source})[\\s\\S]*$`);
  23. } else if (isGlob(value)) {
  24. if (!opts.ignoreGlobs) {
  25. opts.ignoreGlobs = [];
  26. }
  27. const regex = picomatch.makeRe(value, {
  28. // We set `dot: true` to workaround an issue with the
  29. // regular expression on Linux where the resulting
  30. // negative lookahead `(?!(\\/|^)` was never matching
  31. // in some cases. See also https://bit.ly/3UZlQDm
  32. dot: true,
  33. windows: process.platform === 'win32',
  34. });
  35. opts.ignoreGlobs.push(regex.source);
  36. } else {
  37. if (!opts.ignorePaths) {
  38. opts.ignorePaths = [];
  39. }
  40. opts.ignorePaths.push(path.resolve(dir, value));
  41. }
  42. }
  43. }
  44. return opts;
  45. }
  46. exports.createWrapper = (binding) => {
  47. return {
  48. writeSnapshot(dir, snapshot, opts) {
  49. return binding.writeSnapshot(
  50. path.resolve(dir),
  51. path.resolve(snapshot),
  52. normalizeOptions(dir, opts),
  53. );
  54. },
  55. getEventsSince(dir, snapshot, opts) {
  56. return binding.getEventsSince(
  57. path.resolve(dir),
  58. path.resolve(snapshot),
  59. normalizeOptions(dir, opts),
  60. );
  61. },
  62. async subscribe(dir, fn, opts) {
  63. dir = path.resolve(dir);
  64. opts = normalizeOptions(dir, opts);
  65. await binding.subscribe(dir, fn, opts);
  66. return {
  67. unsubscribe() {
  68. return binding.unsubscribe(dir, fn, opts);
  69. },
  70. };
  71. },
  72. unsubscribe(dir, fn, opts) {
  73. return binding.unsubscribe(
  74. path.resolve(dir),
  75. fn,
  76. normalizeOptions(dir, opts),
  77. );
  78. },
  79. };
  80. };