UNPKG

lambda-live-debugger

Version:

Debug Lambda functions locally like it is running in the cloud

524 lines (454 loc) 13 kB
/** * TypeScript definitions for path-expression-matcher (CommonJS) */ /** * Options for creating an Expression */ declare interface ExpressionOptions { /** * Path separator character * @default '.' */ separator?: string; } /** * Parsed segment from an expression pattern */ declare interface Segment { /** * Type of segment */ type: 'tag' | 'deep-wildcard'; /** * Tag name (e.g., "user", "*" for wildcard) * Only present when type is 'tag' */ tag?: string; /** * Namespace prefix (e.g., "ns" in "ns::user") * Only present when namespace is specified */ namespace?: string; /** * Attribute name to match (e.g., "id" in "user[id]") * Only present when attribute condition exists */ attrName?: string; /** * Attribute value to match (e.g., "123" in "user[id=123]") * Only present when attribute value is specified */ attrValue?: string; /** * Position selector type * Only present when position selector exists */ position?: 'first' | 'last' | 'odd' | 'even' | 'nth'; /** * Numeric value for nth() selector * Only present when position is 'nth' */ positionValue?: number; } /** * Expression - Parses and stores a tag pattern expression * * Patterns are parsed once and stored in an optimized structure for fast matching. * * @example * ```javascript * const { Expression } = require('path-expression-matcher'); * const expr = new Expression("root.users.user"); * const expr2 = new Expression("..user[id]:first"); * const expr3 = new Expression("root/users/user", { separator: '/' }); * ``` * * Pattern Syntax: * - `root.users.user` - Match exact path * - `..user` - Match "user" at any depth (deep wildcard) * - `user[id]` - Match user tag with "id" attribute * - `user[id=123]` - Match user tag where id="123" * - `user:first` - Match first occurrence of user tag * - `ns::user` - Match user tag with namespace "ns" * - `ns::user[id]:first` - Combine namespace, attribute, and position * ``` */ declare class Expression { /** * Original pattern string */ readonly pattern: string; /** * Path separator character */ readonly separator: string; /** * Parsed segments */ readonly segments: Segment[]; /** * Create a new Expression * @param pattern - Pattern string (e.g., "root.users.user", "..user[id]") * @param options - Configuration options */ constructor(pattern: string, options?: ExpressionOptions); /** * Get the number of segments */ get length(): number; /** * Check if expression contains deep wildcard (..) */ hasDeepWildcard(): boolean; /** * Check if expression has attribute conditions */ hasAttributeCondition(): boolean; /** * Check if expression has position selectors */ hasPositionSelector(): boolean; /** * Get string representation */ toString(): string; } /** * Options for creating a Matcher */ declare interface MatcherOptions { /** * Default path separator * @default '.' */ separator?: string; } /** * Internal node structure in the path stack */ declare interface PathNode { /** * Tag name */ tag: string; /** * Namespace (if present) */ namespace?: string; /** * Position in sibling list (child index in parent) */ position: number; /** * Counter (occurrence count of this tag name) */ counter: number; /** * Attribute key-value pairs * Only present for the current (last) node in path */ values?: Record<string, any>; } /** * Snapshot of matcher state */ declare interface MatcherSnapshot { /** * Copy of the path stack */ path: PathNode[]; /** * Copy of sibling tracking maps */ siblingStacks: Map<string, number>[]; } /** * ReadOnlyMatcher - A safe, read-only view over a {@link Matcher} instance. * * Returned by {@link Matcher.readOnly}. Exposes all query and inspection * methods but **throws a `TypeError`** if any state-mutating method is called * (`push`, `pop`, `reset`, `updateCurrent`, `restore`). Direct property * writes are also blocked. * * Pass this to consumers that only need to inspect or match the current path * so they cannot accidentally corrupt the parser state. * * @example * ```javascript * const matcher = new Matcher(); * matcher.push("root", {}); * matcher.push("users", {}); * matcher.push("user", { id: "123" }); * * const ro: ReadOnlyMatcher = matcher.readOnly(); * * ro.matches(expr); // ✓ works * ro.getCurrentTag(); // ✓ "user" * ro.getDepth(); // ✓ 3 * ro.push("child", {}); // ✗ TypeError: Cannot call 'push' on a read-only Matcher * ro.reset(); // ✗ TypeError: Cannot call 'reset' on a read-only Matcher * ``` */ declare interface ReadOnlyMatcher { /** * Default path separator (read-only) */ readonly separator: string; /** * Current path stack (each node is a frozen copy) */ readonly path: ReadonlyArray<Readonly<PathNode>>; // ── Query methods ─────────────────────────────────────────────────────────── /** * Get current tag name * @returns Current tag name or undefined if path is empty */ getCurrentTag(): string | undefined; /** * Get current namespace * @returns Current namespace or undefined if not present or path is empty */ getCurrentNamespace(): string | undefined; /** * Get current node's attribute value * @param attrName - Attribute name * @returns Attribute value or undefined */ getAttrValue(attrName: string): any; /** * Check if current node has an attribute * @param attrName - Attribute name */ hasAttr(attrName: string): boolean; /** * Get current node's sibling position (child index in parent) * @returns Position index or -1 if path is empty */ getPosition(): number; /** * Get current node's repeat counter (occurrence count of this tag name) * @returns Counter value or -1 if path is empty */ getCounter(): number; /** * Get current node's sibling index (alias for getPosition for backward compatibility) * @returns Index or -1 if path is empty * @deprecated Use getPosition() or getCounter() instead */ getIndex(): number; /** * Get current path depth * @returns Number of nodes in the path */ getDepth(): number; /** * Get path as string * @param separator - Optional separator (uses default if not provided) * @param includeNamespace - Whether to include namespace in output * @returns Path string (e.g., "root.users.user" or "ns:root.ns:users.user") */ toString(separator?: string, includeNamespace?: boolean): string; /** * Get path as array of tag names * @returns Array of tag names */ toArray(): string[]; /** * Match current path against an Expression * @param expression - The expression to match against * @returns True if current path matches the expression */ matches(expression: Expression): boolean; /** * Create a snapshot of current state * @returns State snapshot that can be restored later */ snapshot(): MatcherSnapshot; // ── Blocked mutating methods ──────────────────────────────────────────────── // These are present in the type so callers get a compile-time error with a // helpful message instead of a silent "property does not exist" error. /** * @throws {TypeError} Always – mutation is not allowed on a read-only view. */ push(tagName: string, attrValues?: Record<string, any> | null, namespace?: string | null): never; /** * @throws {TypeError} Always – mutation is not allowed on a read-only view. */ pop(): never; /** * @throws {TypeError} Always – mutation is not allowed on a read-only view. */ updateCurrent(attrValues: Record<string, any>): never; /** * @throws {TypeError} Always – mutation is not allowed on a read-only view. */ reset(): never; /** * @throws {TypeError} Always – mutation is not allowed on a read-only view. */ restore(snapshot: MatcherSnapshot): never; } /** * Matcher - Tracks current path in XML/JSON tree and matches against Expressions * * The matcher maintains a stack of nodes representing the current path from root to * current tag. It only stores attribute values for the current (top) node to minimize * memory usage. * * @example * ```javascript * const { Matcher } = require('path-expression-matcher'); * const matcher = new Matcher(); * matcher.push("root", {}); * matcher.push("users", {}); * matcher.push("user", { id: "123", type: "admin" }); * * const expr = new Expression("root.users.user"); * matcher.matches(expr); // true * * matcher.pop(); * matcher.matches(expr); // false * ``` */ declare class Matcher { /** * Default path separator */ readonly separator: string; /** * Current path stack */ readonly path: PathNode[]; /** * Create a new Matcher * @param options - Configuration options */ constructor(options?: MatcherOptions); /** * Push a new tag onto the path * @param tagName - Name of the tag * @param attrValues - Attribute key-value pairs for current node (optional) * @param namespace - Namespace for the tag (optional) * * @example * ```javascript * matcher.push("user", { id: "123", type: "admin" }); * matcher.push("user", { id: "456" }, "ns"); * matcher.push("container", null); * ``` */ push(tagName: string, attrValues?: Record<string, any> | null, namespace?: string | null): void; /** * Pop the last tag from the path * @returns The popped node or undefined if path is empty */ pop(): PathNode | undefined; /** * Update current node's attribute values * Useful when attributes are parsed after push * @param attrValues - Attribute values */ updateCurrent(attrValues: Record<string, any>): void; /** * Get current tag name * @returns Current tag name or undefined if path is empty */ getCurrentTag(): string | undefined; /** * Get current namespace * @returns Current namespace or undefined if not present or path is empty */ getCurrentNamespace(): string | undefined; /** * Get current node's attribute value * @param attrName - Attribute name * @returns Attribute value or undefined */ getAttrValue(attrName: string): any; /** * Check if current node has an attribute * @param attrName - Attribute name */ hasAttr(attrName: string): boolean; /** * Get current node's sibling position (child index in parent) * @returns Position index or -1 if path is empty */ getPosition(): number; /** * Get current node's repeat counter (occurrence count of this tag name) * @returns Counter value or -1 if path is empty */ getCounter(): number; /** * Get current node's sibling index (alias for getPosition for backward compatibility) * @returns Index or -1 if path is empty * @deprecated Use getPosition() or getCounter() instead */ getIndex(): number; /** * Get current path depth * @returns Number of nodes in the path */ getDepth(): number; /** * Get path as string * @param separator - Optional separator (uses default if not provided) * @param includeNamespace - Whether to include namespace in output * @returns Path string (e.g., "root.users.user" or "ns:root.ns:users.user") */ toString(separator?: string, includeNamespace?: boolean): string; /** * Get path as array of tag names * @returns Array of tag names */ toArray(): string[]; /** * Reset the path to empty */ reset(): void; /** * Match current path against an Expression * @param expression - The expression to match against * @returns True if current path matches the expression * * @example * ```javascript * const expr = new Expression("root.users.user[id]"); * const matcher = new Matcher(); * * matcher.push("root"); * matcher.push("users"); * matcher.push("user", { id: "123" }); * * matcher.matches(expr); // true * ``` */ matches(expression: Expression): boolean; /** * Create a snapshot of current state * @returns State snapshot that can be restored later */ snapshot(): MatcherSnapshot; /** * Restore state from snapshot * @param snapshot - State snapshot from previous snapshot() call */ restore(snapshot: MatcherSnapshot): void; /** * Return a read-only view of this matcher. */ readOnly(): ReadOnlyMatcher; } declare namespace pathExpressionMatcher { export { Expression, Matcher, ExpressionOptions, MatcherOptions, Segment, PathNode, MatcherSnapshot, }; } export = pathExpressionMatcher;