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