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,1235 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Public type surface for `pyric/sandbox`.
|
|
3
|
+
*
|
|
4
|
+
* Kept service-agnostic on purpose: `/app` is the host the rest of the
|
|
5
|
+
* library plugs into. Service modules (`/firestore`, future `/storage`,
|
|
6
|
+
* `/auth`, `/database`) depend on these types; they don't ship from
|
|
7
|
+
* here. See design rationale for the dependency-direction
|
|
8
|
+
* argument.
|
|
9
|
+
*/
|
|
10
|
+
import type { SandboxPersistenceOptions } from './persistence/types.js';
|
|
11
|
+
import type { TabSyncOptions } from './tab-sync/index.js';
|
|
12
|
+
/**
|
|
13
|
+
* A signed-in identity for sandbox operations. `null` is anonymous.
|
|
14
|
+
*
|
|
15
|
+
* `token` is the Firebase Auth token claims map (custom claims plus
|
|
16
|
+
* standard ones). It surfaces the same way it does in production rules
|
|
17
|
+
* via `request.auth.token.*`. Omit it for plain UID-only auth.
|
|
18
|
+
*
|
|
19
|
+
* Renamed from `AuthContext` (pre-multi-context) so the data type
|
|
20
|
+
* doesn't visually collide with `SandboxContext` (the identity-bearing
|
|
21
|
+
* handle). They sit at different layers — payload vs. handle — and the
|
|
22
|
+
* names should reflect that.
|
|
23
|
+
*/
|
|
24
|
+
export type AuthState = {
|
|
25
|
+
uid: string;
|
|
26
|
+
token?: Record<string, unknown>;
|
|
27
|
+
} | null;
|
|
28
|
+
/**
|
|
29
|
+
* Initialization config for a sandbox. All fields are optional; an
|
|
30
|
+
* empty config produces a sandbox with no rules and no seeded data.
|
|
31
|
+
*
|
|
32
|
+
* **No `auth` field.** Identity belongs to {@link SandboxContext}, not
|
|
33
|
+
* the sandbox. Service handles always require an explicit context.
|
|
34
|
+
*/
|
|
35
|
+
export interface SandboxConfig {
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Error codes raised by the sandbox layer.
|
|
39
|
+
*
|
|
40
|
+
* The first batch matches Firebase / gRPC conventions so existing
|
|
41
|
+
* `if (e.code === 'permission-denied')` code from production paths
|
|
42
|
+
* keeps working. The second batch is sandbox-specific and exists so
|
|
43
|
+
* agents can distinguish "sandbox doesn't simulate this" from "your
|
|
44
|
+
* code is wrong" without parsing message strings.
|
|
45
|
+
*/
|
|
46
|
+
export type SandboxErrorCode = 'invalid-argument' | 'permission-denied' | 'not-found' | 'already-exists' | 'failed-precondition' | 'aborted' | 'unavailable' | 'unimplemented' | 'not-seeded' | 'rules-not-loaded';
|
|
47
|
+
/**
|
|
48
|
+
* Structured denial context emitted alongside a `permission-denied`
|
|
49
|
+
* error. Real Firebase strips this server-side for security; the
|
|
50
|
+
* sandbox can expose it because it's a development tool.
|
|
51
|
+
*
|
|
52
|
+
* `auth` and `reasons` are populated whenever the sandbox raises a
|
|
53
|
+
* `permission-denied` error. `rule` (line + expression) requires
|
|
54
|
+
* source-position tracking in the rules AST and is deferred — see
|
|
55
|
+
* design rationale "Open questions" for the follow-up.
|
|
56
|
+
* `failedFields` will be filled in once the evaluator surfaces field-
|
|
57
|
+
* reference traces.
|
|
58
|
+
*/
|
|
59
|
+
export interface DenialContext {
|
|
60
|
+
/** The rule whose evaluation produced the denial. Best effort; may be absent until source positions land in the AST. */
|
|
61
|
+
rule?: {
|
|
62
|
+
line: number;
|
|
63
|
+
expression: string;
|
|
64
|
+
};
|
|
65
|
+
/** Auth identity that was active when the denial fired. */
|
|
66
|
+
auth?: AuthState;
|
|
67
|
+
/** Field paths in `request.resource.data` that the rule referenced and that failed. */
|
|
68
|
+
failedFields?: string[];
|
|
69
|
+
/**
|
|
70
|
+
* Raw simulator reasoning lines (the underlying engine's
|
|
71
|
+
* `debugMessages`). Always present on `permission-denied`. Stable
|
|
72
|
+
* enough for log surfacing; not stable as machine-parseable data.
|
|
73
|
+
*/
|
|
74
|
+
reasons?: string[];
|
|
75
|
+
/**
|
|
76
|
+
* Eval-time request shape — what the rule saw on `request.*`. Lets
|
|
77
|
+
* callers render a "why did this deny" frame (auth, method, path,
|
|
78
|
+
* `request.resource.data` with sentinels resolved) without re-deriving
|
|
79
|
+
* any of it from out-of-band state.
|
|
80
|
+
*/
|
|
81
|
+
request?: {
|
|
82
|
+
method: 'get' | 'list' | 'create' | 'update' | 'delete';
|
|
83
|
+
path: string;
|
|
84
|
+
/**
|
|
85
|
+
* The user's proposed `request.resource.data` — pre-resolution.
|
|
86
|
+
* `FieldValue.*` sentinels are preserved as their marker shapes
|
|
87
|
+
* (`{ __type: 'serverTimestamp' }`, etc.). The rule engine
|
|
88
|
+
* evaluated against the resolved form; what surfaces here is the
|
|
89
|
+
* caller's INTENT so consumers see what they tried to write.
|
|
90
|
+
* Absent for reads (no proposed write) and for `delete` (no payload).
|
|
91
|
+
*/
|
|
92
|
+
resourceData?: Record<string, unknown>;
|
|
93
|
+
};
|
|
94
|
+
/**
|
|
95
|
+
* Eval-time existing-document snapshot — what the rule saw on
|
|
96
|
+
* `resource.data`. `null` data with `exists: false` mirrors how the
|
|
97
|
+
* rule sees an absent doc. Absent for collection ops (`list`).
|
|
98
|
+
*/
|
|
99
|
+
resource?: {
|
|
100
|
+
data: Record<string, unknown> | null;
|
|
101
|
+
exists: boolean;
|
|
102
|
+
};
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Options bag for `SandboxError`. Used by call sites that want to
|
|
106
|
+
* attach actionable remediation text (or both denial context and
|
|
107
|
+
* remediation) without juggling positional argument order.
|
|
108
|
+
*/
|
|
109
|
+
export interface SandboxErrorOptions {
|
|
110
|
+
code: SandboxErrorCode;
|
|
111
|
+
message: string;
|
|
112
|
+
denialContext?: DenialContext;
|
|
113
|
+
/**
|
|
114
|
+
* Optional human-readable guidance appended to the error's
|
|
115
|
+
* `.message` so existing consumers that surface `error.message`
|
|
116
|
+
* (logs, UIs) see the remediation without an API change. Stored on
|
|
117
|
+
* the instance as well so structured callers can read it directly.
|
|
118
|
+
*/
|
|
119
|
+
remediation?: string;
|
|
120
|
+
}
|
|
121
|
+
/**
|
|
122
|
+
* Sandbox-layer error. Catch with `instanceof SandboxError` and switch
|
|
123
|
+
* on `code`. `denialContext` is populated for `permission-denied` only
|
|
124
|
+
* (and only after Slice 4 wires it through).
|
|
125
|
+
*
|
|
126
|
+
* Two construction forms are supported:
|
|
127
|
+
* - Positional: `new SandboxError(code, message, denialContext?)` —
|
|
128
|
+
* the original signature, kept for backward compatibility with
|
|
129
|
+
* existing internal call sites.
|
|
130
|
+
* - Options bag: `new SandboxError({ code, message, remediation? })` —
|
|
131
|
+
* used when attaching remediation guidance.
|
|
132
|
+
*/
|
|
133
|
+
export declare class SandboxError extends Error {
|
|
134
|
+
readonly code: SandboxErrorCode;
|
|
135
|
+
readonly denialContext?: DenialContext;
|
|
136
|
+
readonly remediation?: string;
|
|
137
|
+
constructor(code: SandboxErrorCode, message: string, denialContext?: DenialContext);
|
|
138
|
+
constructor(options: SandboxErrorOptions);
|
|
139
|
+
}
|
|
140
|
+
/**
|
|
141
|
+
* Contract for a service that can contribute its state to the sandbox
|
|
142
|
+
* persistence layer. Services (auth, storage, database) register
|
|
143
|
+
* themselves via {@link Sandbox.registerPersistableService} so the
|
|
144
|
+
* sandbox core stays service-agnostic — the sandbox doesn't know what
|
|
145
|
+
* auth or storage look like; it just calls `snapshot()` / `restore()`.
|
|
146
|
+
*
|
|
147
|
+
* `subscribe` is optional but strongly recommended: without it, a
|
|
148
|
+
* service's changes (e.g. new users created via auth) only reach the
|
|
149
|
+
* persisted blob on the next Firestore write. With `subscribe`, the
|
|
150
|
+
* controller debounces a flush on every user-DB change — same latency
|
|
151
|
+
* as Firestore writes.
|
|
152
|
+
*/
|
|
153
|
+
export interface PersistableService {
|
|
154
|
+
/**
|
|
155
|
+
* Return a plain-JSON-serializable snapshot of this service's state.
|
|
156
|
+
* Called by the persistence controller on every flush. The return
|
|
157
|
+
* value is stored under the service's registered name in the
|
|
158
|
+
* `services` map of the persisted blob.
|
|
159
|
+
*/
|
|
160
|
+
snapshot(): unknown;
|
|
161
|
+
/**
|
|
162
|
+
* Restore previously snapshotted state. Called once during
|
|
163
|
+
* `enablePersistence`, AFTER Firestore docs have been restored (so
|
|
164
|
+
* any service that needs Firestore to be hydrated first can rely on
|
|
165
|
+
* that ordering). Guard against bad data — the blob came from disk
|
|
166
|
+
* and may be stale or from a schema migration.
|
|
167
|
+
*/
|
|
168
|
+
restore(data: unknown): void;
|
|
169
|
+
/**
|
|
170
|
+
* Optional: subscribe to changes in this service's state. When
|
|
171
|
+
* provided, the persistence controller hooks it up and schedules
|
|
172
|
+
* a debounced flush on each change — ensuring auth-user edits reach
|
|
173
|
+
* the backend promptly, not only on the next Firestore write.
|
|
174
|
+
*
|
|
175
|
+
* Must return an unsubscribe function. The controller unsubscribes
|
|
176
|
+
* on `dispose()`.
|
|
177
|
+
*/
|
|
178
|
+
subscribe?: (onChange: () => void) => () => void;
|
|
179
|
+
/**
|
|
180
|
+
* Optional: session-level persistence hooks. When provided, the
|
|
181
|
+
* persistence controller uses these to save and restore the CURRENTLY
|
|
182
|
+
* SIGNED-IN user (not the user database — that's `snapshot`/`restore`).
|
|
183
|
+
*
|
|
184
|
+
* The controller calls `session.subscribe` so it hears every sign-in /
|
|
185
|
+
* sign-out, then writes the uid to the appropriate web-storage slot
|
|
186
|
+
* (determined by `session.mode()`). On init, the controller reads the
|
|
187
|
+
* stored uid and calls `session.restore(uid)` to re-establish the
|
|
188
|
+
* session, firing `onAuthStateChanged` as if the user just signed in.
|
|
189
|
+
*
|
|
190
|
+
* Only active when `SandboxPersistenceOptions.sessionStorage` is
|
|
191
|
+
* provided; omitting `sessionStorage` causes the controller to skip
|
|
192
|
+
* session persistence entirely (no fake durability).
|
|
193
|
+
*
|
|
194
|
+
* Auth is the only service that provides session hooks today. The
|
|
195
|
+
* field is on the generic interface so the controller stays
|
|
196
|
+
* service-agnostic — if a second service ever needs session-style
|
|
197
|
+
* semantics it can add its own hooks without changing the controller.
|
|
198
|
+
*/
|
|
199
|
+
session?: {
|
|
200
|
+
/**
|
|
201
|
+
* The uid of the currently signed-in user, or null when signed out.
|
|
202
|
+
* Read by the controller after a subscription fires, and before a
|
|
203
|
+
* save, to snapshot the current state.
|
|
204
|
+
*/
|
|
205
|
+
currentUid(): string | null;
|
|
206
|
+
/**
|
|
207
|
+
* Re-establish the signed-in session for `uid`. Fires
|
|
208
|
+
* `onAuthStateChanged` as if the user just signed in. May throw
|
|
209
|
+
* `auth/user-not-found` or `auth/user-disabled` — the controller
|
|
210
|
+
* catches and clears the stored session so a stale uid (user deleted
|
|
211
|
+
* between sessions) doesn't crash init.
|
|
212
|
+
*/
|
|
213
|
+
restore(uid: string): void;
|
|
214
|
+
/**
|
|
215
|
+
* Current persistence mode. Determines which web-storage slot the
|
|
216
|
+
* controller writes to:
|
|
217
|
+
* LOCAL → localStorage (survives reload + restart; Firebase default)
|
|
218
|
+
* SESSION → sessionStorage (survives reload, cleared on tab close)
|
|
219
|
+
* NONE → not stored
|
|
220
|
+
*
|
|
221
|
+
* Read on every save so a `setPersistence` call is reflected in the
|
|
222
|
+
* next write without an explicit migration step.
|
|
223
|
+
*/
|
|
224
|
+
mode(): 'LOCAL' | 'SESSION' | 'NONE';
|
|
225
|
+
/**
|
|
226
|
+
* Subscribe to sign-in / sign-out changes. The controller installs
|
|
227
|
+
* exactly one subscription here and uses it to drive session saves.
|
|
228
|
+
* Must return an unsubscribe function.
|
|
229
|
+
*
|
|
230
|
+
* Note: this fires on any currentUser change, including external
|
|
231
|
+
* mutations (sandbox.reset(), another handle's sign-in). The
|
|
232
|
+
* controller reads `currentUid()` + `mode()` on each fire and
|
|
233
|
+
* re-computes the correct storage slot — no stale references.
|
|
234
|
+
*/
|
|
235
|
+
subscribe(onChange: () => void): () => void;
|
|
236
|
+
};
|
|
237
|
+
}
|
|
238
|
+
/**
|
|
239
|
+
* Sandbox-level snapshot — a coarse capture of every service's state
|
|
240
|
+
* keyed by service name. The `firestore` key is always present; the
|
|
241
|
+
* `services` map holds one entry per registered persistable service
|
|
242
|
+
* (auth users, future storage objects, etc.). Service-specific
|
|
243
|
+
* snapshot types live in their service modules; `/app` keeps the index
|
|
244
|
+
* structural so it stays decoupled from service implementations.
|
|
245
|
+
*
|
|
246
|
+
* v2 shape — `services` was added when the persistable-service registry
|
|
247
|
+
* landed. Prior `{ firestore }` v1 blobs are treated as having an empty
|
|
248
|
+
* `services` map on restore.
|
|
249
|
+
*/
|
|
250
|
+
export interface SandboxSnapshot {
|
|
251
|
+
/** Firestore documents, keyed by full path. Always present — empty
|
|
252
|
+
* `{}` for a fresh or just-reset sandbox. Per-document values are
|
|
253
|
+
* the post-resolution state the keyspace stored. */
|
|
254
|
+
firestore: Record<string, Record<string, unknown>>;
|
|
255
|
+
/**
|
|
256
|
+
* Per-service opaque state, keyed by service name (e.g. `'auth'`).
|
|
257
|
+
* Each entry is whatever the service's `PersistableService.snapshot()`
|
|
258
|
+
* returned. May be `{}` when no services are registered.
|
|
259
|
+
*/
|
|
260
|
+
services: Record<string, unknown>;
|
|
261
|
+
}
|
|
262
|
+
/**
|
|
263
|
+
* Admin-plane access — bypasses rules, intended for test assertions
|
|
264
|
+
* ("did the write actually land?"). Surfaced only on the root sandbox
|
|
265
|
+
* because admin reads are identity-agnostic and presenting them on a
|
|
266
|
+
* fork (which exists to *carry* an identity) is conceptually muddled.
|
|
267
|
+
*
|
|
268
|
+
* The shape is intentionally flat for v1 since only Firestore exists.
|
|
269
|
+
* When other services land, this surface namespaces by service
|
|
270
|
+
* (`admin.firestore.getDocument`, `admin.storage.getObject`) and the
|
|
271
|
+
* current flat methods will move under `admin.firestore.*`. Document
|
|
272
|
+
* the migration loudly when it happens.
|
|
273
|
+
*/
|
|
274
|
+
export interface SandboxAdmin {
|
|
275
|
+
/**
|
|
276
|
+
* Read a Firestore document by full path, ignoring rules. Returns
|
|
277
|
+
* `null` if the document doesn't exist.
|
|
278
|
+
*/
|
|
279
|
+
getDocument(path: string): unknown | null;
|
|
280
|
+
/**
|
|
281
|
+
* List Firestore documents under a collection path, ignoring rules.
|
|
282
|
+
* Returns `{ path, data, phantom? }` records — `phantom: true` marks
|
|
283
|
+
* synthesized parent docs that have descendants but no stored data
|
|
284
|
+
* of their own (matches what a live Firestore listing would expose).
|
|
285
|
+
*/
|
|
286
|
+
listDocuments(prefix: string): {
|
|
287
|
+
path: string;
|
|
288
|
+
data: unknown;
|
|
289
|
+
phantom?: true;
|
|
290
|
+
}[];
|
|
291
|
+
/**
|
|
292
|
+
* Write a Firestore document by full path, ignoring rules. Creates
|
|
293
|
+
* or overwrites the doc — same "replace" semantics as the user-plane
|
|
294
|
+
* `setDoc(ref, data)` (no merge). Intended for admin tools like the
|
|
295
|
+
* playground's Firestore explorer where the operator should be able
|
|
296
|
+
* to seed/edit data regardless of what rules say.
|
|
297
|
+
*
|
|
298
|
+
* Listeners fire as if the write had gone through the rules path,
|
|
299
|
+
* so subscriptions see the change live. Emits a `request` event with
|
|
300
|
+
* `result: 'allow'` and an `auth: null` shape — admin writes leave
|
|
301
|
+
* a trace in the event log, but aren't gated.
|
|
302
|
+
*/
|
|
303
|
+
setDocument(path: string, data: Record<string, unknown>): void;
|
|
304
|
+
/**
|
|
305
|
+
* Delete a Firestore document by full path, ignoring rules. Returns
|
|
306
|
+
* `{ deleted }` reflecting whether a doc was actually removed
|
|
307
|
+
* (`false` if the path didn't exist). Idempotent.
|
|
308
|
+
*
|
|
309
|
+
* Same listener / event-log semantics as {@link setDocument}.
|
|
310
|
+
*/
|
|
311
|
+
deleteDocument(path: string): {
|
|
312
|
+
deleted: boolean;
|
|
313
|
+
};
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* A Firebase sandbox — an isolated environment with one auth identity.
|
|
317
|
+
*
|
|
318
|
+
* Created via `initializeSandbox(config)`. Use `fork({ auth })` to
|
|
319
|
+
* derive a new sandbox with a different identity that shares the
|
|
320
|
+
* underlying environment (rules, data, state). Fork is the only
|
|
321
|
+
* identity-switching mechanism — there are no per-op auth overrides
|
|
322
|
+
* and no in-place mutation.
|
|
323
|
+
*/
|
|
324
|
+
/**
|
|
325
|
+
* Eval-time payload emitted to {@link Sandbox.onDenial} subscribers.
|
|
326
|
+
*
|
|
327
|
+
* Mirrors the structured fields {@link DenialContext} carries (`request`
|
|
328
|
+
* + `resource` + `reasons` + `auth`) so a host environment that wants
|
|
329
|
+
* to surface denials independent of try/catch behavior gets the same
|
|
330
|
+
* frame either way.
|
|
331
|
+
*/
|
|
332
|
+
export interface DenialEvent {
|
|
333
|
+
code: 'permission-denied';
|
|
334
|
+
message: string;
|
|
335
|
+
auth?: AuthState;
|
|
336
|
+
request?: {
|
|
337
|
+
method: 'get' | 'list' | 'create' | 'update' | 'delete';
|
|
338
|
+
path: string;
|
|
339
|
+
resourceData?: Record<string, unknown>;
|
|
340
|
+
};
|
|
341
|
+
resource?: {
|
|
342
|
+
data: Record<string, unknown> | null;
|
|
343
|
+
exists: boolean;
|
|
344
|
+
};
|
|
345
|
+
reasons?: string[];
|
|
346
|
+
}
|
|
347
|
+
/**
|
|
348
|
+
* Eval-time payload emitted to {@link Sandbox.onSnapshotError} subscribers.
|
|
349
|
+
*
|
|
350
|
+
* Stream-level error from a Firestore `onSnapshot` listener — the
|
|
351
|
+
* listener has been silently terminated and will deliver no further
|
|
352
|
+
* snapshots (matches production: a stream error is once-per-stream and
|
|
353
|
+
* the listener stays "subscribed" from the consumer's perspective but
|
|
354
|
+
* receives nothing further). Carries the `target` so the host UI can
|
|
355
|
+
* attribute the error to a specific watch.
|
|
356
|
+
*
|
|
357
|
+
* Currently `permission-denied` is the only code the sandbox produces
|
|
358
|
+
* (production also emits `unavailable`, `aborted`, `resource-exhausted`
|
|
359
|
+
* — none of which have a sandbox analog: no network stream to drop, no
|
|
360
|
+
* quota, no concurrent transactions to conflict). Documented divergence
|
|
361
|
+
* from production; new codes can be added if a sandbox-specific
|
|
362
|
+
* scenario surfaces them.
|
|
363
|
+
*/
|
|
364
|
+
export interface SnapshotErrorEvent {
|
|
365
|
+
code: 'permission-denied';
|
|
366
|
+
message: string;
|
|
367
|
+
target: {
|
|
368
|
+
kind: 'doc';
|
|
369
|
+
path: string;
|
|
370
|
+
} | {
|
|
371
|
+
kind: 'query';
|
|
372
|
+
collection: string;
|
|
373
|
+
};
|
|
374
|
+
auth?: AuthState;
|
|
375
|
+
request?: {
|
|
376
|
+
method: 'get' | 'list' | 'create' | 'update' | 'delete';
|
|
377
|
+
path: string;
|
|
378
|
+
resourceData?: Record<string, unknown>;
|
|
379
|
+
};
|
|
380
|
+
resource?: {
|
|
381
|
+
data: Record<string, unknown> | null;
|
|
382
|
+
exists: boolean;
|
|
383
|
+
};
|
|
384
|
+
reasons?: string[];
|
|
385
|
+
}
|
|
386
|
+
/**
|
|
387
|
+
* Eval-time payload emitted to {@link Sandbox.onRequest} subscribers —
|
|
388
|
+
* one per evaluated op, regardless of outcome.
|
|
389
|
+
*
|
|
390
|
+
* Issue #307: the playground today only renders denials, but every op
|
|
391
|
+
* the simulator evaluates is a request worth seeing. This event is the
|
|
392
|
+
* source of truth; {@link DenialEvent} is a filtered projection over
|
|
393
|
+
* the `result === 'deny'` subset.
|
|
394
|
+
*
|
|
395
|
+
* Origin tells the consumer who initiated the eval:
|
|
396
|
+
* - `user` single op via the data-plane adapter (admin / firestore).
|
|
397
|
+
* - `batch` part of a multi-op batch — shares `groupId` with siblings.
|
|
398
|
+
* - `transaction` part of a transaction commit — shares `groupId`.
|
|
399
|
+
* - `listener` a write or `deployRules` triggered a snapshot listener
|
|
400
|
+
* to re-evaluate. Carries `triggeredBy` naming the
|
|
401
|
+
* originating user op (when knowable).
|
|
402
|
+
*
|
|
403
|
+
* `evalMs` measures the wall-clock duration of the simulator's
|
|
404
|
+
* `simulate(...)` call. Sub-millisecond is normal for simple rules;
|
|
405
|
+
* rule-engine-heavy rules (deep boolean chains, many get() calls) can
|
|
406
|
+
* reach tens of milliseconds; a traffic-monitor validation probe measured
|
|
407
|
+
* connect-four rules at ~95ms p99. Surface this in your UI when it matters.
|
|
408
|
+
*
|
|
409
|
+
* Listener throws are swallowed by the dispatcher so a faulty
|
|
410
|
+
* subscriber can't change rule semantics or hide other events.
|
|
411
|
+
*
|
|
412
|
+
* @see traffic-monitor-decision.md for the field-by-field rationale.
|
|
413
|
+
*/
|
|
414
|
+
export interface RequestEvent {
|
|
415
|
+
/** Discriminator. */
|
|
416
|
+
kind: 'request';
|
|
417
|
+
/** Unique within a sandbox process. Useful for React list keys. */
|
|
418
|
+
id: string;
|
|
419
|
+
/** Wall-clock at op start, ms since epoch. */
|
|
420
|
+
at: number;
|
|
421
|
+
/** Wall-clock duration of the simulator.simulate(...) call, in ms. */
|
|
422
|
+
evalMs: number;
|
|
423
|
+
method: 'get' | 'list' | 'create' | 'update' | 'set' | 'delete';
|
|
424
|
+
path: string;
|
|
425
|
+
auth: AuthState;
|
|
426
|
+
/** `'unsupported'` fires when the simulator hit an unmodelled feature
|
|
427
|
+
* and the sandbox upgraded it (today: thrown as SimulatorUnsupportedError,
|
|
428
|
+
* surfaced here as a discrete result so the panel can show it distinctly
|
|
429
|
+
* from a real denial). */
|
|
430
|
+
result: 'allow' | 'deny' | 'unsupported';
|
|
431
|
+
/** Simulator debug messages — the per-rule trace (`Rule #0 (read) → ALLOW`).
|
|
432
|
+
* Same shape as `DenialEvent.reasons` so consumer code can share rendering. */
|
|
433
|
+
reasons: string[];
|
|
434
|
+
/** Proposed write payload, for create/update/set. Absent on reads + delete.
|
|
435
|
+
* Pre-resolution: `FieldValue.*` sentinels are preserved as their marker
|
|
436
|
+
* shapes (`{ __type: 'serverTimestamp' }`, etc.) so the replay engine
|
|
437
|
+
* can re-resolve them. The rule engine evaluated against the resolved
|
|
438
|
+
* form internally; that resolved form lives on
|
|
439
|
+
* {@link WriteSandboxEvent.nextState}, not here. */
|
|
440
|
+
request?: {
|
|
441
|
+
resourceData?: Record<string, unknown>;
|
|
442
|
+
};
|
|
443
|
+
/** Existing document state before the write (or read target for get). */
|
|
444
|
+
resourceBefore?: {
|
|
445
|
+
data: Record<string, unknown> | null;
|
|
446
|
+
exists: boolean;
|
|
447
|
+
};
|
|
448
|
+
/** Projected document state after the write. Absent on reads. */
|
|
449
|
+
resourceAfter?: {
|
|
450
|
+
data: Record<string, unknown> | null;
|
|
451
|
+
exists: boolean;
|
|
452
|
+
};
|
|
453
|
+
/** Parsed from the simulator's "Rule #N → …" debug line. Absent when no
|
|
454
|
+
* rule matched (e.g. no allow rules at the path — implicit deny). */
|
|
455
|
+
matchedRule?: {
|
|
456
|
+
ruleIndex: number;
|
|
457
|
+
operations: string[];
|
|
458
|
+
};
|
|
459
|
+
/** The DECIDING rule's verdict + 1-indexed source line + full sub-expression
|
|
460
|
+
* trace, projected from the simulator's structured `RuleEvaluation`
|
|
461
|
+
* (additive: present on `result: 'allow' | 'deny'` Firestore events when the
|
|
462
|
+
* simulator produced a per-rule trace — the allowing rule on an allow, the
|
|
463
|
+
* denying rule on a deny). Studio's rules inspector reads this to mark the
|
|
464
|
+
* deciding line and render the evaluation step-through ("show the work").
|
|
465
|
+
* Absent on an implicit deny (no rule evaluated), a simulator-error deny,
|
|
466
|
+
* and unsupported results. */
|
|
467
|
+
evaluatedRule?: import('../rules/test/spec.js').EvaluatedRuleInfo;
|
|
468
|
+
origin: 'user' | 'listener' | 'transaction' | 'batch';
|
|
469
|
+
/** Shared across ops in one batch or transaction. Opaque to consumers. */
|
|
470
|
+
groupId?: string;
|
|
471
|
+
/** Disambiguates `origin: 'transaction' | 'batch'` cases when consumers
|
|
472
|
+
* need to tell them apart without inspecting `origin` directly. */
|
|
473
|
+
groupKind?: 'batch' | 'transaction';
|
|
474
|
+
/** For listener re-evals: the originating user op that triggered this
|
|
475
|
+
* re-evaluation. Absent on the initial-snapshot fire. */
|
|
476
|
+
triggeredBy?: {
|
|
477
|
+
method: string;
|
|
478
|
+
path: string;
|
|
479
|
+
};
|
|
480
|
+
/** Free-form operation metadata. `admin: true` marks a rules-bypassing
|
|
481
|
+
* setup/admin operation so fixture tooling can exclude it from protected
|
|
482
|
+
* behavior while still preserving it as replay context. */
|
|
483
|
+
detail?: {
|
|
484
|
+
admin?: boolean;
|
|
485
|
+
} & Record<string, unknown>;
|
|
486
|
+
}
|
|
487
|
+
/**
|
|
488
|
+
* Committed write — a `create`/`update`/`set`/`delete` that the rule
|
|
489
|
+
* engine allowed AND that the keyspace successfully applied. Includes
|
|
490
|
+
* pre- and post-state so consumers can render diffs and (in a future
|
|
491
|
+
* `sandbox.history()` API) reconstruct state by replay.
|
|
492
|
+
*
|
|
493
|
+
* Fires AFTER the corresponding `kind: 'request'` event for the same
|
|
494
|
+
* op. A denied or rolled-back write surfaces as a request-deny only;
|
|
495
|
+
* `write` events only fire for committed writes.
|
|
496
|
+
*
|
|
497
|
+
* `sentinels` and `autoId` are placeholders for the eventual replay
|
|
498
|
+
* engine — v1 of the unified channel leaves them undefined. The shape
|
|
499
|
+
* is locked so consumers can build against it without churn when
|
|
500
|
+
* sentinel/auto-id capture lands.
|
|
501
|
+
*/
|
|
502
|
+
export interface WriteSandboxEvent {
|
|
503
|
+
kind: 'write';
|
|
504
|
+
id: string;
|
|
505
|
+
at: number;
|
|
506
|
+
method: 'create' | 'update' | 'set' | 'delete';
|
|
507
|
+
path: string;
|
|
508
|
+
auth: AuthState;
|
|
509
|
+
/** Pre-resolution write payload — `FieldValue.*` sentinels preserved
|
|
510
|
+
* as marker shapes (`{ __type: 'serverTimestamp' }`, etc.) so the
|
|
511
|
+
* replay engine can re-resolve them. The rule engine evaluated
|
|
512
|
+
* against the resolved form internally; the resolved form lives on
|
|
513
|
+
* {@link nextState}. Absent on `delete`. */
|
|
514
|
+
data?: Record<string, unknown>;
|
|
515
|
+
/** State BEFORE this write. `null` for a non-existent doc. */
|
|
516
|
+
priorState: Record<string, unknown> | null;
|
|
517
|
+
/** State AFTER this write. `null` on `delete`. */
|
|
518
|
+
nextState: Record<string, unknown> | null;
|
|
519
|
+
groupId?: string;
|
|
520
|
+
groupKind?: 'batch' | 'transaction';
|
|
521
|
+
/** FieldValue sentinels (serverTimestamp / increment / arrayUnion /
|
|
522
|
+
* arrayRemove / deleteField → 'delete') extracted from the
|
|
523
|
+
* pre-resolution write payload. The replay engine consumes this
|
|
524
|
+
* to re-issue the same sentinels at replay time without consulting
|
|
525
|
+
* resolved values that would have drifted. Path syntax: dotted
|
|
526
|
+
* with bracket-indices ('a.b[0].c'). Absent when the write
|
|
527
|
+
* contained no sentinels. */
|
|
528
|
+
sentinels?: Array<{
|
|
529
|
+
field: string;
|
|
530
|
+
kind: 'serverTimestamp' | 'increment' | 'arrayUnion' | 'arrayRemove' | 'delete';
|
|
531
|
+
}>;
|
|
532
|
+
/** Minted document ID when this write came from `collection.add()` /
|
|
533
|
+
* `LocalEnvironment.createWithAutoId`. The replay engine aliases
|
|
534
|
+
* the path's last segment to a fresh mint on replay (rather than
|
|
535
|
+
* preserving the original auto-ID). */
|
|
536
|
+
autoId?: string;
|
|
537
|
+
/** Server time at which the rule engine evaluated this write —
|
|
538
|
+
* pinned per op (or shared across sub-ops in a batch / transaction).
|
|
539
|
+
* The replay engine re-issues this exact value when re-resolving
|
|
540
|
+
* `serverTimestamp()` sentinels so resolved fields are bit-identical
|
|
541
|
+
* on replay. Shape mirrors the Firestore Web SDK Timestamp
|
|
542
|
+
* (`{ seconds, nanoseconds }`). */
|
|
543
|
+
requestTime: {
|
|
544
|
+
seconds: number;
|
|
545
|
+
nanoseconds: number;
|
|
546
|
+
};
|
|
547
|
+
/** Free-form write metadata. `admin: true` marks a rules-bypassing
|
|
548
|
+
* setup/admin commit so replay can apply it as context without asking
|
|
549
|
+
* candidate rules to permit it. */
|
|
550
|
+
detail?: {
|
|
551
|
+
admin?: boolean;
|
|
552
|
+
} & Record<string, unknown>;
|
|
553
|
+
}
|
|
554
|
+
/**
|
|
555
|
+
* Snapshot delivered to a `onSnapshot` listener's user callback.
|
|
556
|
+
*
|
|
557
|
+
* Fires AFTER the no-op suppression check — every `snapshot_delivery`
|
|
558
|
+
* event corresponds to an actual user-callback invocation. Listener
|
|
559
|
+
* re-evals that resolved to no-ops emit {@link SnapshotSuppressedEvent}
|
|
560
|
+
* instead.
|
|
561
|
+
*
|
|
562
|
+
* `sample` carries best-effort serializable views of the docs the
|
|
563
|
+
* callback received; consumers truncate before persisting if the
|
|
564
|
+
* scenario produces large snapshots.
|
|
565
|
+
*/
|
|
566
|
+
export interface SnapshotDeliveryEvent {
|
|
567
|
+
kind: 'snapshot_delivery';
|
|
568
|
+
id: string;
|
|
569
|
+
at: number;
|
|
570
|
+
/** Opaque listener id assigned at attach time. */
|
|
571
|
+
listenerId: string;
|
|
572
|
+
target: {
|
|
573
|
+
kind: 'doc';
|
|
574
|
+
path: string;
|
|
575
|
+
} | {
|
|
576
|
+
kind: 'query';
|
|
577
|
+
collection: string;
|
|
578
|
+
};
|
|
579
|
+
auth: AuthState;
|
|
580
|
+
addedCount: number;
|
|
581
|
+
modifiedCount: number;
|
|
582
|
+
removedCount: number;
|
|
583
|
+
/** `1` for doc-kind (exists) / `0` (deleted), `n` for query-kind. */
|
|
584
|
+
size: number;
|
|
585
|
+
/** Doc payloads, in the order the user callback saw them. */
|
|
586
|
+
sample?: {
|
|
587
|
+
docs: Array<{
|
|
588
|
+
path: string;
|
|
589
|
+
data: Record<string, unknown> | null;
|
|
590
|
+
}>;
|
|
591
|
+
};
|
|
592
|
+
/** The user op that triggered this re-eval. Absent on initial fire
|
|
593
|
+
* and on `deployRules`-driven re-evals. */
|
|
594
|
+
triggeredBy?: {
|
|
595
|
+
method: string;
|
|
596
|
+
path: string;
|
|
597
|
+
};
|
|
598
|
+
}
|
|
599
|
+
/**
|
|
600
|
+
* Listener re-eval that was suppressed before delivery — the re-eval
|
|
601
|
+
* ran but produced no observable change vs the prior snapshot, so the
|
|
602
|
+
* user callback wasn't invoked.
|
|
603
|
+
*
|
|
604
|
+
* Useful for "why didn't my listener fire" debugging. Default UIs
|
|
605
|
+
* should filter these out; only the inspector-style consumer needs
|
|
606
|
+
* them.
|
|
607
|
+
*/
|
|
608
|
+
export interface SnapshotSuppressedEvent {
|
|
609
|
+
kind: 'snapshot_suppressed';
|
|
610
|
+
id: string;
|
|
611
|
+
at: number;
|
|
612
|
+
listenerId: string;
|
|
613
|
+
target: {
|
|
614
|
+
kind: 'doc';
|
|
615
|
+
path: string;
|
|
616
|
+
} | {
|
|
617
|
+
kind: 'query';
|
|
618
|
+
collection: string;
|
|
619
|
+
};
|
|
620
|
+
auth: AuthState;
|
|
621
|
+
/** Why this re-eval was suppressed. v1 only emits `'no-op'`. */
|
|
622
|
+
reason: 'no-op';
|
|
623
|
+
triggeredBy?: {
|
|
624
|
+
method: string;
|
|
625
|
+
path: string;
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
/**
|
|
629
|
+
* Listener lifecycle event — attach, detach, or errored. Errored
|
|
630
|
+
* supersedes the prior `onSnapshotError` channel; `error` is populated
|
|
631
|
+
* on the errored phase only.
|
|
632
|
+
*/
|
|
633
|
+
export interface ListenerLifecycleEvent {
|
|
634
|
+
kind: 'listener_attach' | 'listener_detach' | 'listener_errored';
|
|
635
|
+
id: string;
|
|
636
|
+
at: number;
|
|
637
|
+
listenerId: string;
|
|
638
|
+
target: {
|
|
639
|
+
kind: 'doc';
|
|
640
|
+
path: string;
|
|
641
|
+
} | {
|
|
642
|
+
kind: 'query';
|
|
643
|
+
collection: string;
|
|
644
|
+
};
|
|
645
|
+
auth: AuthState;
|
|
646
|
+
/** Populated on `listener_errored` only. */
|
|
647
|
+
error?: {
|
|
648
|
+
code: 'permission-denied';
|
|
649
|
+
message: string;
|
|
650
|
+
reasons?: string[];
|
|
651
|
+
};
|
|
652
|
+
}
|
|
653
|
+
/**
|
|
654
|
+
* Session boundary — emitted before `sandbox.reset()` swaps the env,
|
|
655
|
+
* and before `sandbox.dispose()` tears it down. Lets consumers segment
|
|
656
|
+
* a persisted event stream into "session N pre-reset" / "session N+1
|
|
657
|
+
* post-reset" runs.
|
|
658
|
+
*/
|
|
659
|
+
export interface SessionBoundaryEvent {
|
|
660
|
+
kind: 'session_boundary';
|
|
661
|
+
id: string;
|
|
662
|
+
at: number;
|
|
663
|
+
phase: 'reset' | 'dispose';
|
|
664
|
+
/** Total events emitted on this sandbox before the boundary. */
|
|
665
|
+
priorOpCount: number;
|
|
666
|
+
}
|
|
667
|
+
/**
|
|
668
|
+
* Cross-service mutation event — the unified envelope the NON-Firestore
|
|
669
|
+
* services (`auth` / `storage` / `rtdb`) emit into the single
|
|
670
|
+
* `onEvent`/`history()` stream (Pyric Studio keystone, track T1).
|
|
671
|
+
*
|
|
672
|
+
* **Why a new variant rather than reusing `request`/`write`.** Firestore's
|
|
673
|
+
* existing kinds are tightly coupled to the rules-simulator: `RequestEvent`
|
|
674
|
+
* carries `result: 'allow'|'deny'`, `evalMs`, the simulator's `reasons[]`,
|
|
675
|
+
* and `matchedRule`; `WriteSandboxEvent` carries Firestore-specific
|
|
676
|
+
* `sentinels`, `autoId`, and a Firestore `requestTime` Timestamp. Auth user-
|
|
677
|
+
* DB mutations (no path, no rule eval), Storage object puts, and RTDB tree
|
|
678
|
+
* writes don't have those concepts, and bending them into the Firestore
|
|
679
|
+
* shapes would either lie (synthesize a fake `result`/`requestTime`) or
|
|
680
|
+
* pollute the Firestore consumer contract. So this is ONE small, additive
|
|
681
|
+
* variant the three services share — Firestore consumers filter on their
|
|
682
|
+
* existing `kind`s and never see it. See the design rationale.
|
|
683
|
+
*
|
|
684
|
+
* It is intentionally generic: `op` is a free-ish string discriminated by
|
|
685
|
+
* `service`, and `before`/`after` are best-effort serializable snapshots
|
|
686
|
+
* (omitted when not meaningful — e.g. a sign-out has no `after`). Studio's
|
|
687
|
+
* data grids / Action Center render `service` + `op` + `path` directly and
|
|
688
|
+
* diff `before`→`after` when both are present.
|
|
689
|
+
*/
|
|
690
|
+
export interface ServiceMutationEvent {
|
|
691
|
+
kind: 'service_mutation';
|
|
692
|
+
id: string;
|
|
693
|
+
at: number;
|
|
694
|
+
/**
|
|
695
|
+
* Which service performed the mutation. Always one of the non-Firestore
|
|
696
|
+
* services — Firestore rides its own `request`/`write` path. (The
|
|
697
|
+
* provenance `service` field on the stamped event mirrors this; it is set
|
|
698
|
+
* redundantly here so a consumer matching purely on `kind` still gets the
|
|
699
|
+
* discriminator without reaching into provenance.)
|
|
700
|
+
*/
|
|
701
|
+
service: 'auth' | 'storage' | 'rtdb';
|
|
702
|
+
/**
|
|
703
|
+
* Service-scoped operation name. Stable, lowercase, snake/kebab-free:
|
|
704
|
+
* - auth: `user_create` | `user_update` | `user_delete` |
|
|
705
|
+
* `users_clear` | `sign_in` | `sign_out`
|
|
706
|
+
* - storage: `object_put` | `object_delete` | `metadata_update`
|
|
707
|
+
* - rtdb: `set` | `update` | `remove` | `transaction`
|
|
708
|
+
* New ops can be added without a breaking change (consumers switch with a
|
|
709
|
+
* default branch).
|
|
710
|
+
*/
|
|
711
|
+
op: string;
|
|
712
|
+
/**
|
|
713
|
+
* The thing mutated, in the service's own addressing scheme:
|
|
714
|
+
* - auth: the user `uid` (or `'*'` for a clear-all). Absent for a
|
|
715
|
+
* sign-out with no prior user.
|
|
716
|
+
* - storage: the object `fullPath` (e.g. `avatars/alice.png`).
|
|
717
|
+
* - rtdb: the database path (e.g. `/rooms/r1/messages`), or for a
|
|
718
|
+
* multi-path `update` the ref path the call targeted.
|
|
719
|
+
*/
|
|
720
|
+
path?: string;
|
|
721
|
+
/** Identity in effect when the op ran (the service's `request.auth`
|
|
722
|
+
* equivalent). `null` for admin/anonymous-driven mutations (e.g.
|
|
723
|
+
* `sandbox.createUser`, an unauthenticated RTDB write). */
|
|
724
|
+
auth: AuthState;
|
|
725
|
+
/** Best-effort serializable snapshot of the state BEFORE the mutation.
|
|
726
|
+
* Absent when there was no prior state (a create) or it isn't cheap to
|
|
727
|
+
* capture. */
|
|
728
|
+
before?: unknown;
|
|
729
|
+
/** Best-effort serializable snapshot of the state AFTER the mutation.
|
|
730
|
+
* Absent on deletes / sign-outs (nothing remains). */
|
|
731
|
+
after?: unknown;
|
|
732
|
+
/** Free-form, service-specific extras a consumer may surface without
|
|
733
|
+
* re-deriving (e.g. storage `{ size, contentType }`, rtdb
|
|
734
|
+
* `{ committed }` for a transaction). Kept loose on purpose — it's a
|
|
735
|
+
* display hint, not a contract. */
|
|
736
|
+
detail?: Record<string, unknown>;
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* Canonical service operation event. This is the service-neutral successor to
|
|
740
|
+
* Firestore's `request` traffic shape: every user-visible operation can be
|
|
741
|
+
* represented here, whether it is backed by security rules (Firestore/RTDB/
|
|
742
|
+
* Storage) or by a service control plane (Auth).
|
|
743
|
+
*
|
|
744
|
+
* Existing Firestore `request` events remain for compatibility. New cross-
|
|
745
|
+
* service consumers should prefer `operation` because it carries an explicit
|
|
746
|
+
* `service` discriminator and does not require RTDB/Storage/Auth to pretend
|
|
747
|
+
* their state is a Firestore document.
|
|
748
|
+
*/
|
|
749
|
+
export interface SandboxOperationEvent {
|
|
750
|
+
kind: 'operation';
|
|
751
|
+
id: string;
|
|
752
|
+
at: number;
|
|
753
|
+
service: EventService;
|
|
754
|
+
method: string;
|
|
755
|
+
path?: string;
|
|
756
|
+
auth: AuthState;
|
|
757
|
+
result: 'allow' | 'deny' | 'unsupported' | 'error' | 'not-applicable';
|
|
758
|
+
origin: 'user' | 'listener' | 'transaction' | 'batch' | 'admin' | 'system';
|
|
759
|
+
durationMs?: number;
|
|
760
|
+
reasons?: string[];
|
|
761
|
+
rules?: {
|
|
762
|
+
engine: 'firestore' | 'rtdb' | 'storage';
|
|
763
|
+
matchedPath?: string;
|
|
764
|
+
matchedRule?: string;
|
|
765
|
+
ruleIndex?: number;
|
|
766
|
+
operations?: string[];
|
|
767
|
+
pathVariableBindings?: Record<string, string>;
|
|
768
|
+
reason?: string;
|
|
769
|
+
errorCode?: string;
|
|
770
|
+
};
|
|
771
|
+
request?: {
|
|
772
|
+
data?: unknown;
|
|
773
|
+
resourceData?: unknown;
|
|
774
|
+
query?: unknown;
|
|
775
|
+
};
|
|
776
|
+
resourceBefore?: {
|
|
777
|
+
data: unknown;
|
|
778
|
+
exists: boolean;
|
|
779
|
+
};
|
|
780
|
+
resourceAfter?: {
|
|
781
|
+
data: unknown;
|
|
782
|
+
exists: boolean;
|
|
783
|
+
};
|
|
784
|
+
groupId?: string;
|
|
785
|
+
groupKind?: 'batch' | 'transaction';
|
|
786
|
+
triggeredBy?: {
|
|
787
|
+
method: string;
|
|
788
|
+
path?: string;
|
|
789
|
+
};
|
|
790
|
+
detail?: Record<string, unknown>;
|
|
791
|
+
}
|
|
792
|
+
/**
|
|
793
|
+
* Canonical committed mutation event. Unlike `operation`, this fires only when
|
|
794
|
+
* state actually changed. Replay and branch tooling should eventually consume
|
|
795
|
+
* these service adapters instead of filtering Firestore-only `write` events.
|
|
796
|
+
*/
|
|
797
|
+
export interface SandboxCommitEvent {
|
|
798
|
+
kind: 'commit';
|
|
799
|
+
id: string;
|
|
800
|
+
at: number;
|
|
801
|
+
service: EventService;
|
|
802
|
+
method: string;
|
|
803
|
+
path?: string;
|
|
804
|
+
auth: AuthState;
|
|
805
|
+
data?: unknown;
|
|
806
|
+
priorState?: unknown;
|
|
807
|
+
nextState?: unknown;
|
|
808
|
+
groupId?: string;
|
|
809
|
+
groupKind?: 'batch' | 'transaction';
|
|
810
|
+
replay?: {
|
|
811
|
+
requestTime?: number;
|
|
812
|
+
autoId?: string;
|
|
813
|
+
sentinels?: Array<{
|
|
814
|
+
field: string;
|
|
815
|
+
kind: string;
|
|
816
|
+
}>;
|
|
817
|
+
};
|
|
818
|
+
detail?: Record<string, unknown>;
|
|
819
|
+
}
|
|
820
|
+
/**
|
|
821
|
+
* Canonical listener lifecycle/delivery event. Firestore's existing snapshot
|
|
822
|
+
* delivery/lifecycle variants are preserved; this shape gives RTDB and future
|
|
823
|
+
* service listeners the same debuggable surface.
|
|
824
|
+
*/
|
|
825
|
+
export interface SandboxListenerEvent {
|
|
826
|
+
kind: 'listener';
|
|
827
|
+
id: string;
|
|
828
|
+
at: number;
|
|
829
|
+
service: EventService;
|
|
830
|
+
phase: 'attach' | 'detach' | 'delivery' | 'suppressed' | 'errored';
|
|
831
|
+
listenerId: string;
|
|
832
|
+
target: {
|
|
833
|
+
kind: string;
|
|
834
|
+
path?: string;
|
|
835
|
+
query?: unknown;
|
|
836
|
+
};
|
|
837
|
+
auth: AuthState;
|
|
838
|
+
result?: 'allow' | 'deny' | 'unsupported' | 'error';
|
|
839
|
+
size?: number;
|
|
840
|
+
sample?: unknown;
|
|
841
|
+
reason?: string;
|
|
842
|
+
error?: {
|
|
843
|
+
code?: string;
|
|
844
|
+
message: string;
|
|
845
|
+
reasons?: string[];
|
|
846
|
+
};
|
|
847
|
+
triggeredBy?: {
|
|
848
|
+
method: string;
|
|
849
|
+
path?: string;
|
|
850
|
+
};
|
|
851
|
+
detail?: Record<string, unknown>;
|
|
852
|
+
}
|
|
853
|
+
/** Canonical non-rules operational failure. */
|
|
854
|
+
export interface SandboxRuntimeErrorEvent {
|
|
855
|
+
kind: 'runtime_error';
|
|
856
|
+
id: string;
|
|
857
|
+
at: number;
|
|
858
|
+
service: EventService;
|
|
859
|
+
method: string;
|
|
860
|
+
path?: string;
|
|
861
|
+
auth: AuthState;
|
|
862
|
+
error: {
|
|
863
|
+
code?: string;
|
|
864
|
+
message: string;
|
|
865
|
+
};
|
|
866
|
+
detail?: Record<string, unknown>;
|
|
867
|
+
}
|
|
868
|
+
/**
|
|
869
|
+
* Discriminated union of every event the sandbox emits to
|
|
870
|
+
* {@link Sandbox.onEvent} subscribers.
|
|
871
|
+
*
|
|
872
|
+
* Issue #307 — replaces the prior three-channel surface
|
|
873
|
+
* (`onRequest` / `onDenial` / `onSnapshotError`). Filter on `kind`
|
|
874
|
+
* to recover the subset each old channel covered:
|
|
875
|
+
* - request: `kind === 'request'`
|
|
876
|
+
* - denial: `kind === 'request' && result === 'deny'`
|
|
877
|
+
* - snapshotError: `kind === 'listener_errored'`
|
|
878
|
+
*
|
|
879
|
+
* See the design rationale for the
|
|
880
|
+
* field-by-field rationale.
|
|
881
|
+
*/
|
|
882
|
+
/**
|
|
883
|
+
* Which sandbox service emitted an event. Today only Firestore emits (events
|
|
884
|
+
* omit `service`, read as `'firestore'`); Pyric Studio's keystone track makes
|
|
885
|
+
* Auth/Storage/RTDB emit into this same stream. See the design rationale.
|
|
886
|
+
*/
|
|
887
|
+
export type EventService = 'firestore' | 'auth' | 'storage' | 'rtdb';
|
|
888
|
+
/** Who initiated the operation behind an event (Studio attributes activity to
|
|
889
|
+
* the human, the app, or a specific agent). Absent ⇒ the served app. */
|
|
890
|
+
export type EventActor = {
|
|
891
|
+
kind: 'app';
|
|
892
|
+
} | {
|
|
893
|
+
kind: 'studio';
|
|
894
|
+
} | {
|
|
895
|
+
kind: 'agent';
|
|
896
|
+
name: string;
|
|
897
|
+
} | {
|
|
898
|
+
kind: 'app-builder';
|
|
899
|
+
};
|
|
900
|
+
/**
|
|
901
|
+
* The auth lens an operation ran under: `admin` bypasses rules, `as` evaluates
|
|
902
|
+
* rules as a specific uid (impersonation — the rules-debugging primitive),
|
|
903
|
+
* `app-session` is the app's own signed-in user, and `anon` is a genuinely
|
|
904
|
+
* UNAUTHENTICATED context (`withAuth(null)` — `request.auth == null` in rules).
|
|
905
|
+
* Mirrors the worker's per-op `actAs`. Absent ⇒ `app-session`.
|
|
906
|
+
*
|
|
907
|
+
* `anon` vs absent matters for RELAYED ops (the remote sandbox): an op with no
|
|
908
|
+
* lens resolves to the browser tab's port session — whoever happens to be
|
|
909
|
+
* signed in in the tab. Remote code that means "no auth" must pin
|
|
910
|
+
* `{ mode: 'anon' }` explicitly, or it silently runs as the tab's user.
|
|
911
|
+
*/
|
|
912
|
+
export type AuthLens = {
|
|
913
|
+
mode: 'admin';
|
|
914
|
+
} | {
|
|
915
|
+
mode: 'as';
|
|
916
|
+
uid: string;
|
|
917
|
+
token?: Record<string, unknown>;
|
|
918
|
+
} | {
|
|
919
|
+
mode: 'app-session';
|
|
920
|
+
} | {
|
|
921
|
+
mode: 'anon';
|
|
922
|
+
};
|
|
923
|
+
/**
|
|
924
|
+
* Provenance carried by every {@link SandboxEvent}. All fields are OPTIONAL and
|
|
925
|
+
* additive: pre-provenance emitters omit them (treated as
|
|
926
|
+
* firestore / app / app-session), so nothing breaks. The Pyric Studio event
|
|
927
|
+
* unification track stamps them at emit across all services, which is what
|
|
928
|
+
* turns the log into "who did what" (Action Center, audit, agent attribution).
|
|
929
|
+
*/
|
|
930
|
+
export interface EventProvenance {
|
|
931
|
+
service?: EventService;
|
|
932
|
+
actor?: EventActor;
|
|
933
|
+
authLens?: AuthLens;
|
|
934
|
+
/** Set when the op is part of an agent plan (Pyric Agent dry-run / accept). */
|
|
935
|
+
planId?: string;
|
|
936
|
+
}
|
|
937
|
+
export type SandboxEvent = (RequestEvent | WriteSandboxEvent | SnapshotDeliveryEvent | SnapshotSuppressedEvent | ListenerLifecycleEvent | SessionBoundaryEvent | ServiceMutationEvent | SandboxOperationEvent | SandboxCommitEvent | SandboxListenerEvent | SandboxRuntimeErrorEvent) & EventProvenance;
|
|
938
|
+
/**
|
|
939
|
+
* The data + rules + lifecycle foundation. **Identity-agnostic** —
|
|
940
|
+
* operations through services attached to a `Sandbox` always go via a
|
|
941
|
+
* {@link SandboxContext} that names the auth identity for that
|
|
942
|
+
* operation. Multiple contexts can share one sandbox.
|
|
943
|
+
*
|
|
944
|
+
* Mental model: sandboxes hold the data, contexts carry identity,
|
|
945
|
+
* services attach via factories. See
|
|
946
|
+
* the design rationale for the design rationale.
|
|
947
|
+
*/
|
|
948
|
+
export interface Sandbox {
|
|
949
|
+
/**
|
|
950
|
+
* Derive a context bound to this sandbox under the given auth
|
|
951
|
+
* identity. Operations through services attached to the returned
|
|
952
|
+
* context evaluate rules under that identity. Many contexts can
|
|
953
|
+
* coexist for one sandbox; data is shared.
|
|
954
|
+
*
|
|
955
|
+
* `null` is anonymous; an `AuthState` object names the user (and
|
|
956
|
+
* optional custom claims). Passing `undefined` is a deliberate
|
|
957
|
+
* error — say `withAuth(null)` for anonymous so the call site is
|
|
958
|
+
* unambiguous.
|
|
959
|
+
*
|
|
960
|
+
* @example
|
|
961
|
+
* ```ts
|
|
962
|
+
* const sandbox = initializeSandbox();
|
|
963
|
+
* const dbAlice = getFirestore(sandbox.withAuth({ uid: 'alice' }));
|
|
964
|
+
* const dbAnon = getFirestore(sandbox.withAuth(null));
|
|
965
|
+
* ```
|
|
966
|
+
*/
|
|
967
|
+
withAuth(auth: AuthState): SandboxContext;
|
|
968
|
+
/**
|
|
969
|
+
* Subscribe to every event the sandbox emits — see {@link SandboxEvent}
|
|
970
|
+
* for the discriminated-union shape. One subscription covers
|
|
971
|
+
* request/denial/snapshot-error/listener-lifecycle/session-boundary;
|
|
972
|
+
* filter on `event.kind` to recover individual streams.
|
|
973
|
+
*
|
|
974
|
+
* Replaces the prior three-channel surface (`onRequest` / `onDenial`
|
|
975
|
+
* / `onSnapshotError`) — see issue #307. Filter cookbook:
|
|
976
|
+
* - All denials: `event.kind === 'request' && event.result === 'deny'`
|
|
977
|
+
* - Stream errors: `event.kind === 'listener_errored'`
|
|
978
|
+
* - Per-op traffic: `event.kind === 'request'`
|
|
979
|
+
*
|
|
980
|
+
* Survives `sandbox.reset()` — the subscription is held on the
|
|
981
|
+
* sandbox, not on the underlying environment. A `session_boundary`
|
|
982
|
+
* event with `phase: 'reset'` fires before the env swap so consumers
|
|
983
|
+
* can segment their stream.
|
|
984
|
+
*
|
|
985
|
+
* Returns an unsubscribe function. Listener errors are swallowed so a
|
|
986
|
+
* faulty subscriber can't change rule semantics or hide other events.
|
|
987
|
+
* Both synchronous throws and rejected Promises from async callbacks
|
|
988
|
+
* are silently discarded — subscribers are **observational**, the
|
|
989
|
+
* sandbox doesn't await them and doesn't propagate their errors.
|
|
990
|
+
*/
|
|
991
|
+
onEvent(cb: (event: SandboxEvent) => void): () => void;
|
|
992
|
+
/**
|
|
993
|
+
* Run `fn` with ambient {@link EventProvenance} defaults: every event
|
|
994
|
+
* emitted SYNCHRONOUSLY during `fn` that doesn't already carry a
|
|
995
|
+
* provenance field (on the event itself or via an explicit per-emit
|
|
996
|
+
* override) is stamped with these values instead of the global
|
|
997
|
+
* defaults. This is the mechanical "who issued this op" seam the
|
|
998
|
+
* serve worker uses to tag Studio-issued ops (`actor: { kind:
|
|
999
|
+
* 'studio' }`) and to stamp the auth lens an op ran under
|
|
1000
|
+
* (`authLens`) — declared by the caller that issues the op, never
|
|
1001
|
+
* inferred from the op's shape.
|
|
1002
|
+
*
|
|
1003
|
+
* SYNCHRONOUS WINDOW: the ambient values apply only until `fn`
|
|
1004
|
+
* returns (for an async `fn`, its synchronous prefix — which covers
|
|
1005
|
+
* the local environment's rules eval + event emission, since those
|
|
1006
|
+
* run before the op's promise is handed back). Work an op DEFERS
|
|
1007
|
+
* (snapshot-listener deliveries and re-evals drain on a microtask,
|
|
1008
|
+
* off-stack) is intentionally OUTSIDE the window: a listener re-eval
|
|
1009
|
+
* belongs to the listener's owner, not to whoever's write triggered
|
|
1010
|
+
* it. Nested calls stack — the innermost window wins per field, and
|
|
1011
|
+
* each window restores the previous one on exit (including on throw).
|
|
1012
|
+
*
|
|
1013
|
+
* OPTIONAL because remote sandbox proxies can't provide an ambient
|
|
1014
|
+
* emit window (events are emitted in the worker they front). Callers
|
|
1015
|
+
* spell `sandbox.runWithProvenance?.(prov, fn) ?? fn()`.
|
|
1016
|
+
*/
|
|
1017
|
+
runWithProvenance?<T>(provenance: EventProvenance, fn: () => T): T;
|
|
1018
|
+
/**
|
|
1019
|
+
* Every {@link SandboxEvent} this sandbox has emitted since init or
|
|
1020
|
+
* the last `reset()`. Returns a defensive copy.
|
|
1021
|
+
*
|
|
1022
|
+
* Use this for replay: hand the array to `replay(events, rules)`
|
|
1023
|
+
* from `pyric/sandbox` and the engine re-issues every
|
|
1024
|
+
* captured write against a fresh sandbox.
|
|
1025
|
+
*
|
|
1026
|
+
* Unlike {@link onEvent} (live stream from the moment of subscribe),
|
|
1027
|
+
* `history()` returns *every* event the sandbox has seen — useful
|
|
1028
|
+
* for consumers that attach late (e.g., loading a saved session
|
|
1029
|
+
* before subscribing) or that need a snapshot at a particular moment.
|
|
1030
|
+
*
|
|
1031
|
+
* `reset()` and `dispose()` each append a closing `session_boundary`
|
|
1032
|
+
* event; `reset()` then clears the history. Consumers that took a
|
|
1033
|
+
* snapshot *before* reset retain the boundary in their copy.
|
|
1034
|
+
*/
|
|
1035
|
+
history(): SandboxEvent[];
|
|
1036
|
+
/**
|
|
1037
|
+
* Admin-plane access (rule-bypass reads). Identity-agnostic by
|
|
1038
|
+
* design — admin reads aren't gated on auth, so they live on the
|
|
1039
|
+
* sandbox, not on a context. See {@link SandboxAdmin}.
|
|
1040
|
+
*/
|
|
1041
|
+
readonly admin: SandboxAdmin;
|
|
1042
|
+
/**
|
|
1043
|
+
* Reset the underlying environment to a fresh state — wipes data,
|
|
1044
|
+
* rules, and any service-specific configuration.
|
|
1045
|
+
*
|
|
1046
|
+
* Snapshot listeners attached to the OLD environment are dropped at
|
|
1047
|
+
* the swap — they can't survive because their target docs have been
|
|
1048
|
+
* wiped. `onEvent` subscribers DO survive — the registry lives on
|
|
1049
|
+
* the sandbox, and a `session_boundary` event with `phase: 'reset'`
|
|
1050
|
+
* fires before the swap so subscribers know the rollover happened.
|
|
1051
|
+
* Existing {@link SandboxContext}s continue to work — their sandbox
|
|
1052
|
+
* reference is stable; subsequent operations resolve to the new env.
|
|
1053
|
+
*/
|
|
1054
|
+
reset(): void;
|
|
1055
|
+
/**
|
|
1056
|
+
* Tear down listener registries on this sandbox's environment without
|
|
1057
|
+
* replacing it. Use this when you're about to discard the sandbox
|
|
1058
|
+
* itself (e.g. `runner.reseed()` builds a fresh sandbox rather than
|
|
1059
|
+
* calling `reset()`) and want to drop callback references on the
|
|
1060
|
+
* outgoing instance defensively. Idempotent. Does not touch data.
|
|
1061
|
+
*/
|
|
1062
|
+
dispose(): void;
|
|
1063
|
+
/**
|
|
1064
|
+
* Capture a snapshot of every service's state. For v1 with only
|
|
1065
|
+
* Firestore, the return value carries a `firestore` key mapping doc
|
|
1066
|
+
* paths to data. Future services will add their own keys.
|
|
1067
|
+
*/
|
|
1068
|
+
snapshot(): SandboxSnapshot;
|
|
1069
|
+
/**
|
|
1070
|
+
* CLOBBER-restore the sandbox's entire state from a prior {@link snapshot}:
|
|
1071
|
+
* `reset()` (clears firestore + the signed-in session), then rebuild firestore
|
|
1072
|
+
* from `data` and restore each registered service. This is a TOTAL replace —
|
|
1073
|
+
* documents absent from `data` do NOT survive — and is the counterpart to
|
|
1074
|
+
* {@link snapshot}. It is what makes "transfer (clobber) one instance's data
|
|
1075
|
+
* into another" and named-branch switching possible.
|
|
1076
|
+
*
|
|
1077
|
+
* Fires a `session_boundary` (reset phase), re-evaluates live listeners against
|
|
1078
|
+
* the loaded state, and the next persistence flush writes the loaded state.
|
|
1079
|
+
* Services present in `data` but not currently registered are skipped (a
|
|
1080
|
+
* snapshot taken via {@link snapshot} always includes every registered
|
|
1081
|
+
* service, so this only affects cross-instance imports from a sandbox that had
|
|
1082
|
+
* a service this one lacks).
|
|
1083
|
+
*/
|
|
1084
|
+
loadSnapshot(data: SandboxSnapshot): void;
|
|
1085
|
+
/**
|
|
1086
|
+
* Current authenticated user across the sandbox.
|
|
1087
|
+
*
|
|
1088
|
+
* Mutated by `pyric/auth`'s `signInAnonymously` /
|
|
1089
|
+
* `signInWithEmailAndPassword` / `signOut` / `sandbox.setUser`. Read
|
|
1090
|
+
* per-call by service factories (e.g. a future
|
|
1091
|
+
* `getFirestore(sandbox)` overload) so they see auth state changes
|
|
1092
|
+
* without re-binding handles. Defaults to `null` (anonymous /
|
|
1093
|
+
* signed out).
|
|
1094
|
+
*
|
|
1095
|
+
* **Independent of `withAuth({uid})`** — `withAuth` still produces a
|
|
1096
|
+
* frozen {@link SandboxContext} that carries its own identity for
|
|
1097
|
+
* the runner's test code (the existing pattern: explicit identity
|
|
1098
|
+
* per service call). `currentUser` exists for the `pyric/auth`
|
|
1099
|
+
* mirror, where consumer app code drives identity through a
|
|
1100
|
+
* stateful `Auth` handle rather than naming it per call.
|
|
1101
|
+
*/
|
|
1102
|
+
currentUser: AuthState;
|
|
1103
|
+
/**
|
|
1104
|
+
* Subscribe to `currentUser` changes. Fires on every mutation —
|
|
1105
|
+
* sign-in, sign-out, user swap. Does NOT fire on subscribe.
|
|
1106
|
+
*
|
|
1107
|
+
* Survives `reset()` and `dispose()` only as a no-op: a disposed
|
|
1108
|
+
* sandbox emits nothing further; a reset sandbox clears
|
|
1109
|
+
* `currentUser` to `null` (and fires the change) before swapping
|
|
1110
|
+
* the env.
|
|
1111
|
+
*
|
|
1112
|
+
* Returns an unsubscribe function. Listener errors are swallowed —
|
|
1113
|
+
* subscribers are observational, the sandbox does not propagate
|
|
1114
|
+
* their errors.
|
|
1115
|
+
*/
|
|
1116
|
+
onCurrentUserChanged(cb: (user: AuthState) => void): () => void;
|
|
1117
|
+
/**
|
|
1118
|
+
* Enable cross-tab realtime sync via `BroadcastChannel`. A write in
|
|
1119
|
+
* this tab will propagate to every OTHER tab of the same origin that
|
|
1120
|
+
* also called `enableTabSync`, causing their `onSnapshot` listeners to
|
|
1121
|
+
* re-evaluate — restoring production's cross-client realtime behavior.
|
|
1122
|
+
*
|
|
1123
|
+
* **Opt-in, OFF by default.** Firestore only (RTDB is a follow-on).
|
|
1124
|
+
*
|
|
1125
|
+
* Returns a disable function. Calling it removes the `onEvent`
|
|
1126
|
+
* subscription, the channel message listener, and closes the channel
|
|
1127
|
+
* (when it was created internally). After disable, no further propagation
|
|
1128
|
+
* occurs in either direction.
|
|
1129
|
+
*
|
|
1130
|
+
* **Multi-writer note:** concurrent writes from two tabs to the same doc
|
|
1131
|
+
* produce last-write-wins divergence — there is no conflict resolution.
|
|
1132
|
+
* The intended model is one active writer (one user, one tab) with
|
|
1133
|
+
* observers in other tabs; this covers the overwhelming majority of
|
|
1134
|
+
* local development scenarios.
|
|
1135
|
+
*
|
|
1136
|
+
* @see {@link TabSyncOptions} for channel injection (tests) and originId.
|
|
1137
|
+
*
|
|
1138
|
+
* @example
|
|
1139
|
+
* ```ts
|
|
1140
|
+
* // In every tab that should participate in realtime:
|
|
1141
|
+
* const sandbox = initializeSandbox();
|
|
1142
|
+
* const disableSync = sandbox.enableTabSync();
|
|
1143
|
+
* // Later, to stop syncing:
|
|
1144
|
+
* disableSync();
|
|
1145
|
+
* ```
|
|
1146
|
+
*/
|
|
1147
|
+
enableTabSync(options?: TabSyncOptions): () => void;
|
|
1148
|
+
/**
|
|
1149
|
+
* Persist the sandbox's data to a backend and restore it on next
|
|
1150
|
+
* `enablePersistence` call. The default `'indexedDB'` backend turns
|
|
1151
|
+
* the sandbox into the host page's local Firestore — writes flush
|
|
1152
|
+
* automatically and a fresh `initializeSandbox()` rehydrates from
|
|
1153
|
+
* the prior session.
|
|
1154
|
+
*
|
|
1155
|
+
* Restoration happens before the promise resolves; awaiting this
|
|
1156
|
+
* call is sufficient to guarantee in-memory state matches the
|
|
1157
|
+
* persisted blob.
|
|
1158
|
+
*
|
|
1159
|
+
* Idempotent across the same `key` — calling twice in one process
|
|
1160
|
+
* is a no-op on the second call. Different keys are rejected as an
|
|
1161
|
+
* error (a sandbox can persist to at most one backend at a time).
|
|
1162
|
+
*
|
|
1163
|
+
* Listener semantics: every write event the sandbox emits triggers
|
|
1164
|
+
* a debounced flush (default 250ms). Browser hosts additionally
|
|
1165
|
+
* flush on `beforeunload` so a page navigation doesn't lose the
|
|
1166
|
+
* tail of the debounce window.
|
|
1167
|
+
*
|
|
1168
|
+
* See {@link SandboxPersistenceOptions} for backend selection and
|
|
1169
|
+
* tuning.
|
|
1170
|
+
*/
|
|
1171
|
+
enablePersistence(options: SandboxPersistenceOptions): Promise<void>;
|
|
1172
|
+
/**
|
|
1173
|
+
* Force a snapshot to the configured persistence backend right now.
|
|
1174
|
+
* Useful before a manual navigation, or in tests that need
|
|
1175
|
+
* deterministic ordering against the debounce window. Resolves once
|
|
1176
|
+
* the write hits the backend.
|
|
1177
|
+
*
|
|
1178
|
+
* Throws if persistence is not enabled.
|
|
1179
|
+
*/
|
|
1180
|
+
flush(): Promise<void>;
|
|
1181
|
+
/**
|
|
1182
|
+
* Wipe the persisted blob for this sandbox's `key`. In-memory state
|
|
1183
|
+
* is left intact — call `reset()` if you want both. Useful for
|
|
1184
|
+
* "sign out and forget" flows.
|
|
1185
|
+
*
|
|
1186
|
+
* No-op when persistence is not enabled.
|
|
1187
|
+
*/
|
|
1188
|
+
clearPersistence(): Promise<void>;
|
|
1189
|
+
/**
|
|
1190
|
+
* Register a service (auth, storage, …) as a persistence participant.
|
|
1191
|
+
* The sandbox calls `hooks.snapshot()` on every flush and
|
|
1192
|
+
* `hooks.restore(data)` on restore. If `hooks.subscribe` is provided,
|
|
1193
|
+
* the persistence controller subscribes and schedules a debounced
|
|
1194
|
+
* flush on each change — so auth-user edits flush promptly, not only
|
|
1195
|
+
* on the next Firestore write.
|
|
1196
|
+
*
|
|
1197
|
+
* Returns an unregister function — call it if the service is torn
|
|
1198
|
+
* down before the sandbox is disposed (uncommon in practice; the
|
|
1199
|
+
* sandbox's `dispose()` clears the registry anyway).
|
|
1200
|
+
*
|
|
1201
|
+
* Throws `failed-precondition` when a service with the same `name` is
|
|
1202
|
+
* already registered — the auth package registers `'auth'` once when
|
|
1203
|
+
* `getAuth(sandbox)` first creates a backend, so accidental double-
|
|
1204
|
+
* registration is a caller bug, not a no-op.
|
|
1205
|
+
*
|
|
1206
|
+
* **Advanced / internal API.** Service packages (auth, storage) call
|
|
1207
|
+
* this when they first attach to a sandbox. Consumer app code should
|
|
1208
|
+
* not need to call this directly.
|
|
1209
|
+
*/
|
|
1210
|
+
registerPersistableService(name: string, hooks: PersistableService): () => void;
|
|
1211
|
+
}
|
|
1212
|
+
/**
|
|
1213
|
+
* Identity-bearing handle on a {@link Sandbox}. A `(sandbox, auth)`
|
|
1214
|
+
* pair — cheap to create, immutable, freely shareable. Service
|
|
1215
|
+
* factories require a `SandboxContext`; bare `Sandbox` is a type
|
|
1216
|
+
* error so every call site states identity explicitly.
|
|
1217
|
+
*
|
|
1218
|
+
* Constructed via `Sandbox.withAuth(auth)` or chained via
|
|
1219
|
+
* `SandboxContext.withAuth(auth)`. The concrete class is exported
|
|
1220
|
+
* from `pyric/sandbox` for `instanceof` routing in service
|
|
1221
|
+
* factories; consumers don't construct it directly.
|
|
1222
|
+
*/
|
|
1223
|
+
export interface SandboxContext {
|
|
1224
|
+
/** The data foundation this context operates against. */
|
|
1225
|
+
readonly sandbox: Sandbox;
|
|
1226
|
+
/** The identity rules evaluate under for operations through this context. */
|
|
1227
|
+
readonly auth: AuthState;
|
|
1228
|
+
/**
|
|
1229
|
+
* Derive a sibling context on the same sandbox with different auth.
|
|
1230
|
+
* Replaces, doesn't merge — the new context carries only the new
|
|
1231
|
+
* auth, regardless of any prior context's auth.
|
|
1232
|
+
*/
|
|
1233
|
+
withAuth(auth: AuthState): SandboxContext;
|
|
1234
|
+
}
|
|
1235
|
+
//# sourceMappingURL=types.d.ts.map
|