pem.d.cts 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634
  1. /**
  2. * TypeScript definitions for path-expression-matcher (CommonJS)
  3. */
  4. /**
  5. * Options for creating an Expression
  6. */
  7. declare interface ExpressionOptions {
  8. /**
  9. * Path separator character
  10. * @default '.'
  11. */
  12. separator?: string;
  13. }
  14. /**
  15. * Parsed segment from an expression pattern
  16. */
  17. declare interface Segment {
  18. /**
  19. * Type of segment
  20. */
  21. type: 'tag' | 'deep-wildcard';
  22. /**
  23. * Tag name (e.g., "user", "*" for wildcard)
  24. * Only present when type is 'tag'
  25. */
  26. tag?: string;
  27. /**
  28. * Namespace prefix (e.g., "ns" in "ns::user")
  29. * Only present when namespace is specified
  30. */
  31. namespace?: string;
  32. /**
  33. * Attribute name to match (e.g., "id" in "user[id]")
  34. * Only present when attribute condition exists
  35. */
  36. attrName?: string;
  37. /**
  38. * Attribute value to match (e.g., "123" in "user[id=123]")
  39. * Only present when attribute value is specified
  40. */
  41. attrValue?: string;
  42. /**
  43. * Position selector type
  44. * Only present when position selector exists
  45. */
  46. position?: 'first' | 'last' | 'odd' | 'even' | 'nth';
  47. /**
  48. * Numeric value for nth() selector
  49. * Only present when position is 'nth'
  50. */
  51. positionValue?: number;
  52. }
  53. /**
  54. * Expression - Parses and stores a tag pattern expression
  55. *
  56. * Patterns are parsed once and stored in an optimized structure for fast matching.
  57. *
  58. * @example
  59. * ```javascript
  60. * const { Expression } = require('path-expression-matcher');
  61. * const expr = new Expression("root.users.user");
  62. * const expr2 = new Expression("..user[id]:first");
  63. * const expr3 = new Expression("root/users/user", { separator: '/' });
  64. * ```
  65. *
  66. * Pattern Syntax:
  67. * - `root.users.user` - Match exact path
  68. * - `..user` - Match "user" at any depth (deep wildcard)
  69. * - `user[id]` - Match user tag with "id" attribute
  70. * - `user[id=123]` - Match user tag where id="123"
  71. * - `user:first` - Match first occurrence of user tag
  72. * - `ns::user` - Match user tag with namespace "ns"
  73. * - `ns::user[id]:first` - Combine namespace, attribute, and position
  74. * ```
  75. */
  76. declare class Expression {
  77. /**
  78. * Original pattern string
  79. */
  80. readonly pattern: string;
  81. /**
  82. * Path separator character
  83. */
  84. readonly separator: string;
  85. /**
  86. * Parsed segments
  87. */
  88. readonly segments: Segment[];
  89. /**
  90. * Create a new Expression
  91. * @param pattern - Pattern string (e.g., "root.users.user", "..user[id]")
  92. * @param options - Configuration options
  93. */
  94. constructor(pattern: string, options?: ExpressionOptions);
  95. /**
  96. * Get the number of segments
  97. */
  98. get length(): number;
  99. /**
  100. * Check if expression contains deep wildcard (..)
  101. */
  102. hasDeepWildcard(): boolean;
  103. /**
  104. * Check if expression has attribute conditions
  105. */
  106. hasAttributeCondition(): boolean;
  107. /**
  108. * Check if expression has position selectors
  109. */
  110. hasPositionSelector(): boolean;
  111. /**
  112. * Get string representation
  113. */
  114. toString(): string;
  115. }
  116. /**
  117. * Options for creating a Matcher
  118. */
  119. declare interface MatcherOptions {
  120. /**
  121. * Default path separator
  122. * @default '.'
  123. */
  124. separator?: string;
  125. }
  126. /**
  127. * Internal node structure in the path stack
  128. */
  129. declare interface PathNode {
  130. /**
  131. * Tag name
  132. */
  133. tag: string;
  134. /**
  135. * Namespace (if present)
  136. */
  137. namespace?: string;
  138. /**
  139. * Position in sibling list (child index in parent)
  140. */
  141. position: number;
  142. /**
  143. * Counter (occurrence count of this tag name)
  144. */
  145. counter: number;
  146. /**
  147. * Attribute key-value pairs
  148. * Only present for the current (last) node in path
  149. */
  150. values?: Record<string, any>;
  151. }
  152. /**
  153. * Snapshot of matcher state
  154. */
  155. declare interface MatcherSnapshot {
  156. /**
  157. * Copy of the path stack
  158. */
  159. path: PathNode[];
  160. /**
  161. * Copy of sibling tracking maps
  162. */
  163. siblingStacks: Map<string, number>[];
  164. }
  165. /**
  166. * ReadOnlyMatcher - A safe, read-only view over a {@link Matcher} instance.
  167. *
  168. * Returned by {@link Matcher.readOnly}. Exposes all query and inspection
  169. * methods but **throws a `TypeError`** if any state-mutating method is called
  170. * (`push`, `pop`, `reset`, `updateCurrent`, `restore`). Direct property
  171. * writes are also blocked.
  172. *
  173. * Pass this to consumers that only need to inspect or match the current path
  174. * so they cannot accidentally corrupt the parser state.
  175. *
  176. * @example
  177. * ```javascript
  178. * const matcher = new Matcher();
  179. * matcher.push("root", {});
  180. * matcher.push("users", {});
  181. * matcher.push("user", { id: "123" });
  182. *
  183. * const ro: ReadOnlyMatcher = matcher.readOnly();
  184. *
  185. * ro.matches(expr); // ✓ works
  186. * ro.getCurrentTag(); // ✓ "user"
  187. * ro.getDepth(); // ✓ 3
  188. * ro.push("child", {}); // ✗ TypeError: Cannot call 'push' on a read-only Matcher
  189. * ro.reset(); // ✗ TypeError: Cannot call 'reset' on a read-only Matcher
  190. * ```
  191. */
  192. declare interface ReadOnlyMatcher {
  193. /**
  194. * Default path separator (read-only)
  195. */
  196. readonly separator: string;
  197. /**
  198. * Current path stack (each node is a frozen copy)
  199. */
  200. readonly path: ReadonlyArray<Readonly<PathNode>>;
  201. // ── Query methods ───────────────────────────────────────────────────────────
  202. /**
  203. * Get current tag name
  204. * @returns Current tag name or undefined if path is empty
  205. */
  206. getCurrentTag(): string | undefined;
  207. /**
  208. * Get current namespace
  209. * @returns Current namespace or undefined if not present or path is empty
  210. */
  211. getCurrentNamespace(): string | undefined;
  212. /**
  213. * Get current node's attribute value
  214. * @param attrName - Attribute name
  215. * @returns Attribute value or undefined
  216. */
  217. getAttrValue(attrName: string): any;
  218. /**
  219. * Check if current node has an attribute
  220. * @param attrName - Attribute name
  221. */
  222. hasAttr(attrName: string): boolean;
  223. /**
  224. * Get current node's sibling position (child index in parent)
  225. * @returns Position index or -1 if path is empty
  226. */
  227. getPosition(): number;
  228. /**
  229. * Get current node's repeat counter (occurrence count of this tag name)
  230. * @returns Counter value or -1 if path is empty
  231. */
  232. getCounter(): number;
  233. /**
  234. * Get current node's sibling index (alias for getPosition for backward compatibility)
  235. * @returns Index or -1 if path is empty
  236. * @deprecated Use getPosition() or getCounter() instead
  237. */
  238. getIndex(): number;
  239. /**
  240. * Get current path depth
  241. * @returns Number of nodes in the path
  242. */
  243. getDepth(): number;
  244. /**
  245. * Get path as string
  246. * @param separator - Optional separator (uses default if not provided)
  247. * @param includeNamespace - Whether to include namespace in output
  248. * @returns Path string (e.g., "root.users.user" or "ns:root.ns:users.user")
  249. */
  250. toString(separator?: string, includeNamespace?: boolean): string;
  251. /**
  252. * Get path as array of tag names
  253. * @returns Array of tag names
  254. */
  255. toArray(): string[];
  256. /**
  257. * Match current path against an Expression
  258. * @param expression - The expression to match against
  259. * @returns True if current path matches the expression
  260. */
  261. matches(expression: Expression): boolean;
  262. /**
  263. * Test whether the matcher's current path matches **any** expression in the set.
  264. *
  265. * @param exprSet - A `ExpressionSet` instance
  266. * @returns `true` if at least one expression matches the current path
  267. */
  268. matchesAny(exprSet: ExpressionSet): boolean;
  269. /**
  270. * Create a snapshot of current state
  271. * @returns State snapshot that can be restored later
  272. */
  273. snapshot(): MatcherSnapshot;
  274. // ── Blocked mutating methods ────────────────────────────────────────────────
  275. // These are present in the type so callers get a compile-time error with a
  276. // helpful message instead of a silent "property does not exist" error.
  277. /**
  278. * @throws {TypeError} Always – mutation is not allowed on a read-only view.
  279. */
  280. push(tagName: string, attrValues?: Record<string, any> | null, namespace?: string | null): never;
  281. /**
  282. * @throws {TypeError} Always – mutation is not allowed on a read-only view.
  283. */
  284. pop(): never;
  285. /**
  286. * @throws {TypeError} Always – mutation is not allowed on a read-only view.
  287. */
  288. updateCurrent(attrValues: Record<string, any>): never;
  289. /**
  290. * @throws {TypeError} Always – mutation is not allowed on a read-only view.
  291. */
  292. reset(): never;
  293. /**
  294. * @throws {TypeError} Always – mutation is not allowed on a read-only view.
  295. */
  296. restore(snapshot: MatcherSnapshot): never;
  297. }
  298. /**
  299. * Matcher - Tracks current path in XML/JSON tree and matches against Expressions
  300. *
  301. * The matcher maintains a stack of nodes representing the current path from root to
  302. * current tag. It only stores attribute values for the current (top) node to minimize
  303. * memory usage.
  304. *
  305. * @example
  306. * ```javascript
  307. * const { Matcher } = require('path-expression-matcher');
  308. * const matcher = new Matcher();
  309. * matcher.push("root", {});
  310. * matcher.push("users", {});
  311. * matcher.push("user", { id: "123", type: "admin" });
  312. *
  313. * const expr = new Expression("root.users.user");
  314. * matcher.matches(expr); // true
  315. *
  316. * matcher.pop();
  317. * matcher.matches(expr); // false
  318. * ```
  319. */
  320. declare class Matcher {
  321. /**
  322. * Default path separator
  323. */
  324. readonly separator: string;
  325. /**
  326. * Current path stack
  327. */
  328. readonly path: PathNode[];
  329. /**
  330. * Create a new Matcher
  331. * @param options - Configuration options
  332. */
  333. constructor(options?: MatcherOptions);
  334. /**
  335. * Push a new tag onto the path
  336. * @param tagName - Name of the tag
  337. * @param attrValues - Attribute key-value pairs for current node (optional)
  338. * @param namespace - Namespace for the tag (optional)
  339. *
  340. * @example
  341. * ```javascript
  342. * matcher.push("user", { id: "123", type: "admin" });
  343. * matcher.push("user", { id: "456" }, "ns");
  344. * matcher.push("container", null);
  345. * ```
  346. */
  347. push(tagName: string, attrValues?: Record<string, any> | null, namespace?: string | null): void;
  348. /**
  349. * Pop the last tag from the path
  350. * @returns The popped node or undefined if path is empty
  351. */
  352. pop(): PathNode | undefined;
  353. /**
  354. * Update current node's attribute values
  355. * Useful when attributes are parsed after push
  356. * @param attrValues - Attribute values
  357. */
  358. updateCurrent(attrValues: Record<string, any>): void;
  359. /**
  360. * Get current tag name
  361. * @returns Current tag name or undefined if path is empty
  362. */
  363. getCurrentTag(): string | undefined;
  364. /**
  365. * Get current namespace
  366. * @returns Current namespace or undefined if not present or path is empty
  367. */
  368. getCurrentNamespace(): string | undefined;
  369. /**
  370. * Get current node's attribute value
  371. * @param attrName - Attribute name
  372. * @returns Attribute value or undefined
  373. */
  374. getAttrValue(attrName: string): any;
  375. /**
  376. * Check if current node has an attribute
  377. * @param attrName - Attribute name
  378. */
  379. hasAttr(attrName: string): boolean;
  380. /**
  381. * Get current node's sibling position (child index in parent)
  382. * @returns Position index or -1 if path is empty
  383. */
  384. getPosition(): number;
  385. /**
  386. * Get current node's repeat counter (occurrence count of this tag name)
  387. * @returns Counter value or -1 if path is empty
  388. */
  389. getCounter(): number;
  390. /**
  391. * Get current node's sibling index (alias for getPosition for backward compatibility)
  392. * @returns Index or -1 if path is empty
  393. * @deprecated Use getPosition() or getCounter() instead
  394. */
  395. getIndex(): number;
  396. /**
  397. * Get current path depth
  398. * @returns Number of nodes in the path
  399. */
  400. getDepth(): number;
  401. /**
  402. * Get path as string
  403. * @param separator - Optional separator (uses default if not provided)
  404. * @param includeNamespace - Whether to include namespace in output
  405. * @returns Path string (e.g., "root.users.user" or "ns:root.ns:users.user")
  406. */
  407. toString(separator?: string, includeNamespace?: boolean): string;
  408. /**
  409. * Get path as array of tag names
  410. * @returns Array of tag names
  411. */
  412. toArray(): string[];
  413. /**
  414. * Reset the path to empty
  415. */
  416. reset(): void;
  417. /**
  418. * Match current path against an Expression
  419. * @param expression - The expression to match against
  420. * @returns True if current path matches the expression
  421. *
  422. * @example
  423. * ```javascript
  424. * const expr = new Expression("root.users.user[id]");
  425. * const matcher = new Matcher();
  426. *
  427. * matcher.push("root");
  428. * matcher.push("users");
  429. * matcher.push("user", { id: "123" });
  430. *
  431. * matcher.matches(expr); // true
  432. * ```
  433. */
  434. matches(expression: Expression): boolean;
  435. /**
  436. * Test whether the matcher's current path matches **any** expression in the set.
  437. *
  438. * Uses the pre-built index to evaluate only the relevant bucket(s):
  439. * 1. Exact depth + tag — O(1) lookup
  440. * 2. Depth-matched wildcard tag — O(1) lookup
  441. * 3. Deep-wildcard expressions — always scanned (typically a small list)
  442. *
  443. * @param exprSet - A `ExpressionSet` instance
  444. * @returns `true` if at least one expression matches the current path
  445. *
  446. * @example
  447. * ```typescript
  448. * // Replaces:
  449. * // for (const expr of stopNodeExpressions) {
  450. * // if (matcher.matches(expr)) return true;
  451. * // }
  452. *
  453. * if (matcher.matchesAny(stopNodes)) {
  454. * // current tag is a stop node
  455. * }
  456. * ```
  457. */
  458. matchesAny(exprSet: ExpressionSet): boolean;
  459. /**
  460. * Create a snapshot of current state
  461. * @returns State snapshot that can be restored later
  462. */
  463. snapshot(): MatcherSnapshot;
  464. /**
  465. * Restore state from snapshot
  466. * @param snapshot - State snapshot from previous snapshot() call
  467. */
  468. restore(snapshot: MatcherSnapshot): void;
  469. /**
  470. * Return a read-only view of this matcher.
  471. */
  472. readOnly(): ReadOnlyMatcher;
  473. }
  474. /**
  475. * ExpressionSet - An indexed collection of Expressions for efficient bulk matching
  476. *
  477. * Pre-indexes expressions at insertion time by depth and terminal tag name so
  478. * that `matchesAny()` performs an O(1) bucket lookup rather than a full O(E)
  479. * linear scan on every tag.
  480. *
  481. * @example
  482. * ```javascript
  483. * const { Expression, ExpressionSet, Matcher } = require('path-expression-matcher');
  484. *
  485. * // Build once at config time
  486. * const stopNodes = new ExpressionSet();
  487. * stopNodes
  488. * .add(new Expression('root.users.user'))
  489. * .add(new Expression('root.config.*'))
  490. * .add(new Expression('..script'))
  491. * .seal();
  492. *
  493. * // Per-tag — hot path
  494. * if (stopNodes.matchesAny(matcher)) { ... }
  495. * ```
  496. */
  497. declare class ExpressionSet {
  498. constructor();
  499. /** Number of expressions currently in the set. */
  500. readonly size: number;
  501. /** Whether the set has been sealed against further modifications. */
  502. readonly isSealed: boolean;
  503. /**
  504. * Add a single Expression. Duplicate patterns are silently ignored.
  505. * @throws {TypeError} if the set has been sealed
  506. */
  507. add(expression: Expression): this;
  508. /**
  509. * Add multiple expressions at once.
  510. * @throws {TypeError} if the set has been sealed
  511. */
  512. addAll(expressions: Expression[]): this;
  513. /** Check whether an expression with the same pattern is already present. */
  514. has(expression: Expression): boolean;
  515. /**
  516. * Seal the set against further modifications.
  517. * Any subsequent call to add() or addAll() will throw a TypeError.
  518. */
  519. seal(): this;
  520. /**
  521. * Test whether the matcher's current path matches any expression in the set.
  522. * Accepts both a Matcher instance and a ReadOnlyMatcher view.
  523. *
  524. *
  525. * @param matcher - A `Matcher` instance or a `ReadOnlyMatcher` view
  526. * @returns Expression if at least one expression matches the current path
  527. */
  528. matchesAny(matcher: Matcher | ReadOnlyMatcher): boolean;
  529. /**
  530. * Find the first expression in the set that matches the matcher's current path.
  531. *
  532. * @param matcher - A `Matcher` instance or a `ReadOnlyMatcher` view
  533. * @returns Expression if at least one expression matches the current path
  534. *
  535. * @example
  536. * ```typescript
  537. * const node = stopNodes.findMatch(matcher);
  538. * ```
  539. */
  540. findMatch(matcher: Matcher | ReadOnlyMatcher): Expression;
  541. }
  542. declare namespace pathExpressionMatcher {
  543. export {
  544. Expression,
  545. Matcher,
  546. ExpressionSet,
  547. ExpressionOptions,
  548. MatcherOptions,
  549. Segment,
  550. PathNode,
  551. MatcherSnapshot,
  552. };
  553. }
  554. export = pathExpressionMatcher;