@jjrawlins/cdk-diff-pr-github-action 1.9.15 → 1.9.17

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.
Files changed (97) hide show
  1. package/.jsii +3 -3
  2. package/cdkdiffprgithubaction/jsii/jsii.go +2 -2
  3. package/cdkdiffprgithubaction/version +1 -1
  4. package/lib/CdkDiffIamTemplate.js +2 -2
  5. package/lib/CdkDiffIamTemplateStackSet.js +2 -2
  6. package/lib/CdkDiffStackWorkflow.js +1 -1
  7. package/lib/CdkDriftDetectionWorkflow.js +1 -1
  8. package/lib/CdkDriftIamTemplate.js +2 -2
  9. package/node_modules/@aws-sdk/client-cloudformation/package.json +12 -12
  10. package/node_modules/@aws-sdk/core/package.json +3 -3
  11. package/node_modules/@aws-sdk/credential-provider-env/package.json +2 -2
  12. package/node_modules/@aws-sdk/credential-provider-http/package.json +3 -3
  13. package/node_modules/@aws-sdk/credential-provider-ini/package.json +9 -9
  14. package/node_modules/@aws-sdk/credential-provider-login/package.json +3 -3
  15. package/node_modules/@aws-sdk/credential-provider-node/package.json +7 -7
  16. package/node_modules/@aws-sdk/credential-provider-process/package.json +2 -2
  17. package/node_modules/@aws-sdk/credential-provider-sso/package.json +4 -4
  18. package/node_modules/@aws-sdk/credential-provider-web-identity/package.json +3 -3
  19. package/node_modules/@aws-sdk/middleware-user-agent/package.json +2 -2
  20. package/node_modules/@aws-sdk/nested-clients/dist-es/submodules/cognito-identity/CognitoIdentity.js +1 -1
  21. package/node_modules/@aws-sdk/nested-clients/dist-types/submodules/cognito-identity/CognitoIdentity.d.ts +2 -2
  22. package/node_modules/@aws-sdk/nested-clients/package.json +11 -11
  23. package/node_modules/@aws-sdk/region-config-resolver/package.json +2 -2
  24. package/node_modules/@aws-sdk/token-providers/package.json +3 -3
  25. package/node_modules/@aws-sdk/util-user-agent-node/package.json +2 -2
  26. package/node_modules/@aws-sdk/xml-builder/package.json +2 -2
  27. package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/CHANGELOG.md +7 -0
  28. package/node_modules/fast-xml-parser/lib/fxbuilder.min.js +2 -0
  29. package/node_modules/fast-xml-parser/lib/fxbuilder.min.js.map +1 -0
  30. package/node_modules/fast-xml-parser/lib/fxp.cjs +1 -0
  31. package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/lib/fxp.d.cts +20 -12
  32. package/node_modules/fast-xml-parser/lib/fxp.min.js +2 -0
  33. package/node_modules/fast-xml-parser/lib/fxp.min.js.map +1 -0
  34. package/node_modules/fast-xml-parser/lib/fxparser.min.js +2 -0
  35. package/node_modules/fast-xml-parser/lib/fxparser.min.js.map +1 -0
  36. package/node_modules/fast-xml-parser/lib/pem.d.cts +148 -0
  37. package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/package.json +3 -3
  38. package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/fxp.d.ts +13 -11
  39. package/node_modules/fast-xml-parser/src/pem.d.ts +135 -0
  40. package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/xmlparser/DocTypeReader.js +26 -17
  41. package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/xmlparser/OptionsBuilder.js +6 -6
  42. package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/xmlparser/OrderedObjParser.js +22 -16
  43. package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/xmlparser/XMLParser.js +2 -2
  44. package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/xmlparser/node2json.js +10 -11
  45. package/node_modules/path-expression-matcher/README.md +98 -13
  46. package/node_modules/path-expression-matcher/lib/pem.cjs +1 -1
  47. package/node_modules/path-expression-matcher/lib/pem.d.cts +188 -0
  48. package/node_modules/path-expression-matcher/lib/pem.min.js +1 -1
  49. package/node_modules/path-expression-matcher/lib/pem.min.js.map +1 -1
  50. package/node_modules/path-expression-matcher/package.json +2 -2
  51. package/node_modules/path-expression-matcher/src/Matcher.js +84 -0
  52. package/node_modules/path-expression-matcher/src/index.d.ts +152 -0
  53. package/package.json +2 -2
  54. package/node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser/lib/fxbuilder.min.js +0 -2
  55. package/node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser/lib/fxbuilder.min.js.map +0 -1
  56. package/node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser/lib/fxp.cjs +0 -1
  57. package/node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser/lib/fxp.min.js +0 -2
  58. package/node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser/lib/fxp.min.js.map +0 -1
  59. package/node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser/lib/fxparser.min.js +0 -2
  60. package/node_modules/@aws-sdk/xml-builder/node_modules/fast-xml-parser/lib/fxparser.min.js.map +0 -1
  61. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/LICENSE +0 -0
  62. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/README.md +0 -0
  63. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/lib/fxvalidator.min.js +0 -0
  64. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/lib/fxvalidator.min.js.map +0 -0
  65. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/cli/cli.js +0 -0
  66. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/cli/man.js +0 -0
  67. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/cli/read.js +0 -0
  68. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/fxp.js +0 -0
  69. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/ignoreAttributes.js +0 -0
  70. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/util.js +0 -0
  71. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/CharsSymbol.js +0 -0
  72. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/EntitiesParser.js +0 -0
  73. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/OptionsBuilder.js +0 -0
  74. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/OutputBuilders/BaseOutputBuilder.js +0 -0
  75. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/OutputBuilders/JsArrBuilder.js +0 -0
  76. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/OutputBuilders/JsMinArrBuilder.js +0 -0
  77. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/OutputBuilders/JsObjBuilder.js +0 -0
  78. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/OutputBuilders/ParserOptionsBuilder.js +0 -0
  79. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/Report.js +0 -0
  80. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/TagPath.js +0 -0
  81. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/TagPathMatcher.js +0 -0
  82. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/XMLParser.js +0 -0
  83. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/Xml2JsParser.js +0 -0
  84. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/XmlPartReader.js +0 -0
  85. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/XmlSpecialTagsReader.js +0 -0
  86. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/inputSource/BufferSource.js +0 -0
  87. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/inputSource/StringSource.js +0 -0
  88. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/valueParsers/EntitiesParser.js +0 -0
  89. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/valueParsers/booleanParser.js +0 -0
  90. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/valueParsers/booleanParserExt.js +0 -0
  91. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/valueParsers/currency.js +0 -0
  92. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/valueParsers/join.js +0 -0
  93. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/valueParsers/number.js +0 -0
  94. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/v6/valueParsers/trim.js +0 -0
  95. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/validator.js +0 -0
  96. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/xmlbuilder/json2xml.js +0 -0
  97. /package/node_modules/{@aws-sdk/xml-builder/node_modules/fast-xml-parser → fast-xml-parser}/src/xmlparser/xmlNode.js +0 -0
@@ -113,6 +113,10 @@ export default class OrderedObjParser {
113
113
  // Initialize path matcher for path-expression-matcher
114
114
  this.matcher = new Matcher();
115
115
 
116
+ // Live read-only proxy of matcher — PEM creates and caches this internally.
117
+ // All user callbacks receive this instead of the mutable matcher.
118
+ this.readonlyMatcher = this.matcher.readOnly();
119
+
116
120
  // Flag to track if current node is a stop node (optimization)
117
121
  this.isCurrentNodeStopNode = false;
118
122
 
@@ -225,7 +229,7 @@ function buildAttributesMap(attrStr, jPath, tagName) {
225
229
  if (this.options.trimValues) {
226
230
  parsedVal = parsedVal.trim();
227
231
  }
228
- parsedVal = this.replaceEntitiesValue(parsedVal, tagName, jPath);
232
+ parsedVal = this.replaceEntitiesValue(parsedVal, tagName, this.readonlyMatcher);
229
233
  rawAttrsForMatcher[attrName] = parsedVal;
230
234
  }
231
235
  }
@@ -240,7 +244,7 @@ function buildAttributesMap(attrStr, jPath, tagName) {
240
244
  const attrName = this.resolveNameSpace(matches[i][1]);
241
245
 
242
246
  // Convert jPath to string if needed for ignoreAttributesFn
243
- const jPathStr = this.options.jPath ? jPath.toString() : jPath;
247
+ const jPathStr = this.options.jPath ? jPath.toString() : this.readonlyMatcher;
244
248
  if (this.ignoreAttributesFn(attrName, jPathStr)) {
245
249
  continue
246
250
  }
@@ -259,10 +263,10 @@ function buildAttributesMap(attrStr, jPath, tagName) {
259
263
  if (this.options.trimValues) {
260
264
  oldVal = oldVal.trim();
261
265
  }
262
- oldVal = this.replaceEntitiesValue(oldVal, tagName, jPath);
266
+ oldVal = this.replaceEntitiesValue(oldVal, tagName, this.readonlyMatcher);
263
267
 
264
- // Pass jPath string or matcher based on options.jPath setting
265
- const jPathOrMatcher = this.options.jPath ? jPath.toString() : jPath;
268
+ // Pass jPath string or readonlyMatcher based on options.jPath setting
269
+ const jPathOrMatcher = this.options.jPath ? jPath.toString() : this.readonlyMatcher;
266
270
  const newVal = this.options.attributeValueProcessor(attrName, oldVal, jPathOrMatcher);
267
271
  if (newVal === null || newVal === undefined) {
268
272
  //don't parse
@@ -329,7 +333,7 @@ const parseXml = function (xmlData) {
329
333
  tagName = transformTagName(this.options.transformTagName, tagName, "", this.options).tagName;
330
334
 
331
335
  if (currentNode) {
332
- textData = this.saveTextToParentTag(textData, currentNode, this.matcher);
336
+ textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
333
337
  }
334
338
 
335
339
  //check if last tag of nested tag was unpaired tag
@@ -354,7 +358,7 @@ const parseXml = function (xmlData) {
354
358
  let tagData = readTagExp(xmlData, i, false, "?>");
355
359
  if (!tagData) throw new Error("Pi Tag is not closed.");
356
360
 
357
- textData = this.saveTextToParentTag(textData, currentNode, this.matcher);
361
+ textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
358
362
  if ((this.options.ignoreDeclaration && tagData.tagName === "?xml") || this.options.ignorePiTags) {
359
363
  //do nothing
360
364
  } else {
@@ -365,7 +369,7 @@ const parseXml = function (xmlData) {
365
369
  if (tagData.tagName !== tagData.tagExp && tagData.attrExpPresent) {
366
370
  childNode[":@"] = this.buildAttributesMap(tagData.tagExp, this.matcher, tagData.tagName);
367
371
  }
368
- this.addChild(currentNode, childNode, this.matcher, i);
372
+ this.addChild(currentNode, childNode, this.readonlyMatcher, i);
369
373
  }
370
374
 
371
375
 
@@ -375,7 +379,7 @@ const parseXml = function (xmlData) {
375
379
  if (this.options.commentPropName) {
376
380
  const comment = xmlData.substring(i + 4, endIndex - 2);
377
381
 
378
- textData = this.saveTextToParentTag(textData, currentNode, this.matcher);
382
+ textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
379
383
 
380
384
  currentNode.add(this.options.commentPropName, [{ [this.options.textNodeName]: comment }]);
381
385
  }
@@ -388,9 +392,9 @@ const parseXml = function (xmlData) {
388
392
  const closeIndex = findClosingIndex(xmlData, "]]>", i, "CDATA is not closed.") - 2;
389
393
  const tagExp = xmlData.substring(i + 9, closeIndex);
390
394
 
391
- textData = this.saveTextToParentTag(textData, currentNode, this.matcher);
395
+ textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher);
392
396
 
393
- let val = this.parseTextData(tagExp, currentNode.tagname, this.matcher, true, false, true, true);
397
+ let val = this.parseTextData(tagExp, currentNode.tagname, this.readonlyMatcher, true, false, true, true);
394
398
  if (val == undefined) val = "";
395
399
 
396
400
  //cdata should be set even if it is 0 length string
@@ -422,6 +426,8 @@ const parseXml = function (xmlData) {
422
426
  if (this.options.strictReservedNames &&
423
427
  (tagName === this.options.commentPropName
424
428
  || tagName === this.options.cdataPropName
429
+ || tagName === this.options.textNodeName
430
+ || tagName === this.options.attributesGroupName
425
431
  )) {
426
432
  throw new Error(`Invalid tag name: ${tagName}`);
427
433
  }
@@ -430,7 +436,7 @@ const parseXml = function (xmlData) {
430
436
  if (currentNode && textData) {
431
437
  if (currentNode.tagname !== '!xml') {
432
438
  //when nested tag is found
433
- textData = this.saveTextToParentTag(textData, currentNode, this.matcher, false);
439
+ textData = this.saveTextToParentTag(textData, currentNode, this.readonlyMatcher, false);
434
440
  }
435
441
  }
436
442
 
@@ -520,7 +526,7 @@ const parseXml = function (xmlData) {
520
526
  this.matcher.pop(); // Pop the stop node tag
521
527
  this.isCurrentNodeStopNode = false; // Reset flag
522
528
 
523
- this.addChild(currentNode, childNode, this.matcher, startIndex);
529
+ this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
524
530
  } else {
525
531
  //selfClosing tag
526
532
  if (isSelfClosing) {
@@ -530,7 +536,7 @@ const parseXml = function (xmlData) {
530
536
  if (prefixedAttrs) {
531
537
  childNode[":@"] = prefixedAttrs;
532
538
  }
533
- this.addChild(currentNode, childNode, this.matcher, startIndex);
539
+ this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
534
540
  this.matcher.pop(); // Pop self-closing tag
535
541
  this.isCurrentNodeStopNode = false; // Reset flag
536
542
  }
@@ -539,7 +545,7 @@ const parseXml = function (xmlData) {
539
545
  if (prefixedAttrs) {
540
546
  childNode[":@"] = prefixedAttrs;
541
547
  }
542
- this.addChild(currentNode, childNode, this.matcher, startIndex);
548
+ this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
543
549
  this.matcher.pop(); // Pop unpaired tag
544
550
  this.isCurrentNodeStopNode = false; // Reset flag
545
551
  i = result.closeIndex;
@@ -557,7 +563,7 @@ const parseXml = function (xmlData) {
557
563
  if (prefixedAttrs) {
558
564
  childNode[":@"] = prefixedAttrs;
559
565
  }
560
- this.addChild(currentNode, childNode, this.matcher, startIndex);
566
+ this.addChild(currentNode, childNode, this.readonlyMatcher, startIndex);
561
567
  currentNode = childNode;
562
568
  }
563
569
  textData = "";
@@ -35,7 +35,7 @@ export default class XMLParser {
35
35
  orderedObjParser.addExternalEntities(this.externalEntities);
36
36
  const orderedResult = orderedObjParser.parseXml(xmlData);
37
37
  if (this.options.preserveOrder || orderedResult === undefined) return orderedResult;
38
- else return prettify(orderedResult, this.options, orderedObjParser.matcher);
38
+ else return prettify(orderedResult, this.options, orderedObjParser.matcher, orderedObjParser.readonlyMatcher);
39
39
  }
40
40
 
41
41
  /**
@@ -68,4 +68,4 @@ export default class XMLParser {
68
68
  static getMetaDataSymbol() {
69
69
  return XmlNode.getMetaDataSymbol();
70
70
  }
71
- }
71
+ }
@@ -35,18 +35,17 @@ function stripAttributePrefix(attrs, prefix) {
35
35
  * @param {Matcher} matcher - Path matcher instance
36
36
  * @returns
37
37
  */
38
- export default function prettify(node, options, matcher) {
39
- return compress(node, options, matcher);
38
+ export default function prettify(node, options, matcher, readonlyMatcher) {
39
+ return compress(node, options, matcher, readonlyMatcher);
40
40
  }
41
41
 
42
42
  /**
43
- *
44
43
  * @param {array} arr
45
44
  * @param {object} options
46
45
  * @param {Matcher} matcher - Path matcher instance
47
46
  * @returns object
48
47
  */
49
- function compress(arr, options, matcher) {
48
+ function compress(arr, options, matcher, readonlyMatcher) {
50
49
  let text;
51
50
  const compressedObj = {}; //This is intended to be a plain object
52
51
  for (let i = 0; i < arr.length; i++) {
@@ -69,11 +68,11 @@ function compress(arr, options, matcher) {
69
68
  continue;
70
69
  } else if (tagObj[property]) {
71
70
 
72
- let val = compress(tagObj[property], options, matcher);
71
+ let val = compress(tagObj[property], options, matcher, readonlyMatcher);
73
72
  const isLeaf = isLeafTag(val, options);
74
73
 
75
74
  if (tagObj[":@"]) {
76
- assignAttributes(val, tagObj[":@"], matcher, options);
75
+ assignAttributes(val, tagObj[":@"], readonlyMatcher, options);
77
76
  } else if (Object.keys(val).length === 1 && val[options.textNodeName] !== undefined && !options.alwaysCreateTextNode) {
78
77
  val = val[options.textNodeName];
79
78
  } else if (Object.keys(val).length === 0) {
@@ -95,8 +94,8 @@ function compress(arr, options, matcher) {
95
94
  //TODO: if a node is not an array, then check if it should be an array
96
95
  //also determine if it is a leaf node
97
96
 
98
- // Pass jPath string or matcher based on options.jPath setting
99
- const jPathOrMatcher = options.jPath ? matcher.toString() : matcher;
97
+ // Pass jPath string or readonlyMatcher based on options.jPath setting
98
+ const jPathOrMatcher = options.jPath ? readonlyMatcher.toString() : readonlyMatcher;
100
99
  if (options.isArray(property, jPathOrMatcher, isLeaf)) {
101
100
  compressedObj[property] = [val];
102
101
  } else {
@@ -128,7 +127,7 @@ function propName(obj) {
128
127
  }
129
128
  }
130
129
 
131
- function assignAttributes(obj, attrMap, matcher, options) {
130
+ function assignAttributes(obj, attrMap, readonlyMatcher, options) {
132
131
  if (attrMap) {
133
132
  const keys = Object.keys(attrMap);
134
133
  const len = keys.length; //don't make it inline
@@ -143,8 +142,8 @@ function assignAttributes(obj, attrMap, matcher, options) {
143
142
  // For attributes, we need to create a temporary path
144
143
  // Pass jPath string or matcher based on options.jPath setting
145
144
  const jPathOrMatcher = options.jPath
146
- ? matcher.toString() + "." + rawAttrName
147
- : matcher;
145
+ ? readonlyMatcher.toString() + "." + rawAttrName
146
+ : readonlyMatcher;
148
147
 
149
148
  if (options.isArray(atrrName, jPathOrMatcher, true, true)) {
150
149
  obj[atrrName] = [attrMap[atrrName]];
@@ -346,6 +346,57 @@ Restore from a snapshot.
346
346
  matcher.restore(snapshot);
347
347
  ```
348
348
 
349
+ #### Read-Only Access
350
+
351
+ ##### `readOnly()`
352
+
353
+ Returns a **live, read-only proxy** of the matcher. All query and inspection methods work normally, but any attempt to call a state-mutating method (`push`, `pop`, `reset`, `updateCurrent`, `restore`) or to write/delete a property throws a `TypeError`.
354
+
355
+ This is the recommended way to share the matcher with external consumers — plugins, callbacks, event handlers — that only need to inspect the current path without being able to corrupt parser state.
356
+
357
+ ```javascript
358
+ const ro = matcher.readOnly();
359
+ ```
360
+
361
+ **What works on the read-only view:**
362
+
363
+ ```javascript
364
+ ro.matches(expr) // ✓ pattern matching
365
+ ro.getCurrentTag() // ✓ current tag name
366
+ ro.getCurrentNamespace() // ✓ current namespace
367
+ ro.getAttrValue("id") // ✓ attribute value
368
+ ro.hasAttr("id") // ✓ attribute presence check
369
+ ro.getPosition() // ✓ sibling position
370
+ ro.getCounter() // ✓ occurrence counter
371
+ ro.getDepth() // ✓ path depth
372
+ ro.toString() // ✓ path as string
373
+ ro.toArray() // ✓ path as array
374
+ ro.snapshot() // ✓ snapshot (can be used to restore the real matcher)
375
+ ```
376
+
377
+ **What throws a `TypeError`:**
378
+
379
+ ```javascript
380
+ ro.push("child", {}) // ✗ TypeError: Cannot call 'push' on a read-only Matcher
381
+ ro.pop() // ✗ TypeError: Cannot call 'pop' on a read-only Matcher
382
+ ro.reset() // ✗ TypeError: Cannot call 'reset' on a read-only Matcher
383
+ ro.updateCurrent({}) // ✗ TypeError: Cannot call 'updateCurrent' on a read-only Matcher
384
+ ro.restore(snapshot) // ✗ TypeError: Cannot call 'restore' on a read-only Matcher
385
+ ro.separator = '/' // ✗ TypeError: Cannot set property on a read-only Matcher
386
+ ```
387
+
388
+ **Important:** The read-only view is **live** — it always reflects the current state of the underlying matcher. If you need a frozen-in-time copy instead, use `snapshot()`.
389
+
390
+ ```javascript
391
+ const matcher = new Matcher();
392
+ const ro = matcher.readOnly();
393
+
394
+ matcher.push("root");
395
+ ro.getDepth(); // 1 — immediately reflects the push
396
+ matcher.push("users");
397
+ ro.getDepth(); // 2 — still live
398
+ ```
399
+
349
400
  ## 💡 Usage Examples
350
401
 
351
402
  ### Example 1: XML Parser with stopNodes
@@ -481,7 +532,53 @@ const expr = new Expression("root.item:first");
481
532
  console.log(matcher.matches(expr)); // false (counter=1, not 0)
482
533
  ```
483
534
 
484
- ### Example 7: Namespace Support (XML/SOAP)
535
+ ### Example 8: Passing a Read-Only Matcher to External Consumers
536
+
537
+ When passing the matcher into callbacks, plugins, or other code you don't control, use `readOnly()` to prevent accidental state corruption.
538
+
539
+ ```javascript
540
+ import { Expression, Matcher } from 'path-expression-matcher';
541
+
542
+ const matcher = new Matcher();
543
+
544
+ const adminExpr = new Expression("..user[type=admin]");
545
+
546
+ function parseTag(tagName, attrs, onTag) {
547
+ matcher.push(tagName, attrs);
548
+
549
+ // Pass a read-only view — consumer can inspect but not mutate
550
+ onTag(matcher.readOnly());
551
+
552
+ matcher.pop();
553
+ }
554
+
555
+ // Safe consumer — can only read
556
+ function myPlugin(ro) {
557
+ if (ro.matches(adminExpr)) {
558
+ console.log("Admin at path:", ro.toString());
559
+ console.log("Depth:", ro.getDepth());
560
+ console.log("ID:", ro.getAttrValue("id"));
561
+ }
562
+ }
563
+
564
+ // ro.push(...) or ro.reset() here would throw TypeError,
565
+ // so the parser's state is always safe.
566
+ parseTag("user", { id: "1", type: "admin" }, myPlugin);
567
+ ```
568
+
569
+ **Combining with `snapshot()`:** A snapshot taken via the read-only view can still be used to restore the real matcher.
570
+
571
+ ```javascript
572
+ const matcher = new Matcher();
573
+ matcher.push("root");
574
+ matcher.push("users");
575
+
576
+ const ro = matcher.readOnly();
577
+ const snap = ro.snapshot(); // ✓ snapshot works on read-only view
578
+
579
+ matcher.push("user"); // continue parsing...
580
+ matcher.restore(snap); // restore to "root.users" using the snapshot
581
+ ```
485
582
 
486
583
  ```javascript
487
584
  const matcher = new Matcher();
@@ -614,18 +711,6 @@ const parser = new XMLParser({
614
711
  });
615
712
  ```
616
713
 
617
- ## 🧪 Testing
618
-
619
- ```bash
620
- npm test
621
- ```
622
-
623
- All 77 tests covering:
624
- - Pattern parsing (exact, wildcards, attributes, position)
625
- - Path tracking (push, pop, update)
626
- - Pattern matching (all combinations)
627
- - Edge cases and error conditions
628
-
629
714
  ## 📄 License
630
715
 
631
716
  MIT
@@ -1 +1 @@
1
- (()=>{"use strict";var t={d:(e,s)=>{for(var i in s)t.o(s,i)&&!t.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:s[i]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{Expression:()=>s,Matcher:()=>i,default:()=>n});class s{constructor(t,e={}){this.pattern=t,this.separator=e.separator||".",this.segments=this._parse(t),this._hasDeepWildcard=this.segments.some(t=>"deep-wildcard"===t.type),this._hasAttributeCondition=this.segments.some(t=>void 0!==t.attrName),this._hasPositionSelector=this.segments.some(t=>void 0!==t.position)}_parse(t){const e=[];let s=0,i="";for(;s<t.length;)t[s]===this.separator?s+1<t.length&&t[s+1]===this.separator?(i.trim()&&(e.push(this._parseSegment(i.trim())),i=""),e.push({type:"deep-wildcard"}),s+=2):(i.trim()&&e.push(this._parseSegment(i.trim())),i="",s++):(i+=t[s],s++);return i.trim()&&e.push(this._parseSegment(i.trim())),e}_parseSegment(t){const e={type:"tag"};let s=null,i=t;const n=t.match(/^([^\[]+)(\[[^\]]*\])(.*)$/);if(n&&(i=n[1]+n[3],n[2])){const t=n[2].slice(1,-1);t&&(s=t)}let r,a,h=i;if(i.includes("::")){const e=i.indexOf("::");if(r=i.substring(0,e).trim(),h=i.substring(e+2).trim(),!r)throw new Error(`Invalid namespace in pattern: ${t}`)}let o=null;if(h.includes(":")){const t=h.lastIndexOf(":"),e=h.substring(0,t).trim(),s=h.substring(t+1).trim();["first","last","odd","even"].includes(s)||/^nth\(\d+\)$/.test(s)?(a=e,o=s):a=h}else a=h;if(!a)throw new Error(`Invalid segment pattern: ${t}`);if(e.tag=a,r&&(e.namespace=r),s)if(s.includes("=")){const t=s.indexOf("=");e.attrName=s.substring(0,t).trim(),e.attrValue=s.substring(t+1).trim()}else e.attrName=s.trim();if(o){const t=o.match(/^nth\((\d+)\)$/);t?(e.position="nth",e.positionValue=parseInt(t[1],10)):e.position=o}return e}get length(){return this.segments.length}hasDeepWildcard(){return this._hasDeepWildcard}hasAttributeCondition(){return this._hasAttributeCondition}hasPositionSelector(){return this._hasPositionSelector}toString(){return this.pattern}}class i{constructor(t={}){this.separator=t.separator||".",this.path=[],this.siblingStacks=[]}push(t,e=null,s=null){this.path.length>0&&(this.path[this.path.length-1].values=void 0);const i=this.path.length;this.siblingStacks[i]||(this.siblingStacks[i]=new Map);const n=this.siblingStacks[i],r=s?`${s}:${t}`:t,a=n.get(r)||0;let h=0;for(const t of n.values())h+=t;n.set(r,a+1);const o={tag:t,position:h,counter:a};null!=s&&(o.namespace=s),null!=e&&(o.values=e),this.path.push(o)}pop(){if(0===this.path.length)return;const t=this.path.pop();return this.siblingStacks.length>this.path.length+1&&(this.siblingStacks.length=this.path.length+1),t}updateCurrent(t){if(this.path.length>0){const e=this.path[this.path.length-1];null!=t&&(e.values=t)}}getCurrentTag(){return this.path.length>0?this.path[this.path.length-1].tag:void 0}getCurrentNamespace(){return this.path.length>0?this.path[this.path.length-1].namespace:void 0}getAttrValue(t){if(0===this.path.length)return;const e=this.path[this.path.length-1];return e.values?.[t]}hasAttr(t){if(0===this.path.length)return!1;const e=this.path[this.path.length-1];return void 0!==e.values&&t in e.values}getPosition(){return 0===this.path.length?-1:this.path[this.path.length-1].position??0}getCounter(){return 0===this.path.length?-1:this.path[this.path.length-1].counter??0}getIndex(){return this.getPosition()}getDepth(){return this.path.length}toString(t,e=!0){const s=t||this.separator;return this.path.map(t=>e&&t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(s)}toArray(){return this.path.map(t=>t.tag)}reset(){this.path=[],this.siblingStacks=[]}matches(t){const e=t.segments;return 0!==e.length&&(t.hasDeepWildcard()?this._matchWithDeepWildcard(e):this._matchSimple(e))}_matchSimple(t){if(this.path.length!==t.length)return!1;for(let e=0;e<t.length;e++){const s=t[e],i=this.path[e],n=e===this.path.length-1;if(!this._matchSegment(s,i,n))return!1}return!0}_matchWithDeepWildcard(t){let e=this.path.length-1,s=t.length-1;for(;s>=0&&e>=0;){const i=t[s];if("deep-wildcard"===i.type){if(s--,s<0)return!0;const i=t[s];let n=!1;for(let t=e;t>=0;t--){const r=t===this.path.length-1;if(this._matchSegment(i,this.path[t],r)){e=t-1,s--,n=!0;break}}if(!n)return!1}else{const t=e===this.path.length-1;if(!this._matchSegment(i,this.path[e],t))return!1;e--,s--}}return s<0}_matchSegment(t,e,s){if("*"!==t.tag&&t.tag!==e.tag)return!1;if(void 0!==t.namespace&&"*"!==t.namespace&&t.namespace!==e.namespace)return!1;if(void 0!==t.attrName){if(!s)return!1;if(!e.values||!(t.attrName in e.values))return!1;if(void 0!==t.attrValue){const s=e.values[t.attrName];if(String(s)!==String(t.attrValue))return!1}}if(void 0!==t.position){if(!s)return!1;const i=e.counter??0;if("first"===t.position&&0!==i)return!1;if("odd"===t.position&&i%2!=1)return!1;if("even"===t.position&&i%2!=0)return!1;if("nth"===t.position&&i!==t.positionValue)return!1}return!0}snapshot(){return{path:this.path.map(t=>({...t})),siblingStacks:this.siblingStacks.map(t=>new Map(t))}}restore(t){this.path=t.path.map(t=>({...t})),this.siblingStacks=t.siblingStacks.map(t=>new Map(t))}}const n={Expression:s,Matcher:i};module.exports=e})();
1
+ (()=>{"use strict";var t={d:(e,s)=>{for(var n in s)t.o(s,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:s[n]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{Expression:()=>s,Matcher:()=>i,default:()=>r});class s{constructor(t,e={}){this.pattern=t,this.separator=e.separator||".",this.segments=this._parse(t),this._hasDeepWildcard=this.segments.some(t=>"deep-wildcard"===t.type),this._hasAttributeCondition=this.segments.some(t=>void 0!==t.attrName),this._hasPositionSelector=this.segments.some(t=>void 0!==t.position)}_parse(t){const e=[];let s=0,n="";for(;s<t.length;)t[s]===this.separator?s+1<t.length&&t[s+1]===this.separator?(n.trim()&&(e.push(this._parseSegment(n.trim())),n=""),e.push({type:"deep-wildcard"}),s+=2):(n.trim()&&e.push(this._parseSegment(n.trim())),n="",s++):(n+=t[s],s++);return n.trim()&&e.push(this._parseSegment(n.trim())),e}_parseSegment(t){const e={type:"tag"};let s=null,n=t;const i=t.match(/^([^\[]+)(\[[^\]]*\])(.*)$/);if(i&&(n=i[1]+i[3],i[2])){const t=i[2].slice(1,-1);t&&(s=t)}let r,a,h=n;if(n.includes("::")){const e=n.indexOf("::");if(r=n.substring(0,e).trim(),h=n.substring(e+2).trim(),!r)throw new Error(`Invalid namespace in pattern: ${t}`)}let o=null;if(h.includes(":")){const t=h.lastIndexOf(":"),e=h.substring(0,t).trim(),s=h.substring(t+1).trim();["first","last","odd","even"].includes(s)||/^nth\(\d+\)$/.test(s)?(a=e,o=s):a=h}else a=h;if(!a)throw new Error(`Invalid segment pattern: ${t}`);if(e.tag=a,r&&(e.namespace=r),s)if(s.includes("=")){const t=s.indexOf("=");e.attrName=s.substring(0,t).trim(),e.attrValue=s.substring(t+1).trim()}else e.attrName=s.trim();if(o){const t=o.match(/^nth\((\d+)\)$/);t?(e.position="nth",e.positionValue=parseInt(t[1],10)):e.position=o}return e}get length(){return this.segments.length}hasDeepWildcard(){return this._hasDeepWildcard}hasAttributeCondition(){return this._hasAttributeCondition}hasPositionSelector(){return this._hasPositionSelector}toString(){return this.pattern}}const n=new Set(["push","pop","reset","updateCurrent","restore"]);class i{constructor(t={}){this.separator=t.separator||".",this.path=[],this.siblingStacks=[]}push(t,e=null,s=null){this.path.length>0&&(this.path[this.path.length-1].values=void 0);const n=this.path.length;this.siblingStacks[n]||(this.siblingStacks[n]=new Map);const i=this.siblingStacks[n],r=s?`${s}:${t}`:t,a=i.get(r)||0;let h=0;for(const t of i.values())h+=t;i.set(r,a+1);const o={tag:t,position:h,counter:a};null!=s&&(o.namespace=s),null!=e&&(o.values=e),this.path.push(o)}pop(){if(0===this.path.length)return;const t=this.path.pop();return this.siblingStacks.length>this.path.length+1&&(this.siblingStacks.length=this.path.length+1),t}updateCurrent(t){if(this.path.length>0){const e=this.path[this.path.length-1];null!=t&&(e.values=t)}}getCurrentTag(){return this.path.length>0?this.path[this.path.length-1].tag:void 0}getCurrentNamespace(){return this.path.length>0?this.path[this.path.length-1].namespace:void 0}getAttrValue(t){if(0===this.path.length)return;const e=this.path[this.path.length-1];return e.values?.[t]}hasAttr(t){if(0===this.path.length)return!1;const e=this.path[this.path.length-1];return void 0!==e.values&&t in e.values}getPosition(){return 0===this.path.length?-1:this.path[this.path.length-1].position??0}getCounter(){return 0===this.path.length?-1:this.path[this.path.length-1].counter??0}getIndex(){return this.getPosition()}getDepth(){return this.path.length}toString(t,e=!0){const s=t||this.separator;return this.path.map(t=>e&&t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(s)}toArray(){return this.path.map(t=>t.tag)}reset(){this.path=[],this.siblingStacks=[]}matches(t){const e=t.segments;return 0!==e.length&&(t.hasDeepWildcard()?this._matchWithDeepWildcard(e):this._matchSimple(e))}_matchSimple(t){if(this.path.length!==t.length)return!1;for(let e=0;e<t.length;e++){const s=t[e],n=this.path[e],i=e===this.path.length-1;if(!this._matchSegment(s,n,i))return!1}return!0}_matchWithDeepWildcard(t){let e=this.path.length-1,s=t.length-1;for(;s>=0&&e>=0;){const n=t[s];if("deep-wildcard"===n.type){if(s--,s<0)return!0;const n=t[s];let i=!1;for(let t=e;t>=0;t--){const r=t===this.path.length-1;if(this._matchSegment(n,this.path[t],r)){e=t-1,s--,i=!0;break}}if(!i)return!1}else{const t=e===this.path.length-1;if(!this._matchSegment(n,this.path[e],t))return!1;e--,s--}}return s<0}_matchSegment(t,e,s){if("*"!==t.tag&&t.tag!==e.tag)return!1;if(void 0!==t.namespace&&"*"!==t.namespace&&t.namespace!==e.namespace)return!1;if(void 0!==t.attrName){if(!s)return!1;if(!e.values||!(t.attrName in e.values))return!1;if(void 0!==t.attrValue){const s=e.values[t.attrName];if(String(s)!==String(t.attrValue))return!1}}if(void 0!==t.position){if(!s)return!1;const n=e.counter??0;if("first"===t.position&&0!==n)return!1;if("odd"===t.position&&n%2!=1)return!1;if("even"===t.position&&n%2!=0)return!1;if("nth"===t.position&&n!==t.positionValue)return!1}return!0}snapshot(){return{path:this.path.map(t=>({...t})),siblingStacks:this.siblingStacks.map(t=>new Map(t))}}restore(t){this.path=t.path.map(t=>({...t})),this.siblingStacks=t.siblingStacks.map(t=>new Map(t))}readOnly(){return new Proxy(this,{get(t,e,s){if(n.has(e))return()=>{throw new TypeError(`Cannot call '${e}' on a read-only Matcher. Obtain a writable instance to mutate state.`)};const i=Reflect.get(t,e,s);return"path"===e||"siblingStacks"===e?Object.freeze(Array.isArray(i)?i.map(t=>t instanceof Map?Object.freeze(new Map(t)):Object.freeze({...t})):i):"function"==typeof i?i.bind(t):i},set(t,e){throw new TypeError(`Cannot set property '${String(e)}' on a read-only Matcher.`)},deleteProperty(t,e){throw new TypeError(`Cannot delete property '${String(e)}' from a read-only Matcher.`)}})}}const r={Expression:s,Matcher:i};module.exports=e})();
@@ -69,6 +69,17 @@ declare interface Segment {
69
69
  * const { Expression } = require('path-expression-matcher');
70
70
  * const expr = new Expression("root.users.user");
71
71
  * const expr2 = new Expression("..user[id]:first");
72
+ * const expr3 = new Expression("root/users/user", { separator: '/' });
73
+ * ```
74
+ *
75
+ * Pattern Syntax:
76
+ * - `root.users.user` - Match exact path
77
+ * - `..user` - Match "user" at any depth (deep wildcard)
78
+ * - `user[id]` - Match user tag with "id" attribute
79
+ * - `user[id=123]` - Match user tag where id="123"
80
+ * - `user:first` - Match first occurrence of user tag
81
+ * - `ns::user` - Match user tag with namespace "ns"
82
+ * - `ns::user[id]:first` - Combine namespace, attribute, and position
72
83
  * ```
73
84
  */
74
85
  declare class Expression {
@@ -177,6 +188,153 @@ declare interface MatcherSnapshot {
177
188
  siblingStacks: Map<string, number>[];
178
189
  }
179
190
 
191
+ /**
192
+ * ReadOnlyMatcher - A safe, read-only view over a {@link Matcher} instance.
193
+ *
194
+ * Returned by {@link Matcher.readOnly}. Exposes all query and inspection
195
+ * methods but **throws a `TypeError`** if any state-mutating method is called
196
+ * (`push`, `pop`, `reset`, `updateCurrent`, `restore`). Direct property
197
+ * writes are also blocked.
198
+ *
199
+ * Pass this to consumers that only need to inspect or match the current path
200
+ * so they cannot accidentally corrupt the parser state.
201
+ *
202
+ * @example
203
+ * ```javascript
204
+ * const matcher = new Matcher();
205
+ * matcher.push("root", {});
206
+ * matcher.push("users", {});
207
+ * matcher.push("user", { id: "123" });
208
+ *
209
+ * const ro: ReadOnlyMatcher = matcher.readOnly();
210
+ *
211
+ * ro.matches(expr); // ✓ works
212
+ * ro.getCurrentTag(); // ✓ "user"
213
+ * ro.getDepth(); // ✓ 3
214
+ * ro.push("child", {}); // ✗ TypeError: Cannot call 'push' on a read-only Matcher
215
+ * ro.reset(); // ✗ TypeError: Cannot call 'reset' on a read-only Matcher
216
+ * ```
217
+ */
218
+ declare interface ReadOnlyMatcher {
219
+ /**
220
+ * Default path separator (read-only)
221
+ */
222
+ readonly separator: string;
223
+
224
+ /**
225
+ * Current path stack (each node is a frozen copy)
226
+ */
227
+ readonly path: ReadonlyArray<Readonly<PathNode>>;
228
+
229
+ // ── Query methods ───────────────────────────────────────────────────────────
230
+
231
+ /**
232
+ * Get current tag name
233
+ * @returns Current tag name or undefined if path is empty
234
+ */
235
+ getCurrentTag(): string | undefined;
236
+
237
+ /**
238
+ * Get current namespace
239
+ * @returns Current namespace or undefined if not present or path is empty
240
+ */
241
+ getCurrentNamespace(): string | undefined;
242
+
243
+ /**
244
+ * Get current node's attribute value
245
+ * @param attrName - Attribute name
246
+ * @returns Attribute value or undefined
247
+ */
248
+ getAttrValue(attrName: string): any;
249
+
250
+ /**
251
+ * Check if current node has an attribute
252
+ * @param attrName - Attribute name
253
+ */
254
+ hasAttr(attrName: string): boolean;
255
+
256
+ /**
257
+ * Get current node's sibling position (child index in parent)
258
+ * @returns Position index or -1 if path is empty
259
+ */
260
+ getPosition(): number;
261
+
262
+ /**
263
+ * Get current node's repeat counter (occurrence count of this tag name)
264
+ * @returns Counter value or -1 if path is empty
265
+ */
266
+ getCounter(): number;
267
+
268
+ /**
269
+ * Get current node's sibling index (alias for getPosition for backward compatibility)
270
+ * @returns Index or -1 if path is empty
271
+ * @deprecated Use getPosition() or getCounter() instead
272
+ */
273
+ getIndex(): number;
274
+
275
+ /**
276
+ * Get current path depth
277
+ * @returns Number of nodes in the path
278
+ */
279
+ getDepth(): number;
280
+
281
+ /**
282
+ * Get path as string
283
+ * @param separator - Optional separator (uses default if not provided)
284
+ * @param includeNamespace - Whether to include namespace in output
285
+ * @returns Path string (e.g., "root.users.user" or "ns:root.ns:users.user")
286
+ */
287
+ toString(separator?: string, includeNamespace?: boolean): string;
288
+
289
+ /**
290
+ * Get path as array of tag names
291
+ * @returns Array of tag names
292
+ */
293
+ toArray(): string[];
294
+
295
+ /**
296
+ * Match current path against an Expression
297
+ * @param expression - The expression to match against
298
+ * @returns True if current path matches the expression
299
+ */
300
+ matches(expression: Expression): boolean;
301
+
302
+ /**
303
+ * Create a snapshot of current state
304
+ * @returns State snapshot that can be restored later
305
+ */
306
+ snapshot(): MatcherSnapshot;
307
+
308
+ // ── Blocked mutating methods ────────────────────────────────────────────────
309
+ // These are present in the type so callers get a compile-time error with a
310
+ // helpful message instead of a silent "property does not exist" error.
311
+
312
+ /**
313
+ * @throws {TypeError} Always – mutation is not allowed on a read-only view.
314
+ */
315
+ push(tagName: string, attrValues?: Record<string, any> | null, namespace?: string | null): never;
316
+
317
+ /**
318
+ * @throws {TypeError} Always – mutation is not allowed on a read-only view.
319
+ */
320
+ pop(): never;
321
+
322
+ /**
323
+ * @throws {TypeError} Always – mutation is not allowed on a read-only view.
324
+ */
325
+ updateCurrent(attrValues: Record<string, any>): never;
326
+
327
+ /**
328
+ * @throws {TypeError} Always – mutation is not allowed on a read-only view.
329
+ */
330
+ reset(): never;
331
+
332
+ /**
333
+ * @throws {TypeError} Always – mutation is not allowed on a read-only view.
334
+ */
335
+ restore(snapshot: MatcherSnapshot): never;
336
+ }
337
+
180
338
  /**
181
339
  * Matcher - Tracks current path in XML/JSON tree and matches against Expressions
182
340
  *
@@ -191,6 +349,12 @@ declare interface MatcherSnapshot {
191
349
  * matcher.push("root", {});
192
350
  * matcher.push("users", {});
193
351
  * matcher.push("user", { id: "123", type: "admin" });
352
+ *
353
+ * const expr = new Expression("root.users.user");
354
+ * matcher.matches(expr); // true
355
+ *
356
+ * matcher.pop();
357
+ * matcher.matches(expr); // false
194
358
  * ```
195
359
  */
196
360
  declare class Matcher {
@@ -215,6 +379,13 @@ declare class Matcher {
215
379
  * @param tagName - Name of the tag
216
380
  * @param attrValues - Attribute key-value pairs for current node (optional)
217
381
  * @param namespace - Namespace for the tag (optional)
382
+ *
383
+ * @example
384
+ * ```javascript
385
+ * matcher.push("user", { id: "123", type: "admin" });
386
+ * matcher.push("user", { id: "456" }, "ns");
387
+ * matcher.push("container", null);
388
+ * ```
218
389
  */
219
390
  push(tagName: string, attrValues?: Record<string, any> | null, namespace?: string | null): void;
220
391
 
@@ -304,6 +475,18 @@ declare class Matcher {
304
475
  * Match current path against an Expression
305
476
  * @param expression - The expression to match against
306
477
  * @returns True if current path matches the expression
478
+ *
479
+ * @example
480
+ * ```javascript
481
+ * const expr = new Expression("root.users.user[id]");
482
+ * const matcher = new Matcher();
483
+ *
484
+ * matcher.push("root");
485
+ * matcher.push("users");
486
+ * matcher.push("user", { id: "123" });
487
+ *
488
+ * matcher.matches(expr); // true
489
+ * ```
307
490
  */
308
491
  matches(expression: Expression): boolean;
309
492
 
@@ -318,6 +501,11 @@ declare class Matcher {
318
501
  * @param snapshot - State snapshot from previous snapshot() call
319
502
  */
320
503
  restore(snapshot: MatcherSnapshot): void;
504
+
505
+ /**
506
+ * Return a read-only view of this matcher.
507
+ */
508
+ readOnly(): ReadOnlyMatcher;
321
509
  }
322
510
 
323
511
  declare namespace pathExpressionMatcher {
@@ -1,2 +1,2 @@
1
- !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.pem=e():t.pem=e()}(this,()=>(()=>{"use strict";var t={d:(e,s)=>{for(var i in s)t.o(s,i)&&!t.o(e,i)&&Object.defineProperty(e,i,{enumerable:!0,get:s[i]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{Expression:()=>s,Matcher:()=>i,default:()=>n});class s{constructor(t,e={}){this.pattern=t,this.separator=e.separator||".",this.segments=this._parse(t),this._hasDeepWildcard=this.segments.some(t=>"deep-wildcard"===t.type),this._hasAttributeCondition=this.segments.some(t=>void 0!==t.attrName),this._hasPositionSelector=this.segments.some(t=>void 0!==t.position)}_parse(t){const e=[];let s=0,i="";for(;s<t.length;)t[s]===this.separator?s+1<t.length&&t[s+1]===this.separator?(i.trim()&&(e.push(this._parseSegment(i.trim())),i=""),e.push({type:"deep-wildcard"}),s+=2):(i.trim()&&e.push(this._parseSegment(i.trim())),i="",s++):(i+=t[s],s++);return i.trim()&&e.push(this._parseSegment(i.trim())),e}_parseSegment(t){const e={type:"tag"};let s=null,i=t;const n=t.match(/^([^\[]+)(\[[^\]]*\])(.*)$/);if(n&&(i=n[1]+n[3],n[2])){const t=n[2].slice(1,-1);t&&(s=t)}let r,a,h=i;if(i.includes("::")){const e=i.indexOf("::");if(r=i.substring(0,e).trim(),h=i.substring(e+2).trim(),!r)throw new Error(`Invalid namespace in pattern: ${t}`)}let o=null;if(h.includes(":")){const t=h.lastIndexOf(":"),e=h.substring(0,t).trim(),s=h.substring(t+1).trim();["first","last","odd","even"].includes(s)||/^nth\(\d+\)$/.test(s)?(a=e,o=s):a=h}else a=h;if(!a)throw new Error(`Invalid segment pattern: ${t}`);if(e.tag=a,r&&(e.namespace=r),s)if(s.includes("=")){const t=s.indexOf("=");e.attrName=s.substring(0,t).trim(),e.attrValue=s.substring(t+1).trim()}else e.attrName=s.trim();if(o){const t=o.match(/^nth\((\d+)\)$/);t?(e.position="nth",e.positionValue=parseInt(t[1],10)):e.position=o}return e}get length(){return this.segments.length}hasDeepWildcard(){return this._hasDeepWildcard}hasAttributeCondition(){return this._hasAttributeCondition}hasPositionSelector(){return this._hasPositionSelector}toString(){return this.pattern}}class i{constructor(t={}){this.separator=t.separator||".",this.path=[],this.siblingStacks=[]}push(t,e=null,s=null){this.path.length>0&&(this.path[this.path.length-1].values=void 0);const i=this.path.length;this.siblingStacks[i]||(this.siblingStacks[i]=new Map);const n=this.siblingStacks[i],r=s?`${s}:${t}`:t,a=n.get(r)||0;let h=0;for(const t of n.values())h+=t;n.set(r,a+1);const o={tag:t,position:h,counter:a};null!=s&&(o.namespace=s),null!=e&&(o.values=e),this.path.push(o)}pop(){if(0===this.path.length)return;const t=this.path.pop();return this.siblingStacks.length>this.path.length+1&&(this.siblingStacks.length=this.path.length+1),t}updateCurrent(t){if(this.path.length>0){const e=this.path[this.path.length-1];null!=t&&(e.values=t)}}getCurrentTag(){return this.path.length>0?this.path[this.path.length-1].tag:void 0}getCurrentNamespace(){return this.path.length>0?this.path[this.path.length-1].namespace:void 0}getAttrValue(t){if(0===this.path.length)return;const e=this.path[this.path.length-1];return e.values?.[t]}hasAttr(t){if(0===this.path.length)return!1;const e=this.path[this.path.length-1];return void 0!==e.values&&t in e.values}getPosition(){return 0===this.path.length?-1:this.path[this.path.length-1].position??0}getCounter(){return 0===this.path.length?-1:this.path[this.path.length-1].counter??0}getIndex(){return this.getPosition()}getDepth(){return this.path.length}toString(t,e=!0){const s=t||this.separator;return this.path.map(t=>e&&t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(s)}toArray(){return this.path.map(t=>t.tag)}reset(){this.path=[],this.siblingStacks=[]}matches(t){const e=t.segments;return 0!==e.length&&(t.hasDeepWildcard()?this._matchWithDeepWildcard(e):this._matchSimple(e))}_matchSimple(t){if(this.path.length!==t.length)return!1;for(let e=0;e<t.length;e++){const s=t[e],i=this.path[e],n=e===this.path.length-1;if(!this._matchSegment(s,i,n))return!1}return!0}_matchWithDeepWildcard(t){let e=this.path.length-1,s=t.length-1;for(;s>=0&&e>=0;){const i=t[s];if("deep-wildcard"===i.type){if(s--,s<0)return!0;const i=t[s];let n=!1;for(let t=e;t>=0;t--){const r=t===this.path.length-1;if(this._matchSegment(i,this.path[t],r)){e=t-1,s--,n=!0;break}}if(!n)return!1}else{const t=e===this.path.length-1;if(!this._matchSegment(i,this.path[e],t))return!1;e--,s--}}return s<0}_matchSegment(t,e,s){if("*"!==t.tag&&t.tag!==e.tag)return!1;if(void 0!==t.namespace&&"*"!==t.namespace&&t.namespace!==e.namespace)return!1;if(void 0!==t.attrName){if(!s)return!1;if(!e.values||!(t.attrName in e.values))return!1;if(void 0!==t.attrValue){const s=e.values[t.attrName];if(String(s)!==String(t.attrValue))return!1}}if(void 0!==t.position){if(!s)return!1;const i=e.counter??0;if("first"===t.position&&0!==i)return!1;if("odd"===t.position&&i%2!=1)return!1;if("even"===t.position&&i%2!=0)return!1;if("nth"===t.position&&i!==t.positionValue)return!1}return!0}snapshot(){return{path:this.path.map(t=>({...t})),siblingStacks:this.siblingStacks.map(t=>new Map(t))}}restore(t){this.path=t.path.map(t=>({...t})),this.siblingStacks=t.siblingStacks.map(t=>new Map(t))}}const n={Expression:s,Matcher:i};return e})());
1
+ !function(t,e){"object"==typeof exports&&"object"==typeof module?module.exports=e():"function"==typeof define&&define.amd?define([],e):"object"==typeof exports?exports.pem=e():t.pem=e()}(this,()=>(()=>{"use strict";var t={d:(e,s)=>{for(var n in s)t.o(s,n)&&!t.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:s[n]})},o:(t,e)=>Object.prototype.hasOwnProperty.call(t,e),r:t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})}},e={};t.r(e),t.d(e,{Expression:()=>s,Matcher:()=>i,default:()=>r});class s{constructor(t,e={}){this.pattern=t,this.separator=e.separator||".",this.segments=this._parse(t),this._hasDeepWildcard=this.segments.some(t=>"deep-wildcard"===t.type),this._hasAttributeCondition=this.segments.some(t=>void 0!==t.attrName),this._hasPositionSelector=this.segments.some(t=>void 0!==t.position)}_parse(t){const e=[];let s=0,n="";for(;s<t.length;)t[s]===this.separator?s+1<t.length&&t[s+1]===this.separator?(n.trim()&&(e.push(this._parseSegment(n.trim())),n=""),e.push({type:"deep-wildcard"}),s+=2):(n.trim()&&e.push(this._parseSegment(n.trim())),n="",s++):(n+=t[s],s++);return n.trim()&&e.push(this._parseSegment(n.trim())),e}_parseSegment(t){const e={type:"tag"};let s=null,n=t;const i=t.match(/^([^\[]+)(\[[^\]]*\])(.*)$/);if(i&&(n=i[1]+i[3],i[2])){const t=i[2].slice(1,-1);t&&(s=t)}let r,a,h=n;if(n.includes("::")){const e=n.indexOf("::");if(r=n.substring(0,e).trim(),h=n.substring(e+2).trim(),!r)throw new Error(`Invalid namespace in pattern: ${t}`)}let o=null;if(h.includes(":")){const t=h.lastIndexOf(":"),e=h.substring(0,t).trim(),s=h.substring(t+1).trim();["first","last","odd","even"].includes(s)||/^nth\(\d+\)$/.test(s)?(a=e,o=s):a=h}else a=h;if(!a)throw new Error(`Invalid segment pattern: ${t}`);if(e.tag=a,r&&(e.namespace=r),s)if(s.includes("=")){const t=s.indexOf("=");e.attrName=s.substring(0,t).trim(),e.attrValue=s.substring(t+1).trim()}else e.attrName=s.trim();if(o){const t=o.match(/^nth\((\d+)\)$/);t?(e.position="nth",e.positionValue=parseInt(t[1],10)):e.position=o}return e}get length(){return this.segments.length}hasDeepWildcard(){return this._hasDeepWildcard}hasAttributeCondition(){return this._hasAttributeCondition}hasPositionSelector(){return this._hasPositionSelector}toString(){return this.pattern}}const n=new Set(["push","pop","reset","updateCurrent","restore"]);class i{constructor(t={}){this.separator=t.separator||".",this.path=[],this.siblingStacks=[]}push(t,e=null,s=null){this.path.length>0&&(this.path[this.path.length-1].values=void 0);const n=this.path.length;this.siblingStacks[n]||(this.siblingStacks[n]=new Map);const i=this.siblingStacks[n],r=s?`${s}:${t}`:t,a=i.get(r)||0;let h=0;for(const t of i.values())h+=t;i.set(r,a+1);const o={tag:t,position:h,counter:a};null!=s&&(o.namespace=s),null!=e&&(o.values=e),this.path.push(o)}pop(){if(0===this.path.length)return;const t=this.path.pop();return this.siblingStacks.length>this.path.length+1&&(this.siblingStacks.length=this.path.length+1),t}updateCurrent(t){if(this.path.length>0){const e=this.path[this.path.length-1];null!=t&&(e.values=t)}}getCurrentTag(){return this.path.length>0?this.path[this.path.length-1].tag:void 0}getCurrentNamespace(){return this.path.length>0?this.path[this.path.length-1].namespace:void 0}getAttrValue(t){if(0===this.path.length)return;const e=this.path[this.path.length-1];return e.values?.[t]}hasAttr(t){if(0===this.path.length)return!1;const e=this.path[this.path.length-1];return void 0!==e.values&&t in e.values}getPosition(){return 0===this.path.length?-1:this.path[this.path.length-1].position??0}getCounter(){return 0===this.path.length?-1:this.path[this.path.length-1].counter??0}getIndex(){return this.getPosition()}getDepth(){return this.path.length}toString(t,e=!0){const s=t||this.separator;return this.path.map(t=>e&&t.namespace?`${t.namespace}:${t.tag}`:t.tag).join(s)}toArray(){return this.path.map(t=>t.tag)}reset(){this.path=[],this.siblingStacks=[]}matches(t){const e=t.segments;return 0!==e.length&&(t.hasDeepWildcard()?this._matchWithDeepWildcard(e):this._matchSimple(e))}_matchSimple(t){if(this.path.length!==t.length)return!1;for(let e=0;e<t.length;e++){const s=t[e],n=this.path[e],i=e===this.path.length-1;if(!this._matchSegment(s,n,i))return!1}return!0}_matchWithDeepWildcard(t){let e=this.path.length-1,s=t.length-1;for(;s>=0&&e>=0;){const n=t[s];if("deep-wildcard"===n.type){if(s--,s<0)return!0;const n=t[s];let i=!1;for(let t=e;t>=0;t--){const r=t===this.path.length-1;if(this._matchSegment(n,this.path[t],r)){e=t-1,s--,i=!0;break}}if(!i)return!1}else{const t=e===this.path.length-1;if(!this._matchSegment(n,this.path[e],t))return!1;e--,s--}}return s<0}_matchSegment(t,e,s){if("*"!==t.tag&&t.tag!==e.tag)return!1;if(void 0!==t.namespace&&"*"!==t.namespace&&t.namespace!==e.namespace)return!1;if(void 0!==t.attrName){if(!s)return!1;if(!e.values||!(t.attrName in e.values))return!1;if(void 0!==t.attrValue){const s=e.values[t.attrName];if(String(s)!==String(t.attrValue))return!1}}if(void 0!==t.position){if(!s)return!1;const n=e.counter??0;if("first"===t.position&&0!==n)return!1;if("odd"===t.position&&n%2!=1)return!1;if("even"===t.position&&n%2!=0)return!1;if("nth"===t.position&&n!==t.positionValue)return!1}return!0}snapshot(){return{path:this.path.map(t=>({...t})),siblingStacks:this.siblingStacks.map(t=>new Map(t))}}restore(t){this.path=t.path.map(t=>({...t})),this.siblingStacks=t.siblingStacks.map(t=>new Map(t))}readOnly(){return new Proxy(this,{get(t,e,s){if(n.has(e))return()=>{throw new TypeError(`Cannot call '${e}' on a read-only Matcher. Obtain a writable instance to mutate state.`)};const i=Reflect.get(t,e,s);return"path"===e||"siblingStacks"===e?Object.freeze(Array.isArray(i)?i.map(t=>t instanceof Map?Object.freeze(new Map(t)):Object.freeze({...t})):i):"function"==typeof i?i.bind(t):i},set(t,e){throw new TypeError(`Cannot set property '${String(e)}' on a read-only Matcher.`)},deleteProperty(t,e){throw new TypeError(`Cannot delete property '${String(e)}' from a read-only Matcher.`)}})}}const r={Expression:s,Matcher:i};return e})());
2
2
  //# sourceMappingURL=pem.min.js.map