@boundaries/elements 1.0.0 → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js CHANGED
@@ -79,99 +79,6 @@ __export(src_exports, {
79
79
  });
80
80
  module.exports = __toCommonJS(src_exports);
81
81
 
82
- // src/Cache/Cache.ts
83
- var import_object_hash = __toESM(require("object-hash"));
84
- var CacheManager = class {
85
- /**
86
- * Internal cache map
87
- */
88
- _cache;
89
- /**
90
- * Creates a new CacheManager instance
91
- */
92
- constructor() {
93
- this._cache = /* @__PURE__ */ new Map();
94
- }
95
- /**
96
- * Generates a hashed key for the given cache key
97
- * @param key The cache key to hash
98
- * @returns The hashed key as a string
99
- */
100
- _getHashedKey(key) {
101
- return (0, import_object_hash.default)(key);
102
- }
103
- /**
104
- * Retrieves a value from the cache based on the given key
105
- * @param key The cache key to retrieve
106
- * @returns The cached value or undefined if not found
107
- */
108
- get(key) {
109
- const hashedKey = this._getHashedKey(key);
110
- return this._cache.get(hashedKey);
111
- }
112
- /**
113
- * Stores a value in the cache
114
- * @param key The cache key to store
115
- * @param value The value to cache
116
- */
117
- set(key, value) {
118
- const hashedKey = this._getHashedKey(key);
119
- this._cache.set(hashedKey, value);
120
- }
121
- /**
122
- * Restores a value in the cache from a given already hashed key
123
- * @param key The hashed key to restore
124
- * @param value The value to restore
125
- */
126
- restore(key, value) {
127
- this._cache.set(key, value);
128
- }
129
- /**
130
- * Checks if a value exists in the cache
131
- * @param key The cache key to check
132
- * @returns True if the value exists, false otherwise
133
- */
134
- has(key) {
135
- const hashedKey = this._getHashedKey(key);
136
- return this._cache.has(hashedKey);
137
- }
138
- /**
139
- * Retrieves all cached values
140
- * @returns A map of all cached values
141
- */
142
- getAll() {
143
- return this._cache;
144
- }
145
- /**
146
- * Clears the entire cache
147
- */
148
- clear() {
149
- this._cache.clear();
150
- }
151
- /**
152
- * Serializes the cache to a plain object.
153
- * @returns The serialized cache.
154
- */
155
- serialize() {
156
- return Array.from(this.getAll().entries()).reduce(
157
- (acc, [key, value]) => {
158
- acc[key] = value;
159
- return acc;
160
- },
161
- {}
162
- );
163
- }
164
- /**
165
- * Sets the cache from a serialized object.
166
- * @param serializedCache The serialized cache.
167
- */
168
- setFromSerialized(serializedCache) {
169
- for (const key in serializedCache) {
170
- this.restore(key, serializedCache[key]);
171
- }
172
- }
173
- };
174
-
175
82
  // src/Config/Config.ts
176
83
  var Config = class {
177
84
  /** The ignore paths */
@@ -180,6 +87,8 @@ var Config = class {
180
87
  _includePaths;
181
88
  /** Whether legacy template support is enabled */
182
89
  _legacyTemplates;
90
+ /** Whether the cache is enabled */
91
+ _cache;
183
92
  /**
184
93
  * Creates a new Config instance
185
94
  * @param options Configuration options
@@ -188,6 +97,7 @@ var Config = class {
188
97
  this._ignorePaths = options?.ignorePaths;
189
98
  this._includePaths = options?.includePaths;
190
99
  this._legacyTemplates = options?.legacyTemplates ?? true;
100
+ this._cache = options?.cache ?? true;
191
101
  }
192
102
  /**
193
103
  * The normalized configuration options
@@ -196,14 +106,38 @@ var Config = class {
196
106
  return {
197
107
  ignorePaths: this._ignorePaths,
198
108
  includePaths: this._includePaths,
109
+ legacyTemplates: this._legacyTemplates,
110
+ cache: this._cache
111
+ };
112
+ }
113
+ /**
114
+ * Normalized options for descriptors
115
+ */
116
+ get descriptorOptions() {
117
+ return {
118
+ ignorePaths: this._ignorePaths,
119
+ includePaths: this._includePaths,
120
+ cache: this._cache
121
+ };
122
+ }
123
+ /**
124
+ * Normalized options for element matchers
125
+ */
126
+ get matchersOptions() {
127
+ return {
199
128
  legacyTemplates: this._legacyTemplates
200
129
  };
201
130
  }
131
+ /**
132
+ * Whether caching is enabled
133
+ */
134
+ get cache() {
135
+ return this._cache;
136
+ }
202
137
  };
203
138
 
204
139
  // src/Matcher/BaseElementsMatcher.ts
205
140
  var import_handlebars = __toESM(require("handlebars"));
206
- var import_micromatch = __toESM(require("micromatch"));
207
141
 
208
142
  // src/Support/TypeGuards.ts
209
143
  function isString(value) {
@@ -221,6 +155,9 @@ function isBoolean(value) {
221
155
  function isObject(value) {
222
156
  return !isNullish(value) && !isBoolean(value) && !isArray(value) && typeof value === "object";
223
157
  }
158
+ function isEmptyObject(obj) {
159
+ return isObject(obj) && Object.keys(obj).length === 0;
160
+ }
224
161
  function isArray(value) {
225
162
  return Array.isArray(value);
226
163
  }
@@ -273,8 +210,9 @@ function isElementSelectorData(value) {
273
210
  ]);
274
211
  }
275
212
  function isElementSelectorWithLegacyOptions(value) {
276
- return isArray(value) && value.length === 2 && isSimpleElementSelectorByType(value[0]) && // NOTE: Arrays of length 2 with captured values selector as second element having a key "type" or "category" will be treated as legacy options instead of two different selectors. We have to live with this limitation for now.
277
- isCapturedValuesSelector(value[1]);
213
+ return isArray(value) && (value.length === 2 && isSimpleElementSelectorByType(value[0]) && // NOTE: Arrays of length 2 with captured values selector as second element having a key "type" or "category" will be treated as legacy options instead of two different selectors. We have to live with this limitation for now.
214
+ isCapturedValuesSelector(value[1]) || // NOTE: Backwards compatibility: Allow arrays of length 1 with simple element selector. Some users might defined arrays without options.
215
+ value.length === 1 && isSimpleElementSelectorByType(value[0]));
278
216
  }
279
217
  function isElementSelector(value) {
280
218
  return isSimpleElementSelectorByType(value) || isElementSelectorData(value) || isElementSelectorWithLegacyOptions(value);
@@ -305,6 +243,8 @@ function isExternalLibrariesSelector(value) {
305
243
  }
306
244
 
307
245
  // src/Matcher/BaseElementsMatcher.ts
246
+ var HANDLEBARS_TEMPLATE_REGEX = /{{\s*[^}]+\s*}}/;
247
+ var LEGACY_TEMPLATE_REGEX = /\$\{([^}]+)\}/g;
308
248
  function normalizeSelector(selector) {
309
249
  if (isSimpleElementSelectorByType(selector)) {
310
250
  return { type: selector };
@@ -315,7 +255,7 @@ function normalizeSelector(selector) {
315
255
  if (isElementSelectorWithLegacyOptions(selector)) {
316
256
  return {
317
257
  type: selector[0],
318
- captured: { ...selector[1] }
258
+ captured: selector[1] ? { ...selector[1] } : void 0
319
259
  };
320
260
  }
321
261
  throw new Error("Invalid element selector");
@@ -330,12 +270,21 @@ function normalizeElementsSelector(elementsSelector) {
330
270
  return [normalizeSelector(elementsSelector)];
331
271
  }
332
272
  var BaseElementsMatcher = class {
273
+ /**
274
+ * Option to use legacy templates with ${} syntax.
275
+ */
333
276
  _legacyTemplates;
277
+ /**
278
+ * Micromatch instance for matching.
279
+ */
280
+ micromatch;
334
281
  /**
335
282
  * Creates a new BaseElementsMatcher.
336
283
  * @param config Configuration options for the matcher.
284
+ * @param globalCache Global cache instance.
337
285
  */
338
- constructor(config) {
286
+ constructor(config, micromatch2) {
287
+ this.micromatch = micromatch2;
339
288
  this._legacyTemplates = config.legacyTemplates;
340
289
  }
341
290
  /**
@@ -344,17 +293,30 @@ var BaseElementsMatcher = class {
344
293
  * @returns The converted template.
345
294
  */
346
295
  _getBackwardsCompatibleTemplate(template) {
347
- return template.replaceAll(/\$\{([^}]+)\}/g, "{{ $1 }}");
296
+ return template.replaceAll(LEGACY_TEMPLATE_REGEX, "{{ $1 }}");
297
+ }
298
+ /**
299
+ * Determines if a template contains Handlebars syntax.
300
+ * @param template The template to check.
301
+ * @returns True if the template contains Handlebars syntax, false otherwise.
302
+ */
303
+ _isHandlebarsTemplate(template) {
304
+ return HANDLEBARS_TEMPLATE_REGEX.test(template);
348
305
  }
349
306
  /**
350
307
  * Returns a rendered template using the provided template data.
308
+ * Optimized version with template caching for better performance.
351
309
  * @param template The template to render.
352
- * @param extraTemplateData The data to use for replace in the template.
310
+ * @param templateData The data to use for replace in the template.
353
311
  * @returns The rendered template.
354
312
  */
355
313
  _getRenderedTemplate(template, templateData) {
356
314
  const templateToUse = this._legacyTemplates ? this._getBackwardsCompatibleTemplate(template) : template;
357
- return import_handlebars.default.compile(templateToUse)(templateData);
315
+ if (!this._isHandlebarsTemplate(templateToUse)) {
316
+ return template;
317
+ }
318
+ const compiledTemplate = import_handlebars.default.compile(templateToUse);
319
+ return compiledTemplate(templateData);
358
320
  }
359
321
  /**
360
322
  * Returns rendered templates using the provided template data.
@@ -372,6 +334,7 @@ var BaseElementsMatcher = class {
372
334
  }
373
335
  /**
374
336
  * Returns whether the given value matches the micromatch pattern, converting non-string values to strings.
337
+ * Optimized version with caching for better performance.
375
338
  * @param value The value to check.
376
339
  * @param pattern The micromatch pattern to match against.
377
340
  * @returns Whether the value matches the pattern.
@@ -379,7 +342,28 @@ var BaseElementsMatcher = class {
379
342
  isMicromatchMatch(value, pattern) {
380
343
  const elementValueToCheck = !value || !isString(value) ? String(value) : value;
381
344
  const selectorValueToCheck = isArray(pattern) ? pattern.filter(Boolean) : pattern;
382
- return import_micromatch.default.isMatch(elementValueToCheck, selectorValueToCheck);
345
+ return this.micromatch.isMatch(elementValueToCheck, selectorValueToCheck);
346
+ }
347
+ /**
348
+ * Returns whether the given value matches the micromatch pattern after rendering it as a template.
349
+ * @param pattern The micromatch pattern to render and match against.
350
+ * @param templateData The data to use for rendering the pattern as a template.
351
+ * @param value The value to check.
352
+ * @returns Whether the value matches the rendered pattern.
353
+ */
354
+ isTemplateMicromatchMatch(pattern, templateData, value) {
355
+ if (isNullish(value)) {
356
+ return false;
357
+ }
358
+ const patternRendered = this.getRenderedTemplates(pattern, templateData);
359
+ if (!patternRendered) {
360
+ return false;
361
+ }
362
+ const filteredPattern = isArray(patternRendered) ? patternRendered.filter(Boolean) : patternRendered;
363
+ if (isArray(value)) {
364
+ return value.some((val) => this.isMicromatchMatch(val, filteredPattern));
365
+ }
366
+ return this.isMicromatchMatch(value, filteredPattern);
383
367
  }
384
368
  /**
385
369
  * Whether the given element key matches the selector key as booleans.
@@ -426,61 +410,34 @@ var BaseElementsMatcher = class {
426
410
  if (!selectorValue) {
427
411
  return false;
428
412
  }
429
- const selectorValueRendered = this.getRenderedTemplates(
430
- selectorValue,
431
- templateData
432
- );
433
- if (!selectorValueRendered) {
434
- return false;
435
- }
436
413
  if (!isObjectWithProperty(element, elementKey)) {
437
414
  return false;
438
415
  }
439
- if (isNullish(element[elementKey])) {
440
- return false;
441
- }
442
- return this.isMicromatchMatch(element[elementKey], selectorValueRendered);
416
+ return this.isTemplateMicromatchMatch(
417
+ selectorValue,
418
+ templateData,
419
+ element[elementKey]
420
+ );
443
421
  }
444
422
  };
445
423
 
446
424
  // src/Matcher/DependenciesMatcher.ts
447
425
  var DependenciesMatcher = class extends BaseElementsMatcher {
448
- /**
449
- * Cache to store previously described dependencies.
450
- */
451
- _cache;
452
426
  /**
453
427
  * Elements matcher to use for matching elements within dependencies.
454
428
  */
455
429
  _elementsMatcher;
456
430
  /**
457
431
  * Creates a new DependenciesMatcher.
432
+ * @param elementsMatcher Elements matcher to use for matching elements within dependencies.
433
+ * @param config Configuration options for the matcher.
434
+ * @param micromatch Micromatch instance for matching.
435
+ * @param globalCache Global cache instance.
458
436
  */
459
- constructor(elementsMatcher, config) {
460
- super(config);
461
- this._cache = new CacheManager();
437
+ constructor(elementsMatcher, config, micromatch2) {
438
+ super(config, micromatch2);
462
439
  this._elementsMatcher = elementsMatcher;
463
440
  }
464
- /**
465
- * Serializes the cache to a plain object.
466
- * @returns The serialized cache.
467
- */
468
- serializeCache() {
469
- return this._cache.serialize();
470
- }
471
- /**
472
- * Sets the cache from a serialized object.
473
- * @param serializedCache The serialized cache.
474
- */
475
- setCacheFromSerialized(serializedCache) {
476
- this._cache.setFromSerialized(serializedCache);
477
- }
478
- /**
479
- * Clears the cache.
480
- */
481
- clearCache() {
482
- this._cache.clear();
483
- }
484
441
  /**
485
442
  * Normalizes selector into DependencySelectorNormalized format, containing arrays of selectors data.
486
443
  * @param selector The dependency selector to normalize.
@@ -618,17 +575,11 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
618
575
  if (!selector.relationship) {
619
576
  return true;
620
577
  }
621
- const renderedPattern = this.getRenderedTemplates(
578
+ return this.isTemplateMicromatchMatch(
622
579
  selector.relationship,
623
- templateData
580
+ templateData,
581
+ relationship
624
582
  );
625
- if (!renderedPattern) {
626
- return false;
627
- }
628
- if (!relationship) {
629
- return false;
630
- }
631
- return this.isMicromatchMatch(relationship, renderedPattern);
632
583
  }
633
584
  /**
634
585
  * Determines if the selector matches an specific kind
@@ -641,17 +592,7 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
641
592
  if (!selector.kind) {
642
593
  return true;
643
594
  }
644
- const renderedPattern = this.getRenderedTemplates(
645
- selector.kind,
646
- templateData
647
- );
648
- if (!renderedPattern) {
649
- return false;
650
- }
651
- if (!kind) {
652
- return false;
653
- }
654
- return this.isMicromatchMatch(kind, renderedPattern);
595
+ return this.isTemplateMicromatchMatch(selector.kind, templateData, kind);
655
596
  }
656
597
  /**
657
598
  * Determines if the selector matches some of the specifiers
@@ -661,22 +602,13 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
661
602
  * @returns Whether the selector matches some of the specifiers
662
603
  */
663
604
  _specifierMatches(selector, specifiers, templateData) {
664
- const specifierPattern = selector.specifiers;
665
- if (!specifierPattern) {
605
+ if (!selector.specifiers) {
666
606
  return true;
667
607
  }
668
- const renderedPattern = this.getRenderedTemplates(
669
- specifierPattern,
670
- templateData
671
- );
672
- if (!renderedPattern) {
673
- return false;
674
- }
675
- if (!specifiers) {
676
- return false;
677
- }
678
- return specifiers.some(
679
- (specifier) => this.isMicromatchMatch(specifier, renderedPattern)
608
+ return this.isTemplateMicromatchMatch(
609
+ selector.specifiers,
610
+ templateData,
611
+ specifiers
680
612
  );
681
613
  }
682
614
  /**
@@ -687,21 +619,14 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
687
619
  * @returns Whether the selector matches the nodeKind
688
620
  */
689
621
  _nodeKindMatches(selector, nodeKind, templateData) {
690
- const nodeKindPattern = selector.nodeKind;
691
- if (!nodeKindPattern) {
622
+ if (!selector.nodeKind) {
692
623
  return true;
693
624
  }
694
- const renderedPattern = this.getRenderedTemplates(
695
- nodeKindPattern,
696
- templateData
625
+ return this.isTemplateMicromatchMatch(
626
+ selector.nodeKind,
627
+ templateData,
628
+ nodeKind
697
629
  );
698
- if (!renderedPattern) {
699
- return false;
700
- }
701
- if (!nodeKind) {
702
- return false;
703
- }
704
- return this.isMicromatchMatch(nodeKind, renderedPattern);
705
630
  }
706
631
  /**
707
632
  * Determines if the dependency description matches the selector for 'from'.
@@ -727,25 +652,17 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
727
652
  * @returns Whether the dependency properties match the selector for 'to'.
728
653
  */
729
654
  _dependencyToPropertiesMatch(dependency, toSelector, templateData) {
730
- return toSelector.some((selectorData) => {
731
- return this._relationshipMatches(
732
- selectorData,
733
- dependency.dependency.relationship.to,
734
- templateData
735
- ) && this._kindMatches(
736
- selectorData,
737
- dependency.dependency.kind,
738
- templateData
739
- ) && this._nodeKindMatches(
740
- selectorData,
741
- dependency.dependency.nodeKind,
742
- templateData
743
- ) && this._specifierMatches(
744
- selectorData,
745
- dependency.dependency.specifiers,
746
- templateData
747
- );
748
- });
655
+ const dependencyInfo = dependency.dependency;
656
+ const relationshipTo = dependencyInfo.relationship.to;
657
+ const kind = dependencyInfo.kind;
658
+ const nodeKind = dependencyInfo.nodeKind;
659
+ const specifiers = dependencyInfo.specifiers;
660
+ for (const selectorData of toSelector) {
661
+ if (this._kindMatches(selectorData, kind, templateData) && this._nodeKindMatches(selectorData, nodeKind, templateData) && this._relationshipMatches(selectorData, relationshipTo, templateData) && this._specifierMatches(selectorData, specifiers, templateData)) {
662
+ return true;
663
+ }
664
+ }
665
+ return false;
749
666
  }
750
667
  /**
751
668
  * Returns the selectors matching result for the given dependency.
@@ -758,29 +675,18 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
758
675
  extraTemplateData = {},
759
676
  dependencySelectorsGlobals = {}
760
677
  } = {}) {
761
- if (this._cache.has({
762
- dependency,
763
- selector,
764
- extraTemplateData,
765
- dependencySelectorsGlobals
766
- })) {
767
- return this._cache.get({
768
- dependency,
769
- selector,
770
- extraTemplateData,
771
- dependencySelectorsGlobals
772
- });
773
- }
774
678
  const normalizedSelector = this._normalizeDependencySelector(
775
679
  selector,
776
680
  dependencySelectorsGlobals
777
681
  );
682
+ const fromExtraData = extraTemplateData.from || {};
683
+ const toExtraData = extraTemplateData.to || {};
778
684
  const templateData = {
779
685
  ...extraTemplateData,
780
686
  from: {
781
687
  ...dependency.from,
782
688
  relationship: dependency.dependency.relationship.from,
783
- ...extraTemplateData.from || {}
689
+ ...fromExtraData
784
690
  },
785
691
  to: {
786
692
  ...dependency.to,
@@ -788,7 +694,7 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
788
694
  kind: dependency.dependency.kind,
789
695
  nodeKind: dependency.dependency.nodeKind,
790
696
  specifiers: dependency.dependency.specifiers,
791
- ...extraTemplateData.to || {}
697
+ ...toExtraData
792
698
  }
793
699
  };
794
700
  const result = this._getSelectorMatching(
@@ -796,15 +702,6 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
796
702
  normalizedSelector,
797
703
  templateData
798
704
  );
799
- this._cache.set(
800
- {
801
- dependency,
802
- selector,
803
- extraTemplateData,
804
- dependencySelectorsGlobals
805
- },
806
- result
807
- );
808
705
  return result;
809
706
  }
810
707
  /**
@@ -825,38 +722,17 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
825
722
  };
826
723
 
827
724
  // src/Matcher/ElementsMatcher.ts
828
- var import_micromatch2 = __toESM(require("micromatch"));
829
725
  var ElementsMatcher = class extends BaseElementsMatcher {
830
- /**
831
- * Cache to store previously described elements.
832
- */
833
- _cache;
726
+ /** Whether the cache is enabled or not */
727
+ _cacheIsEnabled;
834
728
  /**
835
729
  * Creates a new ElementsSelectorMatcher.
730
+ * @param config Configuration options for the matcher.
731
+ * @param micromatch Micromatch instance for matching.
732
+ * @param globalCache Global cache instance.
836
733
  */
837
- constructor(config) {
838
- super(config);
839
- this._cache = new CacheManager();
840
- }
841
- /**
842
- * Serializes the cache to a plain object.
843
- * @returns The serialized cache.
844
- */
845
- serializeCache() {
846
- return this._cache.serialize();
847
- }
848
- /**
849
- * Sets the cache from a serialized object.
850
- * @param serializedCache The serialized cache.
851
- */
852
- setCacheFromSerialized(serializedCache) {
853
- this._cache.setFromSerialized(serializedCache);
854
- }
855
- /**
856
- * Clears the cache.
857
- */
858
- clearCache() {
859
- this._cache.clear();
734
+ constructor(config, micromatch2) {
735
+ super(config, micromatch2);
860
736
  }
861
737
  /**
862
738
  * Whether the given element type matches the selector type.
@@ -1002,13 +878,13 @@ var ElementsMatcher = class extends BaseElementsMatcher {
1002
878
  * @returns True if the captured values match, false otherwise.
1003
879
  */
1004
880
  _isCapturedValuesMatch(element, selector, templateData) {
1005
- if (!selector.captured) {
881
+ if (!selector.captured || isEmptyObject(selector.captured)) {
1006
882
  return true;
1007
883
  }
1008
884
  if (!element.captured) {
1009
885
  return false;
1010
886
  }
1011
- return Object.entries(selector.captured).every(([key, pattern]) => {
887
+ for (const [key, pattern] of Object.entries(selector.captured)) {
1012
888
  const elementValue = element.captured?.[key];
1013
889
  if (!elementValue) {
1014
890
  return false;
@@ -1018,8 +894,12 @@ var ElementsMatcher = class extends BaseElementsMatcher {
1018
894
  return false;
1019
895
  }
1020
896
  const filteredPattern = isArray(renderedPattern) ? renderedPattern.filter(Boolean) : renderedPattern;
1021
- return import_micromatch2.default.isMatch(elementValue, filteredPattern);
1022
- });
897
+ const isMatch = this.micromatch.isMatch(elementValue, filteredPattern);
898
+ if (!isMatch) {
899
+ return false;
900
+ }
901
+ }
902
+ return true;
1023
903
  }
1024
904
  /**
1025
905
  * Determines if the isIgnored property of the element matches that in the selector.
@@ -1056,17 +936,16 @@ var ElementsMatcher = class extends BaseElementsMatcher {
1056
936
  * @param extraTemplateData Extra template data to use for matching.
1057
937
  * @returns The selector matching result for the given element, or null if none matches.
1058
938
  */
1059
- _getSelectorMatching(element, selector, extraTemplateData) {
1060
- const selectorsData = normalizeElementsSelector(selector);
939
+ _getSelectorMatching(element, selectorsData, extraTemplateData) {
1061
940
  const templateData = {
1062
941
  element,
1063
942
  ...extraTemplateData
1064
943
  };
1065
944
  for (const selectorData of selectorsData) {
1066
- const isMatch = this._isTypeMatch(element, selectorData, templateData) && this._isCategoryMatch(element, selectorData, templateData) && this._isCapturedValuesMatch(element, selectorData, templateData) && this._isPathMatch(element, selectorData, templateData) && this._isElementPathMatch(element, selectorData, templateData) && this._isInternalPathMatch(element, selectorData, templateData) && this._isOriginMatch(element, selectorData, templateData) && this._isSourceMatch(element, selectorData, templateData) && this._isBaseSourceMatch(element, selectorData, templateData) && this._isIgnoredMatch(element, selectorData) && this._isUnknownMatch(element, selectorData);
1067
- if (isMatch) {
1068
- return selectorData;
945
+ if (!this._isTypeMatch(element, selectorData, templateData) || !this._isCategoryMatch(element, selectorData, templateData) || !this._isOriginMatch(element, selectorData, templateData) || !this._isIgnoredMatch(element, selectorData) || !this._isUnknownMatch(element, selectorData) || !this._isPathMatch(element, selectorData, templateData) || !this._isElementPathMatch(element, selectorData, templateData) || !this._isInternalPathMatch(element, selectorData, templateData) || !this._isSourceMatch(element, selectorData, templateData) || !this._isBaseSourceMatch(element, selectorData, templateData) || !this._isCapturedValuesMatch(element, selectorData, templateData)) {
946
+ continue;
1069
947
  }
948
+ return selectorData;
1070
949
  }
1071
950
  return null;
1072
951
  }
@@ -1079,31 +958,8 @@ var ElementsMatcher = class extends BaseElementsMatcher {
1079
958
  * @returns The selector matching result for the given element, or null if none matches.
1080
959
  */
1081
960
  getSelectorMatching(element, selector, { extraTemplateData = {} } = {}) {
1082
- if (this._cache.has({
1083
- element,
1084
- selector,
1085
- extraTemplateData
1086
- })) {
1087
- return this._cache.get({
1088
- element,
1089
- selector,
1090
- extraTemplateData
1091
- });
1092
- }
1093
- const result = this._getSelectorMatching(
1094
- element,
1095
- selector,
1096
- extraTemplateData
1097
- );
1098
- this._cache.set(
1099
- {
1100
- element,
1101
- selector,
1102
- extraTemplateData
1103
- },
1104
- result
1105
- );
1106
- return result;
961
+ const selectorsData = normalizeElementsSelector(selector);
962
+ return this._getSelectorMatching(element, selectorsData, extraTemplateData);
1107
963
  }
1108
964
  /**
1109
965
  * Returns whether the given element matches the selector.
@@ -1253,22 +1109,173 @@ function isInternalDependency(dependency) {
1253
1109
  return dependency.dependency.relationship.to === DEPENDENCY_RELATIONSHIPS_MAP.INTERNAL;
1254
1110
  }
1255
1111
 
1112
+ // src/Cache/Cache.ts
1113
+ var CacheManager = class {
1114
+ /**
1115
+ * Internal cache map
1116
+ */
1117
+ _cache;
1118
+ /**
1119
+ * Creates a new CacheManager instance
1120
+ */
1121
+ constructor() {
1122
+ this._cache = /* @__PURE__ */ new Map();
1123
+ }
1124
+ /**
1125
+ * Generates a string key from the given cache key. Has to be implemented for non-string keys.
1126
+ * @param key The cache key to generate from
1127
+ * @returns The generated string key
1128
+ */
1129
+ generateKey(key) {
1130
+ if (isString(key)) {
1131
+ return key;
1132
+ }
1133
+ const errorMessage = "Cache key generation for non-string keys is not implemented because it causes performance issues: " + JSON.stringify(key);
1134
+ throw new Error(errorMessage);
1135
+ }
1136
+ /**
1137
+ * Generates a hashed key for the given cache key
1138
+ * @param key The cache key to hash
1139
+ * @returns The hashed key as a string
1140
+ */
1141
+ getKey(key) {
1142
+ return this.generateKey(key);
1143
+ }
1144
+ /**
1145
+ * Retrieves a value from the cache based on the given hashed key
1146
+ * @param hashedKey The hashed key to retrieve
1147
+ * @returns The cached value or undefined if not found
1148
+ */
1149
+ get(hashedKey) {
1150
+ return this._cache.get(hashedKey);
1151
+ }
1152
+ /**
1153
+ * Stores a value in the cache with a given hashed key
1154
+ * @param hashedKey The hashed key to store
1155
+ * @param value The value to cache
1156
+ */
1157
+ set(hashedKey, value) {
1158
+ this._cache.set(hashedKey, value);
1159
+ }
1160
+ /**
1161
+ * Checks if a value exists in the cache based on the given hashed key
1162
+ * @param hashedKey The hashed key to check
1163
+ * @returns True if the value exists, false otherwise
1164
+ */
1165
+ has(hashedKey) {
1166
+ return this._cache.has(hashedKey);
1167
+ }
1168
+ /**
1169
+ * Retrieves all cached values
1170
+ * @returns A map of all cached values
1171
+ */
1172
+ getAll() {
1173
+ return this._cache;
1174
+ }
1175
+ /**
1176
+ * Clears the entire cache
1177
+ */
1178
+ clear() {
1179
+ this._cache.clear();
1180
+ }
1181
+ /**
1182
+ * Serializes the cache to a plain object.
1183
+ * @returns The serialized cache.
1184
+ */
1185
+ serialize() {
1186
+ return Array.from(this.getAll().entries()).reduce(
1187
+ (acc, [key, value]) => {
1188
+ acc[key] = value;
1189
+ return acc;
1190
+ },
1191
+ {}
1192
+ );
1193
+ }
1194
+ /**
1195
+ * Sets the cache from a serialized object.
1196
+ * @param serializedCache The serialized cache.
1197
+ */
1198
+ setFromSerialized(serializedCache) {
1199
+ for (const key in serializedCache) {
1200
+ this.set(key, serializedCache[key]);
1201
+ }
1202
+ }
1203
+ };
1204
+
1205
+ // src/Cache/CacheDisabled.ts
1206
+ var CacheManagerDisabled = class extends CacheManager {
1207
+ /**
1208
+ * Generates a fake cache key as caching is disabled
1209
+ * @param key The cache key to hash
1210
+ * @returns An empty string
1211
+ */
1212
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1213
+ getKey(_key) {
1214
+ return "";
1215
+ }
1216
+ /**
1217
+ * Does nothing as caching is disabled
1218
+ * @param hashedKey The hashed key to retrieve
1219
+ * @returns Undefined as caching is disabled
1220
+ */
1221
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1222
+ get(_hashedKey) {
1223
+ return void 0;
1224
+ }
1225
+ /**
1226
+ * Does nothing as caching is disabled
1227
+ * @param hashedKey The hashed key to store
1228
+ * @param value The value to cache
1229
+ */
1230
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1231
+ set(_hashedKey, _value) {
1232
+ return;
1233
+ }
1234
+ /**
1235
+ * Does nothing as caching is disabled
1236
+ * @param hashedKey The hashed key to check
1237
+ * @returns False as caching is disabled
1238
+ */
1239
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1240
+ has(_hashedKey) {
1241
+ return false;
1242
+ }
1243
+ };
1244
+
1245
+ // src/Descriptor/DependenciesDescriptionsCache.ts
1246
+ var DependenciesDescriptionsCache = class extends CacheManager {
1247
+ /** Generates a unique key for the given dependency description options.
1248
+ * @param options The options to generate the key from.
1249
+ * @returns The generated key.
1250
+ */
1251
+ generateKey(options) {
1252
+ return `${options.from}|${options.to}|${options.source}|${options.kind}|${options.nodeKind}|${options.specifiers ? options.specifiers.join(",") : ""}`;
1253
+ }
1254
+ };
1255
+
1256
1256
  // src/Descriptor/DependenciesDescriptor.ts
1257
1257
  var DependenciesDescriptor = class {
1258
1258
  /**
1259
1259
  * Cache to store previously described dependencies.
1260
1260
  */
1261
- _dependenciesCache = new CacheManager();
1261
+ _dependenciesCache;
1262
1262
  /**
1263
1263
  * Elements descriptor instance.
1264
1264
  */
1265
1265
  _elementsDescriptor;
1266
+ /**
1267
+ * Configuration options.
1268
+ */
1269
+ _config;
1266
1270
  /**
1267
1271
  * Creates a new DependenciesDescriptor instance.
1268
1272
  * @param elementsDescriptor The elements descriptor instance.
1273
+ * @param config The configuration options.
1269
1274
  */
1270
- constructor(elementsDescriptor) {
1275
+ constructor(elementsDescriptor, config) {
1271
1276
  this._elementsDescriptor = elementsDescriptor;
1277
+ this._config = config;
1278
+ this._dependenciesCache = this._config.cache ? new DependenciesDescriptionsCache() : new CacheManagerDisabled();
1272
1279
  }
1273
1280
  /**
1274
1281
  * Serializes the elements cache to a plain object.
@@ -1419,22 +1426,16 @@ var DependenciesDescriptor = class {
1419
1426
  nodeKind,
1420
1427
  specifiers
1421
1428
  }) {
1422
- if (this._dependenciesCache.has({
1429
+ const cacheKey = this._dependenciesCache.getKey({
1423
1430
  from,
1424
1431
  to,
1425
1432
  source,
1426
1433
  kind,
1427
1434
  nodeKind,
1428
1435
  specifiers
1429
- })) {
1430
- return this._dependenciesCache.get({
1431
- from,
1432
- to,
1433
- source,
1434
- kind,
1435
- nodeKind,
1436
- specifiers
1437
- });
1436
+ });
1437
+ if (this._dependenciesCache.has(cacheKey)) {
1438
+ return this._dependenciesCache.get(cacheKey);
1438
1439
  }
1439
1440
  const fromElement = this._elementsDescriptor.describeElement(from);
1440
1441
  const toElement = this._elementsDescriptor.describeDependencyElement(
@@ -1451,25 +1452,14 @@ var DependenciesDescriptor = class {
1451
1452
  specifiers: specifiers || null
1452
1453
  }
1453
1454
  };
1454
- this._dependenciesCache.set(
1455
- {
1456
- from,
1457
- to,
1458
- source,
1459
- kind,
1460
- nodeKind,
1461
- specifiers
1462
- },
1463
- result
1464
- );
1455
+ this._dependenciesCache.set(cacheKey, result);
1465
1456
  return result;
1466
1457
  }
1467
1458
  };
1468
1459
 
1469
1460
  // src/Descriptor/ElementsDescriptor.ts
1470
1461
  var import_is_core_module = __toESM(require("is-core-module"));
1471
- var import_micromatch3 = __toESM(require("micromatch"));
1472
- var UNKNOWN_LOCAL_ELEMENT = {
1462
+ var UNKNOWN_ELEMENT = {
1473
1463
  path: null,
1474
1464
  elementPath: null,
1475
1465
  internalPath: null,
@@ -1483,16 +1473,18 @@ var UNKNOWN_LOCAL_ELEMENT = {
1483
1473
  isIgnored: false,
1484
1474
  isUnknown: true
1485
1475
  };
1476
+ var SCOPED_PACKAGE_REGEX = /^@[^/]*\/?[^/]+/;
1477
+ var EXTERNAL_PATH_REGEX = /^\w/;
1486
1478
  var ElementsDescriptor = class {
1487
1479
  _mod = null;
1488
1480
  /**
1489
1481
  * Cache to store previously described elements.
1490
1482
  */
1491
- _elementsCache = new CacheManager();
1483
+ _descriptionsCache;
1492
1484
  /**
1493
1485
  * Cache to store previously described files.
1494
1486
  */
1495
- _filesCache = new CacheManager();
1487
+ _filesCache;
1496
1488
  /**
1497
1489
  * Configuration instance for this descriptor.
1498
1490
  */
@@ -1501,15 +1493,22 @@ var ElementsDescriptor = class {
1501
1493
  * Element descriptors used by this descriptor.
1502
1494
  */
1503
1495
  _elementDescriptors;
1496
+ /** Micromatch instance for path matching */
1497
+ _micromatch;
1504
1498
  /**
1505
1499
  * The configuration options for this descriptor.
1506
1500
  * @param elementDescriptors The element descriptors.
1507
1501
  * @param configOptions The configuration options.
1502
+ * @param globalCache The global cache for various caching needs.
1503
+ * @param micromatch The micromatch instance for path matching.
1508
1504
  */
1509
- constructor(elementDescriptors, configOptions) {
1505
+ constructor(elementDescriptors, configOptions, micromatch2) {
1506
+ this._micromatch = micromatch2;
1510
1507
  this._elementDescriptors = elementDescriptors;
1511
1508
  this._validateDescriptors(elementDescriptors);
1512
- this._config = new Config(configOptions);
1509
+ this._config = configOptions;
1510
+ this._filesCache = this._config.cache ? new CacheManager() : new CacheManagerDisabled();
1511
+ this._descriptionsCache = this._config.cache ? new CacheManager() : new CacheManagerDisabled();
1513
1512
  this._loadModuleInNode();
1514
1513
  }
1515
1514
  /**
@@ -1517,20 +1516,24 @@ var ElementsDescriptor = class {
1517
1516
  * @returns The serialized elements cache.
1518
1517
  */
1519
1518
  serializeCache() {
1520
- return this._elementsCache.serialize();
1519
+ return {
1520
+ descriptions: this._descriptionsCache.serialize(),
1521
+ files: this._filesCache.serialize()
1522
+ };
1521
1523
  }
1522
1524
  /**
1523
1525
  * Sets the elements cache from a serialized object.
1524
1526
  * @param serializedCache The serialized elements cache.
1525
1527
  */
1526
1528
  setCacheFromSerialized(serializedCache) {
1527
- this._elementsCache.setFromSerialized(serializedCache);
1529
+ this._descriptionsCache.setFromSerialized(serializedCache.descriptions);
1530
+ this._filesCache.setFromSerialized(serializedCache.files);
1528
1531
  }
1529
1532
  /**
1530
1533
  * Clears the elements cache.
1531
1534
  */
1532
1535
  clearCache() {
1533
- this._elementsCache.clear();
1536
+ this._descriptionsCache.clear();
1534
1537
  this._filesCache.clear();
1535
1538
  }
1536
1539
  /**
@@ -1574,7 +1577,7 @@ var ElementsDescriptor = class {
1574
1577
  * @returns True if the dependency source is scoped, false otherwise.
1575
1578
  */
1576
1579
  _dependencySourceIsScoped(dependencySource) {
1577
- return /^@[^/]*\/?[^/]+/.test(dependencySource);
1580
+ return SCOPED_PACKAGE_REGEX.test(dependencySource);
1578
1581
  }
1579
1582
  /**
1580
1583
  * Determines if a dependency source is external or an alias.
@@ -1582,14 +1585,14 @@ var ElementsDescriptor = class {
1582
1585
  * @returns True if the dependency source is external or an alias, false otherwise.
1583
1586
  */
1584
1587
  _dependencySourceIsExternalOrScoped(dependencySource) {
1585
- return /^\w/.test(dependencySource) || this._dependencySourceIsScoped(dependencySource);
1588
+ return EXTERNAL_PATH_REGEX.test(dependencySource) || this._dependencySourceIsScoped(dependencySource);
1586
1589
  }
1587
1590
  /**
1588
1591
  * Gets the base source of an external module.
1589
1592
  * @param dependencySource The source of the dependency to check.
1590
1593
  * @returns The base source of the external module. (e.g., for "@scope/package/submodule", it returns "@scope/package")
1591
1594
  */
1592
- _getExternalModuleBaseSource(dependencySource) {
1595
+ _getExternalOrCoreModuleBaseSource(dependencySource) {
1593
1596
  if (this._dependencySourceIsScoped(dependencySource)) {
1594
1597
  const [scope, packageName] = dependencySource.split("/");
1595
1598
  return `${scope}/${packageName}`;
@@ -1612,27 +1615,31 @@ var ElementsDescriptor = class {
1612
1615
  }
1613
1616
  /**
1614
1617
  * Determines if a given path is included based on the configuration.
1618
+ * Uses caching for better performance on repeated calls.
1615
1619
  * @param elementPath The element path to check.
1620
+ * @param includeExternal Whether to include external files.
1616
1621
  * @returns True if the path is included, false otherwise.
1617
1622
  */
1618
- _pathIsIncluded(elementPath, includeExternal) {
1619
- const isExternal = includeExternal ? import_micromatch3.default.isMatch(elementPath, "**/node_modules/**") : false;
1620
- if (this._config.options.includePaths && this._config.options.ignorePaths) {
1621
- const isIncluded = import_micromatch3.default.isMatch(
1623
+ _pathIsIncluded(elementPath) {
1624
+ let result;
1625
+ if (this._config.includePaths && this._config.ignorePaths) {
1626
+ const isIncluded = this._micromatch.isMatch(
1622
1627
  elementPath,
1623
- this._config.options.includePaths
1628
+ this._config.includePaths
1624
1629
  );
1625
- const isIgnored = import_micromatch3.default.isMatch(
1630
+ const isIgnored = this._micromatch.isMatch(
1626
1631
  elementPath,
1627
- this._config.options.ignorePaths
1632
+ this._config.ignorePaths
1628
1633
  );
1629
- return (isIncluded || isExternal) && !isIgnored;
1630
- } else if (this._config.options.includePaths) {
1631
- return import_micromatch3.default.isMatch(elementPath, this._config.options.includePaths) || isExternal;
1632
- } else if (this._config.options.ignorePaths) {
1633
- return !import_micromatch3.default.isMatch(elementPath, this._config.options.ignorePaths);
1634
+ result = isIncluded && !isIgnored;
1635
+ } else if (this._config.includePaths) {
1636
+ result = this._micromatch.isMatch(elementPath, this._config.includePaths);
1637
+ } else if (this._config.ignorePaths) {
1638
+ result = !this._micromatch.isMatch(elementPath, this._config.ignorePaths);
1639
+ } else {
1640
+ result = true;
1634
1641
  }
1635
- return true;
1642
+ return result;
1636
1643
  }
1637
1644
  /**
1638
1645
  * Gets captured values from the captured array and capture configuration.
@@ -1659,16 +1666,15 @@ var ElementsDescriptor = class {
1659
1666
  * @returns The element path.
1660
1667
  */
1661
1668
  _getElementPath(pathPattern, pathSegments, allPathSegments) {
1662
- const elementPathRegexp = import_micromatch3.default.makeRe(pathPattern);
1669
+ const elementPathRegexp = this._micromatch.makeRe(pathPattern);
1663
1670
  const testedSegments = [];
1664
1671
  let result;
1665
1672
  for (const pathSegment of pathSegments) {
1666
- if (!result) {
1667
- testedSegments.push(pathSegment);
1668
- const joinedSegments = testedSegments.join("/");
1669
- if (elementPathRegexp.test(joinedSegments)) {
1670
- result = joinedSegments;
1671
- }
1673
+ testedSegments.push(pathSegment);
1674
+ const joinedSegments = testedSegments.join("/");
1675
+ if (elementPathRegexp.test(joinedSegments)) {
1676
+ result = joinedSegments;
1677
+ break;
1672
1678
  }
1673
1679
  }
1674
1680
  return `${[...allPathSegments].reverse().join("/").split(result)[0]}${result}`;
@@ -1685,20 +1691,18 @@ var ElementsDescriptor = class {
1685
1691
  for (const pattern of patterns) {
1686
1692
  const useFullPathMatch = mode === ELEMENT_DESCRIPTOR_MODES_MAP.FULL && !alreadyMatched;
1687
1693
  const effectivePattern = mode === ELEMENT_DESCRIPTOR_MODES_MAP.FOLDER && !alreadyMatched ? `${pattern}/**/*` : pattern;
1694
+ const targetPath = useFullPathMatch ? filePath : currentPathSegments.join("/");
1688
1695
  let baseCapture = null;
1689
1696
  let hasCapture = true;
1690
1697
  if (elementDescriptor.basePattern) {
1691
1698
  const baseTarget = filePath.split("/").slice(0, filePath.split("/").length - lastPathSegmentMatching).join("/");
1692
- baseCapture = import_micromatch3.default.capture(
1699
+ baseCapture = this._micromatch.capture(
1693
1700
  [elementDescriptor.basePattern, "**", effectivePattern].join("/"),
1694
1701
  baseTarget
1695
1702
  );
1696
1703
  hasCapture = baseCapture !== null;
1697
1704
  }
1698
- const capture = import_micromatch3.default.capture(
1699
- effectivePattern,
1700
- useFullPathMatch ? filePath : currentPathSegments.join("/")
1701
- );
1705
+ const capture = this._micromatch.capture(effectivePattern, targetPath);
1702
1706
  if (capture && hasCapture) {
1703
1707
  return {
1704
1708
  matched: true,
@@ -1712,22 +1716,19 @@ var ElementsDescriptor = class {
1712
1716
  return { matched: false };
1713
1717
  }
1714
1718
  /**
1715
- * Retrieves the description of an element given its path.
1716
- * It does not identify external files. Files not matching any element are considered unknown.
1717
- * If a file in node_modules does a match, it is considered local as well.
1718
- * @param includeExternal Whether to include external files (inside node_modules) in the matching process.
1719
+ * Retrieves the description of a local file given its path.
1719
1720
  * @param elementPath The path of the element to describe.
1720
1721
  * @returns The description of the element.
1721
1722
  */
1722
- _getFileDescription(includeExternal, filePath) {
1723
+ _getFileDescription(filePath) {
1723
1724
  if (!filePath) {
1724
1725
  return {
1725
- ...UNKNOWN_LOCAL_ELEMENT
1726
+ ...UNKNOWN_ELEMENT
1726
1727
  };
1727
1728
  }
1728
- if (!this._pathIsIncluded(filePath, includeExternal)) {
1729
+ if (!this._pathIsIncluded(filePath)) {
1729
1730
  return {
1730
- ...UNKNOWN_LOCAL_ELEMENT,
1731
+ ...UNKNOWN_ELEMENT,
1731
1732
  path: filePath,
1732
1733
  isIgnored: true,
1733
1734
  origin: null
@@ -1783,13 +1784,14 @@ var ElementsDescriptor = class {
1783
1784
  for (let i = 0; i < pathSegments.length; i++) {
1784
1785
  const segment = pathSegments[i];
1785
1786
  state.pathSegmentsAccumulator.unshift(segment);
1787
+ const alreadyHasMainElement = Boolean(elementResult.type) || Boolean(elementResult.category);
1786
1788
  for (const elementDescriptor of this._elementDescriptors) {
1787
1789
  const match = this._fileDescriptorMatch({
1788
1790
  elementDescriptor,
1789
1791
  filePath,
1790
1792
  currentPathSegments: state.pathSegmentsAccumulator,
1791
1793
  lastPathSegmentMatching: state.lastPathSegmentMatching,
1792
- alreadyMatched: Boolean(elementResult.type) || Boolean(elementResult.category)
1794
+ alreadyMatched: alreadyHasMainElement
1793
1795
  });
1794
1796
  if (match.matched) {
1795
1797
  processElementMatch(
@@ -1807,7 +1809,7 @@ var ElementsDescriptor = class {
1807
1809
  const result = { ...elementResult, parents };
1808
1810
  if (!isKnownLocalElement(result)) {
1809
1811
  return {
1810
- ...UNKNOWN_LOCAL_ELEMENT,
1812
+ ...UNKNOWN_ELEMENT,
1811
1813
  path: filePath
1812
1814
  };
1813
1815
  }
@@ -1819,35 +1821,30 @@ var ElementsDescriptor = class {
1819
1821
  * @param filePath The path of the file to describe.
1820
1822
  * @returns The description of the element.
1821
1823
  */
1822
- _describeFile(includeExternal, filePath) {
1823
- if (this._filesCache.has(String(filePath))) {
1824
- return this._filesCache.get(String(filePath));
1824
+ _describeFile(filePath) {
1825
+ const cacheKey = this._filesCache.getKey(String(filePath));
1826
+ if (this._filesCache.has(cacheKey)) {
1827
+ return this._filesCache.get(cacheKey);
1825
1828
  }
1826
- const description = this._getFileDescription(includeExternal, filePath);
1827
- this._filesCache.set(String(filePath), description);
1829
+ const description = this._getFileDescription(filePath);
1830
+ this._filesCache.set(cacheKey, description);
1828
1831
  return description;
1829
1832
  }
1830
1833
  /**
1831
- * Describes a dependency element given the file element and dependency source, by completing the file description.
1832
- * @param element The file element to complete the description for.
1834
+ * Returns an external or core dependency element given its dependency source and file path.
1833
1835
  * @param dependencySource The source of the dependency.
1834
- * @returns The description of the dependency element.
1836
+ * @param filePath The resolved file path of the dependency, if known.
1837
+ * @returns The external or core dependency element, or null if it is a local dependency.
1835
1838
  */
1836
- _describeDependencyElement(element, dependencySource) {
1837
- if (isIgnoredElement(element)) {
1838
- return {
1839
- ...element,
1840
- source: dependencySource
1841
- };
1842
- }
1843
- const baseDependencySource = this._getExternalModuleBaseSource(dependencySource);
1839
+ _getExternalOrCoreDependencyElement(dependencySource, filePath) {
1840
+ const baseDependencySource = this._getExternalOrCoreModuleBaseSource(dependencySource);
1844
1841
  const isCore = this._dependencySourceIsCoreModule(
1845
1842
  dependencySource,
1846
1843
  baseDependencySource
1847
1844
  );
1848
1845
  if (isCore) {
1849
1846
  const coreElement = {
1850
- ...element,
1847
+ ...UNKNOWN_ELEMENT,
1851
1848
  source: dependencySource,
1852
1849
  baseSource: baseDependencySource,
1853
1850
  origin: ELEMENT_ORIGINS_MAP.CORE
@@ -1855,44 +1852,38 @@ var ElementsDescriptor = class {
1855
1852
  return coreElement;
1856
1853
  }
1857
1854
  const isExternal = this._isExternalDependency(
1858
- element.path,
1855
+ filePath || null,
1859
1856
  dependencySource
1860
1857
  );
1861
- if (!isExternal) {
1862
- const localElement = {
1863
- ...element,
1864
- source: dependencySource
1858
+ if (isExternal) {
1859
+ const externalElement = {
1860
+ ...UNKNOWN_ELEMENT,
1861
+ path: filePath || null,
1862
+ internalPath: dependencySource.replace(baseDependencySource, ""),
1863
+ source: dependencySource,
1864
+ baseSource: baseDependencySource,
1865
+ origin: ELEMENT_ORIGINS_MAP.EXTERNAL
1865
1866
  };
1866
- return localElement;
1867
- }
1868
- const externalElement = {
1869
- ...element,
1870
- internalPath: dependencySource.replace(baseDependencySource, ""),
1871
- source: dependencySource,
1872
- baseSource: baseDependencySource,
1873
- origin: ELEMENT_ORIGINS_MAP.EXTERNAL
1874
- };
1875
- return externalElement;
1867
+ return externalElement;
1868
+ }
1869
+ return null;
1876
1870
  }
1877
1871
  _describeElement(filePath, dependencySource) {
1878
- if (this._elementsCache.has({
1879
- dependencySource,
1880
- filePath: String(filePath)
1881
- })) {
1882
- return this._elementsCache.get({
1883
- dependencySource,
1884
- filePath: String(filePath)
1885
- });
1886
- }
1887
- const fileDescription = this._describeFile(!!dependencySource, filePath);
1888
- const elementResult = dependencySource ? this._describeDependencyElement(fileDescription, dependencySource) : fileDescription;
1889
- this._elementsCache.set(
1890
- {
1891
- dependencySource,
1892
- filePath: String(filePath)
1893
- },
1894
- elementResult
1895
- );
1872
+ const cacheKey = `${String(dependencySource)}::${String(filePath)}`;
1873
+ if (this._descriptionsCache.has(cacheKey)) {
1874
+ return this._descriptionsCache.get(cacheKey);
1875
+ }
1876
+ const externalOrCoreDependencyElement = dependencySource ? this._getExternalOrCoreDependencyElement(dependencySource, filePath) : null;
1877
+ if (externalOrCoreDependencyElement) {
1878
+ this._descriptionsCache.set(cacheKey, externalOrCoreDependencyElement);
1879
+ return externalOrCoreDependencyElement;
1880
+ }
1881
+ const fileDescription = this._describeFile(filePath);
1882
+ const elementResult = dependencySource ? {
1883
+ ...fileDescription,
1884
+ source: dependencySource
1885
+ } : fileDescription;
1886
+ this._descriptionsCache.set(cacheKey, elementResult);
1896
1887
  return elementResult;
1897
1888
  }
1898
1889
  /**
@@ -1921,14 +1912,17 @@ var Descriptors = class {
1921
1912
  /** Creates a new DescriptorsManager instance
1922
1913
  * @param elementDescriptors The element descriptors.
1923
1914
  * @param configOptions The configuration options.
1915
+ * @param micromatch The Micromatch instance.
1924
1916
  */
1925
- constructor(elementDescriptors, configOptions) {
1917
+ constructor(elementDescriptors, config, micromatch2) {
1926
1918
  this._elementsDescriptor = new ElementsDescriptor(
1927
1919
  elementDescriptors,
1928
- configOptions
1920
+ config,
1921
+ micromatch2
1929
1922
  );
1930
1923
  this._dependenciesDescriptor = new DependenciesDescriptor(
1931
- this._elementsDescriptor
1924
+ this._elementsDescriptor,
1925
+ config
1932
1926
  );
1933
1927
  }
1934
1928
  /**
@@ -1996,15 +1990,15 @@ var Matcher = class {
1996
1990
  /**
1997
1991
  * Constructor for the Matcher class.
1998
1992
  * @param descriptors Element descriptors to use for matching.
1993
+ * @param elementsMatcher Elements matcher instance.
1994
+ * @param dependenciesMatcher Dependencies matcher instance.
1999
1995
  * @param config Configuration options.
1996
+ * @param globalCache Global cache instance.
2000
1997
  */
2001
- constructor(descriptors, config) {
2002
- this._descriptors = new Descriptors(descriptors, config);
2003
- this._elementsMatcher = new ElementsMatcher(config);
2004
- this._dependenciesMatcher = new DependenciesMatcher(
2005
- this._elementsMatcher,
2006
- config
2007
- );
1998
+ constructor(descriptors, elementsMatcher, dependenciesMatcher, config, micromatch2) {
1999
+ this._descriptors = new Descriptors(descriptors, config, micromatch2);
2000
+ this._elementsMatcher = elementsMatcher;
2001
+ this._dependenciesMatcher = dependenciesMatcher;
2008
2002
  }
2009
2003
  /**
2010
2004
  * Determines if an element matches a given selector.
@@ -2068,7 +2062,7 @@ var Matcher = class {
2068
2062
  * @param options Extra options for matching
2069
2063
  * @returns The matching dependency result or null if no match is found
2070
2064
  */
2071
- _isDependencySelectorMatching(dependencyData, selector, options) {
2065
+ _getDependencySelectorMatching(dependencyData, selector, options) {
2072
2066
  const description = this._descriptors.describeDependency(dependencyData);
2073
2067
  return this._dependenciesMatcher.getSelectorsMatching(
2074
2068
  description,
@@ -2084,7 +2078,7 @@ var Matcher = class {
2084
2078
  options
2085
2079
  );
2086
2080
  }
2087
- return this._isDependencySelectorMatching(
2081
+ return this._getDependencySelectorMatching(
2088
2082
  descriptorOptions,
2089
2083
  selector,
2090
2084
  options
@@ -2141,32 +2135,161 @@ var Matcher = class {
2141
2135
  */
2142
2136
  clearCache() {
2143
2137
  this._descriptors.clearCache();
2144
- this._elementsMatcher.clearCache();
2145
- this._dependenciesMatcher.clearCache();
2146
2138
  }
2147
2139
  /**
2148
- * Serializes the descriptors and elements matchers cache to a plain object.
2140
+ * Serializes the descriptors matchers cache to a plain object.
2149
2141
  * @returns The serialized cache
2150
2142
  */
2151
2143
  serializeCache() {
2152
2144
  return {
2153
- descriptors: this._descriptors.serializeCache(),
2154
- elementsMatcher: this._elementsMatcher.serializeCache(),
2155
- dependenciesMatcher: this._dependenciesMatcher.serializeCache()
2145
+ descriptors: this._descriptors.serializeCache()
2156
2146
  };
2157
2147
  }
2158
2148
  /**
2159
- * Sets the descriptors and elements matchers cache from a serialized object.
2149
+ * Sets the descriptors matchers cache from a serialized object.
2160
2150
  * @param serializedCache The serialized cache
2161
2151
  */
2162
2152
  setCacheFromSerialized(serializedCache) {
2163
2153
  this._descriptors.setCacheFromSerialized(serializedCache.descriptors);
2164
- this._elementsMatcher.setCacheFromSerialized(
2165
- serializedCache.elementsMatcher
2166
- );
2167
- this._dependenciesMatcher.setCacheFromSerialized(
2168
- serializedCache.dependenciesMatcher
2154
+ }
2155
+ };
2156
+
2157
+ // src/Matcher/Micromatch.ts
2158
+ var import_micromatch = __toESM(require("micromatch"));
2159
+ var MatchingResultsCache = class extends CacheManager {
2160
+ /**
2161
+ * Generates a unique cache key based on the value and pattern
2162
+ * @param param0 The cache key components
2163
+ * @returns The generated cache key
2164
+ */
2165
+ generateKey({ value, pattern }) {
2166
+ return `${value}::${isArray(pattern) ? pattern.join("|") : pattern}`;
2167
+ }
2168
+ };
2169
+ var CapturedValueCache = class extends CacheManager {
2170
+ /**
2171
+ * Generates a unique cache key based on the pattern and target
2172
+ * @param param0 The cache key components
2173
+ * @returns The generated cache key
2174
+ */
2175
+ generateKey({ pattern, target }) {
2176
+ return `${pattern}|${target}`;
2177
+ }
2178
+ };
2179
+ var Micromatch = class {
2180
+ /**
2181
+ * Cache for micromatch matching results
2182
+ */
2183
+ _matchingResultsCache;
2184
+ /**
2185
+ * Cache for micromatch captures
2186
+ */
2187
+ _capturesCache = new CacheManagerDisabled();
2188
+ /**
2189
+ * Cache for micromatch makeRe results
2190
+ */
2191
+ _makeReCache = new CacheManagerDisabled();
2192
+ /**
2193
+ * Creates an instance of Micromatch class.
2194
+ * @param cache Whether to use caching or not.
2195
+ */
2196
+ constructor(cache) {
2197
+ this._matchingResultsCache = cache ? new MatchingResultsCache() : new CacheManagerDisabled();
2198
+ this._capturesCache = cache ? new CapturedValueCache() : new CacheManagerDisabled();
2199
+ this._makeReCache = cache ? new CacheManager() : new CacheManagerDisabled();
2200
+ }
2201
+ /**
2202
+ * Clears all caches.
2203
+ */
2204
+ clearCache() {
2205
+ this._matchingResultsCache.clear();
2206
+ this._capturesCache.clear();
2207
+ this._makeReCache.clear();
2208
+ }
2209
+ /**
2210
+ * Serializes the current cache state.
2211
+ * @returns The serialized cache data.
2212
+ */
2213
+ serializeCache() {
2214
+ return {
2215
+ matchingResults: this._matchingResultsCache.serialize(),
2216
+ captures: this._capturesCache.serialize()
2217
+ };
2218
+ }
2219
+ /**
2220
+ * Restores the cache state from serialized data.
2221
+ * @param serializedCache The serialized cache data.
2222
+ */
2223
+ setFromSerialized(serializedCache) {
2224
+ this._matchingResultsCache.setFromSerialized(
2225
+ serializedCache.matchingResults
2169
2226
  );
2227
+ this._capturesCache.setFromSerialized(serializedCache.captures);
2228
+ }
2229
+ /**
2230
+ * Optimized micromatch match with caching.
2231
+ * @param value The value to match.
2232
+ * @param pattern The pattern to match against.
2233
+ * @returns True if the value matches the pattern, false otherwise.
2234
+ */
2235
+ isMatch(value, pattern) {
2236
+ const cacheKey = this._matchingResultsCache.getKey({
2237
+ value,
2238
+ pattern
2239
+ });
2240
+ if (this._matchingResultsCache.has(cacheKey)) {
2241
+ return this._matchingResultsCache.get(cacheKey);
2242
+ }
2243
+ const isMatch = import_micromatch.default.isMatch(value, pattern);
2244
+ this._matchingResultsCache.set(cacheKey, isMatch);
2245
+ return isMatch;
2246
+ }
2247
+ /**
2248
+ * Optimized micromatch capture with caching.
2249
+ * @param pattern The pattern to match against.
2250
+ * @param target The target string to test.
2251
+ * @returns Captured groups or null if no match.
2252
+ */
2253
+ capture(pattern, target) {
2254
+ const cacheKey = this._capturesCache.getKey({ pattern, target });
2255
+ if (this._capturesCache.has(cacheKey)) {
2256
+ return this._capturesCache.get(cacheKey);
2257
+ }
2258
+ const result = import_micromatch.default.capture(pattern, target);
2259
+ this._capturesCache.set(cacheKey, result);
2260
+ return result;
2261
+ }
2262
+ /**
2263
+ * Optimized micromatch makeRe with caching.
2264
+ * @param pattern The pattern to convert to RegExp.
2265
+ * @returns The RegExp instance.
2266
+ */
2267
+ makeRe(pattern) {
2268
+ if (this._makeReCache.has(pattern)) {
2269
+ return this._makeReCache.get(pattern);
2270
+ }
2271
+ const regexp = import_micromatch.default.makeRe(pattern);
2272
+ this._makeReCache.set(pattern, regexp);
2273
+ return regexp;
2274
+ }
2275
+ };
2276
+
2277
+ // src/MatchersCache.ts
2278
+ var MatchersCache = class extends CacheManager {
2279
+ /**
2280
+ * Generates a unique key based on the configuration options and element descriptors
2281
+ * @param params The configuration and element descriptors
2282
+ * @returns A unique string key
2283
+ */
2284
+ generateKey({
2285
+ config,
2286
+ elementDescriptors
2287
+ }) {
2288
+ const configHash = `${config.legacyTemplates}|${config.includePaths}|${config.ignorePaths}|${config.cache}`;
2289
+ const elementDescriptorsHash = elementDescriptors.map(
2290
+ (descriptor) => `${descriptor.type}|${descriptor.category}|${descriptor.pattern}|${descriptor.basePattern}|${descriptor.mode}|${descriptor.capture}|${descriptor.baseCapture}`
2291
+ ).join(",");
2292
+ return `${configHash}|:|${elementDescriptorsHash}`;
2170
2293
  }
2171
2294
  };
2172
2295
 
@@ -2175,11 +2298,10 @@ var Elements = class {
2175
2298
  /** The global configuration options for Elements. Can be overridden when getting a descriptor */
2176
2299
  _globalConfigOptions;
2177
2300
  /** Cache manager for Matcher instances, unique for each different configuration */
2178
- _matchersCache = new CacheManager();
2179
- /** Matcher for element selectors */
2180
- _elementsMatcher;
2181
- /** Matcher for dependency selectors */
2182
- _dependenciesMatcher;
2301
+ _matchersCache = new MatchersCache();
2302
+ /** Micromatch instances for pattern matching */
2303
+ _micromatchWithCache = new Micromatch(true);
2304
+ _micromatchWithoutCache = new Micromatch(false);
2183
2305
  /**
2184
2306
  * Creates a new Elements instance
2185
2307
  * @param configOptions The global configuration options for Elements. Can be overridden when getting a descriptor.
@@ -2187,11 +2309,6 @@ var Elements = class {
2187
2309
  constructor(configOptions) {
2188
2310
  const globalConfig = new Config(configOptions);
2189
2311
  this._globalConfigOptions = globalConfig.options;
2190
- this._elementsMatcher = new ElementsMatcher(this._globalConfigOptions);
2191
- this._dependenciesMatcher = new DependenciesMatcher(
2192
- this._elementsMatcher,
2193
- this._globalConfigOptions
2194
- );
2195
2312
  }
2196
2313
  /**
2197
2314
  * Returns a serialized representation of the current state of the cache.
@@ -2201,20 +2318,20 @@ var Elements = class {
2201
2318
  const matchersCache = Array.from(
2202
2319
  this._matchersCache.getAll().entries()
2203
2320
  ).reduce(
2204
- (acc, [key, descriptorCache]) => {
2321
+ (acc, [key, cache]) => {
2205
2322
  acc[key] = {
2206
- config: descriptorCache.config,
2207
- elementDescriptors: descriptorCache.elementDescriptors,
2208
- cache: descriptorCache.matcher.serializeCache()
2323
+ config: cache.config,
2324
+ elementDescriptors: cache.elementDescriptors,
2325
+ cache: cache.matcher.serializeCache()
2209
2326
  };
2210
2327
  return acc;
2211
2328
  },
2212
2329
  {}
2213
2330
  );
2331
+ const micromatchCache = this._micromatchWithCache.serializeCache();
2214
2332
  return {
2215
2333
  matchers: matchersCache,
2216
- elementsMatcher: this._elementsMatcher.serializeCache(),
2217
- dependenciesMatcher: this._dependenciesMatcher.serializeCache()
2334
+ micromatch: micromatchCache
2218
2335
  };
2219
2336
  }
2220
2337
  /**
@@ -2222,54 +2339,70 @@ var Elements = class {
2222
2339
  * @param serializedCache The serialized cache to set.
2223
2340
  */
2224
2341
  setCacheFromSerialized(serializedCache) {
2342
+ this._micromatchWithCache.setFromSerialized(serializedCache.micromatch);
2225
2343
  for (const key in serializedCache.matchers) {
2226
2344
  const matcher = this.getMatcher(
2227
2345
  serializedCache.matchers[key].elementDescriptors,
2228
2346
  serializedCache.matchers[key].config
2229
2347
  );
2230
2348
  matcher.setCacheFromSerialized(serializedCache.matchers[key].cache);
2231
- this._matchersCache.restore(key, {
2349
+ this._matchersCache.set(key, {
2232
2350
  config: serializedCache.matchers[key].config,
2233
2351
  elementDescriptors: serializedCache.matchers[key].elementDescriptors,
2234
2352
  matcher
2235
2353
  });
2236
2354
  }
2237
- this._elementsMatcher.setCacheFromSerialized(
2238
- serializedCache.elementsMatcher
2239
- );
2240
- this._dependenciesMatcher.setCacheFromSerialized(
2241
- serializedCache.dependenciesMatcher
2242
- );
2243
2355
  }
2244
2356
  /**
2245
2357
  * Clears cache
2246
2358
  */
2247
2359
  clearCache() {
2248
- this._elementsMatcher.clearCache();
2249
- this._dependenciesMatcher.clearCache();
2250
2360
  for (const { matcher } of this._matchersCache.getAll().values()) {
2251
2361
  matcher.clearCache();
2252
2362
  }
2253
2363
  this._matchersCache.clear();
2364
+ this._micromatchWithCache.clearCache();
2254
2365
  }
2255
2366
  /**
2256
2367
  * Gets a Matcher instance for the given configuration options.
2257
2368
  * It uses caching to return the same instance for the same configuration options. If no options are provided, the global configuration options are used.
2258
2369
  * @param elementDescriptors The element descriptors to use.
2259
- * @param configOptions Optional configuration options to override the global ones.
2370
+ * @param config Optional configuration options to override the global ones.
2260
2371
  * @returns A matcher instance, unique for each different configuration.
2261
2372
  */
2262
- getMatcher(elementDescriptors, configOptions) {
2263
- const optionsToUse = configOptions || this._globalConfigOptions;
2373
+ getMatcher(elementDescriptors, config) {
2374
+ const optionsToUse = config || this._globalConfigOptions;
2264
2375
  const configInstance = new Config(optionsToUse);
2265
- const normalizedOptions = configInstance.options;
2266
- const cacheKey = { config: normalizedOptions, elementDescriptors };
2376
+ const cacheIsEnabled = configInstance.cache;
2377
+ const configOptionsNormalized = configInstance.options;
2378
+ const descriptorNormalizedOptions = configInstance.descriptorOptions;
2379
+ const matchersNormalizedOptions = configInstance.matchersOptions;
2380
+ const cacheKey = this._matchersCache.getKey({
2381
+ config: configOptionsNormalized,
2382
+ elementDescriptors
2383
+ });
2267
2384
  if (this._matchersCache.has(cacheKey)) {
2268
2385
  return this._matchersCache.get(cacheKey).matcher;
2269
2386
  }
2270
- const matcher = new Matcher(elementDescriptors, normalizedOptions);
2387
+ const micromatch2 = cacheIsEnabled ? this._micromatchWithCache : this._micromatchWithoutCache;
2388
+ const elementsMatcher = new ElementsMatcher(
2389
+ matchersNormalizedOptions,
2390
+ micromatch2
2391
+ );
2392
+ const dependenciesMatcher = new DependenciesMatcher(
2393
+ elementsMatcher,
2394
+ matchersNormalizedOptions,
2395
+ micromatch2
2396
+ );
2397
+ const matcher = new Matcher(
2398
+ elementDescriptors,
2399
+ elementsMatcher,
2400
+ dependenciesMatcher,
2401
+ descriptorNormalizedOptions,
2402
+ micromatch2
2403
+ );
2271
2404
  this._matchersCache.set(cacheKey, {
2272
- config: normalizedOptions,
2405
+ config: configOptionsNormalized,
2273
2406
  elementDescriptors,
2274
2407
  matcher
2275
2408
  });