pyric 0.0.1 → 0.1.0-alpha.7
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/README.md +52 -1
- package/dist/app/index.d.ts +81 -0
- package/dist/app/index.d.ts.map +1 -0
- package/dist/app/index.js +78 -0
- package/dist/app/index.js.map +1 -0
- package/dist/auth/index.d.ts +346 -0
- package/dist/auth/index.d.ts.map +1 -0
- package/dist/auth/index.js +701 -0
- package/dist/auth/index.js.map +1 -0
- package/dist/auth/prod-backend.d.ts +39 -0
- package/dist/auth/prod-backend.d.ts.map +1 -0
- package/dist/auth/prod-backend.js +179 -0
- package/dist/auth/prod-backend.js.map +1 -0
- package/dist/auth/providers.d.ts +107 -0
- package/dist/auth/providers.d.ts.map +1 -0
- package/dist/auth/providers.js +138 -0
- package/dist/auth/providers.js.map +1 -0
- package/dist/auth/sandbox-backend.d.ts +769 -0
- package/dist/auth/sandbox-backend.d.ts.map +1 -0
- package/dist/auth/sandbox-backend.js +1598 -0
- package/dist/auth/sandbox-backend.js.map +1 -0
- package/dist/auth/target.d.ts +40 -0
- package/dist/auth/target.d.ts.map +1 -0
- package/dist/auth/target.js +28 -0
- package/dist/auth/target.js.map +1 -0
- package/dist/auth/types.d.ts +252 -0
- package/dist/auth/types.d.ts.map +1 -0
- package/dist/auth/types.js +26 -0
- package/dist/auth/types.js.map +1 -0
- package/dist/database/constraints/atoms.d.ts +29 -0
- package/dist/database/constraints/atoms.d.ts.map +1 -0
- package/dist/database/constraints/atoms.js +43 -0
- package/dist/database/constraints/atoms.js.map +1 -0
- package/dist/database/constraints/compose.d.ts +16 -0
- package/dist/database/constraints/compose.d.ts.map +1 -0
- package/dist/database/constraints/compose.js +15 -0
- package/dist/database/constraints/compose.js.map +1 -0
- package/dist/database/constraints/data.d.ts +30 -0
- package/dist/database/constraints/data.d.ts.map +1 -0
- package/dist/database/constraints/data.js +46 -0
- package/dist/database/constraints/data.js.map +1 -0
- package/dist/database/constraints/document.d.ts +42 -0
- package/dist/database/constraints/document.d.ts.map +1 -0
- package/dist/database/constraints/document.js +86 -0
- package/dist/database/constraints/document.js.map +1 -0
- package/dist/database/constraints/game.d.ts +30 -0
- package/dist/database/constraints/game.d.ts.map +1 -0
- package/dist/database/constraints/game.js +49 -0
- package/dist/database/constraints/game.js.map +1 -0
- package/dist/database/constraints/index.d.ts +12 -0
- package/dist/database/constraints/index.d.ts.map +1 -0
- package/dist/database/constraints/index.js +9 -0
- package/dist/database/constraints/index.js.map +1 -0
- package/dist/database/constraints/policies.d.ts +16 -0
- package/dist/database/constraints/policies.d.ts.map +1 -0
- package/dist/database/constraints/policies.js +17 -0
- package/dist/database/constraints/policies.js.map +1 -0
- package/dist/database/constraints/ruleset.d.ts +5 -0
- package/dist/database/constraints/ruleset.d.ts.map +1 -0
- package/dist/database/constraints/ruleset.js +132 -0
- package/dist/database/constraints/ruleset.js.map +1 -0
- package/dist/database/constraints/schema.d.ts +17 -0
- package/dist/database/constraints/schema.d.ts.map +1 -0
- package/dist/database/constraints/schema.js +74 -0
- package/dist/database/constraints/schema.js.map +1 -0
- package/dist/database/constraints/types.d.ts +22 -0
- package/dist/database/constraints/types.d.ts.map +1 -0
- package/dist/database/constraints/types.js +2 -0
- package/dist/database/constraints/types.js.map +1 -0
- package/dist/database/crawl/handler.d.ts +7 -0
- package/dist/database/crawl/handler.d.ts.map +1 -0
- package/dist/database/crawl/handler.js +91 -0
- package/dist/database/crawl/handler.js.map +1 -0
- package/dist/database/crawl/semaphore.d.ts +9 -0
- package/dist/database/crawl/semaphore.d.ts.map +1 -0
- package/dist/database/crawl/semaphore.js +27 -0
- package/dist/database/crawl/semaphore.js.map +1 -0
- package/dist/database/crawl/spec.d.ts +33 -0
- package/dist/database/crawl/spec.d.ts.map +1 -0
- package/dist/database/crawl/spec.js +12 -0
- package/dist/database/crawl/spec.js.map +1 -0
- package/dist/database/data/handler.d.ts +9 -0
- package/dist/database/data/handler.d.ts.map +1 -0
- package/dist/database/data/handler.js +96 -0
- package/dist/database/data/handler.js.map +1 -0
- package/dist/database/data/spec.d.ts +77 -0
- package/dist/database/data/spec.d.ts.map +1 -0
- package/dist/database/data/spec.js +17 -0
- package/dist/database/data/spec.js.map +1 -0
- package/dist/database/data/validated.d.ts +8 -0
- package/dist/database/data/validated.d.ts.map +1 -0
- package/dist/database/data/validated.js +99 -0
- package/dist/database/data/validated.js.map +1 -0
- package/dist/database/grammar/RtdbExpr.ohm +98 -0
- package/dist/database/grammar/RtdbExpr.ohm.generated.d.ts +2 -0
- package/dist/database/grammar/RtdbExpr.ohm.generated.d.ts.map +1 -0
- package/dist/database/grammar/RtdbExpr.ohm.generated.js +103 -0
- package/dist/database/grammar/RtdbExpr.ohm.generated.js.map +1 -0
- package/dist/database/grammar/RtdbExprParser.d.ts +5 -0
- package/dist/database/grammar/RtdbExprParser.d.ts.map +1 -0
- package/dist/database/grammar/RtdbExprParser.js +53 -0
- package/dist/database/grammar/RtdbExprParser.js.map +1 -0
- package/dist/database/grammar/linter.d.ts +3 -0
- package/dist/database/grammar/linter.d.ts.map +1 -0
- package/dist/database/grammar/linter.js +66 -0
- package/dist/database/grammar/linter.js.map +1 -0
- package/dist/database/grammar/simulator.d.ts +31 -0
- package/dist/database/grammar/simulator.d.ts.map +1 -0
- package/dist/database/grammar/simulator.js +255 -0
- package/dist/database/grammar/simulator.js.map +1 -0
- package/dist/database/grammar/validator.d.ts +3 -0
- package/dist/database/grammar/validator.d.ts.map +1 -0
- package/dist/database/grammar/validator.js +84 -0
- package/dist/database/grammar/validator.js.map +1 -0
- package/dist/database/host.d.ts +50 -0
- package/dist/database/host.d.ts.map +1 -0
- package/dist/database/host.js +41 -0
- package/dist/database/host.js.map +1 -0
- package/dist/database/index.d.ts +40 -0
- package/dist/database/index.d.ts.map +1 -0
- package/dist/database/index.js +47 -0
- package/dist/database/index.js.map +1 -0
- package/dist/database/initialize-from-app.d.ts +28 -0
- package/dist/database/initialize-from-app.d.ts.map +1 -0
- package/dist/database/initialize-from-app.js +23 -0
- package/dist/database/initialize-from-app.js.map +1 -0
- package/dist/database/ir/handler.d.ts +6 -0
- package/dist/database/ir/handler.d.ts.map +1 -0
- package/dist/database/ir/handler.js +52 -0
- package/dist/database/ir/handler.js.map +1 -0
- package/dist/database/ir/spec.d.ts +25 -0
- package/dist/database/ir/spec.d.ts.map +1 -0
- package/dist/database/ir/spec.js +11 -0
- package/dist/database/ir/spec.js.map +1 -0
- package/dist/database/mapper.d.ts +9 -0
- package/dist/database/mapper.d.ts.map +1 -0
- package/dist/database/mapper.js +115 -0
- package/dist/database/mapper.js.map +1 -0
- package/dist/database/modular.d.ts +604 -0
- package/dist/database/modular.d.ts.map +1 -0
- package/dist/database/modular.js +1226 -0
- package/dist/database/modular.js.map +1 -0
- package/dist/database/replay.d.ts +33 -0
- package/dist/database/replay.d.ts.map +1 -0
- package/dist/database/replay.js +124 -0
- package/dist/database/replay.js.map +1 -0
- package/dist/database/resolver.d.ts +4 -0
- package/dist/database/resolver.d.ts.map +1 -0
- package/dist/database/resolver.js +66 -0
- package/dist/database/resolver.js.map +1 -0
- package/dist/database/sandbox/backend.d.ts +403 -0
- package/dist/database/sandbox/backend.d.ts.map +1 -0
- package/dist/database/sandbox/backend.js +1467 -0
- package/dist/database/sandbox/backend.js.map +1 -0
- package/dist/database/sandbox/data-tree.d.ts +123 -0
- package/dist/database/sandbox/data-tree.d.ts.map +1 -0
- package/dist/database/sandbox/data-tree.js +310 -0
- package/dist/database/sandbox/data-tree.js.map +1 -0
- package/dist/database/sandbox/normalize.d.ts +77 -0
- package/dist/database/sandbox/normalize.d.ts.map +1 -0
- package/dist/database/sandbox/normalize.js +165 -0
- package/dist/database/sandbox/normalize.js.map +1 -0
- package/dist/database/sandbox/push-id.d.ts +32 -0
- package/dist/database/sandbox/push-id.d.ts.map +1 -0
- package/dist/database/sandbox/push-id.js +82 -0
- package/dist/database/sandbox/push-id.js.map +1 -0
- package/dist/database/sandbox/query.d.ts +175 -0
- package/dist/database/sandbox/query.d.ts.map +1 -0
- package/dist/database/sandbox/query.js +269 -0
- package/dist/database/sandbox/query.js.map +1 -0
- package/dist/database/sandbox/rules-eval.d.ts +69 -0
- package/dist/database/sandbox/rules-eval.d.ts.map +1 -0
- package/dist/database/sandbox/rules-eval.js +124 -0
- package/dist/database/sandbox/rules-eval.js.map +1 -0
- package/dist/database/sandbox/sentinels.d.ts +71 -0
- package/dist/database/sandbox/sentinels.d.ts.map +1 -0
- package/dist/database/sandbox/sentinels.js +92 -0
- package/dist/database/sandbox/sentinels.js.map +1 -0
- package/dist/database/simulation/handler.d.ts +6 -0
- package/dist/database/simulation/handler.d.ts.map +1 -0
- package/dist/database/simulation/handler.js +236 -0
- package/dist/database/simulation/handler.js.map +1 -0
- package/dist/database/simulation/spec.d.ts +69 -0
- package/dist/database/simulation/spec.d.ts.map +1 -0
- package/dist/database/simulation/spec.js +25 -0
- package/dist/database/simulation/spec.js.map +1 -0
- package/dist/database/tools.d.ts +22 -0
- package/dist/database/tools.d.ts.map +1 -0
- package/dist/database/tools.js +272 -0
- package/dist/database/tools.js.map +1 -0
- package/dist/database/types.d.ts +210 -0
- package/dist/database/types.d.ts.map +1 -0
- package/dist/database/types.js +26 -0
- package/dist/database/types.js.map +1 -0
- package/dist/database/write/handler.d.ts +7 -0
- package/dist/database/write/handler.d.ts.map +1 -0
- package/dist/database/write/handler.js +42 -0
- package/dist/database/write/handler.js.map +1 -0
- package/dist/database/write/spec.d.ts +18 -0
- package/dist/database/write/spec.d.ts.map +1 -0
- package/dist/database/write/spec.js +7 -0
- package/dist/database/write/spec.js.map +1 -0
- package/dist/firestore/index.d.ts +533 -0
- package/dist/firestore/index.d.ts.map +1 -0
- package/dist/firestore/index.js +1536 -0
- package/dist/firestore/index.js.map +1 -0
- package/dist/firestore/tools.d.ts +67 -0
- package/dist/firestore/tools.d.ts.map +1 -0
- package/dist/firestore/tools.js +318 -0
- package/dist/firestore/tools.js.map +1 -0
- package/dist/firestore-values/index.d.ts +63 -0
- package/dist/firestore-values/index.d.ts.map +1 -0
- package/dist/firestore-values/index.js +148 -0
- package/dist/firestore-values/index.js.map +1 -0
- package/dist/project-scope.d.ts +5 -0
- package/dist/project-scope.d.ts.map +1 -0
- package/dist/project-scope.js +2 -0
- package/dist/project-scope.js.map +1 -0
- package/dist/rules/extract.d.ts +28 -0
- package/dist/rules/extract.d.ts.map +1 -0
- package/dist/rules/extract.js +25 -0
- package/dist/rules/extract.js.map +1 -0
- package/dist/rules/generators/assembler.d.ts +19 -0
- package/dist/rules/generators/assembler.d.ts.map +1 -0
- package/dist/rules/generators/assembler.js +292 -0
- package/dist/rules/generators/assembler.js.map +1 -0
- package/dist/rules/generators/expressions.d.ts +52 -0
- package/dist/rules/generators/expressions.d.ts.map +1 -0
- package/dist/rules/generators/expressions.js +117 -0
- package/dist/rules/generators/expressions.js.map +1 -0
- package/dist/rules/generators/grid.d.ts +22 -0
- package/dist/rules/generators/grid.d.ts.map +1 -0
- package/dist/rules/generators/grid.js +52 -0
- package/dist/rules/generators/grid.js.map +1 -0
- package/dist/rules/grammar/FirestoreAST.d.ts +129 -0
- package/dist/rules/grammar/FirestoreAST.d.ts.map +1 -0
- package/dist/rules/grammar/FirestoreAST.js +3 -0
- package/dist/rules/grammar/FirestoreAST.js.map +1 -0
- package/dist/rules/grammar/FirestoreAssembler.d.ts +5 -0
- package/dist/rules/grammar/FirestoreAssembler.d.ts.map +1 -0
- package/dist/rules/grammar/FirestoreAssembler.js +158 -0
- package/dist/rules/grammar/FirestoreAssembler.js.map +1 -0
- package/dist/rules/grammar/FirestoreParser.d.ts +46 -0
- package/dist/rules/grammar/FirestoreParser.d.ts.map +1 -0
- package/dist/rules/grammar/FirestoreParser.js +409 -0
- package/dist/rules/grammar/FirestoreParser.js.map +1 -0
- package/dist/rules/grammar/FirestoreRules.ohm +229 -0
- package/dist/rules/grammar/FirestoreRules.ohm.generated.d.ts +2 -0
- package/dist/rules/grammar/FirestoreRules.ohm.generated.d.ts.map +1 -0
- package/dist/rules/grammar/FirestoreRules.ohm.generated.js +234 -0
- package/dist/rules/grammar/FirestoreRules.ohm.generated.js.map +1 -0
- package/dist/rules/grammar/FirestoreValidator.d.ts +10 -0
- package/dist/rules/grammar/FirestoreValidator.d.ts.map +1 -0
- package/dist/rules/grammar/FirestoreValidator.js +482 -0
- package/dist/rules/grammar/FirestoreValidator.js.map +1 -0
- package/dist/rules/index.d.ts +67 -0
- package/dist/rules/index.d.ts.map +1 -0
- package/dist/rules/index.js +80 -0
- package/dist/rules/index.js.map +1 -0
- package/dist/rules/indexes/extract/annotation-collect.d.ts +42 -0
- package/dist/rules/indexes/extract/annotation-collect.d.ts.map +1 -0
- package/dist/rules/indexes/extract/annotation-collect.js +69 -0
- package/dist/rules/indexes/extract/annotation-collect.js.map +1 -0
- package/dist/rules/indexes/extract/annotations.d.ts +50 -0
- package/dist/rules/indexes/extract/annotations.d.ts.map +1 -0
- package/dist/rules/indexes/extract/annotations.js +144 -0
- package/dist/rules/indexes/extract/annotations.js.map +1 -0
- package/dist/rules/indexes/extract/ast.d.ts +54 -0
- package/dist/rules/indexes/extract/ast.d.ts.map +1 -0
- package/dist/rules/indexes/extract/ast.js +119 -0
- package/dist/rules/indexes/extract/ast.js.map +1 -0
- package/dist/rules/indexes/extract/classify.d.ts +41 -0
- package/dist/rules/indexes/extract/classify.d.ts.map +1 -0
- package/dist/rules/indexes/extract/classify.js +138 -0
- package/dist/rules/indexes/extract/classify.js.map +1 -0
- package/dist/rules/indexes/extract/composite.d.ts +38 -0
- package/dist/rules/indexes/extract/composite.d.ts.map +1 -0
- package/dist/rules/indexes/extract/composite.js +85 -0
- package/dist/rules/indexes/extract/composite.js.map +1 -0
- package/dist/rules/indexes/extract/dataflow.d.ts +45 -0
- package/dist/rules/indexes/extract/dataflow.d.ts.map +1 -0
- package/dist/rules/indexes/extract/dataflow.js +200 -0
- package/dist/rules/indexes/extract/dataflow.js.map +1 -0
- package/dist/rules/indexes/extract/enumerate.d.ts +41 -0
- package/dist/rules/indexes/extract/enumerate.d.ts.map +1 -0
- package/dist/rules/indexes/extract/enumerate.js +163 -0
- package/dist/rules/indexes/extract/enumerate.js.map +1 -0
- package/dist/rules/indexes/extract/extractor.d.ts +3 -0
- package/dist/rules/indexes/extract/extractor.d.ts.map +1 -0
- package/dist/rules/indexes/extract/extractor.js +274 -0
- package/dist/rules/indexes/extract/extractor.js.map +1 -0
- package/dist/rules/indexes/extract/types.d.ts +211 -0
- package/dist/rules/indexes/extract/types.d.ts.map +1 -0
- package/dist/rules/indexes/extract/types.js +14 -0
- package/dist/rules/indexes/extract/types.js.map +1 -0
- package/dist/rules/indexes/extractHandler.d.ts +16 -0
- package/dist/rules/indexes/extractHandler.d.ts.map +1 -0
- package/dist/rules/indexes/extractHandler.js +100 -0
- package/dist/rules/indexes/extractHandler.js.map +1 -0
- package/dist/rules/indexes/extractTool.d.ts +15 -0
- package/dist/rules/indexes/extractTool.d.ts.map +1 -0
- package/dist/rules/indexes/extractTool.js +55 -0
- package/dist/rules/indexes/extractTool.js.map +1 -0
- package/dist/rules/indexes/types.d.ts +71 -0
- package/dist/rules/indexes/types.d.ts.map +1 -0
- package/dist/rules/indexes/types.js +15 -0
- package/dist/rules/indexes/types.js.map +1 -0
- package/dist/rules/inspect/handler.d.ts +6 -0
- package/dist/rules/inspect/handler.d.ts.map +1 -0
- package/dist/rules/inspect/handler.js +144 -0
- package/dist/rules/inspect/handler.js.map +1 -0
- package/dist/rules/inspect/spec.d.ts +37 -0
- package/dist/rules/inspect/spec.d.ts.map +1 -0
- package/dist/rules/inspect/spec.js +2 -0
- package/dist/rules/inspect/spec.js.map +1 -0
- package/dist/rules/inspect/tools.d.ts +21 -0
- package/dist/rules/inspect/tools.d.ts.map +1 -0
- package/dist/rules/inspect/tools.js +21 -0
- package/dist/rules/inspect/tools.js.map +1 -0
- package/dist/rules/linter/ast-utils.d.ts +97 -0
- package/dist/rules/linter/ast-utils.d.ts.map +1 -0
- package/dist/rules/linter/ast-utils.js +491 -0
- package/dist/rules/linter/ast-utils.js.map +1 -0
- package/dist/rules/linter/hallucinations.d.ts +34 -0
- package/dist/rules/linter/hallucinations.d.ts.map +1 -0
- package/dist/rules/linter/hallucinations.js +334 -0
- package/dist/rules/linter/hallucinations.js.map +1 -0
- package/dist/rules/linter/linter.d.ts +84 -0
- package/dist/rules/linter/linter.d.ts.map +1 -0
- package/dist/rules/linter/linter.js +784 -0
- package/dist/rules/linter/linter.js.map +1 -0
- package/dist/rules/modules/resolver-browser.d.ts +41 -0
- package/dist/rules/modules/resolver-browser.d.ts.map +1 -0
- package/dist/rules/modules/resolver-browser.js +63 -0
- package/dist/rules/modules/resolver-browser.js.map +1 -0
- package/dist/rules/modules/resolver-core.d.ts +51 -0
- package/dist/rules/modules/resolver-core.d.ts.map +1 -0
- package/dist/rules/modules/resolver-core.js +338 -0
- package/dist/rules/modules/resolver-core.js.map +1 -0
- package/dist/rules/modules/resolver.d.ts +17 -0
- package/dist/rules/modules/resolver.d.ts.map +1 -0
- package/dist/rules/modules/resolver.js +49 -0
- package/dist/rules/modules/resolver.js.map +1 -0
- package/dist/rules/modules/stdlib/atomic.rules +52 -0
- package/dist/rules/modules/stdlib/atomic.test.json +152 -0
- package/dist/rules/modules/stdlib/auth.rules +7 -0
- package/dist/rules/modules/stdlib/auth.test.json +53 -0
- package/dist/rules/modules/stdlib/content.rules +50 -0
- package/dist/rules/modules/stdlib/content.test.json +238 -0
- package/dist/rules/modules/stdlib/counters.rules +41 -0
- package/dist/rules/modules/stdlib/counters.test.json +254 -0
- package/dist/rules/modules/stdlib/geometry.rules +43 -0
- package/dist/rules/modules/stdlib/geometry.test.json +200 -0
- package/dist/rules/modules/stdlib/joining.rules +49 -0
- package/dist/rules/modules/stdlib/joining.test.json +287 -0
- package/dist/rules/modules/stdlib/lifecycle.rules +51 -0
- package/dist/rules/modules/stdlib/lifecycle.test.json +288 -0
- package/dist/rules/modules/stdlib/lobby.rules +44 -0
- package/dist/rules/modules/stdlib/lobby.test.json +32 -0
- package/dist/rules/modules/stdlib/membership.rules +40 -0
- package/dist/rules/modules/stdlib/membership.test.json +107 -0
- package/dist/rules/modules/stdlib/spaces.rules +46 -0
- package/dist/rules/modules/stdlib/spaces.test.json +392 -0
- package/dist/rules/modules/stdlib/state.rules +28 -0
- package/dist/rules/modules/stdlib/state.test.json +55 -0
- package/dist/rules/modules/stdlib/timing.rules +20 -0
- package/dist/rules/modules/stdlib/timing.test.json +106 -0
- package/dist/rules/modules/stdlib/transitions.rules +34 -0
- package/dist/rules/modules/stdlib/transitions.test.json +86 -0
- package/dist/rules/modules/stdlib/turns.rules +27 -0
- package/dist/rules/modules/stdlib/turns.test.json +64 -0
- package/dist/rules/modules/stdlib/validation.rules +31 -0
- package/dist/rules/modules/stdlib/validation.test.json +184 -0
- package/dist/rules/modules/stdlib-content.d.ts +11 -0
- package/dist/rules/modules/stdlib-content.d.ts.map +1 -0
- package/dist/rules/modules/stdlib-content.js +590 -0
- package/dist/rules/modules/stdlib-content.js.map +1 -0
- package/dist/rules/node.d.ts +17 -0
- package/dist/rules/node.d.ts.map +1 -0
- package/dist/rules/node.js +21 -0
- package/dist/rules/node.js.map +1 -0
- package/dist/rules/rtdb.d.ts +28 -0
- package/dist/rules/rtdb.d.ts.map +1 -0
- package/dist/rules/rtdb.js +15 -0
- package/dist/rules/rtdb.js.map +1 -0
- package/dist/rules/simulator/evaluator.d.ts +179 -0
- package/dist/rules/simulator/evaluator.d.ts.map +1 -0
- package/dist/rules/simulator/evaluator.js +1221 -0
- package/dist/rules/simulator/evaluator.js.map +1 -0
- package/dist/rules/simulator/expression/eval-errors.d.ts +86 -0
- package/dist/rules/simulator/expression/eval-errors.d.ts.map +1 -0
- package/dist/rules/simulator/expression/eval-errors.js +68 -0
- package/dist/rules/simulator/expression/eval-errors.js.map +1 -0
- package/dist/rules/simulator/expression/evaluator.d.ts +43 -0
- package/dist/rules/simulator/expression/evaluator.d.ts.map +1 -0
- package/dist/rules/simulator/expression/evaluator.js +298 -0
- package/dist/rules/simulator/expression/evaluator.js.map +1 -0
- package/dist/rules/simulator/expression/lexer.d.ts +36 -0
- package/dist/rules/simulator/expression/lexer.d.ts.map +1 -0
- package/dist/rules/simulator/expression/lexer.js +318 -0
- package/dist/rules/simulator/expression/lexer.js.map +1 -0
- package/dist/rules/simulator/expression/parser.d.ts +39 -0
- package/dist/rules/simulator/expression/parser.d.ts.map +1 -0
- package/dist/rules/simulator/expression/parser.js +329 -0
- package/dist/rules/simulator/expression/parser.js.map +1 -0
- package/dist/rules/simulator/expression/types.d.ts +137 -0
- package/dist/rules/simulator/expression/types.d.ts.map +1 -0
- package/dist/rules/simulator/expression/types.js +90 -0
- package/dist/rules/simulator/expression/types.js.map +1 -0
- package/dist/rules/simulator/expression/walk-data.d.ts +52 -0
- package/dist/rules/simulator/expression/walk-data.d.ts.map +1 -0
- package/dist/rules/simulator/expression/walk-data.js +167 -0
- package/dist/rules/simulator/expression/walk-data.js.map +1 -0
- package/dist/rules/simulator/firestore-set.d.ts +25 -0
- package/dist/rules/simulator/firestore-set.d.ts.map +1 -0
- package/dist/rules/simulator/firestore-set.js +89 -0
- package/dist/rules/simulator/firestore-set.js.map +1 -0
- package/dist/rules/simulator/handler.d.ts +36 -0
- package/dist/rules/simulator/handler.d.ts.map +1 -0
- package/dist/rules/simulator/handler.js +583 -0
- package/dist/rules/simulator/handler.js.map +1 -0
- package/dist/rules/simulator/mapdiff.d.ts +29 -0
- package/dist/rules/simulator/mapdiff.d.ts.map +1 -0
- package/dist/rules/simulator/mapdiff.js +72 -0
- package/dist/rules/simulator/mapdiff.js.map +1 -0
- package/dist/rules/simulator/project-after-state.d.ts +33 -0
- package/dist/rules/simulator/project-after-state.d.ts.map +1 -0
- package/dist/rules/simulator/project-after-state.js +88 -0
- package/dist/rules/simulator/project-after-state.js.map +1 -0
- package/dist/rules/simulator/query-proof.d.ts +80 -0
- package/dist/rules/simulator/query-proof.d.ts.map +1 -0
- package/dist/rules/simulator/query-proof.js +142 -0
- package/dist/rules/simulator/query-proof.js.map +1 -0
- package/dist/rules/simulator/value-equality.d.ts +8 -0
- package/dist/rules/simulator/value-equality.d.ts.map +1 -0
- package/dist/rules/simulator/value-equality.js +40 -0
- package/dist/rules/simulator/value-equality.js.map +1 -0
- package/dist/rules/simulator/wrappers/base.d.ts +129 -0
- package/dist/rules/simulator/wrappers/base.d.ts.map +1 -0
- package/dist/rules/simulator/wrappers/base.js +90 -0
- package/dist/rules/simulator/wrappers/base.js.map +1 -0
- package/dist/rules/simulator/wrappers/bytes.d.ts +45 -0
- package/dist/rules/simulator/wrappers/bytes.d.ts.map +1 -0
- package/dist/rules/simulator/wrappers/bytes.js +130 -0
- package/dist/rules/simulator/wrappers/bytes.js.map +1 -0
- package/dist/rules/simulator/wrappers/duration.d.ts +76 -0
- package/dist/rules/simulator/wrappers/duration.d.ts.map +1 -0
- package/dist/rules/simulator/wrappers/duration.js +176 -0
- package/dist/rules/simulator/wrappers/duration.js.map +1 -0
- package/dist/rules/simulator/wrappers/float.d.ts +52 -0
- package/dist/rules/simulator/wrappers/float.d.ts.map +1 -0
- package/dist/rules/simulator/wrappers/float.js +88 -0
- package/dist/rules/simulator/wrappers/float.js.map +1 -0
- package/dist/rules/simulator/wrappers/latlng.d.ts +40 -0
- package/dist/rules/simulator/wrappers/latlng.d.ts.map +1 -0
- package/dist/rules/simulator/wrappers/latlng.js +100 -0
- package/dist/rules/simulator/wrappers/latlng.js.map +1 -0
- package/dist/rules/simulator/wrappers/path.d.ts +75 -0
- package/dist/rules/simulator/wrappers/path.d.ts.map +1 -0
- package/dist/rules/simulator/wrappers/path.js +158 -0
- package/dist/rules/simulator/wrappers/path.js.map +1 -0
- package/dist/rules/simulator/wrappers/reference.d.ts +82 -0
- package/dist/rules/simulator/wrappers/reference.d.ts.map +1 -0
- package/dist/rules/simulator/wrappers/reference.js +145 -0
- package/dist/rules/simulator/wrappers/reference.js.map +1 -0
- package/dist/rules/simulator/wrappers/timestamp.d.ts +86 -0
- package/dist/rules/simulator/wrappers/timestamp.d.ts.map +1 -0
- package/dist/rules/simulator/wrappers/timestamp.js +207 -0
- package/dist/rules/simulator/wrappers/timestamp.js.map +1 -0
- package/dist/rules/simulator/wrappers/vector.d.ts +43 -0
- package/dist/rules/simulator/wrappers/vector.d.ts.map +1 -0
- package/dist/rules/simulator/wrappers/vector.js +80 -0
- package/dist/rules/simulator/wrappers/vector.js.map +1 -0
- package/dist/rules/simulator-tools-impl.d.ts +64 -0
- package/dist/rules/simulator-tools-impl.d.ts.map +1 -0
- package/dist/rules/simulator-tools-impl.js +462 -0
- package/dist/rules/simulator-tools-impl.js.map +1 -0
- package/dist/rules/simulator.d.ts +20 -0
- package/dist/rules/simulator.d.ts.map +1 -0
- package/dist/rules/simulator.js +24 -0
- package/dist/rules/simulator.js.map +1 -0
- package/dist/rules/stdlib-modules.d.ts +73 -0
- package/dist/rules/stdlib-modules.d.ts.map +1 -0
- package/dist/rules/stdlib-modules.js +849 -0
- package/dist/rules/stdlib-modules.js.map +1 -0
- package/dist/rules/stdlib-tools.d.ts +19 -0
- package/dist/rules/stdlib-tools.d.ts.map +1 -0
- package/dist/rules/stdlib-tools.js +164 -0
- package/dist/rules/stdlib-tools.js.map +1 -0
- package/dist/rules/test/handler.d.ts +9 -0
- package/dist/rules/test/handler.d.ts.map +1 -0
- package/dist/rules/test/handler.js +124 -0
- package/dist/rules/test/handler.js.map +1 -0
- package/dist/rules/test/spec.d.ts +517 -0
- package/dist/rules/test/spec.d.ts.map +1 -0
- package/dist/rules/test/spec.js +227 -0
- package/dist/rules/test/spec.js.map +1 -0
- package/dist/rules/tools.d.ts +41 -0
- package/dist/rules/tools.d.ts.map +1 -0
- package/dist/rules/tools.js +124 -0
- package/dist/rules/tools.js.map +1 -0
- package/dist/rules/write/handler.d.ts +6 -0
- package/dist/rules/write/handler.d.ts.map +1 -0
- package/dist/rules/write/handler.js +126 -0
- package/dist/rules/write/handler.js.map +1 -0
- package/dist/rules/write/spec.d.ts +28 -0
- package/dist/rules/write/spec.d.ts.map +1 -0
- package/dist/rules/write/spec.js +2 -0
- package/dist/rules/write/spec.js.map +1 -0
- package/dist/sandbox/admin-compat.d.ts +20 -0
- package/dist/sandbox/admin-compat.d.ts.map +1 -0
- package/dist/sandbox/admin-compat.js +19 -0
- package/dist/sandbox/admin-compat.js.map +1 -0
- package/dist/sandbox/admin-firestore/error-translation.d.ts +86 -0
- package/dist/sandbox/admin-firestore/error-translation.d.ts.map +1 -0
- package/dist/sandbox/admin-firestore/error-translation.js +204 -0
- package/dist/sandbox/admin-firestore/error-translation.js.map +1 -0
- package/dist/sandbox/admin-firestore/index.d.ts +169 -0
- package/dist/sandbox/admin-firestore/index.d.ts.map +1 -0
- package/dist/sandbox/admin-firestore/index.js +456 -0
- package/dist/sandbox/admin-firestore/index.js.map +1 -0
- package/dist/sandbox/admin-firestore/remote.d.ts +97 -0
- package/dist/sandbox/admin-firestore/remote.d.ts.map +1 -0
- package/dist/sandbox/admin-firestore/remote.js +735 -0
- package/dist/sandbox/admin-firestore/remote.js.map +1 -0
- package/dist/sandbox/branches/index.d.ts +141 -0
- package/dist/sandbox/branches/index.d.ts.map +1 -0
- package/dist/sandbox/branches/index.js +327 -0
- package/dist/sandbox/branches/index.js.map +1 -0
- package/dist/sandbox/firestore/admin-compat/batch.d.ts +34 -0
- package/dist/sandbox/firestore/admin-compat/batch.d.ts.map +1 -0
- package/dist/sandbox/firestore/admin-compat/batch.js +73 -0
- package/dist/sandbox/firestore/admin-compat/batch.js.map +1 -0
- package/dist/sandbox/firestore/admin-compat/doc-ref.d.ts +38 -0
- package/dist/sandbox/firestore/admin-compat/doc-ref.d.ts.map +1 -0
- package/dist/sandbox/firestore/admin-compat/doc-ref.js +154 -0
- package/dist/sandbox/firestore/admin-compat/doc-ref.js.map +1 -0
- package/dist/sandbox/firestore/admin-compat/firestore.d.ts +45 -0
- package/dist/sandbox/firestore/admin-compat/firestore.d.ts.map +1 -0
- package/dist/sandbox/firestore/admin-compat/firestore.js +114 -0
- package/dist/sandbox/firestore/admin-compat/firestore.js.map +1 -0
- package/dist/sandbox/firestore/admin-compat/index.d.ts +45 -0
- package/dist/sandbox/firestore/admin-compat/index.d.ts.map +1 -0
- package/dist/sandbox/firestore/admin-compat/index.js +27 -0
- package/dist/sandbox/firestore/admin-compat/index.js.map +1 -0
- package/dist/sandbox/firestore/admin-compat/paths.d.ts +37 -0
- package/dist/sandbox/firestore/admin-compat/paths.d.ts.map +1 -0
- package/dist/sandbox/firestore/admin-compat/paths.js +49 -0
- package/dist/sandbox/firestore/admin-compat/paths.js.map +1 -0
- package/dist/sandbox/firestore/admin-compat/query.d.ts +261 -0
- package/dist/sandbox/firestore/admin-compat/query.d.ts.map +1 -0
- package/dist/sandbox/firestore/admin-compat/query.js +704 -0
- package/dist/sandbox/firestore/admin-compat/query.js.map +1 -0
- package/dist/sandbox/firestore/admin-compat/read-translation.d.ts +8 -0
- package/dist/sandbox/firestore/admin-compat/read-translation.d.ts.map +1 -0
- package/dist/sandbox/firestore/admin-compat/read-translation.js +59 -0
- package/dist/sandbox/firestore/admin-compat/read-translation.js.map +1 -0
- package/dist/sandbox/firestore/admin-compat/snapshots.d.ts +39 -0
- package/dist/sandbox/firestore/admin-compat/snapshots.d.ts.map +1 -0
- package/dist/sandbox/firestore/admin-compat/snapshots.js +50 -0
- package/dist/sandbox/firestore/admin-compat/snapshots.js.map +1 -0
- package/dist/sandbox/firestore/admin-compat/transaction.d.ts +35 -0
- package/dist/sandbox/firestore/admin-compat/transaction.d.ts.map +1 -0
- package/dist/sandbox/firestore/admin-compat/transaction.js +88 -0
- package/dist/sandbox/firestore/admin-compat/transaction.js.map +1 -0
- package/dist/sandbox/firestore/admin-compat/types.d.ts +297 -0
- package/dist/sandbox/firestore/admin-compat/types.d.ts.map +1 -0
- package/dist/sandbox/firestore/admin-compat/types.js +127 -0
- package/dist/sandbox/firestore/admin-compat/types.js.map +1 -0
- package/dist/sandbox/firestore/admin-compat/value-order.d.ts +49 -0
- package/dist/sandbox/firestore/admin-compat/value-order.d.ts.map +1 -0
- package/dist/sandbox/firestore/admin-compat/value-order.js +172 -0
- package/dist/sandbox/firestore/admin-compat/value-order.js.map +1 -0
- package/dist/sandbox/firestore/auto-id.d.ts +26 -0
- package/dist/sandbox/firestore/auto-id.d.ts.map +1 -0
- package/dist/sandbox/firestore/auto-id.js +36 -0
- package/dist/sandbox/firestore/auto-id.js.map +1 -0
- package/dist/sandbox/firestore/converters/bytes-geopoint.d.ts +48 -0
- package/dist/sandbox/firestore/converters/bytes-geopoint.d.ts.map +1 -0
- package/dist/sandbox/firestore/converters/bytes-geopoint.js +85 -0
- package/dist/sandbox/firestore/converters/bytes-geopoint.js.map +1 -0
- package/dist/sandbox/firestore/converters/fieldvalue.d.ts +69 -0
- package/dist/sandbox/firestore/converters/fieldvalue.d.ts.map +1 -0
- package/dist/sandbox/firestore/converters/fieldvalue.js +166 -0
- package/dist/sandbox/firestore/converters/fieldvalue.js.map +1 -0
- package/dist/sandbox/firestore/converters/reference.d.ts +31 -0
- package/dist/sandbox/firestore/converters/reference.d.ts.map +1 -0
- package/dist/sandbox/firestore/converters/reference.js +51 -0
- package/dist/sandbox/firestore/converters/reference.js.map +1 -0
- package/dist/sandbox/firestore/converters/timestamp.d.ts +32 -0
- package/dist/sandbox/firestore/converters/timestamp.d.ts.map +1 -0
- package/dist/sandbox/firestore/converters/timestamp.js +63 -0
- package/dist/sandbox/firestore/converters/timestamp.js.map +1 -0
- package/dist/sandbox/firestore/converters/user-timestamp.d.ts +46 -0
- package/dist/sandbox/firestore/converters/user-timestamp.d.ts.map +1 -0
- package/dist/sandbox/firestore/converters/user-timestamp.js +65 -0
- package/dist/sandbox/firestore/converters/user-timestamp.js.map +1 -0
- package/dist/sandbox/firestore/converters/vector.d.ts +24 -0
- package/dist/sandbox/firestore/converters/vector.d.ts.map +1 -0
- package/dist/sandbox/firestore/converters/vector.js +53 -0
- package/dist/sandbox/firestore/converters/vector.js.map +1 -0
- package/dist/sandbox/firestore/errors.d.ts +82 -0
- package/dist/sandbox/firestore/errors.d.ts.map +1 -0
- package/dist/sandbox/firestore/errors.js +54 -0
- package/dist/sandbox/firestore/errors.js.map +1 -0
- package/dist/sandbox/firestore/event-log.d.ts +99 -0
- package/dist/sandbox/firestore/event-log.d.ts.map +1 -0
- package/dist/sandbox/firestore/event-log.js +67 -0
- package/dist/sandbox/firestore/event-log.js.map +1 -0
- package/dist/sandbox/firestore/field-merge.d.ts +64 -0
- package/dist/sandbox/firestore/field-merge.d.ts.map +1 -0
- package/dist/sandbox/firestore/field-merge.js +221 -0
- package/dist/sandbox/firestore/field-merge.js.map +1 -0
- package/dist/sandbox/firestore/list-query-proof.d.ts +77 -0
- package/dist/sandbox/firestore/list-query-proof.d.ts.map +1 -0
- package/dist/sandbox/firestore/list-query-proof.js +170 -0
- package/dist/sandbox/firestore/list-query-proof.js.map +1 -0
- package/dist/sandbox/firestore/local-environment.d.ts +806 -0
- package/dist/sandbox/firestore/local-environment.d.ts.map +1 -0
- package/dist/sandbox/firestore/local-environment.js +3028 -0
- package/dist/sandbox/firestore/local-environment.js.map +1 -0
- package/dist/sandbox/firestore/local-state.d.ts +196 -0
- package/dist/sandbox/firestore/local-state.d.ts.map +1 -0
- package/dist/sandbox/firestore/local-state.js +413 -0
- package/dist/sandbox/firestore/local-state.js.map +1 -0
- package/dist/sandbox/firestore/overlay-backing.d.ts +44 -0
- package/dist/sandbox/firestore/overlay-backing.d.ts.map +1 -0
- package/dist/sandbox/firestore/overlay-backing.js +82 -0
- package/dist/sandbox/firestore/overlay-backing.js.map +1 -0
- package/dist/sandbox/firestore/sentinel-capture.d.ts +30 -0
- package/dist/sandbox/firestore/sentinel-capture.d.ts.map +1 -0
- package/dist/sandbox/firestore/sentinel-capture.js +61 -0
- package/dist/sandbox/firestore/sentinel-capture.js.map +1 -0
- package/dist/sandbox/firestore/snapshot-listeners.d.ts +284 -0
- package/dist/sandbox/firestore/snapshot-listeners.d.ts.map +1 -0
- package/dist/sandbox/firestore/snapshot-listeners.js +194 -0
- package/dist/sandbox/firestore/snapshot-listeners.js.map +1 -0
- package/dist/sandbox/firestore/topk.d.ts +12 -0
- package/dist/sandbox/firestore/topk.d.ts.map +1 -0
- package/dist/sandbox/firestore/topk.js +42 -0
- package/dist/sandbox/firestore/topk.js.map +1 -0
- package/dist/sandbox/firestore/transaction-merge.d.ts +55 -0
- package/dist/sandbox/firestore/transaction-merge.d.ts.map +1 -0
- package/dist/sandbox/firestore/transaction-merge.js +107 -0
- package/dist/sandbox/firestore/transaction-merge.js.map +1 -0
- package/dist/sandbox/firestore/transaction-types.d.ts +152 -0
- package/dist/sandbox/firestore/transaction-types.d.ts.map +1 -0
- package/dist/sandbox/firestore/transaction-types.js +10 -0
- package/dist/sandbox/firestore/transaction-types.js.map +1 -0
- package/dist/sandbox/firestore/transaction.d.ts +79 -0
- package/dist/sandbox/firestore/transaction.d.ts.map +1 -0
- package/dist/sandbox/firestore/transaction.js +95 -0
- package/dist/sandbox/firestore/transaction.js.map +1 -0
- package/dist/sandbox/firestore/value-equality.d.ts +2 -0
- package/dist/sandbox/firestore/value-equality.d.ts.map +1 -0
- package/dist/sandbox/firestore/value-equality.js +35 -0
- package/dist/sandbox/firestore/value-equality.js.map +1 -0
- package/dist/sandbox/firestore/value-resolver.d.ts +172 -0
- package/dist/sandbox/firestore/value-resolver.d.ts.map +1 -0
- package/dist/sandbox/firestore/value-resolver.js +221 -0
- package/dist/sandbox/firestore/value-resolver.js.map +1 -0
- package/dist/sandbox/firestore/wire-encoder.d.ts +14 -0
- package/dist/sandbox/firestore/wire-encoder.d.ts.map +1 -0
- package/dist/sandbox/firestore/wire-encoder.js +130 -0
- package/dist/sandbox/firestore/wire-encoder.js.map +1 -0
- package/dist/sandbox/index.d.ts +50 -0
- package/dist/sandbox/index.d.ts.map +1 -0
- package/dist/sandbox/index.js +63 -0
- package/dist/sandbox/index.js.map +1 -0
- package/dist/sandbox/internal/index.d.ts +36 -0
- package/dist/sandbox/internal/index.d.ts.map +1 -0
- package/dist/sandbox/internal/index.js +72 -0
- package/dist/sandbox/internal/index.js.map +1 -0
- package/dist/sandbox/internal/sandbox-impl.d.ts +343 -0
- package/dist/sandbox/internal/sandbox-impl.d.ts.map +1 -0
- package/dist/sandbox/internal/sandbox-impl.js +718 -0
- package/dist/sandbox/internal/sandbox-impl.js.map +1 -0
- package/dist/sandbox/persistence/backends.d.ts +37 -0
- package/dist/sandbox/persistence/backends.d.ts.map +1 -0
- package/dist/sandbox/persistence/backends.js +202 -0
- package/dist/sandbox/persistence/backends.js.map +1 -0
- package/dist/sandbox/persistence/chunk-format.d.ts +58 -0
- package/dist/sandbox/persistence/chunk-format.d.ts.map +1 -0
- package/dist/sandbox/persistence/chunk-format.js +163 -0
- package/dist/sandbox/persistence/chunk-format.js.map +1 -0
- package/dist/sandbox/persistence/controller.d.ts +39 -0
- package/dist/sandbox/persistence/controller.d.ts.map +1 -0
- package/dist/sandbox/persistence/controller.js +605 -0
- package/dist/sandbox/persistence/controller.js.map +1 -0
- package/dist/sandbox/persistence/index.d.ts +13 -0
- package/dist/sandbox/persistence/index.d.ts.map +1 -0
- package/dist/sandbox/persistence/index.js +5 -0
- package/dist/sandbox/persistence/index.js.map +1 -0
- package/dist/sandbox/persistence/serialize.d.ts +53 -0
- package/dist/sandbox/persistence/serialize.d.ts.map +1 -0
- package/dist/sandbox/persistence/serialize.js +98 -0
- package/dist/sandbox/persistence/serialize.js.map +1 -0
- package/dist/sandbox/persistence/types.d.ts +118 -0
- package/dist/sandbox/persistence/types.d.ts.map +1 -0
- package/dist/sandbox/persistence/types.js +15 -0
- package/dist/sandbox/persistence/types.js.map +1 -0
- package/dist/sandbox/remote.d.ts +118 -0
- package/dist/sandbox/remote.d.ts.map +1 -0
- package/dist/sandbox/remote.js +60 -0
- package/dist/sandbox/remote.js.map +1 -0
- package/dist/sandbox/replay/index.d.ts +106 -0
- package/dist/sandbox/replay/index.d.ts.map +1 -0
- package/dist/sandbox/replay/index.js +246 -0
- package/dist/sandbox/replay/index.js.map +1 -0
- package/dist/sandbox/sandbox-context.d.ts +40 -0
- package/dist/sandbox/sandbox-context.d.ts.map +1 -0
- package/dist/sandbox/sandbox-context.js +72 -0
- package/dist/sandbox/sandbox-context.js.map +1 -0
- package/dist/sandbox/tab-sync/index.d.ts +120 -0
- package/dist/sandbox/tab-sync/index.d.ts.map +1 -0
- package/dist/sandbox/tab-sync/index.js +272 -0
- package/dist/sandbox/tab-sync/index.js.map +1 -0
- package/dist/sandbox/types.d.ts +1235 -0
- package/dist/sandbox/types.d.ts.map +1 -0
- package/dist/sandbox/types.js +46 -0
- package/dist/sandbox/types.js.map +1 -0
- package/dist/storage/admin/api.d.ts +206 -0
- package/dist/storage/admin/api.d.ts.map +1 -0
- package/dist/storage/admin/api.js +349 -0
- package/dist/storage/admin/api.js.map +1 -0
- package/dist/storage/admin/handler.d.ts +29 -0
- package/dist/storage/admin/handler.d.ts.map +1 -0
- package/dist/storage/admin/handler.js +82 -0
- package/dist/storage/admin/handler.js.map +1 -0
- package/dist/storage/admin/spec.d.ts +64 -0
- package/dist/storage/admin/spec.d.ts.map +1 -0
- package/dist/storage/admin/spec.js +8 -0
- package/dist/storage/admin/spec.js.map +1 -0
- package/dist/storage/admin/tools.d.ts +23 -0
- package/dist/storage/admin/tools.d.ts.map +1 -0
- package/dist/storage/admin/tools.js +90 -0
- package/dist/storage/admin/tools.js.map +1 -0
- package/dist/storage/download.d.ts +27 -0
- package/dist/storage/download.d.ts.map +1 -0
- package/dist/storage/download.js +136 -0
- package/dist/storage/download.js.map +1 -0
- package/dist/storage/enforce.d.ts +26 -0
- package/dist/storage/enforce.d.ts.map +1 -0
- package/dist/storage/enforce.js +16 -0
- package/dist/storage/enforce.js.map +1 -0
- package/dist/storage/errors.d.ts +46 -0
- package/dist/storage/errors.d.ts.map +1 -0
- package/dist/storage/errors.js +62 -0
- package/dist/storage/errors.js.map +1 -0
- package/dist/storage/index.d.ts +49 -0
- package/dist/storage/index.d.ts.map +1 -0
- package/dist/storage/index.js +60 -0
- package/dist/storage/index.js.map +1 -0
- package/dist/storage/internal.d.ts +18 -0
- package/dist/storage/internal.d.ts.map +1 -0
- package/dist/storage/internal.js +18 -0
- package/dist/storage/internal.js.map +1 -0
- package/dist/storage/list.d.ts +17 -0
- package/dist/storage/list.d.ts.map +1 -0
- package/dist/storage/list.js +91 -0
- package/dist/storage/list.js.map +1 -0
- package/dist/storage/metadata.d.ts +86 -0
- package/dist/storage/metadata.d.ts.map +1 -0
- package/dist/storage/metadata.js +167 -0
- package/dist/storage/metadata.js.map +1 -0
- package/dist/storage/persistence.d.ts +134 -0
- package/dist/storage/persistence.d.ts.map +1 -0
- package/dist/storage/persistence.js +132 -0
- package/dist/storage/persistence.js.map +1 -0
- package/dist/storage/reference.d.ts +63 -0
- package/dist/storage/reference.d.ts.map +1 -0
- package/dist/storage/reference.js +156 -0
- package/dist/storage/reference.js.map +1 -0
- package/dist/storage/rules.d.ts +176 -0
- package/dist/storage/rules.d.ts.map +1 -0
- package/dist/storage/rules.js +621 -0
- package/dist/storage/rules.js.map +1 -0
- package/dist/storage/service.d.ts +139 -0
- package/dist/storage/service.d.ts.map +1 -0
- package/dist/storage/service.js +241 -0
- package/dist/storage/service.js.map +1 -0
- package/dist/storage/upload.d.ts +43 -0
- package/dist/storage/upload.d.ts.map +1 -0
- package/dist/storage/upload.js +235 -0
- package/dist/storage/upload.js.map +1 -0
- package/package.json +109 -3
|
@@ -0,0 +1,849 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Firestore Rules standard library — a module-organized reference an
|
|
3
|
+
* agent can call before writing rules.
|
|
4
|
+
*
|
|
5
|
+
* Three flavors of module live here, distinguished by `kind`:
|
|
6
|
+
*
|
|
7
|
+
* `language-namespace` — namespaces like `math`, `timestamp`,
|
|
8
|
+
* `duration`, `latlng`, `hashing`. Functions called as
|
|
9
|
+
* `<namespace>.<fn>(...)`. Built into the rules engine; always
|
|
10
|
+
* in scope.
|
|
11
|
+
* `type-methods` — methods that dispatch on a value's type:
|
|
12
|
+
* `string`, `list`, `map`, `bytes`, `path`. Called as
|
|
13
|
+
* `<value>.<method>(...)`. Built into the engine; always in
|
|
14
|
+
* scope.
|
|
15
|
+
* `globals` — root identifiers (`request`, `resource`) that carry
|
|
16
|
+
* request-time and existing-doc state. Accessed as paths
|
|
17
|
+
* (`request.auth.uid`), not callables.
|
|
18
|
+
* `user-module` — reusable libraries shipped under
|
|
19
|
+
* `packages/pyric/src/rules/modules/stdlib/` (auth,
|
|
20
|
+
* validation, lobby, …). Imported via
|
|
21
|
+
* `import { isAuthenticated } from 'auth';` after
|
|
22
|
+
* `rules_version = '2+modules';`. Functions called bare after
|
|
23
|
+
* import. Resolver also accepts the path form
|
|
24
|
+
* `from './stdlib/auth.rules'` if the source prefers.
|
|
25
|
+
*
|
|
26
|
+
* Source of truth: this file's names are kept in sync with
|
|
27
|
+
* - `BUILTIN_FUNCTIONS` (`grammar/FirestoreValidator.ts`)
|
|
28
|
+
* - `BUILTIN_NAMESPACES` (`simulator/evaluator.ts`)
|
|
29
|
+
* - `KNOWN_BUILTIN_METHODS` (`linter/hallucinations.ts`)
|
|
30
|
+
* - wrapper-class implementations (`simulator/wrappers/*.ts`)
|
|
31
|
+
* - `modules/stdlib/STDLIB.md`
|
|
32
|
+
* by a drift-check vitest in `test/stdlib-modules.test.ts`. If a
|
|
33
|
+
* runtime constant grows, the test fails until this file catches up.
|
|
34
|
+
*/
|
|
35
|
+
// ─── Top-level callables ──────────────────────────────────────────────
|
|
36
|
+
const BUILTINS_MODULE = {
|
|
37
|
+
key: 'builtins',
|
|
38
|
+
kind: 'language-namespace',
|
|
39
|
+
description: 'Top-level functions always in scope inside rules — get, exists, getAfter, debug. Called bare, no namespace prefix.',
|
|
40
|
+
purpose: 'The four built-in functions Firestore Rules ships with at the top level. They are NOT inside a namespace — call `get(path)`, not `firestore.get(path)`. Used to read other documents (cross-document gates), check existence, peek at post-write state, and print debug values.',
|
|
41
|
+
whenToUse: 'Reach for `builtins` any time a rule needs information that isn\'t already on `request` or `resource`. Most common: `get(path)` to read another document\'s fields inside a predicate.',
|
|
42
|
+
entries: [
|
|
43
|
+
{
|
|
44
|
+
signature: 'get(path: path): Resource',
|
|
45
|
+
description: 'Read another document. Returns a Resource whose `.data` is the doc map. Counts against the rule\'s `get()` budget (cap 10 per evaluation).',
|
|
46
|
+
examples: [
|
|
47
|
+
`allow update: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == 'admin';`,
|
|
48
|
+
],
|
|
49
|
+
notes: 'Path must start with `/databases/$(database)/documents/`. Hardcoding a different database id silently fails.',
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
signature: 'exists(path: path): bool',
|
|
53
|
+
description: 'True if a document at `path` exists. Counts against the get() budget like `get`.',
|
|
54
|
+
examples: [
|
|
55
|
+
`allow create: if exists(/databases/$(database)/documents/teams/$(request.resource.data.teamId));`,
|
|
56
|
+
],
|
|
57
|
+
},
|
|
58
|
+
{
|
|
59
|
+
signature: 'getAfter(path: path): Resource',
|
|
60
|
+
description: 'Like `get`, but reads the doc AS IT WILL BE after the current transaction commits. Use for cross-document consistency gates that depend on the post-write state of another doc in the same batch.',
|
|
61
|
+
notes: 'Only meaningful inside transactions / batched writes. Outside a batch, equivalent to `get`.',
|
|
62
|
+
},
|
|
63
|
+
{
|
|
64
|
+
signature: 'debug(value: any): bool',
|
|
65
|
+
description: 'Print `value` to the Firestore emulator/test runner log and return true. No-op in production. Useful for narrowing why a rule denies during local development.',
|
|
66
|
+
notes: 'Always returns true — wrapping it in a predicate (`if debug(resource.data.x) && otherCondition`) shows the value without changing rule outcome.',
|
|
67
|
+
},
|
|
68
|
+
],
|
|
69
|
+
relatedKeys: ['request', 'resource', 'path'],
|
|
70
|
+
};
|
|
71
|
+
// ─── Language namespaces ──────────────────────────────────────────────
|
|
72
|
+
const MATH = {
|
|
73
|
+
key: 'math',
|
|
74
|
+
kind: 'language-namespace',
|
|
75
|
+
description: 'Numeric helpers — abs, ceil, floor, round, sqrt, pow, isInfinite, isNaN. Use when rules need to coerce or bound numbers.',
|
|
76
|
+
purpose: 'The `math` namespace exposes a small set of numeric utilities for use inside rule predicates. Functions are called as `math.<fn>(...)`. Always in scope; no import needed.',
|
|
77
|
+
whenToUse: 'Reach for `math` whenever a rule needs to round, bound, or guard against non-finite numbers in a user-supplied field.',
|
|
78
|
+
entries: [
|
|
79
|
+
{ signature: 'math.abs(n: number): number', description: 'Absolute value of `n`.' },
|
|
80
|
+
{ signature: 'math.ceil(n: number): int', description: 'Smallest integer >= `n`.' },
|
|
81
|
+
{ signature: 'math.floor(n: number): int', description: 'Largest integer <= `n`.' },
|
|
82
|
+
{ signature: 'math.round(n: number): int', description: 'Nearest integer to `n`.' },
|
|
83
|
+
{ signature: 'math.sqrt(n: number): number', description: 'Square root of `n`. Negative input returns NaN.' },
|
|
84
|
+
{ signature: 'math.pow(base: number, exp: number): number', description: '`base` raised to `exp`.' },
|
|
85
|
+
{
|
|
86
|
+
signature: 'math.isInfinite(n: number): bool',
|
|
87
|
+
description: 'True if `n` is +Infinity or -Infinity.',
|
|
88
|
+
notes: 'Pairs with `math.isNaN` for safe numeric guards before arithmetic.',
|
|
89
|
+
},
|
|
90
|
+
{ signature: 'math.isNaN(n: number): bool', description: 'True if `n` is NaN.' },
|
|
91
|
+
],
|
|
92
|
+
examples: [
|
|
93
|
+
`allow update: if math.ceil(request.resource.data.score) <= 100;`,
|
|
94
|
+
`allow create: if !math.isNaN(request.resource.data.lat) && !math.isInfinite(request.resource.data.lat);`,
|
|
95
|
+
],
|
|
96
|
+
relatedKeys: ['hashing'],
|
|
97
|
+
};
|
|
98
|
+
const TIMESTAMP_NS = {
|
|
99
|
+
key: 'timestamp',
|
|
100
|
+
kind: 'language-namespace',
|
|
101
|
+
description: 'Timestamp constructors — date(year, month, day), value(epochMillis). Use to build timestamps in rule comparisons.',
|
|
102
|
+
purpose: 'The `timestamp` namespace contains constructors that produce Timestamp values for use in comparisons. The Timestamp TYPE has its own methods (year, month, etc.) — those live under the `string`/`list`/`map`-style key `timestamp-methods` in this stdlib, accessed via dot notation on a timestamp value.',
|
|
103
|
+
whenToUse: 'Reach for the `timestamp` namespace when a rule needs to construct a specific Timestamp value to compare against `request.time` or a document field.',
|
|
104
|
+
entries: [
|
|
105
|
+
{
|
|
106
|
+
signature: 'timestamp.date(year: int, month: int, day: int): Timestamp',
|
|
107
|
+
description: 'Construct a Timestamp at UTC midnight of the given date.',
|
|
108
|
+
examples: [`allow read: if request.time > timestamp.date(2024, 1, 1);`],
|
|
109
|
+
},
|
|
110
|
+
{
|
|
111
|
+
signature: 'timestamp.value(epochMillis: int): Timestamp',
|
|
112
|
+
description: 'Construct a Timestamp from epoch milliseconds.',
|
|
113
|
+
},
|
|
114
|
+
],
|
|
115
|
+
relatedKeys: ['duration', 'request', 'lifecycle'],
|
|
116
|
+
};
|
|
117
|
+
const DURATION_NS = {
|
|
118
|
+
key: 'duration',
|
|
119
|
+
kind: 'language-namespace',
|
|
120
|
+
description: 'Duration constructors — value(magnitude, unit), time(h, m, s, ns), abs(d). Use for "within N seconds" windows.',
|
|
121
|
+
purpose: 'The `duration` namespace builds Duration values that can be added to or subtracted from Timestamps. Useful for time-window predicates in security rules.',
|
|
122
|
+
whenToUse: 'Reach for `duration` whenever a rule expresses a time window — "within 5 minutes of write", "older than 30 days", etc.',
|
|
123
|
+
entries: [
|
|
124
|
+
{
|
|
125
|
+
signature: "duration.value(magnitude: int, unit: 'w' | 'd' | 'h' | 'm' | 's' | 'ms' | 'ns'): Duration",
|
|
126
|
+
description: 'Construct a Duration of `magnitude` of the given unit.',
|
|
127
|
+
examples: [
|
|
128
|
+
`allow update: if request.time < resource.data.createdAt + duration.value(5, 'm');`,
|
|
129
|
+
],
|
|
130
|
+
},
|
|
131
|
+
{
|
|
132
|
+
signature: 'duration.time(h: int, m: int, s: int, ns: int): Duration',
|
|
133
|
+
description: 'Construct a Duration as a sum of hours, minutes, seconds, nanoseconds.',
|
|
134
|
+
},
|
|
135
|
+
{
|
|
136
|
+
signature: 'duration.abs(d: Duration): Duration',
|
|
137
|
+
description: 'Absolute value of a Duration (drops sign).',
|
|
138
|
+
},
|
|
139
|
+
],
|
|
140
|
+
relatedKeys: ['timestamp'],
|
|
141
|
+
};
|
|
142
|
+
const LATLNG_NS = {
|
|
143
|
+
key: 'latlng',
|
|
144
|
+
kind: 'language-namespace',
|
|
145
|
+
description: 'GeoPoint constructor — value(lat, lng). Builds LatLng values for proximity rules.',
|
|
146
|
+
purpose: 'The `latlng` namespace constructs LatLng values. The LatLng type itself has methods (`latitude()`, `longitude()`, `distance(other)`) accessed via dot notation on a latlng value.',
|
|
147
|
+
whenToUse: 'Reach for `latlng` when a rule gates on physical proximity — e.g. "this write must come within N meters of the document\'s anchor point".',
|
|
148
|
+
entries: [
|
|
149
|
+
{
|
|
150
|
+
signature: 'latlng.value(lat: number, lng: number): LatLng',
|
|
151
|
+
description: 'Construct a LatLng. Latitude in [-90, 90], longitude in [-180, 180].',
|
|
152
|
+
examples: [
|
|
153
|
+
`allow update: if latlng.value(request.resource.data.lat, request.resource.data.lng).distance(resource.data.anchor) < 1000;`,
|
|
154
|
+
],
|
|
155
|
+
},
|
|
156
|
+
],
|
|
157
|
+
};
|
|
158
|
+
const HASHING_NS = {
|
|
159
|
+
key: 'hashing',
|
|
160
|
+
kind: 'language-namespace',
|
|
161
|
+
description: 'Hash digests — md5, sha256, crc32, crc32c. Each takes Bytes or String and returns Bytes.',
|
|
162
|
+
purpose: 'The `hashing` namespace exposes one-shot digest functions. Output is Bytes; compare equality with `==` against a stored Bytes value.',
|
|
163
|
+
whenToUse: 'Reach for `hashing` for tamper-evidence checks — comparing a submitted hash against a stored digest, or verifying a public-facing checksum.',
|
|
164
|
+
entries: [
|
|
165
|
+
{
|
|
166
|
+
signature: 'hashing.md5(input: Bytes | String): Bytes',
|
|
167
|
+
description: 'MD5 digest. 128-bit; do not use for security-sensitive integrity proofs.',
|
|
168
|
+
},
|
|
169
|
+
{
|
|
170
|
+
signature: 'hashing.sha256(input: Bytes | String): Bytes',
|
|
171
|
+
description: 'SHA-256 digest. 256-bit; the right choice for integrity proofs.',
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
signature: 'hashing.crc32(input: Bytes | String): Bytes',
|
|
175
|
+
description: 'CRC32 checksum (Bytes). Use for non-cryptographic integrity.',
|
|
176
|
+
},
|
|
177
|
+
{
|
|
178
|
+
signature: 'hashing.crc32c(input: Bytes | String): Bytes',
|
|
179
|
+
description: 'CRC32C checksum (Bytes). Same role as crc32 with a different polynomial.',
|
|
180
|
+
},
|
|
181
|
+
],
|
|
182
|
+
examples: [
|
|
183
|
+
`allow update: if hashing.sha256(request.resource.data.payload) == resource.data.checksum;`,
|
|
184
|
+
],
|
|
185
|
+
relatedKeys: ['bytes'],
|
|
186
|
+
};
|
|
187
|
+
// ─── Type methods ─────────────────────────────────────────────────────
|
|
188
|
+
const STRING_METHODS = {
|
|
189
|
+
key: 'string',
|
|
190
|
+
kind: 'type-methods',
|
|
191
|
+
description: 'Methods on string values — matches, lower, upper, trim, size, split, replace, toUtf8. Called as `value.method(...)`.',
|
|
192
|
+
purpose: 'Methods available on values of type `string` inside rule expressions. Dispatched on the value: `myField.matches(...)`, not `string.matches(myField, ...)`. The engine routes the call based on the value\'s runtime type.',
|
|
193
|
+
whenToUse: 'Reach for these whenever a rule examines a string field — pattern checks, case-insensitive comparisons, trimming user input, encoding to bytes.',
|
|
194
|
+
entries: [
|
|
195
|
+
{
|
|
196
|
+
signature: 'string.matches(pattern: string): bool',
|
|
197
|
+
description: 'True if the string matches the given RE2 regex (full match).',
|
|
198
|
+
examples: [`allow create: if request.resource.data.email.matches('.*@example[.]com');`],
|
|
199
|
+
notes: 'Pattern is RE2 syntax, NOT JavaScript regex. No anchors needed — the match is full-string by default.',
|
|
200
|
+
},
|
|
201
|
+
{ signature: 'string.lower(): string', description: 'Return the string lowercased.' },
|
|
202
|
+
{ signature: 'string.upper(): string', description: 'Return the string uppercased.' },
|
|
203
|
+
{ signature: 'string.trim(): string', description: 'Strip leading + trailing whitespace.' },
|
|
204
|
+
{ signature: 'string.size(): int', description: 'Length in characters (NOT bytes — use `toUtf8().size()` for byte length).' },
|
|
205
|
+
{
|
|
206
|
+
signature: 'string.split(separator: string): list<string>',
|
|
207
|
+
description: 'Split the string into a list on `separator`.',
|
|
208
|
+
},
|
|
209
|
+
{
|
|
210
|
+
signature: 'string.replace(old: string, new: string): string',
|
|
211
|
+
description: 'Replace all occurrences of `old` with `new`.',
|
|
212
|
+
},
|
|
213
|
+
{
|
|
214
|
+
signature: 'string.toUtf8(): bytes',
|
|
215
|
+
description: 'Encode the string as UTF-8 bytes.',
|
|
216
|
+
notes: 'Use before hashing if the input is a string.',
|
|
217
|
+
},
|
|
218
|
+
],
|
|
219
|
+
examples: [
|
|
220
|
+
`allow create: if request.resource.data.slug.size() > 0 && request.resource.data.slug.size() <= 64;`,
|
|
221
|
+
`allow update: if request.resource.data.kind.lower() == 'public';`,
|
|
222
|
+
],
|
|
223
|
+
relatedKeys: ['bytes', 'hashing', 'validation'],
|
|
224
|
+
};
|
|
225
|
+
const LIST_METHODS = {
|
|
226
|
+
key: 'list',
|
|
227
|
+
kind: 'type-methods',
|
|
228
|
+
description: 'Methods on list values — hasAll, hasAny, hasOnly, size, toSet, concat, removeAll, join. Called as `value.method(...)`.',
|
|
229
|
+
purpose: 'Methods on list values — used to check membership, compare contents, transform to sets, and concatenate. Lists in rules are ordered + finite; methods often have parallel semantics on the `set` view produced by `toSet()`.',
|
|
230
|
+
whenToUse: 'Reach for these whenever a rule examines an array field — tag membership ("user can update if their uid is in editors"), array-shape validation, or projecting to a set for difference checks.',
|
|
231
|
+
entries: [
|
|
232
|
+
{
|
|
233
|
+
signature: 'list.hasAll(other: list): bool',
|
|
234
|
+
description: 'True if every element of `other` is present in this list.',
|
|
235
|
+
examples: [`allow update: if request.resource.data.tags.hasAll(['public', 'reviewed']);`],
|
|
236
|
+
},
|
|
237
|
+
{
|
|
238
|
+
signature: 'list.hasAny(other: list): bool',
|
|
239
|
+
description: 'True if at least one element of `other` is present in this list.',
|
|
240
|
+
},
|
|
241
|
+
{
|
|
242
|
+
signature: 'list.hasOnly(other: list): bool',
|
|
243
|
+
description: 'True if every element of THIS list is in `other` (i.e. this is a subset).',
|
|
244
|
+
notes: 'Often the right call for "no fields outside this allowlist" patterns when used with `request.resource.data.keys()`.',
|
|
245
|
+
},
|
|
246
|
+
{ signature: 'list.size(): int', description: 'Number of elements.' },
|
|
247
|
+
{
|
|
248
|
+
signature: 'list.toSet(): set',
|
|
249
|
+
description: 'Convert to a Set view (de-duplicated, unordered). Useful for `difference`/`union`/`intersection` operations.',
|
|
250
|
+
},
|
|
251
|
+
{
|
|
252
|
+
signature: 'list.concat(other: list): list',
|
|
253
|
+
description: 'Return a new list with `other` appended.',
|
|
254
|
+
},
|
|
255
|
+
{
|
|
256
|
+
signature: 'list.removeAll(other: list): list',
|
|
257
|
+
description: 'Return a new list with every element of `other` removed.',
|
|
258
|
+
},
|
|
259
|
+
{
|
|
260
|
+
signature: 'list.join(separator: string): string',
|
|
261
|
+
description: 'Join elements into a single string with `separator` between them.',
|
|
262
|
+
},
|
|
263
|
+
],
|
|
264
|
+
relatedKeys: ['map', 'string'],
|
|
265
|
+
};
|
|
266
|
+
const MAP_METHODS = {
|
|
267
|
+
key: 'map',
|
|
268
|
+
kind: 'type-methods',
|
|
269
|
+
description: 'Methods on map values — keys, values, size, get, diff. Called as `value.method(...)`.',
|
|
270
|
+
purpose: 'Methods on map values. The most common in rule code: `keys()` returns a list of map keys (combined with `list.hasAll`/`list.hasOnly` for shape checks), and `diff(other)` returns a MapDiff used to assert which fields changed across an update.',
|
|
271
|
+
whenToUse: 'Reach for these for shape validation (which keys exist), for default-aware reads (`get(key, default)`), and for diff-based immutability gates on updates.',
|
|
272
|
+
entries: [
|
|
273
|
+
{
|
|
274
|
+
signature: 'map.keys(): list<string>',
|
|
275
|
+
description: 'List of top-level keys in the map.',
|
|
276
|
+
examples: [
|
|
277
|
+
`allow create: if request.resource.data.keys().hasOnly(['title','body','authorId']);`,
|
|
278
|
+
],
|
|
279
|
+
},
|
|
280
|
+
{
|
|
281
|
+
signature: 'map.values(): list',
|
|
282
|
+
description: 'List of top-level values in the map.',
|
|
283
|
+
},
|
|
284
|
+
{
|
|
285
|
+
signature: 'map.size(): int',
|
|
286
|
+
description: 'Number of top-level keys.',
|
|
287
|
+
},
|
|
288
|
+
{
|
|
289
|
+
signature: 'map.get(key: string, fallback: any): any',
|
|
290
|
+
description: 'Return `map[key]` if present, otherwise `fallback`. Same shape as `get(map, key, fallback)`.',
|
|
291
|
+
},
|
|
292
|
+
{
|
|
293
|
+
signature: 'map.diff(other: map): MapDiff',
|
|
294
|
+
description: 'Return a MapDiff with `.addedKeys()`, `.removedKeys()`, `.changedKeys()`, `.affectedKeys()`, `.unchangedKeys()` methods, each returning a Set of keys.',
|
|
295
|
+
examples: [
|
|
296
|
+
`allow update: if request.resource.data.diff(resource.data).affectedKeys().hasOnly(['updatedAt']);`,
|
|
297
|
+
],
|
|
298
|
+
notes: 'The MapDiff result is the right surface for immutability gates — easier to read than chaining individual field-unchanged checks.',
|
|
299
|
+
},
|
|
300
|
+
],
|
|
301
|
+
relatedKeys: ['list', 'lifecycle', 'validation'],
|
|
302
|
+
};
|
|
303
|
+
const BYTES_METHODS = {
|
|
304
|
+
key: 'bytes',
|
|
305
|
+
kind: 'type-methods',
|
|
306
|
+
description: 'Methods on bytes values — size, toBase64, toHexString. Called as `value.method(...)`.',
|
|
307
|
+
purpose: 'Methods on Bytes values — the output of hashing operations and the storage shape for arbitrary binary payloads. Bytes also support comparison operators (<, <=, >, >=) for lexicographic ordering.',
|
|
308
|
+
whenToUse: 'Reach for these when a rule examines a Bytes field — typically a stored digest from `hashing.sha256(...)` — or when comparing two hashes for tamper-evidence.',
|
|
309
|
+
entries: [
|
|
310
|
+
{
|
|
311
|
+
signature: 'bytes.size(): int',
|
|
312
|
+
description: 'Number of bytes.',
|
|
313
|
+
},
|
|
314
|
+
{
|
|
315
|
+
signature: 'bytes.toBase64(): string',
|
|
316
|
+
description: 'Standard base64 encoding of the bytes.',
|
|
317
|
+
},
|
|
318
|
+
{
|
|
319
|
+
signature: 'bytes.toHexString(): string',
|
|
320
|
+
description: 'Lowercase hexadecimal encoding of the bytes.',
|
|
321
|
+
},
|
|
322
|
+
],
|
|
323
|
+
relatedKeys: ['hashing', 'string'],
|
|
324
|
+
};
|
|
325
|
+
const PATH_METHODS = {
|
|
326
|
+
key: 'path',
|
|
327
|
+
kind: 'type-methods',
|
|
328
|
+
description: 'Methods on path values — bind. Used to fill in template variables in document paths.',
|
|
329
|
+
purpose: 'Path values are the type used for cross-document references inside rules (e.g. the path passed to `get()` or `exists()`). The `bind` method substitutes template variables into a path literal.',
|
|
330
|
+
whenToUse: 'Reach for `path.bind` when a `get()` or `exists()` call needs a dynamic path with one or more template variables filled in from rule context.',
|
|
331
|
+
entries: [
|
|
332
|
+
{
|
|
333
|
+
signature: 'path.bind(bindings: map<string, string>): path',
|
|
334
|
+
description: 'Return a new path with template variables (`{name}`) replaced by values from `bindings`.',
|
|
335
|
+
examples: [
|
|
336
|
+
`allow update: if exists(/databases/$(database)/documents/users/$(request.auth.uid)/profile/main);`,
|
|
337
|
+
],
|
|
338
|
+
notes: 'In practice most rule code constructs paths inline with `$()` interpolation instead of `path.bind`. `bind` is here for completeness.',
|
|
339
|
+
},
|
|
340
|
+
],
|
|
341
|
+
relatedKeys: ['request', 'resource'],
|
|
342
|
+
};
|
|
343
|
+
// ─── Globals ──────────────────────────────────────────────────────────
|
|
344
|
+
const REQUEST_GLOBALS = {
|
|
345
|
+
key: 'request',
|
|
346
|
+
kind: 'globals',
|
|
347
|
+
description: 'Root namespace for the in-flight request — auth, resource.data, time, path, method, query. Always available, no import.',
|
|
348
|
+
purpose: 'The `request` identifier carries everything the engine knows about the current request — who is making it (`auth`), what they are sending (`resource.data`), when (`time`), and where (`path`, `method`). These are *paths*, not callables — read fields off them in rule predicates.',
|
|
349
|
+
whenToUse: 'Every non-trivial rule reads from `request` to authorize the operation. The two most common touchpoints: `request.auth` (who) and `request.resource.data` (what).',
|
|
350
|
+
entries: [
|
|
351
|
+
{
|
|
352
|
+
signature: 'request.auth: map | null',
|
|
353
|
+
description: 'The authenticated user. `null` for unauthenticated requests.',
|
|
354
|
+
examples: [`allow read: if request.auth != null;`],
|
|
355
|
+
},
|
|
356
|
+
{
|
|
357
|
+
signature: 'request.auth.uid: string',
|
|
358
|
+
description: 'The signed-in user\'s UID. Only safe to read after a null-check on `request.auth`.',
|
|
359
|
+
examples: [`allow update: if request.auth.uid == resource.data.ownerId;`],
|
|
360
|
+
},
|
|
361
|
+
{
|
|
362
|
+
signature: 'request.auth.token: map',
|
|
363
|
+
description: 'Map of custom claims set on the user\'s ID token (e.g. `request.auth.token.admin`).',
|
|
364
|
+
examples: [`allow delete: if request.auth.token.admin == true;`],
|
|
365
|
+
notes: 'Custom claims live under `request.auth.token.*`, NOT `request.auth.*`. Agents often emit `request.auth.admin` — that always reads `null`.',
|
|
366
|
+
},
|
|
367
|
+
{
|
|
368
|
+
signature: 'request.resource.data: map',
|
|
369
|
+
description: 'The document data being written (create/update/set). Read it to validate what the client is sending.',
|
|
370
|
+
examples: [
|
|
371
|
+
`allow create: if request.resource.data.keys().hasOnly(['title','body','authorId']);`,
|
|
372
|
+
],
|
|
373
|
+
},
|
|
374
|
+
{
|
|
375
|
+
signature: 'request.resource.id: string',
|
|
376
|
+
description: 'Document id being written. Same as the last `{wildcard}` segment of the match path.',
|
|
377
|
+
},
|
|
378
|
+
{
|
|
379
|
+
signature: 'request.time: timestamp',
|
|
380
|
+
description: 'Server time of the request. Compare against document timestamps for windowed gates.',
|
|
381
|
+
},
|
|
382
|
+
{
|
|
383
|
+
signature: 'request.path: path',
|
|
384
|
+
description: 'Path of the document being operated on (e.g. `/databases/(default)/documents/users/alice`).',
|
|
385
|
+
},
|
|
386
|
+
{
|
|
387
|
+
signature: "request.method: 'get' | 'list' | 'create' | 'update' | 'delete'",
|
|
388
|
+
description: 'Which operation triggered the rule. Usually inferred from the `allow` clause, but available for fine-grained checks.',
|
|
389
|
+
},
|
|
390
|
+
{
|
|
391
|
+
signature: 'request.query: map',
|
|
392
|
+
description: 'Query metadata for `list` requests — `limit`, `offset`, `orderBy`. Available on `allow list` rules only.',
|
|
393
|
+
},
|
|
394
|
+
],
|
|
395
|
+
relatedKeys: ['resource', 'auth'],
|
|
396
|
+
};
|
|
397
|
+
const RESOURCE_GLOBALS = {
|
|
398
|
+
key: 'resource',
|
|
399
|
+
kind: 'globals',
|
|
400
|
+
description: 'Root namespace for the existing document — resource.data, resource.id, resource.__name__. Use to compare against what is already there.',
|
|
401
|
+
purpose: 'The `resource` identifier is the document state BEFORE the request — what is currently stored. On a create, `resource` is null. On an update/delete, it contains the pre-write doc. Use it to compare incoming changes against existing values.',
|
|
402
|
+
whenToUse: 'Whenever a rule needs the pre-write state — e.g. "the existing owner is the one updating", "the field already had this value before the write".',
|
|
403
|
+
entries: [
|
|
404
|
+
{
|
|
405
|
+
signature: 'resource.data: map',
|
|
406
|
+
description: 'The currently stored document data. On a create, the whole `resource` is `null`.',
|
|
407
|
+
examples: [`allow update: if resource.data.ownerId == request.auth.uid;`],
|
|
408
|
+
},
|
|
409
|
+
{
|
|
410
|
+
signature: 'resource.id: string',
|
|
411
|
+
description: 'Existing document\'s id. Same as `request.resource.id` for non-create ops.',
|
|
412
|
+
},
|
|
413
|
+
{
|
|
414
|
+
signature: 'resource.__name__: path',
|
|
415
|
+
description: 'Fully-qualified path of the existing document.',
|
|
416
|
+
},
|
|
417
|
+
],
|
|
418
|
+
relatedKeys: ['request'],
|
|
419
|
+
};
|
|
420
|
+
// ─── User-authored modules (mirror of STDLIB.md) ──────────────────────
|
|
421
|
+
const AUTH_MODULE = {
|
|
422
|
+
key: 'auth',
|
|
423
|
+
kind: 'user-module',
|
|
424
|
+
description: "User-authored module: authentication primitives (isAuthenticated, isOwner). Self-contained. Import via `import { isAuthenticated, isOwner } from 'auth';` (the resolver also accepts the path form `from './stdlib/auth.rules'` if you prefer).",
|
|
425
|
+
purpose: 'Two-function module covering the most common access-control predicates in any user-facing app: "is the request authenticated" and "is the request the owner of this document".',
|
|
426
|
+
whenToUse: 'Import as the first stdlib module on any project that has user-owned documents. Pairs with `validation` and `lifecycle` for full create/update/delete coverage.',
|
|
427
|
+
entries: [
|
|
428
|
+
{
|
|
429
|
+
signature: 'isAuthenticated(): bool',
|
|
430
|
+
description: '`request.auth != null`.',
|
|
431
|
+
},
|
|
432
|
+
{
|
|
433
|
+
signature: 'isOwner(userId: string): bool',
|
|
434
|
+
description: '`request.auth.uid == userId`. Pass a field path like `resource.data.ownerId`.',
|
|
435
|
+
examples: [`allow update: if isAuthenticated() && isOwner(resource.data.ownerId);`],
|
|
436
|
+
},
|
|
437
|
+
],
|
|
438
|
+
examples: [
|
|
439
|
+
`rules_version = '2+modules';\nimport { isAuthenticated } from 'auth';\n\nservice cloud.firestore {\n match /databases/{db}/documents {\n match /posts/{id} { allow read: if isAuthenticated(); }\n }\n}`,
|
|
440
|
+
],
|
|
441
|
+
relatedKeys: ['validation', 'lifecycle', 'membership'],
|
|
442
|
+
};
|
|
443
|
+
const VALIDATION_MODULE = {
|
|
444
|
+
key: 'validation',
|
|
445
|
+
kind: 'user-module',
|
|
446
|
+
description: "User-authored module: shape validation (hasRequired, hasOnly). Self-contained. Import via `import { hasRequired, hasOnly } from 'validation';` after `rules_version = '2+modules';`.",
|
|
447
|
+
purpose: 'Field-shape predicates: "the incoming doc has all these fields" and "the incoming doc has only these fields". Layered on top of `request.resource.data.keys()` so the agent does not have to remember the list-method idioms.',
|
|
448
|
+
whenToUse: 'Reach for `validation` on every `create` allow rule to gate field shape — and on `update` rules when the schema is strict.',
|
|
449
|
+
entries: [
|
|
450
|
+
{
|
|
451
|
+
signature: 'hasRequired(fields: list<string>): bool',
|
|
452
|
+
description: '`request.resource.data.keys().hasAll(fields)`.',
|
|
453
|
+
},
|
|
454
|
+
{
|
|
455
|
+
signature: 'hasOnly(fields: list<string>): bool',
|
|
456
|
+
description: '`request.resource.data.keys().hasOnly(fields)`.',
|
|
457
|
+
examples: [
|
|
458
|
+
// Imports resolve to FLAT names — call `hasRequired(...)`, never `validation.hasRequired(...)`.
|
|
459
|
+
`allow create: if hasRequired(['title','body']) && hasOnly(['title','body','tags']);`,
|
|
460
|
+
],
|
|
461
|
+
},
|
|
462
|
+
{
|
|
463
|
+
signature: 'validString(field: string, min: int, max: int): bool',
|
|
464
|
+
description: 'The incoming field is a string with size in [min, max] (inclusive). Uses dynamic access, so a MISSING field reads null and fails the type check instead of erroring — safe on optional fields.',
|
|
465
|
+
examples: [`allow create: if validString('title', 1, 100);`],
|
|
466
|
+
},
|
|
467
|
+
{
|
|
468
|
+
signature: 'isOneOf(field: string, values: list): bool',
|
|
469
|
+
description: "Enum check: the incoming field value is in the allowed list (`request.resource.data[field] in values`). The rules idiom for what JS would write as `.includes()` — which does not exist here.",
|
|
470
|
+
examples: [`allow create: if isOneOf('status', ['draft', 'published']);`],
|
|
471
|
+
},
|
|
472
|
+
],
|
|
473
|
+
relatedKeys: ['map', 'lifecycle', 'content'],
|
|
474
|
+
};
|
|
475
|
+
const LOBBY_MODULE = {
|
|
476
|
+
key: 'lobby',
|
|
477
|
+
kind: 'user-module',
|
|
478
|
+
description: 'User-authored module: lobby lifecycle (validCreate, validJoin, canCancel) for two-player game sessions. Self-contained.',
|
|
479
|
+
purpose: 'Convention-based lifecycle for game lobbies — assumes the document has `host`, `guest`, and `status` fields. Encapsulates the rules for opening a lobby, joining as the second player, and cancelling.',
|
|
480
|
+
whenToUse: 'Reach for `lobby` on games with a join-then-start flow. The convention names are load-bearing — if your schema differs, fork these functions rather than try to remap.',
|
|
481
|
+
entries: [
|
|
482
|
+
{
|
|
483
|
+
signature: 'validCreate(): bool',
|
|
484
|
+
description: 'Host is the auth user, guest is empty, status is "waiting".',
|
|
485
|
+
},
|
|
486
|
+
{
|
|
487
|
+
signature: 'validJoin(): bool',
|
|
488
|
+
description: 'Guest slot is empty, joiner is not the host, status transitions to "playing".',
|
|
489
|
+
},
|
|
490
|
+
{
|
|
491
|
+
signature: 'canCancel(): bool',
|
|
492
|
+
description: 'Status is "waiting" and the requester is the host.',
|
|
493
|
+
},
|
|
494
|
+
],
|
|
495
|
+
relatedKeys: ['turns', 'state', 'transitions'],
|
|
496
|
+
};
|
|
497
|
+
const TURNS_MODULE = {
|
|
498
|
+
key: 'turns',
|
|
499
|
+
kind: 'user-module',
|
|
500
|
+
description: 'User-authored module: turn enforcement for two-player games (isMyTurn, turnFlipped). Self-contained.',
|
|
501
|
+
purpose: 'Convention-based turn handling on docs with `host`, `guest`, and `currentTurn` fields. Asserts the request is from the current player and that turn alternates correctly across writes.',
|
|
502
|
+
whenToUse: 'Reach for `turns` on any turn-based game where exactly one player can act per state.',
|
|
503
|
+
entries: [
|
|
504
|
+
{
|
|
505
|
+
signature: 'isMyTurn(): bool',
|
|
506
|
+
description: 'Current player matches the auth uid (matches against `host` or `guest`).',
|
|
507
|
+
},
|
|
508
|
+
{
|
|
509
|
+
signature: 'turnFlipped(): bool',
|
|
510
|
+
description: 'After the write, `currentTurn` has switched from host to guest (or vice-versa).',
|
|
511
|
+
},
|
|
512
|
+
],
|
|
513
|
+
relatedKeys: ['lobby', 'state', 'transitions'],
|
|
514
|
+
};
|
|
515
|
+
const STATE_MODULE = {
|
|
516
|
+
key: 'state',
|
|
517
|
+
kind: 'user-module',
|
|
518
|
+
description: 'User-authored module: game state tracking (isPlaying, moveIncremented, participantsUnchanged). Self-contained.',
|
|
519
|
+
purpose: 'Mid-game state predicates: the game is in play, the move counter incremented by exactly one, the participant list did not change.',
|
|
520
|
+
whenToUse: 'Reach for `state` on per-move updates to assert the move actually advanced the game and did not change the players.',
|
|
521
|
+
entries: [
|
|
522
|
+
{ signature: 'isPlaying(): bool', description: '`resource.data.status == "playing"`.' },
|
|
523
|
+
{
|
|
524
|
+
signature: 'moveIncremented(): bool',
|
|
525
|
+
description: '`request.resource.data.moveCount == resource.data.moveCount + 1`.',
|
|
526
|
+
},
|
|
527
|
+
{
|
|
528
|
+
signature: 'participantsUnchanged(): bool',
|
|
529
|
+
description: 'Host and guest fields are identical pre- and post-write.',
|
|
530
|
+
},
|
|
531
|
+
],
|
|
532
|
+
relatedKeys: ['turns', 'lifecycle', 'transitions'],
|
|
533
|
+
};
|
|
534
|
+
const MEMBERSHIP_MODULE = {
|
|
535
|
+
key: 'membership',
|
|
536
|
+
kind: 'user-module',
|
|
537
|
+
description: 'User-authored module: claims + role-based access (hasClaim, hasClaimRole, isMemberOf, hasRole). Self-contained.',
|
|
538
|
+
purpose: 'Two halves: claim-based checks against the auth token, and role checks against a `members` map on a document. The module is the right cover for "team-style" apps where each doc has a participant map.',
|
|
539
|
+
whenToUse: 'Reach for `membership` whenever a rule gates on a custom claim (`request.auth.token.admin`) or on a role inside a participant map.',
|
|
540
|
+
entries: [
|
|
541
|
+
{
|
|
542
|
+
signature: 'hasClaim(claim: string): bool',
|
|
543
|
+
description: 'Auth token has a non-null value for the named claim.',
|
|
544
|
+
},
|
|
545
|
+
{
|
|
546
|
+
signature: 'hasClaimRole(claim: string, role: string): bool',
|
|
547
|
+
description: 'Auth token claim equals the named role value.',
|
|
548
|
+
},
|
|
549
|
+
{
|
|
550
|
+
signature: 'isMemberOf(membersMap: map): bool',
|
|
551
|
+
description: 'Auth uid is a key in the members map.',
|
|
552
|
+
},
|
|
553
|
+
{
|
|
554
|
+
signature: 'hasRole(membersMap: map, role: string): bool',
|
|
555
|
+
description: 'Auth uid is in the members map with the named role.',
|
|
556
|
+
},
|
|
557
|
+
],
|
|
558
|
+
relatedKeys: ['auth', 'request'],
|
|
559
|
+
};
|
|
560
|
+
const LIFECYCLE_MODULE = {
|
|
561
|
+
key: 'lifecycle',
|
|
562
|
+
kind: 'user-module',
|
|
563
|
+
description: 'User-authored module: field immutability + server-timestamp checks (fieldUnchanged, immutableFields, isServerTimestamp). Self-contained.',
|
|
564
|
+
purpose: 'Locks specific fields against modification on updates and asserts that a timestamp field matches `request.time` (i.e. the client used the server-timestamp sentinel).',
|
|
565
|
+
whenToUse: 'Reach for `lifecycle` on every update rule to lock identity fields (`createdAt`, `ownerId`) and to enforce server-set timestamps.',
|
|
566
|
+
entries: [
|
|
567
|
+
{
|
|
568
|
+
signature: 'fieldUnchanged(field: string): bool',
|
|
569
|
+
description: 'The named field is byte-identical before and after the write.',
|
|
570
|
+
},
|
|
571
|
+
{
|
|
572
|
+
signature: 'immutableFields(fields: list<string>): bool',
|
|
573
|
+
description: 'All listed fields are unchanged. Implemented via MapDiff so it is cheaper than chaining `fieldUnchanged` calls.',
|
|
574
|
+
},
|
|
575
|
+
{
|
|
576
|
+
signature: 'isServerTimestamp(field: string): bool',
|
|
577
|
+
description: 'The named field equals `request.time` (i.e. the client wrote `FieldValue.serverTimestamp()`).',
|
|
578
|
+
},
|
|
579
|
+
{
|
|
580
|
+
signature: 'onlyFieldsChanged(fields: list<string>): bool',
|
|
581
|
+
description: 'The dual of immutableFields: every CHANGED field is in the allowed list, so unlisted fields are implicitly immutable (adds and removes count as changes). The single most common update guard — "users may edit title/body and nothing else". Top-level keys only; nested-map diffs are unreliable in production.',
|
|
582
|
+
examples: [`allow update: if onlyFieldsChanged(['title', 'body']);`],
|
|
583
|
+
},
|
|
584
|
+
{
|
|
585
|
+
signature: 'nFieldsChanged(n: int): bool',
|
|
586
|
+
description: 'Exactly n top-level fields changed in this write. `nFieldsChanged(1)` is the board-integrity / edit-one-field-per-write guard.',
|
|
587
|
+
},
|
|
588
|
+
],
|
|
589
|
+
relatedKeys: ['map', 'validation', 'request', 'counters'],
|
|
590
|
+
};
|
|
591
|
+
const TRANSITIONS_MODULE = {
|
|
592
|
+
key: 'transitions',
|
|
593
|
+
kind: 'user-module',
|
|
594
|
+
description: 'User-authored module: state-machine transitions (validTransition, statusIs, newStatusIs). Self-contained.',
|
|
595
|
+
purpose: 'Asserts that a field moves from one specific value to another specific value on a write. Use to encode state-machine edges directly in rules.',
|
|
596
|
+
whenToUse: 'Reach for `transitions` whenever a rule encodes a state machine — order: pending → paid → shipped, etc.',
|
|
597
|
+
entries: [
|
|
598
|
+
{
|
|
599
|
+
signature: 'validTransition(field: string, from: string, to: string): bool',
|
|
600
|
+
description: 'Field was `from` before and is `to` after.',
|
|
601
|
+
},
|
|
602
|
+
{
|
|
603
|
+
signature: 'statusIs(field: string, value: string): bool',
|
|
604
|
+
description: 'Pre-write field equals `value`.',
|
|
605
|
+
},
|
|
606
|
+
{
|
|
607
|
+
signature: 'newStatusIs(field: string, value: string): bool',
|
|
608
|
+
description: 'Post-write field equals `value`.',
|
|
609
|
+
},
|
|
610
|
+
],
|
|
611
|
+
relatedKeys: ['state', 'lifecycle'],
|
|
612
|
+
};
|
|
613
|
+
const GEOMETRY_MODULE = {
|
|
614
|
+
key: 'geometry',
|
|
615
|
+
kind: 'user-module',
|
|
616
|
+
description: 'User-authored module: movement validation via config-doc lookup (validSimpleMove, validJumpMove). Caller must pass the config from a `get()` call.',
|
|
617
|
+
purpose: 'Board-game movement rules expressed as lookups in a config document — `cfg.moves[piece][from][to]` for simple moves, `cfg.jumps[piece][from][to]` for jumps (with captured-cell info). The module is "explicit parameter" style: no implicit reads — the caller passes the config explicitly.',
|
|
618
|
+
whenToUse: 'Reach for `geometry` on grid-based games (chess, checkers, go variants). Pair the function call with a `get()` on your config document.',
|
|
619
|
+
entries: [
|
|
620
|
+
{
|
|
621
|
+
signature: 'validSimpleMove(cfg: map): bool',
|
|
622
|
+
description: '`cfg.moves[piece][from][to] == true`.',
|
|
623
|
+
},
|
|
624
|
+
{
|
|
625
|
+
signature: 'validJumpMove(cfg: map): bool',
|
|
626
|
+
description: '`cfg.jumps[piece][from][to] == capturedCell`.',
|
|
627
|
+
},
|
|
628
|
+
],
|
|
629
|
+
relatedKeys: ['transitions', 'state'],
|
|
630
|
+
};
|
|
631
|
+
// ─── Module registry ──────────────────────────────────────────────────
|
|
632
|
+
const COUNTERS_MODULE = {
|
|
633
|
+
key: 'counters',
|
|
634
|
+
kind: 'user-module',
|
|
635
|
+
description: 'User-authored module: denormalized numeric integrity (incrementedBy, changedBy, boundedNumber). Self-contained.',
|
|
636
|
+
purpose: 'Keeps client-maintained counts honest — likes, votes, moves, quantities may only change by a known step or stay within known bounds. Generalizes the state module\'s moveIncremented() (hardcoded to moveCount) to any field.',
|
|
637
|
+
whenToUse: 'Reach for `counters` whenever a numeric field is client-written but semantically constrained: vote/like toggles (`changedBy(f, -1, 1)`), move counters (`incrementedBy(f, 1)`), ratings (`boundedNumber(f, 1, 5)`).',
|
|
638
|
+
entries: [
|
|
639
|
+
{
|
|
640
|
+
signature: 'incrementedBy(field: string, n: int): bool',
|
|
641
|
+
description: 'The field changed by EXACTLY n vs the existing document (n may be negative). Update rules only.',
|
|
642
|
+
examples: [`allow update: if incrementedBy('moveCount', 1);`],
|
|
643
|
+
},
|
|
644
|
+
{
|
|
645
|
+
signature: 'changedBy(field: string, min: int, max: int): bool',
|
|
646
|
+
description: 'The field\'s delta is within [min, max] inclusive; a zero delta passes when the range spans 0.',
|
|
647
|
+
examples: [`allow update: if changedBy('likeCount', -1, 1);`],
|
|
648
|
+
},
|
|
649
|
+
{
|
|
650
|
+
signature: 'boundedNumber(field: string, min: number, max: number): bool',
|
|
651
|
+
description: 'The incoming value is an int or float within [min, max]. Missing field reads null (dynamic access) and fails closed.',
|
|
652
|
+
examples: [`allow write: if boundedNumber('rating', 1, 5);`],
|
|
653
|
+
},
|
|
654
|
+
],
|
|
655
|
+
relatedKeys: ['lifecycle', 'state'],
|
|
656
|
+
};
|
|
657
|
+
const TIMING_MODULE = {
|
|
658
|
+
key: 'timing',
|
|
659
|
+
kind: 'user-module',
|
|
660
|
+
description: 'User-authored module: cooldown / rate-limit enforcement (cooldownElapsed). Self-contained. Live-verified against the production engine.',
|
|
661
|
+
purpose: 'Rules CAN rate-limit: compare `request.time` against a stored server timestamp with duration arithmetic. Enforces a minimum interval between writes to a document.',
|
|
662
|
+
whenToUse: "Reach for `timing` to throttle per-document writes — game move intervals, post cooldowns, retry backoff. ALWAYS pair with lifecycle's `isServerTimestamp(field)` on the same write so the stored timestamp cannot be forged by the client. Per-document intervals only; sliding-window quotas need a counter document plus this guard.",
|
|
663
|
+
entries: [
|
|
664
|
+
{
|
|
665
|
+
signature: 'cooldownElapsed(field: string, seconds: int): bool',
|
|
666
|
+
description: "`request.time > resource.data[field] + duration.value(seconds, 's')` — the stored timestamp is STRICTLY older than the window. Update rules only (needs `resource`); a missing or non-timestamp field errors, which denies (fail-closed).",
|
|
667
|
+
examples: [
|
|
668
|
+
`allow update: if cooldownElapsed('lastMoveAt', 2) && isServerTimestamp('lastMoveAt');`,
|
|
669
|
+
],
|
|
670
|
+
},
|
|
671
|
+
],
|
|
672
|
+
relatedKeys: ['lifecycle', 'timestamp', 'duration'],
|
|
673
|
+
};
|
|
674
|
+
const CONTENT_MODULE = {
|
|
675
|
+
key: 'content',
|
|
676
|
+
kind: 'user-module',
|
|
677
|
+
description: 'User-authored module: author-owned documents (validAuthorCreate, isAuthor, canReadContent, notDeleted). Self-contained. Field names are parameters, not conventions.',
|
|
678
|
+
purpose: 'The most common Firebase app shape — posts, notes, docs, comments, tasks. Covers the create/read/update/delete lifecycle of documents that belong to their author, with draft/published visibility and soft delete.',
|
|
679
|
+
whenToUse: 'Reach for `content` on any collection whose documents have an author/owner field. Compose with lifecycle.onlyFieldsChanged to keep authorship immutable on edits.',
|
|
680
|
+
entries: [
|
|
681
|
+
{
|
|
682
|
+
signature: 'validAuthorCreate(authorField: string): bool',
|
|
683
|
+
description: 'Create guard: signed in AND the incoming doc\'s author field is the caller\'s uid.',
|
|
684
|
+
examples: [`allow create: if validAuthorCreate('author');`],
|
|
685
|
+
},
|
|
686
|
+
{
|
|
687
|
+
signature: 'isAuthor(authorField: string): bool',
|
|
688
|
+
description: 'The caller is the EXISTING document\'s author. Update/delete rules.',
|
|
689
|
+
examples: [`allow update: if isAuthor('author') && onlyFieldsChanged(['title', 'body']);`],
|
|
690
|
+
},
|
|
691
|
+
{
|
|
692
|
+
signature: 'canReadContent(statusField: string, authorField: string): bool',
|
|
693
|
+
description: "Published content is public; anything else is visible to its author only. `get` rules — a bare collection `list` will be denied unless the query proves `status == 'published'` via filters (rules are not filters).",
|
|
694
|
+
examples: [`allow read: if canReadContent('status', 'author') && notDeleted();`],
|
|
695
|
+
},
|
|
696
|
+
{
|
|
697
|
+
signature: 'notDeleted(): bool',
|
|
698
|
+
description: "Soft-delete guard: `resource.data['deleted'] != true`. Bracket access is the null-on-miss idiom, so a document WITHOUT the field passes.",
|
|
699
|
+
},
|
|
700
|
+
],
|
|
701
|
+
relatedKeys: ['auth', 'lifecycle', 'validation'],
|
|
702
|
+
};
|
|
703
|
+
const SPACES_MODULE = {
|
|
704
|
+
key: 'spaces',
|
|
705
|
+
kind: 'user-module',
|
|
706
|
+
description: 'User-authored module: cross-document membership gating (isSpaceMember, hasSpaceRole, validMemberCreate). Explicit param — pass the parent doc data from a get(). Live-verified against the production engine.',
|
|
707
|
+
purpose: "Shared spaces — teams, rooms, groups, projects, parties: a PARENT document's members field gates its children. The second-most-common app shape after author-owned content.",
|
|
708
|
+
whenToUse: "Reach for `spaces` whenever a subcollection is gated by a parent doc. Define ONE helper in the child match block — `function space() { return get(/databases/$(database)/documents/spaces/$(spaceId)).data; }` — and pass it to every function: get() is cached per request, so all rules on the request share a single read of the 10-get budget. Do NOT inline a get() per allow clause.",
|
|
709
|
+
entries: [
|
|
710
|
+
{
|
|
711
|
+
signature: 'isSpaceMember(spaceData: map): bool',
|
|
712
|
+
description: "The caller's uid is in `spaceData.members`. `in` covers BOTH shapes: list membership (`members: ['a','b']`) and map keys (`members: {a: 'admin'}`). Missing field / non-member / missing parent doc all fail closed.",
|
|
713
|
+
examples: [`allow read: if isSpaceMember(space());`],
|
|
714
|
+
},
|
|
715
|
+
{
|
|
716
|
+
signature: 'hasSpaceRole(spaceData: map, role: string): bool',
|
|
717
|
+
description: "The caller's role in a MAP-shaped members field equals `role` (`spaceData.members[request.auth.uid] == role`). List-shaped members carry no roles — denies.",
|
|
718
|
+
examples: [`allow delete: if hasSpaceRole(space(), 'admin');`],
|
|
719
|
+
},
|
|
720
|
+
{
|
|
721
|
+
signature: 'validMemberCreate(spaceData: map, authorField: string): bool',
|
|
722
|
+
description: 'Member-gated authored create: caller is a member AND the incoming child doc\'s author field is the caller. The "post a message / add a task" guard.',
|
|
723
|
+
examples: [`allow create: if validMemberCreate(space(), 'author');`],
|
|
724
|
+
},
|
|
725
|
+
],
|
|
726
|
+
relatedKeys: ['membership', 'content', 'builtins'],
|
|
727
|
+
};
|
|
728
|
+
const JOINING_MODULE = {
|
|
729
|
+
key: 'joining',
|
|
730
|
+
kind: 'user-module',
|
|
731
|
+
description: 'User-authored module: safe self-service membership changes (onlyAddedSelf, onlyRemovedSelf). Self-contained. Live-verified against the production engine.',
|
|
732
|
+
purpose: 'How membership CHANGES without an admin backend: users join and leave a MAP-shaped members field (uid -> role) with zero privilege escalation — no self-granted roles, no touching other members, no-op writes denied.',
|
|
733
|
+
whenToUse: "Reach for `joining` on the PARENT doc's update rule wherever spaces gates the children. ALWAYS compose with lifecycle's onlyFieldsChanged(['members']) so a join/leave write cannot modify anything else on the doc. Invite-doc consumption (single-use invites) is a Pattern, not a function — it needs a batch write + getAfter().",
|
|
734
|
+
entries: [
|
|
735
|
+
{
|
|
736
|
+
signature: 'onlyAddedSelf(membersField: string, role: string): bool',
|
|
737
|
+
description: "The write adds EXACTLY the caller to the members map at EXACTLY `role` — changing nobody, removing nobody; a no-op write denies (uses set equality `diff.addedKeys() == [uid].toSet()`, not hasOnly, which passes on an empty diff). Update rules only.",
|
|
738
|
+
examples: [
|
|
739
|
+
`allow update: if onlyFieldsChanged(['members']) && (onlyAddedSelf('members', 'editor') || onlyRemovedSelf('members'));`,
|
|
740
|
+
],
|
|
741
|
+
},
|
|
742
|
+
{
|
|
743
|
+
signature: 'onlyRemovedSelf(membersField: string): bool',
|
|
744
|
+
description: 'The write removes EXACTLY the caller — adding nobody, changing nobody. Self-service leave. Update rules only.',
|
|
745
|
+
},
|
|
746
|
+
],
|
|
747
|
+
relatedKeys: ['spaces', 'lifecycle', 'membership'],
|
|
748
|
+
};
|
|
749
|
+
const ATOMIC_MODULE = {
|
|
750
|
+
key: 'atomic',
|
|
751
|
+
kind: 'user-module',
|
|
752
|
+
description: 'User-authored module: cross-document BATCH-write integrity via get()/getAfter() (companionChangedBy, consumedFlag). Explicit param. Live-verified against a real production database.',
|
|
753
|
+
purpose: 'Rules that require a COMPANION write in the same atomic batch: denormalized counters (create task + increment team.taskCount), single-use invite consumption (join + mark invite used), paired documents. getAfter(path) returns the post-batch state of another doc in the batch; for docs not in the batch it equals get(path).',
|
|
754
|
+
whenToUse: "Reach for `atomic` when two documents must change together. Define before()/after() helpers — `get(path).data` and `getAfter(path).data` for the SAME companion path — and pass both. Every write in a batch is rules-evaluated: the companion write needs its own allow rule. The client must use a batch/transaction (writeBatch / runTransaction); solo writes deny by construction.",
|
|
755
|
+
entries: [
|
|
756
|
+
{
|
|
757
|
+
signature: 'companionChangedBy(before: map, after: map, field: string, n: int): bool',
|
|
758
|
+
description: "The companion doc's field changed by EXACTLY n in this batch (`after[field] == before[field] + n`). A solo write denies: without a companion write, getAfter == get, so the delta is 0.",
|
|
759
|
+
examples: [
|
|
760
|
+
`allow create: if companionChangedBy(teamBefore(), teamAfter(), 'taskCount', 1);`,
|
|
761
|
+
],
|
|
762
|
+
},
|
|
763
|
+
{
|
|
764
|
+
signature: 'consumedFlag(before: map, after: map, flagField: string): bool',
|
|
765
|
+
description: 'A single-use flag was consumed IN THIS BATCH: pre-batch false AND post-batch true. Replays deny (already true before the batch); solo writes deny (false != true when getAfter == get). Pair with an allow rule on the flag doc itself (e.g. invitee-only, resource.used == false).',
|
|
766
|
+
examples: [
|
|
767
|
+
`allow update: if consumedFlag(inviteBefore(), inviteAfter(), 'used');`,
|
|
768
|
+
],
|
|
769
|
+
},
|
|
770
|
+
],
|
|
771
|
+
relatedKeys: ['counters', 'joining', 'spaces', 'builtins'],
|
|
772
|
+
};
|
|
773
|
+
export const STDLIB_MODULES = [
|
|
774
|
+
// top-level callables (get / exists / getAfter / debug)
|
|
775
|
+
BUILTINS_MODULE,
|
|
776
|
+
// language namespaces
|
|
777
|
+
MATH,
|
|
778
|
+
TIMESTAMP_NS,
|
|
779
|
+
DURATION_NS,
|
|
780
|
+
LATLNG_NS,
|
|
781
|
+
HASHING_NS,
|
|
782
|
+
// type methods
|
|
783
|
+
STRING_METHODS,
|
|
784
|
+
LIST_METHODS,
|
|
785
|
+
MAP_METHODS,
|
|
786
|
+
BYTES_METHODS,
|
|
787
|
+
PATH_METHODS,
|
|
788
|
+
// globals
|
|
789
|
+
REQUEST_GLOBALS,
|
|
790
|
+
RESOURCE_GLOBALS,
|
|
791
|
+
// user-authored modules
|
|
792
|
+
AUTH_MODULE,
|
|
793
|
+
VALIDATION_MODULE,
|
|
794
|
+
LOBBY_MODULE,
|
|
795
|
+
TURNS_MODULE,
|
|
796
|
+
STATE_MODULE,
|
|
797
|
+
MEMBERSHIP_MODULE,
|
|
798
|
+
LIFECYCLE_MODULE,
|
|
799
|
+
TRANSITIONS_MODULE,
|
|
800
|
+
GEOMETRY_MODULE,
|
|
801
|
+
COUNTERS_MODULE,
|
|
802
|
+
TIMING_MODULE,
|
|
803
|
+
CONTENT_MODULE,
|
|
804
|
+
SPACES_MODULE,
|
|
805
|
+
JOINING_MODULE,
|
|
806
|
+
ATOMIC_MODULE,
|
|
807
|
+
];
|
|
808
|
+
/** Look up a module by case-insensitive key. */
|
|
809
|
+
export function findModuleByKey(key) {
|
|
810
|
+
const k = key.toLowerCase();
|
|
811
|
+
return STDLIB_MODULES.find((m) => m.key.toLowerCase() === k);
|
|
812
|
+
}
|
|
813
|
+
/** All valid keys — used in the error response when a get-call misses. */
|
|
814
|
+
export function allModuleKeys() {
|
|
815
|
+
return STDLIB_MODULES.map((m) => m.key);
|
|
816
|
+
}
|
|
817
|
+
/** Closest-match suggestion (cheap Levenshtein) for a bad key. */
|
|
818
|
+
export function suggestKey(input) {
|
|
819
|
+
const want = input.toLowerCase();
|
|
820
|
+
let best = null;
|
|
821
|
+
for (const m of STDLIB_MODULES) {
|
|
822
|
+
const d = levenshtein(want, m.key.toLowerCase());
|
|
823
|
+
if (best === null || d < best.d)
|
|
824
|
+
best = { key: m.key, d };
|
|
825
|
+
}
|
|
826
|
+
// Only return a suggestion if it's reasonably close.
|
|
827
|
+
if (best && best.d <= Math.max(2, Math.floor(want.length / 3)))
|
|
828
|
+
return best.key;
|
|
829
|
+
return null;
|
|
830
|
+
}
|
|
831
|
+
function levenshtein(a, b) {
|
|
832
|
+
if (a.length === 0)
|
|
833
|
+
return b.length;
|
|
834
|
+
if (b.length === 0)
|
|
835
|
+
return a.length;
|
|
836
|
+
const v0 = new Array(b.length + 1).fill(0).map((_, i) => i);
|
|
837
|
+
const v1 = new Array(b.length + 1).fill(0);
|
|
838
|
+
for (let i = 0; i < a.length; i++) {
|
|
839
|
+
v1[0] = i + 1;
|
|
840
|
+
for (let j = 0; j < b.length; j++) {
|
|
841
|
+
const cost = a[i] === b[j] ? 0 : 1;
|
|
842
|
+
v1[j + 1] = Math.min(v1[j] + 1, v0[j + 1] + 1, v0[j] + cost);
|
|
843
|
+
}
|
|
844
|
+
for (let j = 0; j <= b.length; j++)
|
|
845
|
+
v0[j] = v1[j];
|
|
846
|
+
}
|
|
847
|
+
return v1[b.length];
|
|
848
|
+
}
|
|
849
|
+
//# sourceMappingURL=stdlib-modules.js.map
|