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,1226 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `@pyric/rtdb` modular SDK surface — Phase 3 implementation.
|
|
3
|
+
*
|
|
4
|
+
* Mirrors `firebase/database`'s tree-shakable free-function shape:
|
|
5
|
+
* `getDatabase`, `ref`, `child`, `get`, `set`, `update`, `remove`,
|
|
6
|
+
* `push`, `onValue`, `serverTimestamp`, `connectDatabaseEmulator`.
|
|
7
|
+
*
|
|
8
|
+
* Three backends picked by what's passed to `getDatabase`:
|
|
9
|
+
*
|
|
10
|
+
* - **Sandbox target** — wraps `RtdbBackend` (in-memory JSON tree
|
|
11
|
+
* plus the existing `@pyric/rtdb` rule simulator). Identity is the
|
|
12
|
+
* `SandboxContext`'s frozen `auth`.
|
|
13
|
+
* - **Sandbox-live target** — same backend, but identity is read
|
|
14
|
+
* per-op from `sandbox.currentUser` so a `pyric/auth`-driven
|
|
15
|
+
* sign-in flips the next op's `request.auth` without re-binding.
|
|
16
|
+
* - **Prod target** — wraps `firebase/database` against a real
|
|
17
|
+
* Firebase project.
|
|
18
|
+
*
|
|
19
|
+
* Dispatch machinery mirrors `pyric/firestore`:
|
|
20
|
+
* - {@link TARGET_SYMBOL} brand on every {@link Database} handle.
|
|
21
|
+
* - {@link refToTarget} WeakMap from refs to their owning target so
|
|
22
|
+
* chained calls (`child(ref, 'sub')`, `get(ref)`) recover routing.
|
|
23
|
+
*
|
|
24
|
+
* Every public function has a `target.kind` switch with explicit
|
|
25
|
+
* branches — structure is parallel and grep-friendly.
|
|
26
|
+
*
|
|
27
|
+
* **Critical contract — error shape (locked by oracle observation
|
|
28
|
+
* `scripts/oracle/observations/rtdb-rules-denied-error-code.json`):**
|
|
29
|
+
*
|
|
30
|
+
* - Throws a **plain `Error`** (NOT a `FirebaseError`).
|
|
31
|
+
* - `.code === 'PERMISSION_DENIED'` (uppercase snake-case — distinct
|
|
32
|
+
* from Firestore's `'permission-denied'`).
|
|
33
|
+
* - `.message === 'PERMISSION_DENIED: Permission denied'`.
|
|
34
|
+
*
|
|
35
|
+
* The sandbox backend matches this shape exactly. Tests assert against
|
|
36
|
+
* `.constructor.name === 'Error'` to catch any future "improvement" to
|
|
37
|
+
* a custom subclass.
|
|
38
|
+
*/
|
|
39
|
+
import * as fb from 'firebase/database';
|
|
40
|
+
import { SandboxContextImpl } from 'pyric/sandbox';
|
|
41
|
+
// Phase 3 unified app handle. Adapter dispatch reads `APP_TARGET` and
|
|
42
|
+
// routes to the existing direct-handle path (sandbox vs prod).
|
|
43
|
+
import { APP_TARGET } from 'pyric/app';
|
|
44
|
+
import { RtdbBackend } from './sandbox/backend.js';
|
|
45
|
+
import { generatePushId } from './sandbox/push-id.js';
|
|
46
|
+
import { serverTimestampSentinel, incrementSentinel, } from './sandbox/sentinels.js';
|
|
47
|
+
import { joinPath, pathSegments } from './sandbox/data-tree.js';
|
|
48
|
+
import { coerceArrays } from './sandbox/normalize.js';
|
|
49
|
+
import { applyConstraint, emptySpec, } from './sandbox/query.js';
|
|
50
|
+
// ─── Brand + routing ─────────────────────────────────────────────────
|
|
51
|
+
/** Hidden brand on every {@link Database} handle. */
|
|
52
|
+
export const TARGET_SYMBOL = Symbol('@pyric/rtdb/target');
|
|
53
|
+
function isSandboxKind(t) {
|
|
54
|
+
return t.kind === 'sandbox' || t.kind === 'sandbox-live';
|
|
55
|
+
}
|
|
56
|
+
/** Resolve the active identity for a sandbox-flavored target. */
|
|
57
|
+
function authFor(t) {
|
|
58
|
+
if (t.admin)
|
|
59
|
+
return null;
|
|
60
|
+
return t.kind === 'sandbox' ? t.auth : t.sandbox.currentUser;
|
|
61
|
+
}
|
|
62
|
+
/**
|
|
63
|
+
* One backend per `Sandbox`. The modular surface tracks the binding
|
|
64
|
+
* here so successive `getDatabase(sandbox)` calls return handles that
|
|
65
|
+
* share data (matches `firebase/database`'s singleton-per-`FirebaseApp`).
|
|
66
|
+
*/
|
|
67
|
+
const backendBySandbox = new WeakMap();
|
|
68
|
+
function getOrCreateBackend(sandbox) {
|
|
69
|
+
let backend = backendBySandbox.get(sandbox);
|
|
70
|
+
if (!backend) {
|
|
71
|
+
// Pass the owning sandbox so the backend can land RTDB write activity
|
|
72
|
+
// on the unified Studio `onEvent`/`history()` stream (keystone T1).
|
|
73
|
+
backend = new RtdbBackend(sandbox);
|
|
74
|
+
backendBySandbox.set(sandbox, backend);
|
|
75
|
+
// Register the RTDB tree as a persistable service on the sandbox — the
|
|
76
|
+
// same durability mechanism auth uses (see auth/index.ts:backendFor).
|
|
77
|
+
// This makes `enablePersistence` include the tree in the serialized blob
|
|
78
|
+
// and restore it on reload (worker death / browser restart), instead of
|
|
79
|
+
// the old memory-only behavior where RTDB data was lost while Firestore
|
|
80
|
+
// docs + auth users came back.
|
|
81
|
+
//
|
|
82
|
+
// Guarded by the WeakMap memoization above: we only reach this branch
|
|
83
|
+
// ONCE per sandbox, so double-registration is impossible in practice
|
|
84
|
+
// (registerPersistableService throws on duplicates anyway).
|
|
85
|
+
//
|
|
86
|
+
// - snapshot: serialize the tree as a plain JSON value.
|
|
87
|
+
// - restore : REPLACE the tree AND fire listeners so a live RTDB view
|
|
88
|
+
// (Studio's RTDB tab) converges on the restored data.
|
|
89
|
+
// - subscribe: notify the controller on ANY write so a mutation
|
|
90
|
+
// schedules a debounced flush. RTDB writes emit
|
|
91
|
+
// `service_mutation` events, which the controller's
|
|
92
|
+
// `isPersistableEvent` does NOT cover — so this hook is the
|
|
93
|
+
// sole flush trigger, exactly as auth does it.
|
|
94
|
+
const capturedBackend = backend;
|
|
95
|
+
sandbox.registerPersistableService('rtdb', {
|
|
96
|
+
snapshot: () => capturedBackend.exportTree(),
|
|
97
|
+
restore: (data) => {
|
|
98
|
+
capturedBackend.restoreTree(data);
|
|
99
|
+
},
|
|
100
|
+
subscribe: (onChange) => capturedBackend.subscribeWrites(onChange),
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
return backend;
|
|
104
|
+
}
|
|
105
|
+
const refToTarget = new WeakMap();
|
|
106
|
+
function tag(obj, target) {
|
|
107
|
+
refToTarget.set(obj, target);
|
|
108
|
+
return obj;
|
|
109
|
+
}
|
|
110
|
+
function targetOf(refOrDb) {
|
|
111
|
+
if (TARGET_SYMBOL in refOrDb) {
|
|
112
|
+
return refOrDb[TARGET_SYMBOL];
|
|
113
|
+
}
|
|
114
|
+
const t = refToTarget.get(refOrDb);
|
|
115
|
+
if (!t) {
|
|
116
|
+
throw new TypeError('@pyric/rtdb: unrecognized reference — was it produced by a factory in this package?');
|
|
117
|
+
}
|
|
118
|
+
return t;
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Hidden brand on every {@link Query} (and on every QueryConstraint).
|
|
122
|
+
* Distinct from `TARGET_SYMBOL`; this brand is only used to dispatch
|
|
123
|
+
* `get` / `onValue` between plain refs and query-wrapped refs.
|
|
124
|
+
*/
|
|
125
|
+
export const QUERY_SYMBOL = Symbol('@pyric/rtdb/query');
|
|
126
|
+
/** Hidden brand on every {@link QueryConstraint}. */
|
|
127
|
+
const CONSTRAINT_SYMBOL = Symbol('@pyric/rtdb/query-constraint');
|
|
128
|
+
function buildConstraint(type, internal) {
|
|
129
|
+
return Object.freeze({
|
|
130
|
+
type,
|
|
131
|
+
[CONSTRAINT_SYMBOL]: internal,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
function isQuery(v) {
|
|
135
|
+
return QUERY_SYMBOL in v;
|
|
136
|
+
}
|
|
137
|
+
/** Internal-only: bridge our constraint into the prod-side fb constraint. */
|
|
138
|
+
function toFbConstraint(c) {
|
|
139
|
+
switch (c.type) {
|
|
140
|
+
case 'orderByChild': {
|
|
141
|
+
const ic = c[CONSTRAINT_SYMBOL];
|
|
142
|
+
return fb.orderByChild(ic.spec.path);
|
|
143
|
+
}
|
|
144
|
+
case 'orderByKey':
|
|
145
|
+
return fb.orderByKey();
|
|
146
|
+
case 'orderByValue':
|
|
147
|
+
return fb.orderByValue();
|
|
148
|
+
case 'startAt': {
|
|
149
|
+
const ic = c[CONSTRAINT_SYMBOL];
|
|
150
|
+
return fb.startAt(ic.bound.value, ic.bound.key);
|
|
151
|
+
}
|
|
152
|
+
case 'startAfter': {
|
|
153
|
+
const ic = c[CONSTRAINT_SYMBOL];
|
|
154
|
+
return fb.startAfter(ic.bound.value, ic.bound.key);
|
|
155
|
+
}
|
|
156
|
+
case 'endAt': {
|
|
157
|
+
const ic = c[CONSTRAINT_SYMBOL];
|
|
158
|
+
return fb.endAt(ic.bound.value, ic.bound.key);
|
|
159
|
+
}
|
|
160
|
+
case 'endBefore': {
|
|
161
|
+
const ic = c[CONSTRAINT_SYMBOL];
|
|
162
|
+
return fb.endBefore(ic.bound.value, ic.bound.key);
|
|
163
|
+
}
|
|
164
|
+
case 'equalTo': {
|
|
165
|
+
const ic = c[CONSTRAINT_SYMBOL];
|
|
166
|
+
return fb.equalTo(ic.bound.value, ic.bound.key);
|
|
167
|
+
}
|
|
168
|
+
case 'limitToFirst': {
|
|
169
|
+
const ic = c[CONSTRAINT_SYMBOL];
|
|
170
|
+
return fb.limitToFirst(ic.n);
|
|
171
|
+
}
|
|
172
|
+
case 'limitToLast': {
|
|
173
|
+
const ic = c[CONSTRAINT_SYMBOL];
|
|
174
|
+
return fb.limitToLast(ic.n);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
export function getDatabase(target) {
|
|
179
|
+
// PyricApp dispatch: inspect the brand and forward to the existing
|
|
180
|
+
// direct-handle path. Ordered FIRST so a PyricApp's outer shell
|
|
181
|
+
// never falls through to a structural sniff for `Sandbox`.
|
|
182
|
+
if (isPyricApp(target)) {
|
|
183
|
+
return target[APP_TARGET] === 'sandbox'
|
|
184
|
+
? getDatabase(target.sandbox)
|
|
185
|
+
: getDatabase(target.firebaseApp);
|
|
186
|
+
}
|
|
187
|
+
if (isSandboxContext(target)) {
|
|
188
|
+
const backend = getOrCreateBackend(target.sandbox);
|
|
189
|
+
const t = { kind: 'sandbox', backend, auth: target.auth };
|
|
190
|
+
return { [TARGET_SYMBOL]: t };
|
|
191
|
+
}
|
|
192
|
+
if (isSandbox(target)) {
|
|
193
|
+
const backend = getOrCreateBackend(target);
|
|
194
|
+
const t = { kind: 'sandbox-live', backend, sandbox: target };
|
|
195
|
+
return { [TARGET_SYMBOL]: t };
|
|
196
|
+
}
|
|
197
|
+
const fbDb = fb.getDatabase(target);
|
|
198
|
+
const t = { kind: 'prod', db: fbDb };
|
|
199
|
+
return { [TARGET_SYMBOL]: t };
|
|
200
|
+
}
|
|
201
|
+
export function getAdminDatabase(target) {
|
|
202
|
+
if (isPyricApp(target)) {
|
|
203
|
+
if (target[APP_TARGET] !== 'sandbox') {
|
|
204
|
+
throw new TypeError('getAdminDatabase: the admin (rules-bypass) lens is sandbox-only — ' +
|
|
205
|
+
'a prod-backed app has no way to bypass deployed security rules.');
|
|
206
|
+
}
|
|
207
|
+
return getAdminDatabase(target.sandbox);
|
|
208
|
+
}
|
|
209
|
+
const sandbox = isSandboxContext(target) ? target.sandbox : target;
|
|
210
|
+
const backend = getOrCreateBackend(sandbox);
|
|
211
|
+
const t = { kind: 'sandbox', backend, auth: null, admin: true };
|
|
212
|
+
return { [TARGET_SYMBOL]: t };
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Brand-based test for the {@link PyricApp} overload. Reads the
|
|
216
|
+
* `APP_TARGET` symbol that `pyric/app`'s `initializeApp` stamps on
|
|
217
|
+
* every handle. Cheap + collision-free: a `Sandbox` / `FirebaseApp`
|
|
218
|
+
* / `SandboxContext` will never carry this symbol.
|
|
219
|
+
*/
|
|
220
|
+
function isPyricApp(target) {
|
|
221
|
+
return (target !== null
|
|
222
|
+
&& typeof target === 'object'
|
|
223
|
+
&& APP_TARGET in target);
|
|
224
|
+
}
|
|
225
|
+
function isSandboxContext(target) {
|
|
226
|
+
return target instanceof SandboxContextImpl;
|
|
227
|
+
}
|
|
228
|
+
function isSandbox(target) {
|
|
229
|
+
if (target === null || typeof target !== 'object')
|
|
230
|
+
return false;
|
|
231
|
+
const o = target;
|
|
232
|
+
return (typeof o.withAuth === 'function'
|
|
233
|
+
&& typeof o.onCurrentUserChanged === 'function'
|
|
234
|
+
&& 'currentUser' in o
|
|
235
|
+
&& 'admin' in o);
|
|
236
|
+
}
|
|
237
|
+
// ─── Reference constructors ──────────────────────────────────────────
|
|
238
|
+
/**
|
|
239
|
+
* Build a {@link DatabaseReference} at `path` (default root).
|
|
240
|
+
*
|
|
241
|
+
* Sandbox: returns a lightweight ref object owning its absolute path.
|
|
242
|
+
* Prod: delegates to `firebase/database`'s `ref(db, path)` and tags
|
|
243
|
+
* the returned ref so chained ops route correctly.
|
|
244
|
+
*
|
|
245
|
+
* Path normalisation: leading + trailing slashes are stripped;
|
|
246
|
+
* empty path / `'/'` becomes the root.
|
|
247
|
+
*/
|
|
248
|
+
export function ref(db, path) {
|
|
249
|
+
const target = targetOf(db);
|
|
250
|
+
if (isSandboxKind(target)) {
|
|
251
|
+
return buildSandboxRef(target, path ?? '/');
|
|
252
|
+
}
|
|
253
|
+
const r = fb.ref(target.db, path);
|
|
254
|
+
// Tag so subsequent free-function calls (child, get, set, …)
|
|
255
|
+
// recover routing without inspecting the ref shape.
|
|
256
|
+
tag(r, target);
|
|
257
|
+
return r;
|
|
258
|
+
}
|
|
259
|
+
/**
|
|
260
|
+
* Sub-path constructor. `child(ref, 'sub/path')` returns a ref at
|
|
261
|
+
* `<ref>/sub/path`.
|
|
262
|
+
*
|
|
263
|
+
* Mirrors `firebase/database`'s `child(parent, path)` — leading +
|
|
264
|
+
* empty segments stripped; the result inherits the parent's target.
|
|
265
|
+
*/
|
|
266
|
+
export function child(parent, path) {
|
|
267
|
+
const target = targetOf(parent);
|
|
268
|
+
if (isSandboxKind(target)) {
|
|
269
|
+
const absSegs = [...pathSegments(parent._path), ...pathSegments(path)];
|
|
270
|
+
return buildSandboxRef(target, joinPath(absSegs));
|
|
271
|
+
}
|
|
272
|
+
const r = fb.child(parent, path);
|
|
273
|
+
tag(r, target);
|
|
274
|
+
return r;
|
|
275
|
+
}
|
|
276
|
+
/**
|
|
277
|
+
* Build a sandbox-backed `DatabaseReference`. Cached parent / root
|
|
278
|
+
* pointers are computed lazily so a long chain doesn't materialise
|
|
279
|
+
* every intermediate ref upfront.
|
|
280
|
+
*/
|
|
281
|
+
function buildSandboxRef(target, path) {
|
|
282
|
+
const canonical = joinPath(pathSegments(path));
|
|
283
|
+
const segs = pathSegments(canonical);
|
|
284
|
+
const key = segs.length === 0 ? null : segs[segs.length - 1];
|
|
285
|
+
const self = {
|
|
286
|
+
key,
|
|
287
|
+
_path: canonical,
|
|
288
|
+
get parent() {
|
|
289
|
+
if (segs.length === 0)
|
|
290
|
+
return null;
|
|
291
|
+
return buildSandboxRef(target, joinPath(segs.slice(0, -1)));
|
|
292
|
+
},
|
|
293
|
+
get root() {
|
|
294
|
+
return buildSandboxRef(target, '/');
|
|
295
|
+
},
|
|
296
|
+
toString() {
|
|
297
|
+
return `sandbox://rtdb${canonical}`;
|
|
298
|
+
},
|
|
299
|
+
};
|
|
300
|
+
tag(self, target);
|
|
301
|
+
return self;
|
|
302
|
+
}
|
|
303
|
+
// ─── Reads ───────────────────────────────────────────────────────────
|
|
304
|
+
/**
|
|
305
|
+
* `get(ref)` — one-shot read at the ref's path. Resolves to a
|
|
306
|
+
* `DataSnapshot`-shaped object.
|
|
307
|
+
*
|
|
308
|
+
* Sandbox: runs through the rule engine; denial throws the plain-`Error`
|
|
309
|
+
* shape locked by the oracle. Prod: delegates to `firebase/database`'s
|
|
310
|
+
* `get(ref)` and wraps the returned snapshot in our minimal shape.
|
|
311
|
+
*
|
|
312
|
+
* Absent path → `snap.val() === null && snap.exists() === false`.
|
|
313
|
+
* Matches the SDK's `DataSnapshot.val()` contract.
|
|
314
|
+
*/
|
|
315
|
+
export async function get(r) {
|
|
316
|
+
// Query branch — windowed read.
|
|
317
|
+
if (isQuery(r)) {
|
|
318
|
+
const q = r;
|
|
319
|
+
const target = targetOf(q.ref);
|
|
320
|
+
if (isSandboxKind(target)) {
|
|
321
|
+
const rows = target.admin
|
|
322
|
+
? target.backend.adminGetQuery(q.ref._path, q._spec)
|
|
323
|
+
: target.backend.getQuery(authFor(target), q.ref._path, q._spec);
|
|
324
|
+
return buildSandboxQuerySnap(target, q.ref, rows);
|
|
325
|
+
}
|
|
326
|
+
// Prod — q._fbQuery was built via fb.query() at construction time.
|
|
327
|
+
const fbQ = q._fbQuery ?? q.ref;
|
|
328
|
+
const snap = await fb.get(fbQ);
|
|
329
|
+
return wrapFbSnap(snap, target, q.ref);
|
|
330
|
+
}
|
|
331
|
+
const ref0 = r;
|
|
332
|
+
const target = targetOf(ref0);
|
|
333
|
+
if (isSandboxKind(target)) {
|
|
334
|
+
const val = target.admin
|
|
335
|
+
? target.backend.adminGet(ref0._path)
|
|
336
|
+
: target.backend.get(authFor(target), ref0._path);
|
|
337
|
+
return buildSandboxSnap(target, ref0, val);
|
|
338
|
+
}
|
|
339
|
+
const snap = await fb.get(ref0);
|
|
340
|
+
return wrapFbSnap(snap, target, ref0);
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* `set(ref, value)` — replace the value at `ref`'s path. `null`
|
|
344
|
+
* deletes (matches the RTDB invariant — locked by oracle observation
|
|
345
|
+
* `rtdb-remove-vs-set-null.json`).
|
|
346
|
+
*
|
|
347
|
+
* `serverTimestamp()` sentinels are resolved at write time on the
|
|
348
|
+
* sandbox side; the prod side relies on `firebase/database`'s wire
|
|
349
|
+
* encoder.
|
|
350
|
+
*/
|
|
351
|
+
export async function set(r, value) {
|
|
352
|
+
const target = targetOf(r);
|
|
353
|
+
if (isSandboxKind(target)) {
|
|
354
|
+
if (target.admin) {
|
|
355
|
+
target.backend.adminSet(r._path, value);
|
|
356
|
+
}
|
|
357
|
+
else {
|
|
358
|
+
target.backend.set(authFor(target), r._path, value);
|
|
359
|
+
}
|
|
360
|
+
return;
|
|
361
|
+
}
|
|
362
|
+
await fb.set(r, value);
|
|
363
|
+
}
|
|
364
|
+
/**
|
|
365
|
+
* `update(ref, values)` — partial update.
|
|
366
|
+
*
|
|
367
|
+
* - When `values` keys contain `/`, the call is a **multi-path atomic
|
|
368
|
+
* update**: every listed path is written as one transaction (any
|
|
369
|
+
* denial fails the whole batch).
|
|
370
|
+
* - Otherwise it's a **shallow merge** at the ref's path: each
|
|
371
|
+
* top-level key replaces the corresponding child. `null` values
|
|
372
|
+
* delete.
|
|
373
|
+
*
|
|
374
|
+
* Both behaviors are sandbox-implemented per the RtdbBackend's
|
|
375
|
+
* `update` method (`rtdb-modular`-spec atomic claim, matrix row #23).
|
|
376
|
+
*/
|
|
377
|
+
export async function update(r, values) {
|
|
378
|
+
const target = targetOf(r);
|
|
379
|
+
if (isSandboxKind(target)) {
|
|
380
|
+
if (target.admin) {
|
|
381
|
+
target.backend.adminUpdate(r._path, values);
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
target.backend.update(authFor(target), r._path, values);
|
|
385
|
+
}
|
|
386
|
+
return;
|
|
387
|
+
}
|
|
388
|
+
await fb.update(r, values);
|
|
389
|
+
}
|
|
390
|
+
/**
|
|
391
|
+
* `remove(ref)` — delete the subtree at the ref's path.
|
|
392
|
+
*
|
|
393
|
+
* RTDB invariant (oracle: `rtdb-remove-vs-set-null.json`): equivalent
|
|
394
|
+
* to `set(ref, null)`. The sandbox backend dispatches `remove` through
|
|
395
|
+
* the same code path as `set(_, null)`.
|
|
396
|
+
*/
|
|
397
|
+
export async function remove(r) {
|
|
398
|
+
const target = targetOf(r);
|
|
399
|
+
if (isSandboxKind(target)) {
|
|
400
|
+
if (target.admin) {
|
|
401
|
+
target.backend.adminRemove(r._path);
|
|
402
|
+
}
|
|
403
|
+
else {
|
|
404
|
+
target.backend.remove(authFor(target), r._path);
|
|
405
|
+
}
|
|
406
|
+
return;
|
|
407
|
+
}
|
|
408
|
+
await fb.remove(r);
|
|
409
|
+
}
|
|
410
|
+
/**
|
|
411
|
+
* `push(ref, value?)` — mint an auto-id child key under `ref`'s path,
|
|
412
|
+
* optionally writing `value` at the new child.
|
|
413
|
+
*
|
|
414
|
+
* Returns a ref at the new child path. The ref's `key` is the minted
|
|
415
|
+
* id (locked by oracle observation `rtdb-push-autoid-format.json`:
|
|
416
|
+
* 20 chars, leading `-`, lex-sortable).
|
|
417
|
+
*
|
|
418
|
+
* Production note: the key is minted **client-side** (no server
|
|
419
|
+
* round-trip required); it's available synchronously on the returned
|
|
420
|
+
* ref even when the optional write is denied by rules. The oracle
|
|
421
|
+
* observation confirms this — the sandbox matches.
|
|
422
|
+
*/
|
|
423
|
+
export function push(r, value) {
|
|
424
|
+
const target = targetOf(r);
|
|
425
|
+
if (isSandboxKind(target)) {
|
|
426
|
+
// Mint the key SYNCHRONOUSLY (client-side, no rule check) so the
|
|
427
|
+
// returned ref + `.key` are available even if the optional write is
|
|
428
|
+
// later denied (DB-B7). The write is deferred onto the thenable's
|
|
429
|
+
// promise — a rules denial REJECTS the promise rather than throwing
|
|
430
|
+
// here and discarding the key.
|
|
431
|
+
const key = target.backend.mintKey();
|
|
432
|
+
const childPath = joinPath([...pathSegments(r._path), key]);
|
|
433
|
+
// Two refs (mirroring upstream): `thenablePushRef` gets then/catch and
|
|
434
|
+
// is returned; `pushRef` is a SEPARATE plain ref used as the promise's
|
|
435
|
+
// fulfilled value — so resolving the promise doesn't re-enter the
|
|
436
|
+
// thenable's own `then` (the self-reference unwrap trap).
|
|
437
|
+
const thenablePushRef = buildSandboxRef(target, childPath);
|
|
438
|
+
const pushRef = buildSandboxRef(target, childPath);
|
|
439
|
+
const promise = value === undefined
|
|
440
|
+
? Promise.resolve(pushRef)
|
|
441
|
+
: set(pushRef, value).then(() => pushRef);
|
|
442
|
+
return makeThenable(thenablePushRef, promise);
|
|
443
|
+
}
|
|
444
|
+
const out = value === undefined
|
|
445
|
+
? fb.push(r)
|
|
446
|
+
: fb.push(r, value);
|
|
447
|
+
tag(out, target);
|
|
448
|
+
return out;
|
|
449
|
+
}
|
|
450
|
+
/**
|
|
451
|
+
* Attach `then`/`catch` to a ref so it satisfies {@link ThenableReference}.
|
|
452
|
+
* Mirrors upstream's `thenablePushRef.then = promise.then.bind(promise)`
|
|
453
|
+
* (`api/Reference_impl.ts:627-629`). The ref's own fields are untouched —
|
|
454
|
+
* it stays a usable {@link DatabaseReference}.
|
|
455
|
+
*/
|
|
456
|
+
function makeThenable(pushRef, promise) {
|
|
457
|
+
const thenable = pushRef;
|
|
458
|
+
thenable.then = promise.then.bind(promise);
|
|
459
|
+
thenable.catch = promise.catch.bind(promise);
|
|
460
|
+
return thenable;
|
|
461
|
+
}
|
|
462
|
+
/**
|
|
463
|
+
* Pre-mint a push key without writing. Used by callers that need the
|
|
464
|
+
* key for a multi-path update (`update(rootRef, { [\`/users/${key}\`]: ... })`).
|
|
465
|
+
* Sandbox-side: returns a freshly-minted key. Prod-side: same — the
|
|
466
|
+
* `push(ref).key` pattern is the documented way.
|
|
467
|
+
*/
|
|
468
|
+
export function pushKey() {
|
|
469
|
+
return generatePushId();
|
|
470
|
+
}
|
|
471
|
+
// ─── Listeners (Tier 2) ──────────────────────────────────────────────
|
|
472
|
+
/**
|
|
473
|
+
* `onValue(ref, cb)` — subscribe to value changes at the ref's path.
|
|
474
|
+
*
|
|
475
|
+
* Fires immediately on subscribe with the current value (or
|
|
476
|
+
* `null` + `exists: false` for an absent path), then on every
|
|
477
|
+
* subsequent write that touches the path or any descendant.
|
|
478
|
+
*
|
|
479
|
+
* Returns an unsubscribe function. The unsubscribe is idempotent;
|
|
480
|
+
* calling it twice is a no-op.
|
|
481
|
+
*
|
|
482
|
+
* `options.onlyOnce` (DB-B12): when `true`, the listener auto-unsubscribes
|
|
483
|
+
* after its first fire (mirrors `api/Reference_impl.ts:975-980`).
|
|
484
|
+
*
|
|
485
|
+
* Errors path: subscribing under rules that deny the read throws the
|
|
486
|
+
* plain-`Error` `PERMISSION_DENIED` shape synchronously (matching the
|
|
487
|
+
* production behavior where the subscribe path immediately errors).
|
|
488
|
+
*/
|
|
489
|
+
export function onValue(r, cb, options) {
|
|
490
|
+
// `onlyOnce` (DB-B12): wrap the callback so it unsubscribes itself
|
|
491
|
+
// after the first fire. The unsub is filled in once the real
|
|
492
|
+
// subscription is created below.
|
|
493
|
+
if (options?.onlyOnce) {
|
|
494
|
+
let unsub = null;
|
|
495
|
+
let fired = false;
|
|
496
|
+
const onceCb = (snap) => {
|
|
497
|
+
if (fired)
|
|
498
|
+
return;
|
|
499
|
+
fired = true;
|
|
500
|
+
// `unsub` may not be assigned yet if the initial fire is
|
|
501
|
+
// synchronous (the backend fires during subscribe, before
|
|
502
|
+
// `onValue` returns). The post-subscribe check below covers it.
|
|
503
|
+
if (unsub)
|
|
504
|
+
unsub();
|
|
505
|
+
cb(snap);
|
|
506
|
+
};
|
|
507
|
+
unsub = onValue(r, onceCb);
|
|
508
|
+
// Synchronous initial fire: `onceCb` ran before `unsub` was set, so
|
|
509
|
+
// remove the now-stale listener here.
|
|
510
|
+
if (fired)
|
|
511
|
+
unsub();
|
|
512
|
+
return fired ? () => { } : unsub;
|
|
513
|
+
}
|
|
514
|
+
// Query branch — fire only when the windowed result changes.
|
|
515
|
+
// Locked by oracle observation `rtdb-modular-onvalue-with-query.json`:
|
|
516
|
+
// a write OUTSIDE the window does NOT re-fire the listener; a write
|
|
517
|
+
// INSIDE or one that displaces a member DOES.
|
|
518
|
+
if (isQuery(r)) {
|
|
519
|
+
const q = r;
|
|
520
|
+
const target = targetOf(q.ref);
|
|
521
|
+
if (isSandboxKind(target)) {
|
|
522
|
+
return target.backend.onValue(authFor(target), q.ref._path, (raw) => {
|
|
523
|
+
const snap = buildSandboxSnapFromRaw(target, q.ref, raw.val);
|
|
524
|
+
try {
|
|
525
|
+
cb(snap);
|
|
526
|
+
}
|
|
527
|
+
catch {
|
|
528
|
+
// Listener throws are swallowed.
|
|
529
|
+
}
|
|
530
|
+
}, q._spec);
|
|
531
|
+
}
|
|
532
|
+
const fbQ = q._fbQuery ?? q.ref;
|
|
533
|
+
const off = fb.onValue(fbQ, (snap) => {
|
|
534
|
+
cb(wrapFbSnap(snap, target, q.ref));
|
|
535
|
+
});
|
|
536
|
+
return off;
|
|
537
|
+
}
|
|
538
|
+
const ref0 = r;
|
|
539
|
+
const target = targetOf(ref0);
|
|
540
|
+
if (isSandboxKind(target)) {
|
|
541
|
+
const wrapper = (raw) => {
|
|
542
|
+
const snap = buildSandboxSnapFromRaw(target, ref0, raw.val);
|
|
543
|
+
try {
|
|
544
|
+
cb(snap);
|
|
545
|
+
}
|
|
546
|
+
catch {
|
|
547
|
+
// Listener throws are swallowed — match `firebase/database`'s
|
|
548
|
+
// behavior where one observer's exception doesn't block others.
|
|
549
|
+
}
|
|
550
|
+
};
|
|
551
|
+
rememberWrapper(target.backend, ref0._path, 'value', cb, wrapper);
|
|
552
|
+
const unsub = target.backend.onValue(authFor(target), ref0._path, wrapper);
|
|
553
|
+
return () => {
|
|
554
|
+
forgetWrapper(target.backend, ref0._path, 'value', cb);
|
|
555
|
+
unsub();
|
|
556
|
+
};
|
|
557
|
+
}
|
|
558
|
+
const off = fb.onValue(ref0, (snap) => {
|
|
559
|
+
cb(wrapFbSnap(snap, target, ref0));
|
|
560
|
+
});
|
|
561
|
+
return off;
|
|
562
|
+
}
|
|
563
|
+
/**
|
|
564
|
+
* `onChildAdded(ref, cb)` — subscribe to child-added events at the
|
|
565
|
+
* ref's path.
|
|
566
|
+
*
|
|
567
|
+
* Semantics (locked by oracle observations under
|
|
568
|
+
* `scripts/oracle/observations/rtdb-modular-onchildadded-*.json`):
|
|
569
|
+
*
|
|
570
|
+
* - On subscribe, replays every existing direct child of `ref`'s path
|
|
571
|
+
* (one fire per existing key, in `orderByKey`-default order).
|
|
572
|
+
* - After subscribe, fires exactly once per new direct child write.
|
|
573
|
+
*
|
|
574
|
+
* Also accepts a {@link Query} (a `query(ref, ...)` with `orderBy*` /
|
|
575
|
+
* `limitTo*` constraints): child events are then computed against the
|
|
576
|
+
* ordered, windowed result — a child ENTERING the window fires
|
|
577
|
+
* `child_added`; on subscribe the current window is replayed in window
|
|
578
|
+
* order.
|
|
579
|
+
*
|
|
580
|
+
* Returns an unsubscribe; calling it twice is a no-op.
|
|
581
|
+
*/
|
|
582
|
+
export function onChildAdded(r, cb) {
|
|
583
|
+
return onChildEvent(r, 'child_added', cb);
|
|
584
|
+
}
|
|
585
|
+
/**
|
|
586
|
+
* `onChildChanged(ref, cb)` — subscribe to child-changed events.
|
|
587
|
+
*
|
|
588
|
+
* Semantics (oracle: `rtdb-modular-onchildchanged-fires-on-update`):
|
|
589
|
+
*
|
|
590
|
+
* - No initial replay.
|
|
591
|
+
* - Fires when an existing direct child's value transitions to a
|
|
592
|
+
* NEW non-null value. Snapshot carries the NEW value.
|
|
593
|
+
* - Does NOT fire for added or removed children.
|
|
594
|
+
*
|
|
595
|
+
* Also accepts a {@link Query}: fires when a child that is IN the query
|
|
596
|
+
* window changes value (an in-window update).
|
|
597
|
+
*/
|
|
598
|
+
export function onChildChanged(r, cb) {
|
|
599
|
+
return onChildEvent(r, 'child_changed', cb);
|
|
600
|
+
}
|
|
601
|
+
/**
|
|
602
|
+
* `onChildRemoved(ref, cb)` — subscribe to child-removed events.
|
|
603
|
+
*
|
|
604
|
+
* Semantics (oracle: `rtdb-modular-onchildremoved-fires-on-delete`):
|
|
605
|
+
*
|
|
606
|
+
* - No initial replay.
|
|
607
|
+
* - Fires when a direct child is deleted (via `remove(child)` or
|
|
608
|
+
* `set(child, null)`).
|
|
609
|
+
* - Snapshot carries the PRIOR (now-removed) value — the listener
|
|
610
|
+
* sees what was there before deletion.
|
|
611
|
+
*
|
|
612
|
+
* Also accepts a {@link Query}: a child LEAVING the query window (e.g.
|
|
613
|
+
* displaced past a `limitTo*` boundary or filtered out) fires
|
|
614
|
+
* `child_removed` carrying its prior value.
|
|
615
|
+
*/
|
|
616
|
+
export function onChildRemoved(r, cb) {
|
|
617
|
+
return onChildEvent(r, 'child_removed', cb);
|
|
618
|
+
}
|
|
619
|
+
/**
|
|
620
|
+
* `onChildMoved(ref, cb)` — subscribe to child-moved events.
|
|
621
|
+
*
|
|
622
|
+
* Semantics (oracle: `rtdb-modular-onchildmoved-with-orderby`):
|
|
623
|
+
*
|
|
624
|
+
* - Only fires under an ordered query (`query(ref, orderByChild(...))`).
|
|
625
|
+
* - Under a plain ref, this listener is effectively a no-op — the
|
|
626
|
+
* upstream SDK accepts the subscription but never fires it
|
|
627
|
+
* (matches RTDB docs).
|
|
628
|
+
*
|
|
629
|
+
* Accepts a {@link Query} WITHOUT throwing, but the sandbox deliberately
|
|
630
|
+
* does NOT fire `child_moved` on reorder yet: prod fires here (matrix row
|
|
631
|
+
* `rtdb-modular#137`) while the sandbox holds — the reorder /
|
|
632
|
+
* `previousChildName` ordering semantics are pending two new oracle
|
|
633
|
+
* captures. This is a documented, pinned divergence (both sides asserted
|
|
634
|
+
* in `test/database/modular/sandbox-child-events.test.ts`).
|
|
635
|
+
*/
|
|
636
|
+
export function onChildMoved(r, cb) {
|
|
637
|
+
return onChildEvent(r, 'child_moved', cb);
|
|
638
|
+
}
|
|
639
|
+
/**
|
|
640
|
+
* Map from a user-supplied callback to the wrapper the backend actually
|
|
641
|
+
* stored. Used by `off(ref, eventType, userCb)` to find the wrapper to
|
|
642
|
+
* remove — otherwise the user's callback identity wouldn't match the
|
|
643
|
+
* backend's registered listener.
|
|
644
|
+
*
|
|
645
|
+
* Keyed by `(backend, path, event, userCb)` — same user-cb can subscribe
|
|
646
|
+
* to multiple paths/events under different wrappers. The `WeakMap` outer
|
|
647
|
+
* layer is on the backend so removing a sandbox releases the inner refs.
|
|
648
|
+
*/
|
|
649
|
+
const wrapperRegistry = new WeakMap();
|
|
650
|
+
function registryKey(path, event, userCb) {
|
|
651
|
+
// Identity by cb-object — JS `Map` keys can be objects but we need a
|
|
652
|
+
// string-shaped composite. Use a Symbol-keyed identity weakRefId. The
|
|
653
|
+
// simplest approach: assign each unique user-cb a numeric id once.
|
|
654
|
+
const id = idForCb(userCb);
|
|
655
|
+
return `${path}${event}${id}`;
|
|
656
|
+
}
|
|
657
|
+
let nextCbId = 1;
|
|
658
|
+
const cbIds = new WeakMap();
|
|
659
|
+
function idForCb(cb) {
|
|
660
|
+
let id = cbIds.get(cb);
|
|
661
|
+
if (id === undefined) {
|
|
662
|
+
id = nextCbId++;
|
|
663
|
+
cbIds.set(cb, id);
|
|
664
|
+
}
|
|
665
|
+
return id;
|
|
666
|
+
}
|
|
667
|
+
function rememberWrapper(backend, path, event, userCb, wrapper) {
|
|
668
|
+
let map = wrapperRegistry.get(backend);
|
|
669
|
+
if (!map) {
|
|
670
|
+
map = new Map();
|
|
671
|
+
wrapperRegistry.set(backend, map);
|
|
672
|
+
}
|
|
673
|
+
map.set(registryKey(path, event, userCb), wrapper);
|
|
674
|
+
}
|
|
675
|
+
function lookupWrapper(backend, path, event, userCb) {
|
|
676
|
+
return wrapperRegistry.get(backend)?.get(registryKey(path, event, userCb));
|
|
677
|
+
}
|
|
678
|
+
function forgetWrapper(backend, path, event, userCb) {
|
|
679
|
+
wrapperRegistry.get(backend)?.delete(registryKey(path, event, userCb));
|
|
680
|
+
}
|
|
681
|
+
/**
|
|
682
|
+
* Internal shared implementation for the four `onChild*` variants.
|
|
683
|
+
*
|
|
684
|
+
* Accepts a plain {@link DatabaseReference} OR a {@link Query}
|
|
685
|
+
* (a `query(ref, ...)` with `orderBy*` / `limitTo*`). For a query, the
|
|
686
|
+
* child-event diff is computed against the ordered, windowed result rather
|
|
687
|
+
* than the raw child
|
|
688
|
+
* key-set — a child entering/leaving the window fires `child_added` /
|
|
689
|
+
* `child_removed`, an in-window value change fires `child_changed`. (Note
|
|
690
|
+
* `child_moved` on a query registers but does not fire on reorder — the
|
|
691
|
+
* reorder semantics are held pending fresh oracle captures.)
|
|
692
|
+
*/
|
|
693
|
+
function onChildEvent(r, event, cb) {
|
|
694
|
+
// Unwrap a Query into its base ref + spec; a plain ref has no spec.
|
|
695
|
+
const isQ = isQuery(r);
|
|
696
|
+
const baseRef = isQ ? r.ref : r;
|
|
697
|
+
const spec = isQ ? r._spec : undefined;
|
|
698
|
+
const target = targetOf(baseRef);
|
|
699
|
+
if (isSandboxKind(target)) {
|
|
700
|
+
const wrapper = (raw) => {
|
|
701
|
+
// Synthesize a snapshot rooted at the child path so `snap.key`
|
|
702
|
+
// and `snap.val()` match the upstream `onChildAdded` snapshot
|
|
703
|
+
// shape (key = the child's key, val = the child's value).
|
|
704
|
+
const childRef = child(baseRef, raw.key);
|
|
705
|
+
const snap = buildSandboxSnapFromRaw(target, childRef, raw.val);
|
|
706
|
+
try {
|
|
707
|
+
cb(snap);
|
|
708
|
+
}
|
|
709
|
+
catch {
|
|
710
|
+
// Listener throws are swallowed — match `firebase/database`'s
|
|
711
|
+
// behavior where one observer's exception doesn't block others.
|
|
712
|
+
}
|
|
713
|
+
};
|
|
714
|
+
rememberWrapper(target.backend, baseRef._path, event, cb, wrapper);
|
|
715
|
+
const unsub = target.backend.onChild(authFor(target), event, baseRef._path, wrapper, spec);
|
|
716
|
+
return () => {
|
|
717
|
+
forgetWrapper(target.backend, baseRef._path, event, cb);
|
|
718
|
+
unsub();
|
|
719
|
+
};
|
|
720
|
+
}
|
|
721
|
+
const handler = (snap) => {
|
|
722
|
+
cb(wrapFbSnap(snap, target, child(baseRef, snap.key ?? '')));
|
|
723
|
+
};
|
|
724
|
+
// Prod: subscribe against the fb Query when one was built at construction
|
|
725
|
+
// time, else the plain fb ref.
|
|
726
|
+
const fbListenTarget = (isQ
|
|
727
|
+
? (r._fbQuery ?? baseRef)
|
|
728
|
+
: baseRef);
|
|
729
|
+
switch (event) {
|
|
730
|
+
case 'child_added':
|
|
731
|
+
return fb.onChildAdded(fbListenTarget, handler);
|
|
732
|
+
case 'child_changed':
|
|
733
|
+
return fb.onChildChanged(fbListenTarget, handler);
|
|
734
|
+
case 'child_removed':
|
|
735
|
+
return fb.onChildRemoved(fbListenTarget, handler);
|
|
736
|
+
case 'child_moved':
|
|
737
|
+
return fb.onChildMoved(fbListenTarget, handler);
|
|
738
|
+
}
|
|
739
|
+
}
|
|
740
|
+
/**
|
|
741
|
+
* `off(ref, eventType?, callback?)` — unsubscribe variant.
|
|
742
|
+
*
|
|
743
|
+
* Semantics (locked by oracle observation
|
|
744
|
+
* `scripts/oracle/observations/rtdb-modular-off-stops-child-fires.json`):
|
|
745
|
+
*
|
|
746
|
+
* - `off(ref)` (no eventType) removes ALL listeners at that ref —
|
|
747
|
+
* value + every child event variety.
|
|
748
|
+
* - `off(ref, 'value')` removes only `value` listeners.
|
|
749
|
+
* - `off(ref, 'child_added')` (or any child event type) removes only
|
|
750
|
+
* that variety.
|
|
751
|
+
* - `off(ref, eventType, cb)` removes only the matching callback.
|
|
752
|
+
*
|
|
753
|
+
* The returned-unsubscribe pattern from `onValue` / `onChild*` is
|
|
754
|
+
* functionally equivalent to `off(ref, eventType, cb)` for a specific
|
|
755
|
+
* registration — both are supported.
|
|
756
|
+
*/
|
|
757
|
+
export function off(r, eventType, callback) {
|
|
758
|
+
const target = targetOf(r);
|
|
759
|
+
if (isSandboxKind(target)) {
|
|
760
|
+
if (callback !== undefined && eventType !== undefined) {
|
|
761
|
+
// Translate the user-supplied callback to the wrapper actually
|
|
762
|
+
// registered with the backend.
|
|
763
|
+
const wrapper = lookupWrapper(target.backend, r._path, eventType, callback);
|
|
764
|
+
if (wrapper !== undefined) {
|
|
765
|
+
target.backend.off(r._path, eventType, wrapper);
|
|
766
|
+
forgetWrapper(target.backend, r._path, eventType, callback);
|
|
767
|
+
}
|
|
768
|
+
// If no wrapper was found, the user-cb wasn't registered against
|
|
769
|
+
// this ref + eventType — no-throw, matches upstream behavior.
|
|
770
|
+
return;
|
|
771
|
+
}
|
|
772
|
+
target.backend.off(r._path, eventType, undefined);
|
|
773
|
+
return;
|
|
774
|
+
}
|
|
775
|
+
fb.off(r, eventType, callback);
|
|
776
|
+
}
|
|
777
|
+
// ─── Queries (Tier 3) ────────────────────────────────────────────────
|
|
778
|
+
/**
|
|
779
|
+
* `query(ref, ...constraints)` — wrap a ref in an immutable
|
|
780
|
+
* constraint chain. The resulting {@link Query} routes through
|
|
781
|
+
* {@link get}/{@link onValue} and applies the ordering + filtering +
|
|
782
|
+
* limit pipeline on the sandbox backend; on prod it delegates to
|
|
783
|
+
* `firebase/database`'s `query()`.
|
|
784
|
+
*
|
|
785
|
+
* Chaining is supported — `query(query(ref, orderByChild('x')),
|
|
786
|
+
* limitToFirst(2))` folds both constraints into one spec.
|
|
787
|
+
*
|
|
788
|
+
* Locked semantics (oracle):
|
|
789
|
+
* - `orderByChild('p') + startAt(v) + endAt(w)` is BOTH-inclusive
|
|
790
|
+
* (`rtdb-modular-orderbychild-window.json`).
|
|
791
|
+
* - `orderByKey() + startAt('b') + endAt('d')` matches `[b, c, d]`
|
|
792
|
+
* (`rtdb-modular-orderbykey-window.json`).
|
|
793
|
+
* - `orderByValue() + limitToFirst(3)` returns the 3 smallest by
|
|
794
|
+
* value (`rtdb-modular-orderbyvalue-numeric.json` — note: prod
|
|
795
|
+
* requires `.indexOn: ".value"`; sandbox does not enforce indexes).
|
|
796
|
+
* - `orderByChild('group') + equalTo('b')` returns ALL matching
|
|
797
|
+
* children (`rtdb-modular-equalTo-filter.json`).
|
|
798
|
+
* - `limitToFirst(N)` / `limitToLast(N)` take from the start / end of
|
|
799
|
+
* the ordered window (`rtdb-modular-limittofirst-vs-limittolast.json`).
|
|
800
|
+
* - `startAfter` / `endBefore` are EXCLUSIVE
|
|
801
|
+
* (`rtdb-modular-startafter-endbefore-exclusive.json`).
|
|
802
|
+
*/
|
|
803
|
+
export function query(refOrQuery, ...constraints) {
|
|
804
|
+
// Resolve base — could be a ref or a prior query (chaining).
|
|
805
|
+
let baseRef;
|
|
806
|
+
let baseSpec;
|
|
807
|
+
let basePriorFbQuery;
|
|
808
|
+
if (isQuery(refOrQuery)) {
|
|
809
|
+
const prior = refOrQuery;
|
|
810
|
+
baseRef = prior.ref;
|
|
811
|
+
baseSpec = prior._spec;
|
|
812
|
+
basePriorFbQuery = prior._fbQuery;
|
|
813
|
+
}
|
|
814
|
+
else {
|
|
815
|
+
baseRef = refOrQuery;
|
|
816
|
+
baseSpec = emptySpec();
|
|
817
|
+
}
|
|
818
|
+
let spec = baseSpec;
|
|
819
|
+
for (const c of constraints) {
|
|
820
|
+
spec = applyConstraint(spec, c[CONSTRAINT_SYMBOL]);
|
|
821
|
+
}
|
|
822
|
+
// Prod branch — chain into fb.query so the wire encoder + index
|
|
823
|
+
// checks happen in the upstream SDK exactly as a non-shim consumer
|
|
824
|
+
// would see them.
|
|
825
|
+
const target = targetOf(baseRef);
|
|
826
|
+
let fbQuery;
|
|
827
|
+
if (target.kind === 'prod') {
|
|
828
|
+
const fbBase = (basePriorFbQuery ?? baseRef);
|
|
829
|
+
fbQuery = constraints.length === 0
|
|
830
|
+
? fbBase
|
|
831
|
+
: fb.query(fbBase, ...constraints.map(toFbConstraint));
|
|
832
|
+
}
|
|
833
|
+
const q = {
|
|
834
|
+
ref: baseRef,
|
|
835
|
+
_spec: spec,
|
|
836
|
+
_fbQuery: fbQuery,
|
|
837
|
+
[QUERY_SYMBOL]: true,
|
|
838
|
+
toString() {
|
|
839
|
+
return baseRef.toString();
|
|
840
|
+
},
|
|
841
|
+
};
|
|
842
|
+
return q;
|
|
843
|
+
}
|
|
844
|
+
/** `orderByChild('path')` — order children by the value at the nested
|
|
845
|
+
* child path. Locked by oracle observation
|
|
846
|
+
* `rtdb-modular-orderbychild-window.json`. */
|
|
847
|
+
export function orderByChild(path) {
|
|
848
|
+
return buildConstraint('orderByChild', {
|
|
849
|
+
kind: 'orderBy',
|
|
850
|
+
spec: { kind: 'child', path },
|
|
851
|
+
});
|
|
852
|
+
}
|
|
853
|
+
/** `orderByKey()` — order children lexicographically by key string.
|
|
854
|
+
* Locked by oracle observation `rtdb-modular-orderbykey-window.json`. */
|
|
855
|
+
export function orderByKey() {
|
|
856
|
+
return buildConstraint('orderByKey', {
|
|
857
|
+
kind: 'orderBy',
|
|
858
|
+
spec: { kind: 'key' },
|
|
859
|
+
});
|
|
860
|
+
}
|
|
861
|
+
/** `orderByValue()` — order children by primitive value. Prod requires
|
|
862
|
+
* `.indexOn: ".value"` (oracle: `rtdb-modular-orderbyvalue-numeric.json`
|
|
863
|
+
* threw `Index not defined` against blockingfun); sandbox does NOT
|
|
864
|
+
* enforce indexes (the rules engine here checks read-allow only, not
|
|
865
|
+
* query-index conformance). */
|
|
866
|
+
export function orderByValue() {
|
|
867
|
+
return buildConstraint('orderByValue', {
|
|
868
|
+
kind: 'orderBy',
|
|
869
|
+
spec: { kind: 'value' },
|
|
870
|
+
});
|
|
871
|
+
}
|
|
872
|
+
/** `startAt(value, key?)` — INCLUSIVE lower bound under the active
|
|
873
|
+
* ordering. Optional `key` is the tie-breaker when ordering by
|
|
874
|
+
* child/value and multiple children share the bound's value. */
|
|
875
|
+
export function startAt(value, key) {
|
|
876
|
+
return buildConstraint('startAt', {
|
|
877
|
+
kind: 'bound',
|
|
878
|
+
bound: { kind: 'startAt', value, key },
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
/** `startAfter(value, key?)` — EXCLUSIVE lower bound. Locked by
|
|
882
|
+
* `rtdb-modular-startafter-endbefore-exclusive.json`. */
|
|
883
|
+
export function startAfter(value, key) {
|
|
884
|
+
return buildConstraint('startAfter', {
|
|
885
|
+
kind: 'bound',
|
|
886
|
+
bound: { kind: 'startAfter', value, key },
|
|
887
|
+
});
|
|
888
|
+
}
|
|
889
|
+
/** `endAt(value, key?)` — INCLUSIVE upper bound. Adjacent to startAt;
|
|
890
|
+
* same key tie-breaker semantics. */
|
|
891
|
+
export function endAt(value, key) {
|
|
892
|
+
return buildConstraint('endAt', {
|
|
893
|
+
kind: 'bound',
|
|
894
|
+
bound: { kind: 'endAt', value, key },
|
|
895
|
+
});
|
|
896
|
+
}
|
|
897
|
+
/** `endBefore(value, key?)` — EXCLUSIVE upper bound. Locked by
|
|
898
|
+
* `rtdb-modular-startafter-endbefore-exclusive.json`. */
|
|
899
|
+
export function endBefore(value, key) {
|
|
900
|
+
return buildConstraint('endBefore', {
|
|
901
|
+
kind: 'bound',
|
|
902
|
+
bound: { kind: 'endBefore', value, key },
|
|
903
|
+
});
|
|
904
|
+
}
|
|
905
|
+
/** `equalTo(value, key?)` — sugar for `startAt(value, key) +
|
|
906
|
+
* endAt(value, key)`. Returns ALL matching children (no uniqueness).
|
|
907
|
+
* Locked by oracle observation `rtdb-modular-equalTo-filter.json`. */
|
|
908
|
+
export function equalTo(value, key) {
|
|
909
|
+
return buildConstraint('equalTo', {
|
|
910
|
+
kind: 'bound',
|
|
911
|
+
bound: { kind: 'equalTo', value, key },
|
|
912
|
+
});
|
|
913
|
+
}
|
|
914
|
+
/** `limitToFirst(n)` — keep the first N children of the ordered window.
|
|
915
|
+
* Locked by oracle observation `rtdb-modular-limittofirst-vs-limittolast.json`. */
|
|
916
|
+
export function limitToFirst(n) {
|
|
917
|
+
return buildConstraint('limitToFirst', {
|
|
918
|
+
kind: 'limit',
|
|
919
|
+
limitKind: 'limitToFirst',
|
|
920
|
+
n,
|
|
921
|
+
});
|
|
922
|
+
}
|
|
923
|
+
/** `limitToLast(n)` — keep the last N children of the ordered window.
|
|
924
|
+
* Locked by oracle observation `rtdb-modular-limittofirst-vs-limittolast.json`. */
|
|
925
|
+
export function limitToLast(n) {
|
|
926
|
+
return buildConstraint('limitToLast', {
|
|
927
|
+
kind: 'limit',
|
|
928
|
+
limitKind: 'limitToLast',
|
|
929
|
+
n,
|
|
930
|
+
});
|
|
931
|
+
}
|
|
932
|
+
/**
|
|
933
|
+
* `runTransaction(ref, transactionUpdate, options?)` — atomic
|
|
934
|
+
* read-modify-write.
|
|
935
|
+
*
|
|
936
|
+
* Contract (oracle-locked):
|
|
937
|
+
*
|
|
938
|
+
* 1. `transactionUpdate` is called with the CURRENT value at `ref`'s
|
|
939
|
+
* path. For an absent path the arg is `null` (NOT `undefined`);
|
|
940
|
+
* oracle:
|
|
941
|
+
* `rtdb-modular-runtransaction-current-value-arg.json` →
|
|
942
|
+
* `missingFirstWasNull: true`.
|
|
943
|
+
* 2. Returning `undefined` from the update fn ABORTS the transaction:
|
|
944
|
+
* resolves `{ committed: false, snapshot }` where the snapshot is
|
|
945
|
+
* the pre-transaction value; oracle:
|
|
946
|
+
* `rtdb-modular-runtransaction-abort-undefined.json` → `committed:
|
|
947
|
+
* false, snapVal: null`.
|
|
948
|
+
* 3. Returning any defined value WRITES that value (rules-checked);
|
|
949
|
+
* resolves `{ committed: true, snapshot }` where `snapshot.val()`
|
|
950
|
+
* is the committed value; oracle:
|
|
951
|
+
* `rtdb-modular-runtransaction-success.json` → `committedNewValue:
|
|
952
|
+
* true` and
|
|
953
|
+
* `rtdb-modular-runtransaction-returns-committed-snapshot.json`.
|
|
954
|
+
* 4. If rules deny the write, the promise REJECTS with a plain
|
|
955
|
+
* `Error` whose `message === 'permission_denied'` and NO `.code`
|
|
956
|
+
* field (distinct from `set`/`get`'s `'PERMISSION_DENIED:
|
|
957
|
+
* Permission denied'`); oracle:
|
|
958
|
+
* `rtdb-modular-runtransaction-on-rules-denied-path.json`.
|
|
959
|
+
*
|
|
960
|
+
* `options.applyLocally` (default `true`): when `false`, the
|
|
961
|
+
* intermediate optimistic value is NOT fanned out to listeners — they
|
|
962
|
+
* see only the committed value. In a single-client harness this is
|
|
963
|
+
* usually invisible; we honor the flag for prod-parity. Oracle
|
|
964
|
+
* observation `rtdb-modular-runtransaction-options-applylocally.json`
|
|
965
|
+
* confirms both branches commit and end at the same value; the
|
|
966
|
+
* intermediate-fire difference isn't observable from a single client.
|
|
967
|
+
*
|
|
968
|
+
* Single-client sandbox doesn't model concurrency conflicts; the
|
|
969
|
+
* documented "retry on conflict" path is degenerate (no other writer
|
|
970
|
+
* exists to conflict with). The fn is invoked once.
|
|
971
|
+
*/
|
|
972
|
+
export async function runTransaction(r, transactionUpdate, options) {
|
|
973
|
+
const target = targetOf(r);
|
|
974
|
+
if (isSandboxKind(target)) {
|
|
975
|
+
const result = target.backend.runTransaction(authFor(target), r._path, transactionUpdate, options);
|
|
976
|
+
const snap = buildSandboxSnapFromRaw(target, r, result.val);
|
|
977
|
+
return { committed: result.committed, snapshot: snap };
|
|
978
|
+
}
|
|
979
|
+
const fbResult = await fb.runTransaction(r, transactionUpdate, options);
|
|
980
|
+
return {
|
|
981
|
+
committed: fbResult.committed,
|
|
982
|
+
snapshot: wrapFbSnap(fbResult.snapshot, target, r),
|
|
983
|
+
};
|
|
984
|
+
}
|
|
985
|
+
// ─── Sentinels ───────────────────────────────────────────────────────
|
|
986
|
+
/**
|
|
987
|
+
* `serverTimestamp()` — returns the `{ ".sv": "timestamp" }` sentinel
|
|
988
|
+
* the wire encoder recognises. Resolves to `Date.now()` (epoch ms) on
|
|
989
|
+
* write — locked by the prod SDK's resolved-as-number contract
|
|
990
|
+
* (oracle: `rtdb-servertimestamp-resolves.json`).
|
|
991
|
+
*
|
|
992
|
+
* Same shape across targets: the sandbox backend recognises the
|
|
993
|
+
* marker; the prod backend's wire encoder does too. Agent code that
|
|
994
|
+
* imports `serverTimestamp` from `@pyric/rtdb` works identically on
|
|
995
|
+
* either target.
|
|
996
|
+
*/
|
|
997
|
+
export function serverTimestamp() {
|
|
998
|
+
return serverTimestampSentinel();
|
|
999
|
+
}
|
|
1000
|
+
/**
|
|
1001
|
+
* `increment(delta)` — returns the `{ ".sv": { increment: delta } }`
|
|
1002
|
+
* sentinel that atomically adds `delta` to the current value at the
|
|
1003
|
+
* write's field. Starts from `0` when the field is absent or
|
|
1004
|
+
* non-numeric (oracle: `rtdb-modular-increment-from-missing.json`).
|
|
1005
|
+
*
|
|
1006
|
+
* Same shape across targets: the sandbox backend resolves it against the
|
|
1007
|
+
* field's prior value at write time; the prod backend's wire encoder
|
|
1008
|
+
* recognises the marker. Mirrors `firebase/database`'s `increment`
|
|
1009
|
+
* (`api/ServerValue.ts:38-44`).
|
|
1010
|
+
*/
|
|
1011
|
+
export function increment(delta) {
|
|
1012
|
+
return incrementSentinel(delta);
|
|
1013
|
+
}
|
|
1014
|
+
// ─── Emulator (no-op on sandbox) ─────────────────────────────────────
|
|
1015
|
+
/**
|
|
1016
|
+
* `connectDatabaseEmulator(db, host, port)` — point a prod handle at
|
|
1017
|
+
* a Firebase emulator. No-op on sandbox handles (the sandbox IS a
|
|
1018
|
+
* local emulator); the call is still accepted so consumer code that
|
|
1019
|
+
* does the wiring unconditionally compiles against both targets.
|
|
1020
|
+
*/
|
|
1021
|
+
export function connectDatabaseEmulator(db, host, port,
|
|
1022
|
+
// The modular SDK's signature lets you pass an optional namespace
|
|
1023
|
+
// (multi-DB projects). We accept-and-forward.
|
|
1024
|
+
options) {
|
|
1025
|
+
const target = targetOf(db);
|
|
1026
|
+
if (isSandboxKind(target))
|
|
1027
|
+
return;
|
|
1028
|
+
fb.connectDatabaseEmulator(target.db, host, port, options);
|
|
1029
|
+
}
|
|
1030
|
+
// ─── Sandbox-only ops ───────────────────────────────────────────────
|
|
1031
|
+
//
|
|
1032
|
+
// Mirrors `pyric/firestore`'s `sandbox` namespace — explicit
|
|
1033
|
+
// per-package sandbox lifecycle that the prod target doesn't ship.
|
|
1034
|
+
// Calling against a prod handle throws.
|
|
1035
|
+
export const sandbox = {
|
|
1036
|
+
/**
|
|
1037
|
+
* Replace deployed rules. Pass `null` to clear (sandbox returns to
|
|
1038
|
+
* default-allow). Rules are evaluated through the existing
|
|
1039
|
+
* `@pyric/rtdb` simulator — same engine as `simulate()` /
|
|
1040
|
+
* `rtdb_simulate_access`.
|
|
1041
|
+
*
|
|
1042
|
+
* @example
|
|
1043
|
+
* ```ts
|
|
1044
|
+
* sandbox.setRules(db, {
|
|
1045
|
+
* rules: {
|
|
1046
|
+
* '.read': 'auth != null',
|
|
1047
|
+
* '.write': 'auth != null',
|
|
1048
|
+
* },
|
|
1049
|
+
* });
|
|
1050
|
+
* ```
|
|
1051
|
+
*/
|
|
1052
|
+
setRules(db, rulesJson) {
|
|
1053
|
+
const target = targetOf(db);
|
|
1054
|
+
if (!isSandboxKind(target)) {
|
|
1055
|
+
throw new Error('sandbox.setRules is sandbox-only.');
|
|
1056
|
+
}
|
|
1057
|
+
target.backend.setRules(rulesJson);
|
|
1058
|
+
},
|
|
1059
|
+
/**
|
|
1060
|
+
* Bulk-load data bypassing rules. The supplied map's keys are
|
|
1061
|
+
* absolute paths (`'/users/alice'`) and the values land at those
|
|
1062
|
+
* paths. Convenient for test fixtures.
|
|
1063
|
+
*/
|
|
1064
|
+
setData(db, data) {
|
|
1065
|
+
const target = targetOf(db);
|
|
1066
|
+
if (!isSandboxKind(target)) {
|
|
1067
|
+
throw new Error('sandbox.setData is sandbox-only.');
|
|
1068
|
+
}
|
|
1069
|
+
target.backend.setData(data);
|
|
1070
|
+
},
|
|
1071
|
+
/** Snapshot the full sandbox tree (rule-bypass read). Usually a keyed
|
|
1072
|
+
* object; may be a primitive when the root holds one (DB-B13). */
|
|
1073
|
+
snapshotState(db) {
|
|
1074
|
+
const target = targetOf(db);
|
|
1075
|
+
if (!isSandboxKind(target)) {
|
|
1076
|
+
throw new Error('sandbox.snapshotState is sandbox-only.');
|
|
1077
|
+
}
|
|
1078
|
+
return target.backend.snapshotState();
|
|
1079
|
+
},
|
|
1080
|
+
};
|
|
1081
|
+
// ─── Snapshot wrappers ───────────────────────────────────────────────
|
|
1082
|
+
function buildSandboxSnap(target, refForSnap, val) {
|
|
1083
|
+
return buildSandboxSnapFromRaw(target, refForSnap, val);
|
|
1084
|
+
}
|
|
1085
|
+
function buildSandboxSnapFromRaw(_target, refForSnap, val) {
|
|
1086
|
+
const exists = val !== null;
|
|
1087
|
+
// `val` is the STORED (integer-keyed) shape. Structural ops
|
|
1088
|
+
// (`child`/`forEach`/`hasChildren`/`numChildren`) walk it directly;
|
|
1089
|
+
// `val()`/`toJSON()` render the DB-B2 array coercion lazily so a list
|
|
1090
|
+
// written as an array reads back as an array.
|
|
1091
|
+
const coerced = coerceArrays(val);
|
|
1092
|
+
const childCount = (val !== null && typeof val === 'object' && !Array.isArray(val))
|
|
1093
|
+
? Object.keys(val).length
|
|
1094
|
+
: 0;
|
|
1095
|
+
return {
|
|
1096
|
+
key: refForSnap.key,
|
|
1097
|
+
ref: refForSnap,
|
|
1098
|
+
size: childCount,
|
|
1099
|
+
priority: null,
|
|
1100
|
+
exists() { return exists; },
|
|
1101
|
+
val() { return coerced; },
|
|
1102
|
+
child(p) {
|
|
1103
|
+
const segs = pathSegments(p);
|
|
1104
|
+
let cur = val;
|
|
1105
|
+
for (const s of segs) {
|
|
1106
|
+
if (cur === null || typeof cur !== 'object' || Array.isArray(cur)) {
|
|
1107
|
+
cur = null;
|
|
1108
|
+
break;
|
|
1109
|
+
}
|
|
1110
|
+
cur = cur[s] ?? null;
|
|
1111
|
+
}
|
|
1112
|
+
const childRef = child(refForSnap, p);
|
|
1113
|
+
return buildSandboxSnapFromRaw(_target, childRef, cur);
|
|
1114
|
+
},
|
|
1115
|
+
hasChild(p) {
|
|
1116
|
+
return this.child(p).exists();
|
|
1117
|
+
},
|
|
1118
|
+
hasChildren() {
|
|
1119
|
+
return val !== null && typeof val === 'object' && !Array.isArray(val)
|
|
1120
|
+
&& Object.keys(val).length > 0;
|
|
1121
|
+
},
|
|
1122
|
+
exportVal() { return coerced; },
|
|
1123
|
+
toJSON() { return coerced; },
|
|
1124
|
+
forEach(cb) {
|
|
1125
|
+
if (val === null || typeof val !== 'object' || Array.isArray(val))
|
|
1126
|
+
return false;
|
|
1127
|
+
for (const [k, v] of Object.entries(val)) {
|
|
1128
|
+
const childRef = child(refForSnap, k);
|
|
1129
|
+
const childSnap = buildSandboxSnapFromRaw(_target, childRef, v);
|
|
1130
|
+
if (cb(childSnap) === true)
|
|
1131
|
+
return true;
|
|
1132
|
+
}
|
|
1133
|
+
return false;
|
|
1134
|
+
},
|
|
1135
|
+
};
|
|
1136
|
+
}
|
|
1137
|
+
/**
|
|
1138
|
+
* Build a snapshot from a query result. Differs from
|
|
1139
|
+
* {@link buildSandboxSnapFromRaw} in that the children iterate in the
|
|
1140
|
+
* order the executor produced them (not insertion order).
|
|
1141
|
+
*
|
|
1142
|
+
* `val()` returns a `Record<string, JsonValue>` containing only the
|
|
1143
|
+
* windowed children (or `null` if the window is empty), matching
|
|
1144
|
+
* `firebase/database`'s `DataSnapshot.val()` on a query snap.
|
|
1145
|
+
*
|
|
1146
|
+
* `numChildren()` is the window size; `forEach` walks the ordered rows.
|
|
1147
|
+
*/
|
|
1148
|
+
function buildSandboxQuerySnap(target, refForSnap, rows) {
|
|
1149
|
+
let val;
|
|
1150
|
+
if (rows.length === 0) {
|
|
1151
|
+
val = null;
|
|
1152
|
+
}
|
|
1153
|
+
else {
|
|
1154
|
+
const obj = {};
|
|
1155
|
+
for (const { key, value } of rows)
|
|
1156
|
+
obj[key] = value;
|
|
1157
|
+
val = obj;
|
|
1158
|
+
}
|
|
1159
|
+
const exists = rows.length > 0;
|
|
1160
|
+
const coerced = coerceArrays(val);
|
|
1161
|
+
return {
|
|
1162
|
+
key: refForSnap.key,
|
|
1163
|
+
ref: refForSnap,
|
|
1164
|
+
size: rows.length,
|
|
1165
|
+
priority: null,
|
|
1166
|
+
exists() { return exists; },
|
|
1167
|
+
val() { return coerced; },
|
|
1168
|
+
child(p) {
|
|
1169
|
+
const segs = pathSegments(p);
|
|
1170
|
+
let cur = val;
|
|
1171
|
+
for (const s of segs) {
|
|
1172
|
+
if (cur === null || typeof cur !== 'object' || Array.isArray(cur)) {
|
|
1173
|
+
cur = null;
|
|
1174
|
+
break;
|
|
1175
|
+
}
|
|
1176
|
+
cur = cur[s] ?? null;
|
|
1177
|
+
}
|
|
1178
|
+
const childRef = child(refForSnap, p);
|
|
1179
|
+
return buildSandboxSnapFromRaw(target, childRef, cur);
|
|
1180
|
+
},
|
|
1181
|
+
hasChild(p) {
|
|
1182
|
+
return this.child(p).exists();
|
|
1183
|
+
},
|
|
1184
|
+
hasChildren() { return rows.length > 0; },
|
|
1185
|
+
exportVal() { return coerced; },
|
|
1186
|
+
toJSON() { return coerced; },
|
|
1187
|
+
forEach(cb) {
|
|
1188
|
+
for (const { key, value } of rows) {
|
|
1189
|
+
const childRef = child(refForSnap, key);
|
|
1190
|
+
const childSnap = buildSandboxSnapFromRaw(target, childRef, value);
|
|
1191
|
+
if (cb(childSnap) === true)
|
|
1192
|
+
return true;
|
|
1193
|
+
}
|
|
1194
|
+
return false;
|
|
1195
|
+
},
|
|
1196
|
+
};
|
|
1197
|
+
}
|
|
1198
|
+
/**
|
|
1199
|
+
* Adapt a `firebase/database` `DataSnapshot` to our minimal interface.
|
|
1200
|
+
*
|
|
1201
|
+
* The fb snap already has all the methods our `DataSnapshot` shape
|
|
1202
|
+
* promises; we just need a `ref` that routes through our `Database`
|
|
1203
|
+
* handle's target on subsequent calls. Returning `fbSnap` unchanged
|
|
1204
|
+
* works for everything except the ref — the snap's `.ref` is an
|
|
1205
|
+
* `fb.DatabaseReference` that hasn't been tagged. Tag it.
|
|
1206
|
+
*/
|
|
1207
|
+
function wrapFbSnap(fbSnap, target, refForSnap) {
|
|
1208
|
+
// The fb snap's `.ref` is the same `fb.DatabaseReference` semantically
|
|
1209
|
+
// identical to what we built in `get(r)`. Tag it so chained ops
|
|
1210
|
+
// through `snap.ref` route correctly.
|
|
1211
|
+
tag(fbSnap.ref, target);
|
|
1212
|
+
return new Proxy(fbSnap, {
|
|
1213
|
+
get(t, prop) {
|
|
1214
|
+
if (prop === 'ref')
|
|
1215
|
+
return refForSnap;
|
|
1216
|
+
// Forward through to the fb snap for everything else; bind
|
|
1217
|
+
// methods so `this` stays the fb snap (it relies on private
|
|
1218
|
+
// state).
|
|
1219
|
+
const v = t[prop];
|
|
1220
|
+
if (typeof v === 'function')
|
|
1221
|
+
return v.bind(t);
|
|
1222
|
+
return v;
|
|
1223
|
+
},
|
|
1224
|
+
});
|
|
1225
|
+
}
|
|
1226
|
+
//# sourceMappingURL=modular.js.map
|