@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.mjs CHANGED
@@ -5,99 +5,6 @@ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require
5
5
  throw Error('Dynamic require of "' + x + '" is not supported');
6
6
  });
7
7
 
8
- // src/Cache/Cache.ts
9
- import objectHash from "object-hash";
10
- var CacheManager = class {
11
- /**
12
- * Internal cache map
13
- */
14
- _cache;
15
- /**
16
- * Creates a new CacheManager instance
17
- */
18
- constructor() {
19
- this._cache = /* @__PURE__ */ new Map();
20
- }
21
- /**
22
- * Generates a hashed key for the given cache key
23
- * @param key The cache key to hash
24
- * @returns The hashed key as a string
25
- */
26
- _getHashedKey(key) {
27
- return objectHash(key);
28
- }
29
- /**
30
- * Retrieves a value from the cache based on the given key
31
- * @param key The cache key to retrieve
32
- * @returns The cached value or undefined if not found
33
- */
34
- get(key) {
35
- const hashedKey = this._getHashedKey(key);
36
- return this._cache.get(hashedKey);
37
- }
38
- /**
39
- * Stores a value in the cache
40
- * @param key The cache key to store
41
- * @param value The value to cache
42
- */
43
- set(key, value) {
44
- const hashedKey = this._getHashedKey(key);
45
- this._cache.set(hashedKey, value);
46
- }
47
- /**
48
- * Restores a value in the cache from a given already hashed key
49
- * @param key The hashed key to restore
50
- * @param value The value to restore
51
- */
52
- restore(key, value) {
53
- this._cache.set(key, value);
54
- }
55
- /**
56
- * Checks if a value exists in the cache
57
- * @param key The cache key to check
58
- * @returns True if the value exists, false otherwise
59
- */
60
- has(key) {
61
- const hashedKey = this._getHashedKey(key);
62
- return this._cache.has(hashedKey);
63
- }
64
- /**
65
- * Retrieves all cached values
66
- * @returns A map of all cached values
67
- */
68
- getAll() {
69
- return this._cache;
70
- }
71
- /**
72
- * Clears the entire cache
73
- */
74
- clear() {
75
- this._cache.clear();
76
- }
77
- /**
78
- * Serializes the cache to a plain object.
79
- * @returns The serialized cache.
80
- */
81
- serialize() {
82
- return Array.from(this.getAll().entries()).reduce(
83
- (acc, [key, value]) => {
84
- acc[key] = value;
85
- return acc;
86
- },
87
- {}
88
- );
89
- }
90
- /**
91
- * Sets the cache from a serialized object.
92
- * @param serializedCache The serialized cache.
93
- */
94
- setFromSerialized(serializedCache) {
95
- for (const key in serializedCache) {
96
- this.restore(key, serializedCache[key]);
97
- }
98
- }
99
- };
100
-
101
8
  // src/Config/Config.ts
102
9
  var Config = class {
103
10
  /** The ignore paths */
@@ -106,6 +13,8 @@ var Config = class {
106
13
  _includePaths;
107
14
  /** Whether legacy template support is enabled */
108
15
  _legacyTemplates;
16
+ /** Whether the cache is enabled */
17
+ _cache;
109
18
  /**
110
19
  * Creates a new Config instance
111
20
  * @param options Configuration options
@@ -114,6 +23,7 @@ var Config = class {
114
23
  this._ignorePaths = options?.ignorePaths;
115
24
  this._includePaths = options?.includePaths;
116
25
  this._legacyTemplates = options?.legacyTemplates ?? true;
26
+ this._cache = options?.cache ?? true;
117
27
  }
118
28
  /**
119
29
  * The normalized configuration options
@@ -122,14 +32,38 @@ var Config = class {
122
32
  return {
123
33
  ignorePaths: this._ignorePaths,
124
34
  includePaths: this._includePaths,
35
+ legacyTemplates: this._legacyTemplates,
36
+ cache: this._cache
37
+ };
38
+ }
39
+ /**
40
+ * Normalized options for descriptors
41
+ */
42
+ get descriptorOptions() {
43
+ return {
44
+ ignorePaths: this._ignorePaths,
45
+ includePaths: this._includePaths,
46
+ cache: this._cache
47
+ };
48
+ }
49
+ /**
50
+ * Normalized options for element matchers
51
+ */
52
+ get matchersOptions() {
53
+ return {
125
54
  legacyTemplates: this._legacyTemplates
126
55
  };
127
56
  }
57
+ /**
58
+ * Whether caching is enabled
59
+ */
60
+ get cache() {
61
+ return this._cache;
62
+ }
128
63
  };
129
64
 
130
65
  // src/Matcher/BaseElementsMatcher.ts
131
66
  import Handlebars from "handlebars";
132
- import micromatch from "micromatch";
133
67
 
134
68
  // src/Support/TypeGuards.ts
135
69
  function isString(value) {
@@ -147,6 +81,9 @@ function isBoolean(value) {
147
81
  function isObject(value) {
148
82
  return !isNullish(value) && !isBoolean(value) && !isArray(value) && typeof value === "object";
149
83
  }
84
+ function isEmptyObject(obj) {
85
+ return isObject(obj) && Object.keys(obj).length === 0;
86
+ }
150
87
  function isArray(value) {
151
88
  return Array.isArray(value);
152
89
  }
@@ -199,8 +136,9 @@ function isElementSelectorData(value) {
199
136
  ]);
200
137
  }
201
138
  function isElementSelectorWithLegacyOptions(value) {
202
- 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.
203
- isCapturedValuesSelector(value[1]);
139
+ 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.
140
+ isCapturedValuesSelector(value[1]) || // NOTE: Backwards compatibility: Allow arrays of length 1 with simple element selector. Some users might defined arrays without options.
141
+ value.length === 1 && isSimpleElementSelectorByType(value[0]));
204
142
  }
205
143
  function isElementSelector(value) {
206
144
  return isSimpleElementSelectorByType(value) || isElementSelectorData(value) || isElementSelectorWithLegacyOptions(value);
@@ -231,6 +169,8 @@ function isExternalLibrariesSelector(value) {
231
169
  }
232
170
 
233
171
  // src/Matcher/BaseElementsMatcher.ts
172
+ var HANDLEBARS_TEMPLATE_REGEX = /{{\s*[^}]+\s*}}/;
173
+ var LEGACY_TEMPLATE_REGEX = /\$\{([^}]+)\}/g;
234
174
  function normalizeSelector(selector) {
235
175
  if (isSimpleElementSelectorByType(selector)) {
236
176
  return { type: selector };
@@ -241,7 +181,7 @@ function normalizeSelector(selector) {
241
181
  if (isElementSelectorWithLegacyOptions(selector)) {
242
182
  return {
243
183
  type: selector[0],
244
- captured: { ...selector[1] }
184
+ captured: selector[1] ? { ...selector[1] } : void 0
245
185
  };
246
186
  }
247
187
  throw new Error("Invalid element selector");
@@ -256,12 +196,21 @@ function normalizeElementsSelector(elementsSelector) {
256
196
  return [normalizeSelector(elementsSelector)];
257
197
  }
258
198
  var BaseElementsMatcher = class {
199
+ /**
200
+ * Option to use legacy templates with ${} syntax.
201
+ */
259
202
  _legacyTemplates;
203
+ /**
204
+ * Micromatch instance for matching.
205
+ */
206
+ micromatch;
260
207
  /**
261
208
  * Creates a new BaseElementsMatcher.
262
209
  * @param config Configuration options for the matcher.
210
+ * @param globalCache Global cache instance.
263
211
  */
264
- constructor(config) {
212
+ constructor(config, micromatch2) {
213
+ this.micromatch = micromatch2;
265
214
  this._legacyTemplates = config.legacyTemplates;
266
215
  }
267
216
  /**
@@ -270,17 +219,30 @@ var BaseElementsMatcher = class {
270
219
  * @returns The converted template.
271
220
  */
272
221
  _getBackwardsCompatibleTemplate(template) {
273
- return template.replaceAll(/\$\{([^}]+)\}/g, "{{ $1 }}");
222
+ return template.replaceAll(LEGACY_TEMPLATE_REGEX, "{{ $1 }}");
223
+ }
224
+ /**
225
+ * Determines if a template contains Handlebars syntax.
226
+ * @param template The template to check.
227
+ * @returns True if the template contains Handlebars syntax, false otherwise.
228
+ */
229
+ _isHandlebarsTemplate(template) {
230
+ return HANDLEBARS_TEMPLATE_REGEX.test(template);
274
231
  }
275
232
  /**
276
233
  * Returns a rendered template using the provided template data.
234
+ * Optimized version with template caching for better performance.
277
235
  * @param template The template to render.
278
- * @param extraTemplateData The data to use for replace in the template.
236
+ * @param templateData The data to use for replace in the template.
279
237
  * @returns The rendered template.
280
238
  */
281
239
  _getRenderedTemplate(template, templateData) {
282
240
  const templateToUse = this._legacyTemplates ? this._getBackwardsCompatibleTemplate(template) : template;
283
- return Handlebars.compile(templateToUse)(templateData);
241
+ if (!this._isHandlebarsTemplate(templateToUse)) {
242
+ return template;
243
+ }
244
+ const compiledTemplate = Handlebars.compile(templateToUse);
245
+ return compiledTemplate(templateData);
284
246
  }
285
247
  /**
286
248
  * Returns rendered templates using the provided template data.
@@ -298,6 +260,7 @@ var BaseElementsMatcher = class {
298
260
  }
299
261
  /**
300
262
  * Returns whether the given value matches the micromatch pattern, converting non-string values to strings.
263
+ * Optimized version with caching for better performance.
301
264
  * @param value The value to check.
302
265
  * @param pattern The micromatch pattern to match against.
303
266
  * @returns Whether the value matches the pattern.
@@ -305,7 +268,28 @@ var BaseElementsMatcher = class {
305
268
  isMicromatchMatch(value, pattern) {
306
269
  const elementValueToCheck = !value || !isString(value) ? String(value) : value;
307
270
  const selectorValueToCheck = isArray(pattern) ? pattern.filter(Boolean) : pattern;
308
- return micromatch.isMatch(elementValueToCheck, selectorValueToCheck);
271
+ return this.micromatch.isMatch(elementValueToCheck, selectorValueToCheck);
272
+ }
273
+ /**
274
+ * Returns whether the given value matches the micromatch pattern after rendering it as a template.
275
+ * @param pattern The micromatch pattern to render and match against.
276
+ * @param templateData The data to use for rendering the pattern as a template.
277
+ * @param value The value to check.
278
+ * @returns Whether the value matches the rendered pattern.
279
+ */
280
+ isTemplateMicromatchMatch(pattern, templateData, value) {
281
+ if (isNullish(value)) {
282
+ return false;
283
+ }
284
+ const patternRendered = this.getRenderedTemplates(pattern, templateData);
285
+ if (!patternRendered) {
286
+ return false;
287
+ }
288
+ const filteredPattern = isArray(patternRendered) ? patternRendered.filter(Boolean) : patternRendered;
289
+ if (isArray(value)) {
290
+ return value.some((val) => this.isMicromatchMatch(val, filteredPattern));
291
+ }
292
+ return this.isMicromatchMatch(value, filteredPattern);
309
293
  }
310
294
  /**
311
295
  * Whether the given element key matches the selector key as booleans.
@@ -352,61 +336,34 @@ var BaseElementsMatcher = class {
352
336
  if (!selectorValue) {
353
337
  return false;
354
338
  }
355
- const selectorValueRendered = this.getRenderedTemplates(
356
- selectorValue,
357
- templateData
358
- );
359
- if (!selectorValueRendered) {
360
- return false;
361
- }
362
339
  if (!isObjectWithProperty(element, elementKey)) {
363
340
  return false;
364
341
  }
365
- if (isNullish(element[elementKey])) {
366
- return false;
367
- }
368
- return this.isMicromatchMatch(element[elementKey], selectorValueRendered);
342
+ return this.isTemplateMicromatchMatch(
343
+ selectorValue,
344
+ templateData,
345
+ element[elementKey]
346
+ );
369
347
  }
370
348
  };
371
349
 
372
350
  // src/Matcher/DependenciesMatcher.ts
373
351
  var DependenciesMatcher = class extends BaseElementsMatcher {
374
- /**
375
- * Cache to store previously described dependencies.
376
- */
377
- _cache;
378
352
  /**
379
353
  * Elements matcher to use for matching elements within dependencies.
380
354
  */
381
355
  _elementsMatcher;
382
356
  /**
383
357
  * Creates a new DependenciesMatcher.
358
+ * @param elementsMatcher Elements matcher to use for matching elements within dependencies.
359
+ * @param config Configuration options for the matcher.
360
+ * @param micromatch Micromatch instance for matching.
361
+ * @param globalCache Global cache instance.
384
362
  */
385
- constructor(elementsMatcher, config) {
386
- super(config);
387
- this._cache = new CacheManager();
363
+ constructor(elementsMatcher, config, micromatch2) {
364
+ super(config, micromatch2);
388
365
  this._elementsMatcher = elementsMatcher;
389
366
  }
390
- /**
391
- * Serializes the cache to a plain object.
392
- * @returns The serialized cache.
393
- */
394
- serializeCache() {
395
- return this._cache.serialize();
396
- }
397
- /**
398
- * Sets the cache from a serialized object.
399
- * @param serializedCache The serialized cache.
400
- */
401
- setCacheFromSerialized(serializedCache) {
402
- this._cache.setFromSerialized(serializedCache);
403
- }
404
- /**
405
- * Clears the cache.
406
- */
407
- clearCache() {
408
- this._cache.clear();
409
- }
410
367
  /**
411
368
  * Normalizes selector into DependencySelectorNormalized format, containing arrays of selectors data.
412
369
  * @param selector The dependency selector to normalize.
@@ -544,17 +501,11 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
544
501
  if (!selector.relationship) {
545
502
  return true;
546
503
  }
547
- const renderedPattern = this.getRenderedTemplates(
504
+ return this.isTemplateMicromatchMatch(
548
505
  selector.relationship,
549
- templateData
506
+ templateData,
507
+ relationship
550
508
  );
551
- if (!renderedPattern) {
552
- return false;
553
- }
554
- if (!relationship) {
555
- return false;
556
- }
557
- return this.isMicromatchMatch(relationship, renderedPattern);
558
509
  }
559
510
  /**
560
511
  * Determines if the selector matches an specific kind
@@ -567,17 +518,7 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
567
518
  if (!selector.kind) {
568
519
  return true;
569
520
  }
570
- const renderedPattern = this.getRenderedTemplates(
571
- selector.kind,
572
- templateData
573
- );
574
- if (!renderedPattern) {
575
- return false;
576
- }
577
- if (!kind) {
578
- return false;
579
- }
580
- return this.isMicromatchMatch(kind, renderedPattern);
521
+ return this.isTemplateMicromatchMatch(selector.kind, templateData, kind);
581
522
  }
582
523
  /**
583
524
  * Determines if the selector matches some of the specifiers
@@ -587,22 +528,13 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
587
528
  * @returns Whether the selector matches some of the specifiers
588
529
  */
589
530
  _specifierMatches(selector, specifiers, templateData) {
590
- const specifierPattern = selector.specifiers;
591
- if (!specifierPattern) {
531
+ if (!selector.specifiers) {
592
532
  return true;
593
533
  }
594
- const renderedPattern = this.getRenderedTemplates(
595
- specifierPattern,
596
- templateData
597
- );
598
- if (!renderedPattern) {
599
- return false;
600
- }
601
- if (!specifiers) {
602
- return false;
603
- }
604
- return specifiers.some(
605
- (specifier) => this.isMicromatchMatch(specifier, renderedPattern)
534
+ return this.isTemplateMicromatchMatch(
535
+ selector.specifiers,
536
+ templateData,
537
+ specifiers
606
538
  );
607
539
  }
608
540
  /**
@@ -613,21 +545,14 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
613
545
  * @returns Whether the selector matches the nodeKind
614
546
  */
615
547
  _nodeKindMatches(selector, nodeKind, templateData) {
616
- const nodeKindPattern = selector.nodeKind;
617
- if (!nodeKindPattern) {
548
+ if (!selector.nodeKind) {
618
549
  return true;
619
550
  }
620
- const renderedPattern = this.getRenderedTemplates(
621
- nodeKindPattern,
622
- templateData
551
+ return this.isTemplateMicromatchMatch(
552
+ selector.nodeKind,
553
+ templateData,
554
+ nodeKind
623
555
  );
624
- if (!renderedPattern) {
625
- return false;
626
- }
627
- if (!nodeKind) {
628
- return false;
629
- }
630
- return this.isMicromatchMatch(nodeKind, renderedPattern);
631
556
  }
632
557
  /**
633
558
  * Determines if the dependency description matches the selector for 'from'.
@@ -653,25 +578,17 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
653
578
  * @returns Whether the dependency properties match the selector for 'to'.
654
579
  */
655
580
  _dependencyToPropertiesMatch(dependency, toSelector, templateData) {
656
- return toSelector.some((selectorData) => {
657
- return this._relationshipMatches(
658
- selectorData,
659
- dependency.dependency.relationship.to,
660
- templateData
661
- ) && this._kindMatches(
662
- selectorData,
663
- dependency.dependency.kind,
664
- templateData
665
- ) && this._nodeKindMatches(
666
- selectorData,
667
- dependency.dependency.nodeKind,
668
- templateData
669
- ) && this._specifierMatches(
670
- selectorData,
671
- dependency.dependency.specifiers,
672
- templateData
673
- );
674
- });
581
+ const dependencyInfo = dependency.dependency;
582
+ const relationshipTo = dependencyInfo.relationship.to;
583
+ const kind = dependencyInfo.kind;
584
+ const nodeKind = dependencyInfo.nodeKind;
585
+ const specifiers = dependencyInfo.specifiers;
586
+ for (const selectorData of toSelector) {
587
+ if (this._kindMatches(selectorData, kind, templateData) && this._nodeKindMatches(selectorData, nodeKind, templateData) && this._relationshipMatches(selectorData, relationshipTo, templateData) && this._specifierMatches(selectorData, specifiers, templateData)) {
588
+ return true;
589
+ }
590
+ }
591
+ return false;
675
592
  }
676
593
  /**
677
594
  * Returns the selectors matching result for the given dependency.
@@ -684,29 +601,18 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
684
601
  extraTemplateData = {},
685
602
  dependencySelectorsGlobals = {}
686
603
  } = {}) {
687
- if (this._cache.has({
688
- dependency,
689
- selector,
690
- extraTemplateData,
691
- dependencySelectorsGlobals
692
- })) {
693
- return this._cache.get({
694
- dependency,
695
- selector,
696
- extraTemplateData,
697
- dependencySelectorsGlobals
698
- });
699
- }
700
604
  const normalizedSelector = this._normalizeDependencySelector(
701
605
  selector,
702
606
  dependencySelectorsGlobals
703
607
  );
608
+ const fromExtraData = extraTemplateData.from || {};
609
+ const toExtraData = extraTemplateData.to || {};
704
610
  const templateData = {
705
611
  ...extraTemplateData,
706
612
  from: {
707
613
  ...dependency.from,
708
614
  relationship: dependency.dependency.relationship.from,
709
- ...extraTemplateData.from || {}
615
+ ...fromExtraData
710
616
  },
711
617
  to: {
712
618
  ...dependency.to,
@@ -714,7 +620,7 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
714
620
  kind: dependency.dependency.kind,
715
621
  nodeKind: dependency.dependency.nodeKind,
716
622
  specifiers: dependency.dependency.specifiers,
717
- ...extraTemplateData.to || {}
623
+ ...toExtraData
718
624
  }
719
625
  };
720
626
  const result = this._getSelectorMatching(
@@ -722,15 +628,6 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
722
628
  normalizedSelector,
723
629
  templateData
724
630
  );
725
- this._cache.set(
726
- {
727
- dependency,
728
- selector,
729
- extraTemplateData,
730
- dependencySelectorsGlobals
731
- },
732
- result
733
- );
734
631
  return result;
735
632
  }
736
633
  /**
@@ -751,38 +648,17 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
751
648
  };
752
649
 
753
650
  // src/Matcher/ElementsMatcher.ts
754
- import micromatch2 from "micromatch";
755
651
  var ElementsMatcher = class extends BaseElementsMatcher {
756
- /**
757
- * Cache to store previously described elements.
758
- */
759
- _cache;
652
+ /** Whether the cache is enabled or not */
653
+ _cacheIsEnabled;
760
654
  /**
761
655
  * Creates a new ElementsSelectorMatcher.
656
+ * @param config Configuration options for the matcher.
657
+ * @param micromatch Micromatch instance for matching.
658
+ * @param globalCache Global cache instance.
762
659
  */
763
- constructor(config) {
764
- super(config);
765
- this._cache = new CacheManager();
766
- }
767
- /**
768
- * Serializes the cache to a plain object.
769
- * @returns The serialized cache.
770
- */
771
- serializeCache() {
772
- return this._cache.serialize();
773
- }
774
- /**
775
- * Sets the cache from a serialized object.
776
- * @param serializedCache The serialized cache.
777
- */
778
- setCacheFromSerialized(serializedCache) {
779
- this._cache.setFromSerialized(serializedCache);
780
- }
781
- /**
782
- * Clears the cache.
783
- */
784
- clearCache() {
785
- this._cache.clear();
660
+ constructor(config, micromatch2) {
661
+ super(config, micromatch2);
786
662
  }
787
663
  /**
788
664
  * Whether the given element type matches the selector type.
@@ -928,13 +804,13 @@ var ElementsMatcher = class extends BaseElementsMatcher {
928
804
  * @returns True if the captured values match, false otherwise.
929
805
  */
930
806
  _isCapturedValuesMatch(element, selector, templateData) {
931
- if (!selector.captured) {
807
+ if (!selector.captured || isEmptyObject(selector.captured)) {
932
808
  return true;
933
809
  }
934
810
  if (!element.captured) {
935
811
  return false;
936
812
  }
937
- return Object.entries(selector.captured).every(([key, pattern]) => {
813
+ for (const [key, pattern] of Object.entries(selector.captured)) {
938
814
  const elementValue = element.captured?.[key];
939
815
  if (!elementValue) {
940
816
  return false;
@@ -944,8 +820,12 @@ var ElementsMatcher = class extends BaseElementsMatcher {
944
820
  return false;
945
821
  }
946
822
  const filteredPattern = isArray(renderedPattern) ? renderedPattern.filter(Boolean) : renderedPattern;
947
- return micromatch2.isMatch(elementValue, filteredPattern);
948
- });
823
+ const isMatch = this.micromatch.isMatch(elementValue, filteredPattern);
824
+ if (!isMatch) {
825
+ return false;
826
+ }
827
+ }
828
+ return true;
949
829
  }
950
830
  /**
951
831
  * Determines if the isIgnored property of the element matches that in the selector.
@@ -982,17 +862,16 @@ var ElementsMatcher = class extends BaseElementsMatcher {
982
862
  * @param extraTemplateData Extra template data to use for matching.
983
863
  * @returns The selector matching result for the given element, or null if none matches.
984
864
  */
985
- _getSelectorMatching(element, selector, extraTemplateData) {
986
- const selectorsData = normalizeElementsSelector(selector);
865
+ _getSelectorMatching(element, selectorsData, extraTemplateData) {
987
866
  const templateData = {
988
867
  element,
989
868
  ...extraTemplateData
990
869
  };
991
870
  for (const selectorData of selectorsData) {
992
- 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);
993
- if (isMatch) {
994
- return selectorData;
871
+ 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)) {
872
+ continue;
995
873
  }
874
+ return selectorData;
996
875
  }
997
876
  return null;
998
877
  }
@@ -1005,31 +884,8 @@ var ElementsMatcher = class extends BaseElementsMatcher {
1005
884
  * @returns The selector matching result for the given element, or null if none matches.
1006
885
  */
1007
886
  getSelectorMatching(element, selector, { extraTemplateData = {} } = {}) {
1008
- if (this._cache.has({
1009
- element,
1010
- selector,
1011
- extraTemplateData
1012
- })) {
1013
- return this._cache.get({
1014
- element,
1015
- selector,
1016
- extraTemplateData
1017
- });
1018
- }
1019
- const result = this._getSelectorMatching(
1020
- element,
1021
- selector,
1022
- extraTemplateData
1023
- );
1024
- this._cache.set(
1025
- {
1026
- element,
1027
- selector,
1028
- extraTemplateData
1029
- },
1030
- result
1031
- );
1032
- return result;
887
+ const selectorsData = normalizeElementsSelector(selector);
888
+ return this._getSelectorMatching(element, selectorsData, extraTemplateData);
1033
889
  }
1034
890
  /**
1035
891
  * Returns whether the given element matches the selector.
@@ -1179,22 +1035,173 @@ function isInternalDependency(dependency) {
1179
1035
  return dependency.dependency.relationship.to === DEPENDENCY_RELATIONSHIPS_MAP.INTERNAL;
1180
1036
  }
1181
1037
 
1038
+ // src/Cache/Cache.ts
1039
+ var CacheManager = class {
1040
+ /**
1041
+ * Internal cache map
1042
+ */
1043
+ _cache;
1044
+ /**
1045
+ * Creates a new CacheManager instance
1046
+ */
1047
+ constructor() {
1048
+ this._cache = /* @__PURE__ */ new Map();
1049
+ }
1050
+ /**
1051
+ * Generates a string key from the given cache key. Has to be implemented for non-string keys.
1052
+ * @param key The cache key to generate from
1053
+ * @returns The generated string key
1054
+ */
1055
+ generateKey(key) {
1056
+ if (isString(key)) {
1057
+ return key;
1058
+ }
1059
+ const errorMessage = "Cache key generation for non-string keys is not implemented because it causes performance issues: " + JSON.stringify(key);
1060
+ throw new Error(errorMessage);
1061
+ }
1062
+ /**
1063
+ * Generates a hashed key for the given cache key
1064
+ * @param key The cache key to hash
1065
+ * @returns The hashed key as a string
1066
+ */
1067
+ getKey(key) {
1068
+ return this.generateKey(key);
1069
+ }
1070
+ /**
1071
+ * Retrieves a value from the cache based on the given hashed key
1072
+ * @param hashedKey The hashed key to retrieve
1073
+ * @returns The cached value or undefined if not found
1074
+ */
1075
+ get(hashedKey) {
1076
+ return this._cache.get(hashedKey);
1077
+ }
1078
+ /**
1079
+ * Stores a value in the cache with a given hashed key
1080
+ * @param hashedKey The hashed key to store
1081
+ * @param value The value to cache
1082
+ */
1083
+ set(hashedKey, value) {
1084
+ this._cache.set(hashedKey, value);
1085
+ }
1086
+ /**
1087
+ * Checks if a value exists in the cache based on the given hashed key
1088
+ * @param hashedKey The hashed key to check
1089
+ * @returns True if the value exists, false otherwise
1090
+ */
1091
+ has(hashedKey) {
1092
+ return this._cache.has(hashedKey);
1093
+ }
1094
+ /**
1095
+ * Retrieves all cached values
1096
+ * @returns A map of all cached values
1097
+ */
1098
+ getAll() {
1099
+ return this._cache;
1100
+ }
1101
+ /**
1102
+ * Clears the entire cache
1103
+ */
1104
+ clear() {
1105
+ this._cache.clear();
1106
+ }
1107
+ /**
1108
+ * Serializes the cache to a plain object.
1109
+ * @returns The serialized cache.
1110
+ */
1111
+ serialize() {
1112
+ return Array.from(this.getAll().entries()).reduce(
1113
+ (acc, [key, value]) => {
1114
+ acc[key] = value;
1115
+ return acc;
1116
+ },
1117
+ {}
1118
+ );
1119
+ }
1120
+ /**
1121
+ * Sets the cache from a serialized object.
1122
+ * @param serializedCache The serialized cache.
1123
+ */
1124
+ setFromSerialized(serializedCache) {
1125
+ for (const key in serializedCache) {
1126
+ this.set(key, serializedCache[key]);
1127
+ }
1128
+ }
1129
+ };
1130
+
1131
+ // src/Cache/CacheDisabled.ts
1132
+ var CacheManagerDisabled = class extends CacheManager {
1133
+ /**
1134
+ * Generates a fake cache key as caching is disabled
1135
+ * @param key The cache key to hash
1136
+ * @returns An empty string
1137
+ */
1138
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1139
+ getKey(_key) {
1140
+ return "";
1141
+ }
1142
+ /**
1143
+ * Does nothing as caching is disabled
1144
+ * @param hashedKey The hashed key to retrieve
1145
+ * @returns Undefined as caching is disabled
1146
+ */
1147
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1148
+ get(_hashedKey) {
1149
+ return void 0;
1150
+ }
1151
+ /**
1152
+ * Does nothing as caching is disabled
1153
+ * @param hashedKey The hashed key to store
1154
+ * @param value The value to cache
1155
+ */
1156
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1157
+ set(_hashedKey, _value) {
1158
+ return;
1159
+ }
1160
+ /**
1161
+ * Does nothing as caching is disabled
1162
+ * @param hashedKey The hashed key to check
1163
+ * @returns False as caching is disabled
1164
+ */
1165
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
1166
+ has(_hashedKey) {
1167
+ return false;
1168
+ }
1169
+ };
1170
+
1171
+ // src/Descriptor/DependenciesDescriptionsCache.ts
1172
+ var DependenciesDescriptionsCache = class extends CacheManager {
1173
+ /** Generates a unique key for the given dependency description options.
1174
+ * @param options The options to generate the key from.
1175
+ * @returns The generated key.
1176
+ */
1177
+ generateKey(options) {
1178
+ return `${options.from}|${options.to}|${options.source}|${options.kind}|${options.nodeKind}|${options.specifiers ? options.specifiers.join(",") : ""}`;
1179
+ }
1180
+ };
1181
+
1182
1182
  // src/Descriptor/DependenciesDescriptor.ts
1183
1183
  var DependenciesDescriptor = class {
1184
1184
  /**
1185
1185
  * Cache to store previously described dependencies.
1186
1186
  */
1187
- _dependenciesCache = new CacheManager();
1187
+ _dependenciesCache;
1188
1188
  /**
1189
1189
  * Elements descriptor instance.
1190
1190
  */
1191
1191
  _elementsDescriptor;
1192
+ /**
1193
+ * Configuration options.
1194
+ */
1195
+ _config;
1192
1196
  /**
1193
1197
  * Creates a new DependenciesDescriptor instance.
1194
1198
  * @param elementsDescriptor The elements descriptor instance.
1199
+ * @param config The configuration options.
1195
1200
  */
1196
- constructor(elementsDescriptor) {
1201
+ constructor(elementsDescriptor, config) {
1197
1202
  this._elementsDescriptor = elementsDescriptor;
1203
+ this._config = config;
1204
+ this._dependenciesCache = this._config.cache ? new DependenciesDescriptionsCache() : new CacheManagerDisabled();
1198
1205
  }
1199
1206
  /**
1200
1207
  * Serializes the elements cache to a plain object.
@@ -1345,22 +1352,16 @@ var DependenciesDescriptor = class {
1345
1352
  nodeKind,
1346
1353
  specifiers
1347
1354
  }) {
1348
- if (this._dependenciesCache.has({
1355
+ const cacheKey = this._dependenciesCache.getKey({
1349
1356
  from,
1350
1357
  to,
1351
1358
  source,
1352
1359
  kind,
1353
1360
  nodeKind,
1354
1361
  specifiers
1355
- })) {
1356
- return this._dependenciesCache.get({
1357
- from,
1358
- to,
1359
- source,
1360
- kind,
1361
- nodeKind,
1362
- specifiers
1363
- });
1362
+ });
1363
+ if (this._dependenciesCache.has(cacheKey)) {
1364
+ return this._dependenciesCache.get(cacheKey);
1364
1365
  }
1365
1366
  const fromElement = this._elementsDescriptor.describeElement(from);
1366
1367
  const toElement = this._elementsDescriptor.describeDependencyElement(
@@ -1377,25 +1378,14 @@ var DependenciesDescriptor = class {
1377
1378
  specifiers: specifiers || null
1378
1379
  }
1379
1380
  };
1380
- this._dependenciesCache.set(
1381
- {
1382
- from,
1383
- to,
1384
- source,
1385
- kind,
1386
- nodeKind,
1387
- specifiers
1388
- },
1389
- result
1390
- );
1381
+ this._dependenciesCache.set(cacheKey, result);
1391
1382
  return result;
1392
1383
  }
1393
1384
  };
1394
1385
 
1395
1386
  // src/Descriptor/ElementsDescriptor.ts
1396
1387
  import isCoreModule from "is-core-module";
1397
- import micromatch3 from "micromatch";
1398
- var UNKNOWN_LOCAL_ELEMENT = {
1388
+ var UNKNOWN_ELEMENT = {
1399
1389
  path: null,
1400
1390
  elementPath: null,
1401
1391
  internalPath: null,
@@ -1409,16 +1399,18 @@ var UNKNOWN_LOCAL_ELEMENT = {
1409
1399
  isIgnored: false,
1410
1400
  isUnknown: true
1411
1401
  };
1402
+ var SCOPED_PACKAGE_REGEX = /^@[^/]*\/?[^/]+/;
1403
+ var EXTERNAL_PATH_REGEX = /^\w/;
1412
1404
  var ElementsDescriptor = class {
1413
1405
  _mod = null;
1414
1406
  /**
1415
1407
  * Cache to store previously described elements.
1416
1408
  */
1417
- _elementsCache = new CacheManager();
1409
+ _descriptionsCache;
1418
1410
  /**
1419
1411
  * Cache to store previously described files.
1420
1412
  */
1421
- _filesCache = new CacheManager();
1413
+ _filesCache;
1422
1414
  /**
1423
1415
  * Configuration instance for this descriptor.
1424
1416
  */
@@ -1427,15 +1419,22 @@ var ElementsDescriptor = class {
1427
1419
  * Element descriptors used by this descriptor.
1428
1420
  */
1429
1421
  _elementDescriptors;
1422
+ /** Micromatch instance for path matching */
1423
+ _micromatch;
1430
1424
  /**
1431
1425
  * The configuration options for this descriptor.
1432
1426
  * @param elementDescriptors The element descriptors.
1433
1427
  * @param configOptions The configuration options.
1428
+ * @param globalCache The global cache for various caching needs.
1429
+ * @param micromatch The micromatch instance for path matching.
1434
1430
  */
1435
- constructor(elementDescriptors, configOptions) {
1431
+ constructor(elementDescriptors, configOptions, micromatch2) {
1432
+ this._micromatch = micromatch2;
1436
1433
  this._elementDescriptors = elementDescriptors;
1437
1434
  this._validateDescriptors(elementDescriptors);
1438
- this._config = new Config(configOptions);
1435
+ this._config = configOptions;
1436
+ this._filesCache = this._config.cache ? new CacheManager() : new CacheManagerDisabled();
1437
+ this._descriptionsCache = this._config.cache ? new CacheManager() : new CacheManagerDisabled();
1439
1438
  this._loadModuleInNode();
1440
1439
  }
1441
1440
  /**
@@ -1443,20 +1442,24 @@ var ElementsDescriptor = class {
1443
1442
  * @returns The serialized elements cache.
1444
1443
  */
1445
1444
  serializeCache() {
1446
- return this._elementsCache.serialize();
1445
+ return {
1446
+ descriptions: this._descriptionsCache.serialize(),
1447
+ files: this._filesCache.serialize()
1448
+ };
1447
1449
  }
1448
1450
  /**
1449
1451
  * Sets the elements cache from a serialized object.
1450
1452
  * @param serializedCache The serialized elements cache.
1451
1453
  */
1452
1454
  setCacheFromSerialized(serializedCache) {
1453
- this._elementsCache.setFromSerialized(serializedCache);
1455
+ this._descriptionsCache.setFromSerialized(serializedCache.descriptions);
1456
+ this._filesCache.setFromSerialized(serializedCache.files);
1454
1457
  }
1455
1458
  /**
1456
1459
  * Clears the elements cache.
1457
1460
  */
1458
1461
  clearCache() {
1459
- this._elementsCache.clear();
1462
+ this._descriptionsCache.clear();
1460
1463
  this._filesCache.clear();
1461
1464
  }
1462
1465
  /**
@@ -1500,7 +1503,7 @@ var ElementsDescriptor = class {
1500
1503
  * @returns True if the dependency source is scoped, false otherwise.
1501
1504
  */
1502
1505
  _dependencySourceIsScoped(dependencySource) {
1503
- return /^@[^/]*\/?[^/]+/.test(dependencySource);
1506
+ return SCOPED_PACKAGE_REGEX.test(dependencySource);
1504
1507
  }
1505
1508
  /**
1506
1509
  * Determines if a dependency source is external or an alias.
@@ -1508,14 +1511,14 @@ var ElementsDescriptor = class {
1508
1511
  * @returns True if the dependency source is external or an alias, false otherwise.
1509
1512
  */
1510
1513
  _dependencySourceIsExternalOrScoped(dependencySource) {
1511
- return /^\w/.test(dependencySource) || this._dependencySourceIsScoped(dependencySource);
1514
+ return EXTERNAL_PATH_REGEX.test(dependencySource) || this._dependencySourceIsScoped(dependencySource);
1512
1515
  }
1513
1516
  /**
1514
1517
  * Gets the base source of an external module.
1515
1518
  * @param dependencySource The source of the dependency to check.
1516
1519
  * @returns The base source of the external module. (e.g., for "@scope/package/submodule", it returns "@scope/package")
1517
1520
  */
1518
- _getExternalModuleBaseSource(dependencySource) {
1521
+ _getExternalOrCoreModuleBaseSource(dependencySource) {
1519
1522
  if (this._dependencySourceIsScoped(dependencySource)) {
1520
1523
  const [scope, packageName] = dependencySource.split("/");
1521
1524
  return `${scope}/${packageName}`;
@@ -1538,27 +1541,31 @@ var ElementsDescriptor = class {
1538
1541
  }
1539
1542
  /**
1540
1543
  * Determines if a given path is included based on the configuration.
1544
+ * Uses caching for better performance on repeated calls.
1541
1545
  * @param elementPath The element path to check.
1546
+ * @param includeExternal Whether to include external files.
1542
1547
  * @returns True if the path is included, false otherwise.
1543
1548
  */
1544
- _pathIsIncluded(elementPath, includeExternal) {
1545
- const isExternal = includeExternal ? micromatch3.isMatch(elementPath, "**/node_modules/**") : false;
1546
- if (this._config.options.includePaths && this._config.options.ignorePaths) {
1547
- const isIncluded = micromatch3.isMatch(
1549
+ _pathIsIncluded(elementPath) {
1550
+ let result;
1551
+ if (this._config.includePaths && this._config.ignorePaths) {
1552
+ const isIncluded = this._micromatch.isMatch(
1548
1553
  elementPath,
1549
- this._config.options.includePaths
1554
+ this._config.includePaths
1550
1555
  );
1551
- const isIgnored = micromatch3.isMatch(
1556
+ const isIgnored = this._micromatch.isMatch(
1552
1557
  elementPath,
1553
- this._config.options.ignorePaths
1558
+ this._config.ignorePaths
1554
1559
  );
1555
- return (isIncluded || isExternal) && !isIgnored;
1556
- } else if (this._config.options.includePaths) {
1557
- return micromatch3.isMatch(elementPath, this._config.options.includePaths) || isExternal;
1558
- } else if (this._config.options.ignorePaths) {
1559
- return !micromatch3.isMatch(elementPath, this._config.options.ignorePaths);
1560
+ result = isIncluded && !isIgnored;
1561
+ } else if (this._config.includePaths) {
1562
+ result = this._micromatch.isMatch(elementPath, this._config.includePaths);
1563
+ } else if (this._config.ignorePaths) {
1564
+ result = !this._micromatch.isMatch(elementPath, this._config.ignorePaths);
1565
+ } else {
1566
+ result = true;
1560
1567
  }
1561
- return true;
1568
+ return result;
1562
1569
  }
1563
1570
  /**
1564
1571
  * Gets captured values from the captured array and capture configuration.
@@ -1585,16 +1592,15 @@ var ElementsDescriptor = class {
1585
1592
  * @returns The element path.
1586
1593
  */
1587
1594
  _getElementPath(pathPattern, pathSegments, allPathSegments) {
1588
- const elementPathRegexp = micromatch3.makeRe(pathPattern);
1595
+ const elementPathRegexp = this._micromatch.makeRe(pathPattern);
1589
1596
  const testedSegments = [];
1590
1597
  let result;
1591
1598
  for (const pathSegment of pathSegments) {
1592
- if (!result) {
1593
- testedSegments.push(pathSegment);
1594
- const joinedSegments = testedSegments.join("/");
1595
- if (elementPathRegexp.test(joinedSegments)) {
1596
- result = joinedSegments;
1597
- }
1599
+ testedSegments.push(pathSegment);
1600
+ const joinedSegments = testedSegments.join("/");
1601
+ if (elementPathRegexp.test(joinedSegments)) {
1602
+ result = joinedSegments;
1603
+ break;
1598
1604
  }
1599
1605
  }
1600
1606
  return `${[...allPathSegments].reverse().join("/").split(result)[0]}${result}`;
@@ -1611,20 +1617,18 @@ var ElementsDescriptor = class {
1611
1617
  for (const pattern of patterns) {
1612
1618
  const useFullPathMatch = mode === ELEMENT_DESCRIPTOR_MODES_MAP.FULL && !alreadyMatched;
1613
1619
  const effectivePattern = mode === ELEMENT_DESCRIPTOR_MODES_MAP.FOLDER && !alreadyMatched ? `${pattern}/**/*` : pattern;
1620
+ const targetPath = useFullPathMatch ? filePath : currentPathSegments.join("/");
1614
1621
  let baseCapture = null;
1615
1622
  let hasCapture = true;
1616
1623
  if (elementDescriptor.basePattern) {
1617
1624
  const baseTarget = filePath.split("/").slice(0, filePath.split("/").length - lastPathSegmentMatching).join("/");
1618
- baseCapture = micromatch3.capture(
1625
+ baseCapture = this._micromatch.capture(
1619
1626
  [elementDescriptor.basePattern, "**", effectivePattern].join("/"),
1620
1627
  baseTarget
1621
1628
  );
1622
1629
  hasCapture = baseCapture !== null;
1623
1630
  }
1624
- const capture = micromatch3.capture(
1625
- effectivePattern,
1626
- useFullPathMatch ? filePath : currentPathSegments.join("/")
1627
- );
1631
+ const capture = this._micromatch.capture(effectivePattern, targetPath);
1628
1632
  if (capture && hasCapture) {
1629
1633
  return {
1630
1634
  matched: true,
@@ -1638,22 +1642,19 @@ var ElementsDescriptor = class {
1638
1642
  return { matched: false };
1639
1643
  }
1640
1644
  /**
1641
- * Retrieves the description of an element given its path.
1642
- * It does not identify external files. Files not matching any element are considered unknown.
1643
- * If a file in node_modules does a match, it is considered local as well.
1644
- * @param includeExternal Whether to include external files (inside node_modules) in the matching process.
1645
+ * Retrieves the description of a local file given its path.
1645
1646
  * @param elementPath The path of the element to describe.
1646
1647
  * @returns The description of the element.
1647
1648
  */
1648
- _getFileDescription(includeExternal, filePath) {
1649
+ _getFileDescription(filePath) {
1649
1650
  if (!filePath) {
1650
1651
  return {
1651
- ...UNKNOWN_LOCAL_ELEMENT
1652
+ ...UNKNOWN_ELEMENT
1652
1653
  };
1653
1654
  }
1654
- if (!this._pathIsIncluded(filePath, includeExternal)) {
1655
+ if (!this._pathIsIncluded(filePath)) {
1655
1656
  return {
1656
- ...UNKNOWN_LOCAL_ELEMENT,
1657
+ ...UNKNOWN_ELEMENT,
1657
1658
  path: filePath,
1658
1659
  isIgnored: true,
1659
1660
  origin: null
@@ -1709,13 +1710,14 @@ var ElementsDescriptor = class {
1709
1710
  for (let i = 0; i < pathSegments.length; i++) {
1710
1711
  const segment = pathSegments[i];
1711
1712
  state.pathSegmentsAccumulator.unshift(segment);
1713
+ const alreadyHasMainElement = Boolean(elementResult.type) || Boolean(elementResult.category);
1712
1714
  for (const elementDescriptor of this._elementDescriptors) {
1713
1715
  const match = this._fileDescriptorMatch({
1714
1716
  elementDescriptor,
1715
1717
  filePath,
1716
1718
  currentPathSegments: state.pathSegmentsAccumulator,
1717
1719
  lastPathSegmentMatching: state.lastPathSegmentMatching,
1718
- alreadyMatched: Boolean(elementResult.type) || Boolean(elementResult.category)
1720
+ alreadyMatched: alreadyHasMainElement
1719
1721
  });
1720
1722
  if (match.matched) {
1721
1723
  processElementMatch(
@@ -1733,7 +1735,7 @@ var ElementsDescriptor = class {
1733
1735
  const result = { ...elementResult, parents };
1734
1736
  if (!isKnownLocalElement(result)) {
1735
1737
  return {
1736
- ...UNKNOWN_LOCAL_ELEMENT,
1738
+ ...UNKNOWN_ELEMENT,
1737
1739
  path: filePath
1738
1740
  };
1739
1741
  }
@@ -1745,35 +1747,30 @@ var ElementsDescriptor = class {
1745
1747
  * @param filePath The path of the file to describe.
1746
1748
  * @returns The description of the element.
1747
1749
  */
1748
- _describeFile(includeExternal, filePath) {
1749
- if (this._filesCache.has(String(filePath))) {
1750
- return this._filesCache.get(String(filePath));
1750
+ _describeFile(filePath) {
1751
+ const cacheKey = this._filesCache.getKey(String(filePath));
1752
+ if (this._filesCache.has(cacheKey)) {
1753
+ return this._filesCache.get(cacheKey);
1751
1754
  }
1752
- const description = this._getFileDescription(includeExternal, filePath);
1753
- this._filesCache.set(String(filePath), description);
1755
+ const description = this._getFileDescription(filePath);
1756
+ this._filesCache.set(cacheKey, description);
1754
1757
  return description;
1755
1758
  }
1756
1759
  /**
1757
- * Describes a dependency element given the file element and dependency source, by completing the file description.
1758
- * @param element The file element to complete the description for.
1760
+ * Returns an external or core dependency element given its dependency source and file path.
1759
1761
  * @param dependencySource The source of the dependency.
1760
- * @returns The description of the dependency element.
1762
+ * @param filePath The resolved file path of the dependency, if known.
1763
+ * @returns The external or core dependency element, or null if it is a local dependency.
1761
1764
  */
1762
- _describeDependencyElement(element, dependencySource) {
1763
- if (isIgnoredElement(element)) {
1764
- return {
1765
- ...element,
1766
- source: dependencySource
1767
- };
1768
- }
1769
- const baseDependencySource = this._getExternalModuleBaseSource(dependencySource);
1765
+ _getExternalOrCoreDependencyElement(dependencySource, filePath) {
1766
+ const baseDependencySource = this._getExternalOrCoreModuleBaseSource(dependencySource);
1770
1767
  const isCore = this._dependencySourceIsCoreModule(
1771
1768
  dependencySource,
1772
1769
  baseDependencySource
1773
1770
  );
1774
1771
  if (isCore) {
1775
1772
  const coreElement = {
1776
- ...element,
1773
+ ...UNKNOWN_ELEMENT,
1777
1774
  source: dependencySource,
1778
1775
  baseSource: baseDependencySource,
1779
1776
  origin: ELEMENT_ORIGINS_MAP.CORE
@@ -1781,44 +1778,38 @@ var ElementsDescriptor = class {
1781
1778
  return coreElement;
1782
1779
  }
1783
1780
  const isExternal = this._isExternalDependency(
1784
- element.path,
1781
+ filePath || null,
1785
1782
  dependencySource
1786
1783
  );
1787
- if (!isExternal) {
1788
- const localElement = {
1789
- ...element,
1790
- source: dependencySource
1784
+ if (isExternal) {
1785
+ const externalElement = {
1786
+ ...UNKNOWN_ELEMENT,
1787
+ path: filePath || null,
1788
+ internalPath: dependencySource.replace(baseDependencySource, ""),
1789
+ source: dependencySource,
1790
+ baseSource: baseDependencySource,
1791
+ origin: ELEMENT_ORIGINS_MAP.EXTERNAL
1791
1792
  };
1792
- return localElement;
1793
- }
1794
- const externalElement = {
1795
- ...element,
1796
- internalPath: dependencySource.replace(baseDependencySource, ""),
1797
- source: dependencySource,
1798
- baseSource: baseDependencySource,
1799
- origin: ELEMENT_ORIGINS_MAP.EXTERNAL
1800
- };
1801
- return externalElement;
1793
+ return externalElement;
1794
+ }
1795
+ return null;
1802
1796
  }
1803
1797
  _describeElement(filePath, dependencySource) {
1804
- if (this._elementsCache.has({
1805
- dependencySource,
1806
- filePath: String(filePath)
1807
- })) {
1808
- return this._elementsCache.get({
1809
- dependencySource,
1810
- filePath: String(filePath)
1811
- });
1812
- }
1813
- const fileDescription = this._describeFile(!!dependencySource, filePath);
1814
- const elementResult = dependencySource ? this._describeDependencyElement(fileDescription, dependencySource) : fileDescription;
1815
- this._elementsCache.set(
1816
- {
1817
- dependencySource,
1818
- filePath: String(filePath)
1819
- },
1820
- elementResult
1821
- );
1798
+ const cacheKey = `${String(dependencySource)}::${String(filePath)}`;
1799
+ if (this._descriptionsCache.has(cacheKey)) {
1800
+ return this._descriptionsCache.get(cacheKey);
1801
+ }
1802
+ const externalOrCoreDependencyElement = dependencySource ? this._getExternalOrCoreDependencyElement(dependencySource, filePath) : null;
1803
+ if (externalOrCoreDependencyElement) {
1804
+ this._descriptionsCache.set(cacheKey, externalOrCoreDependencyElement);
1805
+ return externalOrCoreDependencyElement;
1806
+ }
1807
+ const fileDescription = this._describeFile(filePath);
1808
+ const elementResult = dependencySource ? {
1809
+ ...fileDescription,
1810
+ source: dependencySource
1811
+ } : fileDescription;
1812
+ this._descriptionsCache.set(cacheKey, elementResult);
1822
1813
  return elementResult;
1823
1814
  }
1824
1815
  /**
@@ -1847,14 +1838,17 @@ var Descriptors = class {
1847
1838
  /** Creates a new DescriptorsManager instance
1848
1839
  * @param elementDescriptors The element descriptors.
1849
1840
  * @param configOptions The configuration options.
1841
+ * @param micromatch The Micromatch instance.
1850
1842
  */
1851
- constructor(elementDescriptors, configOptions) {
1843
+ constructor(elementDescriptors, config, micromatch2) {
1852
1844
  this._elementsDescriptor = new ElementsDescriptor(
1853
1845
  elementDescriptors,
1854
- configOptions
1846
+ config,
1847
+ micromatch2
1855
1848
  );
1856
1849
  this._dependenciesDescriptor = new DependenciesDescriptor(
1857
- this._elementsDescriptor
1850
+ this._elementsDescriptor,
1851
+ config
1858
1852
  );
1859
1853
  }
1860
1854
  /**
@@ -1922,15 +1916,15 @@ var Matcher = class {
1922
1916
  /**
1923
1917
  * Constructor for the Matcher class.
1924
1918
  * @param descriptors Element descriptors to use for matching.
1919
+ * @param elementsMatcher Elements matcher instance.
1920
+ * @param dependenciesMatcher Dependencies matcher instance.
1925
1921
  * @param config Configuration options.
1922
+ * @param globalCache Global cache instance.
1926
1923
  */
1927
- constructor(descriptors, config) {
1928
- this._descriptors = new Descriptors(descriptors, config);
1929
- this._elementsMatcher = new ElementsMatcher(config);
1930
- this._dependenciesMatcher = new DependenciesMatcher(
1931
- this._elementsMatcher,
1932
- config
1933
- );
1924
+ constructor(descriptors, elementsMatcher, dependenciesMatcher, config, micromatch2) {
1925
+ this._descriptors = new Descriptors(descriptors, config, micromatch2);
1926
+ this._elementsMatcher = elementsMatcher;
1927
+ this._dependenciesMatcher = dependenciesMatcher;
1934
1928
  }
1935
1929
  /**
1936
1930
  * Determines if an element matches a given selector.
@@ -1994,7 +1988,7 @@ var Matcher = class {
1994
1988
  * @param options Extra options for matching
1995
1989
  * @returns The matching dependency result or null if no match is found
1996
1990
  */
1997
- _isDependencySelectorMatching(dependencyData, selector, options) {
1991
+ _getDependencySelectorMatching(dependencyData, selector, options) {
1998
1992
  const description = this._descriptors.describeDependency(dependencyData);
1999
1993
  return this._dependenciesMatcher.getSelectorsMatching(
2000
1994
  description,
@@ -2010,7 +2004,7 @@ var Matcher = class {
2010
2004
  options
2011
2005
  );
2012
2006
  }
2013
- return this._isDependencySelectorMatching(
2007
+ return this._getDependencySelectorMatching(
2014
2008
  descriptorOptions,
2015
2009
  selector,
2016
2010
  options
@@ -2067,32 +2061,161 @@ var Matcher = class {
2067
2061
  */
2068
2062
  clearCache() {
2069
2063
  this._descriptors.clearCache();
2070
- this._elementsMatcher.clearCache();
2071
- this._dependenciesMatcher.clearCache();
2072
2064
  }
2073
2065
  /**
2074
- * Serializes the descriptors and elements matchers cache to a plain object.
2066
+ * Serializes the descriptors matchers cache to a plain object.
2075
2067
  * @returns The serialized cache
2076
2068
  */
2077
2069
  serializeCache() {
2078
2070
  return {
2079
- descriptors: this._descriptors.serializeCache(),
2080
- elementsMatcher: this._elementsMatcher.serializeCache(),
2081
- dependenciesMatcher: this._dependenciesMatcher.serializeCache()
2071
+ descriptors: this._descriptors.serializeCache()
2082
2072
  };
2083
2073
  }
2084
2074
  /**
2085
- * Sets the descriptors and elements matchers cache from a serialized object.
2075
+ * Sets the descriptors matchers cache from a serialized object.
2086
2076
  * @param serializedCache The serialized cache
2087
2077
  */
2088
2078
  setCacheFromSerialized(serializedCache) {
2089
2079
  this._descriptors.setCacheFromSerialized(serializedCache.descriptors);
2090
- this._elementsMatcher.setCacheFromSerialized(
2091
- serializedCache.elementsMatcher
2092
- );
2093
- this._dependenciesMatcher.setCacheFromSerialized(
2094
- serializedCache.dependenciesMatcher
2080
+ }
2081
+ };
2082
+
2083
+ // src/Matcher/Micromatch.ts
2084
+ import micromatch from "micromatch";
2085
+ var MatchingResultsCache = class extends CacheManager {
2086
+ /**
2087
+ * Generates a unique cache key based on the value and pattern
2088
+ * @param param0 The cache key components
2089
+ * @returns The generated cache key
2090
+ */
2091
+ generateKey({ value, pattern }) {
2092
+ return `${value}::${isArray(pattern) ? pattern.join("|") : pattern}`;
2093
+ }
2094
+ };
2095
+ var CapturedValueCache = class extends CacheManager {
2096
+ /**
2097
+ * Generates a unique cache key based on the pattern and target
2098
+ * @param param0 The cache key components
2099
+ * @returns The generated cache key
2100
+ */
2101
+ generateKey({ pattern, target }) {
2102
+ return `${pattern}|${target}`;
2103
+ }
2104
+ };
2105
+ var Micromatch = class {
2106
+ /**
2107
+ * Cache for micromatch matching results
2108
+ */
2109
+ _matchingResultsCache;
2110
+ /**
2111
+ * Cache for micromatch captures
2112
+ */
2113
+ _capturesCache = new CacheManagerDisabled();
2114
+ /**
2115
+ * Cache for micromatch makeRe results
2116
+ */
2117
+ _makeReCache = new CacheManagerDisabled();
2118
+ /**
2119
+ * Creates an instance of Micromatch class.
2120
+ * @param cache Whether to use caching or not.
2121
+ */
2122
+ constructor(cache) {
2123
+ this._matchingResultsCache = cache ? new MatchingResultsCache() : new CacheManagerDisabled();
2124
+ this._capturesCache = cache ? new CapturedValueCache() : new CacheManagerDisabled();
2125
+ this._makeReCache = cache ? new CacheManager() : new CacheManagerDisabled();
2126
+ }
2127
+ /**
2128
+ * Clears all caches.
2129
+ */
2130
+ clearCache() {
2131
+ this._matchingResultsCache.clear();
2132
+ this._capturesCache.clear();
2133
+ this._makeReCache.clear();
2134
+ }
2135
+ /**
2136
+ * Serializes the current cache state.
2137
+ * @returns The serialized cache data.
2138
+ */
2139
+ serializeCache() {
2140
+ return {
2141
+ matchingResults: this._matchingResultsCache.serialize(),
2142
+ captures: this._capturesCache.serialize()
2143
+ };
2144
+ }
2145
+ /**
2146
+ * Restores the cache state from serialized data.
2147
+ * @param serializedCache The serialized cache data.
2148
+ */
2149
+ setFromSerialized(serializedCache) {
2150
+ this._matchingResultsCache.setFromSerialized(
2151
+ serializedCache.matchingResults
2095
2152
  );
2153
+ this._capturesCache.setFromSerialized(serializedCache.captures);
2154
+ }
2155
+ /**
2156
+ * Optimized micromatch match with caching.
2157
+ * @param value The value to match.
2158
+ * @param pattern The pattern to match against.
2159
+ * @returns True if the value matches the pattern, false otherwise.
2160
+ */
2161
+ isMatch(value, pattern) {
2162
+ const cacheKey = this._matchingResultsCache.getKey({
2163
+ value,
2164
+ pattern
2165
+ });
2166
+ if (this._matchingResultsCache.has(cacheKey)) {
2167
+ return this._matchingResultsCache.get(cacheKey);
2168
+ }
2169
+ const isMatch = micromatch.isMatch(value, pattern);
2170
+ this._matchingResultsCache.set(cacheKey, isMatch);
2171
+ return isMatch;
2172
+ }
2173
+ /**
2174
+ * Optimized micromatch capture with caching.
2175
+ * @param pattern The pattern to match against.
2176
+ * @param target The target string to test.
2177
+ * @returns Captured groups or null if no match.
2178
+ */
2179
+ capture(pattern, target) {
2180
+ const cacheKey = this._capturesCache.getKey({ pattern, target });
2181
+ if (this._capturesCache.has(cacheKey)) {
2182
+ return this._capturesCache.get(cacheKey);
2183
+ }
2184
+ const result = micromatch.capture(pattern, target);
2185
+ this._capturesCache.set(cacheKey, result);
2186
+ return result;
2187
+ }
2188
+ /**
2189
+ * Optimized micromatch makeRe with caching.
2190
+ * @param pattern The pattern to convert to RegExp.
2191
+ * @returns The RegExp instance.
2192
+ */
2193
+ makeRe(pattern) {
2194
+ if (this._makeReCache.has(pattern)) {
2195
+ return this._makeReCache.get(pattern);
2196
+ }
2197
+ const regexp = micromatch.makeRe(pattern);
2198
+ this._makeReCache.set(pattern, regexp);
2199
+ return regexp;
2200
+ }
2201
+ };
2202
+
2203
+ // src/MatchersCache.ts
2204
+ var MatchersCache = class extends CacheManager {
2205
+ /**
2206
+ * Generates a unique key based on the configuration options and element descriptors
2207
+ * @param params The configuration and element descriptors
2208
+ * @returns A unique string key
2209
+ */
2210
+ generateKey({
2211
+ config,
2212
+ elementDescriptors
2213
+ }) {
2214
+ const configHash = `${config.legacyTemplates}|${config.includePaths}|${config.ignorePaths}|${config.cache}`;
2215
+ const elementDescriptorsHash = elementDescriptors.map(
2216
+ (descriptor) => `${descriptor.type}|${descriptor.category}|${descriptor.pattern}|${descriptor.basePattern}|${descriptor.mode}|${descriptor.capture}|${descriptor.baseCapture}`
2217
+ ).join(",");
2218
+ return `${configHash}|:|${elementDescriptorsHash}`;
2096
2219
  }
2097
2220
  };
2098
2221
 
@@ -2101,11 +2224,10 @@ var Elements = class {
2101
2224
  /** The global configuration options for Elements. Can be overridden when getting a descriptor */
2102
2225
  _globalConfigOptions;
2103
2226
  /** Cache manager for Matcher instances, unique for each different configuration */
2104
- _matchersCache = new CacheManager();
2105
- /** Matcher for element selectors */
2106
- _elementsMatcher;
2107
- /** Matcher for dependency selectors */
2108
- _dependenciesMatcher;
2227
+ _matchersCache = new MatchersCache();
2228
+ /** Micromatch instances for pattern matching */
2229
+ _micromatchWithCache = new Micromatch(true);
2230
+ _micromatchWithoutCache = new Micromatch(false);
2109
2231
  /**
2110
2232
  * Creates a new Elements instance
2111
2233
  * @param configOptions The global configuration options for Elements. Can be overridden when getting a descriptor.
@@ -2113,11 +2235,6 @@ var Elements = class {
2113
2235
  constructor(configOptions) {
2114
2236
  const globalConfig = new Config(configOptions);
2115
2237
  this._globalConfigOptions = globalConfig.options;
2116
- this._elementsMatcher = new ElementsMatcher(this._globalConfigOptions);
2117
- this._dependenciesMatcher = new DependenciesMatcher(
2118
- this._elementsMatcher,
2119
- this._globalConfigOptions
2120
- );
2121
2238
  }
2122
2239
  /**
2123
2240
  * Returns a serialized representation of the current state of the cache.
@@ -2127,20 +2244,20 @@ var Elements = class {
2127
2244
  const matchersCache = Array.from(
2128
2245
  this._matchersCache.getAll().entries()
2129
2246
  ).reduce(
2130
- (acc, [key, descriptorCache]) => {
2247
+ (acc, [key, cache]) => {
2131
2248
  acc[key] = {
2132
- config: descriptorCache.config,
2133
- elementDescriptors: descriptorCache.elementDescriptors,
2134
- cache: descriptorCache.matcher.serializeCache()
2249
+ config: cache.config,
2250
+ elementDescriptors: cache.elementDescriptors,
2251
+ cache: cache.matcher.serializeCache()
2135
2252
  };
2136
2253
  return acc;
2137
2254
  },
2138
2255
  {}
2139
2256
  );
2257
+ const micromatchCache = this._micromatchWithCache.serializeCache();
2140
2258
  return {
2141
2259
  matchers: matchersCache,
2142
- elementsMatcher: this._elementsMatcher.serializeCache(),
2143
- dependenciesMatcher: this._dependenciesMatcher.serializeCache()
2260
+ micromatch: micromatchCache
2144
2261
  };
2145
2262
  }
2146
2263
  /**
@@ -2148,54 +2265,70 @@ var Elements = class {
2148
2265
  * @param serializedCache The serialized cache to set.
2149
2266
  */
2150
2267
  setCacheFromSerialized(serializedCache) {
2268
+ this._micromatchWithCache.setFromSerialized(serializedCache.micromatch);
2151
2269
  for (const key in serializedCache.matchers) {
2152
2270
  const matcher = this.getMatcher(
2153
2271
  serializedCache.matchers[key].elementDescriptors,
2154
2272
  serializedCache.matchers[key].config
2155
2273
  );
2156
2274
  matcher.setCacheFromSerialized(serializedCache.matchers[key].cache);
2157
- this._matchersCache.restore(key, {
2275
+ this._matchersCache.set(key, {
2158
2276
  config: serializedCache.matchers[key].config,
2159
2277
  elementDescriptors: serializedCache.matchers[key].elementDescriptors,
2160
2278
  matcher
2161
2279
  });
2162
2280
  }
2163
- this._elementsMatcher.setCacheFromSerialized(
2164
- serializedCache.elementsMatcher
2165
- );
2166
- this._dependenciesMatcher.setCacheFromSerialized(
2167
- serializedCache.dependenciesMatcher
2168
- );
2169
2281
  }
2170
2282
  /**
2171
2283
  * Clears cache
2172
2284
  */
2173
2285
  clearCache() {
2174
- this._elementsMatcher.clearCache();
2175
- this._dependenciesMatcher.clearCache();
2176
2286
  for (const { matcher } of this._matchersCache.getAll().values()) {
2177
2287
  matcher.clearCache();
2178
2288
  }
2179
2289
  this._matchersCache.clear();
2290
+ this._micromatchWithCache.clearCache();
2180
2291
  }
2181
2292
  /**
2182
2293
  * Gets a Matcher instance for the given configuration options.
2183
2294
  * It uses caching to return the same instance for the same configuration options. If no options are provided, the global configuration options are used.
2184
2295
  * @param elementDescriptors The element descriptors to use.
2185
- * @param configOptions Optional configuration options to override the global ones.
2296
+ * @param config Optional configuration options to override the global ones.
2186
2297
  * @returns A matcher instance, unique for each different configuration.
2187
2298
  */
2188
- getMatcher(elementDescriptors, configOptions) {
2189
- const optionsToUse = configOptions || this._globalConfigOptions;
2299
+ getMatcher(elementDescriptors, config) {
2300
+ const optionsToUse = config || this._globalConfigOptions;
2190
2301
  const configInstance = new Config(optionsToUse);
2191
- const normalizedOptions = configInstance.options;
2192
- const cacheKey = { config: normalizedOptions, elementDescriptors };
2302
+ const cacheIsEnabled = configInstance.cache;
2303
+ const configOptionsNormalized = configInstance.options;
2304
+ const descriptorNormalizedOptions = configInstance.descriptorOptions;
2305
+ const matchersNormalizedOptions = configInstance.matchersOptions;
2306
+ const cacheKey = this._matchersCache.getKey({
2307
+ config: configOptionsNormalized,
2308
+ elementDescriptors
2309
+ });
2193
2310
  if (this._matchersCache.has(cacheKey)) {
2194
2311
  return this._matchersCache.get(cacheKey).matcher;
2195
2312
  }
2196
- const matcher = new Matcher(elementDescriptors, normalizedOptions);
2313
+ const micromatch2 = cacheIsEnabled ? this._micromatchWithCache : this._micromatchWithoutCache;
2314
+ const elementsMatcher = new ElementsMatcher(
2315
+ matchersNormalizedOptions,
2316
+ micromatch2
2317
+ );
2318
+ const dependenciesMatcher = new DependenciesMatcher(
2319
+ elementsMatcher,
2320
+ matchersNormalizedOptions,
2321
+ micromatch2
2322
+ );
2323
+ const matcher = new Matcher(
2324
+ elementDescriptors,
2325
+ elementsMatcher,
2326
+ dependenciesMatcher,
2327
+ descriptorNormalizedOptions,
2328
+ micromatch2
2329
+ );
2197
2330
  this._matchersCache.set(cacheKey, {
2198
- config: normalizedOptions,
2331
+ config: configOptionsNormalized,
2199
2332
  elementDescriptors,
2200
2333
  matcher
2201
2334
  });