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.
- package/dist/rules/index.d.ts +3 -0
- package/dist/rules/index.d.ts.map +1 -1
- package/dist/rules/index.js +3 -0
- package/dist/rules/index.js.map +1 -1
- package/dist/rules/internal/rtdb.d.ts +5 -0
- package/dist/rules/internal/rtdb.d.ts.map +1 -1
- package/dist/rules/internal/rtdb.js +3 -0
- package/dist/rules/internal/rtdb.js.map +1 -1
- package/dist/rules/rtdb/grammar/canonical.d.ts +52 -0
- package/dist/rules/rtdb/grammar/canonical.d.ts.map +1 -0
- package/dist/rules/rtdb/grammar/canonical.js +328 -0
- package/dist/rules/rtdb/grammar/canonical.js.map +1 -0
- package/dist/rules/rtdb/grammar/expression-tree.d.ts +86 -0
- package/dist/rules/rtdb/grammar/expression-tree.d.ts.map +1 -0
- package/dist/rules/rtdb/grammar/expression-tree.js +212 -0
- package/dist/rules/rtdb/grammar/expression-tree.js.map +1 -0
- package/dist/rules/rtdb/rules-diff.d.ts +30 -0
- package/dist/rules/rtdb/rules-diff.d.ts.map +1 -0
- package/dist/rules/rtdb/rules-diff.js +81 -0
- package/dist/rules/rtdb/rules-diff.js.map +1 -0
- package/package.json +1 -1
- package/src/rules/index.ts +5 -0
- package/src/rules/internal/rtdb.ts +16 -0
- package/src/rules/rtdb/grammar/canonical.ts +339 -0
- package/src/rules/rtdb/grammar/expression-tree.ts +256 -0
- package/src/rules/rtdb/rules-diff.ts +118 -0
package/dist/rules/index.d.ts
CHANGED
|
@@ -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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"}
|
package/dist/rules/index.js
CHANGED
|
@@ -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) ────────
|
package/dist/rules/index.js.map
CHANGED
|
@@ -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;
|
|
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"}
|