pyric 0.1.0-alpha.25 → 0.1.0-alpha.26

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.
@@ -36,6 +36,9 @@ export type { RuleIssue, RuleIssueSeverity, RuleIssueOrigin, } from './api/issue
36
36
  export type { FirestoreCase, CaseResult, Explanation, SimulationSummary, RtdbCase, RtdbCaseQuery, RtdbCaseResult, RtdbInstancesData, RtdbExplanation, RtdbRuleEvaluation, RtdbSimulationSummary, } from './api/case-types.js';
37
37
  export { renderRtdbCoverage } from './rtdb/coverage.js';
38
38
  export type { RtdbCoverageOptions, RtdbCoverageStatus, RtdbCoverageSummary, RtdbFileCoverage, RtdbRuleCoverage, RtdbCoverageKind, } from './rtdb/coverage.js';
39
+ export { diffRtdbRules } from './rtdb/rules-diff.js';
40
+ export type { DiffRtdbRulesOptions, RtdbRuleChange, RtdbRuleKind } from './rtdb/rules-diff.js';
41
+ export { canonicalRtdbExpression, RtdbExpressionSyntaxError } from './rtdb/grammar/canonical.js';
39
42
  export type { RuleEvaluation, PathResolutionEntry, PathResolutionTrace, EvaluatedRuleInfo, FirestoreMethod, ListQuery, ListQueryWhereConstraint, RulesResourceLimit, } from './test/spec.js';
40
43
  export type { ExprTraceEntry } from './simulator/evaluator.js';
41
44
  export type { ListQueryProofReport, QueryProofFailure, QueryProofResidual, QueryRepro, } from './simulator/list-query-proof.js';
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAGH,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AACpD,YAAY,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAC3D,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAC1C,YAAY,EAAE,WAAW,EAAE,oBAAoB,EAAE,MAAM,eAAe,CAAC;AACvE,YAAY,EAAE,uBAAuB,EAAE,MAAM,6BAA6B,CAAC;AAG3E,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAGrC,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAG1D,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAGzB,YAAY,EACV,SAAS,EACT,iBAAiB,EACjB,eAAe,GAChB,MAAM,gBAAgB,CAAC;AAGxB,YAAY,EACV,aAAa,EACb,UAAU,EACV,WAAW,EACX,iBAAiB,EACjB,QAAQ,EACR,aAAa,EACb,cAAc,EACd,iBAAiB,EACjB,eAAe,EACf,kBAAkB,EAClB,qBAAqB,GACtB,MAAM,qBAAqB,CAAC;AAG7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AACxD,YAAY,EACV,mBAAmB,EACnB,kBAAkB,EAClB,mBAAmB,EACnB,gBAAgB,EAChB,gBAAgB,EAChB,gBAAgB,GACjB,MAAM,oBAAoB,CAAC;AAG5B,YAAY,EACV,cAAc,EACd,mBAAmB,EACnB,mBAAmB,EACnB,iBAAiB,EACjB,eAAe,EACf,SAAS,EACT,wBAAwB,EACxB,kBAAkB,GACnB,MAAM,gBAAgB,CAAC;AACxB,YAAY,EAAE,cAAc,EAAE,MAAM,0BAA0B,CAAC;AAC/D,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,kBAAkB,EAClB,UAAU,GACX,MAAM,iCAAiC,CAAC;AAGzC,OAAO,EACL,eAAe,EACf,SAAS,EACT,KAAK,EACL,MAAM,EACN,QAAQ,EACR,SAAS,EACT,MAAM,GACP,MAAM,iBAAiB,CAAC;AAGzB,OAAO,EACL,IAAI,EACJ,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,EACH,IAAI,EACJ,MAAM,EACN,KAAK,EACL,aAAa,EACb,OAAO,EACP,QAAQ,EACR,KAAK,EACL,WAAW,EACX,QAAQ,EACR,aAAa,EACb,aAAa,EACb,cAAc,EACd,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACd,UAAU,EACV,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,OAAO,EACP,UAAU,EACV,UAAU,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,EAAE,EACF,GAAG,EACH,EAAE,EACF,GAAG,EACH,QAAQ,EACR,GAAG,EACH,SAAS,EACT,IAAI,EACJ,cAAc,EACd,WAAW,EACX,OAAO,EACP,eAAe,GAChB,MAAM,6BAA6B,CAAC;AAGrC,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC;AACpD,YAAY,EAAE,UAAU,EAAE,SAAS,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAE/F,YAAY,EACV,IAAI,EACJ,OAAO,EACP,OAAO,EACP,cAAc,EACd,iBAAiB,EACjB,mBAAmB,EACnB,iBAAiB,EACjB,aAAa,EACb,oBAAoB,EACpB,gBAAgB,EAChB,oBAAoB,EACpB,uBAAuB,EACvB,wBAAwB,GACzB,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"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"}
@@ -35,6 +35,9 @@ export { assertCase, explainCase } from './api/assert.js';
35
35
  export { RulesCompileError, RulesAssertionError, RulesUnsupportedError, } from './api/errors.js';
36
36
  // ─── RTDB rule coverage ──────────────────────────────────────────────
37
37
  export { renderRtdbCoverage } from './rtdb/coverage.js';
38
+ // ─── RTDB ruleset diff and expression equivalence ───────────────────
39
+ export { diffRtdbRules } from './rtdb/rules-diff.js';
40
+ export { canonicalRtdbExpression, RtdbExpressionSyntaxError } from './rtdb/grammar/canonical.js';
38
41
  // ─── Value helpers ───────────────────────────────────────────────────
39
42
  export { serverTimestamp, timestamp, bytes, latlng, duration, reference, vector, } from './api/values.js';
40
43
  // ─── RTDB constraints DSL (re-exported unchanged as siblings) ────────
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,wEAAwE;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI1C,wEAAwE;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,wEAAwE;AACxE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE1D,wEAAwE;AACxE,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAwBzB,wEAAwE;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AA6BxD,wEAAwE;AACxE,OAAO,EACL,eAAe,EACf,SAAS,EACT,KAAK,EACL,MAAM,EACN,QAAQ,EACR,SAAS,EACT,MAAM,GACP,MAAM,iBAAiB,CAAC;AAEzB,wEAAwE;AACxE,OAAO,EACL,IAAI,EACJ,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,EACH,IAAI,EACJ,MAAM,EACN,KAAK,EACL,aAAa,EACb,OAAO,EACP,QAAQ,EACR,KAAK,EACL,WAAW,EACX,QAAQ,EACR,aAAa,EACb,aAAa,EACb,cAAc,EACd,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACd,UAAU,EACV,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,OAAO,EACP,UAAU,EACV,UAAU,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,EAAE,EACF,GAAG,EACH,EAAE,EACF,GAAG,EACH,QAAQ,EACR,GAAG,EACH,SAAS,EACT,IAAI,EACJ,cAAc,EACd,WAAW,EACX,OAAO,EACP,eAAe,GAChB,MAAM,6BAA6B,CAAC;AAErC,wEAAwE;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/rules/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AAEH,wEAAwE;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AAEpD,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAI1C,wEAAwE;AACxE,OAAO,EAAE,IAAI,EAAE,MAAM,eAAe,CAAC;AAErC,wEAAwE;AACxE,OAAO,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,iBAAiB,CAAC;AAE1D,wEAAwE;AACxE,OAAO,EACL,iBAAiB,EACjB,mBAAmB,EACnB,qBAAqB,GACtB,MAAM,iBAAiB,CAAC;AAwBzB,wEAAwE;AACxE,OAAO,EAAE,kBAAkB,EAAE,MAAM,oBAAoB,CAAC;AAUxD,uEAAuE;AACvE,OAAO,EAAE,aAAa,EAAE,MAAM,sBAAsB,CAAC;AAErD,OAAO,EAAE,uBAAuB,EAAE,yBAAyB,EAAE,MAAM,6BAA6B,CAAC;AAqBjG,wEAAwE;AACxE,OAAO,EACL,eAAe,EACf,SAAS,EACT,KAAK,EACL,MAAM,EACN,QAAQ,EACR,SAAS,EACT,MAAM,GACP,MAAM,iBAAiB,CAAC;AAEzB,wEAAwE;AACxE,OAAO,EACL,IAAI,EACJ,GAAG,EACH,GAAG,EACH,GAAG,EACH,GAAG,EACH,IAAI,EACJ,MAAM,EACN,KAAK,EACL,aAAa,EACb,OAAO,EACP,QAAQ,EACR,KAAK,EACL,WAAW,EACX,QAAQ,EACR,aAAa,EACb,aAAa,EACb,cAAc,EACd,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACd,UAAU,EACV,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,OAAO,EACP,UAAU,EACV,UAAU,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,EAAE,EACF,GAAG,EACH,EAAE,EACF,GAAG,EACH,QAAQ,EACR,GAAG,EACH,SAAS,EACT,IAAI,EACJ,cAAc,EACd,WAAW,EACX,OAAO,EACP,eAAe,GAChB,MAAM,6BAA6B,CAAC;AAErC,wEAAwE;AACxE,OAAO,EAAE,UAAU,EAAE,MAAM,wBAAwB,CAAC"}
@@ -12,6 +12,11 @@ export type { CompiledRtdbRules } from '../rtdb/compiled-rules.js';
12
12
  export { locateRtdbRule, locateRtdbTrace } from '../rtdb/source-locations.js';
13
13
  export type { LocatedRtdbRuleEvaluation, RtdbRuleKind, RtdbSourceLocation, } from '../rtdb/source-locations.js';
14
14
  export { parseExpression } from '../rtdb/grammar/RtdbExprParser.js';
15
+ export { parseRtdbExpressionTree, printRtdbExpressionTree, } from '../rtdb/grammar/expression-tree.js';
16
+ export type { RtdbBinaryOperator, RtdbExpressionTree, RtdbExpressionTreeResult, } from '../rtdb/grammar/expression-tree.js';
17
+ export { canonicalRtdbExpression, canonicalTree as canonicalRtdbExpressionTree, RtdbExpressionSyntaxError, } from '../rtdb/grammar/canonical.js';
18
+ export { DIFFED_RULE_KINDS, diffRtdbRules } from '../rtdb/rules-diff.js';
19
+ export type { DiffRtdbRulesOptions, RtdbRuleChange } from '../rtdb/rules-diff.js';
15
20
  export { validateExpression } from '../rtdb/grammar/validator.js';
16
21
  export { lintExpression } from '../rtdb/grammar/linter.js';
17
22
  export { lintRtdbRuleset } from '../rtdb/grammar/ruleset-lint.js';
@@ -1 +1 @@
1
- {"version":3,"file":"rtdb.d.ts","sourceRoot":"","sources":["../../../src/rules/internal/rtdb.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAClD,YAAY,EACV,oBAAoB,EACpB,iBAAiB,EACjB,gBAAgB,GACjB,MAAM,0BAA0B,CAAC;AAClC,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AACnC,YAAY,EAAE,iBAAiB,EAAE,MAAM,2BAA2B,CAAC;AAEnE,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAC9E,YAAY,EACV,yBAAyB,EACzB,YAAY,EACZ,kBAAkB,GACnB,MAAM,6BAA6B,CAAC;AAErC,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAClE,YAAY,EAAE,gBAAgB,EAAE,mBAAmB,EAAE,MAAM,iCAAiC,CAAC;AAE7F,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,gBAAgB,EAChB,cAAc,GACf,MAAM,4BAA4B,CAAC;AACpC,YAAY,EACV,gBAAgB,EAChB,gBAAgB,IAAI,yBAAyB,EAC7C,QAAQ,EACR,kBAAkB,EAClB,SAAS,EACT,QAAQ,GACT,MAAM,kBAAkB,CAAC;AAE1B,OAAO,EACL,IAAI,EACJ,GAAG,EACH,GAAG,EACH,GAAG,EACH,IAAI,EACJ,MAAM,EACN,KAAK,EACL,aAAa,EACb,OAAO,EACP,QAAQ,EACR,KAAK,EACL,WAAW,EACX,QAAQ,EACR,aAAa,EACb,aAAa,EACb,cAAc,EACd,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACd,UAAU,EACV,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,OAAO,EACP,UAAU,EACV,UAAU,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,EAAE,EACF,GAAG,EACH,EAAE,EACF,GAAG,EACH,GAAG,EACH,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,cAAc,EACd,WAAW,EACX,OAAO,EACP,eAAe,GAChB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3F,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AACvE,YAAY,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC;AAC5E,YAAY,EACV,IAAI,EACJ,OAAO,EACP,oBAAoB,EACpB,mBAAmB,EACnB,yBAAyB,IAAI,iBAAiB,EAC9C,gBAAgB,EAChB,oBAAoB,EACpB,aAAa,EACb,uBAAuB,EACvB,wBAAwB,EACxB,cAAc,EACd,iBAAiB,EACjB,OAAO,GACR,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"rtdb.d.ts","sourceRoot":"","sources":["../../../src/rules/internal/rtdb.ts"],"names":[],"mappings":"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"}
@@ -9,6 +9,9 @@ export { replay } from '../../database/replay.js';
9
9
  export { buildRuleExpression, compileRtdbRules, serializeRtdbRules, simulateRtdbRules, } from '../rtdb/compiled-rules.js';
10
10
  export { locateRtdbRule, locateRtdbTrace } from '../rtdb/source-locations.js';
11
11
  export { parseExpression } from '../rtdb/grammar/RtdbExprParser.js';
12
+ export { parseRtdbExpressionTree, printRtdbExpressionTree, } from '../rtdb/grammar/expression-tree.js';
13
+ export { canonicalRtdbExpression, canonicalTree as canonicalRtdbExpressionTree, RtdbExpressionSyntaxError, } from '../rtdb/grammar/canonical.js';
14
+ export { DIFFED_RULE_KINDS, diffRtdbRules } from '../rtdb/rules-diff.js';
12
15
  export { validateExpression } from '../rtdb/grammar/validator.js';
13
16
  export { lintExpression } from '../rtdb/grammar/linter.js';
14
17
  export { lintRtdbRuleset } from '../rtdb/grammar/ruleset-lint.js';
@@ -1 +1 @@
1
- {"version":3,"file":"rtdb.js","sourceRoot":"","sources":["../../../src/rules/internal/rtdb.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAMlD,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAO9E,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGlE,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AAgBpC,OAAO,EACL,IAAI,EACJ,GAAG,EACH,GAAG,EACH,GAAG,EACH,IAAI,EACJ,MAAM,EACN,KAAK,EACL,aAAa,EACb,OAAO,EACP,QAAQ,EACR,KAAK,EACL,WAAW,EACX,QAAQ,EACR,aAAa,EACb,aAAa,EACb,cAAc,EACd,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACd,UAAU,EACV,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,OAAO,EACP,UAAU,EACV,UAAU,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,EAAE,EACF,GAAG,EACH,EAAE,EACF,GAAG,EACH,GAAG,EACH,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,cAAc,EACd,WAAW,EACX,OAAO,EACP,eAAe,GAChB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3F,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC"}
1
+ {"version":3,"file":"rtdb.js","sourceRoot":"","sources":["../../../src/rules/internal/rtdb.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AACH,OAAO,EAAE,MAAM,EAAE,MAAM,0BAA0B,CAAC;AAMlD,OAAO,EACL,mBAAmB,EACnB,gBAAgB,EAChB,kBAAkB,EAClB,iBAAiB,GAClB,MAAM,2BAA2B,CAAC;AAGnC,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,6BAA6B,CAAC;AAO9E,OAAO,EAAE,eAAe,EAAE,MAAM,mCAAmC,CAAC;AACpE,OAAO,EACL,uBAAuB,EACvB,uBAAuB,GACxB,MAAM,oCAAoC,CAAC;AAM5C,OAAO,EACL,uBAAuB,EACvB,aAAa,IAAI,2BAA2B,EAC5C,yBAAyB,GAC1B,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,iBAAiB,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEzE,OAAO,EAAE,kBAAkB,EAAE,MAAM,8BAA8B,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,2BAA2B,CAAC;AAC3D,OAAO,EAAE,eAAe,EAAE,MAAM,iCAAiC,CAAC;AAGlE,OAAO,EACL,qBAAqB,EACrB,iBAAiB,EACjB,sBAAsB,EACtB,wBAAwB,GACzB,MAAM,4BAA4B,CAAC;AAgBpC,OAAO,EACL,IAAI,EACJ,GAAG,EACH,GAAG,EACH,GAAG,EACH,IAAI,EACJ,MAAM,EACN,KAAK,EACL,aAAa,EACb,OAAO,EACP,QAAQ,EACR,KAAK,EACL,WAAW,EACX,QAAQ,EACR,aAAa,EACb,aAAa,EACb,cAAc,EACd,SAAS,EACT,SAAS,EACT,aAAa,EACb,UAAU,EACV,UAAU,EACV,aAAa,EACb,cAAc,EACd,UAAU,EACV,OAAO,EACP,QAAQ,EACR,QAAQ,EACR,UAAU,EACV,OAAO,EACP,UAAU,EACV,UAAU,EACV,aAAa,EACb,SAAS,EACT,aAAa,EACb,gBAAgB,EAChB,mBAAmB,EACnB,EAAE,EACF,GAAG,EACH,EAAE,EACF,GAAG,EACH,GAAG,EACH,QAAQ,EACR,SAAS,EACT,IAAI,EACJ,cAAc,EACd,WAAW,EACX,OAAO,EACP,eAAe,GAChB,MAAM,8BAA8B,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,wBAAwB,EAAE,MAAM,iCAAiC,CAAC;AAC3F,OAAO,EAAE,wBAAwB,EAAE,MAAM,6BAA6B,CAAC"}
@@ -0,0 +1,52 @@
1
+ /**
2
+ * Canonical text for an RTDB rule expression, for asking whether two rule
3
+ * expressions are the same rule spelled differently.
4
+ *
5
+ * Soundness over completeness. Every rewrite here maps an expression to one
6
+ * that production RTDB evaluates identically for every input: the same
7
+ * boolean or value, and an error exactly where the original errors (an error
8
+ * fails the whole rule, with no rescue from `||` or `!`: captures
9
+ * rules-rtdb-r17, r26, r41). Two expressions whose canonical texts are equal
10
+ * therefore decide every request alike. When equivalence is not certain, the
11
+ * expression is left as written, so two equivalent expressions may still print
12
+ * differently; the reverse must never happen.
13
+ *
14
+ * The rewrites, each justified where it is applied below:
15
+ *
16
+ * 1. Whitespace and grouping parentheses are dropped, `&&` and `||`
17
+ * chains are regrouped left to right, and a string literal written
18
+ * without a backslash prints in single quotes (`"a"` is `'a'`).
19
+ * 2. `===` is `==` and `!==` is `!=`.
20
+ * 3. `auth.uid == null` (either operand order) is `auth == null`.
21
+ * 4. `x.child('a/b/' + $v + '/c')` is `x.child('a').child('b').child($v).child('c')`
22
+ * when every concatenated part is a string literal or a `$` path variable
23
+ * and each `/`-separated segment is one non-empty literal or one variable.
24
+ * 5. `a != b` is `!(a == b)`.
25
+ * 6. The operands of `==` are ordered by their canonical text, when neither
26
+ * operand can raise anything but a rule runtime error and neither
27
+ * indexes into or builds an array.
28
+ *
29
+ * Deliberately not rewritten: a concatenated part that is not a literal or a
30
+ * `$` variable, `auth.uid` included (see `childSegments`); a segment that is
31
+ * empty or holds `.`, `#`, `$`, `[` or `]`; any string literal written with
32
+ * a backslash escape (kept exactly as written); double negation (`!!x` is not `x`
33
+ * for a non-boolean `x`); operand order of `&&`, `||` and the ordering
34
+ * operators (short-circuiting and errors depend on it); and any arithmetic or
35
+ * constant folding.
36
+ */
37
+ import { type RtdbExpressionTree } from './expression-tree.js';
38
+ /** Why {@link canonicalRtdbExpression} could not read its input. */
39
+ export declare class RtdbExpressionSyntaxError extends Error {
40
+ readonly raw: string;
41
+ constructor(raw: string, message: string);
42
+ }
43
+ /** The canonical form of a syntax tree. */
44
+ export declare function canonicalTree(tree: RtdbExpressionTree): RtdbExpressionTree;
45
+ /**
46
+ * Canonical text of an RTDB rule expression: two expressions with equal
47
+ * canonical texts evaluate identically for every request. Deterministic and
48
+ * idempotent. Throws {@link RtdbExpressionSyntaxError} for text that is not a
49
+ * rule expression.
50
+ */
51
+ export declare function canonicalRtdbExpression(raw: string): string;
52
+ //# sourceMappingURL=canonical.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.d.ts","sourceRoot":"","sources":["../../../../src/rules/rtdb/grammar/canonical.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AACH,OAAO,EAGL,KAAK,kBAAkB,EACxB,MAAM,sBAAsB,CAAC;AAG9B,oEAAoE;AACpE,qBAAa,yBAA0B,SAAQ,KAAK;IACtC,QAAQ,CAAC,GAAG,EAAE,MAAM;gBAAX,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM;CAIlD;AAkRD,2CAA2C;AAC3C,wBAAgB,aAAa,CAAC,IAAI,EAAE,kBAAkB,GAAG,kBAAkB,CAE1E;AAED;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAI3D"}
@@ -0,0 +1,328 @@
1
+ /**
2
+ * Canonical text for an RTDB rule expression, for asking whether two rule
3
+ * expressions are the same rule spelled differently.
4
+ *
5
+ * Soundness over completeness. Every rewrite here maps an expression to one
6
+ * that production RTDB evaluates identically for every input: the same
7
+ * boolean or value, and an error exactly where the original errors (an error
8
+ * fails the whole rule, with no rescue from `||` or `!`: captures
9
+ * rules-rtdb-r17, r26, r41). Two expressions whose canonical texts are equal
10
+ * therefore decide every request alike. When equivalence is not certain, the
11
+ * expression is left as written, so two equivalent expressions may still print
12
+ * differently; the reverse must never happen.
13
+ *
14
+ * The rewrites, each justified where it is applied below:
15
+ *
16
+ * 1. Whitespace and grouping parentheses are dropped, `&&` and `||`
17
+ * chains are regrouped left to right, and a string literal written
18
+ * without a backslash prints in single quotes (`"a"` is `'a'`).
19
+ * 2. `===` is `==` and `!==` is `!=`.
20
+ * 3. `auth.uid == null` (either operand order) is `auth == null`.
21
+ * 4. `x.child('a/b/' + $v + '/c')` is `x.child('a').child('b').child($v).child('c')`
22
+ * when every concatenated part is a string literal or a `$` path variable
23
+ * and each `/`-separated segment is one non-empty literal or one variable.
24
+ * 5. `a != b` is `!(a == b)`.
25
+ * 6. The operands of `==` are ordered by their canonical text, when neither
26
+ * operand can raise anything but a rule runtime error and neither
27
+ * indexes into or builds an array.
28
+ *
29
+ * Deliberately not rewritten: a concatenated part that is not a literal or a
30
+ * `$` variable, `auth.uid` included (see `childSegments`); a segment that is
31
+ * empty or holds `.`, `#`, `$`, `[` or `]`; any string literal written with
32
+ * a backslash escape (kept exactly as written); double negation (`!!x` is not `x`
33
+ * for a non-boolean `x`); operand order of `&&`, `||` and the ordering
34
+ * operators (short-circuiting and errors depend on it); and any arithmetic or
35
+ * constant folding.
36
+ */
37
+ import { parseRtdbExpressionTree, printRtdbExpressionTree, } from './expression-tree.js';
38
+ import { isSupportedRegexFlags } from './type-rules.js';
39
+ /** Why {@link canonicalRtdbExpression} could not read its input. */
40
+ export class RtdbExpressionSyntaxError extends Error {
41
+ raw;
42
+ constructor(raw, message) {
43
+ super(`Not an RTDB rule expression: ${message}`);
44
+ this.raw = raw;
45
+ this.name = 'RtdbExpressionSyntaxError';
46
+ }
47
+ }
48
+ /** The methods the rules language defines on a data snapshot (the simulator's set). */
49
+ const SNAPSHOT_METHODS = new Set([
50
+ 'val', 'exists', 'hasChild', 'hasChildren', 'isString', 'isNumber',
51
+ 'isBoolean', 'child', 'parent', 'getPriority',
52
+ ]);
53
+ /** The methods the rules language defines on a string (the simulator's set). */
54
+ const STRING_METHODS = new Set([
55
+ 'matches', 'contains', 'beginsWith', 'endsWith', 'replace', 'toLowerCase', 'toUpperCase',
56
+ ]);
57
+ /** The bare identifiers the rules language binds. Any other bare name is unbound. */
58
+ const BOUND_IDENTIFIERS = new Set(['auth', 'data', 'newData', 'root', 'now', 'query']);
59
+ /** Characters that may not appear in a database key. */
60
+ const INVALID_KEY_CHARS = /[.#$[\]]/;
61
+ /** A string that prints as `'value'` without escapes. */
62
+ const PLAIN_STRING_CHARS = /^[^'\\\u0000-\u001f\u007f\u2028\u2029]*$/;
63
+ const isPathVariable = (tree) => tree.type === 'identifier' && tree.name.startsWith('$');
64
+ const isAuthUid = (tree) => tree.type === 'member' && tree.property === 'uid'
65
+ && tree.object.type === 'identifier' && tree.object.name === 'auth';
66
+ /** Whether `tree` may evaluate to `undefined`: an unbound identifier. */
67
+ function mayBeUndefined(tree) {
68
+ if (tree.type === 'identifier')
69
+ return tree.name.startsWith('$') || !BOUND_IDENTIFIERS.has(tree.name);
70
+ if (tree.type === 'ternary')
71
+ return mayBeUndefined(tree.consequent) || mayBeUndefined(tree.alternate);
72
+ return false;
73
+ }
74
+ /** Whether `tree` may evaluate to a data snapshot. */
75
+ function mayBeSnapshot(tree) {
76
+ switch (tree.type) {
77
+ case 'identifier': return tree.name === 'root' || tree.name === 'data' || tree.name === 'newData';
78
+ case 'ternary': return mayBeSnapshot(tree.consequent) || mayBeSnapshot(tree.alternate);
79
+ case 'call': return (tree.method === 'child' || tree.method === 'parent') && mayBeSnapshot(tree.receiver);
80
+ default: return false;
81
+ }
82
+ }
83
+ function regexCompiles(raw) {
84
+ const end = raw.lastIndexOf('/');
85
+ const flags = raw.slice(end + 1);
86
+ if (!isSupportedRegexFlags(flags))
87
+ return true; // a rule runtime error, not a crash
88
+ try {
89
+ new RegExp(raw.slice(1, end), flags);
90
+ return true;
91
+ }
92
+ catch {
93
+ return false;
94
+ }
95
+ }
96
+ /**
97
+ * Whether every failure `tree` can raise while it evaluates is a rule runtime
98
+ * error, the error that fails the rule. Evaluation can also stop on a
99
+ * construct the simulator does not evaluate (an unknown method, a method
100
+ * called on an unbound name, a regular expression JavaScript cannot compile);
101
+ * production refuses to deploy each of those. Reordering operands changes
102
+ * which operand raises first, so it is applied only where every raise is the
103
+ * same kind of failure.
104
+ */
105
+ function raisesOnlyRuleErrors(tree) {
106
+ switch (tree.type) {
107
+ case 'ternary':
108
+ return raisesOnlyRuleErrors(tree.test) && raisesOnlyRuleErrors(tree.consequent) && raisesOnlyRuleErrors(tree.alternate);
109
+ case 'binary':
110
+ return raisesOnlyRuleErrors(tree.left) && raisesOnlyRuleErrors(tree.right);
111
+ case 'unary':
112
+ return raisesOnlyRuleErrors(tree.argument);
113
+ case 'member':
114
+ return raisesOnlyRuleErrors(tree.object);
115
+ case 'index':
116
+ case 'array':
117
+ // Not followed: an array can hold a snapshot (`[data][0]`), and a
118
+ // string method called on what an index reads out of it stops the
119
+ // simulator rather than raising a rule error. Declining here keeps
120
+ // `mayBeSnapshot` from having to track values through arrays.
121
+ return false;
122
+ case 'regex':
123
+ return regexCompiles(tree.raw);
124
+ case 'call': {
125
+ if (!raisesOnlyRuleErrors(tree.receiver) || !tree.args.every(raisesOnlyRuleErrors))
126
+ return false;
127
+ if (mayBeUndefined(tree.receiver))
128
+ return false;
129
+ if (SNAPSHOT_METHODS.has(tree.method))
130
+ return true;
131
+ return STRING_METHODS.has(tree.method) && !mayBeSnapshot(tree.receiver);
132
+ }
133
+ default:
134
+ return true;
135
+ }
136
+ }
137
+ /** The operands of a chain of one logical operator, left to right. */
138
+ function logicalOperands(tree, operator) {
139
+ if (tree.type === 'binary' && tree.operator === operator) {
140
+ return [...logicalOperands(tree.left, operator), ...logicalOperands(tree.right, operator)];
141
+ }
142
+ return [tree];
143
+ }
144
+ /** The parts of a `+` chain, left to right. */
145
+ function concatenatedParts(tree) {
146
+ if (tree.type === 'binary' && tree.operator === '+') {
147
+ return [...concatenatedParts(tree.left), ...concatenatedParts(tree.right)];
148
+ }
149
+ return [tree];
150
+ }
151
+ /**
152
+ * The path segments a `child()` argument names, or undefined when they are
153
+ * not certain.
154
+ *
155
+ * Only string literals and `$` path variables qualify. A path variable is
156
+ * bound to exactly one key of the path being evaluated, so it is one
157
+ * non-empty segment with no `/`. Any other dynamic part is declined, and
158
+ * `auth.uid` in particular: production child() given a key with an empty
159
+ * segment (a custom-token uid such as `/x` or `a//b`) is not captured, so
160
+ * `child('m/' + auth.uid)` and `child('m').child(auth.uid)` are not known to
161
+ * agree for every uid. What is captured is that both fail for a signed-out
162
+ * request: `'a' + null` is an error (rules-rtdb-r27-stdlib-core-patterns) and
163
+ * `child(auth.uid)` signed out is an error (rules-rtdb-r32-method-argument-types).
164
+ *
165
+ * Each segment must be one non-empty literal or exactly one variable: an
166
+ * empty segment (a leading, trailing or doubled `/`), a literal glued to a
167
+ * variable (`'user_' + $id`), and a literal holding a character invalid in a
168
+ * key are all declined, since production's handling of each is not captured.
169
+ */
170
+ function childSegments(arg) {
171
+ const segments = [{ text: '', variables: [] }];
172
+ for (const part of concatenatedParts(arg)) {
173
+ if (part.type === 'string') {
174
+ // A literal written with an escape is declined: production's reading
175
+ // of most escapes is not captured (see printRtdbStringLiteral).
176
+ if (part.raw.includes('\\'))
177
+ return undefined;
178
+ const pieces = part.value.split('/');
179
+ segments[segments.length - 1].text += pieces[0];
180
+ for (const piece of pieces.slice(1))
181
+ segments.push({ text: piece, variables: [] });
182
+ }
183
+ else if (isPathVariable(part)) {
184
+ segments[segments.length - 1].variables.push(part);
185
+ }
186
+ else {
187
+ return undefined;
188
+ }
189
+ }
190
+ const out = [];
191
+ for (const segment of segments) {
192
+ if (segment.variables.length === 1 && segment.text === '') {
193
+ out.push({ kind: 'variable', tree: segment.variables[0] });
194
+ }
195
+ else if (segment.variables.length === 0 && segment.text !== ''
196
+ && !INVALID_KEY_CHARS.test(segment.text) && PLAIN_STRING_CHARS.test(segment.text)) {
197
+ out.push({ kind: 'literal', text: segment.text });
198
+ }
199
+ else {
200
+ return undefined;
201
+ }
202
+ }
203
+ return out;
204
+ }
205
+ /** The canonical form of a tree whose children are already canonical. */
206
+ function canonicalNode(tree) {
207
+ switch (tree.type) {
208
+ case 'binary': {
209
+ const left = canonicalTree(tree.left);
210
+ const right = canonicalTree(tree.right);
211
+ switch (tree.operator) {
212
+ case '&&':
213
+ case '||': {
214
+ // Rewrite 1: `a && (b && c)` is `(a && b) && c`. Both evaluate the
215
+ // operands left to right, stop at the first false (true for `||`),
216
+ // and fail at the first operand that is not a boolean, so they
217
+ // agree on every value and every error.
218
+ const operands = [...logicalOperands(left, tree.operator), ...logicalOperands(right, tree.operator)];
219
+ return operands.reduce((acc, operand) => ({ type: 'binary', operator: tree.operator, left: acc, right: operand }));
220
+ }
221
+ // Rewrite 2: RTDB's `===` and `!==` are its `==` and `!=`: neither
222
+ // converts types, and the simulator evaluates the pairs with the same
223
+ // operand checks and comparison.
224
+ case '===':
225
+ case '==':
226
+ return canonicalEquality(left, right);
227
+ case '!==':
228
+ case '!=':
229
+ // Rewrite 5: `a != b` is `!(a == b)`. Both evaluate a, then b, with
230
+ // the same operand checks, so they fail on exactly the same inputs
231
+ // (an error under `!` still fails the rule: rules-rtdb-r26 DENIES
232
+ // `!(newData.val().toUpperCase() == 'OK')` for a number, and
233
+ // rules-rtdb-r27 DENIES `data.val() + 1 != 1` with nothing stored).
234
+ // Otherwise `==` yields a boolean, and `!` of a boolean negates it.
235
+ return { type: 'unary', operator: '!', argument: canonicalEquality(left, right) };
236
+ default:
237
+ return { ...tree, left, right };
238
+ }
239
+ }
240
+ case 'call': {
241
+ const receiver = canonicalTree(tree.receiver);
242
+ const args = tree.args.map(canonicalTree);
243
+ if (tree.method === 'child' && args.length === 1 && !mayBeUndefined(receiver)) {
244
+ // Rewrite 4: child() reads its argument as a `/`-separated path, so
245
+ // `x.child('a/' + $v)` and `x.child('a').child($v)` reach the same
246
+ // node. The pieces are literals and path variables, which never fail
247
+ // to evaluate except an unbound variable, and that is a rule runtime
248
+ // error in both forms (`'a/' + undefined` and `child(undefined)`). The
249
+ // receiver must not be unbound, or the split form would fail on the
250
+ // first child() before reaching the variable.
251
+ const segments = childSegments(args[0]);
252
+ if (segments !== undefined && segments.length > 1) {
253
+ return segments.reduce((acc, segment) => ({
254
+ type: 'call',
255
+ receiver: acc,
256
+ method: 'child',
257
+ args: [segment.kind === 'variable'
258
+ ? segment.tree
259
+ : { type: 'string', raw: `'${segment.text}'`, value: segment.text }],
260
+ }), receiver);
261
+ }
262
+ }
263
+ return { ...tree, receiver, args };
264
+ }
265
+ case 'ternary':
266
+ return {
267
+ type: 'ternary',
268
+ test: canonicalTree(tree.test),
269
+ consequent: canonicalTree(tree.consequent),
270
+ alternate: canonicalTree(tree.alternate),
271
+ };
272
+ case 'unary':
273
+ return { ...tree, argument: canonicalTree(tree.argument) };
274
+ case 'member':
275
+ return { ...tree, object: canonicalTree(tree.object) };
276
+ case 'index':
277
+ return { ...tree, object: canonicalTree(tree.object), index: canonicalTree(tree.index) };
278
+ case 'array':
279
+ return { ...tree, elements: tree.elements.map(canonicalTree) };
280
+ default:
281
+ return tree;
282
+ }
283
+ }
284
+ /** `left == right` in canonical form, from canonical operands. */
285
+ function canonicalEquality(left, right) {
286
+ // Rewrite 3: `auth.uid == null` is `auth == null`. `auth` is null exactly
287
+ // for a signed-out request, and then `auth.uid` reads null too; a signed-in
288
+ // `auth` always carries a uid string (production: the ID token's required
289
+ // `sub`; pyric: `SimulationInputSchema` requires `auth.uid` as a string
290
+ // (simulation/spec.ts) and `SimulatedAuth.uid` is a required string,
291
+ // conformance row "`auth` context" in registry/rtdb.ts). Neither operand
292
+ // can fail. The equivalence is a claim about requests as RTDB and pyric's
293
+ // simulate() and sandbox build them: a caller that hands
294
+ // `evaluateRtdbExpression` an `auth` object with no `uid` (`{ token: {} }`)
295
+ // is outside it, and there the two forms differ.
296
+ if ((isAuthUid(left) && right.type === 'null') || (left.type === 'null' && isAuthUid(right))) {
297
+ left = { type: 'identifier', name: 'auth' };
298
+ right = { type: 'null' };
299
+ }
300
+ // Rewrite 6: `a == b` is `b == a`. Equality compares without conversion
301
+ // and is symmetric. The order decides only which operand is evaluated, and
302
+ // can fail, first; when both can fail only with a rule runtime error, the
303
+ // rule fails either way.
304
+ if (raisesOnlyRuleErrors(left) && raisesOnlyRuleErrors(right)) {
305
+ const l = printRtdbExpressionTree(left);
306
+ const r = printRtdbExpressionTree(right);
307
+ if (r < l)
308
+ [left, right] = [right, left];
309
+ }
310
+ return { type: 'binary', operator: '==', left, right };
311
+ }
312
+ /** The canonical form of a syntax tree. */
313
+ export function canonicalTree(tree) {
314
+ return canonicalNode(tree);
315
+ }
316
+ /**
317
+ * Canonical text of an RTDB rule expression: two expressions with equal
318
+ * canonical texts evaluate identically for every request. Deterministic and
319
+ * idempotent. Throws {@link RtdbExpressionSyntaxError} for text that is not a
320
+ * rule expression.
321
+ */
322
+ export function canonicalRtdbExpression(raw) {
323
+ const parsed = parseRtdbExpressionTree(raw);
324
+ if (!parsed.ok)
325
+ throw new RtdbExpressionSyntaxError(raw, parsed.message);
326
+ return printRtdbExpressionTree(canonicalTree(parsed.tree));
327
+ }
328
+ //# sourceMappingURL=canonical.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"canonical.js","sourceRoot":"","sources":["../../../../src/rules/rtdb/grammar/canonical.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,86 @@
1
+ export type RtdbBinaryOperator = '||' | '&&' | '===' | '!==' | '==' | '!=' | '>=' | '<=' | '>' | '<' | '+' | '-' | '*' | '/' | '%';
2
+ export type RtdbExpressionTree = {
3
+ type: 'ternary';
4
+ test: RtdbExpressionTree;
5
+ consequent: RtdbExpressionTree;
6
+ alternate: RtdbExpressionTree;
7
+ } | {
8
+ type: 'binary';
9
+ operator: RtdbBinaryOperator;
10
+ left: RtdbExpressionTree;
11
+ right: RtdbExpressionTree;
12
+ } | {
13
+ type: 'unary';
14
+ operator: '!' | '-';
15
+ argument: RtdbExpressionTree;
16
+ } | {
17
+ type: 'call';
18
+ receiver: RtdbExpressionTree;
19
+ method: string;
20
+ args: RtdbExpressionTree[];
21
+ } | {
22
+ type: 'member';
23
+ object: RtdbExpressionTree;
24
+ property: string;
25
+ } | {
26
+ type: 'index';
27
+ object: RtdbExpressionTree;
28
+ index: RtdbExpressionTree;
29
+ } | {
30
+ type: 'array';
31
+ elements: RtdbExpressionTree[];
32
+ }
33
+ /** `raw` is the literal's source text; `value` is the string a string literal denotes. */
34
+ | {
35
+ type: 'string';
36
+ raw: string;
37
+ value: string;
38
+ } | {
39
+ type: 'number';
40
+ raw: string;
41
+ } | {
42
+ type: 'regex';
43
+ raw: string;
44
+ } | {
45
+ type: 'boolean';
46
+ value: boolean;
47
+ } | {
48
+ type: 'null';
49
+ } | {
50
+ type: 'identifier';
51
+ name: string;
52
+ };
53
+ export type RtdbExpressionTreeResult = {
54
+ ok: true;
55
+ tree: RtdbExpressionTree;
56
+ } | {
57
+ ok: false;
58
+ message: string;
59
+ };
60
+ /**
61
+ * The syntax tree of one RTDB rule expression, or why it does not parse.
62
+ * Refuses exactly what `parseExpression` refuses: text the grammar does not
63
+ * match, brackets nested past the parser's limit, and a raw line break inside
64
+ * a string literal.
65
+ */
66
+ export declare function parseRtdbExpressionTree(raw: string): RtdbExpressionTreeResult;
67
+ /**
68
+ * A string literal as `'value'` when its source has no backslash and the
69
+ * value needs no escape, else its source text unchanged. A literal written
70
+ * with an escape keeps its spelling: the only escapes captured are `\'`,
71
+ * `\xHH` and a raw tab (r44-deploy-string-and-regex-probes, see
72
+ * string-literal.ts); what production makes of `\uHHHH`, `\u{...}` or an
73
+ * escaped ordinary character such as `\d` is not, so folding `'\d'` into
74
+ * `'d'` or `'\u0041'` into `'A'` would claim an equivalence nobody has
75
+ * observed.
76
+ */
77
+ export declare function printRtdbStringLiteral(raw: string, value: string): string;
78
+ /**
79
+ * Expression text for `tree`, with single spaces around binary operators and
80
+ * only the parentheses the tree's shape needs. The text parses back to the
81
+ * same tree. String literals written without a backslash print as
82
+ * `'value'`, so `"a"` and `'a'` print alike; every other literal prints as
83
+ * its source text.
84
+ */
85
+ export declare function printRtdbExpressionTree(tree: RtdbExpressionTree): string;
86
+ //# sourceMappingURL=expression-tree.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"expression-tree.d.ts","sourceRoot":"","sources":["../../../../src/rules/rtdb/grammar/expression-tree.ts"],"names":[],"mappings":"AAuBA,MAAM,MAAM,kBAAkB,GAC1B,IAAI,GAAG,IAAI,GACX,KAAK,GAAG,KAAK,GAAG,IAAI,GAAG,IAAI,GAC3B,IAAI,GAAG,IAAI,GAAG,GAAG,GAAG,GAAG,GACvB,GAAG,GAAG,GAAG,GACT,GAAG,GAAG,GAAG,GAAG,GAAG,CAAC;AAEpB,MAAM,MAAM,kBAAkB,GAC1B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,UAAU,EAAE,kBAAkB,CAAC;IAAC,SAAS,EAAE,kBAAkB,CAAA;CAAE,GAC5G;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,QAAQ,EAAE,kBAAkB,CAAC;IAAC,IAAI,EAAE,kBAAkB,CAAC;IAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,GACrG;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,GAAG,GAAG,GAAG,CAAC;IAAC,QAAQ,EAAE,kBAAkB,CAAA;CAAE,GACpE;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,kBAAkB,CAAC;IAAC,MAAM,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,kBAAkB,EAAE,CAAA;CAAE,GAC1F;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GAChE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,kBAAkB,CAAC;IAAC,KAAK,EAAE,kBAAkB,CAAA;CAAE,GACxE;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,QAAQ,EAAE,kBAAkB,EAAE,CAAA;CAAE;AACnD,0FAA0F;GACxF;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GAC9C;IAAE,IAAI,EAAE,QAAQ,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC/B;IAAE,IAAI,EAAE,OAAO,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,GAC9B;IAAE,IAAI,EAAE,SAAS,CAAC;IAAC,KAAK,EAAE,OAAO,CAAA;CAAE,GACnC;IAAE,IAAI,EAAE,MAAM,CAAA;CAAE,GAChB;IAAE,IAAI,EAAE,YAAY,CAAC;IAAC,IAAI,EAAE,MAAM,CAAA;CAAE,CAAC;AAEzC,MAAM,MAAM,wBAAwB,GAChC;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,IAAI,EAAE,kBAAkB,CAAA;CAAE,GACtC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,OAAO,EAAE,MAAM,CAAA;CAAE,CAAC;AA4FnC;;;;;GAKG;AACH,wBAAgB,uBAAuB,CAAC,GAAG,EAAE,MAAM,GAAG,wBAAwB,CAU7E;AA0CD;;;;;;;;;GASG;AACH,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,CAEzE;AAED;;;;;;GAMG;AACH,wBAAgB,uBAAuB,CAAC,IAAI,EAAE,kBAAkB,GAAG,MAAM,CAoCxE"}