import type { Maybe } from '@dereekb/util'; /** * One brace-delimited block extracted by {@link extractTopLevelBlocks}: a `match`, a * `function`, a `service`, or any other `
{ ... }` shape in a Firebase rules * source. Offsets are relative to the body that was scanned. */ export interface RawBlock { readonly header: string; readonly body: string; readonly headerStart: number; readonly bodyStart: number; } /** * Strips `//`-style line comments from a Firebase rules source string so the brace * walker doesn't trip on braces / semicolons embedded in comments. * * @param source - Raw rules source. * @returns The source with line comments replaced by equal-length whitespace (so offsets are preserved). */ export declare function stripLineComments(source: string): string; /** * Masks `{name}` and `{name=**}` path-variable braces with private-use characters so the * brace walker never confuses them with block braces. Same-length substitution preserves * offsets. Catch-all deny patterns retain a recognizable shape because the inner text * (e.g. `allPaths=**`) is untouched. * * @param source - The (comment-stripped) source. * @returns The source with path-variable braces masked. */ export declare function maskPathVariables(source: string): string; /** * Reverses {@link maskPathVariables} so header / path text reported to callers shows the * original `{name}` form. * * @param text - Text containing masked path variables. * @returns The text with `{name}` braces restored. */ export declare function unmaskPathVariables(text: string): string; /** * Resolves the 1-based line and 1-based column of a character offset in the source string. * * @param source - The original source. * @param index - Zero-based character offset. * @returns The line/column pair. */ export declare function indexToLineColumn(source: string, index: number): { line: number; column: number; }; /** * Finds the matching closing brace for the opening brace at `openIndex` in `source`, * respecting nesting. Returns the index of the closing brace, or -1 when unbalanced. * `source` must be the masked version so path-variable braces don't pollute the count. * * @param source - The masked source string. * @param openIndex - Index of an opening brace. * @returns Index of the matching closing brace, or -1. */ export declare function findMatchingBrace(source: string, openIndex: number): number; /** * Walks backward from `openIndex` to find where this block's header starts: just past the * previous `;` or `}` (now always a true block-sibling close, since path-variable braces * are masked), then forward through whitespace to the first significant char. * * @param body - The masked source slice being scanned. * @param cursor - The search start position (right after the previous sibling's `}`). * @param openIndex - Index of this block's opening brace. * @returns Start index of the header. */ export declare function findHeaderStart(body: string, cursor: number, openIndex: number): number; /** * Extracts top-level brace-delimited blocks inside `body` (path-variable-masked). Each * block carries its header text (with masking still applied — callers unmask when * reporting) and the inner body. Function definitions, match blocks, and `service` / * bucket-root wrappers are all returned as raw blocks. * * @param body - The masked source slice to scan. * @returns The list of top-level child blocks. */ export declare function extractTopLevelBlocks(body: string): RawBlock[]; /** * Pulls the match-path segment out of a `match / { ... }` header. The segment is * unmasked before being returned so callers see original `{name}` braces. * * @param header - The (still-masked) header text. * @returns The path segment with the leading `/`, or null when the header is not a match. */ export declare function matchHeaderPath(header: string): Maybe; /** * Pulls the function name out of a `function () { ... }` header. * * @param header - The header text. * @returns The function name, or null when the header is not a function definition. */ export declare function functionHeaderName(header: string): Maybe; /** * Pulls the `return ` body out of a function definition's inner block. The * body may span multiple lines (CEL expressions wrap freely across newlines); we capture * everything from after `return ` to the closing `}`-relative end of `body`, then strip * an optional trailing `;` and surrounding whitespace. * * @param body - The inner body of a function block (already line-comment-stripped). * @returns The expression text after `return`, or null when no `return` is present. */ export declare function functionReturnExpression(body: string): Maybe; /** * Joins a child match segment onto a parent path so nested matches resolve to absolute paths. * * @param parentPath - The accumulated parent path (e.g. `/uploads/u/{uid}`). * @param childSegment - The child match's segment (e.g. `/avatar.img`). * @returns The combined path. */ export declare function joinMatchPath(parentPath: string, childSegment: string): string; /** * Returns true when the unmasked segment is the catch-all `{var=**}` wildcard that means * "any path" (used for deny rules like `match /{allPaths=**} { allow read, write: if false; }`). * * @param segment - The unmasked match segment to test. * @returns True for catch-all wildcards. */ export declare function isCatchAllSegment(segment: string): boolean;