pyric 0.0.1 → 0.1.0-alpha.10

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.
Files changed (1204) hide show
  1. package/LICENSE +216 -0
  2. package/README.md +179 -2
  3. package/README.md.orig +54 -0
  4. package/dist/ai/backend.d.ts +35 -0
  5. package/dist/ai/backend.d.ts.map +1 -0
  6. package/dist/ai/backend.js +42 -0
  7. package/dist/ai/backend.js.map +1 -0
  8. package/dist/ai/broker/broker.d.ts +65 -0
  9. package/dist/ai/broker/broker.d.ts.map +1 -0
  10. package/dist/ai/broker/broker.js +184 -0
  11. package/dist/ai/broker/broker.js.map +1 -0
  12. package/dist/ai/broker/index.d.ts +12 -0
  13. package/dist/ai/broker/index.d.ts.map +1 -0
  14. package/dist/ai/broker/index.js +11 -0
  15. package/dist/ai/broker/index.js.map +1 -0
  16. package/dist/ai/broker/openai-engine.d.ts +175 -0
  17. package/dist/ai/broker/openai-engine.d.ts.map +1 -0
  18. package/dist/ai/broker/openai-engine.js +502 -0
  19. package/dist/ai/broker/openai-engine.js.map +1 -0
  20. package/dist/ai/broker/scripted-engine.d.ts +44 -0
  21. package/dist/ai/broker/scripted-engine.d.ts.map +1 -0
  22. package/dist/ai/broker/scripted-engine.js +218 -0
  23. package/dist/ai/broker/scripted-engine.js.map +1 -0
  24. package/dist/ai/broker/synthesizer.d.ts +100 -0
  25. package/dist/ai/broker/synthesizer.d.ts.map +1 -0
  26. package/dist/ai/broker/synthesizer.js +278 -0
  27. package/dist/ai/broker/synthesizer.js.map +1 -0
  28. package/dist/ai/broker/types.d.ts +210 -0
  29. package/dist/ai/broker/types.d.ts.map +1 -0
  30. package/dist/ai/broker/types.js +20 -0
  31. package/dist/ai/broker/types.js.map +1 -0
  32. package/dist/ai/enums.d.ts +174 -0
  33. package/dist/ai/enums.d.ts.map +1 -0
  34. package/dist/ai/enums.js +155 -0
  35. package/dist/ai/enums.js.map +1 -0
  36. package/dist/ai/errors.d.ts +66 -0
  37. package/dist/ai/errors.d.ts.map +1 -0
  38. package/dist/ai/errors.js +100 -0
  39. package/dist/ai/errors.js.map +1 -0
  40. package/dist/ai/index.d.ts +31 -0
  41. package/dist/ai/index.d.ts.map +1 -0
  42. package/dist/ai/index.js +27 -0
  43. package/dist/ai/index.js.map +1 -0
  44. package/dist/ai/instances.d.ts +15 -0
  45. package/dist/ai/instances.d.ts.map +1 -0
  46. package/dist/ai/instances.js +69 -0
  47. package/dist/ai/instances.js.map +1 -0
  48. package/dist/ai/internal.d.ts +13 -0
  49. package/dist/ai/internal.d.ts.map +1 -0
  50. package/dist/ai/internal.js +45 -0
  51. package/dist/ai/internal.js.map +1 -0
  52. package/dist/ai/models.d.ts +116 -0
  53. package/dist/ai/models.d.ts.map +1 -0
  54. package/dist/ai/models.js +213 -0
  55. package/dist/ai/models.js.map +1 -0
  56. package/dist/ai/request-helpers.d.ts +59 -0
  57. package/dist/ai/request-helpers.d.ts.map +1 -0
  58. package/dist/ai/request-helpers.js +157 -0
  59. package/dist/ai/request-helpers.js.map +1 -0
  60. package/dist/ai/response-helpers.d.ts +41 -0
  61. package/dist/ai/response-helpers.d.ts.map +1 -0
  62. package/dist/ai/response-helpers.js +204 -0
  63. package/dist/ai/response-helpers.js.map +1 -0
  64. package/dist/ai/sandbox-plane.d.ts +41 -0
  65. package/dist/ai/sandbox-plane.d.ts.map +1 -0
  66. package/dist/ai/sandbox-plane.js +159 -0
  67. package/dist/ai/sandbox-plane.js.map +1 -0
  68. package/dist/ai/schema.d.ts +105 -0
  69. package/dist/ai/schema.d.ts.map +1 -0
  70. package/dist/ai/schema.js +174 -0
  71. package/dist/ai/schema.js.map +1 -0
  72. package/dist/ai/scripting.d.ts +53 -0
  73. package/dist/ai/scripting.d.ts.map +1 -0
  74. package/dist/ai/scripting.js +73 -0
  75. package/dist/ai/scripting.js.map +1 -0
  76. package/dist/ai/target.d.ts +20 -0
  77. package/dist/ai/target.d.ts.map +1 -0
  78. package/dist/ai/target.js +29 -0
  79. package/dist/ai/target.js.map +1 -0
  80. package/dist/ai/types.d.ts +400 -0
  81. package/dist/ai/types.d.ts.map +1 -0
  82. package/dist/ai/types.js +10 -0
  83. package/dist/ai/types.js.map +1 -0
  84. package/dist/app/diagnostics.d.ts +29 -0
  85. package/dist/app/diagnostics.d.ts.map +1 -0
  86. package/dist/app/diagnostics.js +88 -0
  87. package/dist/app/diagnostics.js.map +1 -0
  88. package/dist/app/index.d.ts +7 -0
  89. package/dist/app/index.d.ts.map +1 -0
  90. package/dist/app/index.js +5 -0
  91. package/dist/app/index.js.map +1 -0
  92. package/dist/app/internal.d.ts +11 -0
  93. package/dist/app/internal.d.ts.map +1 -0
  94. package/dist/app/internal.js +18 -0
  95. package/dist/app/internal.js.map +1 -0
  96. package/dist/app/options.d.ts +3 -0
  97. package/dist/app/options.d.ts.map +1 -0
  98. package/dist/app/options.js +19 -0
  99. package/dist/app/options.js.map +1 -0
  100. package/dist/app/register.d.ts +4 -0
  101. package/dist/app/register.d.ts.map +1 -0
  102. package/dist/app/register.js +35 -0
  103. package/dist/app/register.js.map +1 -0
  104. package/dist/app/registry.d.ts +12 -0
  105. package/dist/app/registry.d.ts.map +1 -0
  106. package/dist/app/registry.js +147 -0
  107. package/dist/app/registry.js.map +1 -0
  108. package/dist/app/runtime.d.ts +18 -0
  109. package/dist/app/runtime.d.ts.map +1 -0
  110. package/dist/app/runtime.js +119 -0
  111. package/dist/app/runtime.js.map +1 -0
  112. package/dist/app/types.d.ts +21 -0
  113. package/dist/app/types.d.ts.map +1 -0
  114. package/dist/app/types.js +2 -0
  115. package/dist/app/types.js.map +1 -0
  116. package/dist/auth/action-code-url.d.ts +70 -0
  117. package/dist/auth/action-code-url.d.ts.map +1 -0
  118. package/dist/auth/action-code-url.js +124 -0
  119. package/dist/auth/action-code-url.js.map +1 -0
  120. package/dist/auth/action-codes.d.ts +201 -0
  121. package/dist/auth/action-codes.d.ts.map +1 -0
  122. package/dist/auth/action-codes.js +355 -0
  123. package/dist/auth/action-codes.js.map +1 -0
  124. package/dist/auth/auth-errors.d.ts +21 -0
  125. package/dist/auth/auth-errors.d.ts.map +1 -0
  126. package/dist/auth/auth-errors.js +23 -0
  127. package/dist/auth/auth-errors.js.map +1 -0
  128. package/dist/auth/config-tokens.d.ts +90 -0
  129. package/dist/auth/config-tokens.d.ts.map +1 -0
  130. package/dist/auth/config-tokens.js +86 -0
  131. package/dist/auth/config-tokens.js.map +1 -0
  132. package/dist/auth/credentials.d.ts +140 -0
  133. package/dist/auth/credentials.d.ts.map +1 -0
  134. package/dist/auth/credentials.js +194 -0
  135. package/dist/auth/credentials.js.map +1 -0
  136. package/dist/auth/email-link.d.ts +91 -0
  137. package/dist/auth/email-link.d.ts.map +1 -0
  138. package/dist/auth/email-link.js +172 -0
  139. package/dist/auth/email-link.js.map +1 -0
  140. package/dist/auth/enums.d.ts +210 -0
  141. package/dist/auth/enums.d.ts.map +1 -0
  142. package/dist/auth/enums.js +206 -0
  143. package/dist/auth/enums.js.map +1 -0
  144. package/dist/auth/index.d.ts +3 -0
  145. package/dist/auth/index.d.ts.map +1 -0
  146. package/dist/auth/index.js +3 -0
  147. package/dist/auth/index.js.map +1 -0
  148. package/dist/auth/instances.d.ts +14 -0
  149. package/dist/auth/instances.d.ts.map +1 -0
  150. package/dist/auth/instances.js +95 -0
  151. package/dist/auth/instances.js.map +1 -0
  152. package/dist/auth/linking.d.ts +93 -0
  153. package/dist/auth/linking.d.ts.map +1 -0
  154. package/dist/auth/linking.js +189 -0
  155. package/dist/auth/linking.js.map +1 -0
  156. package/dist/auth/modular.d.ts +22 -0
  157. package/dist/auth/modular.d.ts.map +1 -0
  158. package/dist/auth/modular.js +18 -0
  159. package/dist/auth/modular.js.map +1 -0
  160. package/dist/auth/password-policy.d.ts +60 -0
  161. package/dist/auth/password-policy.d.ts.map +1 -0
  162. package/dist/auth/password-policy.js +68 -0
  163. package/dist/auth/password-policy.js.map +1 -0
  164. package/dist/auth/providers.d.ts +153 -0
  165. package/dist/auth/providers.d.ts.map +1 -0
  166. package/dist/auth/providers.js +207 -0
  167. package/dist/auth/providers.js.map +1 -0
  168. package/dist/auth/reauth.d.ts +73 -0
  169. package/dist/auth/reauth.d.ts.map +1 -0
  170. package/dist/auth/reauth.js +148 -0
  171. package/dist/auth/reauth.js.map +1 -0
  172. package/dist/auth/sandbox/driver.d.ts +51 -0
  173. package/dist/auth/sandbox/driver.d.ts.map +1 -0
  174. package/dist/auth/sandbox/driver.js +88 -0
  175. package/dist/auth/sandbox/driver.js.map +1 -0
  176. package/dist/auth/sandbox/persistence.d.ts +7 -0
  177. package/dist/auth/sandbox/persistence.d.ts.map +1 -0
  178. package/dist/auth/sandbox/persistence.js +121 -0
  179. package/dist/auth/sandbox/persistence.js.map +1 -0
  180. package/dist/auth/sandbox/project-store.d.ts +15 -0
  181. package/dist/auth/sandbox/project-store.d.ts.map +1 -0
  182. package/dist/auth/sandbox/project-store.js +17 -0
  183. package/dist/auth/sandbox/project-store.js.map +1 -0
  184. package/dist/auth/sandbox-auth-flow.d.ts +173 -0
  185. package/dist/auth/sandbox-auth-flow.d.ts.map +1 -0
  186. package/dist/auth/sandbox-auth-flow.js +165 -0
  187. package/dist/auth/sandbox-auth-flow.js.map +1 -0
  188. package/dist/auth/sandbox-backend-types.d.ts +197 -0
  189. package/dist/auth/sandbox-backend-types.d.ts.map +1 -0
  190. package/dist/auth/sandbox-backend-types.js +18 -0
  191. package/dist/auth/sandbox-backend-types.js.map +1 -0
  192. package/dist/auth/sandbox-backend.d.ts +811 -0
  193. package/dist/auth/sandbox-backend.d.ts.map +1 -0
  194. package/dist/auth/sandbox-backend.js +2007 -0
  195. package/dist/auth/sandbox-backend.js.map +1 -0
  196. package/dist/auth/sandbox-credential-validators.d.ts +30 -0
  197. package/dist/auth/sandbox-credential-validators.d.ts.map +1 -0
  198. package/dist/auth/sandbox-credential-validators.js +47 -0
  199. package/dist/auth/sandbox-credential-validators.js.map +1 -0
  200. package/dist/auth/sandbox-token.d.ts +24 -0
  201. package/dist/auth/sandbox-token.d.ts.map +1 -0
  202. package/dist/auth/sandbox-token.js +32 -0
  203. package/dist/auth/sandbox-token.js.map +1 -0
  204. package/dist/auth/sign-in.d.ts +14 -0
  205. package/dist/auth/sign-in.d.ts.map +1 -0
  206. package/dist/auth/sign-in.js +140 -0
  207. package/dist/auth/sign-in.js.map +1 -0
  208. package/dist/auth/target.d.ts +29 -0
  209. package/dist/auth/target.d.ts.map +1 -0
  210. package/dist/auth/target.js +23 -0
  211. package/dist/auth/target.js.map +1 -0
  212. package/dist/auth/tokens.d.ts +54 -0
  213. package/dist/auth/tokens.d.ts.map +1 -0
  214. package/dist/auth/tokens.js +142 -0
  215. package/dist/auth/tokens.js.map +1 -0
  216. package/dist/auth/types.d.ts +283 -0
  217. package/dist/auth/types.d.ts.map +1 -0
  218. package/dist/auth/types.js +24 -0
  219. package/dist/auth/types.js.map +1 -0
  220. package/dist/auth/user-lifecycle.d.ts +17 -0
  221. package/dist/auth/user-lifecycle.d.ts.map +1 -0
  222. package/dist/auth/user-lifecycle.js +60 -0
  223. package/dist/auth/user-lifecycle.js.map +1 -0
  224. package/dist/database/index.d.ts +9 -0
  225. package/dist/database/index.d.ts.map +1 -0
  226. package/dist/database/index.js +9 -0
  227. package/dist/database/index.js.map +1 -0
  228. package/dist/database/listener-registry.d.ts +16 -0
  229. package/dist/database/listener-registry.d.ts.map +1 -0
  230. package/dist/database/listener-registry.js +68 -0
  231. package/dist/database/listener-registry.js.map +1 -0
  232. package/dist/database/modular.d.ts +632 -0
  233. package/dist/database/modular.d.ts.map +1 -0
  234. package/dist/database/modular.js +1071 -0
  235. package/dist/database/modular.js.map +1 -0
  236. package/dist/database/replay.d.ts +32 -0
  237. package/dist/database/replay.d.ts.map +1 -0
  238. package/dist/database/replay.js +124 -0
  239. package/dist/database/replay.js.map +1 -0
  240. package/dist/database/sandbox/backend-for.d.ts +10 -0
  241. package/dist/database/sandbox/backend-for.d.ts.map +1 -0
  242. package/dist/database/sandbox/backend-for.js +19 -0
  243. package/dist/database/sandbox/backend-for.js.map +1 -0
  244. package/dist/database/sandbox/backend.d.ts +407 -0
  245. package/dist/database/sandbox/backend.d.ts.map +1 -0
  246. package/dist/database/sandbox/backend.js +1495 -0
  247. package/dist/database/sandbox/backend.js.map +1 -0
  248. package/dist/database/sandbox/data-tree.d.ts +123 -0
  249. package/dist/database/sandbox/data-tree.d.ts.map +1 -0
  250. package/dist/database/sandbox/data-tree.js +310 -0
  251. package/dist/database/sandbox/data-tree.js.map +1 -0
  252. package/dist/database/sandbox/normalize.d.ts +77 -0
  253. package/dist/database/sandbox/normalize.d.ts.map +1 -0
  254. package/dist/database/sandbox/normalize.js +165 -0
  255. package/dist/database/sandbox/normalize.js.map +1 -0
  256. package/dist/database/sandbox/push-id.d.ts +32 -0
  257. package/dist/database/sandbox/push-id.d.ts.map +1 -0
  258. package/dist/database/sandbox/push-id.js +82 -0
  259. package/dist/database/sandbox/push-id.js.map +1 -0
  260. package/dist/database/sandbox/query.d.ts +175 -0
  261. package/dist/database/sandbox/query.d.ts.map +1 -0
  262. package/dist/database/sandbox/query.js +269 -0
  263. package/dist/database/sandbox/query.js.map +1 -0
  264. package/dist/database/sandbox/rules-eval.d.ts +87 -0
  265. package/dist/database/sandbox/rules-eval.d.ts.map +1 -0
  266. package/dist/database/sandbox/rules-eval.js +131 -0
  267. package/dist/database/sandbox/rules-eval.js.map +1 -0
  268. package/dist/database/sandbox/sentinels.d.ts +71 -0
  269. package/dist/database/sandbox/sentinels.d.ts.map +1 -0
  270. package/dist/database/sandbox/sentinels.js +92 -0
  271. package/dist/database/sandbox/sentinels.js.map +1 -0
  272. package/dist/database/sandbox-controls.d.ts +15 -0
  273. package/dist/database/sandbox-controls.d.ts.map +1 -0
  274. package/dist/database/sandbox-controls.js +18 -0
  275. package/dist/database/sandbox-controls.js.map +1 -0
  276. package/dist/firestore/aggregates.d.ts +50 -0
  277. package/dist/firestore/aggregates.d.ts.map +1 -0
  278. package/dist/firestore/aggregates.js +40 -0
  279. package/dist/firestore/aggregates.js.map +1 -0
  280. package/dist/firestore/equality.d.ts +5 -0
  281. package/dist/firestore/equality.d.ts.map +1 -0
  282. package/dist/firestore/equality.js +20 -0
  283. package/dist/firestore/equality.js.map +1 -0
  284. package/dist/firestore/field-values.d.ts +61 -0
  285. package/dist/firestore/field-values.d.ts.map +1 -0
  286. package/dist/firestore/field-values.js +167 -0
  287. package/dist/firestore/field-values.js.map +1 -0
  288. package/dist/firestore/index.d.ts +54 -0
  289. package/dist/firestore/index.d.ts.map +1 -0
  290. package/dist/firestore/index.js +54 -0
  291. package/dist/firestore/index.js.map +1 -0
  292. package/dist/firestore/instances.d.ts +123 -0
  293. package/dist/firestore/instances.d.ts.map +1 -0
  294. package/dist/firestore/instances.js +177 -0
  295. package/dist/firestore/instances.js.map +1 -0
  296. package/dist/firestore/internal/index.d.ts +2 -0
  297. package/dist/firestore/internal/index.d.ts.map +1 -0
  298. package/dist/firestore/internal/index.js +2 -0
  299. package/dist/firestore/internal/index.js.map +1 -0
  300. package/dist/firestore/internal/listener-routing.d.ts +4 -0
  301. package/dist/firestore/internal/listener-routing.d.ts.map +1 -0
  302. package/dist/firestore/internal/listener-routing.js +4 -0
  303. package/dist/firestore/internal/listener-routing.js.map +1 -0
  304. package/dist/firestore/listeners.d.ts +12 -0
  305. package/dist/firestore/listeners.d.ts.map +1 -0
  306. package/dist/firestore/listeners.js +200 -0
  307. package/dist/firestore/listeners.js.map +1 -0
  308. package/dist/firestore/persistence.d.ts +227 -0
  309. package/dist/firestore/persistence.d.ts.map +1 -0
  310. package/dist/firestore/persistence.js +245 -0
  311. package/dist/firestore/persistence.js.map +1 -0
  312. package/dist/firestore/query-constraints.d.ts +72 -0
  313. package/dist/firestore/query-constraints.d.ts.map +1 -0
  314. package/dist/firestore/query-constraints.js +168 -0
  315. package/dist/firestore/query-constraints.js.map +1 -0
  316. package/dist/firestore/reads.d.ts +12 -0
  317. package/dist/firestore/reads.d.ts.map +1 -0
  318. package/dist/firestore/reads.js +32 -0
  319. package/dist/firestore/reads.js.map +1 -0
  320. package/dist/firestore/refs.d.ts +27 -0
  321. package/dist/firestore/refs.d.ts.map +1 -0
  322. package/dist/firestore/refs.js +74 -0
  323. package/dist/firestore/refs.js.map +1 -0
  324. package/dist/firestore/sandbox-controls.d.ts +60 -0
  325. package/dist/firestore/sandbox-controls.d.ts.map +1 -0
  326. package/dist/firestore/sandbox-controls.js +77 -0
  327. package/dist/firestore/sandbox-controls.js.map +1 -0
  328. package/dist/firestore/snapshots.d.ts +71 -0
  329. package/dist/firestore/snapshots.d.ts.map +1 -0
  330. package/dist/firestore/snapshots.js +160 -0
  331. package/dist/firestore/snapshots.js.map +1 -0
  332. package/dist/firestore/state.d.ts +168 -0
  333. package/dist/firestore/state.d.ts.map +1 -0
  334. package/dist/firestore/state.js +260 -0
  335. package/dist/firestore/state.js.map +1 -0
  336. package/dist/firestore/tools.d.ts +71 -0
  337. package/dist/firestore/tools.d.ts.map +1 -0
  338. package/dist/firestore/tools.js +320 -0
  339. package/dist/firestore/tools.js.map +1 -0
  340. package/dist/firestore/transactions.d.ts +4 -0
  341. package/dist/firestore/transactions.d.ts.map +1 -0
  342. package/dist/firestore/transactions.js +14 -0
  343. package/dist/firestore/transactions.js.map +1 -0
  344. package/dist/firestore/types.d.ts +82 -0
  345. package/dist/firestore/types.d.ts.map +1 -0
  346. package/dist/firestore/types.js +15 -0
  347. package/dist/firestore/types.js.map +1 -0
  348. package/dist/firestore/writes.d.ts +43 -0
  349. package/dist/firestore/writes.d.ts.map +1 -0
  350. package/dist/firestore/writes.js +40 -0
  351. package/dist/firestore/writes.js.map +1 -0
  352. package/dist/firestore-values/index.d.ts +63 -0
  353. package/dist/firestore-values/index.d.ts.map +1 -0
  354. package/dist/firestore-values/index.js +148 -0
  355. package/dist/firestore-values/index.js.map +1 -0
  356. package/dist/messaging/broker/broker.d.ts +171 -0
  357. package/dist/messaging/broker/broker.d.ts.map +1 -0
  358. package/dist/messaging/broker/broker.js +400 -0
  359. package/dist/messaging/broker/broker.js.map +1 -0
  360. package/dist/messaging/broker/envelopes.d.ts +96 -0
  361. package/dist/messaging/broker/envelopes.d.ts.map +1 -0
  362. package/dist/messaging/broker/envelopes.js +132 -0
  363. package/dist/messaging/broker/envelopes.js.map +1 -0
  364. package/dist/messaging/broker/index.d.ts +27 -0
  365. package/dist/messaging/broker/index.d.ts.map +1 -0
  366. package/dist/messaging/broker/index.js +21 -0
  367. package/dist/messaging/broker/index.js.map +1 -0
  368. package/dist/messaging/broker/tokens.d.ts +22 -0
  369. package/dist/messaging/broker/tokens.d.ts.map +1 -0
  370. package/dist/messaging/broker/tokens.js +37 -0
  371. package/dist/messaging/broker/tokens.js.map +1 -0
  372. package/dist/messaging/broker/types.d.ts +117 -0
  373. package/dist/messaging/broker/types.d.ts.map +1 -0
  374. package/dist/messaging/broker/types.js +12 -0
  375. package/dist/messaging/broker/types.js.map +1 -0
  376. package/dist/messaging/broker/validate.d.ts +58 -0
  377. package/dist/messaging/broker/validate.d.ts.map +1 -0
  378. package/dist/messaging/broker/validate.js +196 -0
  379. package/dist/messaging/broker/validate.js.map +1 -0
  380. package/dist/messaging/client.d.ts +108 -0
  381. package/dist/messaging/client.d.ts.map +1 -0
  382. package/dist/messaging/client.js +65 -0
  383. package/dist/messaging/client.js.map +1 -0
  384. package/dist/messaging/index.d.ts +3 -0
  385. package/dist/messaging/index.d.ts.map +1 -0
  386. package/dist/messaging/index.js +3 -0
  387. package/dist/messaging/index.js.map +1 -0
  388. package/dist/messaging/instance.d.ts +72 -0
  389. package/dist/messaging/instance.d.ts.map +1 -0
  390. package/dist/messaging/instance.js +93 -0
  391. package/dist/messaging/instance.js.map +1 -0
  392. package/dist/messaging/internal.d.ts +12 -0
  393. package/dist/messaging/internal.d.ts.map +1 -0
  394. package/dist/messaging/internal.js +12 -0
  395. package/dist/messaging/internal.js.map +1 -0
  396. package/dist/messaging/sw.d.ts +49 -0
  397. package/dist/messaging/sw.d.ts.map +1 -0
  398. package/dist/messaging/sw.js +49 -0
  399. package/dist/messaging/sw.js.map +1 -0
  400. package/dist/project-scope.d.ts +5 -0
  401. package/dist/project-scope.d.ts.map +1 -0
  402. package/dist/project-scope.js +2 -0
  403. package/dist/project-scope.js.map +1 -0
  404. package/dist/rules/api/assert.d.ts +39 -0
  405. package/dist/rules/api/assert.d.ts.map +1 -0
  406. package/dist/rules/api/assert.js +93 -0
  407. package/dist/rules/api/assert.js.map +1 -0
  408. package/dist/rules/api/case-types.d.ts +141 -0
  409. package/dist/rules/api/case-types.d.ts.map +1 -0
  410. package/dist/rules/api/case-types.js +13 -0
  411. package/dist/rules/api/case-types.js.map +1 -0
  412. package/dist/rules/api/errors.d.ts +38 -0
  413. package/dist/rules/api/errors.d.ts.map +1 -0
  414. package/dist/rules/api/errors.js +47 -0
  415. package/dist/rules/api/errors.js.map +1 -0
  416. package/dist/rules/api/firestore.d.ts +34 -0
  417. package/dist/rules/api/firestore.d.ts.map +1 -0
  418. package/dist/rules/api/firestore.js +137 -0
  419. package/dist/rules/api/firestore.js.map +1 -0
  420. package/dist/rules/api/issue.d.ts +50 -0
  421. package/dist/rules/api/issue.d.ts.map +1 -0
  422. package/dist/rules/api/issue.js +66 -0
  423. package/dist/rules/api/issue.js.map +1 -0
  424. package/dist/rules/api/lint.d.ts +16 -0
  425. package/dist/rules/api/lint.d.ts.map +1 -0
  426. package/dist/rules/api/lint.js +60 -0
  427. package/dist/rules/api/lint.js.map +1 -0
  428. package/dist/rules/api/rtdb.d.ts +33 -0
  429. package/dist/rules/api/rtdb.d.ts.map +1 -0
  430. package/dist/rules/api/rtdb.js +166 -0
  431. package/dist/rules/api/rtdb.js.map +1 -0
  432. package/dist/rules/api/values.d.ts +51 -0
  433. package/dist/rules/api/values.d.ts.map +1 -0
  434. package/dist/rules/api/values.js +66 -0
  435. package/dist/rules/api/values.js.map +1 -0
  436. package/dist/rules/generators/assembler.d.ts +19 -0
  437. package/dist/rules/generators/assembler.d.ts.map +1 -0
  438. package/dist/rules/generators/assembler.js +292 -0
  439. package/dist/rules/generators/assembler.js.map +1 -0
  440. package/dist/rules/generators/expressions.d.ts +52 -0
  441. package/dist/rules/generators/expressions.d.ts.map +1 -0
  442. package/dist/rules/generators/expressions.js +117 -0
  443. package/dist/rules/generators/expressions.js.map +1 -0
  444. package/dist/rules/generators/grid.d.ts +22 -0
  445. package/dist/rules/generators/grid.d.ts.map +1 -0
  446. package/dist/rules/generators/grid.js +52 -0
  447. package/dist/rules/generators/grid.js.map +1 -0
  448. package/dist/rules/grammar/FirestoreAST.d.ts +129 -0
  449. package/dist/rules/grammar/FirestoreAST.d.ts.map +1 -0
  450. package/dist/rules/grammar/FirestoreAST.js +3 -0
  451. package/dist/rules/grammar/FirestoreAST.js.map +1 -0
  452. package/dist/rules/grammar/FirestoreAssembler.d.ts +5 -0
  453. package/dist/rules/grammar/FirestoreAssembler.d.ts.map +1 -0
  454. package/dist/rules/grammar/FirestoreAssembler.js +158 -0
  455. package/dist/rules/grammar/FirestoreAssembler.js.map +1 -0
  456. package/dist/rules/grammar/FirestoreParser.d.ts +46 -0
  457. package/dist/rules/grammar/FirestoreParser.d.ts.map +1 -0
  458. package/dist/rules/grammar/FirestoreParser.js +409 -0
  459. package/dist/rules/grammar/FirestoreParser.js.map +1 -0
  460. package/dist/rules/grammar/FirestoreRules.ohm +229 -0
  461. package/dist/rules/grammar/FirestoreRules.ohm.generated.d.ts +2 -0
  462. package/dist/rules/grammar/FirestoreRules.ohm.generated.d.ts.map +1 -0
  463. package/dist/rules/grammar/FirestoreRules.ohm.generated.js +234 -0
  464. package/dist/rules/grammar/FirestoreRules.ohm.generated.js.map +1 -0
  465. package/dist/rules/grammar/FirestoreValidator.d.ts +10 -0
  466. package/dist/rules/grammar/FirestoreValidator.d.ts.map +1 -0
  467. package/dist/rules/grammar/FirestoreValidator.js +482 -0
  468. package/dist/rules/grammar/FirestoreValidator.js.map +1 -0
  469. package/dist/rules/index.d.ts +41 -0
  470. package/dist/rules/index.d.ts.map +1 -0
  471. package/dist/rules/index.js +40 -0
  472. package/dist/rules/index.js.map +1 -0
  473. package/dist/rules/indexes/extract/annotation-collect.d.ts +42 -0
  474. package/dist/rules/indexes/extract/annotation-collect.d.ts.map +1 -0
  475. package/dist/rules/indexes/extract/annotation-collect.js +69 -0
  476. package/dist/rules/indexes/extract/annotation-collect.js.map +1 -0
  477. package/dist/rules/indexes/extract/annotations.d.ts +50 -0
  478. package/dist/rules/indexes/extract/annotations.d.ts.map +1 -0
  479. package/dist/rules/indexes/extract/annotations.js +144 -0
  480. package/dist/rules/indexes/extract/annotations.js.map +1 -0
  481. package/dist/rules/indexes/extract/ast.d.ts +54 -0
  482. package/dist/rules/indexes/extract/ast.d.ts.map +1 -0
  483. package/dist/rules/indexes/extract/ast.js +119 -0
  484. package/dist/rules/indexes/extract/ast.js.map +1 -0
  485. package/dist/rules/indexes/extract/classify.d.ts +41 -0
  486. package/dist/rules/indexes/extract/classify.d.ts.map +1 -0
  487. package/dist/rules/indexes/extract/classify.js +138 -0
  488. package/dist/rules/indexes/extract/classify.js.map +1 -0
  489. package/dist/rules/indexes/extract/composite.d.ts +38 -0
  490. package/dist/rules/indexes/extract/composite.d.ts.map +1 -0
  491. package/dist/rules/indexes/extract/composite.js +85 -0
  492. package/dist/rules/indexes/extract/composite.js.map +1 -0
  493. package/dist/rules/indexes/extract/dataflow.d.ts +45 -0
  494. package/dist/rules/indexes/extract/dataflow.d.ts.map +1 -0
  495. package/dist/rules/indexes/extract/dataflow.js +200 -0
  496. package/dist/rules/indexes/extract/dataflow.js.map +1 -0
  497. package/dist/rules/indexes/extract/enumerate.d.ts +41 -0
  498. package/dist/rules/indexes/extract/enumerate.d.ts.map +1 -0
  499. package/dist/rules/indexes/extract/enumerate.js +163 -0
  500. package/dist/rules/indexes/extract/enumerate.js.map +1 -0
  501. package/dist/rules/indexes/extract/extractor.d.ts +3 -0
  502. package/dist/rules/indexes/extract/extractor.d.ts.map +1 -0
  503. package/dist/rules/indexes/extract/extractor.js +274 -0
  504. package/dist/rules/indexes/extract/extractor.js.map +1 -0
  505. package/dist/rules/indexes/extract/types.d.ts +211 -0
  506. package/dist/rules/indexes/extract/types.d.ts.map +1 -0
  507. package/dist/rules/indexes/extract/types.js +14 -0
  508. package/dist/rules/indexes/extract/types.js.map +1 -0
  509. package/dist/rules/indexes/extractHandler.d.ts +16 -0
  510. package/dist/rules/indexes/extractHandler.d.ts.map +1 -0
  511. package/dist/rules/indexes/extractHandler.js +100 -0
  512. package/dist/rules/indexes/extractHandler.js.map +1 -0
  513. package/dist/rules/indexes/extractTool.d.ts +15 -0
  514. package/dist/rules/indexes/extractTool.d.ts.map +1 -0
  515. package/dist/rules/indexes/extractTool.js +55 -0
  516. package/dist/rules/indexes/extractTool.js.map +1 -0
  517. package/dist/rules/indexes/types.d.ts +71 -0
  518. package/dist/rules/indexes/types.d.ts.map +1 -0
  519. package/dist/rules/indexes/types.js +15 -0
  520. package/dist/rules/indexes/types.js.map +1 -0
  521. package/dist/rules/inspect/handler.d.ts +6 -0
  522. package/dist/rules/inspect/handler.d.ts.map +1 -0
  523. package/dist/rules/inspect/handler.js +144 -0
  524. package/dist/rules/inspect/handler.js.map +1 -0
  525. package/dist/rules/inspect/spec.d.ts +37 -0
  526. package/dist/rules/inspect/spec.d.ts.map +1 -0
  527. package/dist/rules/inspect/spec.js +2 -0
  528. package/dist/rules/inspect/spec.js.map +1 -0
  529. package/dist/rules/inspect/tools.d.ts +21 -0
  530. package/dist/rules/inspect/tools.d.ts.map +1 -0
  531. package/dist/rules/inspect/tools.js +21 -0
  532. package/dist/rules/inspect/tools.js.map +1 -0
  533. package/dist/rules/internal/extract.d.ts +28 -0
  534. package/dist/rules/internal/extract.d.ts.map +1 -0
  535. package/dist/rules/internal/extract.js +25 -0
  536. package/dist/rules/internal/extract.js.map +1 -0
  537. package/dist/rules/internal/index.d.ts +82 -0
  538. package/dist/rules/internal/index.d.ts.map +1 -0
  539. package/dist/rules/internal/index.js +103 -0
  540. package/dist/rules/internal/index.js.map +1 -0
  541. package/dist/rules/internal/node.d.ts +18 -0
  542. package/dist/rules/internal/node.d.ts.map +1 -0
  543. package/dist/rules/internal/node.js +27 -0
  544. package/dist/rules/internal/node.js.map +1 -0
  545. package/dist/rules/internal/rtdb.d.ts +20 -0
  546. package/dist/rules/internal/rtdb.d.ts.map +1 -0
  547. package/dist/rules/internal/rtdb.js +15 -0
  548. package/dist/rules/internal/rtdb.js.map +1 -0
  549. package/dist/rules/linter/ast-utils.d.ts +97 -0
  550. package/dist/rules/linter/ast-utils.d.ts.map +1 -0
  551. package/dist/rules/linter/ast-utils.js +491 -0
  552. package/dist/rules/linter/ast-utils.js.map +1 -0
  553. package/dist/rules/linter/hallucinations.d.ts +34 -0
  554. package/dist/rules/linter/hallucinations.d.ts.map +1 -0
  555. package/dist/rules/linter/hallucinations.js +334 -0
  556. package/dist/rules/linter/hallucinations.js.map +1 -0
  557. package/dist/rules/linter/linter.d.ts +84 -0
  558. package/dist/rules/linter/linter.d.ts.map +1 -0
  559. package/dist/rules/linter/linter.js +783 -0
  560. package/dist/rules/linter/linter.js.map +1 -0
  561. package/dist/rules/modules/resolver-browser.d.ts +41 -0
  562. package/dist/rules/modules/resolver-browser.d.ts.map +1 -0
  563. package/dist/rules/modules/resolver-browser.js +63 -0
  564. package/dist/rules/modules/resolver-browser.js.map +1 -0
  565. package/dist/rules/modules/resolver-core.d.ts +51 -0
  566. package/dist/rules/modules/resolver-core.d.ts.map +1 -0
  567. package/dist/rules/modules/resolver-core.js +338 -0
  568. package/dist/rules/modules/resolver-core.js.map +1 -0
  569. package/dist/rules/modules/resolver.d.ts +17 -0
  570. package/dist/rules/modules/resolver.d.ts.map +1 -0
  571. package/dist/rules/modules/resolver.js +49 -0
  572. package/dist/rules/modules/resolver.js.map +1 -0
  573. package/dist/rules/modules/stdlib/atomic.rules +52 -0
  574. package/dist/rules/modules/stdlib/atomic.test.json +152 -0
  575. package/dist/rules/modules/stdlib/auth.rules +7 -0
  576. package/dist/rules/modules/stdlib/auth.test.json +53 -0
  577. package/dist/rules/modules/stdlib/content.rules +50 -0
  578. package/dist/rules/modules/stdlib/content.test.json +238 -0
  579. package/dist/rules/modules/stdlib/counters.rules +41 -0
  580. package/dist/rules/modules/stdlib/counters.test.json +254 -0
  581. package/dist/rules/modules/stdlib/geometry.rules +43 -0
  582. package/dist/rules/modules/stdlib/geometry.test.json +200 -0
  583. package/dist/rules/modules/stdlib/joining.rules +49 -0
  584. package/dist/rules/modules/stdlib/joining.test.json +287 -0
  585. package/dist/rules/modules/stdlib/lifecycle.rules +51 -0
  586. package/dist/rules/modules/stdlib/lifecycle.test.json +288 -0
  587. package/dist/rules/modules/stdlib/lobby.rules +44 -0
  588. package/dist/rules/modules/stdlib/lobby.test.json +32 -0
  589. package/dist/rules/modules/stdlib/membership.rules +40 -0
  590. package/dist/rules/modules/stdlib/membership.test.json +107 -0
  591. package/dist/rules/modules/stdlib/spaces.rules +46 -0
  592. package/dist/rules/modules/stdlib/spaces.test.json +392 -0
  593. package/dist/rules/modules/stdlib/state.rules +28 -0
  594. package/dist/rules/modules/stdlib/state.test.json +55 -0
  595. package/dist/rules/modules/stdlib/timing.rules +20 -0
  596. package/dist/rules/modules/stdlib/timing.test.json +106 -0
  597. package/dist/rules/modules/stdlib/transitions.rules +34 -0
  598. package/dist/rules/modules/stdlib/transitions.test.json +86 -0
  599. package/dist/rules/modules/stdlib/turns.rules +27 -0
  600. package/dist/rules/modules/stdlib/turns.test.json +64 -0
  601. package/dist/rules/modules/stdlib/validation.rules +31 -0
  602. package/dist/rules/modules/stdlib/validation.test.json +184 -0
  603. package/dist/rules/modules/stdlib-content.d.ts +11 -0
  604. package/dist/rules/modules/stdlib-content.d.ts.map +1 -0
  605. package/dist/rules/modules/stdlib-content.js +590 -0
  606. package/dist/rules/modules/stdlib-content.js.map +1 -0
  607. package/dist/rules/rtdb/compiled-rules.d.ts +11 -0
  608. package/dist/rules/rtdb/compiled-rules.d.ts.map +1 -0
  609. package/dist/rules/rtdb/compiled-rules.js +95 -0
  610. package/dist/rules/rtdb/compiled-rules.js.map +1 -0
  611. package/dist/rules/rtdb/constraints/atoms.d.ts +29 -0
  612. package/dist/rules/rtdb/constraints/atoms.d.ts.map +1 -0
  613. package/dist/rules/rtdb/constraints/atoms.js +43 -0
  614. package/dist/rules/rtdb/constraints/atoms.js.map +1 -0
  615. package/dist/rules/rtdb/constraints/compose.d.ts +16 -0
  616. package/dist/rules/rtdb/constraints/compose.d.ts.map +1 -0
  617. package/dist/rules/rtdb/constraints/compose.js +15 -0
  618. package/dist/rules/rtdb/constraints/compose.js.map +1 -0
  619. package/dist/rules/rtdb/constraints/data.d.ts +30 -0
  620. package/dist/rules/rtdb/constraints/data.d.ts.map +1 -0
  621. package/dist/rules/rtdb/constraints/data.js +46 -0
  622. package/dist/rules/rtdb/constraints/data.js.map +1 -0
  623. package/dist/rules/rtdb/constraints/document.d.ts +57 -0
  624. package/dist/rules/rtdb/constraints/document.d.ts.map +1 -0
  625. package/dist/rules/rtdb/constraints/document.js +85 -0
  626. package/dist/rules/rtdb/constraints/document.js.map +1 -0
  627. package/dist/rules/rtdb/constraints/game.d.ts +30 -0
  628. package/dist/rules/rtdb/constraints/game.d.ts.map +1 -0
  629. package/dist/rules/rtdb/constraints/game.js +49 -0
  630. package/dist/rules/rtdb/constraints/game.js.map +1 -0
  631. package/dist/rules/rtdb/constraints/index.d.ts +12 -0
  632. package/dist/rules/rtdb/constraints/index.d.ts.map +1 -0
  633. package/dist/rules/rtdb/constraints/index.js +9 -0
  634. package/dist/rules/rtdb/constraints/index.js.map +1 -0
  635. package/dist/rules/rtdb/constraints/policies.d.ts +16 -0
  636. package/dist/rules/rtdb/constraints/policies.d.ts.map +1 -0
  637. package/dist/rules/rtdb/constraints/policies.js +17 -0
  638. package/dist/rules/rtdb/constraints/policies.js.map +1 -0
  639. package/dist/rules/rtdb/constraints/ruleset.d.ts +5 -0
  640. package/dist/rules/rtdb/constraints/ruleset.d.ts.map +1 -0
  641. package/dist/rules/rtdb/constraints/ruleset.js +132 -0
  642. package/dist/rules/rtdb/constraints/ruleset.js.map +1 -0
  643. package/dist/rules/rtdb/constraints/schema.d.ts +17 -0
  644. package/dist/rules/rtdb/constraints/schema.d.ts.map +1 -0
  645. package/dist/rules/rtdb/constraints/schema.js +74 -0
  646. package/dist/rules/rtdb/constraints/schema.js.map +1 -0
  647. package/dist/rules/rtdb/constraints/types.d.ts +22 -0
  648. package/dist/rules/rtdb/constraints/types.d.ts.map +1 -0
  649. package/dist/rules/rtdb/constraints/types.js +2 -0
  650. package/dist/rules/rtdb/constraints/types.js.map +1 -0
  651. package/dist/rules/rtdb/constraints/write-rules-file.d.ts +24 -0
  652. package/dist/rules/rtdb/constraints/write-rules-file.d.ts.map +1 -0
  653. package/dist/rules/rtdb/constraints/write-rules-file.js +30 -0
  654. package/dist/rules/rtdb/constraints/write-rules-file.js.map +1 -0
  655. package/dist/rules/rtdb/expression-engine.d.ts +8 -0
  656. package/dist/rules/rtdb/expression-engine.d.ts.map +1 -0
  657. package/dist/rules/rtdb/expression-engine.js +20 -0
  658. package/dist/rules/rtdb/expression-engine.js.map +1 -0
  659. package/dist/rules/rtdb/grammar/RtdbExpr.ohm +98 -0
  660. package/dist/rules/rtdb/grammar/RtdbExpr.ohm.generated.d.ts +2 -0
  661. package/dist/rules/rtdb/grammar/RtdbExpr.ohm.generated.d.ts.map +1 -0
  662. package/dist/rules/rtdb/grammar/RtdbExpr.ohm.generated.js +103 -0
  663. package/dist/rules/rtdb/grammar/RtdbExpr.ohm.generated.js.map +1 -0
  664. package/dist/rules/rtdb/grammar/RtdbExprParser.d.ts +3 -0
  665. package/dist/rules/rtdb/grammar/RtdbExprParser.d.ts.map +1 -0
  666. package/dist/rules/rtdb/grammar/RtdbExprParser.js +56 -0
  667. package/dist/rules/rtdb/grammar/RtdbExprParser.js.map +1 -0
  668. package/dist/rules/rtdb/grammar/linter.d.ts +3 -0
  669. package/dist/rules/rtdb/grammar/linter.d.ts.map +1 -0
  670. package/dist/rules/rtdb/grammar/linter.js +73 -0
  671. package/dist/rules/rtdb/grammar/linter.js.map +1 -0
  672. package/dist/rules/rtdb/grammar/simulator.d.ts +30 -0
  673. package/dist/rules/rtdb/grammar/simulator.d.ts.map +1 -0
  674. package/dist/rules/rtdb/grammar/simulator.js +282 -0
  675. package/dist/rules/rtdb/grammar/simulator.js.map +1 -0
  676. package/dist/rules/rtdb/grammar/validator.d.ts +3 -0
  677. package/dist/rules/rtdb/grammar/validator.d.ts.map +1 -0
  678. package/dist/rules/rtdb/grammar/validator.js +91 -0
  679. package/dist/rules/rtdb/grammar/validator.js.map +1 -0
  680. package/dist/rules/rtdb/simulation/handler.d.ts +6 -0
  681. package/dist/rules/rtdb/simulation/handler.d.ts.map +1 -0
  682. package/dist/rules/rtdb/simulation/handler.js +325 -0
  683. package/dist/rules/rtdb/simulation/handler.js.map +1 -0
  684. package/dist/rules/rtdb/simulation/spec.d.ts +102 -0
  685. package/dist/rules/rtdb/simulation/spec.d.ts.map +1 -0
  686. package/dist/rules/rtdb/simulation/spec.js +40 -0
  687. package/dist/rules/rtdb/simulation/spec.js.map +1 -0
  688. package/dist/rules/rtdb/types.d.ts +166 -0
  689. package/dist/rules/rtdb/types.d.ts.map +1 -0
  690. package/dist/rules/rtdb/types.js +21 -0
  691. package/dist/rules/rtdb/types.js.map +1 -0
  692. package/dist/rules/simulator/evaluator.d.ts +206 -0
  693. package/dist/rules/simulator/evaluator.d.ts.map +1 -0
  694. package/dist/rules/simulator/evaluator.js +1251 -0
  695. package/dist/rules/simulator/evaluator.js.map +1 -0
  696. package/dist/rules/simulator/expression/eval-errors.d.ts +86 -0
  697. package/dist/rules/simulator/expression/eval-errors.d.ts.map +1 -0
  698. package/dist/rules/simulator/expression/eval-errors.js +68 -0
  699. package/dist/rules/simulator/expression/eval-errors.js.map +1 -0
  700. package/dist/rules/simulator/expression/evaluator.d.ts +43 -0
  701. package/dist/rules/simulator/expression/evaluator.d.ts.map +1 -0
  702. package/dist/rules/simulator/expression/evaluator.js +298 -0
  703. package/dist/rules/simulator/expression/evaluator.js.map +1 -0
  704. package/dist/rules/simulator/expression/lexer.d.ts +36 -0
  705. package/dist/rules/simulator/expression/lexer.d.ts.map +1 -0
  706. package/dist/rules/simulator/expression/lexer.js +318 -0
  707. package/dist/rules/simulator/expression/lexer.js.map +1 -0
  708. package/dist/rules/simulator/expression/parser.d.ts +39 -0
  709. package/dist/rules/simulator/expression/parser.d.ts.map +1 -0
  710. package/dist/rules/simulator/expression/parser.js +329 -0
  711. package/dist/rules/simulator/expression/parser.js.map +1 -0
  712. package/dist/rules/simulator/expression/types.d.ts +137 -0
  713. package/dist/rules/simulator/expression/types.d.ts.map +1 -0
  714. package/dist/rules/simulator/expression/types.js +90 -0
  715. package/dist/rules/simulator/expression/types.js.map +1 -0
  716. package/dist/rules/simulator/expression/walk-data.d.ts +52 -0
  717. package/dist/rules/simulator/expression/walk-data.d.ts.map +1 -0
  718. package/dist/rules/simulator/expression/walk-data.js +167 -0
  719. package/dist/rules/simulator/expression/walk-data.js.map +1 -0
  720. package/dist/rules/simulator/firestore-set.d.ts +25 -0
  721. package/dist/rules/simulator/firestore-set.d.ts.map +1 -0
  722. package/dist/rules/simulator/firestore-set.js +89 -0
  723. package/dist/rules/simulator/firestore-set.js.map +1 -0
  724. package/dist/rules/simulator/handler.d.ts +47 -0
  725. package/dist/rules/simulator/handler.d.ts.map +1 -0
  726. package/dist/rules/simulator/handler.js +644 -0
  727. package/dist/rules/simulator/handler.js.map +1 -0
  728. package/dist/rules/simulator/mapdiff.d.ts +29 -0
  729. package/dist/rules/simulator/mapdiff.d.ts.map +1 -0
  730. package/dist/rules/simulator/mapdiff.js +72 -0
  731. package/dist/rules/simulator/mapdiff.js.map +1 -0
  732. package/dist/rules/simulator/project-after-state.d.ts +33 -0
  733. package/dist/rules/simulator/project-after-state.d.ts.map +1 -0
  734. package/dist/rules/simulator/project-after-state.js +88 -0
  735. package/dist/rules/simulator/project-after-state.js.map +1 -0
  736. package/dist/rules/simulator/query-proof.d.ts +80 -0
  737. package/dist/rules/simulator/query-proof.d.ts.map +1 -0
  738. package/dist/rules/simulator/query-proof.js +142 -0
  739. package/dist/rules/simulator/query-proof.js.map +1 -0
  740. package/dist/rules/simulator/value-equality.d.ts +8 -0
  741. package/dist/rules/simulator/value-equality.d.ts.map +1 -0
  742. package/dist/rules/simulator/value-equality.js +40 -0
  743. package/dist/rules/simulator/value-equality.js.map +1 -0
  744. package/dist/rules/simulator/wrappers/base.d.ts +129 -0
  745. package/dist/rules/simulator/wrappers/base.d.ts.map +1 -0
  746. package/dist/rules/simulator/wrappers/base.js +90 -0
  747. package/dist/rules/simulator/wrappers/base.js.map +1 -0
  748. package/dist/rules/simulator/wrappers/bytes.d.ts +45 -0
  749. package/dist/rules/simulator/wrappers/bytes.d.ts.map +1 -0
  750. package/dist/rules/simulator/wrappers/bytes.js +130 -0
  751. package/dist/rules/simulator/wrappers/bytes.js.map +1 -0
  752. package/dist/rules/simulator/wrappers/duration.d.ts +76 -0
  753. package/dist/rules/simulator/wrappers/duration.d.ts.map +1 -0
  754. package/dist/rules/simulator/wrappers/duration.js +176 -0
  755. package/dist/rules/simulator/wrappers/duration.js.map +1 -0
  756. package/dist/rules/simulator/wrappers/float.d.ts +52 -0
  757. package/dist/rules/simulator/wrappers/float.d.ts.map +1 -0
  758. package/dist/rules/simulator/wrappers/float.js +88 -0
  759. package/dist/rules/simulator/wrappers/float.js.map +1 -0
  760. package/dist/rules/simulator/wrappers/latlng.d.ts +40 -0
  761. package/dist/rules/simulator/wrappers/latlng.d.ts.map +1 -0
  762. package/dist/rules/simulator/wrappers/latlng.js +100 -0
  763. package/dist/rules/simulator/wrappers/latlng.js.map +1 -0
  764. package/dist/rules/simulator/wrappers/path.d.ts +75 -0
  765. package/dist/rules/simulator/wrappers/path.d.ts.map +1 -0
  766. package/dist/rules/simulator/wrappers/path.js +158 -0
  767. package/dist/rules/simulator/wrappers/path.js.map +1 -0
  768. package/dist/rules/simulator/wrappers/reference.d.ts +82 -0
  769. package/dist/rules/simulator/wrappers/reference.d.ts.map +1 -0
  770. package/dist/rules/simulator/wrappers/reference.js +145 -0
  771. package/dist/rules/simulator/wrappers/reference.js.map +1 -0
  772. package/dist/rules/simulator/wrappers/timestamp.d.ts +86 -0
  773. package/dist/rules/simulator/wrappers/timestamp.d.ts.map +1 -0
  774. package/dist/rules/simulator/wrappers/timestamp.js +207 -0
  775. package/dist/rules/simulator/wrappers/timestamp.js.map +1 -0
  776. package/dist/rules/simulator/wrappers/vector.d.ts +43 -0
  777. package/dist/rules/simulator/wrappers/vector.d.ts.map +1 -0
  778. package/dist/rules/simulator/wrappers/vector.js +80 -0
  779. package/dist/rules/simulator/wrappers/vector.js.map +1 -0
  780. package/dist/rules/simulator-tools-impl.d.ts +64 -0
  781. package/dist/rules/simulator-tools-impl.d.ts.map +1 -0
  782. package/dist/rules/simulator-tools-impl.js +462 -0
  783. package/dist/rules/simulator-tools-impl.js.map +1 -0
  784. package/dist/rules/simulator.d.ts +20 -0
  785. package/dist/rules/simulator.d.ts.map +1 -0
  786. package/dist/rules/simulator.js +24 -0
  787. package/dist/rules/simulator.js.map +1 -0
  788. package/dist/rules/stdlib-modules.d.ts +73 -0
  789. package/dist/rules/stdlib-modules.d.ts.map +1 -0
  790. package/dist/rules/stdlib-modules.js +837 -0
  791. package/dist/rules/stdlib-modules.js.map +1 -0
  792. package/dist/rules/stdlib-tools.d.ts +19 -0
  793. package/dist/rules/stdlib-tools.d.ts.map +1 -0
  794. package/dist/rules/stdlib-tools.js +164 -0
  795. package/dist/rules/stdlib-tools.js.map +1 -0
  796. package/dist/rules/test/handler.d.ts +21 -0
  797. package/dist/rules/test/handler.d.ts.map +1 -0
  798. package/dist/rules/test/handler.js +214 -0
  799. package/dist/rules/test/handler.js.map +1 -0
  800. package/dist/rules/test/spec.d.ts +677 -0
  801. package/dist/rules/test/spec.d.ts.map +1 -0
  802. package/dist/rules/test/spec.js +327 -0
  803. package/dist/rules/test/spec.js.map +1 -0
  804. package/dist/rules/tools.d.ts +41 -0
  805. package/dist/rules/tools.d.ts.map +1 -0
  806. package/dist/rules/tools.js +120 -0
  807. package/dist/rules/tools.js.map +1 -0
  808. package/dist/rules/write/handler.d.ts +6 -0
  809. package/dist/rules/write/handler.d.ts.map +1 -0
  810. package/dist/rules/write/handler.js +126 -0
  811. package/dist/rules/write/handler.js.map +1 -0
  812. package/dist/rules/write/spec.d.ts +28 -0
  813. package/dist/rules/write/spec.d.ts.map +1 -0
  814. package/dist/rules/write/spec.js +2 -0
  815. package/dist/rules/write/spec.js.map +1 -0
  816. package/dist/sandbox/admin-compat.d.ts +20 -0
  817. package/dist/sandbox/admin-compat.d.ts.map +1 -0
  818. package/dist/sandbox/admin-compat.js +19 -0
  819. package/dist/sandbox/admin-compat.js.map +1 -0
  820. package/dist/sandbox/admin-firestore/error-translation.d.ts +90 -0
  821. package/dist/sandbox/admin-firestore/error-translation.d.ts.map +1 -0
  822. package/dist/sandbox/admin-firestore/error-translation.js +214 -0
  823. package/dist/sandbox/admin-firestore/error-translation.js.map +1 -0
  824. package/dist/sandbox/admin-firestore/get-admin-firestore.d.ts +44 -0
  825. package/dist/sandbox/admin-firestore/get-admin-firestore.d.ts.map +1 -0
  826. package/dist/sandbox/admin-firestore/get-admin-firestore.js +62 -0
  827. package/dist/sandbox/admin-firestore/get-admin-firestore.js.map +1 -0
  828. package/dist/sandbox/admin-firestore/get-firestore.d.ts +34 -0
  829. package/dist/sandbox/admin-firestore/get-firestore.d.ts.map +1 -0
  830. package/dist/sandbox/admin-firestore/get-firestore.js +71 -0
  831. package/dist/sandbox/admin-firestore/get-firestore.js.map +1 -0
  832. package/dist/sandbox/admin-firestore/index.d.ts +36 -0
  833. package/dist/sandbox/admin-firestore/index.d.ts.map +1 -0
  834. package/dist/sandbox/admin-firestore/index.js +33 -0
  835. package/dist/sandbox/admin-firestore/index.js.map +1 -0
  836. package/dist/sandbox/admin-firestore/listeners.d.ts +46 -0
  837. package/dist/sandbox/admin-firestore/listeners.d.ts.map +1 -0
  838. package/dist/sandbox/admin-firestore/listeners.js +290 -0
  839. package/dist/sandbox/admin-firestore/listeners.js.map +1 -0
  840. package/dist/sandbox/admin-firestore/local-handle.d.ts +23 -0
  841. package/dist/sandbox/admin-firestore/local-handle.d.ts.map +1 -0
  842. package/dist/sandbox/admin-firestore/local-handle.js +74 -0
  843. package/dist/sandbox/admin-firestore/local-handle.js.map +1 -0
  844. package/dist/sandbox/admin-firestore/remote/batch.d.ts +6 -0
  845. package/dist/sandbox/admin-firestore/remote/batch.d.ts.map +1 -0
  846. package/dist/sandbox/admin-firestore/remote/batch.js +38 -0
  847. package/dist/sandbox/admin-firestore/remote/batch.js.map +1 -0
  848. package/dist/sandbox/admin-firestore/remote/channel.d.ts +22 -0
  849. package/dist/sandbox/admin-firestore/remote/channel.d.ts.map +1 -0
  850. package/dist/sandbox/admin-firestore/remote/channel.js +27 -0
  851. package/dist/sandbox/admin-firestore/remote/channel.js.map +1 -0
  852. package/dist/sandbox/admin-firestore/remote/doc-ref.d.ts +10 -0
  853. package/dist/sandbox/admin-firestore/remote/doc-ref.d.ts.map +1 -0
  854. package/dist/sandbox/admin-firestore/remote/doc-ref.js +88 -0
  855. package/dist/sandbox/admin-firestore/remote/doc-ref.js.map +1 -0
  856. package/dist/sandbox/admin-firestore/remote/errors.d.ts +17 -0
  857. package/dist/sandbox/admin-firestore/remote/errors.d.ts.map +1 -0
  858. package/dist/sandbox/admin-firestore/remote/errors.js +32 -0
  859. package/dist/sandbox/admin-firestore/remote/errors.js.map +1 -0
  860. package/dist/sandbox/admin-firestore/remote/listeners.d.ts +43 -0
  861. package/dist/sandbox/admin-firestore/remote/listeners.d.ts.map +1 -0
  862. package/dist/sandbox/admin-firestore/remote/listeners.js +89 -0
  863. package/dist/sandbox/admin-firestore/remote/listeners.js.map +1 -0
  864. package/dist/sandbox/admin-firestore/remote/query.d.ts +47 -0
  865. package/dist/sandbox/admin-firestore/remote/query.d.ts.map +1 -0
  866. package/dist/sandbox/admin-firestore/remote/query.js +186 -0
  867. package/dist/sandbox/admin-firestore/remote/query.js.map +1 -0
  868. package/dist/sandbox/admin-firestore/remote/remote-firestore.d.ts +55 -0
  869. package/dist/sandbox/admin-firestore/remote/remote-firestore.d.ts.map +1 -0
  870. package/dist/sandbox/admin-firestore/remote/remote-firestore.js +111 -0
  871. package/dist/sandbox/admin-firestore/remote/remote-firestore.js.map +1 -0
  872. package/dist/sandbox/admin-firestore/remote/snapshots.d.ts +10 -0
  873. package/dist/sandbox/admin-firestore/remote/snapshots.d.ts.map +1 -0
  874. package/dist/sandbox/admin-firestore/remote/snapshots.js +37 -0
  875. package/dist/sandbox/admin-firestore/remote/snapshots.js.map +1 -0
  876. package/dist/sandbox/admin-firestore/remote/transaction.d.ts +19 -0
  877. package/dist/sandbox/admin-firestore/remote/transaction.d.ts.map +1 -0
  878. package/dist/sandbox/admin-firestore/remote/transaction.js +105 -0
  879. package/dist/sandbox/admin-firestore/remote/transaction.js.map +1 -0
  880. package/dist/sandbox/admin-firestore/remote/value-codec.d.ts +52 -0
  881. package/dist/sandbox/admin-firestore/remote/value-codec.d.ts.map +1 -0
  882. package/dist/sandbox/admin-firestore/remote/value-codec.js +120 -0
  883. package/dist/sandbox/admin-firestore/remote/value-codec.js.map +1 -0
  884. package/dist/sandbox/admin-firestore/remote/wire-types.d.ts +111 -0
  885. package/dist/sandbox/admin-firestore/remote/wire-types.d.ts.map +1 -0
  886. package/dist/sandbox/admin-firestore/remote/wire-types.js +8 -0
  887. package/dist/sandbox/admin-firestore/remote/wire-types.js.map +1 -0
  888. package/dist/sandbox/admin-firestore/types.d.ts +59 -0
  889. package/dist/sandbox/admin-firestore/types.d.ts.map +1 -0
  890. package/dist/sandbox/admin-firestore/types.js +6 -0
  891. package/dist/sandbox/admin-firestore/types.js.map +1 -0
  892. package/dist/sandbox/branches/index.d.ts +141 -0
  893. package/dist/sandbox/branches/index.d.ts.map +1 -0
  894. package/dist/sandbox/branches/index.js +327 -0
  895. package/dist/sandbox/branches/index.js.map +1 -0
  896. package/dist/sandbox/firestore/admin-compat/batch.d.ts +34 -0
  897. package/dist/sandbox/firestore/admin-compat/batch.d.ts.map +1 -0
  898. package/dist/sandbox/firestore/admin-compat/batch.js +73 -0
  899. package/dist/sandbox/firestore/admin-compat/batch.js.map +1 -0
  900. package/dist/sandbox/firestore/admin-compat/doc-ref.d.ts +38 -0
  901. package/dist/sandbox/firestore/admin-compat/doc-ref.d.ts.map +1 -0
  902. package/dist/sandbox/firestore/admin-compat/doc-ref.js +154 -0
  903. package/dist/sandbox/firestore/admin-compat/doc-ref.js.map +1 -0
  904. package/dist/sandbox/firestore/admin-compat/firestore.d.ts +47 -0
  905. package/dist/sandbox/firestore/admin-compat/firestore.d.ts.map +1 -0
  906. package/dist/sandbox/firestore/admin-compat/firestore.js +117 -0
  907. package/dist/sandbox/firestore/admin-compat/firestore.js.map +1 -0
  908. package/dist/sandbox/firestore/admin-compat/index.d.ts +49 -0
  909. package/dist/sandbox/firestore/admin-compat/index.d.ts.map +1 -0
  910. package/dist/sandbox/firestore/admin-compat/index.js +27 -0
  911. package/dist/sandbox/firestore/admin-compat/index.js.map +1 -0
  912. package/dist/sandbox/firestore/admin-compat/paths.d.ts +37 -0
  913. package/dist/sandbox/firestore/admin-compat/paths.d.ts.map +1 -0
  914. package/dist/sandbox/firestore/admin-compat/paths.js +49 -0
  915. package/dist/sandbox/firestore/admin-compat/paths.js.map +1 -0
  916. package/dist/sandbox/firestore/admin-compat/query.d.ts +261 -0
  917. package/dist/sandbox/firestore/admin-compat/query.d.ts.map +1 -0
  918. package/dist/sandbox/firestore/admin-compat/query.js +758 -0
  919. package/dist/sandbox/firestore/admin-compat/query.js.map +1 -0
  920. package/dist/sandbox/firestore/admin-compat/read-translation.d.ts +8 -0
  921. package/dist/sandbox/firestore/admin-compat/read-translation.d.ts.map +1 -0
  922. package/dist/sandbox/firestore/admin-compat/read-translation.js +59 -0
  923. package/dist/sandbox/firestore/admin-compat/read-translation.js.map +1 -0
  924. package/dist/sandbox/firestore/admin-compat/snapshots.d.ts +39 -0
  925. package/dist/sandbox/firestore/admin-compat/snapshots.d.ts.map +1 -0
  926. package/dist/sandbox/firestore/admin-compat/snapshots.js +50 -0
  927. package/dist/sandbox/firestore/admin-compat/snapshots.js.map +1 -0
  928. package/dist/sandbox/firestore/admin-compat/transaction.d.ts +35 -0
  929. package/dist/sandbox/firestore/admin-compat/transaction.d.ts.map +1 -0
  930. package/dist/sandbox/firestore/admin-compat/transaction.js +88 -0
  931. package/dist/sandbox/firestore/admin-compat/transaction.js.map +1 -0
  932. package/dist/sandbox/firestore/admin-compat/types.d.ts +297 -0
  933. package/dist/sandbox/firestore/admin-compat/types.d.ts.map +1 -0
  934. package/dist/sandbox/firestore/admin-compat/types.js +127 -0
  935. package/dist/sandbox/firestore/admin-compat/types.js.map +1 -0
  936. package/dist/sandbox/firestore/admin-compat/value-order.d.ts +49 -0
  937. package/dist/sandbox/firestore/admin-compat/value-order.d.ts.map +1 -0
  938. package/dist/sandbox/firestore/admin-compat/value-order.js +172 -0
  939. package/dist/sandbox/firestore/admin-compat/value-order.js.map +1 -0
  940. package/dist/sandbox/firestore/auto-id.d.ts +26 -0
  941. package/dist/sandbox/firestore/auto-id.d.ts.map +1 -0
  942. package/dist/sandbox/firestore/auto-id.js +36 -0
  943. package/dist/sandbox/firestore/auto-id.js.map +1 -0
  944. package/dist/sandbox/firestore/converters/bytes-geopoint.d.ts +48 -0
  945. package/dist/sandbox/firestore/converters/bytes-geopoint.d.ts.map +1 -0
  946. package/dist/sandbox/firestore/converters/bytes-geopoint.js +85 -0
  947. package/dist/sandbox/firestore/converters/bytes-geopoint.js.map +1 -0
  948. package/dist/sandbox/firestore/converters/fieldvalue.d.ts +69 -0
  949. package/dist/sandbox/firestore/converters/fieldvalue.d.ts.map +1 -0
  950. package/dist/sandbox/firestore/converters/fieldvalue.js +166 -0
  951. package/dist/sandbox/firestore/converters/fieldvalue.js.map +1 -0
  952. package/dist/sandbox/firestore/converters/reference.d.ts +31 -0
  953. package/dist/sandbox/firestore/converters/reference.d.ts.map +1 -0
  954. package/dist/sandbox/firestore/converters/reference.js +51 -0
  955. package/dist/sandbox/firestore/converters/reference.js.map +1 -0
  956. package/dist/sandbox/firestore/converters/timestamp.d.ts +32 -0
  957. package/dist/sandbox/firestore/converters/timestamp.d.ts.map +1 -0
  958. package/dist/sandbox/firestore/converters/timestamp.js +63 -0
  959. package/dist/sandbox/firestore/converters/timestamp.js.map +1 -0
  960. package/dist/sandbox/firestore/converters/user-timestamp.d.ts +46 -0
  961. package/dist/sandbox/firestore/converters/user-timestamp.d.ts.map +1 -0
  962. package/dist/sandbox/firestore/converters/user-timestamp.js +65 -0
  963. package/dist/sandbox/firestore/converters/user-timestamp.js.map +1 -0
  964. package/dist/sandbox/firestore/converters/vector.d.ts +24 -0
  965. package/dist/sandbox/firestore/converters/vector.d.ts.map +1 -0
  966. package/dist/sandbox/firestore/converters/vector.js +53 -0
  967. package/dist/sandbox/firestore/converters/vector.js.map +1 -0
  968. package/dist/sandbox/firestore/errors.d.ts +82 -0
  969. package/dist/sandbox/firestore/errors.d.ts.map +1 -0
  970. package/dist/sandbox/firestore/errors.js +54 -0
  971. package/dist/sandbox/firestore/errors.js.map +1 -0
  972. package/dist/sandbox/firestore/event-log.d.ts +99 -0
  973. package/dist/sandbox/firestore/event-log.d.ts.map +1 -0
  974. package/dist/sandbox/firestore/event-log.js +67 -0
  975. package/dist/sandbox/firestore/event-log.js.map +1 -0
  976. package/dist/sandbox/firestore/field-merge.d.ts +64 -0
  977. package/dist/sandbox/firestore/field-merge.d.ts.map +1 -0
  978. package/dist/sandbox/firestore/field-merge.js +221 -0
  979. package/dist/sandbox/firestore/field-merge.js.map +1 -0
  980. package/dist/sandbox/firestore/list-query-proof.d.ts +77 -0
  981. package/dist/sandbox/firestore/list-query-proof.d.ts.map +1 -0
  982. package/dist/sandbox/firestore/list-query-proof.js +170 -0
  983. package/dist/sandbox/firestore/list-query-proof.js.map +1 -0
  984. package/dist/sandbox/firestore/local-environment.d.ts +825 -0
  985. package/dist/sandbox/firestore/local-environment.d.ts.map +1 -0
  986. package/dist/sandbox/firestore/local-environment.js +3129 -0
  987. package/dist/sandbox/firestore/local-environment.js.map +1 -0
  988. package/dist/sandbox/firestore/local-state.d.ts +196 -0
  989. package/dist/sandbox/firestore/local-state.d.ts.map +1 -0
  990. package/dist/sandbox/firestore/local-state.js +413 -0
  991. package/dist/sandbox/firestore/local-state.js.map +1 -0
  992. package/dist/sandbox/firestore/overlay-backing.d.ts +44 -0
  993. package/dist/sandbox/firestore/overlay-backing.d.ts.map +1 -0
  994. package/dist/sandbox/firestore/overlay-backing.js +82 -0
  995. package/dist/sandbox/firestore/overlay-backing.js.map +1 -0
  996. package/dist/sandbox/firestore/sentinel-capture.d.ts +30 -0
  997. package/dist/sandbox/firestore/sentinel-capture.d.ts.map +1 -0
  998. package/dist/sandbox/firestore/sentinel-capture.js +61 -0
  999. package/dist/sandbox/firestore/sentinel-capture.js.map +1 -0
  1000. package/dist/sandbox/firestore/snapshot-listeners.d.ts +290 -0
  1001. package/dist/sandbox/firestore/snapshot-listeners.d.ts.map +1 -0
  1002. package/dist/sandbox/firestore/snapshot-listeners.js +194 -0
  1003. package/dist/sandbox/firestore/snapshot-listeners.js.map +1 -0
  1004. package/dist/sandbox/firestore/topk.d.ts +12 -0
  1005. package/dist/sandbox/firestore/topk.d.ts.map +1 -0
  1006. package/dist/sandbox/firestore/topk.js +42 -0
  1007. package/dist/sandbox/firestore/topk.js.map +1 -0
  1008. package/dist/sandbox/firestore/transaction-merge.d.ts +55 -0
  1009. package/dist/sandbox/firestore/transaction-merge.d.ts.map +1 -0
  1010. package/dist/sandbox/firestore/transaction-merge.js +107 -0
  1011. package/dist/sandbox/firestore/transaction-merge.js.map +1 -0
  1012. package/dist/sandbox/firestore/transaction-types.d.ts +155 -0
  1013. package/dist/sandbox/firestore/transaction-types.d.ts.map +1 -0
  1014. package/dist/sandbox/firestore/transaction-types.js +10 -0
  1015. package/dist/sandbox/firestore/transaction-types.js.map +1 -0
  1016. package/dist/sandbox/firestore/transaction.d.ts +79 -0
  1017. package/dist/sandbox/firestore/transaction.d.ts.map +1 -0
  1018. package/dist/sandbox/firestore/transaction.js +95 -0
  1019. package/dist/sandbox/firestore/transaction.js.map +1 -0
  1020. package/dist/sandbox/firestore/value-equality.d.ts +2 -0
  1021. package/dist/sandbox/firestore/value-equality.d.ts.map +1 -0
  1022. package/dist/sandbox/firestore/value-equality.js +35 -0
  1023. package/dist/sandbox/firestore/value-equality.js.map +1 -0
  1024. package/dist/sandbox/firestore/value-resolver.d.ts +172 -0
  1025. package/dist/sandbox/firestore/value-resolver.d.ts.map +1 -0
  1026. package/dist/sandbox/firestore/value-resolver.js +221 -0
  1027. package/dist/sandbox/firestore/value-resolver.js.map +1 -0
  1028. package/dist/sandbox/firestore/wire-encoder.d.ts +14 -0
  1029. package/dist/sandbox/firestore/wire-encoder.d.ts.map +1 -0
  1030. package/dist/sandbox/firestore/wire-encoder.js +130 -0
  1031. package/dist/sandbox/firestore/wire-encoder.js.map +1 -0
  1032. package/dist/sandbox/index.d.ts +53 -0
  1033. package/dist/sandbox/index.d.ts.map +1 -0
  1034. package/dist/sandbox/index.js +65 -0
  1035. package/dist/sandbox/index.js.map +1 -0
  1036. package/dist/sandbox/internal/client-app.d.ts +29 -0
  1037. package/dist/sandbox/internal/client-app.d.ts.map +1 -0
  1038. package/dist/sandbox/internal/client-app.js +18 -0
  1039. package/dist/sandbox/internal/client-app.js.map +1 -0
  1040. package/dist/sandbox/internal/firebase-error.d.ts +14 -0
  1041. package/dist/sandbox/internal/firebase-error.d.ts.map +1 -0
  1042. package/dist/sandbox/internal/firebase-error.js +22 -0
  1043. package/dist/sandbox/internal/firebase-error.js.map +1 -0
  1044. package/dist/sandbox/internal/index.d.ts +39 -0
  1045. package/dist/sandbox/internal/index.d.ts.map +1 -0
  1046. package/dist/sandbox/internal/index.js +75 -0
  1047. package/dist/sandbox/internal/index.js.map +1 -0
  1048. package/dist/sandbox/internal/local-brand.d.ts +3 -0
  1049. package/dist/sandbox/internal/local-brand.d.ts.map +1 -0
  1050. package/dist/sandbox/internal/local-brand.js +3 -0
  1051. package/dist/sandbox/internal/local-brand.js.map +1 -0
  1052. package/dist/sandbox/internal/provenance.d.ts +16 -0
  1053. package/dist/sandbox/internal/provenance.d.ts.map +1 -0
  1054. package/dist/sandbox/internal/provenance.js +139 -0
  1055. package/dist/sandbox/internal/provenance.js.map +1 -0
  1056. package/dist/sandbox/internal/sandbox-impl.d.ts +328 -0
  1057. package/dist/sandbox/internal/sandbox-impl.d.ts.map +1 -0
  1058. package/dist/sandbox/internal/sandbox-impl.js +695 -0
  1059. package/dist/sandbox/internal/sandbox-impl.js.map +1 -0
  1060. package/dist/sandbox/operation-record.d.ts +48 -0
  1061. package/dist/sandbox/operation-record.d.ts.map +1 -0
  1062. package/dist/sandbox/operation-record.js +143 -0
  1063. package/dist/sandbox/operation-record.js.map +1 -0
  1064. package/dist/sandbox/persistence/backends.d.ts +37 -0
  1065. package/dist/sandbox/persistence/backends.d.ts.map +1 -0
  1066. package/dist/sandbox/persistence/backends.js +202 -0
  1067. package/dist/sandbox/persistence/backends.js.map +1 -0
  1068. package/dist/sandbox/persistence/chunk-format.d.ts +58 -0
  1069. package/dist/sandbox/persistence/chunk-format.d.ts.map +1 -0
  1070. package/dist/sandbox/persistence/chunk-format.js +163 -0
  1071. package/dist/sandbox/persistence/chunk-format.js.map +1 -0
  1072. package/dist/sandbox/persistence/controller.d.ts +39 -0
  1073. package/dist/sandbox/persistence/controller.d.ts.map +1 -0
  1074. package/dist/sandbox/persistence/controller.js +505 -0
  1075. package/dist/sandbox/persistence/controller.js.map +1 -0
  1076. package/dist/sandbox/persistence/index.d.ts +13 -0
  1077. package/dist/sandbox/persistence/index.d.ts.map +1 -0
  1078. package/dist/sandbox/persistence/index.js +5 -0
  1079. package/dist/sandbox/persistence/index.js.map +1 -0
  1080. package/dist/sandbox/persistence/serialize.d.ts +53 -0
  1081. package/dist/sandbox/persistence/serialize.d.ts.map +1 -0
  1082. package/dist/sandbox/persistence/serialize.js +98 -0
  1083. package/dist/sandbox/persistence/serialize.js.map +1 -0
  1084. package/dist/sandbox/persistence/types.d.ts +118 -0
  1085. package/dist/sandbox/persistence/types.d.ts.map +1 -0
  1086. package/dist/sandbox/persistence/types.js +15 -0
  1087. package/dist/sandbox/persistence/types.js.map +1 -0
  1088. package/dist/sandbox/remote.d.ts +118 -0
  1089. package/dist/sandbox/remote.d.ts.map +1 -0
  1090. package/dist/sandbox/remote.js +60 -0
  1091. package/dist/sandbox/remote.js.map +1 -0
  1092. package/dist/sandbox/replay/index.d.ts +106 -0
  1093. package/dist/sandbox/replay/index.d.ts.map +1 -0
  1094. package/dist/sandbox/replay/index.js +246 -0
  1095. package/dist/sandbox/replay/index.js.map +1 -0
  1096. package/dist/sandbox/sandbox-context.d.ts +48 -0
  1097. package/dist/sandbox/sandbox-context.d.ts.map +1 -0
  1098. package/dist/sandbox/sandbox-context.js +97 -0
  1099. package/dist/sandbox/sandbox-context.js.map +1 -0
  1100. package/dist/sandbox/tab-sync/index.d.ts +120 -0
  1101. package/dist/sandbox/tab-sync/index.d.ts.map +1 -0
  1102. package/dist/sandbox/tab-sync/index.js +273 -0
  1103. package/dist/sandbox/tab-sync/index.js.map +1 -0
  1104. package/dist/sandbox/types/auth-state.d.ts +23 -0
  1105. package/dist/sandbox/types/auth-state.d.ts.map +1 -0
  1106. package/dist/sandbox/types/auth-state.js +8 -0
  1107. package/dist/sandbox/types/auth-state.js.map +1 -0
  1108. package/dist/sandbox/types/context.d.ts +33 -0
  1109. package/dist/sandbox/types/context.d.ts.map +1 -0
  1110. package/dist/sandbox/types/context.js +5 -0
  1111. package/dist/sandbox/types/context.js.map +1 -0
  1112. package/dist/sandbox/types/errors.d.ts +109 -0
  1113. package/dist/sandbox/types/errors.d.ts.map +1 -0
  1114. package/dist/sandbox/types/errors.js +41 -0
  1115. package/dist/sandbox/types/errors.js.map +1 -0
  1116. package/dist/sandbox/types/events.d.ts +577 -0
  1117. package/dist/sandbox/types/events.d.ts.map +1 -0
  1118. package/dist/sandbox/types/events.js +7 -0
  1119. package/dist/sandbox/types/events.js.map +1 -0
  1120. package/dist/sandbox/types/index.d.ts +24 -0
  1121. package/dist/sandbox/types/index.d.ts.map +1 -0
  1122. package/dist/sandbox/types/index.js +17 -0
  1123. package/dist/sandbox/types/index.js.map +1 -0
  1124. package/dist/sandbox/types/operation.d.ts +60 -0
  1125. package/dist/sandbox/types/operation.d.ts.map +1 -0
  1126. package/dist/sandbox/types/operation.js +3 -0
  1127. package/dist/sandbox/types/operation.js.map +1 -0
  1128. package/dist/sandbox/types/persistence.d.ts +130 -0
  1129. package/dist/sandbox/types/persistence.d.ts.map +1 -0
  1130. package/dist/sandbox/types/persistence.js +7 -0
  1131. package/dist/sandbox/types/persistence.js.map +1 -0
  1132. package/dist/sandbox/types/service.d.ts +357 -0
  1133. package/dist/sandbox/types/service.d.ts.map +1 -0
  1134. package/dist/sandbox/types/service.js +6 -0
  1135. package/dist/sandbox/types/service.js.map +1 -0
  1136. package/dist/storage/admin/api.d.ts +206 -0
  1137. package/dist/storage/admin/api.d.ts.map +1 -0
  1138. package/dist/storage/admin/api.js +349 -0
  1139. package/dist/storage/admin/api.js.map +1 -0
  1140. package/dist/storage/admin/handler.d.ts +28 -0
  1141. package/dist/storage/admin/handler.d.ts.map +1 -0
  1142. package/dist/storage/admin/handler.js +82 -0
  1143. package/dist/storage/admin/handler.js.map +1 -0
  1144. package/dist/storage/admin/spec.d.ts +64 -0
  1145. package/dist/storage/admin/spec.d.ts.map +1 -0
  1146. package/dist/storage/admin/spec.js +8 -0
  1147. package/dist/storage/admin/spec.js.map +1 -0
  1148. package/dist/storage/admin/tools.d.ts +22 -0
  1149. package/dist/storage/admin/tools.d.ts.map +1 -0
  1150. package/dist/storage/admin/tools.js +90 -0
  1151. package/dist/storage/admin/tools.js.map +1 -0
  1152. package/dist/storage/download.d.ts +41 -0
  1153. package/dist/storage/download.d.ts.map +1 -0
  1154. package/dist/storage/download.js +137 -0
  1155. package/dist/storage/download.js.map +1 -0
  1156. package/dist/storage/enforce.d.ts +5 -0
  1157. package/dist/storage/enforce.d.ts.map +1 -0
  1158. package/dist/storage/enforce.js +147 -0
  1159. package/dist/storage/enforce.js.map +1 -0
  1160. package/dist/storage/errors.d.ts +44 -0
  1161. package/dist/storage/errors.d.ts.map +1 -0
  1162. package/dist/storage/errors.js +64 -0
  1163. package/dist/storage/errors.js.map +1 -0
  1164. package/dist/storage/index.d.ts +45 -0
  1165. package/dist/storage/index.d.ts.map +1 -0
  1166. package/dist/storage/index.js +39 -0
  1167. package/dist/storage/index.js.map +1 -0
  1168. package/dist/storage/instances.d.ts +9 -0
  1169. package/dist/storage/instances.d.ts.map +1 -0
  1170. package/dist/storage/instances.js +24 -0
  1171. package/dist/storage/instances.js.map +1 -0
  1172. package/dist/storage/internal.d.ts +18 -0
  1173. package/dist/storage/internal.d.ts.map +1 -0
  1174. package/dist/storage/internal.js +18 -0
  1175. package/dist/storage/internal.js.map +1 -0
  1176. package/dist/storage/list.d.ts +42 -0
  1177. package/dist/storage/list.d.ts.map +1 -0
  1178. package/dist/storage/list.js +83 -0
  1179. package/dist/storage/list.js.map +1 -0
  1180. package/dist/storage/metadata.d.ts +92 -0
  1181. package/dist/storage/metadata.d.ts.map +1 -0
  1182. package/dist/storage/metadata.js +164 -0
  1183. package/dist/storage/metadata.js.map +1 -0
  1184. package/dist/storage/persistence.d.ts +134 -0
  1185. package/dist/storage/persistence.d.ts.map +1 -0
  1186. package/dist/storage/persistence.js +132 -0
  1187. package/dist/storage/persistence.js.map +1 -0
  1188. package/dist/storage/reference.d.ts +57 -0
  1189. package/dist/storage/reference.d.ts.map +1 -0
  1190. package/dist/storage/reference.js +105 -0
  1191. package/dist/storage/reference.js.map +1 -0
  1192. package/dist/storage/rules.d.ts +339 -0
  1193. package/dist/storage/rules.d.ts.map +1 -0
  1194. package/dist/storage/rules.js +1334 -0
  1195. package/dist/storage/rules.js.map +1 -0
  1196. package/dist/storage/service.d.ts +122 -0
  1197. package/dist/storage/service.d.ts.map +1 -0
  1198. package/dist/storage/service.js +247 -0
  1199. package/dist/storage/service.js.map +1 -0
  1200. package/dist/storage/upload.d.ts +50 -0
  1201. package/dist/storage/upload.d.ts.map +1 -0
  1202. package/dist/storage/upload.js +246 -0
  1203. package/dist/storage/upload.js.map +1 -0
  1204. package/package.json +156 -3
@@ -0,0 +1,1495 @@
1
+ import { emitSandboxEvent, makeSandboxCommitEvent, makeSandboxListenerEvent, makeSandboxOperationEvent, makeServiceMutationEvent, } from 'pyric/sandbox/internal';
2
+ import { DataTree, cloneJson, jsonValuesEqual, joinPath, pathSegments, } from './data-tree.js';
3
+ import { generatePushId } from './push-id.js';
4
+ import { resolveSentinels } from './sentinels.js';
5
+ import { RulesEvaluator, permissionDenied, } from './rules-eval.js';
6
+ import { executeQuery } from './query.js';
7
+ /**
8
+ * Maps a non-`'allow'` rule check to the event-stream `result` value.
9
+ * `'unsupported'` (a simulator gap) is surfaced distinctly from a real
10
+ * `'deny'` so Studio's traffic view can tell "the rules engine said no"
11
+ * apart from "the rules engine couldn't tell" — but both still deny the
12
+ * operation itself (abstain, never grant), matching the Firestore
13
+ * simulator's posture.
14
+ */
15
+ function denyResultFor(check) {
16
+ return check === 'unsupported' ? 'unsupported' : 'deny';
17
+ }
18
+ import { normalizeWrite, coerceArrays } from './normalize.js';
19
+ /**
20
+ * RtdbBackend — the per-`Sandbox` data plane.
21
+ */
22
+ export class RtdbBackend {
23
+ tree = new DataTree();
24
+ rules = new RulesEvaluator();
25
+ activeRules = null;
26
+ valueListeners = new Set();
27
+ childListeners = new Set();
28
+ nextId = 0;
29
+ /**
30
+ * Persistence change-subscribers. The sandbox persistence controller
31
+ * registers one of these (via {@link RtdbBackend.subscribeWrites}) so any
32
+ * tree mutation schedules a debounced flush. RTDB writes emit
33
+ * `kind: 'service_mutation'` events, which are NOT in the controller's
34
+ * `isPersistableEvent` set (`write`/`session_boundary`) — so the sandbox
35
+ * event stream never triggers an RTDB flush. This subscriber channel is
36
+ * the sole flush trigger, mirroring how auth drives its own flushes.
37
+ */
38
+ writeSubscribers = new Set();
39
+ /**
40
+ * The owning `Sandbox`, when this backend was created through the
41
+ * modular surface's `getDatabase(sandbox)` / `getDatabase(ctx)` path.
42
+ * Held only to emit RTDB write activity onto the unified Studio
43
+ * `onEvent`/`history()` stream (keystone, track T1). Optional because
44
+ * the backend is also constructed bare in unit tests that exercise the
45
+ * data plane directly; in that case emission is simply skipped.
46
+ */
47
+ sandbox;
48
+ constructor(sandbox) {
49
+ this.sandbox = sandbox;
50
+ }
51
+ /**
52
+ * Emit an RTDB {@link ServiceMutationEvent} onto the sandbox's unified
53
+ * stream. No-op when this backend has no owning sandbox (bare-test
54
+ * construction). Best-effort + isolated — a throw must not fail the
55
+ * write that triggered it.
56
+ */
57
+ emitRtdbEvent(auth, op, path, fields = {}) {
58
+ if (!this.sandbox)
59
+ return;
60
+ try {
61
+ emitSandboxEvent(this.sandbox, makeServiceMutationEvent({
62
+ service: 'rtdb',
63
+ op,
64
+ path,
65
+ auth,
66
+ before: fields.before,
67
+ after: fields.after,
68
+ detail: fields.detail,
69
+ }), { service: 'rtdb' });
70
+ }
71
+ catch {
72
+ // Observational — never let event emission break an RTDB write.
73
+ }
74
+ }
75
+ nextListenerId() {
76
+ this.nextId += 1;
77
+ return `rtdb-listener-${this.nextId.toString(36)}`;
78
+ }
79
+ nextGroupId(prefix) {
80
+ this.nextId += 1;
81
+ return `rtdb-${prefix}-${this.nextId.toString(36)}`;
82
+ }
83
+ emitOperation(auth, method, path, result, evaluation, fields = {}) {
84
+ if (!this.sandbox)
85
+ return;
86
+ try {
87
+ emitSandboxEvent(this.sandbox, makeSandboxOperationEvent({
88
+ service: 'rtdb',
89
+ method,
90
+ path: canonicalPath(path),
91
+ auth,
92
+ result,
93
+ origin: fields.origin ?? 'user',
94
+ durationMs: fields.durationMs,
95
+ reasons: evaluation?.reasons,
96
+ rules: evaluation
97
+ ? {
98
+ engine: 'rtdb',
99
+ matchedPath: evaluation.matchedPath,
100
+ matchedRule: evaluation.matchedRule,
101
+ pathVariableBindings: evaluation.pathVariableBindings,
102
+ reason: evaluation.reason,
103
+ errorCode: evaluation.errorCode,
104
+ }
105
+ : undefined,
106
+ request: fields.request,
107
+ resourceBefore: fields.resourceBefore,
108
+ resourceAfter: fields.resourceAfter,
109
+ groupId: fields.groupId,
110
+ groupKind: fields.groupKind,
111
+ triggeredBy: fields.triggeredBy,
112
+ detail: fields.detail,
113
+ at: fields.at,
114
+ }), { service: 'rtdb' });
115
+ }
116
+ catch {
117
+ // Observational — never let telemetry break RTDB semantics.
118
+ }
119
+ }
120
+ emitCommit(auth, method, path, fields = {}) {
121
+ if (!this.sandbox)
122
+ return;
123
+ try {
124
+ emitSandboxEvent(this.sandbox, makeSandboxCommitEvent({
125
+ service: 'rtdb',
126
+ method,
127
+ path: canonicalPath(path),
128
+ auth,
129
+ data: fields.data,
130
+ priorState: fields.priorState,
131
+ nextState: fields.nextState,
132
+ groupId: fields.groupId,
133
+ groupKind: fields.groupKind,
134
+ replay: fields.replay,
135
+ detail: fields.detail,
136
+ }), { service: 'rtdb' });
137
+ }
138
+ catch {
139
+ // Observational — never let telemetry break RTDB semantics.
140
+ }
141
+ }
142
+ emitListener(phase, listener, auth, fields = {}) {
143
+ if (!this.sandbox)
144
+ return;
145
+ try {
146
+ emitSandboxEvent(this.sandbox, makeSandboxListenerEvent({
147
+ service: 'rtdb',
148
+ phase,
149
+ listenerId: listener.id,
150
+ target: {
151
+ kind: fields.event ?? 'value',
152
+ path: canonicalPath(listener.path),
153
+ },
154
+ auth,
155
+ result: fields.result,
156
+ size: fields.size,
157
+ sample: fields.sample,
158
+ reason: fields.reason,
159
+ error: fields.error,
160
+ triggeredBy: fields.triggeredBy,
161
+ detail: fields.detail,
162
+ }), { service: 'rtdb' });
163
+ }
164
+ catch {
165
+ // Observational — never let telemetry break RTDB semantics.
166
+ }
167
+ }
168
+ // ─── Admin-plane (rule-bypass) operations ───────────────────────────
169
+ //
170
+ // Used by the `sandbox.setData` / `sandbox.snapshotState` test
171
+ // helpers exported on the modular SDK. Don't go through the rule
172
+ // engine.
173
+ setData(seed) {
174
+ this.tree.restore({});
175
+ // Seed each path individually so the tree's prior-trim semantics
176
+ // apply consistently. For a flat seed of nested data we'd just
177
+ // restore(); but per-path seeding lets `setData({'/a/b': 1})` work
178
+ // when the user supplies dotted-out paths.
179
+ for (const [path, value] of Object.entries(seed)) {
180
+ // Resolve sentinels + normalize in seed too — keeps the seed API
181
+ // symmetric with the user-plane writes (array coercion, pruning).
182
+ const resolved = normalizeWrite(resolveSentinels(value, Date.now()), path === '/' ? '' : path);
183
+ this.tree.write(path, resolved);
184
+ }
185
+ this.notifyWrite();
186
+ }
187
+ setRules(rulesJson) {
188
+ this.rules.setRules(rulesJson);
189
+ this.activeRules = rulesJson === null ? null : structuredClone(rulesJson);
190
+ }
191
+ getActiveRules() {
192
+ return this.activeRules === null ? null : structuredClone(this.activeRules);
193
+ }
194
+ snapshotState() {
195
+ return this.tree.snapshot();
196
+ }
197
+ adminGet(path) {
198
+ const value = this.tree.read(path);
199
+ this.emitOperation(null, 'get', path, 'not-applicable', undefined, {
200
+ origin: 'admin',
201
+ resourceBefore: { data: value, exists: value !== null },
202
+ });
203
+ return value;
204
+ }
205
+ adminGetQuery(path, spec) {
206
+ const rows = executeQuery(this.tree.read(path), spec);
207
+ this.emitOperation(null, 'get', path, 'not-applicable', undefined, {
208
+ origin: 'admin',
209
+ request: { query: spec },
210
+ resourceBefore: { data: rowsToVal(rows), exists: rows.length > 0 },
211
+ });
212
+ return rows;
213
+ }
214
+ adminSet(path, value) {
215
+ const now = Date.now();
216
+ const before = this.tree.read(path);
217
+ const resolved = normalizeWrite(resolveSentinels(value, now, before), path === '/' ? '' : path);
218
+ this.emitOperation(null, resolved === null ? 'remove' : 'set', path, 'not-applicable', undefined, {
219
+ origin: 'admin',
220
+ request: { data: value, resourceData: value },
221
+ resourceBefore: { data: before, exists: before !== null },
222
+ resourceAfter: { data: resolved, exists: resolved !== null },
223
+ });
224
+ const priors = this.snapshotChildListenerParents();
225
+ this.tree.write(path, resolved);
226
+ this.fanOut([path]);
227
+ this.fanOutChildren(priors);
228
+ const after = this.tree.read(path);
229
+ const method = after === null ? 'remove' : 'set';
230
+ this.emitCommit(null, method, path, {
231
+ data: value,
232
+ priorState: before,
233
+ nextState: after,
234
+ replay: { requestTime: now },
235
+ detail: { admin: true },
236
+ });
237
+ this.notifyWrite();
238
+ }
239
+ adminUpdate(path, patch) {
240
+ const now = Date.now();
241
+ const before = this.tree.read(path);
242
+ const isMultiPath = Object.keys(patch).some((k) => k.includes('/'));
243
+ const priors = this.snapshotChildListenerParents();
244
+ if (isMultiPath) {
245
+ const expanded = {};
246
+ for (const [k, v] of Object.entries(patch)) {
247
+ const absPath = joinPath([...pathSegments(path), ...pathSegments(k)]);
248
+ expanded[absPath] = normalizeWrite(resolveSentinels(v, now, this.tree.read(absPath)), absPath);
249
+ }
250
+ this.emitOperation(null, 'update', path, 'not-applicable', undefined, {
251
+ origin: 'admin',
252
+ request: { data: patch, resourceData: patch },
253
+ resourceBefore: { data: before, exists: before !== null },
254
+ detail: { admin: true, multiPath: true, paths: Object.keys(expanded) },
255
+ });
256
+ this.tree.multiUpdate(expanded);
257
+ this.fanOut(Object.keys(expanded));
258
+ this.fanOutChildren(priors);
259
+ const after = this.tree.read(path);
260
+ this.emitCommit(null, 'update', path, {
261
+ data: patch,
262
+ priorState: before,
263
+ nextState: after,
264
+ replay: { requestTime: now },
265
+ detail: { admin: true, multiPath: true, paths: Object.keys(expanded) },
266
+ });
267
+ this.notifyWrite();
268
+ return;
269
+ }
270
+ const resolvedPatch = {};
271
+ const touched = [];
272
+ for (const [k, v] of Object.entries(patch)) {
273
+ const sub = joinPath([...pathSegments(path), ...pathSegments(k)]);
274
+ touched.push(sub);
275
+ resolvedPatch[k] = normalizeWrite(resolveSentinels(v, now, this.tree.read(sub)), sub);
276
+ }
277
+ this.emitOperation(null, 'update', path, 'not-applicable', undefined, {
278
+ origin: 'admin',
279
+ request: { data: patch, resourceData: patch },
280
+ resourceBefore: { data: before, exists: before !== null },
281
+ detail: { admin: true, multiPath: false, keys: Object.keys(resolvedPatch) },
282
+ });
283
+ this.tree.shallowUpdate(path, resolvedPatch);
284
+ this.fanOut(touched);
285
+ this.fanOutChildren(priors);
286
+ const after = this.tree.read(path);
287
+ this.emitCommit(null, 'update', path, {
288
+ data: patch,
289
+ priorState: before,
290
+ nextState: after,
291
+ replay: { requestTime: now },
292
+ detail: { admin: true, multiPath: false, keys: Object.keys(resolvedPatch) },
293
+ });
294
+ this.notifyWrite();
295
+ }
296
+ adminRemove(path) {
297
+ this.adminSet(path, null);
298
+ }
299
+ // ─── User-plane (rule-gated) operations ────────────────────────────
300
+ get(auth, path) {
301
+ const at = Date.now();
302
+ const before = this.tree.read(path);
303
+ const evaluation = this.rules.evaluate('read', path === '/' ? '/' : path, {
304
+ auth,
305
+ mockData: this.tree.snapshot(),
306
+ });
307
+ if (evaluation.check !== 'allow') {
308
+ this.emitOperation(auth, 'get', path, denyResultFor(evaluation.check), evaluation, {
309
+ at,
310
+ durationMs: Date.now() - at,
311
+ resourceBefore: { data: before, exists: before !== null },
312
+ });
313
+ throw permissionDenied();
314
+ }
315
+ this.emitOperation(auth, 'get', path, 'allow', evaluation, {
316
+ at,
317
+ durationMs: Date.now() - at,
318
+ resourceBefore: { data: before, exists: before !== null },
319
+ });
320
+ // Return the stored (integer-keyed) shape. Array coercion (DB-B2) is
321
+ // a `DataSnapshot.val()`-render concern applied by the snapshot
322
+ // wrapper — structural ops (`forEach`/`child`/`size`) walk the node.
323
+ return this.tree.read(path);
324
+ }
325
+ /**
326
+ * `set(path, value)` — full overwrite at the path. `null` deletes the
327
+ * subtree (sandbox match for the RTDB invariant
328
+ * `remove(ref) === set(ref, null)`).
329
+ */
330
+ set(auth, path, value) {
331
+ this.setInternal(auth, path, value, 'set');
332
+ }
333
+ /** Shared `set`/`remove` write path. `op` selects the emitted event
334
+ * label so a `remove` (which is `set(_, null)`) surfaces as `remove`
335
+ * rather than `set` on the Studio stream. */
336
+ setInternal(auth, path, value, op) {
337
+ const now = Date.now();
338
+ // Pass the current value at the path so `increment()` sentinels
339
+ // resolve against the field's prior value (DB-GAP).
340
+ const resolved0 = resolveSentinels(value, now, this.tree.read(path));
341
+ // Write-boundary normalization (DB-B1/B2/B3): validate keys + reject
342
+ // `undefined`/non-finite, coerce arrays → integer-keyed objects, prune
343
+ // null/empty subtrees. An object that prunes to nothing is a delete
344
+ // (`set(ref, {})` === `remove(ref)`).
345
+ const resolved = normalizeWrite(resolved0, path === '/' ? '' : path);
346
+ const before = this.tree.read(path);
347
+ const at = Date.now();
348
+ const evaluation = this.rules.evaluate('write', path === '/' ? '/' : path, {
349
+ auth,
350
+ mockData: this.tree.snapshot(),
351
+ newData: resolved,
352
+ });
353
+ const resourceBefore = { data: before, exists: before !== null };
354
+ const resourceAfter = { data: resolved, exists: resolved !== null };
355
+ if (evaluation.check !== 'allow') {
356
+ this.emitOperation(auth, op, path, denyResultFor(evaluation.check), evaluation, {
357
+ at,
358
+ durationMs: Date.now() - at,
359
+ request: { data: value, resourceData: value },
360
+ resourceBefore,
361
+ resourceAfter,
362
+ });
363
+ throw permissionDenied();
364
+ }
365
+ this.emitOperation(auth, op, path, 'allow', evaluation, {
366
+ at,
367
+ durationMs: Date.now() - at,
368
+ request: { data: value, resourceData: value },
369
+ resourceBefore,
370
+ resourceAfter,
371
+ });
372
+ const priors = this.snapshotChildListenerParents();
373
+ this.tree.write(path, resolved);
374
+ this.fanOut([path]);
375
+ this.fanOutChildren(priors);
376
+ // A write that pruned to nothing (`set(ref, null)` / `set(ref, {})`)
377
+ // is semantically a remove; label it as such even if it arrived via
378
+ // `set`. `after` is the post-write value at the path (`null` when the
379
+ // subtree was deleted).
380
+ const after = this.tree.read(path);
381
+ const effectiveOp = after === null ? 'remove' : op;
382
+ this.emitCommit(auth, effectiveOp, path, {
383
+ data: value,
384
+ priorState: before,
385
+ nextState: after,
386
+ replay: { requestTime: now },
387
+ });
388
+ this.emitRtdbEvent(auth, effectiveOp, canonicalPath(path), { before, after });
389
+ this.notifyWrite();
390
+ }
391
+ remove(auth, path) {
392
+ this.setInternal(auth, path, null, 'remove');
393
+ }
394
+ /**
395
+ * `update(path, patch)` — multi-path atomic update when keys are
396
+ * `/`-prefixed and `path === '/'`; otherwise a shallow merge at the
397
+ * named path. Matches `firebase/database`'s discrimination: an
398
+ * `update(rootRef, { '/users/a/x': 1, '/users/b/y': 2 })` fans out
399
+ * to both paths atomically, while `update(usersRef, { name: 'A' })`
400
+ * shallow-merges into `/users`.
401
+ */
402
+ update(auth, path, patch) {
403
+ const now = Date.now();
404
+ const isMultiPath = Object.keys(patch).some((k) => k.includes('/'));
405
+ if (isMultiPath) {
406
+ const groupId = this.nextGroupId('update');
407
+ // Each key is treated as a path relative to `path`. Resolve
408
+ // sentinels per-leaf so a key whose value contains a
409
+ // `serverTimestamp()` lands as a number.
410
+ const expanded = {};
411
+ for (const [k, v] of Object.entries(patch)) {
412
+ const absSegs = [...pathSegments(path), ...pathSegments(k)];
413
+ const absPath = joinPath(absSegs);
414
+ expanded[absPath] = normalizeWrite(resolveSentinels(v, now, this.tree.read(absPath)), absPath);
415
+ }
416
+ // Check every path under the rules engine. ANY denial fails the
417
+ // entire update — the multi-path atomicity contract.
418
+ //
419
+ // A multi-path update is atomic: every path's `.write`/`.validate`
420
+ // rules must see `newData` reflecting the ENTIRE projected post-update
421
+ // tree (all paths applied together), not just its own leaf. Pass the
422
+ // full update set so the simulator builds one shared projection — a
423
+ // rule on `/a` that reads a sibling `/b` written in the same update
424
+ // must see `/b`'s new value.
425
+ const mock = this.tree.snapshot();
426
+ const updates = Object.entries(expanded).map(([absPath, value]) => ({
427
+ path: absPath,
428
+ value,
429
+ }));
430
+ for (const [absPath, value] of Object.entries(expanded)) {
431
+ const at = Date.now();
432
+ const before = this.tree.read(absPath);
433
+ const evaluation = this.rules.evaluate('write', absPath, {
434
+ auth,
435
+ mockData: mock,
436
+ newData: value,
437
+ updates,
438
+ });
439
+ const common = {
440
+ at,
441
+ durationMs: Date.now() - at,
442
+ origin: 'batch',
443
+ request: { data: value, resourceData: value },
444
+ resourceBefore: { data: before, exists: before !== null },
445
+ resourceAfter: { data: value, exists: value !== null },
446
+ groupId,
447
+ groupKind: 'batch',
448
+ detail: { multiPath: true, rootPath: canonicalPath(path) },
449
+ };
450
+ if (evaluation.check !== 'allow') {
451
+ this.emitOperation(auth, 'update', absPath, denyResultFor(evaluation.check), evaluation, common);
452
+ throw permissionDenied();
453
+ }
454
+ this.emitOperation(auth, 'update', absPath, 'allow', evaluation, common);
455
+ }
456
+ // Apply atomically via the tree's overlap-checked multi-write.
457
+ const beforeRoot = this.tree.read(path);
458
+ const priors = this.snapshotChildListenerParents();
459
+ this.tree.multiUpdate(expanded);
460
+ this.fanOut(Object.keys(expanded));
461
+ this.fanOutChildren(priors);
462
+ const afterRoot = this.tree.read(path);
463
+ this.emitCommit(auth, 'update', path, {
464
+ data: patch,
465
+ priorState: beforeRoot,
466
+ nextState: afterRoot,
467
+ groupId,
468
+ groupKind: 'batch',
469
+ replay: { requestTime: now },
470
+ detail: { multiPath: true, paths: Object.keys(expanded) },
471
+ });
472
+ this.emitRtdbEvent(auth, 'update', canonicalPath(path), {
473
+ after: expanded,
474
+ detail: { multiPath: true, paths: Object.keys(expanded) },
475
+ });
476
+ this.notifyWrite();
477
+ return;
478
+ }
479
+ // Shallow merge mode. Each top-level key of `patch` replaces the
480
+ // key at `<path>/<key>`. `null` deletes.
481
+ const resolvedPatch = {};
482
+ for (const [k, v] of Object.entries(patch)) {
483
+ const sub = joinPath([...pathSegments(path), ...pathSegments(k)]);
484
+ resolvedPatch[k] = normalizeWrite(resolveSentinels(v, now, this.tree.read(sub)), sub);
485
+ }
486
+ const mock = this.tree.snapshot();
487
+ const touched = [];
488
+ const groupId = this.nextGroupId('update');
489
+ for (const [k, v] of Object.entries(resolvedPatch)) {
490
+ const sub = joinPath([...pathSegments(path), ...pathSegments(k)]);
491
+ touched.push(sub);
492
+ const at = Date.now();
493
+ const before = this.tree.read(sub);
494
+ const evaluation = this.rules.evaluate('write', sub, {
495
+ auth,
496
+ mockData: mock,
497
+ newData: v,
498
+ });
499
+ const common = {
500
+ at,
501
+ durationMs: Date.now() - at,
502
+ origin: 'batch',
503
+ request: { data: v, resourceData: v },
504
+ resourceBefore: { data: before, exists: before !== null },
505
+ resourceAfter: { data: v, exists: v !== null },
506
+ groupId,
507
+ groupKind: 'batch',
508
+ detail: { multiPath: false, rootPath: canonicalPath(path), key: k },
509
+ };
510
+ if (evaluation.check !== 'allow') {
511
+ this.emitOperation(auth, 'update', sub, denyResultFor(evaluation.check), evaluation, common);
512
+ throw permissionDenied();
513
+ }
514
+ this.emitOperation(auth, 'update', sub, 'allow', evaluation, common);
515
+ }
516
+ const beforeRoot = this.tree.read(path);
517
+ const priors = this.snapshotChildListenerParents();
518
+ this.tree.shallowUpdate(path, resolvedPatch);
519
+ this.fanOut(touched);
520
+ this.fanOutChildren(priors);
521
+ const afterRoot = this.tree.read(path);
522
+ this.emitCommit(auth, 'update', path, {
523
+ data: patch,
524
+ priorState: beforeRoot,
525
+ nextState: afterRoot,
526
+ groupId,
527
+ groupKind: 'batch',
528
+ replay: { requestTime: now },
529
+ detail: { multiPath: false, keys: Object.keys(resolvedPatch) },
530
+ });
531
+ this.emitRtdbEvent(auth, 'update', canonicalPath(path), {
532
+ after: resolvedPatch,
533
+ detail: { multiPath: false, keys: Object.keys(resolvedPatch) },
534
+ });
535
+ this.notifyWrite();
536
+ }
537
+ // Note: `push()` is implemented entirely on the modular surface
538
+ // (`modular.ts`) — the key is minted client-side via {@link mintKey}
539
+ // (no rule check) so it's available synchronously even under a denying
540
+ // rule (DB-B7), and the optional value write is deferred onto the
541
+ // returned ThenableReference's promise via the normal `set` path.
542
+ // ─── Listeners ─────────────────────────────────────────────────────
543
+ /**
544
+ * Subscribe to `onValue`. Fires immediately with the current value
545
+ * (or `{ val: null, exists: false }` for an absent path — locked by
546
+ * the prod SDK's behavior), then on every write that touches `path`
547
+ * or any descendant.
548
+ *
549
+ * Returns an unsubscribe.
550
+ */
551
+ onValue(auth, path, cb, query) {
552
+ // Rules check at subscribe time. A denied subscribe never gets
553
+ // the initial fire — matches production where the listener errors
554
+ // out before any callback.
555
+ const listenerId = this.nextListenerId();
556
+ const at = Date.now();
557
+ const evaluation = this.rules.evaluate('read', path === '/' ? '/' : path, {
558
+ auth,
559
+ mockData: this.tree.snapshot(),
560
+ });
561
+ if (evaluation.check !== 'allow') {
562
+ this.emitOperation(auth, 'listen', path, denyResultFor(evaluation.check), evaluation, {
563
+ at,
564
+ durationMs: Date.now() - at,
565
+ request: query ? { query } : undefined,
566
+ origin: 'listener',
567
+ });
568
+ this.emitListener('errored', { id: listenerId, path }, auth, {
569
+ event: 'value',
570
+ result: 'deny',
571
+ error: {
572
+ code: 'PERMISSION_DENIED',
573
+ message: 'PERMISSION_DENIED: Permission denied',
574
+ reasons: evaluation.reasons,
575
+ },
576
+ });
577
+ throw permissionDenied();
578
+ }
579
+ this.emitOperation(auth, 'listen', path, 'allow', evaluation, {
580
+ at,
581
+ durationMs: Date.now() - at,
582
+ request: query ? { query } : undefined,
583
+ origin: 'listener',
584
+ });
585
+ const listener = { id: listenerId, auth, cb, path, query };
586
+ this.valueListeners.add(listener);
587
+ this.emitListener('attach', listener, auth, {
588
+ event: 'value',
589
+ result: 'allow',
590
+ detail: query ? { query } : undefined,
591
+ });
592
+ // Initial fire — for queries we record the initial window so the
593
+ // diff check on the next write knows what "the previous result"
594
+ // was. For plain listeners we just feed the path snapshot.
595
+ if (query) {
596
+ const initialWindow = executeQuery(this.tree.read(path), query);
597
+ listener.lastWindow = initialWindow;
598
+ const snap = {
599
+ val: rowsToVal(initialWindow),
600
+ exists: initialWindow.length > 0,
601
+ key: this.keyForPath(path),
602
+ };
603
+ try {
604
+ cb(snap);
605
+ this.emitListener('delivery', listener, auth, {
606
+ event: 'value',
607
+ size: initialWindow.length,
608
+ sample: snap.val,
609
+ detail: { initial: true, query: true },
610
+ });
611
+ }
612
+ catch (e) {
613
+ this.emitListener('errored', listener, auth, {
614
+ event: 'value',
615
+ result: 'error',
616
+ error: { message: e instanceof Error ? e.message : String(e) },
617
+ detail: { initial: true, query: true },
618
+ });
619
+ }
620
+ }
621
+ else {
622
+ const snap = this.makeSnap(path);
623
+ // Record the initial value so a subsequent no-change write is
624
+ // suppressed (DB-B8).
625
+ listener.lastValue = snap.val;
626
+ try {
627
+ cb(snap);
628
+ this.emitListener('delivery', listener, auth, {
629
+ event: 'value',
630
+ size: snap.exists ? 1 : 0,
631
+ sample: snap.val,
632
+ detail: { initial: true },
633
+ });
634
+ }
635
+ catch (e) {
636
+ this.emitListener('errored', listener, auth, {
637
+ event: 'value',
638
+ result: 'error',
639
+ error: { message: e instanceof Error ? e.message : String(e) },
640
+ detail: { initial: true },
641
+ });
642
+ }
643
+ }
644
+ return () => {
645
+ this.valueListeners.delete(listener);
646
+ this.emitListener('detach', listener, auth, { event: 'value' });
647
+ };
648
+ }
649
+ /**
650
+ * One-shot `get` against a query — evaluates the constraint chain
651
+ * against the current tree snapshot. Same rules check as plain `get`
652
+ * (the read is at the query's root path; per-child rule evaluation
653
+ * isn't modeled here — RTDB itself rejects queries that span
654
+ * children with mixed read permissions).
655
+ */
656
+ getQuery(auth, path, spec) {
657
+ const at = Date.now();
658
+ const evaluation = this.rules.evaluate('read', path === '/' ? '/' : path, {
659
+ auth,
660
+ mockData: this.tree.snapshot(),
661
+ });
662
+ if (evaluation.check !== 'allow') {
663
+ this.emitOperation(auth, 'get', path, denyResultFor(evaluation.check), evaluation, {
664
+ at,
665
+ durationMs: Date.now() - at,
666
+ request: { query: spec },
667
+ });
668
+ throw permissionDenied();
669
+ }
670
+ const rows = executeQuery(this.tree.read(path), spec);
671
+ this.emitOperation(auth, 'get', path, 'allow', evaluation, {
672
+ at,
673
+ durationMs: Date.now() - at,
674
+ request: { query: spec },
675
+ resourceBefore: { data: rowsToVal(rows), exists: rows.length > 0 },
676
+ });
677
+ return rows;
678
+ }
679
+ /** The last segment of `path`, or `null` for root. Mirrors
680
+ * `DataSnapshot.key`. */
681
+ keyForPath(path) {
682
+ const segs = pathSegments(path);
683
+ return segs.length === 0 ? null : segs[segs.length - 1];
684
+ }
685
+ /**
686
+ * Compute the listener payload for `path` against the current tree.
687
+ * `key` is the last segment of the path, or `null` for root —
688
+ * matches `DataSnapshot.key`.
689
+ */
690
+ makeSnap(path) {
691
+ const val = this.tree.read(path);
692
+ const exists = val !== null;
693
+ const segs = pathSegments(path);
694
+ const key = segs.length === 0 ? null : segs[segs.length - 1];
695
+ return { val, exists, key };
696
+ }
697
+ /**
698
+ * Fan out `value` listeners after a batch of paths were written.
699
+ * Fires every listener whose path either equals one of the touched
700
+ * paths or is an ancestor/descendant of any (the listener observes
701
+ * the subtree it's watching, so any descendant write triggers).
702
+ */
703
+ fanOut(touched) {
704
+ if (this.valueListeners.size === 0)
705
+ return;
706
+ const touchedSet = touched.map((p) => joinPath(pathSegments(p)));
707
+ for (const listener of this.valueListeners) {
708
+ const lp = joinPath(pathSegments(listener.path));
709
+ const subtreeTouched = touchedSet.some((tp) => {
710
+ if (tp === lp)
711
+ return true;
712
+ const lpp = lp === '/' ? '/' : lp + '/';
713
+ const tpp = tp === '/' ? '/' : tp + '/';
714
+ // Listener watches root: every write fires it.
715
+ if (lp === '/')
716
+ return true;
717
+ // Touched is a descendant of the listener's path → fires.
718
+ if (tp.startsWith(lpp))
719
+ return true;
720
+ // Touched is an ancestor of the listener's path → also fires
721
+ // (the listener's subtree might be different now).
722
+ if (lp.startsWith(tpp))
723
+ return true;
724
+ return false;
725
+ });
726
+ if (!subtreeTouched)
727
+ continue;
728
+ if (listener.query) {
729
+ // Query listener: only fire if the windowed result changed.
730
+ // Locked by oracle observation
731
+ // `rtdb-modular-onvalue-with-query.json` — a write OUTSIDE the
732
+ // window doesn't fire the query listener.
733
+ const nextWindow = executeQuery(this.tree.read(listener.path), listener.query);
734
+ if (windowsEqual(listener.lastWindow ?? [], nextWindow)) {
735
+ this.emitListener('suppressed', listener, listener.auth, {
736
+ event: 'value',
737
+ reason: 'no-op',
738
+ detail: { query: true },
739
+ });
740
+ continue;
741
+ }
742
+ listener.lastWindow = nextWindow;
743
+ const snap = {
744
+ val: rowsToVal(nextWindow),
745
+ exists: nextWindow.length > 0,
746
+ key: this.keyForPath(listener.path),
747
+ };
748
+ this.emitListener('delivery', listener, listener.auth, {
749
+ event: 'value',
750
+ size: nextWindow.length,
751
+ sample: snap.val,
752
+ detail: { query: true },
753
+ });
754
+ try {
755
+ listener.cb(snap);
756
+ }
757
+ catch (e) {
758
+ this.emitListener('errored', listener, listener.auth, {
759
+ event: 'value',
760
+ result: 'error',
761
+ error: { message: e instanceof Error ? e.message : String(e) },
762
+ detail: { query: true },
763
+ });
764
+ // Swallow — see plain-listener branch below.
765
+ }
766
+ continue;
767
+ }
768
+ // Plain listener: suppress the fire when the value at the
769
+ // listener's exact path is byte-identical to the last fired value
770
+ // (DB-B8). An ancestor/descendant write that leaves this subtree
771
+ // unchanged must NOT re-fire — RTDB's SyncTree dedups no-change.
772
+ const snap = this.makeSnap(listener.path);
773
+ const last = listener.lastValue;
774
+ if (last !== undefined && jsonValuesEqual(last, snap.val)) {
775
+ this.emitListener('suppressed', listener, listener.auth, {
776
+ event: 'value',
777
+ reason: 'no-op',
778
+ });
779
+ continue;
780
+ }
781
+ listener.lastValue = snap.val;
782
+ this.emitListener('delivery', listener, listener.auth, {
783
+ event: 'value',
784
+ size: snap.exists ? 1 : 0,
785
+ sample: snap.val,
786
+ });
787
+ try {
788
+ listener.cb(snap);
789
+ }
790
+ catch (e) {
791
+ this.emitListener('errored', listener, listener.auth, {
792
+ event: 'value',
793
+ result: 'error',
794
+ error: { message: e instanceof Error ? e.message : String(e) },
795
+ });
796
+ // Swallow — matches `firebase/database` which doesn't let
797
+ // one observer's throw block another. The faulty listener
798
+ // is the caller's problem.
799
+ }
800
+ }
801
+ }
802
+ /**
803
+ * `runTransaction(path, updateFn, options?)` — RTDB-flavored atomic
804
+ * read-modify-write. The contract mirrors `firebase/database`'s
805
+ * modular `runTransaction`:
806
+ *
807
+ * - Read the current value at `path`.
808
+ * - Call `updateFn(currentValue)`.
809
+ * - `currentValue` is `null` for an absent path (oracle:
810
+ * `rtdb-modular-runtransaction-current-value-arg.json` →
811
+ * `missingArgs[0].isNull === true`).
812
+ * - If `updateFn` returns `undefined` → **abort**: no write happens,
813
+ * resolves `{ committed: false, snapshot }` where the snapshot
814
+ * reflects the pre-transaction value (oracle:
815
+ * `rtdb-modular-runtransaction-abort-undefined.json` → `committed:
816
+ * false, snapVal: null, afterValOnServer: 100`).
817
+ * - If `updateFn` returns any defined value → run the write under
818
+ * the current identity's rules; on allow, commit and resolve
819
+ * `{ committed: true, snapshot }` with the new value. On deny,
820
+ * throw the RTDB-transaction error shape (oracle:
821
+ * `rtdb-modular-runtransaction-on-rules-denied-path.json` →
822
+ * `threw: true, message: 'permission_denied', code: null,
823
+ * constructorName: 'Error'`).
824
+ *
825
+ * Single-client harness → no real concurrency to retry against; the
826
+ * documented "optimistic concurrency with retry" is degenerate here.
827
+ * The sandbox doesn't speculatively call `updateFn` with `null` first
828
+ * for a seeded path (prod does — second invocation with the server
829
+ * value); our contract is the SIMPLEST observable: one invocation
830
+ * with the actual current value.
831
+ *
832
+ * `applyLocally` semantics: when omitted or `true`, the in-flight
833
+ * (post-update-fn, pre-commit) value fans out to listeners as an
834
+ * optimistic fire. With `false`, no listener fire until commit. The
835
+ * difference is invisible in a single-client harness with a
836
+ * synchronous commit path; we still respect the flag so consumers can
837
+ * tune intermediate-fire counts under custom assertions.
838
+ *
839
+ * Returns a payload the modular surface wraps in a `DataSnapshot`
840
+ * shape — the backend stays snapshot-agnostic so the rules engine
841
+ * doesn't need to know about ref objects.
842
+ */
843
+ runTransaction(auth, path, updateFn, options) {
844
+ const applyLocally = options?.applyLocally !== false;
845
+ const segs = pathSegments(path);
846
+ const key = segs.length === 0 ? null : segs[segs.length - 1];
847
+ const current = this.tree.read(path);
848
+ // Hand the user-fn a deep clone so mutation of the arg doesn't
849
+ // corrupt our stored tree (consumer code that does
850
+ // `current.count++; return current` would otherwise mutate-then-
851
+ // read the same reference). Array-coerce so the fn sees the same
852
+ // shape `get()` would return (DB-B2).
853
+ const currentForFn = current === null ? null : coerceArrays(cloneJson(current));
854
+ const proposed = updateFn(currentForFn);
855
+ const groupId = this.nextGroupId('transaction');
856
+ if (proposed === undefined) {
857
+ this.emitOperation(auth, 'transaction', path, 'not-applicable', undefined, {
858
+ origin: 'transaction',
859
+ groupId,
860
+ groupKind: 'transaction',
861
+ resourceBefore: { data: current, exists: current !== null },
862
+ detail: { committed: false, aborted: true },
863
+ });
864
+ // Abort — no write, no rule check, no listener fire. Resolve with
865
+ // the pre-transaction value (oracle pinned for the seeded case:
866
+ // `afterValOnServer: 100` preserved).
867
+ return { committed: false, val: current, key };
868
+ }
869
+ // Resolve sentinels + normalize first so the rule check sees the
870
+ // stored shape (consistent with `set`): array coercion, null/empty
871
+ // pruning, key validation.
872
+ const now = Date.now();
873
+ const resolved = normalizeWrite(resolveSentinels(proposed, now, current), path === '/' ? '' : path);
874
+ // Apply locally if allowed — fires listeners with the optimistic
875
+ // value BEFORE the rule check. The single-client sandbox has a
876
+ // synchronous commit path so this is effectively a no-op in
877
+ // practice; the flag is honored for parity with prod's contract.
878
+ if (applyLocally) {
879
+ // Stash the prior value so a denial below can roll back. The
880
+ // tree's write replaces; we hold the snapshot of the pre-write
881
+ // root to restore on rule-deny.
882
+ const priorRoot = this.tree.snapshot();
883
+ this.tree.write(path, resolved);
884
+ this.fanOut([path]);
885
+ const at = Date.now();
886
+ const evaluation = this.rules.evaluate('write', path === '/' ? '/' : path, {
887
+ auth,
888
+ mockData: priorRoot,
889
+ newData: resolved,
890
+ });
891
+ if (evaluation.check !== 'allow') {
892
+ this.emitOperation(auth, 'transaction', path, denyResultFor(evaluation.check), evaluation, {
893
+ at,
894
+ durationMs: Date.now() - at,
895
+ origin: 'transaction',
896
+ request: { data: proposed, resourceData: proposed },
897
+ resourceBefore: { data: current, exists: current !== null },
898
+ resourceAfter: { data: resolved, exists: resolved !== null },
899
+ groupId,
900
+ groupKind: 'transaction',
901
+ });
902
+ // Roll back the local apply and re-fan-out so listeners see
903
+ // the restored value. Then throw the transaction-specific
904
+ // denial shape.
905
+ this.tree.restore(priorRoot);
906
+ this.fanOut([path]);
907
+ throw transactionPermissionDenied();
908
+ }
909
+ this.emitOperation(auth, 'transaction', path, 'allow', evaluation, {
910
+ at,
911
+ durationMs: Date.now() - at,
912
+ origin: 'transaction',
913
+ request: { data: proposed, resourceData: proposed },
914
+ resourceBefore: { data: current, exists: current !== null },
915
+ resourceAfter: { data: resolved, exists: resolved !== null },
916
+ groupId,
917
+ groupKind: 'transaction',
918
+ });
919
+ this.emitCommit(auth, 'transaction', path, {
920
+ data: proposed,
921
+ priorState: current,
922
+ nextState: resolved,
923
+ groupId,
924
+ groupKind: 'transaction',
925
+ replay: { requestTime: now },
926
+ detail: { committed: true, applyLocally: true },
927
+ });
928
+ this.emitRtdbEvent(auth, 'transaction', canonicalPath(path), {
929
+ before: current,
930
+ after: resolved,
931
+ detail: { committed: true },
932
+ });
933
+ this.notifyWrite();
934
+ return { committed: true, val: resolved, key };
935
+ }
936
+ // applyLocally: false — rule-check FIRST, write only if allowed,
937
+ // listeners see only the committed value.
938
+ const at = Date.now();
939
+ const evaluation = this.rules.evaluate('write', path === '/' ? '/' : path, {
940
+ auth,
941
+ mockData: this.tree.snapshot(),
942
+ newData: resolved,
943
+ });
944
+ if (evaluation.check !== 'allow') {
945
+ this.emitOperation(auth, 'transaction', path, denyResultFor(evaluation.check), evaluation, {
946
+ at,
947
+ durationMs: Date.now() - at,
948
+ origin: 'transaction',
949
+ request: { data: proposed, resourceData: proposed },
950
+ resourceBefore: { data: current, exists: current !== null },
951
+ resourceAfter: { data: resolved, exists: resolved !== null },
952
+ groupId,
953
+ groupKind: 'transaction',
954
+ });
955
+ throw transactionPermissionDenied();
956
+ }
957
+ this.emitOperation(auth, 'transaction', path, 'allow', evaluation, {
958
+ at,
959
+ durationMs: Date.now() - at,
960
+ origin: 'transaction',
961
+ request: { data: proposed, resourceData: proposed },
962
+ resourceBefore: { data: current, exists: current !== null },
963
+ resourceAfter: { data: resolved, exists: resolved !== null },
964
+ groupId,
965
+ groupKind: 'transaction',
966
+ });
967
+ this.tree.write(path, resolved);
968
+ this.fanOut([path]);
969
+ this.emitCommit(auth, 'transaction', path, {
970
+ data: proposed,
971
+ priorState: current,
972
+ nextState: resolved,
973
+ groupId,
974
+ groupKind: 'transaction',
975
+ replay: { requestTime: now },
976
+ detail: { committed: true, applyLocally: false },
977
+ });
978
+ this.emitRtdbEvent(auth, 'transaction', canonicalPath(path), {
979
+ before: current,
980
+ after: resolved,
981
+ detail: { committed: true },
982
+ });
983
+ return { committed: true, val: resolved, key };
984
+ }
985
+ // ─── Child-event listeners (Tier 2) ────────────────────────────────
986
+ //
987
+ // Per-child diff fanout. Each child listener watches a parent path;
988
+ // on write we compare the parent's prior children against its next
989
+ // children and dispatch `child_added` / `child_changed` /
990
+ // `child_removed` accordingly.
991
+ //
992
+ // `child_moved` requires an ordered query (see oracle observation
993
+ // `rtdb-modular-onchildmoved-with-orderby.json`) — for plain refs
994
+ // it never fires. Tier 3 will wire the ordered-query path in.
995
+ /**
996
+ * Subscribe to a child event at `path`.
997
+ *
998
+ * Semantics (locked by oracle observations under
999
+ * `packages/conformance/observations/rtdb-modular/rtdb-modular-onchild*.json`):
1000
+ *
1001
+ * - `child_added`: replays every existing direct child of `path` on
1002
+ * subscribe (one fire per existing key, in current key-iteration
1003
+ * order — matches the upstream `orderByKey` default observed in
1004
+ * `rtdb-modular-onchildadded-initial-replay`). Subsequent
1005
+ * additions fire once each.
1006
+ * - `child_changed`: no initial replay. Fires when an existing
1007
+ * child's value transitions to a NEW non-null value. Snapshot
1008
+ * carries the NEW value.
1009
+ * - `child_removed`: no initial replay. Fires when a child is
1010
+ * deleted (its value transitions to absent). Snapshot carries
1011
+ * the PRIOR (now-removed) value.
1012
+ * - `child_moved`: ordered-query only — never fires on a plain
1013
+ * ref (matches the upstream contract; Tier 3 will wire ordered
1014
+ * queries in).
1015
+ *
1016
+ * Rules check happens at subscribe time, identical to `onValue`. A
1017
+ * denied subscribe throws the plain-`Error` `PERMISSION_DENIED`
1018
+ * shape and the listener is never registered.
1019
+ *
1020
+ * Returns an idempotent unsubscribe.
1021
+ */
1022
+ onChild(auth, event, path, cb, spec) {
1023
+ const listenerId = this.nextListenerId();
1024
+ const at = Date.now();
1025
+ const evaluation = this.rules.evaluate('read', path === '/' ? '/' : path, {
1026
+ auth,
1027
+ mockData: this.tree.snapshot(),
1028
+ });
1029
+ if (evaluation.check !== 'allow') {
1030
+ this.emitOperation(auth, 'listen', path, denyResultFor(evaluation.check), evaluation, {
1031
+ at,
1032
+ durationMs: Date.now() - at,
1033
+ origin: 'listener',
1034
+ detail: { event },
1035
+ });
1036
+ this.emitListener('errored', { id: listenerId, path }, auth, {
1037
+ event,
1038
+ result: 'deny',
1039
+ error: {
1040
+ code: 'PERMISSION_DENIED',
1041
+ message: 'PERMISSION_DENIED: Permission denied',
1042
+ reasons: evaluation.reasons,
1043
+ },
1044
+ });
1045
+ throw permissionDenied();
1046
+ }
1047
+ this.emitOperation(auth, 'listen', path, 'allow', evaluation, {
1048
+ at,
1049
+ durationMs: Date.now() - at,
1050
+ origin: 'listener',
1051
+ detail: { event },
1052
+ });
1053
+ const listener = { id: listenerId, auth, event, path, cb, spec };
1054
+ this.childListeners.add(listener);
1055
+ this.emitListener('attach', listener, auth, {
1056
+ event,
1057
+ result: 'allow',
1058
+ detail: spec ? { query: spec } : undefined,
1059
+ });
1060
+ // Initial state. A query child listener records its ordered window so
1061
+ // the next write's diff knows what "the previous result" was; a
1062
+ // `child_added` query listener also replays the window (in window
1063
+ // order). A plain-ref listener replays raw direct children.
1064
+ if (spec) {
1065
+ const initialWindow = executeQuery(this.tree.read(path), spec);
1066
+ listener.lastWindow = initialWindow;
1067
+ if (event === 'child_added') {
1068
+ for (const { key, value } of initialWindow) {
1069
+ this.emitListener('delivery', listener, auth, {
1070
+ event,
1071
+ size: 1,
1072
+ sample: { key, val: value },
1073
+ detail: { initial: true, query: true },
1074
+ });
1075
+ try {
1076
+ cb({ key, val: value });
1077
+ }
1078
+ catch (e) {
1079
+ this.emitListener('errored', listener, auth, {
1080
+ event,
1081
+ result: 'error',
1082
+ error: { message: e instanceof Error ? e.message : String(e) },
1083
+ detail: { initial: true, query: true },
1084
+ });
1085
+ // Swallow — see fanOut.
1086
+ }
1087
+ }
1088
+ }
1089
+ }
1090
+ else if (event === 'child_added') {
1091
+ // Initial replay — only `child_added` replays existing children.
1092
+ for (const { key, val } of this.directChildren(path)) {
1093
+ this.emitListener('delivery', listener, auth, {
1094
+ event,
1095
+ size: 1,
1096
+ sample: { key, val },
1097
+ detail: { initial: true },
1098
+ });
1099
+ try {
1100
+ cb({ key, val });
1101
+ }
1102
+ catch (e) {
1103
+ this.emitListener('errored', listener, auth, {
1104
+ event,
1105
+ result: 'error',
1106
+ error: { message: e instanceof Error ? e.message : String(e) },
1107
+ detail: { initial: true },
1108
+ });
1109
+ // Swallow — see fanOut.
1110
+ }
1111
+ }
1112
+ }
1113
+ return () => {
1114
+ this.childListeners.delete(listener);
1115
+ this.emitListener('detach', listener, auth, { event });
1116
+ };
1117
+ }
1118
+ /**
1119
+ * `off(refPath, eventType?, callback?)` — unsubscribe variant. Matches
1120
+ * the upstream contract (oracle: `rtdb-modular-off-stops-child-fires`):
1121
+ *
1122
+ * - `off(refPath)` removes ALL listeners (value + child) at the path.
1123
+ * - `off(refPath, 'value')` removes only `value` listeners at the path.
1124
+ * - `off(refPath, 'child_added')` (or any child event type) removes
1125
+ * only that child-event variety at the path.
1126
+ * - `off(refPath, eventType, cb)` removes only the matching callback.
1127
+ *
1128
+ * No-throw on absent listeners — matches the upstream behavior.
1129
+ */
1130
+ off(path, eventType, callback) {
1131
+ const canonical = joinPath(pathSegments(path));
1132
+ // Value listeners.
1133
+ if (eventType === undefined || eventType === 'value') {
1134
+ for (const l of [...this.valueListeners]) {
1135
+ if (joinPath(pathSegments(l.path)) !== canonical)
1136
+ continue;
1137
+ if (callback !== undefined && l.cb !== callback)
1138
+ continue;
1139
+ this.valueListeners.delete(l);
1140
+ this.emitListener('detach', l, l.auth, { event: 'value' });
1141
+ }
1142
+ }
1143
+ // Child listeners.
1144
+ const childEvents = [
1145
+ 'child_added',
1146
+ 'child_changed',
1147
+ 'child_removed',
1148
+ 'child_moved',
1149
+ ];
1150
+ const targetEvents = eventType === undefined
1151
+ ? childEvents
1152
+ : eventType === 'value'
1153
+ ? []
1154
+ : [eventType];
1155
+ if (targetEvents.length > 0) {
1156
+ for (const l of [...this.childListeners]) {
1157
+ if (!targetEvents.includes(l.event))
1158
+ continue;
1159
+ if (joinPath(pathSegments(l.path)) !== canonical)
1160
+ continue;
1161
+ if (callback !== undefined && l.cb !== callback)
1162
+ continue;
1163
+ this.childListeners.delete(l);
1164
+ this.emitListener('detach', l, l.auth, { event: l.event });
1165
+ }
1166
+ }
1167
+ }
1168
+ /** Direct children of `path` as `{ key, val }` pairs. Returns [] if
1169
+ * the path is absent or its value isn't an object. Key iteration
1170
+ * follows `Object.keys` order, which matches `firebase/database`'s
1171
+ * `orderByKey` default (insertion order for non-numeric keys). */
1172
+ directChildren(path) {
1173
+ const v = this.tree.read(path);
1174
+ if (v === null || typeof v !== 'object' || Array.isArray(v))
1175
+ return [];
1176
+ const out = [];
1177
+ for (const [k, val] of Object.entries(v)) {
1178
+ out.push({ key: k, val });
1179
+ }
1180
+ return out;
1181
+ }
1182
+ /** Snapshot the current direct children of every registered child
1183
+ * listener's parent path. Used to capture the "prior" half of the
1184
+ * diff before a write applies. */
1185
+ snapshotChildListenerParents() {
1186
+ const out = new Map();
1187
+ if (this.childListeners.size === 0)
1188
+ return out;
1189
+ for (const listener of this.childListeners) {
1190
+ const canonical = joinPath(pathSegments(listener.path));
1191
+ if (out.has(canonical))
1192
+ continue;
1193
+ const map = new Map();
1194
+ for (const { key, val } of this.directChildren(canonical)) {
1195
+ map.set(key, val);
1196
+ }
1197
+ out.set(canonical, map);
1198
+ }
1199
+ return out;
1200
+ }
1201
+ /**
1202
+ * Fan out child events after a write. `priorByParent` is the snapshot
1203
+ * captured by `snapshotChildListenerParents` before the write applied.
1204
+ *
1205
+ * For each listener, compute the diff between prior and current
1206
+ * children, then dispatch:
1207
+ * - `child_added` when a key appears that wasn't in prior.
1208
+ * - `child_changed` when a key's value transitions.
1209
+ * - `child_removed` when a prior key is gone.
1210
+ */
1211
+ fanOutChildren(priorByParent) {
1212
+ if (this.childListeners.size === 0)
1213
+ return;
1214
+ // Group PLAIN-ref listeners by their canonical parent path so we only
1215
+ // do one diff per parent regardless of how many listeners are attached.
1216
+ // Query listeners diff their ordered window per-listener (below) — the
1217
+ // raw key-set diff would ignore the window/ordering.
1218
+ const byParent = new Map();
1219
+ for (const listener of this.childListeners) {
1220
+ if (listener.spec) {
1221
+ this.fanOutQueryChild(listener);
1222
+ continue;
1223
+ }
1224
+ const canonical = joinPath(pathSegments(listener.path));
1225
+ const arr = byParent.get(canonical) ?? [];
1226
+ arr.push(listener);
1227
+ byParent.set(canonical, arr);
1228
+ }
1229
+ for (const [parentPath, listeners] of byParent) {
1230
+ const prior = priorByParent.get(parentPath) ?? new Map();
1231
+ const next = new Map();
1232
+ for (const { key, val } of this.directChildren(parentPath)) {
1233
+ next.set(key, val);
1234
+ }
1235
+ // Build event lists.
1236
+ const added = [];
1237
+ const changed = [];
1238
+ const removed = [];
1239
+ for (const [k, v] of next) {
1240
+ if (!prior.has(k)) {
1241
+ added.push({ key: k, val: v });
1242
+ }
1243
+ else if (!jsonValuesEqual(prior.get(k), v)) {
1244
+ changed.push({ key: k, val: v });
1245
+ }
1246
+ }
1247
+ for (const [k, v] of prior) {
1248
+ if (!next.has(k)) {
1249
+ removed.push({ key: k, val: v });
1250
+ }
1251
+ }
1252
+ for (const listener of listeners) {
1253
+ let events;
1254
+ switch (listener.event) {
1255
+ case 'child_added':
1256
+ events = added;
1257
+ break;
1258
+ case 'child_changed':
1259
+ events = changed;
1260
+ break;
1261
+ case 'child_removed':
1262
+ events = removed;
1263
+ break;
1264
+ case 'child_moved':
1265
+ events = [];
1266
+ break; // ordered-query only
1267
+ }
1268
+ for (const ev of events) {
1269
+ this.emitListener('delivery', listener, listener.auth, {
1270
+ event: listener.event,
1271
+ size: 1,
1272
+ sample: ev,
1273
+ });
1274
+ try {
1275
+ listener.cb(ev);
1276
+ }
1277
+ catch (e) {
1278
+ this.emitListener('errored', listener, listener.auth, {
1279
+ event: listener.event,
1280
+ result: 'error',
1281
+ error: { message: e instanceof Error ? e.message : String(e) },
1282
+ });
1283
+ // Swallow — see fanOut.
1284
+ }
1285
+ }
1286
+ }
1287
+ }
1288
+ }
1289
+ /**
1290
+ * Fan out a single QUERY child listener after a write, diffing the
1291
+ * ordered window against the listener's last-fired window:
1292
+ *
1293
+ * - a key that ENTERED the window emits `child_added` (window order);
1294
+ * - a key that LEFT the window emits `child_removed` (carrying its
1295
+ * prior value);
1296
+ * - a key that stayed in-window but changed value emits `child_changed`.
1297
+ *
1298
+ * `child_moved` (reorder within the window) is deliberately NOT emitted
1299
+ * — the reorder / `previousChildName` semantics are held pending fresh
1300
+ * oracle captures (matrix row `rtdb-modular#137`). The window is always
1301
+ * advanced so a later real add/change/remove diffs correctly.
1302
+ */
1303
+ fanOutQueryChild(listener) {
1304
+ const prior = listener.lastWindow ?? [];
1305
+ const next = executeQuery(this.tree.read(listener.path), listener.spec);
1306
+ listener.lastWindow = next;
1307
+ const priorByKey = new Map(prior.map((r) => [r.key, r.value]));
1308
+ const nextByKey = new Map(next.map((r) => [r.key, r.value]));
1309
+ let events = [];
1310
+ switch (listener.event) {
1311
+ case 'child_added':
1312
+ for (const { key, value } of next) {
1313
+ if (!priorByKey.has(key))
1314
+ events.push({ key, val: value });
1315
+ }
1316
+ break;
1317
+ case 'child_changed':
1318
+ for (const { key, value } of next) {
1319
+ if (priorByKey.has(key) && !jsonValuesEqual(priorByKey.get(key), value)) {
1320
+ events.push({ key, val: value });
1321
+ }
1322
+ }
1323
+ break;
1324
+ case 'child_removed':
1325
+ for (const { key, value } of prior) {
1326
+ if (!nextByKey.has(key))
1327
+ events.push({ key, val: value });
1328
+ }
1329
+ break;
1330
+ case 'child_moved':
1331
+ // Held — reorder semantics pending two new oracle captures.
1332
+ events = [];
1333
+ break;
1334
+ }
1335
+ for (const ev of events) {
1336
+ this.emitListener('delivery', listener, listener.auth, {
1337
+ event: listener.event,
1338
+ size: 1,
1339
+ sample: ev,
1340
+ detail: { query: true },
1341
+ });
1342
+ try {
1343
+ listener.cb(ev);
1344
+ }
1345
+ catch (e) {
1346
+ this.emitListener('errored', listener, listener.auth, {
1347
+ event: listener.event,
1348
+ result: 'error',
1349
+ error: { message: e instanceof Error ? e.message : String(e) },
1350
+ detail: { query: true },
1351
+ });
1352
+ // Swallow — see fanOut.
1353
+ }
1354
+ }
1355
+ }
1356
+ // ─── Persistence (PersistableService) ──────────────────────────────
1357
+ //
1358
+ // The RTDB tree rides the sandbox persistence controller's `services`
1359
+ // blob exactly like the auth user DB. `getDatabase(sandbox)` registers
1360
+ // these hooks once per sandbox (see modular.ts). Together they give RTDB
1361
+ // the same durability contract as Firestore/auth: worker death / browser
1362
+ // restart restores the whole tree instead of losing it.
1363
+ /** Serialize the whole tree as a plain JSON value for the persistence
1364
+ * snapshot. Defensive deep-copy (via `DataTree.snapshot`). */
1365
+ exportTree() {
1366
+ return this.tree.snapshot();
1367
+ }
1368
+ /**
1369
+ * Replace the whole tree with a persisted snapshot, then fire listeners
1370
+ * so any live UI (Studio's RTDB tab) converges on the restored data
1371
+ * rather than showing a stale/empty view.
1372
+ *
1373
+ * REPLACE, not merge — the tree becomes EXACTLY the snapshot. On boot /
1374
+ * late-registration the tree is empty so this is a pure load; for a
1375
+ * runtime `loadSnapshot()` it clobbers divergent state, matching auth's
1376
+ * restore policy.
1377
+ *
1378
+ * Notification: we capture each child-listener parent's prior children
1379
+ * BEFORE the swap, then fan out value listeners from the root (every
1380
+ * listener re-reads its path) and child listeners against the diff. The
1381
+ * value-listener no-op suppression (DB-B8) means a listener whose subtree
1382
+ * is byte-identical to the snapshot won't spuriously re-fire.
1383
+ */
1384
+ restoreTree(root) {
1385
+ const priors = this.snapshotChildListenerParents();
1386
+ this.tree.restore(root ?? {});
1387
+ this.fanOut(['/']);
1388
+ this.fanOutChildren(priors);
1389
+ }
1390
+ /**
1391
+ * Register a persistence change-subscriber. Returns an unsubscribe.
1392
+ * Fired (best-effort, isolated) after every committed tree mutation so
1393
+ * the controller schedules a debounced flush.
1394
+ */
1395
+ subscribeWrites(onChange) {
1396
+ this.writeSubscribers.add(onChange);
1397
+ return () => {
1398
+ this.writeSubscribers.delete(onChange);
1399
+ };
1400
+ }
1401
+ /** Notify persistence subscribers that the tree changed. Best-effort +
1402
+ * isolated — a subscriber throw must never break the write. */
1403
+ notifyWrite() {
1404
+ if (this.writeSubscribers.size === 0)
1405
+ return;
1406
+ for (const sub of this.writeSubscribers) {
1407
+ try {
1408
+ sub();
1409
+ }
1410
+ catch {
1411
+ // Observational — never let a flush-scheduler throw break a write.
1412
+ }
1413
+ }
1414
+ }
1415
+ /** Generate a key without writing (advisory — same key the next
1416
+ * `push(path)` would produce). Used by the `ref.push().key`
1417
+ * pattern. Each call returns a fresh key. */
1418
+ mintKey() {
1419
+ return generatePushId();
1420
+ }
1421
+ /** Test helper — count value listeners. */
1422
+ listenerCount() {
1423
+ return this.valueListeners.size;
1424
+ }
1425
+ /** Test helper — count child listeners. */
1426
+ childListenerCount() {
1427
+ return this.childListeners.size;
1428
+ }
1429
+ }
1430
+ /** Normalize a path to its canonical `/`-joined form for event paths. */
1431
+ function canonicalPath(path) {
1432
+ return joinPath(pathSegments(path));
1433
+ }
1434
+ /**
1435
+ * Transaction-specific denial constructor. Pinned by oracle observation
1436
+ * `rtdb-modular-runtransaction-on-rules-denied-path.json`:
1437
+ *
1438
+ * - plain `Error` (NOT `FirebaseError`).
1439
+ * - `.message === 'permission_denied'` (LOWERCASE — distinct from
1440
+ * `set`/`get`'s `'PERMISSION_DENIED: Permission denied'` shape).
1441
+ * - **No** `.code` field on the error (prod observation shows
1442
+ * `code: null` — the FirebaseError code shape isn't applied to
1443
+ * transaction rejections).
1444
+ * - `.constructor.name === 'Error'`.
1445
+ *
1446
+ * This is a deliberately distinct shape from the regular
1447
+ * `permissionDenied()` used by `set`/`get`/`update` — prod really does
1448
+ * emit a different surface for `runTransaction` rejections. The test
1449
+ * suite asserts both shapes so a future "unify the error shape"
1450
+ * refactor would catch the divergence at unit time.
1451
+ */
1452
+ function transactionPermissionDenied() {
1453
+ return new Error('permission_denied');
1454
+ }
1455
+ /**
1456
+ * Pack an ordered list of `QueryRow`s into a JSON object — the shape
1457
+ * the `DataSnapshot.val()` contract returns from a query.
1458
+ *
1459
+ * RTDB query snapshots present the windowed rows as a key→value object;
1460
+ * ordering is observable via `snap.forEach` (NOT through `val()`'s
1461
+ * iteration order, which is unspecified for plain objects but happens
1462
+ * to be insertion order in modern V8). The sandbox snap-wrapper
1463
+ * preserves the row order so `snap.forEach` yields children in the
1464
+ * computed query order.
1465
+ */
1466
+ function rowsToVal(rows) {
1467
+ if (rows.length === 0)
1468
+ return null;
1469
+ const out = {};
1470
+ for (const { key, value } of rows) {
1471
+ out[key] = value;
1472
+ }
1473
+ return out;
1474
+ }
1475
+ /** Compare two windowed result lists. Used to decide whether a query
1476
+ * listener should re-fire. Uses RTDB JSON value equality rather than
1477
+ * `JSON.stringify` so a re-write that only reorders object keys is
1478
+ * correctly treated as "no change" (DB-B11: RTDB treats objects as
1479
+ * order-equal). */
1480
+ function windowsEqual(a, b) {
1481
+ if (a.length !== b.length)
1482
+ return false;
1483
+ for (let i = 0; i < a.length; i++) {
1484
+ const ai = a[i];
1485
+ const bi = b[i];
1486
+ if (ai.key !== bi.key)
1487
+ return false;
1488
+ if (!jsonValuesEqual(ai.value, bi.value))
1489
+ return false;
1490
+ }
1491
+ return true;
1492
+ }
1493
+ // Re-exports the modular SDK uses internally.
1494
+ export { cloneJson, pathSegments, joinPath } from './data-tree.js';
1495
+ //# sourceMappingURL=backend.js.map