@dereekb/firebase-server 12.6.21 → 13.0.0

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 (332) hide show
  1. package/LICENSE +1 -1
  2. package/index.cjs.js +2937 -0
  3. package/index.esm.js +2775 -0
  4. package/mailgun/index.cjs.js +48 -0
  5. package/mailgun/index.esm.js +46 -0
  6. package/mailgun/package.json +26 -6
  7. package/model/index.cjs.js +5298 -0
  8. package/model/index.d.ts +1 -0
  9. package/model/index.esm.js +5161 -0
  10. package/model/package.json +31 -3
  11. package/model/src/lib/notification/notification.module.d.ts +10 -10
  12. package/model/src/lib/storagefile/storagefile.task.service.handler.d.ts +3 -14
  13. package/package.json +48 -27
  14. package/src/lib/auth/auth.context.d.ts +1 -1
  15. package/src/lib/auth/auth.service.d.ts +1 -1
  16. package/src/lib/function/assert.d.ts +2 -2
  17. package/src/lib/function/context.d.ts +1 -1
  18. package/src/lib/index.d.ts +1 -0
  19. package/src/lib/nest/app.d.ts +1 -1
  20. package/src/lib/nest/development/development.app.function.d.ts +1 -2
  21. package/src/lib/nest/function/call.d.ts +1 -1
  22. package/src/lib/nest/function/context.d.ts +0 -4
  23. package/src/lib/nest/function/index.d.ts +0 -1
  24. package/src/lib/nest/function/nest.d.ts +1 -1
  25. package/src/lib/nest/function/v2/blocking.d.ts +3 -2
  26. package/src/lib/nest/model/crud.assert.function.d.ts +0 -4
  27. package/src/lib/storage/storage.d.ts +1 -1
  28. package/src/lib/type.d.ts +9 -0
  29. package/test/index.cjs.js +1324 -0
  30. package/test/index.d.ts +1 -0
  31. package/test/index.esm.js +1247 -0
  32. package/test/package.json +34 -3
  33. package/test/src/lib/firebase/firebase.admin.auth.d.ts +22 -13
  34. package/test/src/lib/firebase/firebase.admin.collection.d.ts +6 -6
  35. package/test/src/lib/firebase/firebase.admin.d.ts +10 -10
  36. package/test/src/lib/firebase/firebase.admin.function.d.ts +9 -9
  37. package/test/src/lib/firebase/firebase.admin.nest.d.ts +8 -8
  38. package/test/src/lib/firebase/firebase.admin.nest.function.d.ts +9 -9
  39. package/test/src/lib/firebase/firebase.test.d.ts +30 -0
  40. package/test/src/lib/firebase/index.d.ts +1 -1
  41. package/test/src/lib/firestore/firestore.admin.d.ts +3 -3
  42. package/test/src/lib/firestore/firestore.d.ts +2 -2
  43. package/test/src/lib/storage/storage.admin.d.ts +3 -3
  44. package/test/src/lib/storage/storage.d.ts +2 -2
  45. package/zoho/LICENSE +1 -1
  46. package/zoho/index.d.ts +1 -0
  47. package/zoho/index.esm.js +2 -2
  48. package/zoho/package.json +12 -8
  49. package/CHANGELOG.md +0 -2233
  50. package/mailgun/src/index.js +0 -5
  51. package/mailgun/src/index.js.map +0 -1
  52. package/mailgun/src/lib/auth.mailgun.js +0 -41
  53. package/mailgun/src/lib/auth.mailgun.js.map +0 -1
  54. package/mailgun/src/lib/index.js +0 -5
  55. package/mailgun/src/lib/index.js.map +0 -1
  56. package/model/src/index.js +0 -5
  57. package/model/src/index.js.map +0 -1
  58. package/model/src/lib/index.js +0 -7
  59. package/model/src/lib/index.js.map +0 -1
  60. package/model/src/lib/mailgun/index.js +0 -5
  61. package/model/src/lib/mailgun/index.js.map +0 -1
  62. package/model/src/lib/mailgun/notification.send.service.mailgun.js +0 -68
  63. package/model/src/lib/mailgun/notification.send.service.mailgun.js.map +0 -1
  64. package/model/src/lib/notification/index.js +0 -20
  65. package/model/src/lib/notification/index.js.map +0 -1
  66. package/model/src/lib/notification/notification.action.init.service.js +0 -230
  67. package/model/src/lib/notification/notification.action.init.service.js.map +0 -1
  68. package/model/src/lib/notification/notification.action.service.js +0 -1487
  69. package/model/src/lib/notification/notification.action.service.js.map +0 -1
  70. package/model/src/lib/notification/notification.config.js +0 -13
  71. package/model/src/lib/notification/notification.config.js.map +0 -1
  72. package/model/src/lib/notification/notification.config.service.js +0 -60
  73. package/model/src/lib/notification/notification.config.service.js.map +0 -1
  74. package/model/src/lib/notification/notification.create.run.js +0 -59
  75. package/model/src/lib/notification/notification.create.run.js.map +0 -1
  76. package/model/src/lib/notification/notification.error.js +0 -87
  77. package/model/src/lib/notification/notification.error.js.map +0 -1
  78. package/model/src/lib/notification/notification.expedite.service.js +0 -112
  79. package/model/src/lib/notification/notification.expedite.service.js.map +0 -1
  80. package/model/src/lib/notification/notification.module.js +0 -106
  81. package/model/src/lib/notification/notification.module.js.map +0 -1
  82. package/model/src/lib/notification/notification.send.js +0 -3
  83. package/model/src/lib/notification/notification.send.js.map +0 -1
  84. package/model/src/lib/notification/notification.send.service.js +0 -10
  85. package/model/src/lib/notification/notification.send.service.js.map +0 -1
  86. package/model/src/lib/notification/notification.send.service.notificationsummary.js +0 -104
  87. package/model/src/lib/notification/notification.send.service.notificationsummary.js.map +0 -1
  88. package/model/src/lib/notification/notification.send.service.text.js +0 -29
  89. package/model/src/lib/notification/notification.send.service.text.js.map +0 -1
  90. package/model/src/lib/notification/notification.task.service.handler.js +0 -65
  91. package/model/src/lib/notification/notification.task.service.handler.js.map +0 -1
  92. package/model/src/lib/notification/notification.task.service.js +0 -10
  93. package/model/src/lib/notification/notification.task.service.js.map +0 -1
  94. package/model/src/lib/notification/notification.task.service.util.js +0 -27
  95. package/model/src/lib/notification/notification.task.service.util.js.map +0 -1
  96. package/model/src/lib/notification/notification.task.subtask.handler.js +0 -256
  97. package/model/src/lib/notification/notification.task.subtask.handler.js.map +0 -1
  98. package/model/src/lib/notification/notification.util.js +0 -478
  99. package/model/src/lib/notification/notification.util.js.map +0 -1
  100. package/model/src/lib/storagefile/index.js +0 -12
  101. package/model/src/lib/storagefile/index.js.map +0 -1
  102. package/model/src/lib/storagefile/storagefile.action.init.service.js +0 -155
  103. package/model/src/lib/storagefile/storagefile.action.init.service.js.map +0 -1
  104. package/model/src/lib/storagefile/storagefile.action.server.js +0 -797
  105. package/model/src/lib/storagefile/storagefile.action.server.js.map +0 -1
  106. package/model/src/lib/storagefile/storagefile.error.js +0 -106
  107. package/model/src/lib/storagefile/storagefile.error.js.map +0 -1
  108. package/model/src/lib/storagefile/storagefile.module.js +0 -64
  109. package/model/src/lib/storagefile/storagefile.module.js.map +0 -1
  110. package/model/src/lib/storagefile/storagefile.task.service.handler.js +0 -287
  111. package/model/src/lib/storagefile/storagefile.task.service.handler.js.map +0 -1
  112. package/model/src/lib/storagefile/storagefile.upload.service.initializer.js +0 -180
  113. package/model/src/lib/storagefile/storagefile.upload.service.initializer.js.map +0 -1
  114. package/model/src/lib/storagefile/storagefile.upload.service.js +0 -10
  115. package/model/src/lib/storagefile/storagefile.upload.service.js.map +0 -1
  116. package/model/src/lib/storagefile/storagefile.util.js +0 -54
  117. package/model/src/lib/storagefile/storagefile.util.js.map +0 -1
  118. package/src/index.js +0 -5
  119. package/src/index.js.map +0 -1
  120. package/src/lib/auth/auth.context.js +0 -13
  121. package/src/lib/auth/auth.context.js.map +0 -1
  122. package/src/lib/auth/auth.service.error.js +0 -34
  123. package/src/lib/auth/auth.service.error.js.map +0 -1
  124. package/src/lib/auth/auth.service.js +0 -427
  125. package/src/lib/auth/auth.service.js.map +0 -1
  126. package/src/lib/auth/auth.util.js +0 -23
  127. package/src/lib/auth/auth.util.js.map +0 -1
  128. package/src/lib/auth/index.js +0 -8
  129. package/src/lib/auth/index.js.map +0 -1
  130. package/src/lib/env/env.service.js +0 -7
  131. package/src/lib/env/env.service.js.map +0 -1
  132. package/src/lib/env/index.js +0 -5
  133. package/src/lib/env/index.js.map +0 -1
  134. package/src/lib/firestore/array.js +0 -34
  135. package/src/lib/firestore/array.js.map +0 -1
  136. package/src/lib/firestore/driver.accessor.batch.js +0 -93
  137. package/src/lib/firestore/driver.accessor.batch.js.map +0 -1
  138. package/src/lib/firestore/driver.accessor.default.js +0 -62
  139. package/src/lib/firestore/driver.accessor.default.js.map +0 -1
  140. package/src/lib/firestore/driver.accessor.js +0 -50
  141. package/src/lib/firestore/driver.accessor.js.map +0 -1
  142. package/src/lib/firestore/driver.accessor.transaction.js +0 -96
  143. package/src/lib/firestore/driver.accessor.transaction.js.map +0 -1
  144. package/src/lib/firestore/driver.js +0 -14
  145. package/src/lib/firestore/driver.js.map +0 -1
  146. package/src/lib/firestore/driver.query.js +0 -55
  147. package/src/lib/firestore/driver.query.js.map +0 -1
  148. package/src/lib/firestore/firestore.js +0 -10
  149. package/src/lib/firestore/firestore.js.map +0 -1
  150. package/src/lib/firestore/increment.js +0 -17
  151. package/src/lib/firestore/increment.js.map +0 -1
  152. package/src/lib/firestore/index.js +0 -9
  153. package/src/lib/firestore/index.js.map +0 -1
  154. package/src/lib/function/assert.js +0 -68
  155. package/src/lib/function/assert.js.map +0 -1
  156. package/src/lib/function/context.js +0 -14
  157. package/src/lib/function/context.js.map +0 -1
  158. package/src/lib/function/error.auth.js +0 -25
  159. package/src/lib/function/error.auth.js.map +0 -1
  160. package/src/lib/function/error.js +0 -221
  161. package/src/lib/function/error.js.map +0 -1
  162. package/src/lib/function/index.js +0 -9
  163. package/src/lib/function/index.js.map +0 -1
  164. package/src/lib/function/type.js +0 -3
  165. package/src/lib/function/type.js.map +0 -1
  166. package/src/lib/index.js +0 -11
  167. package/src/lib/index.js.map +0 -1
  168. package/src/lib/nest/app.js +0 -114
  169. package/src/lib/nest/app.js.map +0 -1
  170. package/src/lib/nest/auth/auth.module.js +0 -60
  171. package/src/lib/nest/auth/auth.module.js.map +0 -1
  172. package/src/lib/nest/auth/auth.util.js +0 -72
  173. package/src/lib/nest/auth/auth.util.js.map +0 -1
  174. package/src/lib/nest/auth/index.js +0 -6
  175. package/src/lib/nest/auth/index.js.map +0 -1
  176. package/src/lib/nest/development/development.app.function.js +0 -38
  177. package/src/lib/nest/development/development.app.function.js.map +0 -1
  178. package/src/lib/nest/development/development.assert.function.js +0 -3
  179. package/src/lib/nest/development/development.assert.function.js.map +0 -1
  180. package/src/lib/nest/development/development.function.js +0 -41
  181. package/src/lib/nest/development/development.function.js.map +0 -1
  182. package/src/lib/nest/development/development.schedule.function.error.js +0 -35
  183. package/src/lib/nest/development/development.schedule.function.error.js.map +0 -1
  184. package/src/lib/nest/development/development.schedule.function.js +0 -54
  185. package/src/lib/nest/development/development.schedule.function.js.map +0 -1
  186. package/src/lib/nest/development/index.js +0 -9
  187. package/src/lib/nest/development/index.js.map +0 -1
  188. package/src/lib/nest/env/env.service.js +0 -19
  189. package/src/lib/nest/env/env.service.js.map +0 -1
  190. package/src/lib/nest/env/env.util.js +0 -12
  191. package/src/lib/nest/env/env.util.js.map +0 -1
  192. package/src/lib/nest/env/index.js +0 -6
  193. package/src/lib/nest/env/index.js.map +0 -1
  194. package/src/lib/nest/firebase/firebase.module.js +0 -17
  195. package/src/lib/nest/firebase/firebase.module.js.map +0 -1
  196. package/src/lib/nest/firebase/index.js +0 -5
  197. package/src/lib/nest/firebase/index.js.map +0 -1
  198. package/src/lib/nest/firestore/firestore.module.js +0 -86
  199. package/src/lib/nest/firestore/firestore.module.js.map +0 -1
  200. package/src/lib/nest/firestore/index.js +0 -5
  201. package/src/lib/nest/firestore/index.js.map +0 -1
  202. package/src/lib/nest/function/call.js +0 -46
  203. package/src/lib/nest/function/call.js.map +0 -1
  204. package/src/lib/nest/function/context.js +0 -79
  205. package/src/lib/nest/function/context.js.map +0 -1
  206. package/src/lib/nest/function/index.js +0 -10
  207. package/src/lib/nest/function/index.js.map +0 -1
  208. package/src/lib/nest/function/nest.js +0 -17
  209. package/src/lib/nest/function/nest.js.map +0 -1
  210. package/src/lib/nest/function/schedule.js +0 -8
  211. package/src/lib/nest/function/schedule.js.map +0 -1
  212. package/src/lib/nest/function/v1/call.d.ts +0 -59
  213. package/src/lib/nest/function/v1/call.js +0 -55
  214. package/src/lib/nest/function/v1/call.js.map +0 -1
  215. package/src/lib/nest/function/v1/event.d.ts +0 -80
  216. package/src/lib/nest/function/v1/event.js +0 -52
  217. package/src/lib/nest/function/v1/event.js.map +0 -1
  218. package/src/lib/nest/function/v1/index.d.ts +0 -3
  219. package/src/lib/nest/function/v1/index.js +0 -7
  220. package/src/lib/nest/function/v1/index.js.map +0 -1
  221. package/src/lib/nest/function/v1/schedule.d.ts +0 -47
  222. package/src/lib/nest/function/v1/schedule.js +0 -68
  223. package/src/lib/nest/function/v1/schedule.js.map +0 -1
  224. package/src/lib/nest/function/v2/blocking.js +0 -38
  225. package/src/lib/nest/function/v2/blocking.js.map +0 -1
  226. package/src/lib/nest/function/v2/call.js +0 -31
  227. package/src/lib/nest/function/v2/call.js.map +0 -1
  228. package/src/lib/nest/function/v2/event.js +0 -25
  229. package/src/lib/nest/function/v2/event.js.map +0 -1
  230. package/src/lib/nest/function/v2/index.js +0 -9
  231. package/src/lib/nest/function/v2/index.js.map +0 -1
  232. package/src/lib/nest/function/v2/schedule.js +0 -56
  233. package/src/lib/nest/function/v2/schedule.js.map +0 -1
  234. package/src/lib/nest/function/v2/taskqueue.js +0 -26
  235. package/src/lib/nest/function/v2/taskqueue.js.map +0 -1
  236. package/src/lib/nest/index.js +0 -15
  237. package/src/lib/nest/index.js.map +0 -1
  238. package/src/lib/nest/middleware/appcheck.decorator.js +0 -12
  239. package/src/lib/nest/middleware/appcheck.decorator.js.map +0 -1
  240. package/src/lib/nest/middleware/appcheck.js +0 -3
  241. package/src/lib/nest/middleware/appcheck.js.map +0 -1
  242. package/src/lib/nest/middleware/appcheck.middleware.js +0 -74
  243. package/src/lib/nest/middleware/appcheck.middleware.js.map +0 -1
  244. package/src/lib/nest/middleware/appcheck.module.js +0 -21
  245. package/src/lib/nest/middleware/appcheck.module.js.map +0 -1
  246. package/src/lib/nest/middleware/globalprefix.js +0 -11
  247. package/src/lib/nest/middleware/globalprefix.js.map +0 -1
  248. package/src/lib/nest/middleware/index.js +0 -10
  249. package/src/lib/nest/middleware/index.js.map +0 -1
  250. package/src/lib/nest/middleware/rawbody.middleware.js +0 -16
  251. package/src/lib/nest/middleware/rawbody.middleware.js.map +0 -1
  252. package/src/lib/nest/middleware/webhook.js +0 -24
  253. package/src/lib/nest/middleware/webhook.js.map +0 -1
  254. package/src/lib/nest/model/call.model.function.js +0 -73
  255. package/src/lib/nest/model/call.model.function.js.map +0 -1
  256. package/src/lib/nest/model/create.model.function.js +0 -27
  257. package/src/lib/nest/model/create.model.function.js.map +0 -1
  258. package/src/lib/nest/model/crud.assert.function.js +0 -3
  259. package/src/lib/nest/model/crud.assert.function.js.map +0 -1
  260. package/src/lib/nest/model/delete.model.function.js +0 -27
  261. package/src/lib/nest/model/delete.model.function.js.map +0 -1
  262. package/src/lib/nest/model/index.js +0 -11
  263. package/src/lib/nest/model/index.js.map +0 -1
  264. package/src/lib/nest/model/permission.error.js +0 -24
  265. package/src/lib/nest/model/permission.error.js.map +0 -1
  266. package/src/lib/nest/model/read.model.function.js +0 -27
  267. package/src/lib/nest/model/read.model.function.js.map +0 -1
  268. package/src/lib/nest/model/specifier.function.js +0 -35
  269. package/src/lib/nest/model/specifier.function.js.map +0 -1
  270. package/src/lib/nest/model/update.model.function.js +0 -27
  271. package/src/lib/nest/model/update.model.function.js.map +0 -1
  272. package/src/lib/nest/nest.provider.js +0 -89
  273. package/src/lib/nest/nest.provider.js.map +0 -1
  274. package/src/lib/nest/storage/index.js +0 -5
  275. package/src/lib/nest/storage/index.js.map +0 -1
  276. package/src/lib/nest/storage/storage.module.js +0 -112
  277. package/src/lib/nest/storage/storage.module.js.map +0 -1
  278. package/src/lib/storage/driver.accessor.js +0 -299
  279. package/src/lib/storage/driver.accessor.js.map +0 -1
  280. package/src/lib/storage/driver.js +0 -12
  281. package/src/lib/storage/driver.js.map +0 -1
  282. package/src/lib/storage/index.js +0 -8
  283. package/src/lib/storage/index.js.map +0 -1
  284. package/src/lib/storage/storage.js +0 -20
  285. package/src/lib/storage/storage.js.map +0 -1
  286. package/src/lib/storage/storage.service.js +0 -26
  287. package/src/lib/storage/storage.service.js.map +0 -1
  288. package/test/src/index.js +0 -5
  289. package/test/src/index.js.map +0 -1
  290. package/test/src/lib/firebase/firebase.admin.auth.js +0 -260
  291. package/test/src/lib/firebase/firebase.admin.auth.js.map +0 -1
  292. package/test/src/lib/firebase/firebase.admin.collection.js +0 -108
  293. package/test/src/lib/firebase/firebase.admin.collection.js.map +0 -1
  294. package/test/src/lib/firebase/firebase.admin.function.js +0 -132
  295. package/test/src/lib/firebase/firebase.admin.function.js.map +0 -1
  296. package/test/src/lib/firebase/firebase.admin.js +0 -174
  297. package/test/src/lib/firebase/firebase.admin.js.map +0 -1
  298. package/test/src/lib/firebase/firebase.admin.nest.function.callable.context.js +0 -42
  299. package/test/src/lib/firebase/firebase.admin.nest.function.callable.context.js.map +0 -1
  300. package/test/src/lib/firebase/firebase.admin.nest.function.cloud.context.js +0 -40
  301. package/test/src/lib/firebase/firebase.admin.nest.function.cloud.context.js.map +0 -1
  302. package/test/src/lib/firebase/firebase.admin.nest.function.js +0 -64
  303. package/test/src/lib/firebase/firebase.admin.nest.function.js.map +0 -1
  304. package/test/src/lib/firebase/firebase.admin.nest.js +0 -107
  305. package/test/src/lib/firebase/firebase.admin.nest.js.map +0 -1
  306. package/test/src/lib/firebase/firebase.admin.test.server.js +0 -37
  307. package/test/src/lib/firebase/firebase.admin.test.server.js.map +0 -1
  308. package/test/src/lib/firebase/firebase.function.js +0 -58
  309. package/test/src/lib/firebase/firebase.function.js.map +0 -1
  310. package/test/src/lib/firebase/firebase.jest.d.ts +0 -21
  311. package/test/src/lib/firebase/firebase.jest.js +0 -45
  312. package/test/src/lib/firebase/firebase.jest.js.map +0 -1
  313. package/test/src/lib/firebase/firebase.js +0 -74
  314. package/test/src/lib/firebase/firebase.js.map +0 -1
  315. package/test/src/lib/firebase/index.js +0 -15
  316. package/test/src/lib/firebase/index.js.map +0 -1
  317. package/test/src/lib/firestore/firestore.admin.js +0 -21
  318. package/test/src/lib/firestore/firestore.admin.js.map +0 -1
  319. package/test/src/lib/firestore/firestore.js +0 -57
  320. package/test/src/lib/firestore/firestore.js.map +0 -1
  321. package/test/src/lib/firestore/index.js +0 -6
  322. package/test/src/lib/firestore/index.js.map +0 -1
  323. package/test/src/lib/index.js +0 -7
  324. package/test/src/lib/index.js.map +0 -1
  325. package/test/src/lib/storage/index.js +0 -6
  326. package/test/src/lib/storage/index.js.map +0 -1
  327. package/test/src/lib/storage/storage.admin.js +0 -21
  328. package/test/src/lib/storage/storage.admin.js.map +0 -1
  329. package/test/src/lib/storage/storage.js +0 -59
  330. package/test/src/lib/storage/storage.js.map +0 -1
  331. /package/{zoho/index.cjs.d.ts → index.d.ts} +0 -0
  332. /package/{zoho/index.esm.d.ts → mailgun/index.d.ts} +0 -0
package/index.esm.js ADDED
@@ -0,0 +1,2775 @@
1
+ import { DBX_FIREBASE_SERVER_NO_AUTH_ERROR_CODE, FIREBASE_AUTH_USER_NOT_FOUND_ERROR, FIREBASE_SERVER_AUTH_CLAIMS_RESET_LAST_COM_DATE_KEY, FIREBASE_SERVER_AUTH_CLAIMS_RESET_PASSWORD_KEY, FIREBASE_SERVER_AUTH_CLAIMS_SETUP_PASSWORD_KEY, FIREBASE_SERVER_AUTH_CLAIMS_SETUP_LAST_COM_DATE_KEY, FirestoreDocumentContextType, streamFromOnSnapshot, makeFirestoreQueryConstraintFunctionsDriver, FIRESTORE_END_BEFORE_QUERY_CONSTRAINT_TYPE, FIRESTORE_END_AT_VALUE_QUERY_CONSTRAINT_TYPE, FIRESTORE_END_AT_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AFTER_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AT_VALUE_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AT_QUERY_CONSTRAINT_TYPE, FIRESTORE_OFFSET_QUERY_CONSTRAINT_TYPE, FIRESTORE_WHERE_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE, FIRESTORE_WHERE_QUERY_CONSTRAINT_TYPE, FIRESTORE_ORDER_BY_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE, FIRESTORE_ORDER_BY_QUERY_CONSTRAINT_TYPE, FIRESTORE_LIMIT_TO_LAST_QUERY_CONSTRAINT_TYPE, FIRESTORE_LIMIT_QUERY_CONSTRAINT_TYPE, firestoreContextFactory, setIdAndKeyFromKeyIdRefOnDocumentData, SCHEDULED_FUNCTION_DEV_FUNCTION_SPECIFIER, MODEL_FUNCTION_FIREBASE_CRUD_FUNCTION_SPECIFIER_DEFAULT, storageListFilesResultFactory, assertStorageUploadOptionsStringFormat, firebaseStorageContextFactory, inContextFirebaseModelsServiceFactory, useFirebaseModelsService } from '@dereekb/firebase';
2
+ import { partialServerError, isServerError, randomNumberFactory, cachedGetter, AUTH_ADMIN_ROLE, AUTH_TOS_SIGNED_ROLE, forEachKeyValue, KeyValueTypleValueFilter, filterNullAndUndefinedValues, asSet, filterUndefinedValues, isThrottled, mapObjectMap, batch, asArray, containsAllValues, serverError, mergeObjects, cronExpressionRepeatingEveryNMinutes, mapIdentityFunction, objectToMap, slashPathName, SLASH_PATH_SEPARATOR, toRelativeSlashPathStartType, fixMultiSlashesInSlashPath, objectHasNoKeys, makeGetter, asGetter, pushItemOrArrayItemsIntoArray, build } from '@dereekb/util';
3
+ import { HttpsError } from 'firebase-functions/https';
4
+ import { hoursToMs, toISODateString } from '@dereekb/date';
5
+ import { BaseError } from 'make-error';
6
+ import 'core-js/modules/es.iterator.constructor.js';
7
+ import 'core-js/modules/es.iterator.for-each.js';
8
+ import { from } from 'rxjs';
9
+ import { FieldValue, FieldPath } from '@google-cloud/firestore';
10
+ import { Module, Injectable, ValidationPipe, Optional, Inject, Logger, ForbiddenException, createParamDecorator } from '@nestjs/common';
11
+ import { mergeModuleMetadata, ServerEnvironmentService, DEFAULT_BASE_WEBHOOK_PATH, DEFAULT_WEBHOOK_MIDDLEWARE_ROUTE_INFO, isTestNodeEnv, injectionTokensFromProviders, serverEnvTokenProvider } from '@dereekb/nestjs';
12
+ import { https, scheduler } from 'firebase-functions/v2';
13
+ import { toTransformAndValidateFunctionResultFactory, transformAndValidateObjectFactory } from '@dereekb/model';
14
+ import admin from 'firebase-admin';
15
+ import 'core-js/modules/es.iterator.map.js';
16
+ import { ApiError } from '@google-cloud/storage';
17
+ import { addMilliseconds, addHours } from 'date-fns';
18
+ import { isUint8Array, isArrayBuffer } from 'util/types';
19
+ import 'core-js/modules/es.map.get-or-insert.js';
20
+ import 'core-js/modules/es.map.get-or-insert-computed.js';
21
+ import { NestFactory } from '@nestjs/core';
22
+ import { ExpressAdapter } from '@nestjs/platform-express';
23
+ import express from 'express';
24
+
25
+ /**
26
+ * @deprecated use DBX_FIREBASE_SERVER_NO_AUTH_ERROR_CODE instead
27
+ */
28
+ const NO_AUTH_ERROR_CODE = DBX_FIREBASE_SERVER_NO_AUTH_ERROR_CODE;
29
+ function unauthenticatedContextHasNoAuthData() {
30
+ return unauthenticatedError({
31
+ message: 'expected auth',
32
+ code: NO_AUTH_ERROR_CODE
33
+ });
34
+ }
35
+ /**
36
+ * @deprecated use DBX_FIREBASE_SERVER_NO_UID_ERROR_CODE instead
37
+ */
38
+ const NO_UID_ERROR_CODE = DBX_FIREBASE_SERVER_NO_AUTH_ERROR_CODE;
39
+ function unauthenticatedContextHasNoUidError() {
40
+ return unauthenticatedError({
41
+ message: 'no user uid',
42
+ code: NO_UID_ERROR_CODE
43
+ });
44
+ }
45
+ // MARK: General Errors
46
+ const UNAUTHENTICATED_ERROR_CODE = 'UNAUTHENTICATED';
47
+ function unauthenticatedError(messageOrError) {
48
+ const serverError = partialServerError(messageOrError);
49
+ return new HttpsError('unauthenticated', serverError?.message || 'unauthenticated', {
50
+ status: 401,
51
+ code: UNAUTHENTICATED_ERROR_CODE,
52
+ ...serverError,
53
+ _error: undefined
54
+ });
55
+ }
56
+ const FORBIDDEN_ERROR_CODE = 'FORBIDDEN';
57
+ function forbiddenError(messageOrError) {
58
+ const serverError = partialServerError(messageOrError);
59
+ return new HttpsError('permission-denied', serverError?.message || 'forbidden', {
60
+ status: 403,
61
+ code: FORBIDDEN_ERROR_CODE,
62
+ ...serverError,
63
+ _error: undefined
64
+ });
65
+ }
66
+ const PERMISSION_DENIED_ERROR_CODE = 'PERMISSION_DENIED';
67
+ function permissionDeniedError(messageOrError) {
68
+ const serverError = partialServerError(messageOrError);
69
+ return new HttpsError('permission-denied', serverError?.message || 'permission denied', {
70
+ status: 403,
71
+ code: PERMISSION_DENIED_ERROR_CODE,
72
+ ...serverError,
73
+ _error: undefined
74
+ });
75
+ }
76
+ const NOT_FOUND_ERROR_CODE = 'NOT_FOUND';
77
+ function notFoundError(messageOrError) {
78
+ const serverError = partialServerError(messageOrError);
79
+ return new HttpsError('not-found', serverError?.message || 'not found', {
80
+ status: 404,
81
+ code: NOT_FOUND_ERROR_CODE,
82
+ ...serverError,
83
+ _error: undefined
84
+ });
85
+ }
86
+ const MODEL_NOT_AVAILABLE_ERROR_CODE = 'MODEL_NOT_AVAILABLE';
87
+ function modelNotAvailableError(messageOrError) {
88
+ const serverError = partialServerError(messageOrError);
89
+ return new HttpsError('not-found', serverError?.message || 'model was not available', {
90
+ status: 404,
91
+ code: MODEL_NOT_AVAILABLE_ERROR_CODE,
92
+ ...serverError,
93
+ _error: undefined
94
+ });
95
+ }
96
+ const BAD_REQUEST_ERROR_CODE = 'BAD_REQUEST';
97
+ function badRequestError(messageOrError) {
98
+ const serverError = partialServerError(messageOrError);
99
+ return new HttpsError('invalid-argument', serverError?.message || 'bad request', {
100
+ status: 400,
101
+ code: BAD_REQUEST_ERROR_CODE,
102
+ ...serverError,
103
+ _error: undefined
104
+ });
105
+ }
106
+ const CONFLICT_ERROR_CODE = 'CONFLICT';
107
+ function preconditionConflictError(messageOrError) {
108
+ const serverError = partialServerError(messageOrError);
109
+ return new HttpsError('failed-precondition', serverError?.message || 'conflict', {
110
+ status: 409,
111
+ code: CONFLICT_ERROR_CODE,
112
+ ...serverError,
113
+ _error: undefined
114
+ });
115
+ }
116
+ const ALREADY_EXISTS_ERROR_CODE = 'ALREADY_EXISTS';
117
+ function alreadyExistsError(messageOrError) {
118
+ const serverError = partialServerError(messageOrError);
119
+ return new HttpsError('already-exists', serverError?.message || 'already exists', {
120
+ status: 409,
121
+ code: ALREADY_EXISTS_ERROR_CODE,
122
+ ...serverError,
123
+ _error: undefined
124
+ });
125
+ }
126
+ const UNAVAILABLE_ERROR_CODE = 'UNAVAILABLE';
127
+ function unavailableError(messageOrError) {
128
+ const serverError = partialServerError(messageOrError);
129
+ return new HttpsError('unavailable', serverError?.message || 'service unavailable', {
130
+ status: 503,
131
+ code: UNAVAILABLE_ERROR_CODE,
132
+ ...serverError,
133
+ _error: undefined
134
+ });
135
+ }
136
+ const UNAVAILABLE_OR_DEACTIVATED_FUNCTION_ERROR_CODE = 'UNAVAILABLE_OR_DEACTIVATED_FUNCTION';
137
+ function unavailableOrDeactivatedFunctionError(messageOrError) {
138
+ const serverError = partialServerError(messageOrError);
139
+ return new HttpsError('unimplemented', serverError?.message || 'the requested function is not available or has been deactivated for use', {
140
+ status: 501,
141
+ code: UNAVAILABLE_OR_DEACTIVATED_FUNCTION_ERROR_CODE,
142
+ ...serverError,
143
+ _error: undefined
144
+ });
145
+ }
146
+ const INTERNAL_SERVER_ERROR_CODE = 'INTERNAL_ERROR';
147
+ function internalServerError(messageOrError) {
148
+ const serverError = partialServerError(messageOrError);
149
+ return new HttpsError('internal', serverError?.message || 'internal error', {
150
+ status: 500,
151
+ code: INTERNAL_SERVER_ERROR_CODE,
152
+ ...serverError,
153
+ _error: undefined
154
+ });
155
+ }
156
+ function isFirebaseHttpsError(input) {
157
+ return typeof input === 'object' && input.code != null && input.httpErrorCode != null && input.toJSON != null;
158
+ }
159
+ function isFirebaseError(input) {
160
+ return typeof input === 'object' && input.code != null && input.message != null && input.toJSON != null;
161
+ }
162
+ /**
163
+ * Creates a FirebaseServerErrorInfo from the input.
164
+ *
165
+ * @param e
166
+ * @returns
167
+ */
168
+ function firebaseServerErrorInfo(e) {
169
+ let type = 'unknown';
170
+ let httpsError;
171
+ let firebaseError;
172
+ let firebaseErrorCode;
173
+ let httpsErrorDetailsServerError;
174
+ let serverErrorCode;
175
+ if (e != null) {
176
+ if (isFirebaseHttpsError(e)) {
177
+ type = 'httpsError';
178
+ httpsError = e;
179
+ firebaseErrorCode = httpsError.code;
180
+ if (httpsError.details && isServerError(httpsError.details)) {
181
+ httpsErrorDetailsServerError = httpsError.details;
182
+ serverErrorCode = httpsErrorDetailsServerError.code;
183
+ }
184
+ } else if (isFirebaseError(e)) {
185
+ type = 'firebaseError';
186
+ firebaseError = e;
187
+ firebaseErrorCode = firebaseError.code;
188
+ }
189
+ }
190
+ return {
191
+ httpsError,
192
+ firebaseError,
193
+ firebaseErrorCode,
194
+ httpsErrorDetailsServerError,
195
+ serverErrorCode,
196
+ type,
197
+ e
198
+ };
199
+ }
200
+ function firebaseServerErrorInfoCodePair(e) {
201
+ const info = firebaseServerErrorInfo(e);
202
+ return [info.firebaseErrorCode, info];
203
+ }
204
+ function firebaseServerErrorInfoServerErrorPair(e) {
205
+ const info = firebaseServerErrorInfo(e);
206
+ return [info.httpsErrorDetailsServerError, info];
207
+ }
208
+ function firebaseServerErrorInfoServerErrorCodePair(e) {
209
+ const info = firebaseServerErrorInfo(e);
210
+ return [info.serverErrorCode, info];
211
+ }
212
+ function handleFirebaseError(e, handleFirebaseErrorFn) {
213
+ const firebaseError = e.code ? e : undefined;
214
+ if (firebaseError) {
215
+ handleFirebaseErrorFn(firebaseError);
216
+ }
217
+ }
218
+
219
+ function isContextWithAuthData(context) {
220
+ return Boolean(context.auth !== null && context.auth?.uid);
221
+ }
222
+ function assertIsContextWithAuthData(context) {
223
+ if (!isContextWithAuthData(context)) {
224
+ throw unauthenticatedContextHasNoAuthData();
225
+ }
226
+ }
227
+
228
+ function firebaseAuthTokenFromDecodedIdToken(token) {
229
+ return {
230
+ email: token.email,
231
+ emailVerified: token.email_verified,
232
+ phoneNumber: token.phone_number,
233
+ lastSignInTime: new Date(token.auth_time).toISOString(),
234
+ lastRefreshTime: new Date(token.iat).toISOString()
235
+ };
236
+ }
237
+
238
+ /**
239
+ * Awaits the load result from the input promise. If it encounters a FIREBASE_AUTH_USER_NOT_FOUND_ERROR, then returns undefined. Throws the error otherwise.
240
+ * @param promise
241
+ * @returns
242
+ */
243
+ async function getAuthUserOrUndefined(promise) {
244
+ try {
245
+ return await promise;
246
+ } catch (error) {
247
+ if (error?.code === FIREBASE_AUTH_USER_NOT_FOUND_ERROR) {
248
+ return undefined;
249
+ } else {
250
+ throw error;
251
+ }
252
+ }
253
+ }
254
+
255
+ /**
256
+ * Thrown by sendSetupDetails() if the user has no setup configuration available, meaning they probably already have accepted their invite or is in an invalid state.
257
+ */
258
+ class FirebaseServerAuthNewUserSendSetupDetailsNoSetupConfigError extends BaseError {
259
+ constructor() {
260
+ super(`This user has no setup configuration available.`);
261
+ }
262
+ }
263
+ /**
264
+ * Thrown by sendSetupDetails() if the user was recently sent details.
265
+ */
266
+ class FirebaseServerAuthNewUserSendSetupDetailsThrottleError extends BaseError {
267
+ constructor(lastSentAt) {
268
+ super(`This user was recently sent details. Try again later.`);
269
+ this.lastSentAt = void 0;
270
+ this.lastSentAt = lastSentAt;
271
+ }
272
+ }
273
+ /**
274
+ * Thrown by sendSetupDetails() if the user was recently sent details.
275
+ */
276
+ class FirebaseServerAuthNewUserSendSetupDetailsSendOnceError extends BaseError {
277
+ constructor() {
278
+ super(`The user has been sent details before and the sendSetupDetailsOnce configuration was true.`);
279
+ }
280
+ }
281
+
282
+ const DEFAULT_FIREBASE_PASSWORD_NUMBER_GENERATOR = randomNumberFactory({
283
+ min: 100000,
284
+ max: 1000000,
285
+ round: 'floor'
286
+ }); // 6 digits
287
+ class AbstractFirebaseServerAuthUserContext {
288
+ constructor(service, uid) {
289
+ this._service = void 0;
290
+ this._uid = void 0;
291
+ this._loadRecord = cachedGetter(() => this._service.auth.getUser(this._uid));
292
+ this._service = service;
293
+ this._uid = uid;
294
+ }
295
+ get service() {
296
+ return this._service;
297
+ }
298
+ get uid() {
299
+ return this._uid;
300
+ }
301
+ async exists() {
302
+ return getAuthUserOrUndefined(this._loadRecord()).then(x => Boolean(x));
303
+ }
304
+ loadRecord() {
305
+ return this._loadRecord();
306
+ }
307
+ loadDetails() {
308
+ return this.loadRecord().then(record => this.service.authDetailsForRecord(record));
309
+ }
310
+ _generateResetPasswordKey() {
311
+ return String(DEFAULT_FIREBASE_PASSWORD_NUMBER_GENERATOR());
312
+ }
313
+ async beginResetPassword() {
314
+ const password = this._generateResetPasswordKey();
315
+ const passwordClaimsData = {
316
+ [FIREBASE_SERVER_AUTH_CLAIMS_RESET_PASSWORD_KEY]: password,
317
+ [FIREBASE_SERVER_AUTH_CLAIMS_RESET_LAST_COM_DATE_KEY]: toISODateString(new Date())
318
+ };
319
+ // set the claims
320
+ await this.updateClaims(passwordClaimsData);
321
+ // update the user
322
+ await this.updateUser({
323
+ password
324
+ });
325
+ return passwordClaimsData;
326
+ }
327
+ async loadResetPasswordClaims() {
328
+ const claims = await this.loadClaims();
329
+ if (claims.resetPassword != null) {
330
+ return claims;
331
+ } else {
332
+ return undefined;
333
+ }
334
+ }
335
+ /**
336
+ * Sets the user's password.
337
+ */
338
+ async setPassword(password) {
339
+ const record = await this.updateUser({
340
+ password
341
+ });
342
+ // clear password reset claims
343
+ await this.updateClaims({
344
+ [FIREBASE_SERVER_AUTH_CLAIMS_RESET_PASSWORD_KEY]: null,
345
+ [FIREBASE_SERVER_AUTH_CLAIMS_RESET_LAST_COM_DATE_KEY]: null
346
+ });
347
+ return record;
348
+ }
349
+ async updateUser(template) {
350
+ return this.service.auth.updateUser(this.uid, template);
351
+ }
352
+ async loadRoles() {
353
+ const claims = await this.loadClaims();
354
+ return this.service.readRoles(claims);
355
+ }
356
+ async addRoles(roles) {
357
+ const claims = this._claimsForRolesChange(roles);
358
+ return this.updateClaims(claims);
359
+ }
360
+ async removeRoles(roles) {
361
+ const baseClaims = this._claimsForRolesChange(roles);
362
+ const claims = {};
363
+ forEachKeyValue(baseClaims, {
364
+ forEach: ([key]) => {
365
+ claims[key] = null; // set null on every key
366
+ },
367
+ filter: KeyValueTypleValueFilter.NONE // don't skip any key/value
368
+ });
369
+ return this.updateClaims(claims);
370
+ }
371
+ /**
372
+ * Sets the claims using the input roles and roles set.
373
+ *
374
+ * All other claims are cleared.
375
+ *
376
+ * Use the claimsToRetain input to retain other claims that are outside of the roles.
377
+ *
378
+ * @param roles
379
+ * @param claimsToRetain
380
+ * @returns
381
+ */
382
+ async setRoles(roles, claimsToRetain) {
383
+ const claims = {
384
+ ...claimsToRetain,
385
+ ...this._claimsForRolesChange(Array.from(roles))
386
+ };
387
+ return this.setClaims(claims);
388
+ }
389
+ _claimsForRolesChange(roles) {
390
+ // filter null/undefined since the claims will contain null values for claims that are not related.
391
+ return filterNullAndUndefinedValues(this.service.claimsForRoles(asSet(roles)));
392
+ }
393
+ loadClaims() {
394
+ return this.loadRecord().then(x => x.customClaims ?? {});
395
+ }
396
+ async updateClaims(claims) {
397
+ const currentClaims = await this.loadClaims();
398
+ let newClaims;
399
+ if (currentClaims) {
400
+ newClaims = {
401
+ ...currentClaims,
402
+ ...filterUndefinedValues(claims, false)
403
+ };
404
+ newClaims = filterNullAndUndefinedValues(newClaims);
405
+ } else {
406
+ newClaims = claims;
407
+ }
408
+ return this.setClaims(newClaims);
409
+ }
410
+ clearClaims() {
411
+ return this.setClaims(null);
412
+ }
413
+ setClaims(claims) {
414
+ return this.service.auth.setCustomUserClaims(this.uid, claims).then(() => {
415
+ this._loadRecord.reset(); // reset the cache
416
+ });
417
+ }
418
+ }
419
+ class AbstractFirebaseServerAuthContext {
420
+ constructor(service, context) {
421
+ this._service = void 0;
422
+ this._context = void 0;
423
+ this._authRoles = cachedGetter(() => this.service.readRoles(this.claims));
424
+ this._isAdmin = cachedGetter(() => this.service.isAdminInRoles(this._authRoles()));
425
+ this._hasSignedTos = cachedGetter(() => this.service.hasSignedTosInRoles(this._authRoles()));
426
+ this._userContext = cachedGetter(() => this.service.userContext(this.context.auth.uid));
427
+ this._service = service;
428
+ this._context = context;
429
+ }
430
+ get service() {
431
+ return this._service;
432
+ }
433
+ get context() {
434
+ return this._context;
435
+ }
436
+ get userContext() {
437
+ return this._userContext();
438
+ }
439
+ get isAdmin() {
440
+ return this._isAdmin();
441
+ }
442
+ get hasSignedTos() {
443
+ return this._hasSignedTos();
444
+ }
445
+ get authRoles() {
446
+ return this._authRoles();
447
+ }
448
+ get token() {
449
+ return this.context.auth.token;
450
+ }
451
+ get claims() {
452
+ return this.context.auth.token;
453
+ }
454
+ // MARK: FirebaseServerAuthUserContext
455
+ get uid() {
456
+ return this.userContext.uid;
457
+ }
458
+ }
459
+ /**
460
+ * 1 hour
461
+ */
462
+ const DEFAULT_SETUP_COM_THROTTLE_TIME = hoursToMs(1);
463
+ function userContextFromUid(authService, userContextOrUid) {
464
+ const userContext = typeof userContextOrUid === 'string' ? authService.userContext(userContextOrUid) : userContextOrUid;
465
+ return userContext;
466
+ }
467
+ class AbstractFirebaseServerNewUserService {
468
+ constructor(authService) {
469
+ this._authService = void 0;
470
+ this.setupThrottleTime = DEFAULT_SETUP_COM_THROTTLE_TIME;
471
+ this._authService = authService;
472
+ }
473
+ get authService() {
474
+ return this._authService;
475
+ }
476
+ async initializeNewUser(input) {
477
+ const {
478
+ uid,
479
+ email,
480
+ phone,
481
+ sendSetupContent,
482
+ sendSetupContentIfUserExists,
483
+ sendSetupDetailsOnce,
484
+ sendSetupIgnoreThrottle,
485
+ sendSetupThrowErrors,
486
+ data,
487
+ sendDetailsInTestEnvironment
488
+ } = input;
489
+ let userRecordPromise;
490
+ if (uid) {
491
+ userRecordPromise = this.authService.auth.getUser(uid);
492
+ } else if (email) {
493
+ userRecordPromise = this.authService.auth.getUserByEmail(email);
494
+ } else if (phone) {
495
+ userRecordPromise = this.authService.auth.getUserByPhoneNumber(phone);
496
+ } else {
497
+ throw new Error('email or phone is required to initialize a new user.');
498
+ }
499
+ let userRecord = await getAuthUserOrUndefined(userRecordPromise);
500
+ let userRecordId;
501
+ let createdUser = false;
502
+ if (!userRecord) {
503
+ const createResult = await this.createNewUser(input);
504
+ // add the setup password to the user's credentials
505
+ const userContext = this.authService.userContext(createResult.user.uid);
506
+ await this.addNewUserSetupClaims(userContext, createResult.password);
507
+ createdUser = true;
508
+ userRecordId = userContext.uid;
509
+ userRecord = await userContext.loadRecord();
510
+ } else {
511
+ userRecordId = userRecord.uid;
512
+ }
513
+ // send content if necessary
514
+ if (createdUser && sendSetupContent === true || sendSetupContentIfUserExists) {
515
+ const sentEmail = await this.sendSetupContent(userRecordId, {
516
+ data,
517
+ sendSetupDetailsOnce,
518
+ ignoreSendThrottleTime: sendSetupIgnoreThrottle,
519
+ throwErrors: sendSetupThrowErrors,
520
+ sendDetailsInTestEnvironment
521
+ });
522
+ // reload the user record
523
+ if (sentEmail) {
524
+ const userContext = this.authService.userContext(userRecordId);
525
+ userRecord = await userContext.loadRecord();
526
+ }
527
+ }
528
+ return userRecord;
529
+ }
530
+ async addNewUserSetupClaims(userContextOrUid, setupPassword) {
531
+ const password = setupPassword ?? this.generateRandomSetupPassword();
532
+ const userContext = userContextFromUid(this.authService, userContextOrUid);
533
+ await userContext.updateClaims({
534
+ [FIREBASE_SERVER_AUTH_CLAIMS_SETUP_PASSWORD_KEY]: password
535
+ });
536
+ return userContext;
537
+ }
538
+ async sendSetupContent(userContextOrUid, config) {
539
+ const setupDetails = await this.loadSetupDetails(userContextOrUid, config);
540
+ let sentContent = false;
541
+ if (setupDetails) {
542
+ const {
543
+ setupCommunicationAt
544
+ } = setupDetails.claims;
545
+ const hasSentCommunication = Boolean(setupCommunicationAt);
546
+ if (config?.sendSetupDetailsOnce && hasSentCommunication) {
547
+ // do not send.
548
+ if (config?.throwErrors) {
549
+ throw new FirebaseServerAuthNewUserSendSetupDetailsSendOnceError();
550
+ }
551
+ } else {
552
+ const lastSentAt = setupCommunicationAt ? new Date(setupCommunicationAt) : undefined;
553
+ const sendIsThrottled = hasSentCommunication && !config?.ignoreSendThrottleTime && isThrottled(this.setupThrottleTime, lastSentAt);
554
+ if (!sendIsThrottled) {
555
+ await this.sendSetupContentToUser(setupDetails);
556
+ await this.updateSetupContentSentTime(setupDetails);
557
+ sentContent = true;
558
+ } else if (config?.throwErrors) {
559
+ throw new FirebaseServerAuthNewUserSendSetupDetailsThrottleError(lastSentAt);
560
+ }
561
+ }
562
+ } else if (config?.throwErrors) {
563
+ throw new FirebaseServerAuthNewUserSendSetupDetailsNoSetupConfigError();
564
+ }
565
+ return sentContent;
566
+ }
567
+ async loadSetupDetails(userContextOrUid, config) {
568
+ const userContext = userContextFromUid(this.authService, userContextOrUid);
569
+ const userExists = await userContext.exists();
570
+ let details;
571
+ if (userExists) {
572
+ details = await this.loadSetupDetailsForUserContext(userContext, config);
573
+ }
574
+ return details;
575
+ }
576
+ async loadSetupDetailsForUserContext(userContext, config) {
577
+ let details;
578
+ const {
579
+ setupPassword,
580
+ setupCommunicationAt
581
+ } = await userContext.loadClaims();
582
+ if (setupPassword) {
583
+ details = {
584
+ userContext,
585
+ claims: {
586
+ setupPassword,
587
+ setupCommunicationAt
588
+ },
589
+ data: config?.data,
590
+ sendDetailsInTestEnvironment: config?.sendDetailsInTestEnvironment
591
+ };
592
+ }
593
+ return details;
594
+ }
595
+ async updateSetupContentSentTime(details) {
596
+ const setupCommunicationAt = toISODateString(new Date());
597
+ await details.userContext.updateClaims({
598
+ setupCommunicationAt
599
+ });
600
+ }
601
+ /**
602
+ * Update a user's claims to clear any setup-related content.
603
+ *
604
+ * Returns true if a user was updated.
605
+ *
606
+ * @param uid
607
+ */
608
+ async markUserSetupAsComplete(uid) {
609
+ const userContext = this.authService.userContext(uid);
610
+ const userExists = await userContext.exists();
611
+ if (userExists) {
612
+ await this.updateClaimsToClearUser(userContext);
613
+ }
614
+ return userExists;
615
+ }
616
+ async createNewUser(input) {
617
+ const {
618
+ uid,
619
+ displayName,
620
+ email,
621
+ phone: phoneNumber,
622
+ setupPassword: inputPassword
623
+ } = input;
624
+ const password = inputPassword ?? this.generateRandomSetupPassword();
625
+ const user = await this.authService.auth.createUser({
626
+ uid,
627
+ displayName,
628
+ email,
629
+ phoneNumber,
630
+ password
631
+ });
632
+ return {
633
+ user,
634
+ password
635
+ };
636
+ }
637
+ generateRandomSetupPassword() {
638
+ return `${DEFAULT_FIREBASE_PASSWORD_NUMBER_GENERATOR()}`;
639
+ }
640
+ async updateClaimsToClearUser(userContext) {
641
+ await userContext.updateClaims({
642
+ [FIREBASE_SERVER_AUTH_CLAIMS_SETUP_PASSWORD_KEY]: null,
643
+ [FIREBASE_SERVER_AUTH_CLAIMS_SETUP_LAST_COM_DATE_KEY]: null
644
+ });
645
+ }
646
+ }
647
+ class NoSetupContentFirebaseServerNewUserService extends AbstractFirebaseServerNewUserService {
648
+ async sendSetupContentToUser(user) {
649
+ // send nothing.
650
+ }
651
+ }
652
+ /**
653
+ * FirebaseServer auth service that provides accessors to auth-related components.
654
+ */
655
+ class FirebaseServerAuthService {}
656
+ /**
657
+ * Abstract FirebaseServerAuthService implementation.
658
+ */
659
+ class AbstractFirebaseServerAuthService {
660
+ constructor(auth) {
661
+ this._auth = void 0;
662
+ this._auth = auth;
663
+ }
664
+ get auth() {
665
+ return this._auth;
666
+ }
667
+ context(context) {
668
+ assertIsContextWithAuthData(context);
669
+ return this._context(context);
670
+ }
671
+ isAdmin(claims) {
672
+ return this.isAdminInRoles(this.readRoles(claims));
673
+ }
674
+ isAdminInRoles(roles) {
675
+ return roles.has(AUTH_ADMIN_ROLE);
676
+ }
677
+ hasSignedTos(claims) {
678
+ return this.hasSignedTosInRoles(this.readRoles(claims));
679
+ }
680
+ hasSignedTosInRoles(roles) {
681
+ return roles.has(AUTH_TOS_SIGNED_ROLE);
682
+ }
683
+ newUser() {
684
+ return new NoSetupContentFirebaseServerNewUserService(this);
685
+ }
686
+ authContextInfo(context) {
687
+ const {
688
+ auth
689
+ } = context;
690
+ let result;
691
+ if (auth) {
692
+ const _roles = cachedGetter(() => this.readRoles(auth.token));
693
+ const getClaims = () => auth.token;
694
+ result = {
695
+ uid: auth.uid,
696
+ isAdmin: () => this.isAdminInRoles(_roles()),
697
+ getClaims,
698
+ getAuthRoles: _roles,
699
+ token: firebaseAuthTokenFromDecodedIdToken(auth.token)
700
+ };
701
+ }
702
+ return result;
703
+ }
704
+ authDetailsForRecord(record) {
705
+ return {
706
+ uid: record.uid,
707
+ email: record.email,
708
+ emailVerified: record.emailVerified,
709
+ phoneNumber: record.phoneNumber,
710
+ disabled: record.disabled,
711
+ displayName: record.displayName,
712
+ photoURL: record.photoURL,
713
+ creationTime: record.metadata.creationTime ? new Date(record.metadata.creationTime).toISOString() : undefined,
714
+ lastSignInTime: record.metadata.lastSignInTime ? new Date(record.metadata.lastSignInTime).toISOString() : undefined,
715
+ lastRefreshTime: record.metadata.lastRefreshTime ? new Date(record.metadata.lastRefreshTime).toISOString() : undefined
716
+ };
717
+ }
718
+ }
719
+
720
+ class FirebaseServerEnvService {}
721
+
722
+ /**
723
+ * Creates UpdateData corresponding to the input increment update.
724
+ *
725
+ * @param input
726
+ * @returns
727
+ */
728
+ function firestoreServerIncrementUpdateToUpdateData(input) {
729
+ return mapObjectMap(input, incrementValue => {
730
+ return FieldValue.increment(incrementValue ?? 0);
731
+ });
732
+ }
733
+
734
+ /**
735
+ * Creates UpdateData corresponding to the input array update.
736
+ *
737
+ * @param input
738
+ * @returns
739
+ */
740
+ function firestoreServerArrayUpdateToUpdateData(input) {
741
+ const union = input?.union;
742
+ const remove = input?.remove;
743
+ function createUpdatesWithArrayFunction(fieldUpdate, arrayUpdateFunction) {
744
+ let result;
745
+ if (fieldUpdate) {
746
+ result = mapObjectMap(fieldUpdate, arrayUpdate => {
747
+ let result;
748
+ if (arrayUpdate) {
749
+ result = arrayUpdateFunction(...arrayUpdate); // use spread operator to insert each value as an argument, as "nested arrays" are not allowed in the Firestore
750
+ }
751
+ return result;
752
+ });
753
+ }
754
+ return result;
755
+ }
756
+ const updateData = {
757
+ ...createUpdatesWithArrayFunction(union, FieldValue.arrayUnion),
758
+ ...createUpdatesWithArrayFunction(remove, FieldValue.arrayRemove)
759
+ };
760
+ return updateData;
761
+ }
762
+
763
+ // MARK: Accessor
764
+ /**
765
+ * FirestoreDocumentDataAccessor implementation for a batch.
766
+ */
767
+ class WriteBatchFirestoreDocumentDataAccessor {
768
+ constructor(batch, documentRef) {
769
+ this.documentRef = void 0;
770
+ this._batch = void 0;
771
+ this.documentRef = documentRef;
772
+ this._batch = batch;
773
+ }
774
+ get batch() {
775
+ return this._batch;
776
+ }
777
+ stream() {
778
+ return from(this.get()); // todo
779
+ }
780
+ create(data) {
781
+ this.batch.create(this.documentRef, data);
782
+ return Promise.resolve();
783
+ }
784
+ exists() {
785
+ return this.get().then(x => x.exists);
786
+ }
787
+ get() {
788
+ return this.documentRef.get();
789
+ }
790
+ getWithConverter(converter) {
791
+ return this.documentRef.withConverter(converter).get();
792
+ }
793
+ delete(params) {
794
+ this.batch.delete(this.documentRef, params?.precondition);
795
+ return Promise.resolve();
796
+ }
797
+ set(data) {
798
+ this.batch.set(this.documentRef, data);
799
+ return Promise.resolve();
800
+ }
801
+ increment(data, params) {
802
+ return this.update(firestoreServerIncrementUpdateToUpdateData(data), params);
803
+ }
804
+ arrayUpdate(data, params) {
805
+ return this.update(firestoreServerArrayUpdateToUpdateData(data), params);
806
+ }
807
+ update(data, params) {
808
+ if (params?.precondition != null) {
809
+ this.batch.update(this.documentRef, data, params?.precondition);
810
+ } else {
811
+ this.batch.update(this.documentRef, data);
812
+ }
813
+ return Promise.resolve();
814
+ }
815
+ }
816
+ /**
817
+ * Creates a new FirestoreDocumentDataAccessorFactory for a Batch.
818
+ *
819
+ * @param batch
820
+ * @returns
821
+ */
822
+ function writeBatchAccessorFactory(writeBatch) {
823
+ return {
824
+ accessorFor: ref => new WriteBatchFirestoreDocumentDataAccessor(writeBatch, ref)
825
+ };
826
+ }
827
+ // MARK: Context
828
+ class WriteBatchFirestoreDocumentContext {
829
+ constructor(batch) {
830
+ this._batch = void 0;
831
+ this.contextType = FirestoreDocumentContextType.BATCH;
832
+ this.accessorFactory = void 0;
833
+ this._batch = batch;
834
+ this.accessorFactory = writeBatchAccessorFactory(batch);
835
+ }
836
+ get batch() {
837
+ return this._batch;
838
+ }
839
+ }
840
+ function writeBatchDocumentContext(batch) {
841
+ return new WriteBatchFirestoreDocumentContext(batch);
842
+ }
843
+
844
+ // MARK: Accessor
845
+ class DefaultFirestoreDocumentDataAccessor {
846
+ constructor(documentRef) {
847
+ this._documentRef = void 0;
848
+ this._documentRef = documentRef;
849
+ }
850
+ get documentRef() {
851
+ return this._documentRef;
852
+ }
853
+ stream() {
854
+ return streamFromOnSnapshot(({
855
+ next,
856
+ error
857
+ }) => this.documentRef.onSnapshot(next, error));
858
+ }
859
+ create(data) {
860
+ return this.documentRef.create(data);
861
+ }
862
+ exists() {
863
+ return this.get().then(x => x.exists);
864
+ }
865
+ get() {
866
+ return this.documentRef.get();
867
+ }
868
+ getWithConverter(converter) {
869
+ return this.documentRef.withConverter(converter).get();
870
+ }
871
+ delete(params) {
872
+ return this.documentRef.delete(params?.precondition);
873
+ }
874
+ set(data, options) {
875
+ return options ? this.documentRef.set(data, options) : this.documentRef.set(data);
876
+ }
877
+ increment(data, params) {
878
+ return this.update(firestoreServerIncrementUpdateToUpdateData(data), params);
879
+ }
880
+ arrayUpdate(data, params) {
881
+ return this.update(firestoreServerArrayUpdateToUpdateData(data), params);
882
+ }
883
+ update(data, params) {
884
+ return params?.precondition ? this.documentRef.update(data, params.precondition) : this.documentRef.update(data);
885
+ }
886
+ }
887
+ function defaultFirestoreAccessorFactory() {
888
+ return {
889
+ accessorFor: ref => new DefaultFirestoreDocumentDataAccessor(ref)
890
+ };
891
+ }
892
+ // MARK: Context
893
+ function defaultFirestoreDocumentContext() {
894
+ return {
895
+ contextType: FirestoreDocumentContextType.NONE,
896
+ accessorFactory: defaultFirestoreAccessorFactory()
897
+ };
898
+ }
899
+
900
+ // MARK: Accessor
901
+ /**
902
+ * FirestoreDocumentDataAccessor implementation for a transaction.
903
+ */
904
+ class TransactionFirestoreDocumentDataAccessor {
905
+ constructor(transaction, documentRef) {
906
+ this._transaction = void 0;
907
+ this._documentRef = void 0;
908
+ this._transaction = transaction;
909
+ this._documentRef = documentRef;
910
+ }
911
+ get transaction() {
912
+ return this._transaction;
913
+ }
914
+ get documentRef() {
915
+ return this._documentRef;
916
+ }
917
+ stream() {
918
+ return from(this.get());
919
+ }
920
+ create(data) {
921
+ this.transaction.create(this.documentRef, data);
922
+ return Promise.resolve();
923
+ }
924
+ exists() {
925
+ return this.get().then(x => x.exists);
926
+ }
927
+ get() {
928
+ return this.transaction.get(this.documentRef);
929
+ }
930
+ getWithConverter(converter) {
931
+ return this.transaction.get(this.documentRef.withConverter(converter));
932
+ }
933
+ delete() {
934
+ this.transaction.delete(this.documentRef);
935
+ return Promise.resolve();
936
+ }
937
+ set(data, options) {
938
+ this.transaction.set(this.documentRef, data, options);
939
+ return Promise.resolve();
940
+ }
941
+ increment(data, params) {
942
+ return this.update(firestoreServerIncrementUpdateToUpdateData(data), params);
943
+ }
944
+ arrayUpdate(data, params) {
945
+ return this.update(firestoreServerArrayUpdateToUpdateData(data), params);
946
+ }
947
+ update(data, params) {
948
+ if (params?.precondition) {
949
+ this.transaction.update(this.documentRef, data, params?.precondition);
950
+ } else {
951
+ this.transaction.update(this.documentRef, data);
952
+ }
953
+ return Promise.resolve();
954
+ }
955
+ }
956
+ /**
957
+ * Creates a new FirestoreDocumentDataAccessorFactory for a Transaction.
958
+ *
959
+ * @param transaction
960
+ * @returns
961
+ */
962
+ function transactionAccessorFactory(transaction) {
963
+ return {
964
+ accessorFor: ref => new TransactionFirestoreDocumentDataAccessor(transaction, ref)
965
+ };
966
+ }
967
+ // MARK: Context
968
+ class TransactionFirestoreDocumentContext {
969
+ constructor(transaction) {
970
+ this._transaction = void 0;
971
+ this.contextType = FirestoreDocumentContextType.TRANSACTION;
972
+ this.accessorFactory = void 0;
973
+ this._transaction = transaction;
974
+ this.accessorFactory = transactionAccessorFactory(transaction);
975
+ }
976
+ get transaction() {
977
+ return this._transaction;
978
+ }
979
+ }
980
+ function transactionDocumentContext(transaction) {
981
+ return new TransactionFirestoreDocumentContext(transaction);
982
+ }
983
+
984
+ function collectionRefForPath(start, path, pathSegments) {
985
+ let ref = start.collection(path);
986
+ if (pathSegments?.length) {
987
+ if (pathSegments?.length % 2 !== 0) {
988
+ throw new Error(`Invalid number of path segments provided for collection. Path: "${path}" + "${pathSegments}"`);
989
+ }
990
+ const batches = batch(pathSegments, 2); // batch to tuple [string, string]
991
+ batches.forEach(x => {
992
+ const [first, second] = x;
993
+ ref = ref.doc(first).collection(second);
994
+ });
995
+ }
996
+ return ref;
997
+ }
998
+ function docRefForPath(start, path, pathSegments) {
999
+ let doc = path ? start.doc(path) : start.doc();
1000
+ if (pathSegments?.length) {
1001
+ const batches = batch(pathSegments, 2); // batch to tuple [string, string]
1002
+ batches.forEach(x => {
1003
+ const [first, second] = x;
1004
+ const collection = doc.collection(first);
1005
+ doc = second ? collection.doc(second) : collection.doc();
1006
+ });
1007
+ }
1008
+ return doc;
1009
+ }
1010
+ function googleCloudFirestoreAccessorDriver() {
1011
+ return {
1012
+ doc: (collection, path, ...pathSegments) => docRefForPath(collection, path, pathSegments),
1013
+ docAtPath: (firestore, fullPath) => firestore.doc(fullPath),
1014
+ collectionGroup: (firestore, collectionId) => firestore.collectionGroup(collectionId),
1015
+ collection: (firestore, path, ...pathSegments) => collectionRefForPath(firestore, path, pathSegments),
1016
+ subcollection: (document, path, ...pathSegments) => collectionRefForPath(document, path, pathSegments),
1017
+ transactionFactoryForFirestore: firestore => async fn => await firestore.runTransaction(fn),
1018
+ writeBatchFactoryForFirestore: firestore => () => firestore.batch(),
1019
+ defaultContextFactory: defaultFirestoreDocumentContext,
1020
+ transactionContextFactory: transactionDocumentContext,
1021
+ writeBatchContextFactory: writeBatchDocumentContext
1022
+ };
1023
+ }
1024
+
1025
+ const FIRESTORE_CLIENT_QUERY_CONSTRAINT_HANDLER_MAPPING = {
1026
+ [FIRESTORE_LIMIT_QUERY_CONSTRAINT_TYPE]: (builder, data) => builder.limit(data.limit),
1027
+ [FIRESTORE_LIMIT_TO_LAST_QUERY_CONSTRAINT_TYPE]: (builder, data) => builder.limitToLast(data.limit),
1028
+ [FIRESTORE_ORDER_BY_QUERY_CONSTRAINT_TYPE]: (builder, data) => builder.orderBy(data.fieldPath, data.directionStr),
1029
+ [FIRESTORE_ORDER_BY_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE]: (builder, data) => builder.orderBy(FieldPath.documentId(), data.directionStr),
1030
+ [FIRESTORE_WHERE_QUERY_CONSTRAINT_TYPE]: (builder, data) => builder.where(data.fieldPath, data.opStr, data.value),
1031
+ [FIRESTORE_WHERE_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE]: (builder, data) => builder.where(FieldPath.documentId(), data.opStr, data.value),
1032
+ [FIRESTORE_OFFSET_QUERY_CONSTRAINT_TYPE]: (builder, data) => builder.offset(data.offset),
1033
+ [FIRESTORE_START_AT_QUERY_CONSTRAINT_TYPE]: (builder, data) => builder.startAt(data.snapshot),
1034
+ [FIRESTORE_START_AT_VALUE_QUERY_CONSTRAINT_TYPE]: (builder, data) => builder.startAt(...data.fieldValues),
1035
+ [FIRESTORE_START_AFTER_QUERY_CONSTRAINT_TYPE]: (builder, data) => builder.startAfter(data.snapshot),
1036
+ [FIRESTORE_END_AT_QUERY_CONSTRAINT_TYPE]: (builder, data) => builder.endAt(data.snapshot),
1037
+ [FIRESTORE_END_AT_VALUE_QUERY_CONSTRAINT_TYPE]: (builder, data) => builder.endAt(...data.fieldValues),
1038
+ [FIRESTORE_END_BEFORE_QUERY_CONSTRAINT_TYPE]: (builder, data) => builder.endBefore(data.snapshot)
1039
+ };
1040
+ function firestoreClientQueryConstraintFunctionsDriver() {
1041
+ return makeFirestoreQueryConstraintFunctionsDriver({
1042
+ mapping: FIRESTORE_CLIENT_QUERY_CONSTRAINT_HANDLER_MAPPING,
1043
+ init: query => query,
1044
+ build: query => query,
1045
+ documentIdFieldPath: () => FieldPath.documentId()
1046
+ });
1047
+ }
1048
+ function googleCloudFirestoreQueryDriver() {
1049
+ return {
1050
+ ...firestoreClientQueryConstraintFunctionsDriver(),
1051
+ countDocs(query) {
1052
+ return query.count().get().then(x => x.data().count);
1053
+ },
1054
+ getDocs(query, transaction) {
1055
+ let result;
1056
+ if (transaction) {
1057
+ result = transaction.get(query);
1058
+ } else {
1059
+ result = query.get();
1060
+ }
1061
+ return result;
1062
+ },
1063
+ streamDocs(query) {
1064
+ return streamFromOnSnapshot(({
1065
+ next,
1066
+ error
1067
+ }) => query.onSnapshot(next, error));
1068
+ }
1069
+ };
1070
+ }
1071
+
1072
+ function googleCloudFirestoreDrivers() {
1073
+ return {
1074
+ firestoreDriverIdentifier: '@google-cloud/firestore',
1075
+ firestoreDriverType: 'production',
1076
+ firestoreAccessorDriver: googleCloudFirestoreAccessorDriver(),
1077
+ firestoreQueryDriver: googleCloudFirestoreQueryDriver()
1078
+ };
1079
+ }
1080
+
1081
+ /**
1082
+ * Creates a FirestoreContextFactory that uses the @'@google-cloud/firestore package.
1083
+ */
1084
+ const googleCloudFirestoreContextFactory = firestoreContextFactory(googleCloudFirestoreDrivers());
1085
+
1086
+ function assertContextHasAuth(context) {
1087
+ if (!isContextWithAuthData(context)) {
1088
+ throw unauthenticatedContextHasNoUidError();
1089
+ }
1090
+ }
1091
+ /**
1092
+ * Attempts to load data from the document. A modelNotAvailableError is thrown if the snapshot data is null/undefined (the document does not exist).
1093
+ *
1094
+ * @param document
1095
+ * @param message
1096
+ * @returns
1097
+ */
1098
+ async function assertSnapshotData(document, message) {
1099
+ const data = await document.snapshotData();
1100
+ if (data == null) {
1101
+ throw modelNotAvailableError({
1102
+ message: message ?? `The ${document.modelType} was unavailable.`
1103
+ });
1104
+ }
1105
+ return data;
1106
+ }
1107
+ /**
1108
+ * Convenience function for assertSnapshotData that also attaches the id and key of the document to the data.
1109
+ *
1110
+ * @param document
1111
+ * @param message
1112
+ * @returns
1113
+ */
1114
+ async function assertSnapshotDataWithKey(document, message) {
1115
+ const data = await assertSnapshotData(document, message);
1116
+ return setIdAndKeyFromKeyIdRefOnDocumentData(data, document);
1117
+ }
1118
+ /**
1119
+ * Asserts that the document exists. A modelNotAvailableError is thrown if the document does not exist.
1120
+ *
1121
+ * @param document
1122
+ * @param message
1123
+ * @returns
1124
+ */
1125
+ async function assertDocumentExists(document, message) {
1126
+ const exists = await document.exists();
1127
+ if (!exists) {
1128
+ throw documentModelNotAvailableError(document, message);
1129
+ }
1130
+ }
1131
+ /**
1132
+ * Error thrown by assertDocumentExists().
1133
+ *
1134
+ * @param document
1135
+ * @param message
1136
+ * @returns
1137
+ */
1138
+ function documentModelNotAvailableError(document, message) {
1139
+ return modelNotAvailableError({
1140
+ message: message ?? `The ${document.modelType} was unavailable.`
1141
+ });
1142
+ }
1143
+
1144
+ const PHONE_NUMBER_ALREADY_EXISTS_ERROR_CODE = 'PHONE_NUMBER_ALREADY_EXISTS';
1145
+ function phoneNumberAlreadyExistsError() {
1146
+ return preconditionConflictError({
1147
+ code: PHONE_NUMBER_ALREADY_EXISTS_ERROR_CODE,
1148
+ message: 'This phone number already exists in the system.'
1149
+ });
1150
+ }
1151
+ function handleFirebaseAuthError(e, handleUnknownCode) {
1152
+ handleFirebaseError(e, firebaseError => {
1153
+ switch (firebaseError.code) {
1154
+ case 'auth/phone-number-already-exists':
1155
+ throw phoneNumberAlreadyExistsError();
1156
+ default:
1157
+ handleUnknownCode?.(firebaseError);
1158
+ break;
1159
+ }
1160
+ });
1161
+ }
1162
+
1163
+ /******************************************************************************
1164
+ Copyright (c) Microsoft Corporation.
1165
+
1166
+ Permission to use, copy, modify, and/or distribute this software for any
1167
+ purpose with or without fee is hereby granted.
1168
+
1169
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
1170
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
1171
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
1172
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
1173
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
1174
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
1175
+ PERFORMANCE OF THIS SOFTWARE.
1176
+ ***************************************************************************** */
1177
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
1178
+
1179
+
1180
+ function __decorate(decorators, target, key, desc) {
1181
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
1182
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
1183
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
1184
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
1185
+ }
1186
+
1187
+ function __param(paramIndex, decorator) {
1188
+ return function (target, key) { decorator(target, key, paramIndex); }
1189
+ }
1190
+
1191
+ function __metadata(metadataKey, metadataValue) {
1192
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
1193
+ }
1194
+
1195
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
1196
+ var e = new Error(message);
1197
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
1198
+ };
1199
+
1200
+ // MARK: Tokens
1201
+ /**
1202
+ * Nest Injection Token to access the
1203
+ */
1204
+ const FIREBASE_APP_TOKEN = 'FIREBASE_APP_TOKEN';
1205
+ // MARK: Firebase Admin Provider
1206
+ function firebaseServerAppTokenProvider(useFactory) {
1207
+ return {
1208
+ provide: FIREBASE_APP_TOKEN,
1209
+ useFactory
1210
+ };
1211
+ }
1212
+
1213
+ // MARK: Tokens
1214
+ /**
1215
+ * Token to access the Auth for the app.
1216
+ */
1217
+ const FIREBASE_AUTH_TOKEN = 'FIREBASE_AUTH_TOKEN';
1218
+ /**
1219
+ * Nest provider module for Firebase that provides a firestore, etc. from the firestore token.
1220
+ */
1221
+ let FirebaseServerAuthModule = class FirebaseServerAuthModule {};
1222
+ FirebaseServerAuthModule = __decorate([Module({
1223
+ providers: [{
1224
+ provide: FIREBASE_AUTH_TOKEN,
1225
+ useFactory: app => app.auth(),
1226
+ inject: [FIREBASE_APP_TOKEN]
1227
+ }],
1228
+ exports: [FIREBASE_AUTH_TOKEN]
1229
+ })], FirebaseServerAuthModule);
1230
+ function provideFirebaseServerAuthService(provider) {
1231
+ return [{
1232
+ ...provider,
1233
+ inject: provider.inject ?? [FIREBASE_AUTH_TOKEN]
1234
+ }, {
1235
+ provide: FirebaseServerAuthService,
1236
+ useExisting: provider.provide
1237
+ }];
1238
+ }
1239
+ /**
1240
+ * Convenience function used to generate ModuleMetadata for an app's Auth related modules and FirebaseServerAuthService provider.
1241
+ *
1242
+ * @param provide
1243
+ * @param useFactory
1244
+ * @returns
1245
+ */
1246
+ function firebaseServerAuthModuleMetadata(config) {
1247
+ return mergeModuleMetadata({
1248
+ imports: [FirebaseServerAuthModule],
1249
+ exports: [FirebaseServerAuthModule, config.serviceProvider.provide],
1250
+ providers: provideFirebaseServerAuthService(config.serviceProvider)
1251
+ }, config);
1252
+ }
1253
+
1254
+ function assertIsAdminInRequest(request) {
1255
+ if (!isAdminInRequest(request)) {
1256
+ throw forbiddenError();
1257
+ }
1258
+ }
1259
+ function isAdminInRequest(request) {
1260
+ return request.nest.authService.context(request).isAdmin;
1261
+ }
1262
+ function assertIsAdminOrTargetUserInRequestData(request, requireUid) {
1263
+ if (!isAdminOrTargetUserInRequestData(request, requireUid)) {
1264
+ throw forbiddenError();
1265
+ }
1266
+ return request.data.uid ?? request.auth?.uid;
1267
+ }
1268
+ function isAdminOrTargetUserInRequestData(request, requireUid = false) {
1269
+ const uid = request.data.uid;
1270
+ const authUid = request.auth?.uid;
1271
+ let isAdminOrTargetUser = true;
1272
+ if (requireUid && uid == null || uid != null && uid !== authUid) {
1273
+ isAdminOrTargetUser = request.nest.authService.context(request).isAdmin;
1274
+ }
1275
+ return isAdminOrTargetUser;
1276
+ }
1277
+ function assertHasSignedTosInRequest(request) {
1278
+ if (!hasSignedTosInRequest(request)) {
1279
+ throw forbiddenError({
1280
+ message: 'ToS has not been signed.'
1281
+ });
1282
+ }
1283
+ }
1284
+ function hasSignedTosInRequest(request) {
1285
+ return request.nest.authService.context(request).hasSignedTos;
1286
+ }
1287
+ function assertHasRolesInRequest(request, authRoles) {
1288
+ if (!hasAuthRolesInRequest(request, authRoles)) {
1289
+ throw forbiddenError({
1290
+ message: 'Missing required auth roles.',
1291
+ data: {
1292
+ roles: asArray(authRoles)
1293
+ }
1294
+ });
1295
+ }
1296
+ }
1297
+ function hasAuthRolesInRequest(request, authRoles) {
1298
+ return containsAllValues(request.nest.authService.context(request).authRoles, authRoles);
1299
+ }
1300
+ /**
1301
+ * Returns true if the claims have a FIREBASE_SERVER_AUTH_CLAIMS_SETUP_PASSWORD_KEY claims value, indicating they are a newly invited user.
1302
+ *
1303
+ * This may be used to filter out new users that were not invited from finishing their onboarding.
1304
+ *
1305
+ * @param request
1306
+ */
1307
+ function hasNewUserSetupPasswordInRequest(request) {
1308
+ const claims = request.nest.authService.context(request).claims;
1309
+ return claims[FIREBASE_SERVER_AUTH_CLAIMS_SETUP_PASSWORD_KEY] != null;
1310
+ }
1311
+
1312
+ /**
1313
+ * Creates a OnCallWithAuthorizedNestContext function for creating a model.
1314
+ *
1315
+ * @param map
1316
+ * @returns
1317
+ */
1318
+ function onCallDevelopmentFunction(map, config = {}) {
1319
+ const {
1320
+ preAssert = () => undefined
1321
+ } = config;
1322
+ return request => {
1323
+ const specifier = request.data.specifier;
1324
+ const devFn = map[specifier];
1325
+ if (devFn) {
1326
+ preAssert({
1327
+ request,
1328
+ specifier
1329
+ });
1330
+ return devFn({
1331
+ ...request,
1332
+ specifier,
1333
+ data: request.data.data
1334
+ });
1335
+ } else {
1336
+ throw developmentUnknownSpecifierError(specifier);
1337
+ }
1338
+ };
1339
+ }
1340
+ function developmentUnknownSpecifierError(specifier) {
1341
+ return badRequestError(serverError({
1342
+ status: 400,
1343
+ code: 'UNKNOWN_SPECIFIER_ERROR',
1344
+ message: `Invalid specifier "${specifier}" to run.`,
1345
+ data: {
1346
+ specifier
1347
+ }
1348
+ }));
1349
+ }
1350
+
1351
+ const NO_RUN_NAME_SPECIFIED_FOR_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_CODE = 'NO_RUN_NAME_SPECIFIED_FOR_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION';
1352
+ function noRunNameSpecifiedForScheduledFunctionDevelopmentFunction() {
1353
+ return badRequestError({
1354
+ code: NO_RUN_NAME_SPECIFIED_FOR_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_CODE,
1355
+ message: `Must specify run parameter.`
1356
+ });
1357
+ }
1358
+ const UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_NAME_CODE = 'UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_NAME';
1359
+ function unknownScheduledFunctionDevelopmentFunctionName(name) {
1360
+ return badRequestError({
1361
+ code: UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_NAME_CODE,
1362
+ message: `Unknown function with name "${name}"`,
1363
+ data: {
1364
+ name
1365
+ }
1366
+ });
1367
+ }
1368
+ const UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_TYPE_CODE = 'UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_TYPE';
1369
+ function unknownScheduledFunctionDevelopmentFunctionType(type) {
1370
+ return badRequestError({
1371
+ code: UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_TYPE_CODE,
1372
+ message: `Unknown type "${type}"`,
1373
+ data: {
1374
+ type
1375
+ }
1376
+ });
1377
+ }
1378
+
1379
+ function makeScheduledFunctionDevelopmentFunction(config) {
1380
+ const {
1381
+ allScheduledFunctions
1382
+ } = config;
1383
+ const getListValues = cachedGetter(() => {
1384
+ const result = [];
1385
+ forEachKeyValue(allScheduledFunctions, {
1386
+ forEach: x => {
1387
+ const [functionName, config] = x;
1388
+ result.push({
1389
+ name: functionName.toString()
1390
+ });
1391
+ }
1392
+ });
1393
+ return result;
1394
+ });
1395
+ return async request => {
1396
+ const {
1397
+ data
1398
+ } = request;
1399
+ const {
1400
+ type
1401
+ } = data;
1402
+ switch (type) {
1403
+ case 'run':
1404
+ const targetRunName = data.run;
1405
+ if (!targetRunName) {
1406
+ throw noRunNameSpecifiedForScheduledFunctionDevelopmentFunction();
1407
+ }
1408
+ const targetFunction = allScheduledFunctions[targetRunName];
1409
+ if (!targetFunction) {
1410
+ throw unknownScheduledFunctionDevelopmentFunctionName(targetRunName);
1411
+ }
1412
+ try {
1413
+ await targetFunction._runNow();
1414
+ } catch (e) {
1415
+ console.error(`Failed manually running task "${targetRunName}".`, e);
1416
+ throw e;
1417
+ }
1418
+ return {
1419
+ type: 'run',
1420
+ success: true
1421
+ };
1422
+ case 'list':
1423
+ return {
1424
+ type: 'list',
1425
+ list: getListValues()
1426
+ };
1427
+ default:
1428
+ throw unknownScheduledFunctionDevelopmentFunctionType(type);
1429
+ }
1430
+ };
1431
+ }
1432
+
1433
+ function setNestContextOnRequest(makeNestContext, request) {
1434
+ request.nest = makeNestContext(request.nestApplication);
1435
+ return request;
1436
+ }
1437
+ /**
1438
+ * Wraps the input OnCallWithNestContext function to flag it as optional to have auth data.
1439
+ *
1440
+ * @param fn
1441
+ * @returns
1442
+ */
1443
+ function optionalAuthContext(fn) {
1444
+ const fnWithOptionalAuth = request => fn(request);
1445
+ fnWithOptionalAuth._requireAuth = false;
1446
+ return fnWithOptionalAuth;
1447
+ }
1448
+ /**
1449
+ * Asserts that the input request has auth data if the inputOnCallWithAuthAwareNestRequireAuthRef object is flagged to require auth.
1450
+ *
1451
+ * @param fn
1452
+ * @param request
1453
+ */
1454
+ function assertRequestRequiresAuthForFunction(fn, request) {
1455
+ if (fn._requireAuth !== false) {
1456
+ assertIsContextWithAuthData(request);
1457
+ }
1458
+ }
1459
+ /**
1460
+ * Creates an OnCallWithNestContext wrapper that validates the input CallableContext to assert the context has auth data before entering the function.
1461
+ *
1462
+ * @param fn
1463
+ * @returns
1464
+ */
1465
+ function inAuthContext(fn) {
1466
+ return request => {
1467
+ assertIsContextWithAuthData(request);
1468
+ return fn(request);
1469
+ };
1470
+ }
1471
+
1472
+ function firebaseServerDevFunctions(config) {
1473
+ const {
1474
+ enabled,
1475
+ secure,
1476
+ nest,
1477
+ developerFunctionsMap,
1478
+ onCallFactory,
1479
+ allScheduledFunctions,
1480
+ disableDevelopmentScheduleFunction
1481
+ } = config;
1482
+ let dev;
1483
+ if (enabled) {
1484
+ const fullFunctionsMap = {
1485
+ ...developerFunctionsMap
1486
+ };
1487
+ if (allScheduledFunctions && disableDevelopmentScheduleFunction !== false) {
1488
+ fullFunctionsMap[SCHEDULED_FUNCTION_DEV_FUNCTION_SPECIFIER] = makeScheduledFunctionDevelopmentFunction({
1489
+ allScheduledFunctions
1490
+ });
1491
+ }
1492
+ let onCallFunction = onCallDevelopmentFunction(fullFunctionsMap);
1493
+ if (secure != false) {
1494
+ onCallFunction = inAuthContext(onCallFunction);
1495
+ }
1496
+ dev = onCallFactory(onCallFunction)(nest);
1497
+ } else {
1498
+ dev = onCallFactory(async x => {
1499
+ throw unavailableError({
1500
+ message: 'developer tools service is not enabled.'
1501
+ });
1502
+ })(nest);
1503
+ }
1504
+ return {
1505
+ dev
1506
+ };
1507
+ }
1508
+
1509
+ let DefaultFirebaseServerEnvService = class DefaultFirebaseServerEnvService extends ServerEnvironmentService {
1510
+ /**
1511
+ * Enabled when not in production and not in a testing environment.
1512
+ */
1513
+ get developmentSchedulerEnabled() {
1514
+ return !this.isProduction && !this.isTestingEnv;
1515
+ }
1516
+ };
1517
+ DefaultFirebaseServerEnvService = __decorate([Injectable()], DefaultFirebaseServerEnvService);
1518
+
1519
+ function nestAppIsProductionEnvironment(nest) {
1520
+ return () => nest().then(x => x.get(FirebaseServerEnvService).isProduction);
1521
+ }
1522
+ function nestAppHasDevelopmentSchedulerEnabled(nest) {
1523
+ return () => nest().then(x => x.get(FirebaseServerEnvService).developmentSchedulerEnabled);
1524
+ }
1525
+
1526
+ // MARK: Tokens
1527
+ /**
1528
+ * Token to access the Firestore.
1529
+ */
1530
+ const FIREBASE_FIRESTORE_TOKEN = 'FIREBASE_FIRESTORE_TOKEN';
1531
+ /**
1532
+ * Token to access the root FirestoreContext for a server.
1533
+ */
1534
+ const FIREBASE_FIRESTORE_CONTEXT_TOKEN = 'FIREBASE_FIRESTORE_CONTEXT_TOKEN';
1535
+ /**
1536
+ * Nest provider module for Firebase that provides a firestore, etc. from the firestore token.
1537
+ */
1538
+ let FirebaseServerFirestoreModule = class FirebaseServerFirestoreModule {};
1539
+ FirebaseServerFirestoreModule = __decorate([Module({
1540
+ providers: [{
1541
+ provide: FIREBASE_FIRESTORE_TOKEN,
1542
+ useFactory: app => app.firestore(),
1543
+ inject: [FIREBASE_APP_TOKEN]
1544
+ }],
1545
+ exports: [FIREBASE_FIRESTORE_TOKEN]
1546
+ })], FirebaseServerFirestoreModule);
1547
+ /**
1548
+ * Nest provider module for firebase that includes the FirebaseServerFirestoreModule and provides a value for FIRESTORE_CONTEXT_TOKEN using the googleCloudFirestoreContextFactory.
1549
+ */
1550
+ let FirebaseServerFirestoreContextModule = class FirebaseServerFirestoreContextModule {};
1551
+ FirebaseServerFirestoreContextModule = __decorate([Module({
1552
+ imports: [FirebaseServerFirestoreModule],
1553
+ providers: [{
1554
+ provide: FIREBASE_FIRESTORE_CONTEXT_TOKEN,
1555
+ useFactory: googleCloudFirestoreContextFactory,
1556
+ inject: [FIREBASE_FIRESTORE_TOKEN]
1557
+ }],
1558
+ exports: [FirebaseServerFirestoreModule, FIREBASE_FIRESTORE_CONTEXT_TOKEN]
1559
+ })], FirebaseServerFirestoreContextModule);
1560
+ /**
1561
+ * Used to configure a Nestjs provider for a FirestoreCollections-type object that is initialized with a FirestoreContext.
1562
+ *
1563
+ * @param type
1564
+ * @param useFactory
1565
+ * @returns
1566
+ */
1567
+ function provideAppFirestoreCollections({
1568
+ provide,
1569
+ useFactory
1570
+ }) {
1571
+ return [{
1572
+ provide,
1573
+ useFactory,
1574
+ inject: [FIREBASE_FIRESTORE_CONTEXT_TOKEN]
1575
+ }];
1576
+ }
1577
+ /**
1578
+ * Convenience function used to generate ModuleMetadata for an app's Firestore related modules and an appFirestoreCollection
1579
+ *
1580
+ * @param provide
1581
+ * @param useFactory
1582
+ * @returns
1583
+ */
1584
+ function appFirestoreModuleMetadata(config) {
1585
+ return {
1586
+ imports: [FirebaseServerFirestoreContextModule, ...(config.imports ?? [])],
1587
+ exports: [FirebaseServerFirestoreContextModule, config.provide, ...(config.exports ?? [])],
1588
+ providers: [...provideAppFirestoreCollections(config), ...(config.providers ?? [])]
1589
+ };
1590
+ }
1591
+
1592
+ /**
1593
+ * Creates a BlockingFunctionWithHandler from the input.
1594
+ *
1595
+ * @param blockingFunctionBuilder
1596
+ * @param handler
1597
+ * @returns
1598
+ */
1599
+ function makeBlockingFunctionWithHandler(blockingFunctionBuilder, handler, opts) {
1600
+ const blockingFn = opts != null ? blockingFunctionBuilder(opts, handler) : blockingFunctionBuilder(handler);
1601
+ blockingFn.__handler = handler;
1602
+ return blockingFn;
1603
+ }
1604
+ /**
1605
+ * Creates a BlockingFunctionHandlerWithNestContextFactory.
1606
+ *
1607
+ * @param appFactory
1608
+ * @param makeNestContext
1609
+ * @returns
1610
+ */
1611
+ function blockingFunctionHandlerWithNestContextFactory(makeNestContext) {
1612
+ return fn => {
1613
+ return nestAppPromiseGetter => {
1614
+ const handlerBuilder = handler => {
1615
+ const fnHandler = event => nestAppPromiseGetter().then(nestApplication => handler({
1616
+ ...event,
1617
+ nest: makeNestContext(nestApplication)
1618
+ }));
1619
+ return fnHandler;
1620
+ };
1621
+ return fn(handlerBuilder);
1622
+ };
1623
+ };
1624
+ }
1625
+
1626
+ /**
1627
+ * Creates a factory for generating OnCallWithNestApplication (firebase-functions v2) functions.
1628
+ *
1629
+ * @param opts
1630
+ * @returns
1631
+ */
1632
+ function onCallHandlerWithNestApplicationFactory(defaultOpts = {}) {
1633
+ return (fn, opts) => {
1634
+ return nestAppPromiseGetter => https.onCall({
1635
+ ...defaultOpts,
1636
+ ...opts
1637
+ }, request => nestAppPromiseGetter().then(nestApplication => fn({
1638
+ ...request,
1639
+ nestApplication
1640
+ })));
1641
+ };
1642
+ }
1643
+ /**
1644
+ * Creates a factory for generating OnCallWithNestContext functions with a nest context object that is generated by the input function.
1645
+ *
1646
+ * @param appFactory
1647
+ * @param makeNestContext
1648
+ * @returns
1649
+ */
1650
+ function onCallHandlerWithNestContextFactory(appFactory, makeNestContext) {
1651
+ return (fn, opts) => appFactory(request => fn(setNestContextOnRequest(makeNestContext, request)), opts);
1652
+ }
1653
+
1654
+ /**
1655
+ * Creates a CloudEventHandlerWithNestContextFactory.
1656
+ *
1657
+ * @param appFactory
1658
+ * @param makeNestContext
1659
+ * @returns
1660
+ */
1661
+ function cloudEventHandlerWithNestContextFactory(makeNestContext) {
1662
+ return fn => {
1663
+ return nestAppPromiseGetter => {
1664
+ const handlerBuilder = handler => {
1665
+ const fnHandler = event => nestAppPromiseGetter().then(nestApplication => handler({
1666
+ ...event,
1667
+ nest: makeNestContext(nestApplication)
1668
+ }));
1669
+ return fnHandler;
1670
+ };
1671
+ return fn(handlerBuilder);
1672
+ };
1673
+ };
1674
+ }
1675
+
1676
+ function setNestContextOnScheduleRequest(makeNestContext, request) {
1677
+ request.nest = makeNestContext(request.nestApplication);
1678
+ return request;
1679
+ }
1680
+
1681
+ function makeOnScheduleHandlerWithNestApplicationRequest(nestApplication, scheduleContext) {
1682
+ return {
1683
+ nestApplication,
1684
+ scheduleContext
1685
+ };
1686
+ }
1687
+ /**
1688
+ * Creates a factory for generating OnCallWithNestApplication functions.
1689
+ *
1690
+ * @param nestAppPromiseGetter
1691
+ * @returns
1692
+ */
1693
+ function onScheduleHandlerWithNestApplicationFactory(baseScheduleConfig) {
1694
+ return (inputSchedule, fn) => {
1695
+ const schedule = mergeObjects([baseScheduleConfig, inputSchedule]);
1696
+ if (!schedule.schedule) {
1697
+ if (schedule.cron) {
1698
+ if (typeof schedule.cron === 'number') {
1699
+ schedule.schedule = cronExpressionRepeatingEveryNMinutes(schedule.cron);
1700
+ } else {
1701
+ schedule.schedule = schedule.cron;
1702
+ }
1703
+ } else {
1704
+ throw new Error('Missing required "cron" or "schedule" variable for configuration.');
1705
+ }
1706
+ }
1707
+ return nestAppPromiseGetter => {
1708
+ const runNow = scheduleContext => nestAppPromiseGetter().then(x => fn(makeOnScheduleHandlerWithNestApplicationRequest(x, scheduleContext)));
1709
+ const fnn = scheduler.onSchedule(schedule, runNow);
1710
+ fnn._schedule = schedule;
1711
+ fnn._runNow = runNow;
1712
+ return fnn;
1713
+ };
1714
+ };
1715
+ }
1716
+ /**
1717
+ * Creates a factory for generating OnCallWithNestContext functions with a nest context object that is generated by the input function.
1718
+ *
1719
+ * @param appFactory
1720
+ * @param makeNestContext
1721
+ * @returns
1722
+ */
1723
+ function onScheduleHandlerWithNestContextFactory(appFactory, makeNestContext) {
1724
+ return (schedule, fn) => appFactory(schedule, request => fn(setNestContextOnScheduleRequest(makeNestContext, request)));
1725
+ }
1726
+
1727
+ /**
1728
+ * Creates a TaskQueueFunctionHandlerWithNestContextFactory.
1729
+ *
1730
+ * @param appFactory
1731
+ * @param makeNestContext
1732
+ * @returns
1733
+ */
1734
+ function taskQueueFunctionHandlerWithNestContextFactory(makeNestContext) {
1735
+ return fn => {
1736
+ return nestAppPromiseGetter => {
1737
+ const handlerBuilder = handler => {
1738
+ const fnHandler = taskRequest => nestAppPromiseGetter().then(nestApplication => handler({
1739
+ ...taskRequest,
1740
+ nest: makeNestContext(nestApplication)
1741
+ }));
1742
+ return fnHandler;
1743
+ };
1744
+ return fn(handlerBuilder);
1745
+ };
1746
+ };
1747
+ }
1748
+ // TODO(FUTURE): Add factory that also adds onTaskDispatched usage, as the above is incomplete for full usage and only sets up a function for the request.
1749
+
1750
+ class AbstractFirebaseServerActionsContext {}
1751
+ function firebaseServerActionsContext(options) {
1752
+ return {
1753
+ ...firebaseServerActionsTransformContext(options)
1754
+ };
1755
+ }
1756
+ const defaultFirebaseServerActionsTransformFactoryLogErrorFunction = details => {
1757
+ console.log('firebaseServerActionsTransformFactory() encountered validation error: ', details);
1758
+ };
1759
+ function firebaseServerActionsTransformContext(options) {
1760
+ const firebaseServerActionTransformFactory = firebaseServerActionsTransformFactory(options);
1761
+ const firebaseServerActionTransformFunctionFactory = toTransformAndValidateFunctionResultFactory(firebaseServerActionTransformFactory);
1762
+ return {
1763
+ firebaseServerActionTransformFactory,
1764
+ firebaseServerActionTransformFunctionFactory
1765
+ };
1766
+ }
1767
+ const FIREBASE_SERVER_VALIDATION_ERROR_CODE = 'VALIDATION_ERROR';
1768
+ /**
1769
+ *
1770
+ * @param validationError
1771
+ * @returns
1772
+ */
1773
+ function firebaseServerValidationServerError(validationError) {
1774
+ const nestValidationExceptionFactory = new ValidationPipe({
1775
+ forbidUnknownValues: false
1776
+ }).createExceptionFactory();
1777
+ const nestError = nestValidationExceptionFactory(validationError);
1778
+ const data = nestError.getResponse();
1779
+ return {
1780
+ message: 'One or more data/form validation errors occurred.',
1781
+ code: FIREBASE_SERVER_VALIDATION_ERROR_CODE,
1782
+ data
1783
+ };
1784
+ }
1785
+ /**
1786
+ * Creates a new badRequestError with the validation error details as the response data.
1787
+ *
1788
+ * @param validationError
1789
+ * @returns
1790
+ */
1791
+ function firebaseServerValidationError(validationError) {
1792
+ const serverError = firebaseServerValidationServerError(validationError);
1793
+ return badRequestError(serverError);
1794
+ }
1795
+ function firebaseServerActionsTransformFactory(options) {
1796
+ const {
1797
+ logError,
1798
+ defaultValidationOptions
1799
+ } = options ?? {};
1800
+ const logErrorFunction = logError !== false ? typeof logError === 'function' ? logError : defaultFirebaseServerActionsTransformFactoryLogErrorFunction : mapIdentityFunction;
1801
+ return transformAndValidateObjectFactory({
1802
+ handleValidationError: validationError => {
1803
+ const serverError = firebaseServerValidationServerError(validationError);
1804
+ const {
1805
+ data
1806
+ } = serverError;
1807
+ logErrorFunction(data);
1808
+ throw badRequestError(serverError);
1809
+ },
1810
+ defaultValidationOptions
1811
+ });
1812
+ }
1813
+
1814
+ function injectNestIntoRequest(nest, request) {
1815
+ return {
1816
+ ...request,
1817
+ nest
1818
+ };
1819
+ }
1820
+ function injectNestApplicationContextIntoRequest(nestContext, request) {
1821
+ return {
1822
+ ...request,
1823
+ nestApplication: nestContext
1824
+ };
1825
+ }
1826
+
1827
+ /**
1828
+ * Can be injected to retrieve information about the global prefix configured for the app.
1829
+ */
1830
+ class GlobalRoutePrefixConfig {
1831
+ constructor() {
1832
+ this.globalApiRoutePrefix = void 0;
1833
+ }
1834
+ }
1835
+
1836
+ /**
1837
+ * Middleware that verifies the X-Firebase-AppCheck header using admin.
1838
+ *
1839
+ * It ignores all webhook paths by default.
1840
+ */
1841
+ let FirebaseAppCheckMiddleware = class FirebaseAppCheckMiddleware {
1842
+ constructor(globalRoutePrefixConfig) {
1843
+ this.globalRoutePrefixConfig = void 0;
1844
+ this.logger = new Logger('FirebaseAppCheckMiddleware');
1845
+ this._ignoredWebhookPath = void 0;
1846
+ this.globalRoutePrefixConfig = globalRoutePrefixConfig;
1847
+ this._ignoredWebhookPath = this.globalRoutePrefixConfig?.globalApiRoutePrefix ? `${this.globalRoutePrefixConfig.globalApiRoutePrefix}${DEFAULT_BASE_WEBHOOK_PATH}` : DEFAULT_BASE_WEBHOOK_PATH;
1848
+ }
1849
+ async use(req, res, next) {
1850
+ const isIgnoredRoute = this.isIgnoredRequest(req);
1851
+ let error;
1852
+ if (!isIgnoredRoute) {
1853
+ error = await verifyAppCheckInRequest(req);
1854
+ if (error) {
1855
+ this.logger.error('app check token failed verify');
1856
+ }
1857
+ }
1858
+ next(error);
1859
+ }
1860
+ isIgnoredRequest(req) {
1861
+ const isIgnoredRoute = req.skipAppCheck || this.isIgnoredPath(req.baseUrl);
1862
+ return isIgnoredRoute;
1863
+ }
1864
+ isIgnoredPath(path) {
1865
+ return path.startsWith(this._ignoredWebhookPath);
1866
+ }
1867
+ };
1868
+ FirebaseAppCheckMiddleware = __decorate([Injectable(), __param(0, Optional()), __param(0, Inject(GlobalRoutePrefixConfig)), __metadata("design:paramtypes", [Object])], FirebaseAppCheckMiddleware);
1869
+ /**
1870
+ * Verifies the AppCheck parameter. If it fails, a value is returned.
1871
+ *
1872
+ * @param req
1873
+ * @param res
1874
+ * @param next
1875
+ * @returns
1876
+ */
1877
+ async function verifyAppCheckInRequest(req) {
1878
+ const appCheckToken = req.header('X-Firebase-AppCheck');
1879
+ let error;
1880
+ if (!appCheckToken) {
1881
+ error = new ForbiddenException();
1882
+ } else {
1883
+ // verify the token
1884
+ try {
1885
+ await admin.appCheck().verifyToken(appCheckToken);
1886
+ } catch (e) {
1887
+ error = new ForbiddenException();
1888
+ }
1889
+ }
1890
+ return error;
1891
+ }
1892
+
1893
+ /**
1894
+ * Convenience class that mirrors the ConfigureAppCheckMiddlewareModule class in @dereekb/nestjs, but for Firebase apps.
1895
+ */
1896
+ let ConfigureFirebaseAppCheckMiddlewareModule = class ConfigureFirebaseAppCheckMiddlewareModule {
1897
+ constructor() {
1898
+ this.logger = new Logger('ConfigureFirebaseAppCheckMiddlewareModule');
1899
+ }
1900
+ configure(consumer) {
1901
+ consumer.apply(FirebaseAppCheckMiddleware).forRoutes('*');
1902
+ this.logger.debug('Configured firebase webhook routes with proper middleware.');
1903
+ }
1904
+ };
1905
+ ConfigureFirebaseAppCheckMiddlewareModule = __decorate([Module({})], ConfigureFirebaseAppCheckMiddlewareModule);
1906
+
1907
+ /**
1908
+ * nestjs decorator that will instruct FirebaseAppCheckMiddleware to skip AppCheck for related requests.
1909
+ */
1910
+ const SkipAppCheck = createParamDecorator(async (_, context) => {
1911
+ const req = context.switchToHttp().getRequest();
1912
+ req.skipAppCheck = true;
1913
+ });
1914
+
1915
+ let FirebaseRawBodyMiddleware = class FirebaseRawBodyMiddleware {
1916
+ use(req, res, next) {
1917
+ req.body = req.rawBody;
1918
+ next();
1919
+ }
1920
+ };
1921
+ FirebaseRawBodyMiddleware = __decorate([Injectable()], FirebaseRawBodyMiddleware);
1922
+
1923
+ /**
1924
+ * Convenience class that mirrors the ConfigureWebhookMiddlewareModule class in @dereekb/nestjs, but for Firebase apps.
1925
+ *
1926
+ * Requests to /webhook/* have their request.body value set to the rawBody.
1927
+ */
1928
+ let ConfigureFirebaseWebhookMiddlewareModule = class ConfigureFirebaseWebhookMiddlewareModule {
1929
+ constructor() {
1930
+ this.logger = new Logger('ConfigureFirebaseWebhookMiddlewareModule');
1931
+ }
1932
+ configure(consumer) {
1933
+ consumer.apply(FirebaseRawBodyMiddleware).forRoutes(DEFAULT_WEBHOOK_MIDDLEWARE_ROUTE_INFO);
1934
+ this.logger.debug('Configured firebase webhook routes with proper middleware.');
1935
+ }
1936
+ };
1937
+ ConfigureFirebaseWebhookMiddlewareModule = __decorate([Module({})], ConfigureFirebaseWebhookMiddlewareModule);
1938
+
1939
+ const nestFirebaseDoesNotExistError = firebaseContextGrantedModelRoles => {
1940
+ return modelNotAvailableError({
1941
+ data: {
1942
+ id: firebaseContextGrantedModelRoles.data?.document.key,
1943
+ type: firebaseContextGrantedModelRoles.data?.document.modelType
1944
+ }
1945
+ });
1946
+ };
1947
+ const nestFirebaseForbiddenPermissionError = (firebaseContextGrantedModelRoles, roles) => {
1948
+ return forbiddenError({
1949
+ data: {
1950
+ id: firebaseContextGrantedModelRoles.data?.document.key,
1951
+ type: firebaseContextGrantedModelRoles.data?.document.modelType,
1952
+ roles
1953
+ }
1954
+ });
1955
+ };
1956
+
1957
+ function onCallSpecifierHandler(config) {
1958
+ const map = objectToMap(config);
1959
+ const fn = request => {
1960
+ const {
1961
+ specifier = MODEL_FUNCTION_FIREBASE_CRUD_FUNCTION_SPECIFIER_DEFAULT
1962
+ } = request;
1963
+ const handler = map.get(specifier);
1964
+ if (handler != null) {
1965
+ assertRequestRequiresAuthForFunction(handler, request);
1966
+ return handler(request);
1967
+ } else {
1968
+ throw unknownModelCrudFunctionSpecifierError(specifier);
1969
+ }
1970
+ };
1971
+ fn._requireAuth = false;
1972
+ return fn;
1973
+ }
1974
+ function unknownModelCrudFunctionSpecifierError(specifier) {
1975
+ return badRequestError(serverError({
1976
+ status: 400,
1977
+ code: 'UNKNOWN_SPECIFIER_ERROR',
1978
+ message: 'Invalid/unknown specifier for this function.',
1979
+ data: {
1980
+ specifier
1981
+ }
1982
+ }));
1983
+ }
1984
+
1985
+ /**
1986
+ * Creates a OnCallWithAuthorizedNestContext function for creating a model.
1987
+ *
1988
+ * @param map
1989
+ * @returns
1990
+ */
1991
+ function onCallModel(map, config = {}) {
1992
+ const {
1993
+ preAssert = () => undefined
1994
+ } = config;
1995
+ return request => {
1996
+ const call = request.data?.call;
1997
+ if (call) {
1998
+ const callFn = map[call];
1999
+ if (callFn) {
2000
+ const {
2001
+ specifier,
2002
+ modelType
2003
+ } = request.data;
2004
+ preAssert({
2005
+ call,
2006
+ request,
2007
+ modelType,
2008
+ specifier
2009
+ });
2010
+ return callFn(request);
2011
+ } else {
2012
+ throw onCallModelUnknownCallTypeError(call);
2013
+ }
2014
+ } else {
2015
+ throw onCallModelMissingCallTypeError();
2016
+ }
2017
+ };
2018
+ }
2019
+ function onCallModelMissingCallTypeError() {
2020
+ return badRequestError(serverError({
2021
+ status: 400,
2022
+ code: 'CALL_TYPE_MISSING_ERROR',
2023
+ message: `The call type was missing from the request.`
2024
+ }));
2025
+ }
2026
+ function onCallModelUnknownCallTypeError(call) {
2027
+ return badRequestError(serverError({
2028
+ status: 400,
2029
+ code: 'UNKNOWN_CALL_TYPE_ERROR',
2030
+ message: `Unknown call type "${call}".`,
2031
+ data: {
2032
+ call
2033
+ }
2034
+ }));
2035
+ }
2036
+ function _onCallWithCallTypeFunction(map, config) {
2037
+ const {
2038
+ callType,
2039
+ crudType,
2040
+ preAssert = () => undefined,
2041
+ throwOnUnknownModelType
2042
+ } = config;
2043
+ return request => {
2044
+ const modelType = request.data?.modelType;
2045
+ const crudFn = map[modelType];
2046
+ if (crudFn) {
2047
+ const specifier = request.data.specifier;
2048
+ assertRequestRequiresAuthForFunction(crudFn, request);
2049
+ preAssert({
2050
+ call: callType,
2051
+ request,
2052
+ modelType,
2053
+ specifier
2054
+ });
2055
+ return crudFn({
2056
+ ...request,
2057
+ specifier,
2058
+ data: request.data.data
2059
+ });
2060
+ } else {
2061
+ throw throwOnUnknownModelType(modelType);
2062
+ }
2063
+ };
2064
+ }
2065
+
2066
+ function onCallCreateModel(map, config = {}) {
2067
+ const {
2068
+ preAssert
2069
+ } = config;
2070
+ return _onCallWithCallTypeFunction(map, {
2071
+ callType: 'create',
2072
+ crudType: 'create',
2073
+ preAssert,
2074
+ throwOnUnknownModelType: createModelUnknownModelTypeError
2075
+ });
2076
+ }
2077
+ function createModelUnknownModelTypeError(modelType) {
2078
+ return badRequestError(serverError({
2079
+ status: 400,
2080
+ code: 'UNKNOWN_TYPE_ERROR',
2081
+ message: `Invalid type "${modelType}" to create.`,
2082
+ data: {
2083
+ modelType
2084
+ }
2085
+ }));
2086
+ }
2087
+
2088
+ function onCallReadModel(map, config = {}) {
2089
+ const {
2090
+ preAssert
2091
+ } = config;
2092
+ return _onCallWithCallTypeFunction(map, {
2093
+ callType: 'read',
2094
+ crudType: 'read',
2095
+ preAssert,
2096
+ throwOnUnknownModelType: readModelUnknownModelTypeError
2097
+ });
2098
+ }
2099
+ function readModelUnknownModelTypeError(modelType) {
2100
+ return badRequestError(serverError({
2101
+ status: 400,
2102
+ code: 'UNKNOWN_TYPE_ERROR',
2103
+ message: 'Invalid type to read.',
2104
+ data: {
2105
+ modelType
2106
+ }
2107
+ }));
2108
+ }
2109
+
2110
+ function onCallUpdateModel(map, config = {}) {
2111
+ const {
2112
+ preAssert
2113
+ } = config;
2114
+ return _onCallWithCallTypeFunction(map, {
2115
+ callType: 'update',
2116
+ crudType: 'update',
2117
+ preAssert,
2118
+ throwOnUnknownModelType: updateModelUnknownModelTypeError
2119
+ });
2120
+ }
2121
+ function updateModelUnknownModelTypeError(modelType) {
2122
+ return badRequestError(serverError({
2123
+ status: 400,
2124
+ code: 'UNKNOWN_TYPE_ERROR',
2125
+ message: 'Invalid type to update.',
2126
+ data: {
2127
+ modelType
2128
+ }
2129
+ }));
2130
+ }
2131
+
2132
+ function onCallDeleteModel(map, config = {}) {
2133
+ const {
2134
+ preAssert
2135
+ } = config;
2136
+ return _onCallWithCallTypeFunction(map, {
2137
+ callType: 'delete',
2138
+ crudType: 'delete',
2139
+ preAssert,
2140
+ throwOnUnknownModelType: deleteModelUnknownModelTypeError
2141
+ });
2142
+ }
2143
+ function deleteModelUnknownModelTypeError(modelType) {
2144
+ return badRequestError(serverError({
2145
+ status: 400,
2146
+ code: 'UNKNOWN_TYPE_ERROR',
2147
+ message: 'Invalid type to delete.',
2148
+ data: {
2149
+ modelType
2150
+ }
2151
+ }));
2152
+ }
2153
+
2154
+ function googleCloudStorageBucketForStorageFilePath(storage, path) {
2155
+ return storage.bucket(path.bucketId);
2156
+ }
2157
+ function googleCloudStorageFileForStorageFilePath(storage, path) {
2158
+ return googleCloudStorageBucketForStorageFilePath(storage, path).file(path.pathString);
2159
+ }
2160
+ function googleCloudFileMetadataToStorageMetadata(file, metadata) {
2161
+ const fullPath = file.name;
2162
+ const generation = String(metadata.generation ?? file.generation);
2163
+ const metageneration = String(metadata.metageneration);
2164
+ const size = Number(metadata.size);
2165
+ const customMetadata = metadata.metadata;
2166
+ return {
2167
+ bucket: file.bucket.name,
2168
+ fullPath,
2169
+ generation,
2170
+ metageneration,
2171
+ name: file.name,
2172
+ size,
2173
+ timeCreated: metadata.timeCreated,
2174
+ updated: metadata.updated,
2175
+ md5Hash: metadata.md5Hash,
2176
+ cacheControl: metadata.cacheControl,
2177
+ contentDisposition: metadata.contentDisposition,
2178
+ contentEncoding: metadata.contentEncoding,
2179
+ contentLanguage: metadata.contentLanguage,
2180
+ contentType: metadata.contentType,
2181
+ customMetadata
2182
+ };
2183
+ }
2184
+ function googleCloudStorageAccessorFile(storage, storagePath) {
2185
+ const file = googleCloudStorageFileForStorageFilePath(storage, storagePath);
2186
+ function makeDownloadOptions(maxDownloadSizeBytes) {
2187
+ return {
2188
+ ...(maxDownloadSizeBytes ? {
2189
+ // end is inclusive
2190
+ end: maxDownloadSizeBytes - 1
2191
+ } : undefined)
2192
+ };
2193
+ }
2194
+ function _configureMetadata(options) {
2195
+ const customMetadata = filterUndefinedValues({
2196
+ ...options.metadata?.customMetadata,
2197
+ ...options?.customMetadata
2198
+ });
2199
+ return filterUndefinedValues({
2200
+ cacheControl: options.metadata?.cacheControl,
2201
+ contentDisposition: options.metadata?.contentDisposition,
2202
+ contentEncoding: options.metadata?.contentEncoding,
2203
+ contentLanguage: options.metadata?.contentLanguage,
2204
+ contentType: options.metadata?.contentType,
2205
+ metadata: !objectHasNoKeys(customMetadata) ? customMetadata : undefined
2206
+ });
2207
+ }
2208
+ function makeUploadOptions(options) {
2209
+ let metadata;
2210
+ if (options != null) {
2211
+ metadata = _configureMetadata({
2212
+ metadata: {
2213
+ ...options.metadata,
2214
+ contentType: options.contentType ?? options.metadata?.contentType
2215
+ },
2216
+ customMetadata: options.customMetadata
2217
+ });
2218
+ }
2219
+ return {
2220
+ // non-resumable
2221
+ resumable: false,
2222
+ // add content type and other custom metadata
2223
+ ...(metadata ? {
2224
+ metadata
2225
+ } : undefined)
2226
+ };
2227
+ }
2228
+ function asFileMetadata(metadata) {
2229
+ return _configureMetadata({
2230
+ metadata
2231
+ });
2232
+ }
2233
+ function makeStoragePathForPath(newPath) {
2234
+ let path;
2235
+ if (typeof newPath === 'string') {
2236
+ path = {
2237
+ bucketId: file.bucket.name,
2238
+ pathString: newPath
2239
+ };
2240
+ } else {
2241
+ path = newPath;
2242
+ }
2243
+ return path;
2244
+ }
2245
+ async function copy(newPath, options) {
2246
+ const newStoragePath = makeStoragePathForPath(newPath);
2247
+ const newFile = googleCloudStorageAccessorFile(storage, newStoragePath);
2248
+ return _copyWithFile(newFile, options);
2249
+ }
2250
+ async function _copyWithFile(newFile, options) {
2251
+ const copyOptions = {
2252
+ ...options
2253
+ };
2254
+ await file.copy(newFile.reference, copyOptions);
2255
+ return newFile;
2256
+ }
2257
+ /**
2258
+ * Configuration for the public ACL.
2259
+ */
2260
+ const PUBLIC_ACL = {
2261
+ entity: 'allUsers',
2262
+ role: 'READER'
2263
+ };
2264
+ const accessorFile = {
2265
+ reference: file,
2266
+ storagePath,
2267
+ exists: () => file.exists().then(x => x[0]),
2268
+ getDownloadUrl: () => file.getMetadata().then(() => file.publicUrl()),
2269
+ getSignedUrl: async input => {
2270
+ const expires = input?.expiresAt ?? (input?.expiresIn != null ? addMilliseconds(new Date(), input.expiresIn) // use expiresIn if provided
2271
+ : addHours(new Date(), 1)); // default expiration in 1 hour
2272
+ const config = {
2273
+ ...input,
2274
+ action: input?.action ?? 'read',
2275
+ expires,
2276
+ expiresIn: undefined,
2277
+ // clear from input
2278
+ expiresAt: undefined
2279
+ };
2280
+ return file.getSignedUrl(config).then(x => x[0]).catch(e => {
2281
+ let publicUrlBackup;
2282
+ if (e && e.name === 'SigningError' && (isTestNodeEnv() || process.env.FIREBASE_STORAGE_EMULATOR_HOST)) {
2283
+ // NOTE: Signing does not behave properly in the emulator as it is not supported.
2284
+ // https://github.com/firebase/firebase-tools/issues/3400
2285
+ // we can return the public url instead.
2286
+ // This is fine, as in production this file url is protected by ACLs anyways.
2287
+ publicUrlBackup = file.publicUrl();
2288
+ } else {
2289
+ throw e;
2290
+ }
2291
+ return publicUrlBackup;
2292
+ });
2293
+ },
2294
+ getMetadata: () => file.getMetadata().then(x => googleCloudFileMetadataToStorageMetadata(file, x[0])),
2295
+ setMetadata: metadata => file.setMetadata(asFileMetadata(metadata)).then(x => googleCloudFileMetadataToStorageMetadata(file, x[0])),
2296
+ getBytes: maxDownloadSizeBytes => file.download(makeDownloadOptions(maxDownloadSizeBytes)).then(x => x[0]),
2297
+ getStream: maxDownloadSizeBytes => file.createReadStream(makeDownloadOptions(maxDownloadSizeBytes)),
2298
+ upload: async (input, options) => {
2299
+ let dataToUpload;
2300
+ if (typeof input === 'string') {
2301
+ const parsedStringFormat = assertStorageUploadOptionsStringFormat(options);
2302
+ const stringFormat = parsedStringFormat === 'raw' ? 'utf-8' : parsedStringFormat;
2303
+ if (stringFormat === 'data_url') {
2304
+ // TODO(FUTURE): support this later if necessary. Server should really never see this type.
2305
+ throw new Error('"data_url" is unsupported.');
2306
+ }
2307
+ dataToUpload = Buffer.from(input, stringFormat);
2308
+ } else {
2309
+ if (Buffer.isBuffer(input)) {
2310
+ dataToUpload = input;
2311
+ } else if (isUint8Array(input)) {
2312
+ dataToUpload = Buffer.from(input);
2313
+ } else {
2314
+ // NOTE: these values shouldn't ever be encountered in the NodeJS environment. May remove later.
2315
+ if (isArrayBuffer(input)) {
2316
+ dataToUpload = Buffer.from(input);
2317
+ } else {
2318
+ dataToUpload = input.arrayBuffer().then(x => Buffer.from(x));
2319
+ }
2320
+ }
2321
+ }
2322
+ const data = await dataToUpload;
2323
+ return file.save(data, makeUploadOptions(options));
2324
+ },
2325
+ uploadStream: options => file.createWriteStream(makeUploadOptions(options)),
2326
+ move: async (newPath, options) => {
2327
+ const newStoragePath = makeStoragePathForPath(newPath);
2328
+ const newFile = googleCloudStorageAccessorFile(storage, newStoragePath);
2329
+ const moveOptions = {
2330
+ ...options
2331
+ };
2332
+ await file.moveFileAtomic(newFile.reference, moveOptions).catch(async e => {
2333
+ if (e instanceof ApiError && e.response?.statusMessage === 'Not Implemented') {
2334
+ // NOTE: This is not implemented in storage emulator, so it will fail with this error in testing.
2335
+ // https://github.com/firebase/firebase-tools/issues/3751
2336
+ // we can perform the same task using copy and then deleting this file.
2337
+ await copy(newPath, moveOptions);
2338
+ await accessorFile.delete();
2339
+ } else {
2340
+ throw e;
2341
+ }
2342
+ });
2343
+ return newFile;
2344
+ },
2345
+ copy,
2346
+ delete: options => file.delete(options).then(x => undefined),
2347
+ isPublic: () => file.isPublic().then(x => x[0]),
2348
+ makePublic: setPublic => (setPublic !== false ? file.acl.add(PUBLIC_ACL) : file.acl.delete({
2349
+ entity: PUBLIC_ACL.entity
2350
+ })).then(() => undefined),
2351
+ makePrivate: options => file.makePrivate(options).then(() => undefined),
2352
+ getAcls: options => file.acl.get(options).then(x => ({
2353
+ acls: x[0],
2354
+ metadata: x[1]
2355
+ }))
2356
+ };
2357
+ return accessorFile;
2358
+ }
2359
+ const googleCloudStorageListFilesResultFactory = storageListFilesResultFactory({
2360
+ hasItems(result) {
2361
+ return Boolean(result.apiResponse.items || result.apiResponse.prefixes);
2362
+ },
2363
+ hasNext: result => {
2364
+ return result.nextQuery != null;
2365
+ },
2366
+ nextPageTokenFromResult(result) {
2367
+ return result.nextQuery?.pageToken;
2368
+ },
2369
+ next(storage, options, folder, result) {
2370
+ return folder.list({
2371
+ ...options,
2372
+ ...result.nextQuery
2373
+ });
2374
+ },
2375
+ file(storage, fileResult) {
2376
+ return googleCloudStorageAccessorFile(storage, fileResult.storagePath);
2377
+ },
2378
+ folder(storage, folderResult) {
2379
+ return googleCloudStorageAccessorFolder(storage, folderResult.storagePath);
2380
+ },
2381
+ filesFromResult(result) {
2382
+ const items = result.apiResponse?.items ?? [];
2383
+ return items.map(x => ({
2384
+ raw: x,
2385
+ name: slashPathName(x.name),
2386
+ storagePath: {
2387
+ bucketId: x.bucket,
2388
+ pathString: x.name
2389
+ }
2390
+ }));
2391
+ },
2392
+ foldersFromResult(result, folder) {
2393
+ const items = result.apiResponse?.prefixes ?? [];
2394
+ return items.map(prefix => ({
2395
+ raw: prefix,
2396
+ name: slashPathName(prefix),
2397
+ storagePath: {
2398
+ bucketId: folder.storagePath.bucketId,
2399
+ pathString: prefix
2400
+ }
2401
+ }));
2402
+ }
2403
+ });
2404
+ function googleCloudStorageAccessorFolder(storage, storagePath) {
2405
+ const bucket = googleCloudStorageBucketForStorageFilePath(storage, storagePath);
2406
+ const file = bucket.file(storagePath.pathString);
2407
+ const folder = {
2408
+ reference: file,
2409
+ storagePath,
2410
+ exists: async () => folder.list({
2411
+ maxResults: 1
2412
+ }).then(x => x.hasItems()),
2413
+ list: options => {
2414
+ const {
2415
+ maxResults,
2416
+ pageToken,
2417
+ includeNestedResults: listAll
2418
+ } = options ?? {};
2419
+ const listOptions = {
2420
+ maxResults,
2421
+ pageToken,
2422
+ autoPaginate: false,
2423
+ versions: false,
2424
+ ...(listAll ? {
2425
+ prefix: toRelativeSlashPathStartType(fixMultiSlashesInSlashPath(storagePath.pathString + '/'))
2426
+ } : {
2427
+ // includeTrailingDelimiter: true,
2428
+ delimiter: SLASH_PATH_SEPARATOR,
2429
+ prefix: toRelativeSlashPathStartType(fixMultiSlashesInSlashPath(storagePath.pathString + '/')) // make sure the folder always ends with a slash
2430
+ })
2431
+ };
2432
+ return bucket.getFiles(listOptions).then(x => {
2433
+ const files = x[0];
2434
+ const nextQuery = x[1];
2435
+ const apiResponse = x[2];
2436
+ const result = {
2437
+ files: files,
2438
+ nextQuery,
2439
+ apiResponse: apiResponse
2440
+ };
2441
+ return googleCloudStorageListFilesResultFactory(storage, folder, options, result);
2442
+ });
2443
+ }
2444
+ };
2445
+ return folder;
2446
+ }
2447
+ function googleCloudStorageFirebaseStorageAccessorDriver() {
2448
+ return {
2449
+ type: 'server',
2450
+ file: (storage, path) => googleCloudStorageAccessorFile(storage, path),
2451
+ folder: (storage, path) => googleCloudStorageAccessorFolder(storage, path)
2452
+ };
2453
+ }
2454
+
2455
+ function googleCloudFirebaseStorageDrivers() {
2456
+ return {
2457
+ storageDriverIdentifier: '@google-cloud/storage',
2458
+ storageDriverType: 'production',
2459
+ storageAccessorDriver: googleCloudStorageFirebaseStorageAccessorDriver()
2460
+ };
2461
+ }
2462
+
2463
+ /**
2464
+ * Basic service that implements FirebaseStorageAccessor and provides a FirebaseStorageContext.
2465
+ */
2466
+ class FirebaseServerStorageService {
2467
+ constructor(storageContext) {
2468
+ this._storageContext = void 0;
2469
+ this._storageContext = storageContext;
2470
+ }
2471
+ get storageContext() {
2472
+ return this._storageContext;
2473
+ }
2474
+ defaultBucket() {
2475
+ return this.storageContext.defaultBucket();
2476
+ }
2477
+ file(path) {
2478
+ return this.storageContext.file(path);
2479
+ }
2480
+ folder(path) {
2481
+ return this.storageContext.folder(path);
2482
+ }
2483
+ }
2484
+
2485
+ /**
2486
+ * Creates a FirestoreContextFactory that uses the @google-cloud/storage package.
2487
+ */
2488
+ const googleCloudFirebaseStorageContextFactory = firebaseStorageContextFactory(googleCloudFirebaseStorageDrivers());
2489
+ /**
2490
+ * Retrieves the GoogleCloudStorage object from the input FirebaseAdmin Storage type.
2491
+ *
2492
+ * @param storage
2493
+ * @returns
2494
+ */
2495
+ function googleCloudStorageFromFirebaseAdminStorage(storage) {
2496
+ return storage.storageClient;
2497
+ }
2498
+
2499
+ // MARK: Tokens
2500
+ /**
2501
+ * Token to access the Storage.
2502
+ */
2503
+ const FIREBASE_STORAGE_TOKEN = 'FIREBASE_STORAGE_TOKEN';
2504
+ /**
2505
+ * Token to access the root StorageContext for a server.
2506
+ */
2507
+ const FIREBASE_STORAGE_CONTEXT_TOKEN = 'FIREBASE_STORAGE_CONTEXT_TOKEN';
2508
+ /**
2509
+ * Token to the default bucket id string
2510
+ */
2511
+ const FIREBASE_STORAGE_CONTEXT_FACTORY_CONFIG_TOKEN = 'FIREBASE_STORAGE_CONTEXT_FACTORY_CONFIG_TOKEN';
2512
+ /**
2513
+ * Nest provider module for Firebase that provides a firestore, etc. from the firestore token.
2514
+ */
2515
+ let FirebaseServerStorageModule = class FirebaseServerStorageModule {};
2516
+ FirebaseServerStorageModule = __decorate([Module({
2517
+ providers: [{
2518
+ provide: FIREBASE_STORAGE_TOKEN,
2519
+ useFactory: app => googleCloudStorageFromFirebaseAdminStorage(app.storage()),
2520
+ inject: [FIREBASE_APP_TOKEN]
2521
+ }],
2522
+ exports: [FIREBASE_STORAGE_TOKEN]
2523
+ })], FirebaseServerStorageModule);
2524
+ /**
2525
+ * Nest provider module for firebase that includes the FirebaseServerStorageModule and provides a value for STORAGE_CONTEXT_TOKEN using the googleCloudStorageContextFactory.
2526
+ */
2527
+ let FirebaseServerStorageContextModule = class FirebaseServerStorageContextModule {};
2528
+ FirebaseServerStorageContextModule = __decorate([Module({
2529
+ imports: [FirebaseServerStorageModule],
2530
+ providers: [{
2531
+ provide: FIREBASE_STORAGE_CONTEXT_TOKEN,
2532
+ useFactory: googleCloudFirebaseStorageContextFactory,
2533
+ inject: [FIREBASE_STORAGE_TOKEN, FIREBASE_STORAGE_CONTEXT_FACTORY_CONFIG_TOKEN]
2534
+ }],
2535
+ exports: [FirebaseServerStorageModule, FIREBASE_STORAGE_CONTEXT_TOKEN]
2536
+ })], FirebaseServerStorageContextModule);
2537
+ // MARK: Token Configuration
2538
+ function firebaseServerStorageDefaultBucketIdTokenProvider(input) {
2539
+ const config = typeof input === 'string' ? {
2540
+ defaultBucketId: input
2541
+ } : input;
2542
+ if (!config.defaultBucketId) {
2543
+ throw new Error('Non-empty defaultBucketId is required.');
2544
+ }
2545
+ return {
2546
+ provide: FIREBASE_STORAGE_CONTEXT_FACTORY_CONFIG_TOKEN,
2547
+ useValue: config
2548
+ };
2549
+ }
2550
+ function defaultProvideFirebaseServerStorageServiceSimple() {
2551
+ return {
2552
+ provide: FirebaseServerStorageService,
2553
+ useFactory: context => new FirebaseServerStorageService(context)
2554
+ };
2555
+ }
2556
+ function provideFirebaseServerStorageService(provider) {
2557
+ const providers = [{
2558
+ ...provider,
2559
+ inject: provider.inject ?? [FIREBASE_STORAGE_CONTEXT_TOKEN]
2560
+ }];
2561
+ if (provider.provide !== FirebaseServerStorageService) {
2562
+ providers.push({
2563
+ provide: FirebaseServerStorageService,
2564
+ useExisting: provider.provide
2565
+ });
2566
+ }
2567
+ return providers;
2568
+ }
2569
+ /**
2570
+ * Convenience function used to generate ModuleMetadata for an app's Auth related modules and FirebaseServerStorageService provider.
2571
+ *
2572
+ * @param provide
2573
+ * @param useFactory
2574
+ * @returns
2575
+ */
2576
+ function firebaseServerStorageModuleMetadata(config) {
2577
+ const serviceProvider = config && config.serviceProvider ? config.serviceProvider : defaultProvideFirebaseServerStorageServiceSimple();
2578
+ const providers = provideFirebaseServerStorageService(serviceProvider);
2579
+ const tokensToExport = injectionTokensFromProviders(providers);
2580
+ return mergeModuleMetadata({
2581
+ imports: [FirebaseServerStorageContextModule],
2582
+ exports: [FirebaseServerStorageContextModule, ...tokensToExport],
2583
+ providers
2584
+ }, config);
2585
+ }
2586
+
2587
+ class FirebaseNestServerRootModule {}
2588
+ function nestServerInstance(config) {
2589
+ const {
2590
+ moduleClass,
2591
+ providers: additionalProviders,
2592
+ defaultStorageBucket: inputDefaultStorageBucket,
2593
+ forceStorageBucket,
2594
+ globalApiRoutePrefix,
2595
+ configureNestServerInstance
2596
+ } = config;
2597
+ const serversCache = new Map();
2598
+ const initNestServer = (firebaseApp, env) => {
2599
+ const appName = firebaseApp.name;
2600
+ const defaultStorageBucket = inputDefaultStorageBucket ?? firebaseApp.options.storageBucket;
2601
+ let nestServer = serversCache.get(appName);
2602
+ if (!nestServer) {
2603
+ const server = express();
2604
+ const createNestServer = async expressInstance => {
2605
+ const providers = [firebaseServerAppTokenProvider(asGetter(firebaseApp))];
2606
+ // configure environment providers
2607
+ if (env?.environment != null) {
2608
+ providers.push(serverEnvTokenProvider(env.environment));
2609
+ if (config.configureEnvService !== false) {
2610
+ providers.push({
2611
+ provide: FirebaseServerEnvService,
2612
+ useClass: DefaultFirebaseServerEnvService
2613
+ }, {
2614
+ provide: ServerEnvironmentService,
2615
+ useExisting: FirebaseServerEnvService
2616
+ });
2617
+ }
2618
+ }
2619
+ if (additionalProviders) {
2620
+ pushItemOrArrayItemsIntoArray(providers, additionalProviders);
2621
+ }
2622
+ const imports = [moduleClass];
2623
+ // NOTE: https://cloud.google.com/functions/docs/writing/http#parsing_http_requests
2624
+ const options = {
2625
+ bodyParser: false
2626
+ }; // firebase already parses the requests
2627
+ if (config.configureWebhooks) {
2628
+ imports.push(ConfigureFirebaseWebhookMiddlewareModule);
2629
+ }
2630
+ if (config.appCheckEnabled != false) {
2631
+ imports.push(ConfigureFirebaseAppCheckMiddlewareModule);
2632
+ }
2633
+ if (defaultStorageBucket) {
2634
+ providers.push(firebaseServerStorageDefaultBucketIdTokenProvider({
2635
+ defaultBucketId: defaultStorageBucket,
2636
+ forceBucket: forceStorageBucket
2637
+ }));
2638
+ }
2639
+ // provide the global prefix config to the app
2640
+ providers.push({
2641
+ provide: GlobalRoutePrefixConfig,
2642
+ useValue: {
2643
+ globalApiRoutePrefix
2644
+ }
2645
+ });
2646
+ const providersModule = {
2647
+ module: FirebaseNestServerRootModule,
2648
+ imports,
2649
+ providers,
2650
+ exports: providers,
2651
+ global: true
2652
+ };
2653
+ let nestApp = await NestFactory.create(providersModule, new ExpressAdapter(expressInstance), options);
2654
+ if (globalApiRoutePrefix) {
2655
+ nestApp = nestApp.setGlobalPrefix(globalApiRoutePrefix);
2656
+ }
2657
+ if (configureNestServerInstance) {
2658
+ nestApp = configureNestServerInstance(nestApp) || nestApp;
2659
+ }
2660
+ return nestApp.init();
2661
+ };
2662
+ const nest = createNestServer(server).catch(err => {
2663
+ console.error('Nest failed startup.', err);
2664
+ throw err;
2665
+ });
2666
+ nestServer = {
2667
+ server,
2668
+ nest: makeGetter(nest)
2669
+ };
2670
+ serversCache.set(appName, nestServer);
2671
+ }
2672
+ return nestServer;
2673
+ };
2674
+ const removeNestServer = async firebaseApp => {
2675
+ const appName = firebaseApp.name;
2676
+ const nestServer = serversCache.get(appName);
2677
+ let removed;
2678
+ if (nestServer) {
2679
+ removed = nestServer.nest().then(x => {
2680
+ serversCache.delete(appName);
2681
+ return x.close().then(() => true);
2682
+ });
2683
+ } else {
2684
+ removed = Promise.resolve(false);
2685
+ }
2686
+ return removed;
2687
+ };
2688
+ return {
2689
+ moduleClass,
2690
+ initNestServer,
2691
+ removeNestServer
2692
+ };
2693
+ }
2694
+
2695
+ /**
2696
+ * Abstract class that wraps an INestApplicationContext value.
2697
+ */
2698
+ class AbstractNestContext {
2699
+ constructor(nest) {
2700
+ this._nest = void 0;
2701
+ this._nest = nest;
2702
+ }
2703
+ get nest() {
2704
+ return this._nest;
2705
+ }
2706
+ }
2707
+ class AbstractFirebaseNestContext extends AbstractNestContext {
2708
+ constructor(...args) {
2709
+ super(...args);
2710
+ /**
2711
+ * FirebasePermissionErrorContextErrorFunction to use with makeModelContext().
2712
+ *
2713
+ * Defaults to nestFirebaseForbiddenPermissionError().
2714
+ */
2715
+ this.makePermissionError = nestFirebaseForbiddenPermissionError;
2716
+ /**
2717
+ * FirebaseDoesNotExistErrorContextErrorFunction to use with makeModelContext().
2718
+ *
2719
+ * Defaults to nestFirebaseDoesNotExistError().
2720
+ *
2721
+ * Some configurations may prefer to use nestFirebaseForbiddenPermissionError instead, which returns a forbidden error instead.
2722
+ * This prevents the leaking of information about the existence of an object.
2723
+ */
2724
+ this.makeDoesNotExistError = nestFirebaseDoesNotExistError;
2725
+ }
2726
+ get envService() {
2727
+ return this.nest.get(FirebaseServerEnvService);
2728
+ }
2729
+ get storageService() {
2730
+ return this.nest.get(FirebaseServerStorageService);
2731
+ }
2732
+ /**
2733
+ * Creates a FirebaseAppModelContext instance.
2734
+ *
2735
+ * @param auth
2736
+ * @param buildFn
2737
+ * @returns
2738
+ */
2739
+ makeModelContext(auth, buildFn) {
2740
+ const base = {
2741
+ auth: this.authService.authContextInfo(auth),
2742
+ app: this.app,
2743
+ makePermissionError: this.makePermissionError,
2744
+ makeDoesNotExistError: this.makeDoesNotExistError
2745
+ };
2746
+ return buildFn ? build({
2747
+ base,
2748
+ build: buildFn
2749
+ }) : base;
2750
+ }
2751
+ /**
2752
+ * Creates a InContextFirebaseModelsService given the input context and parameters.
2753
+ *
2754
+ * @param context
2755
+ * @param buildFn
2756
+ * @returns
2757
+ */
2758
+ model(context, buildFn) {
2759
+ const firebaseModelContext = this.makeModelContext(context, buildFn);
2760
+ return inContextFirebaseModelsServiceFactory(this.firebaseModelsService)(firebaseModelContext);
2761
+ }
2762
+ async useModel(type, select) {
2763
+ const context = this.makeModelContext(select.request, select.buildFn);
2764
+ const usePromise = useFirebaseModelsService(this.firebaseModelsService, type, {
2765
+ context,
2766
+ key: select.key,
2767
+ roles: select.roles,
2768
+ rolesSetIncludes: select.rolesSetIncludes
2769
+ });
2770
+ const use = select.use ?? (x => x);
2771
+ return usePromise(use);
2772
+ }
2773
+ }
2774
+
2775
+ export { ALREADY_EXISTS_ERROR_CODE, AbstractFirebaseNestContext, AbstractFirebaseServerActionsContext, AbstractFirebaseServerAuthContext, AbstractFirebaseServerAuthService, AbstractFirebaseServerAuthUserContext, AbstractFirebaseServerNewUserService, AbstractNestContext, BAD_REQUEST_ERROR_CODE, CONFLICT_ERROR_CODE, ConfigureFirebaseAppCheckMiddlewareModule, ConfigureFirebaseWebhookMiddlewareModule, DEFAULT_FIREBASE_PASSWORD_NUMBER_GENERATOR, DEFAULT_SETUP_COM_THROTTLE_TIME, DefaultFirebaseServerEnvService, FIREBASE_APP_TOKEN, FIREBASE_AUTH_TOKEN, FIREBASE_FIRESTORE_CONTEXT_TOKEN, FIREBASE_FIRESTORE_TOKEN, FIREBASE_SERVER_VALIDATION_ERROR_CODE, FIREBASE_STORAGE_CONTEXT_FACTORY_CONFIG_TOKEN, FIREBASE_STORAGE_CONTEXT_TOKEN, FIREBASE_STORAGE_TOKEN, FIRESTORE_CLIENT_QUERY_CONSTRAINT_HANDLER_MAPPING, FORBIDDEN_ERROR_CODE, FirebaseAppCheckMiddleware, FirebaseNestServerRootModule, FirebaseRawBodyMiddleware, FirebaseServerAuthModule, FirebaseServerAuthNewUserSendSetupDetailsNoSetupConfigError, FirebaseServerAuthNewUserSendSetupDetailsSendOnceError, FirebaseServerAuthNewUserSendSetupDetailsThrottleError, FirebaseServerAuthService, FirebaseServerEnvService, FirebaseServerFirestoreContextModule, FirebaseServerFirestoreModule, FirebaseServerStorageContextModule, FirebaseServerStorageModule, FirebaseServerStorageService, INTERNAL_SERVER_ERROR_CODE, MODEL_NOT_AVAILABLE_ERROR_CODE, NOT_FOUND_ERROR_CODE, NO_AUTH_ERROR_CODE, NO_RUN_NAME_SPECIFIED_FOR_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_CODE, NO_UID_ERROR_CODE, NoSetupContentFirebaseServerNewUserService, PERMISSION_DENIED_ERROR_CODE, PHONE_NUMBER_ALREADY_EXISTS_ERROR_CODE, SkipAppCheck, UNAUTHENTICATED_ERROR_CODE, UNAVAILABLE_ERROR_CODE, UNAVAILABLE_OR_DEACTIVATED_FUNCTION_ERROR_CODE, UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_NAME_CODE, UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_TYPE_CODE, _onCallWithCallTypeFunction, alreadyExistsError, appFirestoreModuleMetadata, assertContextHasAuth, assertDocumentExists, assertHasRolesInRequest, assertHasSignedTosInRequest, assertIsAdminInRequest, assertIsAdminOrTargetUserInRequestData, assertIsContextWithAuthData, assertRequestRequiresAuthForFunction, assertSnapshotData, assertSnapshotDataWithKey, badRequestError, blockingFunctionHandlerWithNestContextFactory, cloudEventHandlerWithNestContextFactory, collectionRefForPath, createModelUnknownModelTypeError, defaultFirebaseServerActionsTransformFactoryLogErrorFunction, defaultProvideFirebaseServerStorageServiceSimple, deleteModelUnknownModelTypeError, developmentUnknownSpecifierError, docRefForPath, documentModelNotAvailableError, firebaseAuthTokenFromDecodedIdToken, firebaseServerActionsContext, firebaseServerActionsTransformContext, firebaseServerActionsTransformFactory, firebaseServerAppTokenProvider, firebaseServerAuthModuleMetadata, firebaseServerDevFunctions, firebaseServerErrorInfo, firebaseServerErrorInfoCodePair, firebaseServerErrorInfoServerErrorCodePair, firebaseServerErrorInfoServerErrorPair, firebaseServerStorageDefaultBucketIdTokenProvider, firebaseServerStorageModuleMetadata, firebaseServerValidationError, firebaseServerValidationServerError, firestoreClientQueryConstraintFunctionsDriver, firestoreServerIncrementUpdateToUpdateData, forbiddenError, getAuthUserOrUndefined, googleCloudFileMetadataToStorageMetadata, googleCloudFirebaseStorageContextFactory, googleCloudFirebaseStorageDrivers, googleCloudFirestoreAccessorDriver, googleCloudFirestoreContextFactory, googleCloudFirestoreDrivers, googleCloudFirestoreQueryDriver, googleCloudStorageAccessorFile, googleCloudStorageAccessorFolder, googleCloudStorageBucketForStorageFilePath, googleCloudStorageFileForStorageFilePath, googleCloudStorageFirebaseStorageAccessorDriver, googleCloudStorageFromFirebaseAdminStorage, googleCloudStorageListFilesResultFactory, handleFirebaseAuthError, handleFirebaseError, hasAuthRolesInRequest, hasNewUserSetupPasswordInRequest, hasSignedTosInRequest, inAuthContext, injectNestApplicationContextIntoRequest, injectNestIntoRequest, internalServerError, isAdminInRequest, isAdminOrTargetUserInRequestData, isContextWithAuthData, isFirebaseError, isFirebaseHttpsError, makeBlockingFunctionWithHandler, makeOnScheduleHandlerWithNestApplicationRequest, makeScheduledFunctionDevelopmentFunction, modelNotAvailableError, nestAppHasDevelopmentSchedulerEnabled, nestAppIsProductionEnvironment, nestFirebaseDoesNotExistError, nestFirebaseForbiddenPermissionError, nestServerInstance, noRunNameSpecifiedForScheduledFunctionDevelopmentFunction, notFoundError, onCallCreateModel, onCallDeleteModel, onCallDevelopmentFunction, onCallHandlerWithNestApplicationFactory, onCallHandlerWithNestContextFactory, onCallModel, onCallModelMissingCallTypeError, onCallModelUnknownCallTypeError, onCallReadModel, onCallSpecifierHandler, onCallUpdateModel, onScheduleHandlerWithNestApplicationFactory, onScheduleHandlerWithNestContextFactory, optionalAuthContext, permissionDeniedError, phoneNumberAlreadyExistsError, preconditionConflictError, provideAppFirestoreCollections, provideFirebaseServerAuthService, provideFirebaseServerStorageService, readModelUnknownModelTypeError, setNestContextOnRequest, setNestContextOnScheduleRequest, taskQueueFunctionHandlerWithNestContextFactory, unauthenticatedContextHasNoAuthData, unauthenticatedContextHasNoUidError, unauthenticatedError, unavailableError, unavailableOrDeactivatedFunctionError, unknownModelCrudFunctionSpecifierError, unknownScheduledFunctionDevelopmentFunctionName, unknownScheduledFunctionDevelopmentFunctionType, updateModelUnknownModelTypeError, userContextFromUid, verifyAppCheckInRequest };