@boundaries/elements 1.0.0 → 1.1.1

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