@boundaries/elements 1.0.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 ADDED
@@ -0,0 +1,2253 @@
1
+ var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
2
+ get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
3
+ }) : x)(function(x) {
4
+ if (typeof require !== "undefined") return require.apply(this, arguments);
5
+ throw Error('Dynamic require of "' + x + '" is not supported');
6
+ });
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
+ // src/Config/Config.ts
102
+ var Config = class {
103
+ /** The ignore paths */
104
+ _ignorePaths;
105
+ /** The include paths */
106
+ _includePaths;
107
+ /** Whether legacy template support is enabled */
108
+ _legacyTemplates;
109
+ /**
110
+ * Creates a new Config instance
111
+ * @param options Configuration options
112
+ */
113
+ constructor(options) {
114
+ this._ignorePaths = options?.ignorePaths;
115
+ this._includePaths = options?.includePaths;
116
+ this._legacyTemplates = options?.legacyTemplates ?? true;
117
+ }
118
+ /**
119
+ * The normalized configuration options
120
+ */
121
+ get options() {
122
+ return {
123
+ ignorePaths: this._ignorePaths,
124
+ includePaths: this._includePaths,
125
+ legacyTemplates: this._legacyTemplates
126
+ };
127
+ }
128
+ };
129
+
130
+ // src/Matcher/BaseElementsMatcher.ts
131
+ import Handlebars from "handlebars";
132
+ import micromatch from "micromatch";
133
+
134
+ // src/Support/TypeGuards.ts
135
+ function isString(value) {
136
+ return typeof value === "string";
137
+ }
138
+ function isNullish(value) {
139
+ return value === null || value === void 0;
140
+ }
141
+ function isNull(value) {
142
+ return value === null;
143
+ }
144
+ function isBoolean(value) {
145
+ return typeof value === "boolean";
146
+ }
147
+ function isObject(value) {
148
+ return !isNullish(value) && !isBoolean(value) && !isArray(value) && typeof value === "object";
149
+ }
150
+ function isArray(value) {
151
+ return Array.isArray(value);
152
+ }
153
+ function isEmptyArray(arr) {
154
+ return arr.length === 0;
155
+ }
156
+ function isStringArray(value) {
157
+ return isArray(value) && value.every(isString);
158
+ }
159
+ function isObjectWithProperty(value, key) {
160
+ return isObject(value) && Object.hasOwn(value, key);
161
+ }
162
+ function isObjectWithAnyOfProperties(value, keys) {
163
+ return isObject(value) && keys.some((key) => key in value);
164
+ }
165
+
166
+ // src/Matcher/MatcherHelpers.ts
167
+ function isCapturedValuesSelector(value) {
168
+ if (!isObject(value) || isArray(value)) {
169
+ return false;
170
+ }
171
+ return Object.values(value).every(
172
+ (pattern) => isString(pattern) || isStringArray(pattern)
173
+ );
174
+ }
175
+ function isSimpleElementSelectorByType(value) {
176
+ return isString(value);
177
+ }
178
+ function isBaseElementSelectorData(value) {
179
+ return isObjectWithAnyOfProperties(value, [
180
+ "path",
181
+ "elementPath",
182
+ "internalPath",
183
+ "type",
184
+ "category",
185
+ "captured",
186
+ "origin",
187
+ "source",
188
+ "baseSource",
189
+ "isIgnored",
190
+ "isUnknown"
191
+ ]);
192
+ }
193
+ function isElementSelectorData(value) {
194
+ return isBaseElementSelectorData(value) || isObjectWithAnyOfProperties(value, [
195
+ "relationship",
196
+ "kind",
197
+ "specifiers",
198
+ "nodeKind"
199
+ ]);
200
+ }
201
+ 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]);
204
+ }
205
+ function isElementSelector(value) {
206
+ return isSimpleElementSelectorByType(value) || isElementSelectorData(value) || isElementSelectorWithLegacyOptions(value);
207
+ }
208
+ function isElementsSelector(value) {
209
+ return isElementSelector(value) || isArray(value) && !isEmptyArray(value) && value.every(isElementSelector);
210
+ }
211
+ function isDependencySelector(value) {
212
+ return isObjectWithAnyOfProperties(value, ["from", "to"]);
213
+ }
214
+ function isExternalLibrarySelectorOptionsWithPath(value) {
215
+ return isObjectWithProperty(value, "path") && (isString(value.path) || isStringArray(value.path));
216
+ }
217
+ function isExternalLibrarySelectorOptionsWithSpecifiers(value) {
218
+ return isObjectWithProperty(value, "specifiers") && isStringArray(value.specifiers);
219
+ }
220
+ function isExternalLibrarySelectorOptions(value) {
221
+ return isExternalLibrarySelectorOptionsWithPath(value) || isExternalLibrarySelectorOptionsWithSpecifiers(value);
222
+ }
223
+ function isExternalLibrarySelectorWithOptions(value) {
224
+ return isArray(value) && value.length === 2 && isSimpleElementSelectorByType(value[0]) && isExternalLibrarySelectorOptions(value[1]);
225
+ }
226
+ function isExternalLibrarySelector(value) {
227
+ return isSimpleElementSelectorByType(value) || isExternalLibrarySelectorWithOptions(value);
228
+ }
229
+ function isExternalLibrariesSelector(value) {
230
+ return isExternalLibrarySelector(value) || isArray(value) && !isEmptyArray(value) && value.every(isExternalLibrarySelector);
231
+ }
232
+
233
+ // src/Matcher/BaseElementsMatcher.ts
234
+ function normalizeSelector(selector) {
235
+ if (isSimpleElementSelectorByType(selector)) {
236
+ return { type: selector };
237
+ }
238
+ if (isElementSelectorData(selector)) {
239
+ return { ...selector };
240
+ }
241
+ if (isElementSelectorWithLegacyOptions(selector)) {
242
+ return {
243
+ type: selector[0],
244
+ captured: { ...selector[1] }
245
+ };
246
+ }
247
+ throw new Error("Invalid element selector");
248
+ }
249
+ function normalizeElementsSelector(elementsSelector) {
250
+ if (isArray(elementsSelector)) {
251
+ if (isElementSelectorWithLegacyOptions(elementsSelector)) {
252
+ return [normalizeSelector(elementsSelector)];
253
+ }
254
+ return elementsSelector.map((sel) => normalizeSelector(sel));
255
+ }
256
+ return [normalizeSelector(elementsSelector)];
257
+ }
258
+ var BaseElementsMatcher = class {
259
+ _legacyTemplates;
260
+ /**
261
+ * Creates a new BaseElementsMatcher.
262
+ * @param config Configuration options for the matcher.
263
+ */
264
+ constructor(config) {
265
+ this._legacyTemplates = config.legacyTemplates;
266
+ }
267
+ /**
268
+ * Converts a template with ${} to Handlebars {{}} templates for backwards compatibility.
269
+ * @param template The template to convert.
270
+ * @returns The converted template.
271
+ */
272
+ _getBackwardsCompatibleTemplate(template) {
273
+ return template.replaceAll(/\$\{([^}]+)\}/g, "{{ $1 }}");
274
+ }
275
+ /**
276
+ * Returns a rendered template using the provided template data.
277
+ * @param template The template to render.
278
+ * @param extraTemplateData The data to use for replace in the template.
279
+ * @returns The rendered template.
280
+ */
281
+ _getRenderedTemplate(template, templateData) {
282
+ const templateToUse = this._legacyTemplates ? this._getBackwardsCompatibleTemplate(template) : template;
283
+ return Handlebars.compile(templateToUse)(templateData);
284
+ }
285
+ /**
286
+ * Returns rendered templates using the provided template data.
287
+ * @param template The templates to render.
288
+ * @param extraTemplateData The data to use for replace in the templates.
289
+ * @returns The rendered templates.
290
+ */
291
+ getRenderedTemplates(template, templateData) {
292
+ if (isArray(template)) {
293
+ return template.map((temp) => {
294
+ return this._getRenderedTemplate(temp, templateData);
295
+ });
296
+ }
297
+ return this._getRenderedTemplate(template, templateData);
298
+ }
299
+ /**
300
+ * Returns whether the given value matches the micromatch pattern, converting non-string values to strings.
301
+ * @param value The value to check.
302
+ * @param pattern The micromatch pattern to match against.
303
+ * @returns Whether the value matches the pattern.
304
+ */
305
+ isMicromatchMatch(value, pattern) {
306
+ const elementValueToCheck = !value || !isString(value) ? String(value) : value;
307
+ const selectorValueToCheck = isArray(pattern) ? pattern.filter(Boolean) : pattern;
308
+ return micromatch.isMatch(elementValueToCheck, selectorValueToCheck);
309
+ }
310
+ /**
311
+ * Whether the given element key matches the selector key as booleans.
312
+ * @param param0 The parameters object.
313
+ * @returns Whether the element key matches the selector key.
314
+ */
315
+ isElementKeyBooleanMatch({
316
+ /** The element to check. */
317
+ element,
318
+ /** The selector to check against. */
319
+ selector,
320
+ /** The key of the element to check. */
321
+ elementKey,
322
+ /** The key of the selector to check against. */
323
+ selectorKey
324
+ }) {
325
+ if (!(selectorKey in selector)) {
326
+ return true;
327
+ }
328
+ if (!(elementKey in element)) {
329
+ return false;
330
+ }
331
+ if (!isBoolean(selector[selectorKey]) || !isBoolean(element[elementKey])) {
332
+ return false;
333
+ }
334
+ return selector[selectorKey] === element[elementKey];
335
+ }
336
+ /**
337
+ * Whether the given element key matches the selector key using micromatch.
338
+ * @param param0 The parameters object.
339
+ * @returns Whether the element key matches the selector key.
340
+ */
341
+ isElementKeyMicromatchMatch({
342
+ element,
343
+ selector,
344
+ elementKey,
345
+ selectorKey,
346
+ selectorValue,
347
+ templateData
348
+ }) {
349
+ if (!(selectorKey in selector)) {
350
+ return true;
351
+ }
352
+ if (!selectorValue) {
353
+ return false;
354
+ }
355
+ const selectorValueRendered = this.getRenderedTemplates(
356
+ selectorValue,
357
+ templateData
358
+ );
359
+ if (!selectorValueRendered) {
360
+ return false;
361
+ }
362
+ if (!isObjectWithProperty(element, elementKey)) {
363
+ return false;
364
+ }
365
+ if (isNullish(element[elementKey])) {
366
+ return false;
367
+ }
368
+ return this.isMicromatchMatch(element[elementKey], selectorValueRendered);
369
+ }
370
+ };
371
+
372
+ // src/Matcher/DependenciesMatcher.ts
373
+ var DependenciesMatcher = class extends BaseElementsMatcher {
374
+ /**
375
+ * Cache to store previously described dependencies.
376
+ */
377
+ _cache;
378
+ /**
379
+ * Elements matcher to use for matching elements within dependencies.
380
+ */
381
+ _elementsMatcher;
382
+ /**
383
+ * Creates a new DependenciesMatcher.
384
+ */
385
+ constructor(elementsMatcher, config) {
386
+ super(config);
387
+ this._cache = new CacheManager();
388
+ this._elementsMatcher = elementsMatcher;
389
+ }
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
+ /**
411
+ * Normalizes selector into DependencySelectorNormalized format, containing arrays of selectors data.
412
+ * @param selector The dependency selector to normalize.
413
+ * @returns The normalized dependency selector.
414
+ */
415
+ _normalizeDependencySelector(selector, dependencySelectorsGlobals) {
416
+ if (!isDependencySelector(selector)) {
417
+ throw new Error("Invalid dependency selector");
418
+ }
419
+ let normalizedDependencySelectors = selector.to ? normalizeElementsSelector(selector.to) : null;
420
+ if (normalizedDependencySelectors) {
421
+ normalizedDependencySelectors = normalizedDependencySelectors.map(
422
+ (depSelector) => {
423
+ return {
424
+ ...dependencySelectorsGlobals,
425
+ ...depSelector
426
+ };
427
+ }
428
+ );
429
+ }
430
+ return {
431
+ from: selector.from ? normalizeElementsSelector(selector.from) : null,
432
+ to: normalizedDependencySelectors
433
+ };
434
+ }
435
+ /**
436
+ * Converts a DependencyElementSelectorData to a BaseElementSelectorData, by removing dependency-specific properties.
437
+ * @param selector The dependency element selector data.
438
+ * @returns The base element selector data.
439
+ */
440
+ _convertDependencyElementSelectorDataToBaseElementSelectorData(selector) {
441
+ const baseSelector = {};
442
+ if (selector.type) {
443
+ baseSelector.type = selector.type;
444
+ }
445
+ if (selector.category) {
446
+ baseSelector.category = selector.category;
447
+ }
448
+ if (selector.path) {
449
+ baseSelector.path = selector.path;
450
+ }
451
+ if (selector.elementPath) {
452
+ baseSelector.elementPath = selector.elementPath;
453
+ }
454
+ if (selector.internalPath) {
455
+ baseSelector.internalPath = selector.internalPath;
456
+ }
457
+ if (selector.captured) {
458
+ baseSelector.captured = selector.captured;
459
+ }
460
+ if (selector.origin) {
461
+ baseSelector.origin = selector.origin;
462
+ }
463
+ if (selector.baseSource) {
464
+ baseSelector.baseSource = selector.baseSource;
465
+ }
466
+ if (selector.source) {
467
+ baseSelector.source = selector.source;
468
+ }
469
+ if (!isNullish(selector.isIgnored)) {
470
+ baseSelector.isIgnored = selector.isIgnored;
471
+ }
472
+ if (!isNullish(selector.isUnknown)) {
473
+ baseSelector.isUnknown = selector.isUnknown;
474
+ }
475
+ return baseSelector;
476
+ }
477
+ /**
478
+ * Returns the selectors matching result for the given dependency.
479
+ * @param dependency The dependency description.
480
+ * @param selector The dependency selector normalized.
481
+ * @param extraTemplateData The extra template data for selector values.
482
+ * @returns The selectors matching result for the given dependency.
483
+ */
484
+ _getSelectorMatching(dependency, selector, templateData) {
485
+ const getFromSelectorMatching = () => {
486
+ for (const fromSelectorData of selector.from) {
487
+ const fromMatch = this._elementsMatcher.isElementMatch(
488
+ dependency.from,
489
+ fromSelectorData,
490
+ {
491
+ extraTemplateData: templateData
492
+ }
493
+ );
494
+ const dependencyPropertiesMatch = this._dependencyFromPropertiesMatch(
495
+ dependency,
496
+ [fromSelectorData],
497
+ templateData
498
+ );
499
+ if (fromMatch && dependencyPropertiesMatch) {
500
+ return fromSelectorData;
501
+ }
502
+ }
503
+ return null;
504
+ };
505
+ const getToSelectorMatching = () => {
506
+ for (const toSelectorData of selector.to) {
507
+ const toMatch = isBaseElementSelectorData(toSelectorData) ? this._elementsMatcher.isElementMatch(
508
+ dependency.to,
509
+ this._convertDependencyElementSelectorDataToBaseElementSelectorData(
510
+ toSelectorData
511
+ ),
512
+ {
513
+ extraTemplateData: templateData
514
+ }
515
+ ) : true;
516
+ const dependencyPropertiesMatch = this._dependencyToPropertiesMatch(
517
+ dependency,
518
+ [toSelectorData],
519
+ templateData
520
+ );
521
+ if (toMatch && dependencyPropertiesMatch) {
522
+ return toSelectorData;
523
+ }
524
+ }
525
+ return null;
526
+ };
527
+ const fromSelectorMatching = selector.from ? getFromSelectorMatching() : null;
528
+ const toSelectorMatching = selector.to ? getToSelectorMatching() : null;
529
+ return {
530
+ from: fromSelectorMatching,
531
+ to: toSelectorMatching,
532
+ isMatch: Boolean(
533
+ (selector.from ? fromSelectorMatching : true) && (selector.to ? toSelectorMatching : true)
534
+ )
535
+ };
536
+ }
537
+ /**
538
+ * Determines if the dependency relationship matches the selector.
539
+ * @param dependency The dependency description.
540
+ * @param selector The data of an element selector.
541
+ * @returns Whether the dependency relationship matches the selector.
542
+ */
543
+ _relationshipMatches(selector, relationship, templateData) {
544
+ if (!selector.relationship) {
545
+ return true;
546
+ }
547
+ const renderedPattern = this.getRenderedTemplates(
548
+ selector.relationship,
549
+ templateData
550
+ );
551
+ if (!renderedPattern) {
552
+ return false;
553
+ }
554
+ if (!relationship) {
555
+ return false;
556
+ }
557
+ return this.isMicromatchMatch(relationship, renderedPattern);
558
+ }
559
+ /**
560
+ * Determines if the selector matches an specific kind
561
+ * @param selector The dependency selector data
562
+ * @param kind Kind to check
563
+ * @param templateData The template data for rendering selector values
564
+ * @returns Whether the selector matches the kind
565
+ */
566
+ _kindMatches(selector, kind, templateData) {
567
+ if (!selector.kind) {
568
+ return true;
569
+ }
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);
581
+ }
582
+ /**
583
+ * Determines if the selector matches some of the specifiers
584
+ * @param selector The dependency selector data
585
+ * @param specifiers Specifiers to check
586
+ * @param templateData The template data for rendering selector values
587
+ * @returns Whether the selector matches some of the specifiers
588
+ */
589
+ _specifierMatches(selector, specifiers, templateData) {
590
+ const specifierPattern = selector.specifiers;
591
+ if (!specifierPattern) {
592
+ return true;
593
+ }
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)
606
+ );
607
+ }
608
+ /**
609
+ * Determines if the selector matches the nodeKind
610
+ * @param selector The dependency selector data
611
+ * @param nodeKind The nodeKind to check
612
+ * @param templateData The template data for rendering selector values
613
+ * @returns Whether the selector matches the nodeKind
614
+ */
615
+ _nodeKindMatches(selector, nodeKind, templateData) {
616
+ const nodeKindPattern = selector.nodeKind;
617
+ if (!nodeKindPattern) {
618
+ return true;
619
+ }
620
+ const renderedPattern = this.getRenderedTemplates(
621
+ nodeKindPattern,
622
+ templateData
623
+ );
624
+ if (!renderedPattern) {
625
+ return false;
626
+ }
627
+ if (!nodeKind) {
628
+ return false;
629
+ }
630
+ return this.isMicromatchMatch(nodeKind, renderedPattern);
631
+ }
632
+ /**
633
+ * Determines if the dependency description matches the selector for 'from'.
634
+ * @param dependency The dependency description.
635
+ * @param fromSelector The selector for 'from' elements.
636
+ * @param templateData The template data for rendering selector values
637
+ * @returns Whether the dependency properties match the selector for 'from'.
638
+ */
639
+ _dependencyFromPropertiesMatch(dependency, fromSelector, templateData) {
640
+ return fromSelector.some(
641
+ (selectorData) => this._relationshipMatches(
642
+ selectorData,
643
+ dependency.dependency.relationship.from,
644
+ templateData
645
+ )
646
+ );
647
+ }
648
+ /**
649
+ * Determines if the dependency description matches the selector for 'to'.
650
+ * @param dependency The dependency description.
651
+ * @param toSelector The selector for 'to' elements.
652
+ * @param templateData The template data for rendering selector values
653
+ * @returns Whether the dependency properties match the selector for 'to'.
654
+ */
655
+ _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
+ });
675
+ }
676
+ /**
677
+ * Returns the selectors matching result for the given dependency.
678
+ * @param dependency The dependency to check.
679
+ * @param selector The selector to check against.
680
+ * @param options Extra options for matching, such as templates data, globals for dependency selectors, etc.
681
+ * @returns The matching result for the dependency against the selector.
682
+ */
683
+ getSelectorsMatching(dependency, selector, {
684
+ extraTemplateData = {},
685
+ dependencySelectorsGlobals = {}
686
+ } = {}) {
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
+ const normalizedSelector = this._normalizeDependencySelector(
701
+ selector,
702
+ dependencySelectorsGlobals
703
+ );
704
+ const templateData = {
705
+ ...extraTemplateData,
706
+ from: {
707
+ ...dependency.from,
708
+ relationship: dependency.dependency.relationship.from,
709
+ ...extraTemplateData.from || {}
710
+ },
711
+ to: {
712
+ ...dependency.to,
713
+ relationship: dependency.dependency.relationship.to,
714
+ kind: dependency.dependency.kind,
715
+ nodeKind: dependency.dependency.nodeKind,
716
+ specifiers: dependency.dependency.specifiers,
717
+ ...extraTemplateData.to || {}
718
+ }
719
+ };
720
+ const result = this._getSelectorMatching(
721
+ dependency,
722
+ normalizedSelector,
723
+ templateData
724
+ );
725
+ this._cache.set(
726
+ {
727
+ dependency,
728
+ selector,
729
+ extraTemplateData,
730
+ dependencySelectorsGlobals
731
+ },
732
+ result
733
+ );
734
+ return result;
735
+ }
736
+ /**
737
+ * Returns whether the given dependency matches the selector.
738
+ * @param dependency The dependency to check.
739
+ * @param selector The selector to check against.
740
+ * @param options Extra options for matching, such as templates data, globals for dependency selectors, etc.
741
+ * @returns Whether the dependency matches the selector properties.
742
+ */
743
+ isDependencyMatch(dependency, selector, options) {
744
+ const matchResult = this.getSelectorsMatching(
745
+ dependency,
746
+ selector,
747
+ options
748
+ );
749
+ return matchResult.isMatch;
750
+ }
751
+ };
752
+
753
+ // src/Matcher/ElementsMatcher.ts
754
+ import micromatch2 from "micromatch";
755
+ var ElementsMatcher = class extends BaseElementsMatcher {
756
+ /**
757
+ * Cache to store previously described elements.
758
+ */
759
+ _cache;
760
+ /**
761
+ * Creates a new ElementsSelectorMatcher.
762
+ */
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();
786
+ }
787
+ /**
788
+ * Whether the given element type matches the selector type.
789
+ * @param element The element to check.
790
+ * @param selector The selector to check against.
791
+ * @param templateData The data to use for replace in selector value
792
+ * @returns Whether the element type matches the selector type.
793
+ */
794
+ _isTypeMatch(element, selector, templateData) {
795
+ return this.isElementKeyMicromatchMatch({
796
+ element,
797
+ selector,
798
+ elementKey: "type",
799
+ selectorKey: "type",
800
+ selectorValue: selector.type,
801
+ templateData
802
+ });
803
+ }
804
+ /**
805
+ * Whether the given element category matches the selector category.
806
+ * @param element The element to check.
807
+ * @param selector The selector to check against.
808
+ * @param templateData The data to use for replace in selector value
809
+ * @returns Whether the element category matches the selector category.
810
+ */
811
+ _isCategoryMatch(element, selector, templateData) {
812
+ return this.isElementKeyMicromatchMatch({
813
+ element,
814
+ selector,
815
+ elementKey: "category",
816
+ selectorKey: "category",
817
+ selectorValue: selector.category,
818
+ templateData
819
+ });
820
+ }
821
+ /**
822
+ * Whether the given element path matches the selector path.
823
+ * @param element The element to check.
824
+ * @param selector The selector to check against.
825
+ * @param templateData The data to use for replace in selector value
826
+ * @returns Whether the element path matches the selector path.
827
+ */
828
+ _isPathMatch(element, selector, templateData) {
829
+ return this.isElementKeyMicromatchMatch({
830
+ element,
831
+ selector,
832
+ elementKey: "path",
833
+ selectorKey: "path",
834
+ selectorValue: selector.path,
835
+ templateData
836
+ });
837
+ }
838
+ /**
839
+ * Whether the given element path matches the selector element path.
840
+ * @param element The element to check.
841
+ * @param selector The selector to check against.
842
+ * @param templateData The data to use for replace in selector value
843
+ * @returns Whether the element path matches the selector element path.
844
+ */
845
+ _isElementPathMatch(element, selector, templateData) {
846
+ return this.isElementKeyMicromatchMatch({
847
+ element,
848
+ selector,
849
+ elementKey: "elementPath",
850
+ selectorKey: "elementPath",
851
+ selectorValue: selector.elementPath,
852
+ templateData
853
+ });
854
+ }
855
+ /**
856
+ * Whether the given element internal path matches the selector internal path.
857
+ * @param element The element to check.
858
+ * @param selector The selector to check against.
859
+ * @param templateData The data to use for replace in selector value
860
+ * @returns Whether the element internal path matches the selector internal path.
861
+ */
862
+ _isInternalPathMatch(element, selector, templateData) {
863
+ return this.isElementKeyMicromatchMatch({
864
+ element,
865
+ selector,
866
+ elementKey: "internalPath",
867
+ selectorKey: "internalPath",
868
+ selectorValue: selector.internalPath,
869
+ templateData
870
+ });
871
+ }
872
+ /**
873
+ * Whether the given element origin matches the selector origin
874
+ * @param element The element to check.
875
+ * @param selector The selector to check against.
876
+ * @param templateData The data to use for replace in selector value
877
+ * @returns Whether the element origin matches the selector origin.
878
+ */
879
+ _isOriginMatch(element, selector, templateData) {
880
+ return this.isElementKeyMicromatchMatch({
881
+ element,
882
+ selector,
883
+ elementKey: "origin",
884
+ selectorKey: "origin",
885
+ selectorValue: selector.origin,
886
+ templateData
887
+ });
888
+ }
889
+ /**
890
+ * Whether the given element baseSource matches the selector baseSource
891
+ * @param element The element to check.
892
+ * @param selector The selector to check against.
893
+ * @param templateData The data to use for replace in selector value
894
+ * @returns Whether the element baseSource matches the selector baseSource.
895
+ */
896
+ _isBaseSourceMatch(element, selector, templateData) {
897
+ return this.isElementKeyMicromatchMatch({
898
+ element,
899
+ selector,
900
+ elementKey: "baseSource",
901
+ selectorKey: "baseSource",
902
+ selectorValue: selector.baseSource,
903
+ templateData
904
+ });
905
+ }
906
+ /**
907
+ * Whether the given element source matches the selector source
908
+ * @param element The element to check.
909
+ * @param selector The selector to check against.
910
+ * @param templateData The data to use for replace in selector value
911
+ * @returns Whether the element source matches the selector source.
912
+ */
913
+ _isSourceMatch(element, selector, templateData) {
914
+ return this.isElementKeyMicromatchMatch({
915
+ element,
916
+ selector,
917
+ elementKey: "source",
918
+ selectorKey: "source",
919
+ selectorValue: selector.source,
920
+ templateData
921
+ });
922
+ }
923
+ /**
924
+ * Determines if the captured values of the element match those in the selector.
925
+ * @param element The element to check.
926
+ * @param selector The selector to check against
927
+ * @param templateData The data to use for replace in selector values
928
+ * @returns True if the captured values match, false otherwise.
929
+ */
930
+ _isCapturedValuesMatch(element, selector, templateData) {
931
+ if (!selector.captured) {
932
+ return true;
933
+ }
934
+ if (!element.captured) {
935
+ return false;
936
+ }
937
+ return Object.entries(selector.captured).every(([key, pattern]) => {
938
+ const elementValue = element.captured?.[key];
939
+ if (!elementValue) {
940
+ return false;
941
+ }
942
+ const renderedPattern = this.getRenderedTemplates(pattern, templateData);
943
+ if (!renderedPattern) {
944
+ return false;
945
+ }
946
+ const filteredPattern = isArray(renderedPattern) ? renderedPattern.filter(Boolean) : renderedPattern;
947
+ return micromatch2.isMatch(elementValue, filteredPattern);
948
+ });
949
+ }
950
+ /**
951
+ * Determines if the isIgnored property of the element matches that in the selector.
952
+ * @param element The element to check.
953
+ * @param selector The selector to check against.
954
+ * @returns True if the isIgnored properties match, false otherwise.
955
+ */
956
+ _isIgnoredMatch(element, selector) {
957
+ return this.isElementKeyBooleanMatch({
958
+ element,
959
+ selector,
960
+ elementKey: "isIgnored",
961
+ selectorKey: "isIgnored"
962
+ });
963
+ }
964
+ /**
965
+ * Determines if the isUnknown property of the element matches that in the selector.
966
+ * @param element The element to check.
967
+ * @param selector The selector to check against.
968
+ * @returns True if the isUnknown properties match, false otherwise.
969
+ */
970
+ _isUnknownMatch(element, selector) {
971
+ return this.isElementKeyBooleanMatch({
972
+ element,
973
+ selector,
974
+ elementKey: "isUnknown",
975
+ selectorKey: "isUnknown"
976
+ });
977
+ }
978
+ /**
979
+ * Returns the selector matching result for the given local or external element.
980
+ * @param element The local or external element to check.
981
+ * @param selector The selector to check against.
982
+ * @param extraTemplateData Extra template data to use for matching.
983
+ * @returns The selector matching result for the given element, or null if none matches.
984
+ */
985
+ _getSelectorMatching(element, selector, extraTemplateData) {
986
+ const selectorsData = normalizeElementsSelector(selector);
987
+ const templateData = {
988
+ element,
989
+ ...extraTemplateData
990
+ };
991
+ 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;
995
+ }
996
+ }
997
+ return null;
998
+ }
999
+ /**
1000
+ * Returns the selector matching result for the given element, or null if none matches.
1001
+ * It omits checks in keys applying only to dependency between elements, such as relationship.
1002
+ * @param element The element to check.
1003
+ * @param selector The selector to check against.
1004
+ * @param options Extra options for matching, such as templates data, globals for dependency selectors, etc.
1005
+ * @returns The selector matching result for the given element, or null if none matches.
1006
+ */
1007
+ 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;
1033
+ }
1034
+ /**
1035
+ * Returns whether the given element matches the selector.
1036
+ * It omits checks in keys applying only to dependency between elements, such as relationship.
1037
+ * @param element The element to check.
1038
+ * @param selector The selector to check against.
1039
+ * @param options Extra options for matching, such as templates data, globals for dependency selectors, etc.
1040
+ * @returns Whether the element matches the selector properties applying to elements.
1041
+ */
1042
+ isElementMatch(element, selector, options) {
1043
+ const selectorMatching = this.getSelectorMatching(
1044
+ element,
1045
+ selector,
1046
+ options
1047
+ );
1048
+ return !isNullish(selectorMatching);
1049
+ }
1050
+ };
1051
+
1052
+ // src/Descriptor/ElementsDescriptor.types.ts
1053
+ var ELEMENT_DESCRIPTOR_MODES_MAP = {
1054
+ /** Mode to interpret the pattern as a folder */
1055
+ FOLDER: "folder",
1056
+ /** Mode to interpret the pattern as a file */
1057
+ FILE: "file",
1058
+ /** Mode to interpret the pattern as a full path */
1059
+ FULL: "full"
1060
+ };
1061
+ var ELEMENT_ORIGINS_MAP = {
1062
+ /** Origin of local elements (files) */
1063
+ LOCAL: "local",
1064
+ /** Origin of external elements (libraries) */
1065
+ EXTERNAL: "external",
1066
+ /** Origin of core elements */
1067
+ CORE: "core"
1068
+ };
1069
+
1070
+ // src/Descriptor/ElementsDescriptorHelpers.ts
1071
+ function isElementDescriptorMode(value) {
1072
+ return isString(value) && Object.values(ELEMENT_DESCRIPTOR_MODES_MAP).includes(
1073
+ value
1074
+ );
1075
+ }
1076
+ function isElementDescriptorPattern(value) {
1077
+ return isString(value) || isArray(value) && !isEmptyArray(value) && value.every(isString);
1078
+ }
1079
+ function isBaseElementDescriptor(value) {
1080
+ return isObjectWithProperty(value, "pattern") && isElementDescriptorPattern(value.pattern);
1081
+ }
1082
+ function isElementDescriptorWithType(value) {
1083
+ return isBaseElementDescriptor(value) && isObjectWithProperty(value, "type") && isString(value.type);
1084
+ }
1085
+ function isElementDescriptorWithCategory(value) {
1086
+ return isBaseElementDescriptor(value) && isObjectWithProperty(value, "category") && isString(value.category);
1087
+ }
1088
+ function isElementDescriptor(value) {
1089
+ return isElementDescriptorWithType(value) || isElementDescriptorWithCategory(value);
1090
+ }
1091
+ function isBaseElement(value) {
1092
+ return isObjectWithProperty(value, "type") && isObjectWithProperty(value, "category") && isObjectWithProperty(value, "path") && isObjectWithProperty(value, "captured") && isObjectWithProperty(value, "origin") && isObjectWithProperty(value, "isIgnored") && isObjectWithProperty(value, "isUnknown");
1093
+ }
1094
+ function isIgnoredElement(value) {
1095
+ return isBaseElement(value) && isObjectWithProperty(value, "isIgnored") && value.isIgnored === true;
1096
+ }
1097
+ function isLocalElement(value) {
1098
+ return isBaseElement(value) && value.origin === ELEMENT_ORIGINS_MAP.LOCAL;
1099
+ }
1100
+ function isUnknownLocalElement(value) {
1101
+ return isLocalElement(value) && value.isUnknown === true;
1102
+ }
1103
+ function isKnownLocalElement(value) {
1104
+ return isLocalElement(value) && value.isUnknown === false;
1105
+ }
1106
+ function isDependencyElementDescription(value) {
1107
+ return isBaseElement(value) && isObjectWithProperty(value, "source") && isString(value.source);
1108
+ }
1109
+ function isElementDescription(value) {
1110
+ return isIgnoredElement(value) || isUnknownLocalElement(value) || isKnownLocalElement(value) || isDependencyElementDescription(value);
1111
+ }
1112
+ function isLocalDependencyElement(value) {
1113
+ return isDependencyElementDescription(value) && isLocalElement(value);
1114
+ }
1115
+ function isExternalDependencyElement(value) {
1116
+ return isDependencyElementDescription(value) && value.origin === ELEMENT_ORIGINS_MAP.EXTERNAL && isObjectWithProperty(value, "baseSource") && isString(value.baseSource);
1117
+ }
1118
+ function isCoreDependencyElement(value) {
1119
+ return isDependencyElementDescription(value) && value.origin === ELEMENT_ORIGINS_MAP.CORE && isObjectWithProperty(value, "baseSource") && isString(value.baseSource);
1120
+ }
1121
+
1122
+ // src/Descriptor/DependenciesDescriptor.types.ts
1123
+ var DEPENDENCY_KIND_TYPE = "type";
1124
+ var DEPENDENCY_KIND_VALUE = "value";
1125
+ var DEPENDENCY_KINDS_MAP = {
1126
+ /** Type import, e.g., `import type { X } from 'module'` */
1127
+ TYPE: DEPENDENCY_KIND_TYPE,
1128
+ /** Value import, e.g., `import { X } from 'module'` */
1129
+ VALUE: DEPENDENCY_KIND_VALUE
1130
+ };
1131
+ var DEPENDENCY_RELATIONSHIPS_MAP = {
1132
+ /** The dependency is internal to the element */
1133
+ INTERNAL: "internal",
1134
+ /** The dependency is a child of the element */
1135
+ CHILD: "child",
1136
+ /** The dependency is a descendant of the element */
1137
+ DESCENDANT: "descendant",
1138
+ /** The dependency is a sibling of the element (both have the same parent) */
1139
+ SIBLING: "sibling",
1140
+ /** The dependency is a parent of the element */
1141
+ PARENT: "parent",
1142
+ /** The dependency is an uncle of the element */
1143
+ UNCLE: "uncle",
1144
+ /** The dependency is a nephew of the element */
1145
+ NEPHEW: "nephew",
1146
+ /** The dependency is an ancestor of the element */
1147
+ ANCESTOR: "ancestor"
1148
+ };
1149
+ var DEPENDENCY_RELATIONSHIPS_INVERTED_MAP = {
1150
+ [DEPENDENCY_RELATIONSHIPS_MAP.INTERNAL]: DEPENDENCY_RELATIONSHIPS_MAP.INTERNAL,
1151
+ [DEPENDENCY_RELATIONSHIPS_MAP.CHILD]: DEPENDENCY_RELATIONSHIPS_MAP.PARENT,
1152
+ [DEPENDENCY_RELATIONSHIPS_MAP.DESCENDANT]: DEPENDENCY_RELATIONSHIPS_MAP.ANCESTOR,
1153
+ [DEPENDENCY_RELATIONSHIPS_MAP.SIBLING]: DEPENDENCY_RELATIONSHIPS_MAP.SIBLING,
1154
+ [DEPENDENCY_RELATIONSHIPS_MAP.PARENT]: DEPENDENCY_RELATIONSHIPS_MAP.CHILD,
1155
+ [DEPENDENCY_RELATIONSHIPS_MAP.UNCLE]: DEPENDENCY_RELATIONSHIPS_MAP.NEPHEW,
1156
+ [DEPENDENCY_RELATIONSHIPS_MAP.NEPHEW]: DEPENDENCY_RELATIONSHIPS_MAP.UNCLE,
1157
+ [DEPENDENCY_RELATIONSHIPS_MAP.ANCESTOR]: DEPENDENCY_RELATIONSHIPS_MAP.DESCENDANT
1158
+ };
1159
+
1160
+ // src/Descriptor/DependenciesDescriptorHelpers.ts
1161
+ function isDependencyKind(value) {
1162
+ return isString(value) && Object.values(DEPENDENCY_KINDS_MAP).includes(value);
1163
+ }
1164
+ function isDependencyRelationship(value) {
1165
+ return isString(value) && Object.values(DEPENDENCY_RELATIONSHIPS_MAP).includes(
1166
+ value
1167
+ );
1168
+ }
1169
+ function isDependencyRelationshipDescription(value) {
1170
+ return isObjectWithProperty(value, "to") && (isNull(value.to) || isDependencyRelationship(value.to)) && isObjectWithProperty(value, "from") && (isNull(value.from) || isDependencyRelationship(value.from));
1171
+ }
1172
+ function isElementsDependencyInfo(value) {
1173
+ return isObjectWithProperty(value, "kind") && isDependencyKind(value.kind) && isObjectWithProperty(value, "relationship") && isDependencyRelationshipDescription(value.relationship) && isObjectWithProperty(value, "nodeKind") && (isNull(value.nodeKind) || isString(value.nodeKind));
1174
+ }
1175
+ function isDependencyDescription(value) {
1176
+ return isObjectWithProperty(value, "to") && isElementDescription(value.to) && isObjectWithProperty(value, "from") && isElementDescription(value.from) && isObjectWithProperty(value, "dependency") && isElementsDependencyInfo(value.dependency);
1177
+ }
1178
+ function isInternalDependency(dependency) {
1179
+ return dependency.dependency.relationship.to === DEPENDENCY_RELATIONSHIPS_MAP.INTERNAL;
1180
+ }
1181
+
1182
+ // src/Descriptor/DependenciesDescriptor.ts
1183
+ var DependenciesDescriptor = class {
1184
+ /**
1185
+ * Cache to store previously described dependencies.
1186
+ */
1187
+ _dependenciesCache = new CacheManager();
1188
+ /**
1189
+ * Elements descriptor instance.
1190
+ */
1191
+ _elementsDescriptor;
1192
+ /**
1193
+ * Creates a new DependenciesDescriptor instance.
1194
+ * @param elementsDescriptor The elements descriptor instance.
1195
+ */
1196
+ constructor(elementsDescriptor) {
1197
+ this._elementsDescriptor = elementsDescriptor;
1198
+ }
1199
+ /**
1200
+ * Serializes the elements cache to a plain object.
1201
+ * @returns The serialized elements cache.
1202
+ */
1203
+ serializeCache() {
1204
+ return this._dependenciesCache.serialize();
1205
+ }
1206
+ /**
1207
+ * Sets the elements cache from a serialized object.
1208
+ * @param serializedCache The serialized elements cache.
1209
+ */
1210
+ setCacheFromSerialized(serializedCache) {
1211
+ this._dependenciesCache.setFromSerialized(serializedCache);
1212
+ }
1213
+ /**
1214
+ * Clears the elements cache.
1215
+ */
1216
+ clearCache() {
1217
+ this._dependenciesCache.clear();
1218
+ }
1219
+ /**
1220
+ * Retrieves the element path of the parent of a given element.
1221
+ * @param elementInfo The element whose parent is to be retrieved.
1222
+ * @returns The parent element path, or undefined if none exists.
1223
+ */
1224
+ _getParent(elementInfo) {
1225
+ return elementInfo.parents[0]?.elementPath;
1226
+ }
1227
+ /**
1228
+ * Retrieves the common ancestor of two elements.
1229
+ * @param elementInfoA The first element.
1230
+ * @param elementInfoB The second element.
1231
+ * @returns The common ancestor element path, or undefined if none exists.
1232
+ */
1233
+ _getCommonAncestor(elementInfoA, elementInfoB) {
1234
+ const commonAncestor = elementInfoA.parents.find((elementParentA) => {
1235
+ return elementInfoB.parents.some((elementParentB) => {
1236
+ return elementParentA.elementPath === elementParentB.elementPath;
1237
+ });
1238
+ });
1239
+ return commonAncestor?.elementPath;
1240
+ }
1241
+ /**
1242
+ * Checks if the parent of element A is an ancestor of element B.
1243
+ * @param elementA The element A.
1244
+ * @param elementB The element B.
1245
+ * @returns True if the parent of element A is an ancestor of element B, false otherwise.
1246
+ */
1247
+ _isDescendantOfParent(elementA, elementB) {
1248
+ const commonAncestor = this._getCommonAncestor(elementA, elementB);
1249
+ return commonAncestor && commonAncestor === this._getParent(elementA);
1250
+ }
1251
+ /**
1252
+ * Checks if two elements are siblings (same parent).
1253
+ * @param elementA The first element.
1254
+ * @param elementB The second element.
1255
+ * @returns True if the elements are siblings, false otherwise.
1256
+ */
1257
+ _isSibling(elementA, elementB) {
1258
+ const parentA = this._getParent(elementA);
1259
+ const parentB = this._getParent(elementB);
1260
+ return parentA && parentB && parentA === parentB;
1261
+ }
1262
+ /**
1263
+ * Checks if one element is a descendant of another.
1264
+ * @param elementA The potential descendant element.
1265
+ * @param elementB The potential ancestor element.
1266
+ * @returns True if elementA is a descendant of elementB, false otherwise.
1267
+ */
1268
+ _isDescendant(elementA, elementB) {
1269
+ return elementA.parents.some(
1270
+ (parent) => parent.elementPath === elementB.elementPath
1271
+ );
1272
+ }
1273
+ /**
1274
+ * Checks if one element is a child of another.
1275
+ * @param elementA The potential child element.
1276
+ * @param elementB The potential parent element.
1277
+ * @returns True if elementA is a child of elementB, false otherwise.
1278
+ */
1279
+ _isChild(elementA, elementB) {
1280
+ return this._getParent(elementA) === elementB.elementPath;
1281
+ }
1282
+ /**
1283
+ * Checks if two local elements are internally related (same element).
1284
+ * @param elementA The first element.
1285
+ * @param elementB The second element.
1286
+ * @returns True if the elements are internally related, false otherwise.
1287
+ */
1288
+ _isInternal(elementA, elementB) {
1289
+ return elementA.elementPath === elementB.elementPath;
1290
+ }
1291
+ /**
1292
+ * Retrieves the relationship between two local known elements in terms of dependency.
1293
+ * @param element The element depending on another element.
1294
+ * @param dependency The element being depended on.
1295
+ * @returns The relationship between the elements.
1296
+ */
1297
+ _dependencyRelationship(element, dependency) {
1298
+ if (isIgnoredElement(dependency) || !isKnownLocalElement(dependency) || !isKnownLocalElement(element)) {
1299
+ return null;
1300
+ }
1301
+ if (this._isInternal(dependency, element)) {
1302
+ return DEPENDENCY_RELATIONSHIPS_MAP.INTERNAL;
1303
+ }
1304
+ if (this._isChild(dependency, element)) {
1305
+ return DEPENDENCY_RELATIONSHIPS_MAP.CHILD;
1306
+ }
1307
+ if (this._isDescendant(dependency, element)) {
1308
+ return DEPENDENCY_RELATIONSHIPS_MAP.DESCENDANT;
1309
+ }
1310
+ if (this._isSibling(dependency, element)) {
1311
+ return DEPENDENCY_RELATIONSHIPS_MAP.SIBLING;
1312
+ }
1313
+ if (this._isChild(element, dependency)) {
1314
+ return DEPENDENCY_RELATIONSHIPS_MAP.PARENT;
1315
+ }
1316
+ if (this._isDescendant(element, dependency)) {
1317
+ return DEPENDENCY_RELATIONSHIPS_MAP.ANCESTOR;
1318
+ }
1319
+ if (this._isDescendantOfParent(dependency, element)) {
1320
+ return DEPENDENCY_RELATIONSHIPS_MAP.UNCLE;
1321
+ }
1322
+ if (this._isDescendantOfParent(element, dependency)) {
1323
+ return DEPENDENCY_RELATIONSHIPS_MAP.NEPHEW;
1324
+ }
1325
+ return null;
1326
+ }
1327
+ _dependencyRelationships(element, dependency) {
1328
+ const toRelationship = this._dependencyRelationship(element, dependency);
1329
+ const fromRelationship = toRelationship ? DEPENDENCY_RELATIONSHIPS_INVERTED_MAP[toRelationship] : null;
1330
+ return {
1331
+ from: fromRelationship,
1332
+ to: toRelationship
1333
+ };
1334
+ }
1335
+ /**
1336
+ * Describes elements in a dependency relationship, and provides additional information about the dependency itself.
1337
+ * @param options The options for describing the elements and the dependency details.
1338
+ * @returns The description of the dependency between the elements.
1339
+ */
1340
+ describeDependency({
1341
+ from,
1342
+ to,
1343
+ source,
1344
+ kind,
1345
+ nodeKind,
1346
+ specifiers
1347
+ }) {
1348
+ if (this._dependenciesCache.has({
1349
+ from,
1350
+ to,
1351
+ source,
1352
+ kind,
1353
+ nodeKind,
1354
+ specifiers
1355
+ })) {
1356
+ return this._dependenciesCache.get({
1357
+ from,
1358
+ to,
1359
+ source,
1360
+ kind,
1361
+ nodeKind,
1362
+ specifiers
1363
+ });
1364
+ }
1365
+ const fromElement = this._elementsDescriptor.describeElement(from);
1366
+ const toElement = this._elementsDescriptor.describeDependencyElement(
1367
+ source,
1368
+ to
1369
+ );
1370
+ const result = {
1371
+ from: fromElement,
1372
+ to: toElement,
1373
+ dependency: {
1374
+ kind,
1375
+ nodeKind: nodeKind || null,
1376
+ relationship: this._dependencyRelationships(fromElement, toElement),
1377
+ specifiers: specifiers || null
1378
+ }
1379
+ };
1380
+ this._dependenciesCache.set(
1381
+ {
1382
+ from,
1383
+ to,
1384
+ source,
1385
+ kind,
1386
+ nodeKind,
1387
+ specifiers
1388
+ },
1389
+ result
1390
+ );
1391
+ return result;
1392
+ }
1393
+ };
1394
+
1395
+ // src/Descriptor/ElementsDescriptor.ts
1396
+ import isCoreModule from "is-core-module";
1397
+ import micromatch3 from "micromatch";
1398
+ var UNKNOWN_LOCAL_ELEMENT = {
1399
+ path: null,
1400
+ elementPath: null,
1401
+ internalPath: null,
1402
+ source: null,
1403
+ baseSource: null,
1404
+ parents: null,
1405
+ type: null,
1406
+ category: null,
1407
+ captured: null,
1408
+ origin: ELEMENT_ORIGINS_MAP.LOCAL,
1409
+ isIgnored: false,
1410
+ isUnknown: true
1411
+ };
1412
+ var ElementsDescriptor = class {
1413
+ _mod = null;
1414
+ /**
1415
+ * Cache to store previously described elements.
1416
+ */
1417
+ _elementsCache = new CacheManager();
1418
+ /**
1419
+ * Cache to store previously described files.
1420
+ */
1421
+ _filesCache = new CacheManager();
1422
+ /**
1423
+ * Configuration instance for this descriptor.
1424
+ */
1425
+ _config;
1426
+ /**
1427
+ * Element descriptors used by this descriptor.
1428
+ */
1429
+ _elementDescriptors;
1430
+ /**
1431
+ * The configuration options for this descriptor.
1432
+ * @param elementDescriptors The element descriptors.
1433
+ * @param configOptions The configuration options.
1434
+ */
1435
+ constructor(elementDescriptors, configOptions) {
1436
+ this._elementDescriptors = elementDescriptors;
1437
+ this._validateDescriptors(elementDescriptors);
1438
+ this._config = new Config(configOptions);
1439
+ this._loadModuleInNode();
1440
+ }
1441
+ /**
1442
+ * Serializes the elements cache to a plain object.
1443
+ * @returns The serialized elements cache.
1444
+ */
1445
+ serializeCache() {
1446
+ return this._elementsCache.serialize();
1447
+ }
1448
+ /**
1449
+ * Sets the elements cache from a serialized object.
1450
+ * @param serializedCache The serialized elements cache.
1451
+ */
1452
+ setCacheFromSerialized(serializedCache) {
1453
+ this._elementsCache.setFromSerialized(serializedCache);
1454
+ }
1455
+ /**
1456
+ * Clears the elements cache.
1457
+ */
1458
+ clearCache() {
1459
+ this._elementsCache.clear();
1460
+ this._filesCache.clear();
1461
+ }
1462
+ /**
1463
+ * Loads the Node.js module to access built-in modules information when running in Node.js environment.
1464
+ */
1465
+ _loadModuleInNode() {
1466
+ if (!this._mod && !isNullish(process) && !isNullish(process.versions) && !isNullish(process.versions.node)) {
1467
+ this._mod = __require("module");
1468
+ }
1469
+ }
1470
+ /**
1471
+ * Validates the element descriptors to ensure they are correctly defined.
1472
+ */
1473
+ _validateDescriptors(elementDescriptors) {
1474
+ let index = 0;
1475
+ for (const descriptor of elementDescriptors) {
1476
+ if (!isElementDescriptor(descriptor)) {
1477
+ throw new Error(
1478
+ `Element descriptor at index ${index} must have a pattern, and either a 'type' or 'category' defined.`
1479
+ );
1480
+ }
1481
+ index++;
1482
+ }
1483
+ }
1484
+ /**
1485
+ * Determines if a dependency source is a core module.
1486
+ * @param dependencySource The source of the dependency to check.
1487
+ * @param baseDependencySource The base source of the dependency to check.
1488
+ * @returns True if the dependency source is a core module, false otherwise.
1489
+ */
1490
+ _dependencySourceIsCoreModule(dependencySource, baseDependencySource) {
1491
+ if (this._mod) {
1492
+ const baseSourceWithoutPrefix = baseDependencySource.startsWith("node:") ? baseDependencySource.slice(5) : baseDependencySource;
1493
+ return this._mod.builtinModules.includes(baseSourceWithoutPrefix);
1494
+ }
1495
+ return isCoreModule(dependencySource);
1496
+ }
1497
+ /**
1498
+ * Determines if a dependency source is scoped (e.g., @scope/package).
1499
+ * @param dependencySource The source of the dependency to check.
1500
+ * @returns True if the dependency source is scoped, false otherwise.
1501
+ */
1502
+ _dependencySourceIsScoped(dependencySource) {
1503
+ return /^@[^/]*\/?[^/]+/.test(dependencySource);
1504
+ }
1505
+ /**
1506
+ * Determines if a dependency source is external or an alias.
1507
+ * @param dependencySource The source of the dependency to check.
1508
+ * @returns True if the dependency source is external or an alias, false otherwise.
1509
+ */
1510
+ _dependencySourceIsExternalOrScoped(dependencySource) {
1511
+ return /^\w/.test(dependencySource) || this._dependencySourceIsScoped(dependencySource);
1512
+ }
1513
+ /**
1514
+ * Gets the base source of an external module.
1515
+ * @param dependencySource The source of the dependency to check.
1516
+ * @returns The base source of the external module. (e.g., for "@scope/package/submodule", it returns "@scope/package")
1517
+ */
1518
+ _getExternalModuleBaseSource(dependencySource) {
1519
+ if (this._dependencySourceIsScoped(dependencySource)) {
1520
+ const [scope, packageName] = dependencySource.split("/");
1521
+ return `${scope}/${packageName}`;
1522
+ }
1523
+ const [pkg] = dependencySource.split("/");
1524
+ return pkg;
1525
+ }
1526
+ /**
1527
+ * Determines if an element is external based on its file path and dependency source.
1528
+ * Files inside "node_modules" are considered external.
1529
+ * If the dependency source is not provided, only the file path is considered.
1530
+ * If the dependency source is provided, it must not be a local path (i.e, it should start by "./", "../", or "/").
1531
+ * @param filePath
1532
+ * @param dependencySource
1533
+ * @returns
1534
+ */
1535
+ _isExternalDependency(filePath, dependencySource) {
1536
+ return (!filePath || filePath.includes("node_modules")) && // Not having a source, and being in node_modules only could happen if user is analyzing a file directly from there, not as a dependency. Should this be considered external then?
1537
+ (!dependencySource || this._dependencySourceIsExternalOrScoped(dependencySource));
1538
+ }
1539
+ /**
1540
+ * Determines if a given path is included based on the configuration.
1541
+ * @param elementPath The element path to check.
1542
+ * @returns True if the path is included, false otherwise.
1543
+ */
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(
1548
+ elementPath,
1549
+ this._config.options.includePaths
1550
+ );
1551
+ const isIgnored = micromatch3.isMatch(
1552
+ elementPath,
1553
+ this._config.options.ignorePaths
1554
+ );
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
+ }
1561
+ return true;
1562
+ }
1563
+ /**
1564
+ * Gets captured values from the captured array and capture configuration.
1565
+ * @param captured The array of captured strings.
1566
+ * @param captureConfig The configuration for capturing values.
1567
+ * @returns The captured values as an object.
1568
+ */
1569
+ _getCapturedValues(captured, captureConfig) {
1570
+ if (!captureConfig) {
1571
+ return null;
1572
+ }
1573
+ return captured.reduce((capturedValues, captureValue, index) => {
1574
+ if (captureConfig[index]) {
1575
+ capturedValues[captureConfig[index]] = captureValue;
1576
+ }
1577
+ return capturedValues;
1578
+ }, {});
1579
+ }
1580
+ /**
1581
+ * Gets the element path based on the path pattern, path segments to the element, and all path segments from the file path.
1582
+ * @param pathPattern The element path pattern.
1583
+ * @param pathSegments The path segments leading to the element.
1584
+ * @param allPathSegments The full path segments from the file path.
1585
+ * @returns The element path.
1586
+ */
1587
+ _getElementPath(pathPattern, pathSegments, allPathSegments) {
1588
+ const elementPathRegexp = micromatch3.makeRe(pathPattern);
1589
+ const testedSegments = [];
1590
+ let result;
1591
+ 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
+ }
1598
+ }
1599
+ }
1600
+ return `${[...allPathSegments].reverse().join("/").split(result)[0]}${result}`;
1601
+ }
1602
+ _fileDescriptorMatch({
1603
+ elementDescriptor,
1604
+ filePath,
1605
+ currentPathSegments,
1606
+ lastPathSegmentMatching,
1607
+ alreadyMatched
1608
+ }) {
1609
+ const mode = isElementDescriptorMode(elementDescriptor.mode) ? elementDescriptor.mode : ELEMENT_DESCRIPTOR_MODES_MAP.FOLDER;
1610
+ const patterns = isArray(elementDescriptor.pattern) ? elementDescriptor.pattern : [elementDescriptor.pattern];
1611
+ for (const pattern of patterns) {
1612
+ const useFullPathMatch = mode === ELEMENT_DESCRIPTOR_MODES_MAP.FULL && !alreadyMatched;
1613
+ const effectivePattern = mode === ELEMENT_DESCRIPTOR_MODES_MAP.FOLDER && !alreadyMatched ? `${pattern}/**/*` : pattern;
1614
+ let baseCapture = null;
1615
+ let hasCapture = true;
1616
+ if (elementDescriptor.basePattern) {
1617
+ const baseTarget = filePath.split("/").slice(0, filePath.split("/").length - lastPathSegmentMatching).join("/");
1618
+ baseCapture = micromatch3.capture(
1619
+ [elementDescriptor.basePattern, "**", effectivePattern].join("/"),
1620
+ baseTarget
1621
+ );
1622
+ hasCapture = baseCapture !== null;
1623
+ }
1624
+ const capture = micromatch3.capture(
1625
+ effectivePattern,
1626
+ useFullPathMatch ? filePath : currentPathSegments.join("/")
1627
+ );
1628
+ if (capture && hasCapture) {
1629
+ return {
1630
+ matched: true,
1631
+ capture,
1632
+ baseCapture,
1633
+ useFullPathMatch,
1634
+ patternUsed: pattern
1635
+ };
1636
+ }
1637
+ }
1638
+ return { matched: false };
1639
+ }
1640
+ /**
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
+ * @param elementPath The path of the element to describe.
1646
+ * @returns The description of the element.
1647
+ */
1648
+ _getFileDescription(includeExternal, filePath) {
1649
+ if (!filePath) {
1650
+ return {
1651
+ ...UNKNOWN_LOCAL_ELEMENT
1652
+ };
1653
+ }
1654
+ if (!this._pathIsIncluded(filePath, includeExternal)) {
1655
+ return {
1656
+ ...UNKNOWN_LOCAL_ELEMENT,
1657
+ path: filePath,
1658
+ isIgnored: true,
1659
+ origin: null
1660
+ };
1661
+ }
1662
+ const parents = [];
1663
+ const elementResult = {
1664
+ path: filePath,
1665
+ type: null,
1666
+ category: null,
1667
+ captured: null,
1668
+ origin: ELEMENT_ORIGINS_MAP.LOCAL,
1669
+ isIgnored: false
1670
+ };
1671
+ const state = {
1672
+ pathSegmentsAccumulator: [],
1673
+ lastPathSegmentMatching: 0
1674
+ };
1675
+ const pathSegments = filePath.split("/").reverse();
1676
+ const processElementMatch = (elementDescriptor, matchInfo, currentPathSegments, elementPaths) => {
1677
+ const { capture, baseCapture, useFullPathMatch, patternUsed } = matchInfo;
1678
+ let capturedValues = this._getCapturedValues(
1679
+ capture,
1680
+ elementDescriptor.capture
1681
+ );
1682
+ if (elementDescriptor.basePattern && baseCapture) {
1683
+ capturedValues = {
1684
+ ...this._getCapturedValues(
1685
+ baseCapture,
1686
+ elementDescriptor.baseCapture
1687
+ ),
1688
+ ...capturedValues
1689
+ };
1690
+ }
1691
+ const elementPath = useFullPathMatch ? filePath : this._getElementPath(patternUsed, currentPathSegments, elementPaths);
1692
+ if (!elementResult.type && !elementResult.category) {
1693
+ const mode = elementDescriptor.mode || ELEMENT_DESCRIPTOR_MODES_MAP.FOLDER;
1694
+ elementResult.type = elementDescriptor.type || null;
1695
+ elementResult.category = elementDescriptor.category || null;
1696
+ elementResult.isUnknown = false;
1697
+ elementResult.elementPath = elementPath;
1698
+ elementResult.captured = capturedValues;
1699
+ elementResult.internalPath = mode === ELEMENT_DESCRIPTOR_MODES_MAP.FOLDER || filePath !== elementPath ? filePath.replace(`${elementPath}/`, "") : filePath.split("/").pop();
1700
+ } else {
1701
+ parents.push({
1702
+ type: elementDescriptor.type || null,
1703
+ category: elementDescriptor.category || null,
1704
+ elementPath,
1705
+ captured: capturedValues
1706
+ });
1707
+ }
1708
+ };
1709
+ for (let i = 0; i < pathSegments.length; i++) {
1710
+ const segment = pathSegments[i];
1711
+ state.pathSegmentsAccumulator.unshift(segment);
1712
+ for (const elementDescriptor of this._elementDescriptors) {
1713
+ const match = this._fileDescriptorMatch({
1714
+ elementDescriptor,
1715
+ filePath,
1716
+ currentPathSegments: state.pathSegmentsAccumulator,
1717
+ lastPathSegmentMatching: state.lastPathSegmentMatching,
1718
+ alreadyMatched: Boolean(elementResult.type) || Boolean(elementResult.category)
1719
+ });
1720
+ if (match.matched) {
1721
+ processElementMatch(
1722
+ elementDescriptor,
1723
+ match,
1724
+ state.pathSegmentsAccumulator,
1725
+ pathSegments
1726
+ );
1727
+ state.pathSegmentsAccumulator = [];
1728
+ state.lastPathSegmentMatching = i + 1;
1729
+ break;
1730
+ }
1731
+ }
1732
+ }
1733
+ const result = { ...elementResult, parents };
1734
+ if (!isKnownLocalElement(result)) {
1735
+ return {
1736
+ ...UNKNOWN_LOCAL_ELEMENT,
1737
+ path: filePath
1738
+ };
1739
+ }
1740
+ return result;
1741
+ }
1742
+ /**
1743
+ * Describes a file given its path.
1744
+ * @param includeExternal Whether to include external files (inside node_modules) in the matching process.
1745
+ * @param filePath The path of the file to describe.
1746
+ * @returns The description of the element.
1747
+ */
1748
+ _describeFile(includeExternal, filePath) {
1749
+ if (this._filesCache.has(String(filePath))) {
1750
+ return this._filesCache.get(String(filePath));
1751
+ }
1752
+ const description = this._getFileDescription(includeExternal, filePath);
1753
+ this._filesCache.set(String(filePath), description);
1754
+ return description;
1755
+ }
1756
+ /**
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.
1759
+ * @param dependencySource The source of the dependency.
1760
+ * @returns The description of the dependency element.
1761
+ */
1762
+ _describeDependencyElement(element, dependencySource) {
1763
+ if (isIgnoredElement(element)) {
1764
+ return {
1765
+ ...element,
1766
+ source: dependencySource
1767
+ };
1768
+ }
1769
+ const baseDependencySource = this._getExternalModuleBaseSource(dependencySource);
1770
+ const isCore = this._dependencySourceIsCoreModule(
1771
+ dependencySource,
1772
+ baseDependencySource
1773
+ );
1774
+ if (isCore) {
1775
+ const coreElement = {
1776
+ ...element,
1777
+ source: dependencySource,
1778
+ baseSource: baseDependencySource,
1779
+ origin: ELEMENT_ORIGINS_MAP.CORE
1780
+ };
1781
+ return coreElement;
1782
+ }
1783
+ const isExternal = this._isExternalDependency(
1784
+ element.path,
1785
+ dependencySource
1786
+ );
1787
+ if (!isExternal) {
1788
+ const localElement = {
1789
+ ...element,
1790
+ source: dependencySource
1791
+ };
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;
1802
+ }
1803
+ _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
+ );
1822
+ return elementResult;
1823
+ }
1824
+ /**
1825
+ * Describes an element given its file path.
1826
+ * @param filePath The path of the file to describe.
1827
+ * @returns The description of the element.
1828
+ */
1829
+ describeElement(filePath) {
1830
+ return this._describeElement(filePath);
1831
+ }
1832
+ /**
1833
+ * Describes a dependency element given its dependency source and file path.
1834
+ * @param dependencySource The source of the dependency.
1835
+ * @param filePath The path of the file being the dependency, if known.
1836
+ * @returns The description of the dependency element.
1837
+ */
1838
+ describeDependencyElement(dependencySource, filePath) {
1839
+ return this._describeElement(filePath, dependencySource);
1840
+ }
1841
+ };
1842
+
1843
+ // src/Descriptor/Descriptors.ts
1844
+ var Descriptors = class {
1845
+ _elementsDescriptor;
1846
+ _dependenciesDescriptor;
1847
+ /** Creates a new DescriptorsManager instance
1848
+ * @param elementDescriptors The element descriptors.
1849
+ * @param configOptions The configuration options.
1850
+ */
1851
+ constructor(elementDescriptors, configOptions) {
1852
+ this._elementsDescriptor = new ElementsDescriptor(
1853
+ elementDescriptors,
1854
+ configOptions
1855
+ );
1856
+ this._dependenciesDescriptor = new DependenciesDescriptor(
1857
+ this._elementsDescriptor
1858
+ );
1859
+ }
1860
+ /**
1861
+ * Serializes the elements and dependencies cache to a plain object.
1862
+ * @returns The serialized elements and dependencies cache.
1863
+ */
1864
+ serializeCache() {
1865
+ return {
1866
+ elements: this._elementsDescriptor.serializeCache(),
1867
+ dependencies: this._dependenciesDescriptor.serializeCache()
1868
+ };
1869
+ }
1870
+ /**
1871
+ * Sets the elements and dependencies cache from a serialized object.
1872
+ * @param serializedCache The serialized elements and dependencies cache.
1873
+ */
1874
+ setCacheFromSerialized(serializedCache) {
1875
+ this._elementsDescriptor.setCacheFromSerialized(serializedCache.elements);
1876
+ this._dependenciesDescriptor.setCacheFromSerialized(
1877
+ serializedCache.dependencies
1878
+ );
1879
+ }
1880
+ /**
1881
+ * Clears all caches.
1882
+ */
1883
+ clearCache() {
1884
+ this._elementsDescriptor.clearCache();
1885
+ this._dependenciesDescriptor.clearCache();
1886
+ }
1887
+ /**
1888
+ * Describes an element given its file path.
1889
+ * @param filePath The path of the file to describe.
1890
+ * @returns The description of the element.
1891
+ */
1892
+ describeElement(filePath) {
1893
+ return this._elementsDescriptor.describeElement(filePath);
1894
+ }
1895
+ /**
1896
+ * Describes a dependency element given its dependency source and file path.
1897
+ * @param dependencySource The source of the dependency.
1898
+ * @param filePath The path of the file being the dependency, if known.
1899
+ * @returns The description of the dependency element.
1900
+ */
1901
+ describeDependencyElement(dependencySource, filePath) {
1902
+ return this._elementsDescriptor.describeDependencyElement(
1903
+ dependencySource,
1904
+ filePath
1905
+ );
1906
+ }
1907
+ /**
1908
+ * Describes elements in a dependency relationship, and provides additional information about the dependency itself.
1909
+ * @param options The options for describing the elements and the dependency details.
1910
+ * @returns The description of the dependency between the elements.
1911
+ */
1912
+ describeDependency(options) {
1913
+ return this._dependenciesDescriptor.describeDependency(options);
1914
+ }
1915
+ };
1916
+
1917
+ // src/Matcher/Matcher.ts
1918
+ var Matcher = class {
1919
+ _descriptors;
1920
+ _elementsMatcher;
1921
+ _dependenciesMatcher;
1922
+ /**
1923
+ * Constructor for the Matcher class.
1924
+ * @param descriptors Element descriptors to use for matching.
1925
+ * @param config Configuration options.
1926
+ */
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
+ );
1934
+ }
1935
+ /**
1936
+ * Determines if an element matches a given selector.
1937
+ * @param filePath The file path of the element
1938
+ * @param selector The selector to match against
1939
+ * @param options Extra matcher options
1940
+ * @returns True if the element matches the selector, false otherwise
1941
+ */
1942
+ _isElementMatch(filePath, selector, options) {
1943
+ const description = this._descriptors.describeElement(filePath);
1944
+ return this._elementsMatcher.isElementMatch(description, selector, options);
1945
+ }
1946
+ /**
1947
+ * Determines if a dependency matches a given selector.
1948
+ * @param dependencyData The data describing the dependency
1949
+ * @param selector The selector to match against
1950
+ * @param options Extra matcher options
1951
+ * @returns True if the dependency matches the selector, false otherwise
1952
+ */
1953
+ _isDependencyMatch(dependencyData, selector, options) {
1954
+ const description = this._descriptors.describeDependency(dependencyData);
1955
+ return this._dependenciesMatcher.isDependencyMatch(
1956
+ description,
1957
+ selector,
1958
+ options
1959
+ );
1960
+ }
1961
+ isMatch(descriptorOptions, selector, options) {
1962
+ if (isString(descriptorOptions)) {
1963
+ return this._isElementMatch(
1964
+ descriptorOptions,
1965
+ selector,
1966
+ options
1967
+ );
1968
+ }
1969
+ return this._isDependencyMatch(
1970
+ descriptorOptions,
1971
+ selector,
1972
+ options
1973
+ );
1974
+ }
1975
+ /**
1976
+ * Determines the selector matching for an element.
1977
+ * @param filePath The file path of the element
1978
+ * @param selector The selectors to match against
1979
+ * @param options Extra options for matching
1980
+ * @returns The matching selector data or null if no match is found
1981
+ */
1982
+ _getElementSelectorMatching(filePath, selector, options) {
1983
+ const description = this._descriptors.describeElement(filePath);
1984
+ return this._elementsMatcher.getSelectorMatching(
1985
+ description,
1986
+ selector,
1987
+ options
1988
+ );
1989
+ }
1990
+ /**
1991
+ * Determines the selector matching for a dependency.
1992
+ * @param dependencyData The data describing the dependency
1993
+ * @param selector The selectors to match against
1994
+ * @param options Extra options for matching
1995
+ * @returns The matching dependency result or null if no match is found
1996
+ */
1997
+ _isDependencySelectorMatching(dependencyData, selector, options) {
1998
+ const description = this._descriptors.describeDependency(dependencyData);
1999
+ return this._dependenciesMatcher.getSelectorsMatching(
2000
+ description,
2001
+ selector,
2002
+ options
2003
+ );
2004
+ }
2005
+ getSelectorMatching(descriptorOptions, selector, options) {
2006
+ if (isString(descriptorOptions)) {
2007
+ return this._getElementSelectorMatching(
2008
+ descriptorOptions,
2009
+ selector,
2010
+ options
2011
+ );
2012
+ }
2013
+ return this._isDependencySelectorMatching(
2014
+ descriptorOptions,
2015
+ selector,
2016
+ options
2017
+ );
2018
+ }
2019
+ getSelectorMatchingDescription(description, selector, options) {
2020
+ if (isElementsSelector(selector) && isElementDescription(description)) {
2021
+ return this._elementsMatcher.getSelectorMatching(
2022
+ description,
2023
+ selector,
2024
+ options
2025
+ );
2026
+ } else if (isDependencySelector(selector) && isDependencyDescription(description)) {
2027
+ return this._dependenciesMatcher.getSelectorsMatching(
2028
+ description,
2029
+ selector,
2030
+ options
2031
+ );
2032
+ }
2033
+ throw new Error(
2034
+ "Invalid arguments: Please provide a valid description and selector"
2035
+ );
2036
+ }
2037
+ /**
2038
+ * Describes an element given its file path.
2039
+ * @param filePath The path of the file to describe.
2040
+ * @returns The description of the element.
2041
+ */
2042
+ describeElement(filePath) {
2043
+ return this._descriptors.describeElement(filePath);
2044
+ }
2045
+ /**
2046
+ * Describes a dependency element given its dependency source and file path.
2047
+ * @param dependencySource The source of the dependency.
2048
+ * @param filePath The path of the file being the dependency, if known.
2049
+ * @returns The description of the dependency element.
2050
+ */
2051
+ describeDependencyElement(dependencySource, filePath) {
2052
+ return this._descriptors.describeDependencyElement(
2053
+ dependencySource,
2054
+ filePath
2055
+ );
2056
+ }
2057
+ /**
2058
+ * Describes elements in a dependency relationship, and provides additional information about the dependency itself.
2059
+ * @param options The options for describing the elements and the dependency details.
2060
+ * @returns The description of the dependency between the elements.
2061
+ */
2062
+ describeDependency(options) {
2063
+ return this._descriptors.describeDependency(options);
2064
+ }
2065
+ /**
2066
+ * Clears all caches.
2067
+ */
2068
+ clearCache() {
2069
+ this._descriptors.clearCache();
2070
+ this._elementsMatcher.clearCache();
2071
+ this._dependenciesMatcher.clearCache();
2072
+ }
2073
+ /**
2074
+ * Serializes the descriptors and elements matchers cache to a plain object.
2075
+ * @returns The serialized cache
2076
+ */
2077
+ serializeCache() {
2078
+ return {
2079
+ descriptors: this._descriptors.serializeCache(),
2080
+ elementsMatcher: this._elementsMatcher.serializeCache(),
2081
+ dependenciesMatcher: this._dependenciesMatcher.serializeCache()
2082
+ };
2083
+ }
2084
+ /**
2085
+ * Sets the descriptors and elements matchers cache from a serialized object.
2086
+ * @param serializedCache The serialized cache
2087
+ */
2088
+ setCacheFromSerialized(serializedCache) {
2089
+ this._descriptors.setCacheFromSerialized(serializedCache.descriptors);
2090
+ this._elementsMatcher.setCacheFromSerialized(
2091
+ serializedCache.elementsMatcher
2092
+ );
2093
+ this._dependenciesMatcher.setCacheFromSerialized(
2094
+ serializedCache.dependenciesMatcher
2095
+ );
2096
+ }
2097
+ };
2098
+
2099
+ // src/Elements.ts
2100
+ var Elements = class {
2101
+ /** The global configuration options for Elements. Can be overridden when getting a descriptor */
2102
+ _globalConfigOptions;
2103
+ /** 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;
2109
+ /**
2110
+ * Creates a new Elements instance
2111
+ * @param configOptions The global configuration options for Elements. Can be overridden when getting a descriptor.
2112
+ */
2113
+ constructor(configOptions) {
2114
+ const globalConfig = new Config(configOptions);
2115
+ this._globalConfigOptions = globalConfig.options;
2116
+ this._elementsMatcher = new ElementsMatcher(this._globalConfigOptions);
2117
+ this._dependenciesMatcher = new DependenciesMatcher(
2118
+ this._elementsMatcher,
2119
+ this._globalConfigOptions
2120
+ );
2121
+ }
2122
+ /**
2123
+ * Returns a serialized representation of the current state of the cache.
2124
+ * @returns A serialized representation of the cache.
2125
+ */
2126
+ serializeCache() {
2127
+ const matchersCache = Array.from(
2128
+ this._matchersCache.getAll().entries()
2129
+ ).reduce(
2130
+ (acc, [key, descriptorCache]) => {
2131
+ acc[key] = {
2132
+ config: descriptorCache.config,
2133
+ elementDescriptors: descriptorCache.elementDescriptors,
2134
+ cache: descriptorCache.matcher.serializeCache()
2135
+ };
2136
+ return acc;
2137
+ },
2138
+ {}
2139
+ );
2140
+ return {
2141
+ matchers: matchersCache,
2142
+ elementsMatcher: this._elementsMatcher.serializeCache(),
2143
+ dependenciesMatcher: this._dependenciesMatcher.serializeCache()
2144
+ };
2145
+ }
2146
+ /**
2147
+ * Sets the Elements cache from a serialized representation.
2148
+ * @param serializedCache The serialized cache to set.
2149
+ */
2150
+ setCacheFromSerialized(serializedCache) {
2151
+ for (const key in serializedCache.matchers) {
2152
+ const matcher = this.getMatcher(
2153
+ serializedCache.matchers[key].elementDescriptors,
2154
+ serializedCache.matchers[key].config
2155
+ );
2156
+ matcher.setCacheFromSerialized(serializedCache.matchers[key].cache);
2157
+ this._matchersCache.restore(key, {
2158
+ config: serializedCache.matchers[key].config,
2159
+ elementDescriptors: serializedCache.matchers[key].elementDescriptors,
2160
+ matcher
2161
+ });
2162
+ }
2163
+ this._elementsMatcher.setCacheFromSerialized(
2164
+ serializedCache.elementsMatcher
2165
+ );
2166
+ this._dependenciesMatcher.setCacheFromSerialized(
2167
+ serializedCache.dependenciesMatcher
2168
+ );
2169
+ }
2170
+ /**
2171
+ * Clears cache
2172
+ */
2173
+ clearCache() {
2174
+ this._elementsMatcher.clearCache();
2175
+ this._dependenciesMatcher.clearCache();
2176
+ for (const { matcher } of this._matchersCache.getAll().values()) {
2177
+ matcher.clearCache();
2178
+ }
2179
+ this._matchersCache.clear();
2180
+ }
2181
+ /**
2182
+ * Gets a Matcher instance for the given configuration options.
2183
+ * 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
+ * @param elementDescriptors The element descriptors to use.
2185
+ * @param configOptions Optional configuration options to override the global ones.
2186
+ * @returns A matcher instance, unique for each different configuration.
2187
+ */
2188
+ getMatcher(elementDescriptors, configOptions) {
2189
+ const optionsToUse = configOptions || this._globalConfigOptions;
2190
+ const configInstance = new Config(optionsToUse);
2191
+ const normalizedOptions = configInstance.options;
2192
+ const cacheKey = { config: normalizedOptions, elementDescriptors };
2193
+ if (this._matchersCache.has(cacheKey)) {
2194
+ return this._matchersCache.get(cacheKey).matcher;
2195
+ }
2196
+ const matcher = new Matcher(elementDescriptors, normalizedOptions);
2197
+ this._matchersCache.set(cacheKey, {
2198
+ config: normalizedOptions,
2199
+ elementDescriptors,
2200
+ matcher
2201
+ });
2202
+ return matcher;
2203
+ }
2204
+ };
2205
+ export {
2206
+ CacheManager,
2207
+ DEPENDENCY_KINDS_MAP,
2208
+ DEPENDENCY_KIND_TYPE,
2209
+ DEPENDENCY_KIND_VALUE,
2210
+ DEPENDENCY_RELATIONSHIPS_INVERTED_MAP,
2211
+ DEPENDENCY_RELATIONSHIPS_MAP,
2212
+ ELEMENT_DESCRIPTOR_MODES_MAP,
2213
+ ELEMENT_ORIGINS_MAP,
2214
+ Elements,
2215
+ isBaseElement,
2216
+ isBaseElementDescriptor,
2217
+ isBaseElementSelectorData,
2218
+ isCapturedValuesSelector,
2219
+ isCoreDependencyElement,
2220
+ isDependencyDescription,
2221
+ isDependencyElementDescription,
2222
+ isDependencyKind,
2223
+ isDependencyRelationship,
2224
+ isDependencyRelationshipDescription,
2225
+ isDependencySelector,
2226
+ isElementDescription,
2227
+ isElementDescriptor,
2228
+ isElementDescriptorMode,
2229
+ isElementDescriptorPattern,
2230
+ isElementDescriptorWithCategory,
2231
+ isElementDescriptorWithType,
2232
+ isElementSelector,
2233
+ isElementSelectorData,
2234
+ isElementSelectorWithLegacyOptions,
2235
+ isElementsDependencyInfo,
2236
+ isElementsSelector,
2237
+ isExternalDependencyElement,
2238
+ isExternalLibrariesSelector,
2239
+ isExternalLibrarySelector,
2240
+ isExternalLibrarySelectorOptions,
2241
+ isExternalLibrarySelectorOptionsWithPath,
2242
+ isExternalLibrarySelectorOptionsWithSpecifiers,
2243
+ isExternalLibrarySelectorWithOptions,
2244
+ isIgnoredElement,
2245
+ isInternalDependency,
2246
+ isKnownLocalElement,
2247
+ isLocalDependencyElement,
2248
+ isLocalElement,
2249
+ isSimpleElementSelectorByType,
2250
+ isUnknownLocalElement,
2251
+ normalizeElementsSelector
2252
+ };
2253
+ //# sourceMappingURL=index.mjs.map