@boundaries/elements 1.1.2 → 2.0.0-beta.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -45,8 +45,9 @@ __export(src_exports, {
45
45
  isBaseElementSelectorData: () => isBaseElementSelectorData,
46
46
  isCapturedValuesSelector: () => isCapturedValuesSelector,
47
47
  isCoreDependencyElement: () => isCoreDependencyElement,
48
+ isDependencyDataSelector: () => isDependencyDataSelector,
49
+ isDependencyDataSelectorData: () => isDependencyDataSelectorData,
48
50
  isDependencyDescription: () => isDependencyDescription,
49
- isDependencyElementDescription: () => isDependencyElementDescription,
50
51
  isDependencyKind: () => isDependencyKind,
51
52
  isDependencyRelationship: () => isDependencyRelationship,
52
53
  isDependencyRelationshipDescription: () => isDependencyRelationshipDescription,
@@ -63,12 +64,6 @@ __export(src_exports, {
63
64
  isElementsDependencyInfo: () => isElementsDependencyInfo,
64
65
  isElementsSelector: () => isElementsSelector,
65
66
  isExternalDependencyElement: () => isExternalDependencyElement,
66
- isExternalLibrariesSelector: () => isExternalLibrariesSelector,
67
- isExternalLibrarySelector: () => isExternalLibrarySelector,
68
- isExternalLibrarySelectorOptions: () => isExternalLibrarySelectorOptions,
69
- isExternalLibrarySelectorOptionsWithPath: () => isExternalLibrarySelectorOptionsWithPath,
70
- isExternalLibrarySelectorOptionsWithSpecifiers: () => isExternalLibrarySelectorOptionsWithSpecifiers,
71
- isExternalLibrarySelectorWithOptions: () => isExternalLibrarySelectorWithOptions,
72
67
  isIgnoredElement: () => isIgnoredElement,
73
68
  isInternalDependency: () => isInternalDependency,
74
69
  isKnownLocalElement: () => isKnownLocalElement,
@@ -76,10 +71,54 @@ __export(src_exports, {
76
71
  isLocalElement: () => isLocalElement,
77
72
  isSimpleElementSelectorByType: () => isSimpleElementSelectorByType,
78
73
  isUnknownLocalElement: () => isUnknownLocalElement,
74
+ normalizeElementSelector: () => normalizeElementSelector,
79
75
  normalizeElementsSelector: () => normalizeElementsSelector
80
76
  });
81
77
  module.exports = __toCommonJS(src_exports);
82
78
 
79
+ // src/Support/TypeGuards.ts
80
+ function isString(value) {
81
+ return typeof value === "string";
82
+ }
83
+ function isUndefined(value) {
84
+ return value === void 0;
85
+ }
86
+ function isNull(value) {
87
+ return value === null;
88
+ }
89
+ function isNullish(value) {
90
+ return isUndefined(value) || isNull(value);
91
+ }
92
+ function isBoolean(value) {
93
+ return typeof value === "boolean";
94
+ }
95
+ function isObject(value) {
96
+ return !isNullish(value) && !isBoolean(value) && !isArray(value) && typeof value === "object";
97
+ }
98
+ function isEmptyObject(obj) {
99
+ return isObject(obj) && Object.keys(obj).length === 0;
100
+ }
101
+ function isArray(value) {
102
+ return Array.isArray(value);
103
+ }
104
+ function isEmptyArray(arr) {
105
+ return arr.length === 0;
106
+ }
107
+ function isStringArray(value) {
108
+ return isArray(value) && value.every(isString);
109
+ }
110
+ function isObjectWithProperty(value, key) {
111
+ return isObject(value) && Object.hasOwn(value, key);
112
+ }
113
+ function isObjectWithAnyOfProperties(value, keys) {
114
+ return isObject(value) && keys.some((key) => key in value);
115
+ }
116
+
117
+ // src/Support/Paths.ts
118
+ function normalizePath(filePath) {
119
+ return filePath.replaceAll("\\", "/");
120
+ }
121
+
83
122
  // src/Config/Config.ts
84
123
  var Config = class {
85
124
  /** The ignore paths */
@@ -90,6 +129,10 @@ var Config = class {
90
129
  _legacyTemplates;
91
130
  /** Whether the cache is enabled */
92
131
  _cache;
132
+ /** Configuration for categorizing dependencies as external or local */
133
+ _flagAsExternal;
134
+ /** Root path of the project */
135
+ _rootPath;
93
136
  /**
94
137
  * Creates a new Config instance
95
138
  * @param options Configuration options
@@ -99,6 +142,18 @@ var Config = class {
99
142
  this._includePaths = options?.includePaths;
100
143
  this._legacyTemplates = options?.legacyTemplates ?? true;
101
144
  this._cache = options?.cache ?? true;
145
+ this._flagAsExternal = {
146
+ unresolvableAlias: options?.flagAsExternal?.unresolvableAlias ?? true,
147
+ inNodeModules: options?.flagAsExternal?.inNodeModules ?? true,
148
+ outsideRootPath: options?.flagAsExternal?.outsideRootPath ?? false,
149
+ customSourcePatterns: options?.flagAsExternal?.customSourcePatterns ?? []
150
+ };
151
+ if (options?.rootPath) {
152
+ const normalizedRoot = normalizePath(options.rootPath);
153
+ this._rootPath = normalizedRoot.endsWith("/") ? normalizedRoot : `${normalizedRoot}/`;
154
+ } else {
155
+ this._rootPath = void 0;
156
+ }
102
157
  }
103
158
  /**
104
159
  * The normalized configuration options
@@ -108,7 +163,9 @@ var Config = class {
108
163
  ignorePaths: this._ignorePaths,
109
164
  includePaths: this._includePaths,
110
165
  legacyTemplates: this._legacyTemplates,
111
- cache: this._cache
166
+ cache: this._cache,
167
+ flagAsExternal: this._flagAsExternal,
168
+ rootPath: this._rootPath
112
169
  };
113
170
  }
114
171
  /**
@@ -118,7 +175,9 @@ var Config = class {
118
175
  return {
119
176
  ignorePaths: this._ignorePaths,
120
177
  includePaths: this._includePaths,
121
- cache: this._cache
178
+ cache: this._cache,
179
+ flagAsExternal: this._flagAsExternal,
180
+ rootPath: this._rootPath
122
181
  };
123
182
  }
124
183
  /**
@@ -139,137 +198,8 @@ var Config = class {
139
198
 
140
199
  // src/Matcher/BaseElementsMatcher.ts
141
200
  var import_handlebars = __toESM(require("handlebars"));
142
-
143
- // src/Support/TypeGuards.ts
144
- function isString(value) {
145
- return typeof value === "string";
146
- }
147
- function isNullish(value) {
148
- return value === null || value === void 0;
149
- }
150
- function isNull(value) {
151
- return value === null;
152
- }
153
- function isBoolean(value) {
154
- return typeof value === "boolean";
155
- }
156
- function isObject(value) {
157
- return !isNullish(value) && !isBoolean(value) && !isArray(value) && typeof value === "object";
158
- }
159
- function isEmptyObject(obj) {
160
- return isObject(obj) && Object.keys(obj).length === 0;
161
- }
162
- function isArray(value) {
163
- return Array.isArray(value);
164
- }
165
- function isEmptyArray(arr) {
166
- return arr.length === 0;
167
- }
168
- function isStringArray(value) {
169
- return isArray(value) && value.every(isString);
170
- }
171
- function isObjectWithProperty(value, key) {
172
- return isObject(value) && Object.hasOwn(value, key);
173
- }
174
- function isObjectWithAnyOfProperties(value, keys) {
175
- return isObject(value) && keys.some((key) => key in value);
176
- }
177
-
178
- // src/Matcher/MatcherHelpers.ts
179
- function isCapturedValuesSelector(value) {
180
- if (!isObject(value) || isArray(value)) {
181
- return false;
182
- }
183
- return Object.values(value).every(
184
- (pattern) => isString(pattern) || isStringArray(pattern)
185
- );
186
- }
187
- function isSimpleElementSelectorByType(value) {
188
- return isString(value);
189
- }
190
- function isBaseElementSelectorData(value) {
191
- return isObjectWithAnyOfProperties(value, [
192
- "path",
193
- "elementPath",
194
- "internalPath",
195
- "type",
196
- "category",
197
- "captured",
198
- "origin",
199
- "source",
200
- "baseSource",
201
- "isIgnored",
202
- "isUnknown"
203
- ]);
204
- }
205
- function isElementSelectorData(value) {
206
- return isBaseElementSelectorData(value) || isObjectWithAnyOfProperties(value, [
207
- "relationship",
208
- "kind",
209
- "specifiers",
210
- "nodeKind"
211
- ]);
212
- }
213
- function isElementSelectorWithLegacyOptions(value) {
214
- return isArray(value) && (value.length === 2 && isSimpleElementSelectorByType(value[0]) && // NOTE: Arrays of length 2 with captured values selector as second element having a key "type" or "category" will be treated as legacy options instead of two different selectors. We have to live with this limitation for now.
215
- isCapturedValuesSelector(value[1]) || // NOTE: Backwards compatibility: Allow arrays of length 1 with simple element selector. Some users might defined arrays without options.
216
- value.length === 1 && isSimpleElementSelectorByType(value[0]));
217
- }
218
- function isElementSelector(value) {
219
- return isSimpleElementSelectorByType(value) || isElementSelectorData(value) || isElementSelectorWithLegacyOptions(value);
220
- }
221
- function isElementsSelector(value) {
222
- return isElementSelector(value) || isArray(value) && !isEmptyArray(value) && value.every(isElementSelector);
223
- }
224
- function isDependencySelector(value) {
225
- return isObjectWithAnyOfProperties(value, ["from", "to"]);
226
- }
227
- function isExternalLibrarySelectorOptionsWithPath(value) {
228
- return isObjectWithProperty(value, "path") && (isString(value.path) || isStringArray(value.path));
229
- }
230
- function isExternalLibrarySelectorOptionsWithSpecifiers(value) {
231
- return isObjectWithProperty(value, "specifiers") && isStringArray(value.specifiers);
232
- }
233
- function isExternalLibrarySelectorOptions(value) {
234
- return isExternalLibrarySelectorOptionsWithPath(value) || isExternalLibrarySelectorOptionsWithSpecifiers(value);
235
- }
236
- function isExternalLibrarySelectorWithOptions(value) {
237
- return isArray(value) && value.length === 2 && isSimpleElementSelectorByType(value[0]) && isExternalLibrarySelectorOptions(value[1]);
238
- }
239
- function isExternalLibrarySelector(value) {
240
- return isSimpleElementSelectorByType(value) || isExternalLibrarySelectorWithOptions(value);
241
- }
242
- function isExternalLibrariesSelector(value) {
243
- return isExternalLibrarySelector(value) || isArray(value) && !isEmptyArray(value) && value.every(isExternalLibrarySelector);
244
- }
245
-
246
- // src/Matcher/BaseElementsMatcher.ts
247
- var HANDLEBARS_TEMPLATE_REGEX = /{{\s*[^}\s]+(?:\s+[^}\s]+)*\s*}}/;
248
201
  var LEGACY_TEMPLATE_REGEX = /\$\{([^}]+)\}/g;
249
- function normalizeSelector(selector) {
250
- if (isSimpleElementSelectorByType(selector)) {
251
- return { type: selector };
252
- }
253
- if (isElementSelectorData(selector)) {
254
- return { ...selector };
255
- }
256
- if (isElementSelectorWithLegacyOptions(selector)) {
257
- return {
258
- type: selector[0],
259
- captured: selector[1] ? { ...selector[1] } : void 0
260
- };
261
- }
262
- throw new Error("Invalid element selector");
263
- }
264
- function normalizeElementsSelector(elementsSelector) {
265
- if (isArray(elementsSelector)) {
266
- if (isElementSelectorWithLegacyOptions(elementsSelector)) {
267
- return [normalizeSelector(elementsSelector)];
268
- }
269
- return elementsSelector.map((sel) => normalizeSelector(sel));
270
- }
271
- return [normalizeSelector(elementsSelector)];
272
- }
202
+ var HANDLEBARS_TEMPLATE_REGEX = /{{\s*[^{}\s][^{}]*}}/;
273
203
  var BaseElementsMatcher = class {
274
204
  /**
275
205
  * Option to use legacy templates with ${} syntax.
@@ -294,6 +224,9 @@ var BaseElementsMatcher = class {
294
224
  * @returns The converted template.
295
225
  */
296
226
  _getBackwardsCompatibleTemplate(template) {
227
+ if (!template) {
228
+ return template;
229
+ }
297
230
  return template.replaceAll(LEGACY_TEMPLATE_REGEX, "{{ $1 }}");
298
231
  }
299
232
  /**
@@ -302,6 +235,9 @@ var BaseElementsMatcher = class {
302
235
  * @returns True if the template contains Handlebars syntax, false otherwise.
303
236
  */
304
237
  _isHandlebarsTemplate(template) {
238
+ if (!template) {
239
+ return false;
240
+ }
305
241
  return HANDLEBARS_TEMPLATE_REGEX.test(template);
306
242
  }
307
243
  /**
@@ -333,6 +269,14 @@ var BaseElementsMatcher = class {
333
269
  }
334
270
  return this._getRenderedTemplate(template, templateData);
335
271
  }
272
+ /**
273
+ * Cleans a micromatch pattern by removing falsy values from arrays.
274
+ * @param pattern The micromatch pattern(s) to clean.
275
+ * @returns The cleaned pattern. If an array is provided, falsy entries are removed and the resulting array may be empty. If null is provided, null is returned unchanged.
276
+ */
277
+ cleanMicromatchPattern(pattern) {
278
+ return isArray(pattern) ? pattern.filter(Boolean) : pattern;
279
+ }
336
280
  /**
337
281
  * Returns whether the given value matches the micromatch pattern, converting non-string values to strings.
338
282
  * Optimized version with caching for better performance.
@@ -341,9 +285,18 @@ var BaseElementsMatcher = class {
341
285
  * @returns Whether the value matches the pattern.
342
286
  */
343
287
  isMicromatchMatch(value, pattern) {
288
+ if (isNull(pattern)) {
289
+ return isNull(value);
290
+ }
291
+ if (isNull(value)) {
292
+ return isArray(pattern) && pattern.some(isNull);
293
+ }
294
+ const patternToCheck = this.cleanMicromatchPattern(pattern);
295
+ if (!patternToCheck?.length) {
296
+ return false;
297
+ }
344
298
  const elementValueToCheck = !value || !isString(value) ? String(value) : value;
345
- const selectorValueToCheck = isArray(pattern) ? pattern.filter(Boolean) : pattern;
346
- return this.micromatch.isMatch(elementValueToCheck, selectorValueToCheck);
299
+ return this.micromatch.isMatch(elementValueToCheck, patternToCheck);
347
300
  }
348
301
  /**
349
302
  * Returns whether the given value matches the micromatch pattern after rendering it as a template.
@@ -353,18 +306,17 @@ var BaseElementsMatcher = class {
353
306
  * @returns Whether the value matches the rendered pattern.
354
307
  */
355
308
  isTemplateMicromatchMatch(pattern, templateData, value) {
356
- if (isNullish(value)) {
309
+ if (isUndefined(value)) {
357
310
  return false;
358
311
  }
359
312
  const patternRendered = this.getRenderedTemplates(pattern, templateData);
360
- if (!patternRendered) {
313
+ if (!isNull(patternRendered) && !patternRendered) {
361
314
  return false;
362
315
  }
363
- const filteredPattern = isArray(patternRendered) ? patternRendered.filter(Boolean) : patternRendered;
364
316
  if (isArray(value)) {
365
- return value.some((val) => this.isMicromatchMatch(val, filteredPattern));
317
+ return value.some((val) => this.isMicromatchMatch(val, patternRendered));
366
318
  }
367
- return this.isMicromatchMatch(value, filteredPattern);
319
+ return this.isMicromatchMatch(value, patternRendered);
368
320
  }
369
321
  /**
370
322
  * Whether the given element key matches the selector key as booleans.
@@ -408,20 +360,113 @@ var BaseElementsMatcher = class {
408
360
  if (!(selectorKey in selector)) {
409
361
  return true;
410
362
  }
411
- if (!selectorValue) {
412
- return false;
413
- }
414
- if (!isObjectWithProperty(element, elementKey)) {
363
+ if (isUndefined(selectorValue) || !isObjectWithProperty(element, String(elementKey))) {
415
364
  return false;
416
365
  }
366
+ const elementValue = element[String(elementKey)];
417
367
  return this.isTemplateMicromatchMatch(
418
368
  selectorValue,
419
369
  templateData,
420
- element[elementKey]
370
+ elementValue
421
371
  );
422
372
  }
423
373
  };
424
374
 
375
+ // src/Matcher/MatcherHelpers.ts
376
+ function isCapturedValuesObjectSelector(value) {
377
+ if (!isObject(value) || isArray(value)) {
378
+ return false;
379
+ }
380
+ return Object.values(value).every(
381
+ (pattern) => isString(pattern) || isStringArray(pattern)
382
+ );
383
+ }
384
+ function isCapturedValuesSelector(value) {
385
+ if (isArray(value)) {
386
+ return value.every((item) => isCapturedValuesObjectSelector(item));
387
+ }
388
+ return isCapturedValuesObjectSelector(value);
389
+ }
390
+ function isSimpleElementSelectorByType(value) {
391
+ return isString(value);
392
+ }
393
+ function isBaseElementSelectorData(value) {
394
+ return isObjectWithAnyOfProperties(value, [
395
+ "path",
396
+ "elementPath",
397
+ "internalPath",
398
+ "type",
399
+ "category",
400
+ "captured",
401
+ "parent",
402
+ "origin",
403
+ "source",
404
+ "module",
405
+ "isIgnored",
406
+ "isUnknown"
407
+ ]);
408
+ }
409
+ function isElementSelectorData(value) {
410
+ return isBaseElementSelectorData(value);
411
+ }
412
+ function isElementSelectorWithLegacyOptions(value) {
413
+ 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.
414
+ isCapturedValuesSelector(value[1]) || // NOTE: Backwards compatibility: Allow arrays of length 1 with simple element selector. Some users might defined arrays without options.
415
+ value.length === 1 && isSimpleElementSelectorByType(value[0]));
416
+ }
417
+ function isElementSelector(value) {
418
+ return isSimpleElementSelectorByType(value) || isElementSelectorData(value) || isElementSelectorWithLegacyOptions(value);
419
+ }
420
+ function isElementsSelector(value) {
421
+ return isElementSelector(value) || isArray(value) && !isEmptyArray(value) && value.every(isElementSelector);
422
+ }
423
+ function normalizeElementSelector(selector) {
424
+ if (isSimpleElementSelectorByType(selector)) {
425
+ return { type: selector };
426
+ }
427
+ if (isElementSelectorData(selector)) {
428
+ return { ...selector };
429
+ }
430
+ if (isElementSelectorWithLegacyOptions(selector)) {
431
+ return {
432
+ type: selector[0],
433
+ captured: selector[1] ? { ...selector[1] } : void 0
434
+ };
435
+ }
436
+ throw new Error("Invalid element selector");
437
+ }
438
+ function normalizeElementsSelector(elementsSelector) {
439
+ if (isArray(elementsSelector)) {
440
+ if (isElementSelectorWithLegacyOptions(elementsSelector)) {
441
+ return [normalizeElementSelector(elementsSelector)];
442
+ }
443
+ return elementsSelector.map((sel) => normalizeElementSelector(sel));
444
+ }
445
+ return [normalizeElementSelector(elementsSelector)];
446
+ }
447
+ function isDependencySelector(value) {
448
+ if (!isObjectWithAnyOfProperties(value, ["from", "to", "dependency"])) {
449
+ return false;
450
+ }
451
+ const fromIsValid = !isObjectWithProperty(value, "from") || isElementsSelector(value.from);
452
+ const toIsValid = !isObjectWithProperty(value, "to") || isElementsSelector(value.to);
453
+ const dependencyIsValid = !isObjectWithProperty(value, "dependency") || isDependencyDataSelector(value.dependency);
454
+ return fromIsValid && toIsValid && dependencyIsValid;
455
+ }
456
+ function isDependencyDataSelectorData(value) {
457
+ return isObjectWithAnyOfProperties(value, [
458
+ "kind",
459
+ "relationship",
460
+ "specifiers",
461
+ "nodeKind",
462
+ "source",
463
+ "module"
464
+ ]);
465
+ }
466
+ function isDependencyDataSelector(value) {
467
+ return isDependencyDataSelectorData(value) || isArray(value) && !isEmptyArray(value) && value.every(isDependencyDataSelectorData);
468
+ }
469
+
425
470
  // src/Matcher/DependenciesMatcher.ts
426
471
  var DependenciesMatcher = class extends BaseElementsMatcher {
427
472
  /**
@@ -444,68 +489,20 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
444
489
  * @param selector The dependency selector to normalize.
445
490
  * @returns The normalized dependency selector.
446
491
  */
447
- _normalizeDependencySelector(selector, dependencySelectorsGlobals) {
492
+ _normalizeDependencySelector(selector) {
448
493
  if (!isDependencySelector(selector)) {
449
494
  throw new Error("Invalid dependency selector");
450
495
  }
451
- let normalizedDependencySelectors = selector.to ? normalizeElementsSelector(selector.to) : null;
452
- if (normalizedDependencySelectors) {
453
- normalizedDependencySelectors = normalizedDependencySelectors.map(
454
- (depSelector) => {
455
- return {
456
- ...dependencySelectorsGlobals,
457
- ...depSelector
458
- };
459
- }
460
- );
496
+ let normalizedDependencySelectors = null;
497
+ if (selector.dependency && isDependencyDataSelector(selector.dependency)) {
498
+ normalizedDependencySelectors = isArray(selector.dependency) ? selector.dependency : [selector.dependency];
461
499
  }
462
500
  return {
463
501
  from: selector.from ? normalizeElementsSelector(selector.from) : null,
464
- to: normalizedDependencySelectors
502
+ to: selector.to ? normalizeElementsSelector(selector.to) : null,
503
+ dependency: normalizedDependencySelectors
465
504
  };
466
505
  }
467
- /**
468
- * Converts a DependencyElementSelectorData to a BaseElementSelectorData, by removing dependency-specific properties.
469
- * @param selector The dependency element selector data.
470
- * @returns The base element selector data.
471
- */
472
- _convertDependencyElementSelectorDataToBaseElementSelectorData(selector) {
473
- const baseSelector = {};
474
- if (selector.type) {
475
- baseSelector.type = selector.type;
476
- }
477
- if (selector.category) {
478
- baseSelector.category = selector.category;
479
- }
480
- if (selector.path) {
481
- baseSelector.path = selector.path;
482
- }
483
- if (selector.elementPath) {
484
- baseSelector.elementPath = selector.elementPath;
485
- }
486
- if (selector.internalPath) {
487
- baseSelector.internalPath = selector.internalPath;
488
- }
489
- if (selector.captured) {
490
- baseSelector.captured = selector.captured;
491
- }
492
- if (selector.origin) {
493
- baseSelector.origin = selector.origin;
494
- }
495
- if (selector.baseSource) {
496
- baseSelector.baseSource = selector.baseSource;
497
- }
498
- if (selector.source) {
499
- baseSelector.source = selector.source;
500
- }
501
- if (!isNullish(selector.isIgnored)) {
502
- baseSelector.isIgnored = selector.isIgnored;
503
- }
504
- if (!isNullish(selector.isUnknown)) {
505
- baseSelector.isUnknown = selector.isUnknown;
506
- }
507
- return baseSelector;
508
- }
509
506
  /**
510
507
  * Returns the selectors matching result for the given dependency.
511
508
  * @param dependency The dependency description.
@@ -513,56 +510,37 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
513
510
  * @param extraTemplateData The extra template data for selector values.
514
511
  * @returns The selectors matching result for the given dependency.
515
512
  */
516
- _getSelectorMatching(dependency, selector, templateData) {
517
- const getFromSelectorMatching = () => {
518
- for (const fromSelectorData of selector.from) {
519
- const fromMatch = this._elementsMatcher.isElementMatch(
520
- dependency.from,
521
- fromSelectorData,
522
- {
523
- extraTemplateData: templateData
524
- }
525
- );
526
- const dependencyPropertiesMatch = this._dependencyFromPropertiesMatch(
513
+ _getSelectorsMatching(dependency, selector, templateData) {
514
+ const getDependencyMetadataSelectorMatching = () => {
515
+ for (const dependencySelectorData of selector.dependency) {
516
+ const dependencyPropertiesMatch = this._dependencyPropertiesMatch(
527
517
  dependency,
528
- [fromSelectorData],
518
+ dependencySelectorData,
529
519
  templateData
530
520
  );
531
- if (fromMatch && dependencyPropertiesMatch) {
532
- return fromSelectorData;
521
+ if (dependencyPropertiesMatch) {
522
+ return dependencySelectorData;
533
523
  }
534
524
  }
535
525
  return null;
536
526
  };
537
- const getToSelectorMatching = () => {
538
- for (const toSelectorData of selector.to) {
539
- const toMatch = isBaseElementSelectorData(toSelectorData) ? this._elementsMatcher.isElementMatch(
540
- dependency.to,
541
- this._convertDependencyElementSelectorDataToBaseElementSelectorData(
542
- toSelectorData
543
- ),
544
- {
545
- extraTemplateData: templateData
546
- }
547
- ) : true;
548
- const dependencyPropertiesMatch = this._dependencyToPropertiesMatch(
549
- dependency,
550
- [toSelectorData],
551
- templateData
552
- );
553
- if (toMatch && dependencyPropertiesMatch) {
554
- return toSelectorData;
555
- }
527
+ const fromSelectorMatching = selector.from ? this._elementsMatcher.getSelectorMatching(
528
+ dependency.from,
529
+ selector.from,
530
+ {
531
+ extraTemplateData: templateData
556
532
  }
557
- return null;
558
- };
559
- const fromSelectorMatching = selector.from ? getFromSelectorMatching() : null;
560
- const toSelectorMatching = selector.to ? getToSelectorMatching() : null;
533
+ ) : null;
534
+ const toSelectorMatching = selector.to ? this._elementsMatcher.getSelectorMatching(dependency.to, selector.to, {
535
+ extraTemplateData: templateData
536
+ }) : null;
537
+ const dependencyMetadataSelectorMatching = selector.dependency ? getDependencyMetadataSelectorMatching() : null;
561
538
  return {
562
539
  from: fromSelectorMatching,
563
540
  to: toSelectorMatching,
541
+ dependency: dependencyMetadataSelectorMatching,
564
542
  isMatch: Boolean(
565
- (selector.from ? fromSelectorMatching : true) && (selector.to ? toSelectorMatching : true)
543
+ (selector.from ? fromSelectorMatching : true) && (selector.to ? toSelectorMatching : true) && (selector.dependency ? dependencyMetadataSelectorMatching : true)
566
544
  )
567
545
  };
568
546
  }
@@ -572,12 +550,29 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
572
550
  * @param selector The data of an element selector.
573
551
  * @returns Whether the dependency relationship matches the selector.
574
552
  */
575
- _relationshipMatches(selector, relationship, templateData) {
576
- if (!selector.relationship) {
553
+ _relationshipFromMatches(selector, relationship, templateData) {
554
+ if (!selector.relationship?.from) {
577
555
  return true;
578
556
  }
579
557
  return this.isTemplateMicromatchMatch(
580
- selector.relationship,
558
+ selector.relationship.from,
559
+ templateData,
560
+ relationship
561
+ );
562
+ }
563
+ /**
564
+ * Determines if the dependency origin relationship matches the selector.
565
+ * @param selector The dependency selector data.
566
+ * @param relationship The relationship from origin element to target element.
567
+ * @param templateData The template data for rendering selector values.
568
+ * @returns Whether the dependency origin relationship matches.
569
+ */
570
+ _relationshipToMatches(selector, relationship, templateData) {
571
+ if (!selector.relationship?.to) {
572
+ return true;
573
+ }
574
+ return this.isTemplateMicromatchMatch(
575
+ selector.relationship.to,
581
576
  templateData,
582
577
  relationship
583
578
  );
@@ -630,75 +625,85 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
630
625
  );
631
626
  }
632
627
  /**
633
- * Determines if the dependency description matches the selector for 'from'.
628
+ * Determines if the dependency description matches the selector for 'to'.
634
629
  * @param dependency The dependency description.
635
- * @param fromSelector The selector for 'from' elements.
630
+ * @param toSelector The selector for 'to' elements.
636
631
  * @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
- )
632
+ * @returns Whether the dependency properties match the selector for 'to'.
633
+ */
634
+ _sourceMatches(selector, source, templateData) {
635
+ if (!selector.source) {
636
+ return true;
637
+ }
638
+ return this.isTemplateMicromatchMatch(
639
+ selector.source,
640
+ templateData,
641
+ source
646
642
  );
647
643
  }
648
644
  /**
649
- * Determines if the dependency description matches the selector for 'to'.
645
+ * Determines if the selector matches the module
646
+ * @param selector The dependency selector data
647
+ * @param module The module to check
648
+ * @param templateData The template data for rendering selector values
649
+ * @returns Whether the selector matches the module
650
+ */
651
+ _moduleMatches(selector, dependencyModule, templateData) {
652
+ if (!selector.module) {
653
+ return true;
654
+ }
655
+ return this.isTemplateMicromatchMatch(
656
+ selector.module,
657
+ templateData,
658
+ dependencyModule
659
+ );
660
+ }
661
+ /**
662
+ * Determines if the dependency description matches the selector for dependency metadata.
650
663
  * @param dependency The dependency description.
651
- * @param toSelector The selector for 'to' elements.
664
+ * @param selectorData The selector for dependency metadata.
652
665
  * @param templateData The template data for rendering selector values
653
- * @returns Whether the dependency properties match the selector for 'to'.
666
+ * @returns Whether the dependency properties match the selector.
654
667
  */
655
- _dependencyToPropertiesMatch(dependency, toSelector, templateData) {
668
+ _dependencyPropertiesMatch(dependency, selectorData, templateData) {
656
669
  const dependencyInfo = dependency.dependency;
670
+ const relationshipFrom = dependencyInfo.relationship.from;
657
671
  const relationshipTo = dependencyInfo.relationship.to;
658
672
  const kind = dependencyInfo.kind;
659
673
  const nodeKind = dependencyInfo.nodeKind;
660
674
  const specifiers = dependencyInfo.specifiers;
661
- for (const selectorData of toSelector) {
662
- if (this._kindMatches(selectorData, kind, templateData) && this._nodeKindMatches(selectorData, nodeKind, templateData) && this._relationshipMatches(selectorData, relationshipTo, templateData) && this._specifierMatches(selectorData, specifiers, templateData)) {
663
- return true;
664
- }
665
- }
666
- return false;
675
+ const source = dependencyInfo.source;
676
+ const dependencyModule = dependencyInfo.module;
677
+ return this._kindMatches(selectorData, kind, templateData) && this._nodeKindMatches(selectorData, nodeKind, templateData) && this._sourceMatches(selectorData, source, templateData) && this._moduleMatches(selectorData, dependencyModule, templateData) && this._relationshipFromMatches(
678
+ selectorData,
679
+ relationshipFrom,
680
+ templateData
681
+ ) && this._relationshipToMatches(selectorData, relationshipTo, templateData) && this._specifierMatches(selectorData, specifiers, templateData);
667
682
  }
668
683
  /**
669
684
  * Returns the selectors matching result for the given dependency.
670
685
  * @param dependency The dependency to check.
671
686
  * @param selector The selector to check against.
672
- * @param options Extra options for matching, such as templates data, globals for dependency selectors, etc.
687
+ * @param options Extra options for matching, such as templates data, etc.
673
688
  * @returns The matching result for the dependency against the selector.
674
689
  */
675
- getSelectorsMatching(dependency, selector, {
676
- extraTemplateData = {},
677
- dependencySelectorsGlobals = {}
678
- } = {}) {
679
- const normalizedSelector = this._normalizeDependencySelector(
680
- selector,
681
- dependencySelectorsGlobals
682
- );
690
+ getSelectorsMatching(dependency, selector, { extraTemplateData = {} } = {}) {
691
+ const normalizedSelector = this._normalizeDependencySelector(selector);
683
692
  const fromExtraData = extraTemplateData.from || {};
684
693
  const toExtraData = extraTemplateData.to || {};
685
694
  const templateData = {
686
695
  ...extraTemplateData,
687
696
  from: {
688
697
  ...dependency.from,
689
- relationship: dependency.dependency.relationship.from,
690
698
  ...fromExtraData
691
699
  },
692
700
  to: {
693
701
  ...dependency.to,
694
- relationship: dependency.dependency.relationship.to,
695
- kind: dependency.dependency.kind,
696
- nodeKind: dependency.dependency.nodeKind,
697
- specifiers: dependency.dependency.specifiers,
698
702
  ...toExtraData
699
- }
703
+ },
704
+ dependency: dependency.dependency
700
705
  };
701
- const result = this._getSelectorMatching(
706
+ const result = this._getSelectorsMatching(
702
707
  dependency,
703
708
  normalizedSelector,
704
709
  templateData
@@ -709,7 +714,7 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
709
714
  * Returns whether the given dependency matches the selector.
710
715
  * @param dependency The dependency to check.
711
716
  * @param selector The selector to check against.
712
- * @param options Extra options for matching, such as templates data, globals for dependency selectors, etc.
717
+ * @param options Extra options for matching, such as templates data, etc.
713
718
  * @returns Whether the dependency matches the selector properties.
714
719
  */
715
720
  isDependencyMatch(dependency, selector, options) {
@@ -724,8 +729,6 @@ var DependenciesMatcher = class extends BaseElementsMatcher {
724
729
 
725
730
  // src/Matcher/ElementsMatcher.ts
726
731
  var ElementsMatcher = class extends BaseElementsMatcher {
727
- /** Whether the cache is enabled or not */
728
- _cacheIsEnabled;
729
732
  /**
730
733
  * Creates a new ElementsSelectorMatcher.
731
734
  * @param config Configuration options for the matcher.
@@ -838,41 +841,36 @@ var ElementsMatcher = class extends BaseElementsMatcher {
838
841
  });
839
842
  }
840
843
  /**
841
- * Whether the given element baseSource matches the selector baseSource
842
- * @param element The element to check.
843
- * @param selector The selector to check against.
844
- * @param templateData The data to use for replace in selector value
845
- * @returns Whether the element baseSource matches the selector baseSource.
846
- */
847
- _isBaseSourceMatch(element, selector, templateData) {
848
- return this.isElementKeyMicromatchMatch({
849
- element,
850
- selector,
851
- elementKey: "baseSource",
852
- selectorKey: "baseSource",
853
- selectorValue: selector.baseSource,
854
- templateData
855
- });
856
- }
857
- /**
858
- * Whether the given element source matches the selector source
859
- * @param element The element to check.
860
- * @param selector The selector to check against.
861
- * @param templateData The data to use for replace in selector value
862
- * @returns Whether the element source matches the selector source.
844
+ * Checks if a single captured values object matches the element.
845
+ * @param capturedValues The captured values to check.
846
+ * @param capturedSelector The captured values selector object to check against
847
+ * @param templateData The data to use for replace in selector values
848
+ * @returns True if all captured values in the selector match those in the element, false otherwise.
863
849
  */
864
- _isSourceMatch(element, selector, templateData) {
865
- return this.isElementKeyMicromatchMatch({
866
- element,
867
- selector,
868
- elementKey: "source",
869
- selectorKey: "source",
870
- selectorValue: selector.source,
871
- templateData
872
- });
850
+ _checkCapturedValuesObject(capturedValues, capturedSelector, templateData) {
851
+ if (!capturedValues) {
852
+ return false;
853
+ }
854
+ for (const [key, pattern] of Object.entries(capturedSelector)) {
855
+ const elementValue = capturedValues[key];
856
+ if (!elementValue) {
857
+ return false;
858
+ }
859
+ const renderedPattern = this.getRenderedTemplates(pattern, templateData);
860
+ const filteredPattern = this.cleanMicromatchPattern(renderedPattern);
861
+ if (!filteredPattern) {
862
+ return false;
863
+ }
864
+ const isMatch = this.micromatch.isMatch(elementValue, filteredPattern);
865
+ if (!isMatch) {
866
+ return false;
867
+ }
868
+ }
869
+ return true;
873
870
  }
874
871
  /**
875
872
  * Determines if the captured values of the element match those in the selector.
873
+ * When the selector is an array, the element matches if it matches any of the array elements (OR logic).
876
874
  * @param element The element to check.
877
875
  * @param selector The selector to check against
878
876
  * @param templateData The data to use for replace in selector values
@@ -882,23 +880,98 @@ var ElementsMatcher = class extends BaseElementsMatcher {
882
880
  if (!selector.captured || isEmptyObject(selector.captured)) {
883
881
  return true;
884
882
  }
885
- if (!element.captured) {
886
- return false;
887
- }
888
- for (const [key, pattern] of Object.entries(selector.captured)) {
889
- const elementValue = element.captured?.[key];
890
- if (!elementValue) {
883
+ if (isArray(selector.captured)) {
884
+ if (selector.captured.length === 0) {
891
885
  return false;
892
886
  }
893
- const renderedPattern = this.getRenderedTemplates(pattern, templateData);
894
- if (!renderedPattern) {
895
- return false;
896
- }
897
- const filteredPattern = isArray(renderedPattern) ? renderedPattern.filter(Boolean) : renderedPattern;
898
- const isMatch = this.micromatch.isMatch(elementValue, filteredPattern);
899
- if (!isMatch) {
887
+ return selector.captured.some(
888
+ (capturedSelector) => this._checkCapturedValuesObject(
889
+ element.captured,
890
+ capturedSelector,
891
+ templateData
892
+ )
893
+ );
894
+ }
895
+ return this._checkCapturedValuesObject(
896
+ element.captured,
897
+ selector.captured,
898
+ templateData
899
+ );
900
+ }
901
+ /**
902
+ * Determines if the parent captured values match the selector.
903
+ * @param parentSelector The parent selector to match.
904
+ * @param parentCaptured The captured values from first parent.
905
+ * @param templateData The data to use for replace in selector values
906
+ * @returns True if the captured values match, false otherwise.
907
+ */
908
+ _isParentCapturedValuesMatch(parentSelector, parentCaptured, templateData) {
909
+ if (!parentSelector.captured || isEmptyObject(parentSelector.captured)) {
910
+ return true;
911
+ }
912
+ if (isArray(parentSelector.captured)) {
913
+ if (parentSelector.captured.length === 0) {
900
914
  return false;
901
915
  }
916
+ return parentSelector.captured.some(
917
+ (capturedSelector) => this._checkCapturedValuesObject(
918
+ parentCaptured,
919
+ capturedSelector,
920
+ templateData
921
+ )
922
+ );
923
+ }
924
+ return this._checkCapturedValuesObject(
925
+ parentCaptured,
926
+ parentSelector.captured,
927
+ templateData
928
+ );
929
+ }
930
+ /**
931
+ * Whether the given element first parent matches the selector parent.
932
+ * @param element The element to check.
933
+ * @param selector The selector to check against.
934
+ * @param templateData The data to use for replace in selector values
935
+ * @returns Whether the first parent matches the selector parent.
936
+ */
937
+ _isParentMatch(element, selector, templateData) {
938
+ if (isUndefined(selector.parent)) {
939
+ return true;
940
+ }
941
+ if (isNull(selector.parent)) {
942
+ return !element.parents || element.parents.length === 0;
943
+ }
944
+ const firstParent = element.parents?.[0];
945
+ if (!firstParent) {
946
+ return false;
947
+ }
948
+ if (!isUndefined(selector.parent.type) && !this.isTemplateMicromatchMatch(
949
+ selector.parent.type,
950
+ templateData,
951
+ firstParent.type
952
+ )) {
953
+ return false;
954
+ }
955
+ if (!isUndefined(selector.parent.category) && !this.isTemplateMicromatchMatch(
956
+ selector.parent.category,
957
+ templateData,
958
+ firstParent.category
959
+ )) {
960
+ return false;
961
+ }
962
+ if (!isUndefined(selector.parent.elementPath) && !this.isTemplateMicromatchMatch(
963
+ selector.parent.elementPath,
964
+ templateData,
965
+ firstParent.elementPath
966
+ )) {
967
+ return false;
968
+ }
969
+ if (!this._isParentCapturedValuesMatch(
970
+ selector.parent,
971
+ firstParent.captured,
972
+ templateData
973
+ )) {
974
+ return false;
902
975
  }
903
976
  return true;
904
977
  }
@@ -943,7 +1016,7 @@ var ElementsMatcher = class extends BaseElementsMatcher {
943
1016
  ...extraTemplateData
944
1017
  };
945
1018
  for (const selectorData of selectorsData) {
946
- if (!this._isTypeMatch(element, selectorData, templateData) || !this._isCategoryMatch(element, selectorData, templateData) || !this._isOriginMatch(element, selectorData, templateData) || !this._isIgnoredMatch(element, selectorData) || !this._isUnknownMatch(element, selectorData) || !this._isPathMatch(element, selectorData, templateData) || !this._isElementPathMatch(element, selectorData, templateData) || !this._isInternalPathMatch(element, selectorData, templateData) || !this._isSourceMatch(element, selectorData, templateData) || !this._isBaseSourceMatch(element, selectorData, templateData) || !this._isCapturedValuesMatch(element, selectorData, templateData)) {
1019
+ if (!this._isTypeMatch(element, selectorData, templateData) || !this._isCategoryMatch(element, selectorData, templateData) || !this._isOriginMatch(element, selectorData, templateData) || !this._isIgnoredMatch(element, selectorData) || !this._isUnknownMatch(element, selectorData) || !this._isPathMatch(element, selectorData, templateData) || !this._isElementPathMatch(element, selectorData, templateData) || !this._isInternalPathMatch(element, selectorData, templateData) || !this._isCapturedValuesMatch(element, selectorData, templateData) || !this._isParentMatch(element, selectorData, templateData)) {
947
1020
  continue;
948
1021
  }
949
1022
  return selectorData;
@@ -955,7 +1028,7 @@ var ElementsMatcher = class extends BaseElementsMatcher {
955
1028
  * It omits checks in keys applying only to dependency between elements, such as relationship.
956
1029
  * @param element The element to check.
957
1030
  * @param selector The selector to check against.
958
- * @param options Extra options for matching, such as templates data, globals for dependency selectors, etc.
1031
+ * @param options Extra options for matching, such as templates data, etc.
959
1032
  * @returns The selector matching result for the given element, or null if none matches.
960
1033
  */
961
1034
  getSelectorMatching(element, selector, { extraTemplateData = {} } = {}) {
@@ -967,7 +1040,7 @@ var ElementsMatcher = class extends BaseElementsMatcher {
967
1040
  * It omits checks in keys applying only to dependency between elements, such as relationship.
968
1041
  * @param element The element to check.
969
1042
  * @param selector The selector to check against.
970
- * @param options Extra options for matching, such as templates data, globals for dependency selectors, etc.
1043
+ * @param options Extra options for matching, such as templates data, etc.
971
1044
  * @returns Whether the element matches the selector properties applying to elements.
972
1045
  */
973
1046
  isElementMatch(element, selector, options) {
@@ -1034,20 +1107,17 @@ function isUnknownLocalElement(value) {
1034
1107
  function isKnownLocalElement(value) {
1035
1108
  return isLocalElement(value) && value.isUnknown === false;
1036
1109
  }
1037
- function isDependencyElementDescription(value) {
1038
- return isBaseElement(value) && isObjectWithProperty(value, "source") && isString(value.source);
1039
- }
1040
- function isElementDescription(value) {
1041
- return isIgnoredElement(value) || isUnknownLocalElement(value) || isKnownLocalElement(value) || isDependencyElementDescription(value);
1042
- }
1043
1110
  function isLocalDependencyElement(value) {
1044
- return isDependencyElementDescription(value) && isLocalElement(value);
1111
+ return isLocalElement(value) && value.isIgnored === false;
1045
1112
  }
1046
1113
  function isExternalDependencyElement(value) {
1047
- return isDependencyElementDescription(value) && value.origin === ELEMENT_ORIGINS_MAP.EXTERNAL && isObjectWithProperty(value, "baseSource") && isString(value.baseSource);
1114
+ return isBaseElement(value) && value.origin === ELEMENT_ORIGINS_MAP.EXTERNAL;
1048
1115
  }
1049
1116
  function isCoreDependencyElement(value) {
1050
- return isDependencyElementDescription(value) && value.origin === ELEMENT_ORIGINS_MAP.CORE && isObjectWithProperty(value, "baseSource") && isString(value.baseSource);
1117
+ return isBaseElement(value) && value.origin === ELEMENT_ORIGINS_MAP.CORE;
1118
+ }
1119
+ function isElementDescription(value) {
1120
+ return isIgnoredElement(value) || isUnknownLocalElement(value) || isKnownLocalElement(value) || isExternalDependencyElement(value) || isCoreDependencyElement(value);
1051
1121
  }
1052
1122
 
1053
1123
  // src/Descriptor/DependenciesDescriptor.types.ts
@@ -1104,7 +1174,7 @@ function isDependencyRelationshipDescription(value) {
1104
1174
  return isObjectWithProperty(value, "to") && (isNull(value.to) || isDependencyRelationship(value.to)) && isObjectWithProperty(value, "from") && (isNull(value.from) || isDependencyRelationship(value.from));
1105
1175
  }
1106
1176
  function isElementsDependencyInfo(value) {
1107
- return isObjectWithProperty(value, "kind") && isDependencyKind(value.kind) && isObjectWithProperty(value, "relationship") && isDependencyRelationshipDescription(value.relationship) && isObjectWithProperty(value, "nodeKind") && (isNull(value.nodeKind) || isString(value.nodeKind));
1177
+ return isObjectWithProperty(value, "source") && isString(value.source) && isObjectWithProperty(value, "module") && (isNullish(value.module) || isString(value.module)) && isObjectWithProperty(value, "kind") && isDependencyKind(value.kind) && isObjectWithProperty(value, "relationship") && isDependencyRelationshipDescription(value.relationship) && isObjectWithProperty(value, "nodeKind") && (isNull(value.nodeKind) || isString(value.nodeKind)) && isObjectWithProperty(value, "specifiers") && (isNull(value.specifiers) || isStringArray(value.specifiers));
1108
1178
  }
1109
1179
  function isDependencyDescription(value) {
1110
1180
  return isObjectWithProperty(value, "to") && isElementDescription(value.to) && isObjectWithProperty(value, "from") && isElementDescription(value.from) && isObjectWithProperty(value, "dependency") && isElementsDependencyInfo(value.dependency);
@@ -1442,17 +1512,20 @@ var DependenciesDescriptor = class {
1442
1512
  return this._dependenciesCache.get(cacheKey);
1443
1513
  }
1444
1514
  const fromElement = this._elementsDescriptor.describeElement(from);
1445
- const toElement = this._elementsDescriptor.describeDependencyElement(
1446
- source,
1447
- to
1448
- );
1515
+ const toElement = this._elementsDescriptor.describeElement(to, source);
1516
+ const { module: dependencyModule, ...toElementDescription } = toElement;
1449
1517
  const result = {
1450
1518
  from: fromElement,
1451
- to: toElement,
1519
+ to: toElementDescription,
1452
1520
  dependency: {
1521
+ source,
1522
+ module: dependencyModule || null,
1453
1523
  kind,
1454
1524
  nodeKind: nodeKind || null,
1455
- relationship: this._dependencyRelationships(fromElement, toElement),
1525
+ relationship: this._dependencyRelationships(
1526
+ fromElement,
1527
+ toElementDescription
1528
+ ),
1456
1529
  specifiers: specifiers || null
1457
1530
  }
1458
1531
  };
@@ -1467,8 +1540,6 @@ var UNKNOWN_ELEMENT = {
1467
1540
  path: null,
1468
1541
  elementPath: null,
1469
1542
  internalPath: null,
1470
- source: null,
1471
- baseSource: null,
1472
1543
  parents: null,
1473
1544
  type: null,
1474
1545
  category: null,
@@ -1570,8 +1641,8 @@ var ElementsDescriptor = class {
1570
1641
  */
1571
1642
  _dependencySourceIsCoreModule(dependencySource, baseDependencySource) {
1572
1643
  if (this._mod) {
1573
- const baseSourceWithoutPrefix = baseDependencySource.startsWith("node:") ? baseDependencySource.slice(5) : baseDependencySource;
1574
- return this._mod.builtinModules.includes(baseSourceWithoutPrefix);
1644
+ const moduleWithoutPrefix = baseDependencySource.startsWith("node:") ? baseDependencySource.slice(5) : baseDependencySource;
1645
+ return this._mod.builtinModules.includes(moduleWithoutPrefix);
1575
1646
  }
1576
1647
  return (0, import_is_core_module.default)(dependencySource);
1577
1648
  }
@@ -1596,7 +1667,7 @@ var ElementsDescriptor = class {
1596
1667
  * @param dependencySource The source of the dependency to check.
1597
1668
  * @returns The base source of the external module. (e.g., for "@scope/package/submodule", it returns "@scope/package")
1598
1669
  */
1599
- _getExternalOrCoreModuleBaseSource(dependencySource) {
1670
+ _getExternalOrCoreModuleModule(dependencySource) {
1600
1671
  if (this._dependencySourceIsScoped(dependencySource)) {
1601
1672
  const [scope, packageName] = dependencySource.split("/");
1602
1673
  return `${scope}/${packageName}`;
@@ -1605,17 +1676,72 @@ var ElementsDescriptor = class {
1605
1676
  return pkg;
1606
1677
  }
1607
1678
  /**
1608
- * Determines if an element is external based on its file path and dependency source.
1609
- * Files inside "node_modules" are considered external.
1610
- * If the dependency source is not provided, only the file path is considered.
1611
- * If the dependency source is provided, it must not be a local path (i.e, it should start by "./", "../", or "/").
1612
- * @param filePath
1613
- * @param dependencySource
1614
- * @returns
1679
+ * Determines if a file path is outside the configured root path.
1680
+ * @param filePath The file path to check.
1681
+ * @returns True if the file path is outside the root path, false otherwise.
1682
+ */
1683
+ _isOutsideRootPath(filePath) {
1684
+ if (!this._config.rootPath) {
1685
+ return false;
1686
+ }
1687
+ return !filePath.startsWith(this._config.rootPath);
1688
+ }
1689
+ /**
1690
+ * Converts an absolute file path to a relative path if rootPath is configured.
1691
+ * If rootPath is not configured, returns the path as-is (maintains backward compatibility).
1692
+ * @param filePath The file path to convert (can be absolute or relative)
1693
+ * @returns The relative path if rootPath is configured and path is absolute, otherwise the original path
1615
1694
  */
1616
- _isExternalDependency(filePath, dependencySource) {
1617
- 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?
1618
- (!dependencySource || this._dependencySourceIsExternalOrScoped(dependencySource));
1695
+ _toRelativePath(filePath) {
1696
+ if (!this._config.rootPath || this._isOutsideRootPath(filePath)) {
1697
+ return filePath;
1698
+ }
1699
+ return filePath.replace(this._config.rootPath, "");
1700
+ }
1701
+ /**
1702
+ * Checks if a source string matches any of the provided patterns using micromatch.
1703
+ * @param patterns - Array of micromatch patterns
1704
+ * @param source - The source string to match against patterns
1705
+ * @returns True if the source matches any pattern, false otherwise
1706
+ */
1707
+ _matchesAnyPattern(patterns, source) {
1708
+ if (!source || patterns.length === 0) {
1709
+ return false;
1710
+ }
1711
+ return this._micromatch.isMatch(source, patterns);
1712
+ }
1713
+ /**
1714
+ * Determines if an element is external based on its file path and dependency source.
1715
+ * Uses the flagAsExternal configuration to evaluate multiple conditions with OR logic:
1716
+ * - unresolvableAlias: Files whose path cannot be resolved (filePath is null)
1717
+ * - inNodeModules: Non-relative paths that include "node_modules"
1718
+ * - outsideRootPath: Resolved path is outside the configured root path (only if rootPath is configured)
1719
+ * - customSourcePatterns: Source matches any of the configured patterns
1720
+ * @param filePath The resolved file path (null if unresolved). Can be absolute if rootPath is configured, or relative if rootPath is not configured.
1721
+ * @param isOutsideRootPath Whether the file path is outside the configured root path.
1722
+ * @param dependencySource The import/export source string
1723
+ * @returns True if any of the configured conditions is met, false otherwise
1724
+ */
1725
+ _isExternalDependency(filePath, isOutsideRootPath, dependencySource) {
1726
+ const {
1727
+ unresolvableAlias,
1728
+ inNodeModules,
1729
+ outsideRootPath,
1730
+ customSourcePatterns
1731
+ } = this._config.flagAsExternal;
1732
+ if (outsideRootPath && isOutsideRootPath) {
1733
+ return true;
1734
+ }
1735
+ if (inNodeModules && filePath?.includes("node_modules")) {
1736
+ return true;
1737
+ }
1738
+ if (unresolvableAlias && !filePath && dependencySource && this._dependencySourceIsExternalOrScoped(dependencySource)) {
1739
+ return true;
1740
+ }
1741
+ if (this._matchesAnyPattern(customSourcePatterns, dependencySource)) {
1742
+ return true;
1743
+ }
1744
+ return false;
1619
1745
  }
1620
1746
  /**
1621
1747
  * Determines if a given path is included based on the configuration.
@@ -1683,6 +1809,16 @@ var ElementsDescriptor = class {
1683
1809
  }
1684
1810
  return `${[...allPathSegments].reverse().join("/").split(result)[0]}${result}`;
1685
1811
  }
1812
+ /**
1813
+ * Determines if an element descriptor matches the given parameters in the provided path.
1814
+ * @param options The options for matching the descriptor.
1815
+ * @param options.elementDescriptor The element descriptor to match.
1816
+ * @param options.filePath The file path to match against the descriptor.
1817
+ * @param options.currentPathSegments The current path segments leading to the element.
1818
+ * @param options.lastPathSegmentMatching The last path segment that was matched.
1819
+ * @param options.alreadyMatched Whether the element matched previously.
1820
+ * @returns The result of the match, including whether it matched.
1821
+ */
1686
1822
  _fileDescriptorMatch({
1687
1823
  elementDescriptor,
1688
1824
  filePath,
@@ -1837,11 +1973,12 @@ var ElementsDescriptor = class {
1837
1973
  /**
1838
1974
  * Returns an external or core dependency element given its dependency source and file path.
1839
1975
  * @param dependencySource The source of the dependency.
1840
- * @param filePath The resolved file path of the dependency, if known.
1976
+ * @param isOutsideRootPath Whether the file path is outside the configured root path.
1977
+ * @param filePath The resolved file path of the dependency, if known. Can be absolute if rootPath is configured.
1841
1978
  * @returns The external or core dependency element, or null if it is a local dependency.
1842
1979
  */
1843
- _getExternalOrCoreDependencyElement(dependencySource, filePath) {
1844
- const baseDependencySource = this._getExternalOrCoreModuleBaseSource(dependencySource);
1980
+ _getExternalOrCoreDependencyElement(dependencySource, isOutsideRootPath, filePath) {
1981
+ const baseDependencySource = this._getExternalOrCoreModuleModule(dependencySource);
1845
1982
  const isCore = this._dependencySourceIsCoreModule(
1846
1983
  dependencySource,
1847
1984
  baseDependencySource
@@ -1849,23 +1986,22 @@ var ElementsDescriptor = class {
1849
1986
  if (isCore) {
1850
1987
  const coreElement = {
1851
1988
  ...UNKNOWN_ELEMENT,
1852
- source: dependencySource,
1853
- baseSource: baseDependencySource,
1989
+ module: baseDependencySource,
1854
1990
  origin: ELEMENT_ORIGINS_MAP.CORE
1855
1991
  };
1856
1992
  return coreElement;
1857
1993
  }
1858
1994
  const isExternal = this._isExternalDependency(
1859
1995
  filePath || null,
1996
+ isOutsideRootPath,
1860
1997
  dependencySource
1861
1998
  );
1862
1999
  if (isExternal) {
1863
2000
  const externalElement = {
1864
2001
  ...UNKNOWN_ELEMENT,
1865
2002
  path: filePath || null,
1866
- internalPath: dependencySource.replace(baseDependencySource, ""),
1867
- source: dependencySource,
1868
- baseSource: baseDependencySource,
2003
+ internalPath: dependencySource.replace(baseDependencySource, "") || null,
2004
+ module: baseDependencySource,
1869
2005
  origin: ELEMENT_ORIGINS_MAP.EXTERNAL
1870
2006
  };
1871
2007
  return externalElement;
@@ -1877,34 +2013,23 @@ var ElementsDescriptor = class {
1877
2013
  if (this._descriptionsCache.has(cacheKey)) {
1878
2014
  return this._descriptionsCache.get(cacheKey);
1879
2015
  }
1880
- const externalOrCoreDependencyElement = dependencySource ? this._getExternalOrCoreDependencyElement(dependencySource, filePath) : null;
2016
+ const normalizedFilePath = filePath ? normalizePath(filePath) : filePath;
2017
+ const isOutsideRootPath = normalizedFilePath ? this._isOutsideRootPath(normalizedFilePath) : false;
2018
+ const relativePath = normalizedFilePath && this._config.rootPath ? this._toRelativePath(normalizedFilePath) : normalizedFilePath;
2019
+ const externalOrCoreDependencyElement = dependencySource ? this._getExternalOrCoreDependencyElement(
2020
+ dependencySource,
2021
+ isOutsideRootPath,
2022
+ relativePath
2023
+ ) : null;
1881
2024
  if (externalOrCoreDependencyElement) {
1882
2025
  this._descriptionsCache.set(cacheKey, externalOrCoreDependencyElement);
1883
2026
  return externalOrCoreDependencyElement;
1884
2027
  }
1885
- const fileDescription = this._describeFile(filePath);
1886
- const elementResult = dependencySource ? {
1887
- ...fileDescription,
1888
- source: dependencySource
1889
- } : fileDescription;
1890
- this._descriptionsCache.set(cacheKey, elementResult);
1891
- return elementResult;
2028
+ const fileDescription = this._describeFile(relativePath);
2029
+ this._descriptionsCache.set(cacheKey, fileDescription);
2030
+ return fileDescription;
1892
2031
  }
1893
- /**
1894
- * Describes an element given its file path.
1895
- * @param filePath The path of the file to describe.
1896
- * @returns The description of the element.
1897
- */
1898
- describeElement(filePath) {
1899
- return this._describeElement(filePath);
1900
- }
1901
- /**
1902
- * Describes a dependency element given its dependency source and file path.
1903
- * @param dependencySource The source of the dependency.
1904
- * @param filePath The path of the file being the dependency, if known.
1905
- * @returns The description of the dependency element.
1906
- */
1907
- describeDependencyElement(dependencySource, filePath) {
2032
+ describeElement(filePath, dependencySource) {
1908
2033
  return this._describeElement(filePath, dependencySource);
1909
2034
  }
1910
2035
  };
@@ -1964,18 +2089,6 @@ var Descriptors = class {
1964
2089
  describeElement(filePath) {
1965
2090
  return this._elementsDescriptor.describeElement(filePath);
1966
2091
  }
1967
- /**
1968
- * Describes a dependency element given its dependency source and file path.
1969
- * @param dependencySource The source of the dependency.
1970
- * @param filePath The path of the file being the dependency, if known.
1971
- * @returns The description of the dependency element.
1972
- */
1973
- describeDependencyElement(dependencySource, filePath) {
1974
- return this._elementsDescriptor.describeDependencyElement(
1975
- dependencySource,
1976
- filePath
1977
- );
1978
- }
1979
2092
  /**
1980
2093
  * Describes elements in a dependency relationship, and provides additional information about the dependency itself.
1981
2094
  * @param options The options for describing the elements and the dependency details.
@@ -2004,6 +2117,22 @@ var Matcher = class {
2004
2117
  this._elementsMatcher = elementsMatcher;
2005
2118
  this._dependenciesMatcher = dependenciesMatcher;
2006
2119
  }
2120
+ /**
2121
+ * Describes an element given its file path.
2122
+ * @param filePath The path of the file to describe.
2123
+ * @returns The description of the element.
2124
+ */
2125
+ describeElement(filePath) {
2126
+ return this._descriptors.describeElement(filePath);
2127
+ }
2128
+ /**
2129
+ * Describes elements in a dependency relationship, and provides additional information about the dependency itself.
2130
+ * @param options The options for describing the elements and the dependency details.
2131
+ * @returns The description of the dependency between the elements.
2132
+ */
2133
+ describeDependency(options) {
2134
+ return this._descriptors.describeDependency(options);
2135
+ }
2007
2136
  /**
2008
2137
  * Determines if an element matches a given selector.
2009
2138
  * @param filePath The file path of the element
@@ -2011,7 +2140,7 @@ var Matcher = class {
2011
2140
  * @param options Extra matcher options
2012
2141
  * @returns True if the element matches the selector, false otherwise
2013
2142
  */
2014
- _isElementMatch(filePath, selector, options) {
2143
+ isElementMatch(filePath, selector, options) {
2015
2144
  const description = this._descriptors.describeElement(filePath);
2016
2145
  return this._elementsMatcher.isElementMatch(description, selector, options);
2017
2146
  }
@@ -2022,7 +2151,7 @@ var Matcher = class {
2022
2151
  * @param options Extra matcher options
2023
2152
  * @returns True if the dependency matches the selector, false otherwise
2024
2153
  */
2025
- _isDependencyMatch(dependencyData, selector, options) {
2154
+ isDependencyMatch(dependencyData, selector, options) {
2026
2155
  const description = this._descriptors.describeDependency(dependencyData);
2027
2156
  return this._dependenciesMatcher.isDependencyMatch(
2028
2157
  description,
@@ -2030,20 +2159,6 @@ var Matcher = class {
2030
2159
  options
2031
2160
  );
2032
2161
  }
2033
- isMatch(descriptorOptions, selector, options) {
2034
- if (isString(descriptorOptions)) {
2035
- return this._isElementMatch(
2036
- descriptorOptions,
2037
- selector,
2038
- options
2039
- );
2040
- }
2041
- return this._isDependencyMatch(
2042
- descriptorOptions,
2043
- selector,
2044
- options
2045
- );
2046
- }
2047
2162
  /**
2048
2163
  * Determines the selector matching for an element.
2049
2164
  * @param filePath The file path of the element
@@ -2051,7 +2166,7 @@ var Matcher = class {
2051
2166
  * @param options Extra options for matching
2052
2167
  * @returns The matching selector data or null if no match is found
2053
2168
  */
2054
- _getElementSelectorMatching(filePath, selector, options) {
2169
+ getElementSelectorMatching(filePath, selector, options) {
2055
2170
  const description = this._descriptors.describeElement(filePath);
2056
2171
  return this._elementsMatcher.getSelectorMatching(
2057
2172
  description,
@@ -2066,7 +2181,7 @@ var Matcher = class {
2066
2181
  * @param options Extra options for matching
2067
2182
  * @returns The matching dependency result or null if no match is found
2068
2183
  */
2069
- _getDependencySelectorMatching(dependencyData, selector, options) {
2184
+ getDependencySelectorMatching(dependencyData, selector, options) {
2070
2185
  const description = this._descriptors.describeDependency(dependencyData);
2071
2186
  return this._dependenciesMatcher.getSelectorsMatching(
2072
2187
  description,
@@ -2074,66 +2189,44 @@ var Matcher = class {
2074
2189
  options
2075
2190
  );
2076
2191
  }
2077
- getSelectorMatching(descriptorOptions, selector, options) {
2078
- if (isString(descriptorOptions)) {
2079
- return this._getElementSelectorMatching(
2080
- descriptorOptions,
2192
+ /**
2193
+ * Returns the selectors matching result for the given element or dependency description.
2194
+ * @param description The element or dependency description to check.
2195
+ * @param selector The selector to check against.
2196
+ * @param options Extra options for matching, such as templates data, etc.
2197
+ * @returns The selectors matching result for the given description, and whether it matches or not.
2198
+ */
2199
+ getDependencySelectorMatchingDescription(description, selector, options) {
2200
+ if (isDependencySelector(selector) && isDependencyDescription(description)) {
2201
+ return this._dependenciesMatcher.getSelectorsMatching(
2202
+ description,
2081
2203
  selector,
2082
2204
  options
2083
2205
  );
2084
2206
  }
2085
- return this._getDependencySelectorMatching(
2086
- descriptorOptions,
2087
- selector,
2088
- options
2207
+ throw new Error(
2208
+ "Invalid arguments: Please provide a valid description and selector"
2089
2209
  );
2090
2210
  }
2091
- getSelectorMatchingDescription(description, selector, options) {
2211
+ /**
2212
+ * Returns the first element selector matching result for the given element description.
2213
+ * @param description The element description to check.
2214
+ * @param selector The selector to check against.
2215
+ * @param options Extra options for matching, such as templates data, etc.
2216
+ * @returns The first matching selector result for the given description, or null if no match is found.
2217
+ */
2218
+ getElementSelectorMatchingDescription(description, selector, options) {
2092
2219
  if (isElementsSelector(selector) && isElementDescription(description)) {
2093
2220
  return this._elementsMatcher.getSelectorMatching(
2094
2221
  description,
2095
2222
  selector,
2096
2223
  options
2097
2224
  );
2098
- } else if (isDependencySelector(selector) && isDependencyDescription(description)) {
2099
- return this._dependenciesMatcher.getSelectorsMatching(
2100
- description,
2101
- selector,
2102
- options
2103
- );
2104
2225
  }
2105
2226
  throw new Error(
2106
2227
  "Invalid arguments: Please provide a valid description and selector"
2107
2228
  );
2108
2229
  }
2109
- /**
2110
- * Describes an element given its file path.
2111
- * @param filePath The path of the file to describe.
2112
- * @returns The description of the element.
2113
- */
2114
- describeElement(filePath) {
2115
- return this._descriptors.describeElement(filePath);
2116
- }
2117
- /**
2118
- * Describes a dependency element given its dependency source and file path.
2119
- * @param dependencySource The source of the dependency.
2120
- * @param filePath The path of the file being the dependency, if known.
2121
- * @returns The description of the dependency element.
2122
- */
2123
- describeDependencyElement(dependencySource, filePath) {
2124
- return this._descriptors.describeDependencyElement(
2125
- dependencySource,
2126
- filePath
2127
- );
2128
- }
2129
- /**
2130
- * Describes elements in a dependency relationship, and provides additional information about the dependency itself.
2131
- * @param options The options for describing the elements and the dependency details.
2132
- * @returns The description of the dependency between the elements.
2133
- */
2134
- describeDependency(options) {
2135
- return this._descriptors.describeDependency(options);
2136
- }
2137
2230
  /**
2138
2231
  * Clears all caches.
2139
2232
  */
@@ -2289,7 +2382,7 @@ var MatchersCache = class extends CacheManager {
2289
2382
  config,
2290
2383
  elementDescriptors
2291
2384
  }) {
2292
- const configHash = `${config.legacyTemplates}|${config.includePaths}|${config.ignorePaths}|${config.cache}`;
2385
+ const configHash = `${config.legacyTemplates}|${config.includePaths}|${config.ignorePaths}|${config.cache}|${config.rootPath}|${config.flagAsExternal.inNodeModules}|${config.flagAsExternal.unresolvableAlias}|${config.flagAsExternal.outsideRootPath}|${config.flagAsExternal.customSourcePatterns.join(",")}`;
2293
2386
  const elementDescriptorsHash = elementDescriptors.map(
2294
2387
  (descriptor) => `${descriptor.type}|${descriptor.category}|${descriptor.pattern}|${descriptor.basePattern}|${descriptor.mode}|${descriptor.capture}|${descriptor.baseCapture}`
2295
2388
  ).join(",");