@dereekb/firebase-server 13.7.0 → 13.8.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.
package/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import { DBX_FIREBASE_SERVER_NO_AUTH_ERROR_CODE, UNAUTHENTICATED_ERROR_CODE, FORBIDDEN_ERROR_CODE, PERMISSION_DENIED_ERROR_CODE, NOT_FOUND_ERROR_CODE, MODEL_NOT_AVAILABLE_ERROR_CODE, BAD_REQUEST_ERROR_CODE, CONFLICT_ERROR_CODE, ALREADY_EXISTS_ERROR_CODE, UNAVAILABLE_ERROR_CODE, UNAVAILABLE_OR_DEACTIVATED_FUNCTION_ERROR_CODE, INTERNAL_SERVER_ERROR_CODE, FIREBASE_AUTH_USER_NOT_FOUND_ERROR, FIREBASE_SERVER_AUTH_CLAIMS_RESET_PASSWORD_KEY, FIREBASE_SERVER_AUTH_CLAIMS_RESET_LAST_COM_DATE_KEY, FIREBASE_SERVER_AUTH_CLAIMS_SETUP_PASSWORD_KEY, FIREBASE_AUTH_PHONE_NUMBER_ALREADY_EXISTS_ERROR, FIREBASE_AUTH_EMAIL_ALREADY_EXISTS_ERROR, FIREBASE_AUTH_INVALID_PHONE_NUMBER_ERROR, FIREBASE_SERVER_AUTH_CLAIMS_SETUP_LAST_COM_DATE_KEY, FirestoreDocumentContextType, streamFromOnSnapshot, makeFirestoreQueryConstraintFunctionsDriver, FIRESTORE_LIMIT_QUERY_CONSTRAINT_TYPE, FIRESTORE_LIMIT_TO_LAST_QUERY_CONSTRAINT_TYPE, FIRESTORE_ORDER_BY_QUERY_CONSTRAINT_TYPE, FIRESTORE_ORDER_BY_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE, FIRESTORE_WHERE_QUERY_CONSTRAINT_TYPE, FIRESTORE_WHERE_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE, FIRESTORE_OFFSET_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AT_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AT_VALUE_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AFTER_QUERY_CONSTRAINT_TYPE, FIRESTORE_END_AT_QUERY_CONSTRAINT_TYPE, FIRESTORE_END_AT_VALUE_QUERY_CONSTRAINT_TYPE, FIRESTORE_END_BEFORE_QUERY_CONSTRAINT_TYPE, firestoreContextFactory, firestoreField, optionalFirestoreField, setIdAndKeyFromKeyIdRefOnDocumentData, MODEL_FUNCTION_FIREBASE_CRUD_FUNCTION_SPECIFIER_DEFAULT, UNKNOWN_MODEL_TYPE_ERROR_CODE, BAD_DOCUMENT_QUERY_CURSOR_ERROR_CODE, limit, startAfter, DEFAULT_ON_CALL_QUERY_MODEL_LIMIT, MAX_ON_CALL_QUERY_MODEL_LIMIT, ScheduledFunctionDevelopmentFunctionTypeEnum, SCHEDULED_FUNCTION_DEV_FUNCTION_SPECIFIER, storageListFilesResultFactory, assertStorageUploadOptionsStringFormat, firebaseStorageContextFactory, inContextFirebaseModelsServiceFactory, useFirebaseModelsService } from '@dereekb/firebase';
1
+ import { DBX_FIREBASE_SERVER_NO_AUTH_ERROR_CODE, UNAUTHENTICATED_ERROR_CODE, FORBIDDEN_ERROR_CODE, PERMISSION_DENIED_ERROR_CODE, NOT_FOUND_ERROR_CODE, MODEL_NOT_AVAILABLE_ERROR_CODE, BAD_REQUEST_ERROR_CODE, CONFLICT_ERROR_CODE, ALREADY_EXISTS_ERROR_CODE, UNAVAILABLE_ERROR_CODE, UNAVAILABLE_OR_DEACTIVATED_FUNCTION_ERROR_CODE, INTERNAL_SERVER_ERROR_CODE, FIREBASE_AUTH_USER_NOT_FOUND_ERROR, FIREBASE_SERVER_AUTH_CLAIMS_RESET_PASSWORD_KEY, FIREBASE_SERVER_AUTH_CLAIMS_RESET_LAST_COM_DATE_KEY, FIREBASE_SERVER_AUTH_CLAIMS_SETUP_PASSWORD_KEY, FIREBASE_AUTH_PHONE_NUMBER_ALREADY_EXISTS_ERROR, FIREBASE_AUTH_EMAIL_ALREADY_EXISTS_ERROR, FIREBASE_AUTH_INVALID_PHONE_NUMBER_ERROR, FIREBASE_SERVER_AUTH_CLAIMS_SETUP_LAST_COM_DATE_KEY, setIdAndKeyFromKeyIdRefOnDocumentData, DBX_FIREBASE_SERVER_PASSWORD_RESET_INVALID_CODE_ERROR_CODE, DBX_FIREBASE_SERVER_PASSWORD_RESET_NO_CONFIG_ERROR_CODE, DBX_FIREBASE_SERVER_PASSWORD_RESET_SEND_ONCE_ERROR_CODE, DBX_FIREBASE_SERVER_PASSWORD_RESET_THROTTLE_ERROR_CODE, FirestoreDocumentContextType, streamFromOnSnapshot, makeFirestoreQueryConstraintFunctionsDriver, FIRESTORE_LIMIT_QUERY_CONSTRAINT_TYPE, FIRESTORE_LIMIT_TO_LAST_QUERY_CONSTRAINT_TYPE, FIRESTORE_ORDER_BY_QUERY_CONSTRAINT_TYPE, FIRESTORE_ORDER_BY_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE, FIRESTORE_WHERE_QUERY_CONSTRAINT_TYPE, FIRESTORE_WHERE_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE, FIRESTORE_OFFSET_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AT_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AT_VALUE_QUERY_CONSTRAINT_TYPE, FIRESTORE_START_AFTER_QUERY_CONSTRAINT_TYPE, FIRESTORE_END_AT_QUERY_CONSTRAINT_TYPE, FIRESTORE_END_AT_VALUE_QUERY_CONSTRAINT_TYPE, FIRESTORE_END_BEFORE_QUERY_CONSTRAINT_TYPE, firestoreContextFactory, firestoreField, optionalFirestoreField, MODEL_FUNCTION_FIREBASE_CRUD_FUNCTION_SPECIFIER_DEFAULT, UNKNOWN_MODEL_TYPE_ERROR_CODE, BAD_DOCUMENT_QUERY_CURSOR_ERROR_CODE, limit, startAfter, DEFAULT_ON_CALL_QUERY_MODEL_LIMIT, MAX_ON_CALL_QUERY_MODEL_LIMIT, ScheduledFunctionDevelopmentFunctionTypeEnum, SCHEDULED_FUNCTION_DEV_FUNCTION_SPECIFIER, storageListFilesResultFactory, assertStorageUploadOptionsStringFormat, firebaseStorageContextFactory, inContextFirebaseModelsServiceFactory, useFirebaseModelsService } from '@dereekb/firebase';
2
2
  import { partialServerError, isServerError, randomNumberFactory, cachedGetter, filterNullAndUndefinedValues, asSet, AUTH_ADMIN_ROLE, AUTH_TOS_SIGNED_ROLE, forEachKeyValue, KeyValueTypleValueFilter, filterUndefinedValues, isThrottled, mapObjectMap, batch, objectToMap, serverError, asArray, containsAllValues, websiteUrlDetails, mergeObjects, cronExpressionRepeatingEveryNMinutes, mapIdentityFunction, slashPathName, toRelativeSlashPathStartType, fixMultiSlashesInSlashPath, SLASH_PATH_SEPARATOR, objectHasNoKeys, websiteUrlFromPaths, pushItemOrArrayItemsIntoArray, makeGetter, asGetter, build, performAsyncTasks } from '@dereekb/util';
3
3
  import { HttpsError } from 'firebase-functions/https';
4
4
  import { hoursToMs, toISODateString } from '@dereekb/date';
@@ -430,7 +430,7 @@ function _type_of$7(obj) {
430
430
  };
431
431
  }
432
432
 
433
- function asyncGeneratorStep$g(gen, resolve, reject, _next, _throw, key, arg) {
433
+ function asyncGeneratorStep$h(gen, resolve, reject, _next, _throw, key, arg) {
434
434
  try {
435
435
  var info = gen[key](arg);
436
436
  var value = info.value;
@@ -444,22 +444,22 @@ function asyncGeneratorStep$g(gen, resolve, reject, _next, _throw, key, arg) {
444
444
  Promise.resolve(value).then(_next, _throw);
445
445
  }
446
446
  }
447
- function _async_to_generator$g(fn) {
447
+ function _async_to_generator$h(fn) {
448
448
  return function() {
449
449
  var self = this, args = arguments;
450
450
  return new Promise(function(resolve, reject) {
451
451
  var gen = fn.apply(self, args);
452
452
  function _next(value) {
453
- asyncGeneratorStep$g(gen, resolve, reject, _next, _throw, "next", value);
453
+ asyncGeneratorStep$h(gen, resolve, reject, _next, _throw, "next", value);
454
454
  }
455
455
  function _throw(err) {
456
- asyncGeneratorStep$g(gen, resolve, reject, _next, _throw, "throw", err);
456
+ asyncGeneratorStep$h(gen, resolve, reject, _next, _throw, "throw", err);
457
457
  }
458
458
  _next(undefined);
459
459
  });
460
460
  };
461
461
  }
462
- function _ts_generator$g(thisArg, body) {
462
+ function _ts_generator$h(thisArg, body) {
463
463
  var f, y, t, _ = {
464
464
  label: 0,
465
465
  sent: function() {
@@ -575,9 +575,9 @@ function _ts_generator$g(thisArg, body) {
575
575
  * }
576
576
  * ```
577
577
  */ function getAuthUserOrUndefined(promise) {
578
- return _async_to_generator$g(function() {
578
+ return _async_to_generator$h(function() {
579
579
  var error;
580
- return _ts_generator$g(this, function(_state) {
580
+ return _ts_generator$h(this, function(_state) {
581
581
  switch(_state.label){
582
582
  case 0:
583
583
  _state.trys.push([
@@ -602,9 +602,8 @@ function _ts_generator$g(thisArg, body) {
602
602
  2,
603
603
  undefined
604
604
  ];
605
- } else {
606
- throw error;
607
605
  }
606
+ throw error;
608
607
  case 3:
609
608
  return [
610
609
  2
@@ -782,6 +781,62 @@ function _is_native_reflect_construct$5() {
782
781
  ]);
783
782
  }
784
783
  return FirebaseServerAuthNewUserSendSetupDetailsSendOnceError;
784
+ }(BaseError);
785
+ // MARK: Password Reset Errors
786
+ /**
787
+ * Thrown by {@link AbstractFirebaseServerUserPasswordResetService.sendResetContent} when the user
788
+ * has no active password reset claims, meaning no reset has been initiated or it has already been completed.
789
+ */ var FirebaseServerAuthPasswordResetNoResetConfigError = /*#__PURE__*/ function(BaseError) {
790
+ _inherits$5(FirebaseServerAuthPasswordResetNoResetConfigError, BaseError);
791
+ function FirebaseServerAuthPasswordResetNoResetConfigError() {
792
+ _class_call_check$r(this, FirebaseServerAuthPasswordResetNoResetConfigError);
793
+ return _call_super$5(this, FirebaseServerAuthPasswordResetNoResetConfigError, [
794
+ "This user has no active password reset configuration."
795
+ ]);
796
+ }
797
+ return FirebaseServerAuthPasswordResetNoResetConfigError;
798
+ }(BaseError);
799
+ /**
800
+ * Thrown by {@link AbstractFirebaseServerUserPasswordResetService.sendResetContent} when the user
801
+ * was recently sent reset content and the throttle window has not elapsed.
802
+ */ var FirebaseServerAuthPasswordResetThrottleError = /*#__PURE__*/ function(BaseError) {
803
+ _inherits$5(FirebaseServerAuthPasswordResetThrottleError, BaseError);
804
+ function FirebaseServerAuthPasswordResetThrottleError(lastSentAt) {
805
+ _class_call_check$r(this, FirebaseServerAuthPasswordResetThrottleError);
806
+ var _this;
807
+ _this = _call_super$5(this, FirebaseServerAuthPasswordResetThrottleError, [
808
+ "This user was recently sent password reset details. Try again later."
809
+ ]), _define_property$y(_this, "lastSentAt", void 0);
810
+ _this.lastSentAt = lastSentAt;
811
+ return _this;
812
+ }
813
+ return FirebaseServerAuthPasswordResetThrottleError;
814
+ }(BaseError);
815
+ /**
816
+ * Thrown by {@link AbstractFirebaseServerUserPasswordResetService.sendResetContent} when the user
817
+ * has already been sent reset content and the `sendResetDetailsOnce` option was enabled.
818
+ */ var FirebaseServerAuthPasswordResetSendOnceError = /*#__PURE__*/ function(BaseError) {
819
+ _inherits$5(FirebaseServerAuthPasswordResetSendOnceError, BaseError);
820
+ function FirebaseServerAuthPasswordResetSendOnceError() {
821
+ _class_call_check$r(this, FirebaseServerAuthPasswordResetSendOnceError);
822
+ return _call_super$5(this, FirebaseServerAuthPasswordResetSendOnceError, [
823
+ "The user has been sent password reset details before and the sendResetDetailsOnce configuration was true."
824
+ ]);
825
+ }
826
+ return FirebaseServerAuthPasswordResetSendOnceError;
827
+ }(BaseError);
828
+ /**
829
+ * Thrown by {@link AbstractFirebaseServerUserPasswordResetService.completePasswordReset} when the
830
+ * provided reset code does not match the one stored in the user's claims, or no reset is active.
831
+ */ var FirebaseServerAuthPasswordResetInvalidCodeError = /*#__PURE__*/ function(BaseError) {
832
+ _inherits$5(FirebaseServerAuthPasswordResetInvalidCodeError, BaseError);
833
+ function FirebaseServerAuthPasswordResetInvalidCodeError() {
834
+ _class_call_check$r(this, FirebaseServerAuthPasswordResetInvalidCodeError);
835
+ return _call_super$5(this, FirebaseServerAuthPasswordResetInvalidCodeError, [
836
+ "The provided reset password code is invalid or expired."
837
+ ]);
838
+ }
839
+ return FirebaseServerAuthPasswordResetInvalidCodeError;
785
840
  }
786
841
  (BaseError);
787
842
 
@@ -802,7 +857,7 @@ function _assert_this_initialized$4(self) {
802
857
  }
803
858
  return self;
804
859
  }
805
- function asyncGeneratorStep$f(gen, resolve, reject, _next, _throw, key, arg) {
860
+ function asyncGeneratorStep$g(gen, resolve, reject, _next, _throw, key, arg) {
806
861
  try {
807
862
  var info = gen[key](arg);
808
863
  var value = info.value;
@@ -816,16 +871,16 @@ function asyncGeneratorStep$f(gen, resolve, reject, _next, _throw, key, arg) {
816
871
  Promise.resolve(value).then(_next, _throw);
817
872
  }
818
873
  }
819
- function _async_to_generator$f(fn) {
874
+ function _async_to_generator$g(fn) {
820
875
  return function() {
821
876
  var self = this, args = arguments;
822
877
  return new Promise(function(resolve, reject) {
823
878
  var gen = fn.apply(self, args);
824
879
  function _next(value) {
825
- asyncGeneratorStep$f(gen, resolve, reject, _next, _throw, "next", value);
880
+ asyncGeneratorStep$g(gen, resolve, reject, _next, _throw, "next", value);
826
881
  }
827
882
  function _throw(err) {
828
- asyncGeneratorStep$f(gen, resolve, reject, _next, _throw, "throw", err);
883
+ asyncGeneratorStep$g(gen, resolve, reject, _next, _throw, "throw", err);
829
884
  }
830
885
  _next(undefined);
831
886
  });
@@ -972,7 +1027,7 @@ function _is_native_reflect_construct$4() {
972
1027
  return !!result;
973
1028
  })();
974
1029
  }
975
- function _ts_generator$f(thisArg, body) {
1030
+ function _ts_generator$g(thisArg, body) {
976
1031
  var f, y, t, _ = {
977
1032
  label: 0,
978
1033
  sent: function() {
@@ -1129,8 +1184,8 @@ function _ts_generator$f(thisArg, body) {
1129
1184
  {
1130
1185
  key: "exists",
1131
1186
  value: function exists() {
1132
- return _async_to_generator$f(function() {
1133
- return _ts_generator$f(this, function(_state) {
1187
+ return _async_to_generator$g(function() {
1188
+ return _ts_generator$g(this, function(_state) {
1134
1189
  return [
1135
1190
  2,
1136
1191
  getAuthUserOrUndefined(this._loadRecord()).then(function(x) {
@@ -1169,9 +1224,9 @@ function _ts_generator$f(thisArg, body) {
1169
1224
  {
1170
1225
  key: "beginResetPassword",
1171
1226
  value: function beginResetPassword() {
1172
- return _async_to_generator$f(function() {
1227
+ return _async_to_generator$g(function() {
1173
1228
  var password, _obj, passwordClaimsData;
1174
- return _ts_generator$f(this, function(_state) {
1229
+ return _ts_generator$g(this, function(_state) {
1175
1230
  switch(_state.label){
1176
1231
  case 0:
1177
1232
  password = this._generateResetPasswordKey();
@@ -1204,9 +1259,9 @@ function _ts_generator$f(thisArg, body) {
1204
1259
  {
1205
1260
  key: "loadResetPasswordClaims",
1206
1261
  value: function loadResetPasswordClaims() {
1207
- return _async_to_generator$f(function() {
1262
+ return _async_to_generator$g(function() {
1208
1263
  var claims, result;
1209
- return _ts_generator$f(this, function(_state) {
1264
+ return _ts_generator$g(this, function(_state) {
1210
1265
  switch(_state.label){
1211
1266
  case 0:
1212
1267
  return [
@@ -1228,9 +1283,9 @@ function _ts_generator$f(thisArg, body) {
1228
1283
  {
1229
1284
  key: "setPassword",
1230
1285
  value: function setPassword(password) {
1231
- return _async_to_generator$f(function() {
1286
+ return _async_to_generator$g(function() {
1232
1287
  var record, _obj;
1233
- return _ts_generator$f(this, function(_state) {
1288
+ return _ts_generator$g(this, function(_state) {
1234
1289
  switch(_state.label){
1235
1290
  case 0:
1236
1291
  return [
@@ -1260,8 +1315,8 @@ function _ts_generator$f(thisArg, body) {
1260
1315
  {
1261
1316
  key: "updateUser",
1262
1317
  value: function updateUser(template) {
1263
- return _async_to_generator$f(function() {
1264
- return _ts_generator$f(this, function(_state) {
1318
+ return _async_to_generator$g(function() {
1319
+ return _ts_generator$g(this, function(_state) {
1265
1320
  return [
1266
1321
  2,
1267
1322
  this.service.auth.updateUser(this.uid, template)
@@ -1273,9 +1328,9 @@ function _ts_generator$f(thisArg, body) {
1273
1328
  {
1274
1329
  key: "loadRoles",
1275
1330
  value: function loadRoles() {
1276
- return _async_to_generator$f(function() {
1331
+ return _async_to_generator$g(function() {
1277
1332
  var claims;
1278
- return _ts_generator$f(this, function(_state) {
1333
+ return _ts_generator$g(this, function(_state) {
1279
1334
  switch(_state.label){
1280
1335
  case 0:
1281
1336
  return [
@@ -1296,9 +1351,9 @@ function _ts_generator$f(thisArg, body) {
1296
1351
  {
1297
1352
  key: "addRoles",
1298
1353
  value: function addRoles(roles) {
1299
- return _async_to_generator$f(function() {
1354
+ return _async_to_generator$g(function() {
1300
1355
  var claims;
1301
- return _ts_generator$f(this, function(_state) {
1356
+ return _ts_generator$g(this, function(_state) {
1302
1357
  claims = this._claimsForRolesChange(roles);
1303
1358
  return [
1304
1359
  2,
@@ -1311,9 +1366,9 @@ function _ts_generator$f(thisArg, body) {
1311
1366
  {
1312
1367
  key: "removeRoles",
1313
1368
  value: function removeRoles(roles) {
1314
- return _async_to_generator$f(function() {
1369
+ return _async_to_generator$g(function() {
1315
1370
  var baseClaims, claims;
1316
- return _ts_generator$f(this, function(_state) {
1371
+ return _ts_generator$g(this, function(_state) {
1317
1372
  baseClaims = this._claimsForRolesChange(roles);
1318
1373
  claims = {};
1319
1374
  forEachKeyValue(baseClaims, {
@@ -1349,9 +1404,9 @@ function _ts_generator$f(thisArg, body) {
1349
1404
  * await userCtx.setRoles([AUTH_ADMIN_ROLE], { customFlag: 1 });
1350
1405
  * ```
1351
1406
  */ function setRoles(roles, claimsToRetain) {
1352
- return _async_to_generator$f(function() {
1407
+ return _async_to_generator$g(function() {
1353
1408
  var claims;
1354
- return _ts_generator$f(this, function(_state) {
1409
+ return _ts_generator$g(this, function(_state) {
1355
1410
  claims = _object_spread$i({}, claimsToRetain, this._claimsForRolesChange(_to_consumable_array$a(roles)));
1356
1411
  return [
1357
1412
  2,
@@ -1385,9 +1440,9 @@ function _ts_generator$f(thisArg, body) {
1385
1440
  {
1386
1441
  key: "updateClaims",
1387
1442
  value: function updateClaims(claims) {
1388
- return _async_to_generator$f(function() {
1443
+ return _async_to_generator$g(function() {
1389
1444
  var currentClaims, newClaims;
1390
- return _ts_generator$f(this, function(_state) {
1445
+ return _ts_generator$g(this, function(_state) {
1391
1446
  switch(_state.label){
1392
1447
  case 0:
1393
1448
  return [
@@ -1572,9 +1627,9 @@ function _ts_generator$f(thisArg, body) {
1572
1627
  {
1573
1628
  key: "initializeNewUser",
1574
1629
  value: function initializeNewUser(input) {
1575
- return _async_to_generator$f(function() {
1630
+ return _async_to_generator$g(function() {
1576
1631
  var uid, email, phone, sendSetupContent, sendSetupContentIfUserExists, sendSetupDetailsOnce, sendSetupIgnoreThrottle, sendSetupThrowErrors, data, sendDetailsInTestEnvironment, userRecordPromise, userRecord, userRecordId, createdUser, createResult, userContext, sentEmail, userContext1;
1577
- return _ts_generator$f(this, function(_state) {
1632
+ return _ts_generator$g(this, function(_state) {
1578
1633
  switch(_state.label){
1579
1634
  case 0:
1580
1635
  uid = input.uid, email = input.email, phone = input.phone, sendSetupContent = input.sendSetupContent, sendSetupContentIfUserExists = input.sendSetupContentIfUserExists, sendSetupDetailsOnce = input.sendSetupDetailsOnce, sendSetupIgnoreThrottle = input.sendSetupIgnoreThrottle, sendSetupThrowErrors = input.sendSetupThrowErrors, data = input.data, sendDetailsInTestEnvironment = input.sendDetailsInTestEnvironment;
@@ -1669,9 +1724,9 @@ function _ts_generator$f(thisArg, body) {
1669
1724
  {
1670
1725
  key: "addNewUserSetupClaims",
1671
1726
  value: function addNewUserSetupClaims(userContextOrUid, setupPassword) {
1672
- return _async_to_generator$f(function() {
1727
+ return _async_to_generator$g(function() {
1673
1728
  var password, userContext;
1674
- return _ts_generator$f(this, function(_state) {
1729
+ return _ts_generator$g(this, function(_state) {
1675
1730
  switch(_state.label){
1676
1731
  case 0:
1677
1732
  password = setupPassword !== null && setupPassword !== void 0 ? setupPassword : this.generateRandomSetupPassword();
@@ -1694,9 +1749,9 @@ function _ts_generator$f(thisArg, body) {
1694
1749
  {
1695
1750
  key: "sendSetupContent",
1696
1751
  value: function sendSetupContent(userContextOrUid, config) {
1697
- return _async_to_generator$f(function() {
1752
+ return _async_to_generator$g(function() {
1698
1753
  var setupDetails, sentContent, setupCommunicationAt, hasSentCommunication, lastSentAt, sendIsThrottled;
1699
- return _ts_generator$f(this, function(_state) {
1754
+ return _ts_generator$g(this, function(_state) {
1700
1755
  switch(_state.label){
1701
1756
  case 0:
1702
1757
  return [
@@ -1777,9 +1832,9 @@ function _ts_generator$f(thisArg, body) {
1777
1832
  {
1778
1833
  key: "loadSetupDetails",
1779
1834
  value: function loadSetupDetails(userContextOrUid, config) {
1780
- return _async_to_generator$f(function() {
1835
+ return _async_to_generator$g(function() {
1781
1836
  var userContext, userExists, details;
1782
- return _ts_generator$f(this, function(_state) {
1837
+ return _ts_generator$g(this, function(_state) {
1783
1838
  switch(_state.label){
1784
1839
  case 0:
1785
1840
  userContext = userContextFromUid(this.authService, userContextOrUid);
@@ -1813,9 +1868,9 @@ function _ts_generator$f(thisArg, body) {
1813
1868
  {
1814
1869
  key: "loadSetupDetailsForUserContext",
1815
1870
  value: function loadSetupDetailsForUserContext(userContext, config) {
1816
- return _async_to_generator$f(function() {
1871
+ return _async_to_generator$g(function() {
1817
1872
  var details, _ref, setupPassword, setupCommunicationAt;
1818
- return _ts_generator$f(this, function(_state) {
1873
+ return _ts_generator$g(this, function(_state) {
1819
1874
  switch(_state.label){
1820
1875
  case 0:
1821
1876
  return [
@@ -1851,9 +1906,9 @@ function _ts_generator$f(thisArg, body) {
1851
1906
  *
1852
1907
  * @param details - The user's setup details containing the user context.
1853
1908
  */ function updateSetupContentSentTime(details) {
1854
- return _async_to_generator$f(function() {
1909
+ return _async_to_generator$g(function() {
1855
1910
  var setupCommunicationAt;
1856
- return _ts_generator$f(this, function(_state) {
1911
+ return _ts_generator$g(this, function(_state) {
1857
1912
  switch(_state.label){
1858
1913
  case 0:
1859
1914
  setupCommunicationAt = toISODateString(new Date());
@@ -1876,9 +1931,9 @@ function _ts_generator$f(thisArg, body) {
1876
1931
  {
1877
1932
  key: "markUserSetupAsComplete",
1878
1933
  value: function markUserSetupAsComplete(uid) {
1879
- return _async_to_generator$f(function() {
1934
+ return _async_to_generator$g(function() {
1880
1935
  var userContext, userExists;
1881
- return _ts_generator$f(this, function(_state) {
1936
+ return _ts_generator$g(this, function(_state) {
1882
1937
  switch(_state.label){
1883
1938
  case 0:
1884
1939
  userContext = this.authService.userContext(uid);
@@ -1920,9 +1975,9 @@ function _ts_generator$f(thisArg, body) {
1920
1975
  * @returns The created user record and the setup password used.
1921
1976
  * @throws Throws if the Firebase Admin SDK rejects the user creation.
1922
1977
  */ function createNewUser(input) {
1923
- return _async_to_generator$f(function() {
1978
+ return _async_to_generator$g(function() {
1924
1979
  var uid, displayName, email, phoneNumber, inputPassword, password, user, e, firebaseError, errorCode;
1925
- return _ts_generator$f(this, function(_state) {
1980
+ return _ts_generator$g(this, function(_state) {
1926
1981
  switch(_state.label){
1927
1982
  case 0:
1928
1983
  uid = input.uid, displayName = input.displayName, email = input.email, phoneNumber = input.phone, inputPassword = input.setupPassword;
@@ -1989,9 +2044,9 @@ function _ts_generator$f(thisArg, body) {
1989
2044
  *
1990
2045
  * @param userContext - The user context to clear setup claims from.
1991
2046
  */ function updateClaimsToClearUser(userContext) {
1992
- return _async_to_generator$f(function() {
2047
+ return _async_to_generator$g(function() {
1993
2048
  var _obj;
1994
- return _ts_generator$f(this, function(_state) {
2049
+ return _ts_generator$g(this, function(_state) {
1995
2050
  switch(_state.label){
1996
2051
  case 0:
1997
2052
  return [
@@ -2025,8 +2080,8 @@ function _ts_generator$f(thisArg, body) {
2025
2080
  {
2026
2081
  key: "sendSetupContentToUser",
2027
2082
  value: function sendSetupContentToUser(_details) {
2028
- return _async_to_generator$f(function() {
2029
- return _ts_generator$f(this, function(_state) {
2083
+ return _async_to_generator$g(function() {
2084
+ return _ts_generator$g(this, function(_state) {
2030
2085
  return [
2031
2086
  2
2032
2087
  ];
@@ -2039,111 +2094,460 @@ function _ts_generator$f(thisArg, body) {
2039
2094
  return NoSetupContentFirebaseServerNewUserService;
2040
2095
  }(AbstractFirebaseServerNewUserService);
2041
2096
  /**
2042
- * Abstract contract for a Firebase Server authentication service.
2043
- *
2044
- * Provides the core API for creating auth contexts from callable requests, managing user contexts,
2045
- * checking admin/ToS status, converting between roles and claims, and creating new users.
2046
- *
2047
- * Implement this by extending {@link AbstractFirebaseServerAuthService}, which provides default
2048
- * implementations for most methods and only requires `readRoles`, `claimsForRoles`,
2049
- * `userContext`, and `_context` to be defined.
2097
+ * Default throttle duration (1 hour) between reset content sends to prevent spam.
2050
2098
  *
2051
- * @example
2052
- * ```typescript
2053
- * class MyAuthService extends AbstractFirebaseServerAuthService<MyUserContext, MyAuthContext> {
2054
- * readRoles(claims: AuthClaims): AuthRoleSet { ... }
2055
- * claimsForRoles(roles: AuthRoleSet): AuthClaimsUpdate { ... }
2056
- * userContext(uid: string): MyUserContext { ... }
2057
- * protected _context(ctx: CallableContextWithAuthData): MyAuthContext { ... }
2058
- * }
2059
- * ```
2060
- */ var FirebaseServerAuthService = function FirebaseServerAuthService() {
2061
- _class_call_check$q(this, FirebaseServerAuthService);
2062
- };
2099
+ * Used by {@link AbstractFirebaseServerUserPasswordResetService.sendResetContent} to rate-limit delivery.
2100
+ */ var DEFAULT_RESET_COM_THROTTLE_TIME = hoursToMs(1);
2063
2101
  /**
2064
- * Base implementation of {@link FirebaseServerAuthService} providing standard admin/ToS checks,
2065
- * auth context creation with assertion, and a default no-op new user service.
2102
+ * Base implementation of {@link FirebaseServerUserPasswordResetService} that handles reset initiation,
2103
+ * claims management, throttled reset content delivery, and reset completion.
2066
2104
  *
2067
- * Subclasses must implement:
2068
- * - {@link _context} - to create the concrete auth context type.
2069
- * - {@link userContext} - to create the concrete user context type.
2070
- * - {@link readRoles} - to define the claims-to-roles mapping.
2071
- * - {@link claimsForRoles} - to define the roles-to-claims mapping.
2105
+ * Subclasses must implement {@link sendPasswordResetContentToUser} to define how reset content
2106
+ * (e.g., reset email, SMS) is delivered to the user.
2072
2107
  *
2073
2108
  * @example
2074
2109
  * ```typescript
2075
- * export class MyAuthService extends AbstractFirebaseServerAuthService<MyUserContext, MyAuthContext> {
2076
- * protected _context(context: CallableContextWithAuthData): MyAuthContext {
2077
- * return new MyAuthContext(this, context);
2078
- * }
2079
- * userContext(uid: string): MyUserContext {
2080
- * return new MyUserContext(this, uid);
2081
- * }
2082
- * readRoles(claims: AuthClaims): AuthRoleSet {
2083
- * return MY_CLAIMS_SERVICE.toRoles(claims);
2084
- * }
2085
- * claimsForRoles(roles: AuthRoleSet): AuthClaimsUpdate {
2086
- * return MY_CLAIMS_SERVICE.toClaims(roles);
2110
+ * export class MyPasswordResetService extends AbstractFirebaseServerUserPasswordResetService<MyUserContext> {
2111
+ * protected async sendPasswordResetContentToUser(details: FirebaseServerAuthPasswordResetDetails<MyUserContext>): Promise<void> {
2112
+ * await this.emailService.sendResetEmail(details.userContext.uid, details.claims.resetPassword);
2087
2113
  * }
2088
2114
  * }
2089
2115
  * ```
2090
- */ var AbstractFirebaseServerAuthService = /*#__PURE__*/ function() {
2091
- function AbstractFirebaseServerAuthService(auth) {
2092
- _class_call_check$q(this, AbstractFirebaseServerAuthService);
2093
- _define_property$x(this, "_auth", void 0);
2094
- this._auth = auth;
2116
+ */ var AbstractFirebaseServerUserPasswordResetService = /*#__PURE__*/ function() {
2117
+ function AbstractFirebaseServerUserPasswordResetService(authService) {
2118
+ _class_call_check$q(this, AbstractFirebaseServerUserPasswordResetService);
2119
+ _define_property$x(this, "_authService", void 0);
2120
+ /**
2121
+ * Minimum time between reset content sends. Defaults to {@link DEFAULT_RESET_COM_THROTTLE_TIME} (1 hour).
2122
+ * Override in subclasses to customize the throttle window.
2123
+ */ _define_property$x(this, "resetThrottleTime", DEFAULT_RESET_COM_THROTTLE_TIME);
2124
+ this._authService = authService;
2095
2125
  }
2096
- _create_class$g(AbstractFirebaseServerAuthService, [
2126
+ _create_class$g(AbstractFirebaseServerUserPasswordResetService, [
2097
2127
  {
2098
- key: "auth",
2128
+ key: "authService",
2099
2129
  get: function get() {
2100
- return this._auth;
2101
- }
2102
- },
2103
- {
2104
- key: "context",
2105
- value: function context(context) {
2106
- assertIsContextWithAuthData(context);
2107
- return this._context(context);
2108
- }
2109
- },
2110
- {
2111
- key: "isAdmin",
2112
- value: function isAdmin(claims) {
2113
- return this.isAdminInRoles(this.readRoles(claims));
2114
- }
2115
- },
2116
- {
2117
- key: "isAdminInRoles",
2118
- value: function isAdminInRoles(roles) {
2119
- return roles.has(AUTH_ADMIN_ROLE);
2130
+ return this._authService;
2120
2131
  }
2121
2132
  },
2122
2133
  {
2123
- key: "hasSignedTos",
2124
- value: function hasSignedTos(claims) {
2125
- return this.hasSignedTosInRoles(this.readRoles(claims));
2134
+ key: "beginPasswordReset",
2135
+ value: function beginPasswordReset(input) {
2136
+ return _async_to_generator$g(function() {
2137
+ var uid, email, sendResetContent, sendResetDetailsOnce, sendResetIgnoreThrottle, sendResetThrowErrors, data, sendDetailsInTestEnvironment, resolvedUid, userRecord, userContext, claims;
2138
+ return _ts_generator$g(this, function(_state) {
2139
+ switch(_state.label){
2140
+ case 0:
2141
+ uid = input.uid, email = input.email, sendResetContent = input.sendResetContent, sendResetDetailsOnce = input.sendResetDetailsOnce, sendResetIgnoreThrottle = input.sendResetIgnoreThrottle, sendResetThrowErrors = input.sendResetThrowErrors, data = input.data, sendDetailsInTestEnvironment = input.sendDetailsInTestEnvironment;
2142
+ if (!uid) return [
2143
+ 3,
2144
+ 1
2145
+ ];
2146
+ resolvedUid = uid;
2147
+ return [
2148
+ 3,
2149
+ 4
2150
+ ];
2151
+ case 1:
2152
+ if (!email) return [
2153
+ 3,
2154
+ 3
2155
+ ];
2156
+ return [
2157
+ 4,
2158
+ this.authService.auth.getUserByEmail(email)
2159
+ ];
2160
+ case 2:
2161
+ userRecord = _state.sent();
2162
+ resolvedUid = userRecord.uid;
2163
+ return [
2164
+ 3,
2165
+ 4
2166
+ ];
2167
+ case 3:
2168
+ throw new Error('uid or email is required to initiate a password reset.');
2169
+ case 4:
2170
+ userContext = this.authService.userContext(resolvedUid);
2171
+ return [
2172
+ 4,
2173
+ userContext.beginResetPassword()
2174
+ ];
2175
+ case 5:
2176
+ claims = _state.sent();
2177
+ if (!sendResetContent) return [
2178
+ 3,
2179
+ 7
2180
+ ];
2181
+ return [
2182
+ 4,
2183
+ this.sendResetContent(resolvedUid, {
2184
+ data: data,
2185
+ sendResetDetailsOnce: sendResetDetailsOnce,
2186
+ ignoreSendThrottleTime: sendResetIgnoreThrottle,
2187
+ throwErrors: sendResetThrowErrors,
2188
+ sendDetailsInTestEnvironment: sendDetailsInTestEnvironment
2189
+ })
2190
+ ];
2191
+ case 6:
2192
+ _state.sent();
2193
+ _state.label = 7;
2194
+ case 7:
2195
+ return [
2196
+ 2,
2197
+ claims
2198
+ ];
2199
+ }
2200
+ });
2201
+ }).call(this);
2126
2202
  }
2127
2203
  },
2128
2204
  {
2129
- key: "hasSignedTosInRoles",
2130
- value: function hasSignedTosInRoles(roles) {
2131
- return roles.has(AUTH_TOS_SIGNED_ROLE);
2205
+ key: "sendResetContent",
2206
+ value: function sendResetContent(uid, config) {
2207
+ return _async_to_generator$g(function() {
2208
+ var resetDetails, sentContent, resetCommunicationAt, hasSentCommunication, lastSentAt, sendIsThrottled;
2209
+ return _ts_generator$g(this, function(_state) {
2210
+ switch(_state.label){
2211
+ case 0:
2212
+ return [
2213
+ 4,
2214
+ this.loadResetDetails(uid, config)
2215
+ ];
2216
+ case 1:
2217
+ resetDetails = _state.sent();
2218
+ sentContent = false;
2219
+ if (!resetDetails) return [
2220
+ 3,
2221
+ 7
2222
+ ];
2223
+ resetCommunicationAt = resetDetails.claims.resetCommunicationAt;
2224
+ hasSentCommunication = Boolean(resetCommunicationAt);
2225
+ if (!((config === null || config === void 0 ? void 0 : config.sendResetDetailsOnce) && hasSentCommunication)) return [
2226
+ 3,
2227
+ 2
2228
+ ];
2229
+ if (config.throwErrors) {
2230
+ throw new FirebaseServerAuthPasswordResetSendOnceError();
2231
+ }
2232
+ return [
2233
+ 3,
2234
+ 6
2235
+ ];
2236
+ case 2:
2237
+ lastSentAt = resetCommunicationAt ? new Date(resetCommunicationAt) : undefined;
2238
+ sendIsThrottled = hasSentCommunication && !(config === null || config === void 0 ? void 0 : config.ignoreSendThrottleTime) && isThrottled(this.resetThrottleTime, lastSentAt);
2239
+ if (!!sendIsThrottled) return [
2240
+ 3,
2241
+ 5
2242
+ ];
2243
+ return [
2244
+ 4,
2245
+ this.sendPasswordResetContentToUser(resetDetails)
2246
+ ];
2247
+ case 3:
2248
+ _state.sent();
2249
+ return [
2250
+ 4,
2251
+ this.updateResetContentSentTime(resetDetails)
2252
+ ];
2253
+ case 4:
2254
+ _state.sent();
2255
+ sentContent = true;
2256
+ return [
2257
+ 3,
2258
+ 6
2259
+ ];
2260
+ case 5:
2261
+ if (config === null || config === void 0 ? void 0 : config.throwErrors) {
2262
+ throw new FirebaseServerAuthPasswordResetThrottleError(lastSentAt);
2263
+ }
2264
+ _state.label = 6;
2265
+ case 6:
2266
+ return [
2267
+ 3,
2268
+ 8
2269
+ ];
2270
+ case 7:
2271
+ if (config === null || config === void 0 ? void 0 : config.throwErrors) {
2272
+ throw new FirebaseServerAuthPasswordResetNoResetConfigError();
2273
+ }
2274
+ _state.label = 8;
2275
+ case 8:
2276
+ return [
2277
+ 2,
2278
+ sentContent
2279
+ ];
2280
+ }
2281
+ });
2282
+ }).call(this);
2132
2283
  }
2133
2284
  },
2134
2285
  {
2135
- key: "newUser",
2136
- value: function newUser() {
2137
- return new NoSetupContentFirebaseServerNewUserService(this);
2286
+ key: "loadResetDetails",
2287
+ value: function loadResetDetails(uid, config) {
2288
+ return _async_to_generator$g(function() {
2289
+ var userContext, userExists, details;
2290
+ return _ts_generator$g(this, function(_state) {
2291
+ switch(_state.label){
2292
+ case 0:
2293
+ userContext = this.authService.userContext(uid);
2294
+ return [
2295
+ 4,
2296
+ userContext.exists()
2297
+ ];
2298
+ case 1:
2299
+ userExists = _state.sent();
2300
+ if (!userExists) return [
2301
+ 3,
2302
+ 3
2303
+ ];
2304
+ return [
2305
+ 4,
2306
+ this.loadResetDetailsForUserContext(userContext, config)
2307
+ ];
2308
+ case 2:
2309
+ details = _state.sent();
2310
+ _state.label = 3;
2311
+ case 3:
2312
+ return [
2313
+ 2,
2314
+ details
2315
+ ];
2316
+ }
2317
+ });
2318
+ }).call(this);
2138
2319
  }
2139
2320
  },
2140
2321
  {
2141
- key: "authContextInfo",
2142
- value: function authContextInfo(context) {
2143
- var _this = this;
2144
- var auth = context.auth;
2145
- var result;
2146
- if (auth) {
2322
+ key: "loadResetDetailsForUserContext",
2323
+ value: function loadResetDetailsForUserContext(userContext, config) {
2324
+ return _async_to_generator$g(function() {
2325
+ var details, claims;
2326
+ return _ts_generator$g(this, function(_state) {
2327
+ switch(_state.label){
2328
+ case 0:
2329
+ return [
2330
+ 4,
2331
+ userContext.loadResetPasswordClaims()
2332
+ ];
2333
+ case 1:
2334
+ claims = _state.sent();
2335
+ if (claims) {
2336
+ details = {
2337
+ userContext: userContext,
2338
+ claims: {
2339
+ resetPassword: claims.resetPassword,
2340
+ resetCommunicationAt: claims.resetCommunicationAt
2341
+ },
2342
+ data: config === null || config === void 0 ? void 0 : config.data,
2343
+ sendDetailsInTestEnvironment: config === null || config === void 0 ? void 0 : config.sendDetailsInTestEnvironment
2344
+ };
2345
+ }
2346
+ return [
2347
+ 2,
2348
+ details
2349
+ ];
2350
+ }
2351
+ });
2352
+ })();
2353
+ }
2354
+ },
2355
+ {
2356
+ key: "updateResetContentSentTime",
2357
+ value: /**
2358
+ * Records the current timestamp as the last reset content communication date in the user's claims.
2359
+ *
2360
+ * @param details - The user's reset details containing the user context.
2361
+ */ function updateResetContentSentTime(details) {
2362
+ return _async_to_generator$g(function() {
2363
+ var resetCommunicationAt;
2364
+ return _ts_generator$g(this, function(_state) {
2365
+ switch(_state.label){
2366
+ case 0:
2367
+ resetCommunicationAt = toISODateString(new Date());
2368
+ return [
2369
+ 4,
2370
+ details.userContext.updateClaims(_define_property$x({}, FIREBASE_SERVER_AUTH_CLAIMS_RESET_LAST_COM_DATE_KEY, resetCommunicationAt))
2371
+ ];
2372
+ case 1:
2373
+ _state.sent();
2374
+ return [
2375
+ 2
2376
+ ];
2377
+ }
2378
+ });
2379
+ })();
2380
+ }
2381
+ },
2382
+ {
2383
+ key: "completePasswordReset",
2384
+ value: function completePasswordReset(uid, input) {
2385
+ return _async_to_generator$g(function() {
2386
+ var userContext, claims;
2387
+ return _ts_generator$g(this, function(_state) {
2388
+ switch(_state.label){
2389
+ case 0:
2390
+ userContext = this.authService.userContext(uid);
2391
+ return [
2392
+ 4,
2393
+ userContext.loadResetPasswordClaims()
2394
+ ];
2395
+ case 1:
2396
+ claims = _state.sent();
2397
+ if ((claims === null || claims === void 0 ? void 0 : claims.resetPassword) !== input.resetPassword) {
2398
+ throw new FirebaseServerAuthPasswordResetInvalidCodeError();
2399
+ }
2400
+ return [
2401
+ 2,
2402
+ userContext.setPassword(input.newPassword)
2403
+ ];
2404
+ }
2405
+ });
2406
+ }).call(this);
2407
+ }
2408
+ }
2409
+ ]);
2410
+ return AbstractFirebaseServerUserPasswordResetService;
2411
+ }();
2412
+ /**
2413
+ * No-op implementation of {@link AbstractFirebaseServerUserPasswordResetService} that skips sending reset content.
2414
+ *
2415
+ * Used as the default {@link FirebaseServerUserPasswordResetService} when no custom delivery mechanism is configured.
2416
+ */ var NoContentFirebaseServerUserPasswordResetService = /*#__PURE__*/ function(AbstractFirebaseServerUserPasswordResetService) {
2417
+ _inherits$4(NoContentFirebaseServerUserPasswordResetService, AbstractFirebaseServerUserPasswordResetService);
2418
+ function NoContentFirebaseServerUserPasswordResetService() {
2419
+ _class_call_check$q(this, NoContentFirebaseServerUserPasswordResetService);
2420
+ return _call_super$4(this, NoContentFirebaseServerUserPasswordResetService, arguments);
2421
+ }
2422
+ _create_class$g(NoContentFirebaseServerUserPasswordResetService, [
2423
+ {
2424
+ key: "sendPasswordResetContentToUser",
2425
+ value: function sendPasswordResetContentToUser(_details) {
2426
+ return _async_to_generator$g(function() {
2427
+ return _ts_generator$g(this, function(_state) {
2428
+ return [
2429
+ 2
2430
+ ];
2431
+ });
2432
+ // send nothing.
2433
+ })();
2434
+ }
2435
+ }
2436
+ ]);
2437
+ return NoContentFirebaseServerUserPasswordResetService;
2438
+ }(AbstractFirebaseServerUserPasswordResetService);
2439
+ /**
2440
+ * Abstract contract for a Firebase Server authentication service.
2441
+ *
2442
+ * Provides the core API for creating auth contexts from callable requests, managing user contexts,
2443
+ * checking admin/ToS status, converting between roles and claims, and creating new users.
2444
+ *
2445
+ * Implement this by extending {@link AbstractFirebaseServerAuthService}, which provides default
2446
+ * implementations for most methods and only requires `readRoles`, `claimsForRoles`,
2447
+ * `userContext`, and `_context` to be defined.
2448
+ *
2449
+ * @example
2450
+ * ```typescript
2451
+ * class MyAuthService extends AbstractFirebaseServerAuthService<MyUserContext, MyAuthContext> {
2452
+ * readRoles(claims: AuthClaims): AuthRoleSet { ... }
2453
+ * claimsForRoles(roles: AuthRoleSet): AuthClaimsUpdate { ... }
2454
+ * userContext(uid: string): MyUserContext { ... }
2455
+ * protected _context(ctx: CallableContextWithAuthData): MyAuthContext { ... }
2456
+ * }
2457
+ * ```
2458
+ */ var FirebaseServerAuthService = function FirebaseServerAuthService() {
2459
+ _class_call_check$q(this, FirebaseServerAuthService);
2460
+ };
2461
+ /**
2462
+ * Base implementation of {@link FirebaseServerAuthService} providing standard admin/ToS checks,
2463
+ * auth context creation with assertion, and a default no-op new user service.
2464
+ *
2465
+ * Subclasses must implement:
2466
+ * - {@link _context} - to create the concrete auth context type.
2467
+ * - {@link userContext} - to create the concrete user context type.
2468
+ * - {@link readRoles} - to define the claims-to-roles mapping.
2469
+ * - {@link claimsForRoles} - to define the roles-to-claims mapping.
2470
+ *
2471
+ * @example
2472
+ * ```typescript
2473
+ * export class MyAuthService extends AbstractFirebaseServerAuthService<MyUserContext, MyAuthContext> {
2474
+ * protected _context(context: CallableContextWithAuthData): MyAuthContext {
2475
+ * return new MyAuthContext(this, context);
2476
+ * }
2477
+ * userContext(uid: string): MyUserContext {
2478
+ * return new MyUserContext(this, uid);
2479
+ * }
2480
+ * readRoles(claims: AuthClaims): AuthRoleSet {
2481
+ * return MY_CLAIMS_SERVICE.toRoles(claims);
2482
+ * }
2483
+ * claimsForRoles(roles: AuthRoleSet): AuthClaimsUpdate {
2484
+ * return MY_CLAIMS_SERVICE.toClaims(roles);
2485
+ * }
2486
+ * }
2487
+ * ```
2488
+ */ var AbstractFirebaseServerAuthService = /*#__PURE__*/ function() {
2489
+ function AbstractFirebaseServerAuthService(auth) {
2490
+ _class_call_check$q(this, AbstractFirebaseServerAuthService);
2491
+ _define_property$x(this, "_auth", void 0);
2492
+ this._auth = auth;
2493
+ }
2494
+ _create_class$g(AbstractFirebaseServerAuthService, [
2495
+ {
2496
+ key: "auth",
2497
+ get: function get() {
2498
+ return this._auth;
2499
+ }
2500
+ },
2501
+ {
2502
+ key: "context",
2503
+ value: function context(context) {
2504
+ assertIsContextWithAuthData(context);
2505
+ return this._context(context);
2506
+ }
2507
+ },
2508
+ {
2509
+ key: "isAdmin",
2510
+ value: function isAdmin(claims) {
2511
+ return this.isAdminInRoles(this.readRoles(claims));
2512
+ }
2513
+ },
2514
+ {
2515
+ key: "isAdminInRoles",
2516
+ value: function isAdminInRoles(roles) {
2517
+ return roles.has(AUTH_ADMIN_ROLE);
2518
+ }
2519
+ },
2520
+ {
2521
+ key: "hasSignedTos",
2522
+ value: function hasSignedTos(claims) {
2523
+ return this.hasSignedTosInRoles(this.readRoles(claims));
2524
+ }
2525
+ },
2526
+ {
2527
+ key: "hasSignedTosInRoles",
2528
+ value: function hasSignedTosInRoles(roles) {
2529
+ return roles.has(AUTH_TOS_SIGNED_ROLE);
2530
+ }
2531
+ },
2532
+ {
2533
+ key: "newUser",
2534
+ value: function newUser() {
2535
+ return new NoSetupContentFirebaseServerNewUserService(this);
2536
+ }
2537
+ },
2538
+ {
2539
+ key: "passwordReset",
2540
+ value: function passwordReset() {
2541
+ return new NoContentFirebaseServerUserPasswordResetService(this);
2542
+ }
2543
+ },
2544
+ {
2545
+ key: "authContextInfo",
2546
+ value: function authContextInfo(context) {
2547
+ var _this = this;
2548
+ var auth = context.auth;
2549
+ var result;
2550
+ if (auth) {
2147
2551
  var _roles = cachedGetter(function() {
2148
2552
  return _this.readRoles(auth.token);
2149
2553
  });
@@ -2185,781 +2589,333 @@ function _ts_generator$f(thisArg, body) {
2185
2589
  }
2186
2590
  ();
2187
2591
 
2188
- // MARK: Tokens
2189
- /**
2190
- * Token to access a configured FirebaseServerEnvironmentServiceConfig for the app.
2191
- */ var FIREBASE_SERVER_ENV_TOKEN = 'FIREBASE_SERVER_ENV_TOKEN';
2192
- /**
2193
- * Creates a NestJS provider that binds the given config to the {@link FIREBASE_SERVER_ENV_TOKEN} injection token.
2194
- *
2195
- * @param env - The Firebase server environment configuration.
2196
- * @returns A NestJS provider binding the config to the {@link FIREBASE_SERVER_ENV_TOKEN} token.
2197
- *
2198
- * @example
2199
- * ```typescript
2200
- * const provider = firebaseServerEnvTokenProvider({ appUrl: 'https://myapp.com', ... });
2201
- * ```
2202
- */ function firebaseServerEnvTokenProvider(env) {
2203
- return {
2204
- provide: FIREBASE_SERVER_ENV_TOKEN,
2205
- useValue: env
2206
- };
2207
- }
2208
- /**
2209
- * Creates NestJS providers that bind the given config to both {@link FIREBASE_SERVER_ENV_TOKEN}
2210
- * and the base {@link SERVER_ENV_TOKEN} from `@dereekb/nestjs`.
2211
- *
2212
- * Use this when the NestJS app needs the config accessible via either token.
2213
- *
2214
- * @param env - The Firebase server environment configuration.
2215
- * @returns An array of providers binding the config to both Firebase and base server env tokens.
2216
- *
2217
- * @example
2218
- * ```typescript
2219
- * @Module({
2220
- * providers: [...firebaseServerEnvTokenProviders(myEnvConfig)]
2221
- * })
2222
- * export class AppModule {}
2223
- * ```
2224
- */ function firebaseServerEnvTokenProviders(env) {
2225
- return [
2226
- firebaseServerEnvTokenProvider(env),
2227
- {
2228
- provide: SERVER_ENV_TOKEN,
2229
- useExisting: FIREBASE_SERVER_ENV_TOKEN
2230
- }
2231
- ];
2232
- }
2233
-
2234
- function _class_call_check$p(instance, Constructor) {
2235
- if (!(instance instanceof Constructor)) {
2236
- throw new TypeError("Cannot call a class as a function");
2592
+ function asyncGeneratorStep$f(gen, resolve, reject, _next, _throw, key, arg) {
2593
+ try {
2594
+ var info = gen[key](arg);
2595
+ var value = info.value;
2596
+ } catch (error) {
2597
+ reject(error);
2598
+ return;
2599
+ }
2600
+ if (info.done) {
2601
+ resolve(value);
2602
+ } else {
2603
+ Promise.resolve(value).then(_next, _throw);
2237
2604
  }
2238
2605
  }
2239
- /**
2240
- * Abstract service providing Firebase server environment information such as deployment stage,
2241
- * feature flags, and app URL.
2242
- *
2243
- * Implementations are typically injected via {@link FIREBASE_SERVER_ENV_TOKEN} and
2244
- * backed by a {@link FirebaseServerEnvironmentConfig}.
2245
- */ var FirebaseServerEnvService = function FirebaseServerEnvService() {
2246
- _class_call_check$p(this, FirebaseServerEnvService);
2247
- }
2248
- ;
2249
-
2250
- /**
2251
- * Converts a {@link FirestoreAccessorIncrementUpdate} into Firestore {@link UpdateData} using
2252
- * Google Cloud Firestore's {@link FieldValue.increment}.
2253
- *
2254
- * Each field in the input maps to an atomic increment operation. Null/undefined values default to 0.
2255
- *
2256
- * @param input - The increment specification mapping field names to numeric deltas.
2257
- * @returns Firestore {@link UpdateData} with atomic increment operations.
2258
- *
2259
- * @example
2260
- * ```typescript
2261
- * const updateData = firestoreServerIncrementUpdateToUpdateData<Stats>({
2262
- * viewCount: 1,
2263
- * likeCount: -1
2264
- * });
2265
- * ```
2266
- */ function firestoreServerIncrementUpdateToUpdateData(input) {
2267
- return mapObjectMap(input, function(incrementValue) {
2268
- return FieldValue.increment(incrementValue !== null && incrementValue !== void 0 ? incrementValue : 0);
2269
- });
2270
- }
2271
-
2272
- function _array_like_to_array$d(arr, len) {
2273
- if (len == null || len > arr.length) len = arr.length;
2274
- for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
2275
- return arr2;
2276
- }
2277
- function _array_without_holes$9(arr) {
2278
- if (Array.isArray(arr)) return _array_like_to_array$d(arr);
2279
- }
2280
- function _define_property$w(obj, key, value) {
2281
- if (key in obj) {
2282
- Object.defineProperty(obj, key, {
2283
- value: value,
2284
- enumerable: true,
2285
- configurable: true,
2286
- writable: true
2606
+ function _async_to_generator$f(fn) {
2607
+ return function() {
2608
+ var self = this, args = arguments;
2609
+ return new Promise(function(resolve, reject) {
2610
+ var gen = fn.apply(self, args);
2611
+ function _next(value) {
2612
+ asyncGeneratorStep$f(gen, resolve, reject, _next, _throw, "next", value);
2613
+ }
2614
+ function _throw(err) {
2615
+ asyncGeneratorStep$f(gen, resolve, reject, _next, _throw, "throw", err);
2616
+ }
2617
+ _next(undefined);
2287
2618
  });
2288
- } else {
2289
- obj[key] = value;
2290
- }
2291
- return obj;
2292
- }
2293
- function _iterable_to_array$9(iter) {
2294
- if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
2295
- }
2296
- function _non_iterable_spread$9() {
2297
- throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
2619
+ };
2298
2620
  }
2299
- function _object_spread$h(target) {
2300
- for(var i = 1; i < arguments.length; i++){
2301
- var source = arguments[i] != null ? arguments[i] : {};
2302
- var ownKeys = Object.keys(source);
2303
- if (typeof Object.getOwnPropertySymbols === "function") {
2304
- ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
2305
- return Object.getOwnPropertyDescriptor(source, sym).enumerable;
2306
- }));
2621
+ function _ts_generator$f(thisArg, body) {
2622
+ var f, y, t, _ = {
2623
+ label: 0,
2624
+ sent: function() {
2625
+ if (t[0] & 1) throw t[1];
2626
+ return t[1];
2627
+ },
2628
+ trys: [],
2629
+ ops: []
2630
+ }, g = Object.create((typeof Iterator === "function" ? Iterator : Object).prototype), d = Object.defineProperty;
2631
+ return d(g, "next", {
2632
+ value: verb(0)
2633
+ }), d(g, "throw", {
2634
+ value: verb(1)
2635
+ }), d(g, "return", {
2636
+ value: verb(2)
2637
+ }), typeof Symbol === "function" && d(g, Symbol.iterator, {
2638
+ value: function() {
2639
+ return this;
2307
2640
  }
2308
- ownKeys.forEach(function(key) {
2309
- _define_property$w(target, key, source[key]);
2310
- });
2641
+ }), g;
2642
+ function verb(n) {
2643
+ return function(v) {
2644
+ return step([
2645
+ n,
2646
+ v
2647
+ ]);
2648
+ };
2649
+ }
2650
+ function step(op) {
2651
+ if (f) throw new TypeError("Generator is already executing.");
2652
+ while(g && (g = 0, op[0] && (_ = 0)), _)try {
2653
+ if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
2654
+ if (y = 0, t) op = [
2655
+ op[0] & 2,
2656
+ t.value
2657
+ ];
2658
+ switch(op[0]){
2659
+ case 0:
2660
+ case 1:
2661
+ t = op;
2662
+ break;
2663
+ case 4:
2664
+ _.label++;
2665
+ return {
2666
+ value: op[1],
2667
+ done: false
2668
+ };
2669
+ case 5:
2670
+ _.label++;
2671
+ y = op[1];
2672
+ op = [
2673
+ 0
2674
+ ];
2675
+ continue;
2676
+ case 7:
2677
+ op = _.ops.pop();
2678
+ _.trys.pop();
2679
+ continue;
2680
+ default:
2681
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) {
2682
+ _ = 0;
2683
+ continue;
2684
+ }
2685
+ if (op[0] === 3 && (!t || op[1] > t[0] && op[1] < t[3])) {
2686
+ _.label = op[1];
2687
+ break;
2688
+ }
2689
+ if (op[0] === 6 && _.label < t[1]) {
2690
+ _.label = t[1];
2691
+ t = op;
2692
+ break;
2693
+ }
2694
+ if (t && _.label < t[2]) {
2695
+ _.label = t[2];
2696
+ _.ops.push(op);
2697
+ break;
2698
+ }
2699
+ if (t[2]) _.ops.pop();
2700
+ _.trys.pop();
2701
+ continue;
2702
+ }
2703
+ op = body.call(thisArg, _);
2704
+ } catch (e) {
2705
+ op = [
2706
+ 6,
2707
+ e
2708
+ ];
2709
+ y = 0;
2710
+ } finally{
2711
+ f = t = 0;
2712
+ }
2713
+ if (op[0] & 5) throw op[1];
2714
+ return {
2715
+ value: op[0] ? op[1] : void 0,
2716
+ done: true
2717
+ };
2311
2718
  }
2312
- return target;
2313
- }
2314
- function _to_consumable_array$9(arr) {
2315
- return _array_without_holes$9(arr) || _iterable_to_array$9(arr) || _unsupported_iterable_to_array$d(arr) || _non_iterable_spread$9();
2316
- }
2317
- function _unsupported_iterable_to_array$d(o, minLen) {
2318
- if (!o) return;
2319
- if (typeof o === "string") return _array_like_to_array$d(o, minLen);
2320
- var n = Object.prototype.toString.call(o).slice(8, -1);
2321
- if (n === "Object" && o.constructor) n = o.constructor.name;
2322
- if (n === "Map" || n === "Set") return Array.from(n);
2323
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$d(o, minLen);
2324
2719
  }
2325
2720
  /**
2326
- * Converts a {@link FirestoreAccessorArrayUpdate} into Firestore {@link UpdateData} using
2327
- * Google Cloud Firestore's {@link FieldValue.arrayUnion} and {@link FieldValue.arrayRemove}.
2721
+ * Asserts that the callable context contains auth data with a valid UID.
2328
2722
  *
2329
- * @param input - The array update specification with `union` and/or `remove` field maps.
2330
- * @returns Firestore {@link UpdateData} with array union/remove operations.
2723
+ * @param context - The callable context to check for auth data.
2724
+ * @throws {HttpsError} Throws unauthenticated error if no auth data is present.
2331
2725
  *
2332
2726
  * @example
2333
2727
  * ```typescript
2334
- * const updateData = firestoreServerArrayUpdateToUpdateData<User>({
2335
- * union: { tags: ['new-tag'] },
2336
- * remove: { tags: ['old-tag'] }
2337
- * });
2728
+ * assertContextHasAuth(context);
2729
+ * // Safe to access context.auth.uid
2338
2730
  * ```
2339
- */ function firestoreServerArrayUpdateToUpdateData(input) {
2340
- var union = input.union;
2341
- var remove = input.remove;
2342
- function createUpdatesWithArrayFunction(fieldUpdate, arrayUpdateFunction) {
2343
- var result;
2344
- if (fieldUpdate) {
2345
- result = mapObjectMap(fieldUpdate, function(arrayUpdate) {
2346
- var result;
2347
- if (arrayUpdate) {
2348
- result = arrayUpdateFunction.apply(void 0, _to_consumable_array$9(arrayUpdate)); // use spread operator to insert each value as an argument, as "nested arrays" are not allowed in the Firestore
2349
- }
2350
- return result;
2351
- });
2352
- }
2353
- return result;
2354
- }
2355
- var updateData = _object_spread$h({}, createUpdatesWithArrayFunction(union, FieldValue.arrayUnion), createUpdatesWithArrayFunction(remove, FieldValue.arrayRemove));
2356
- return updateData;
2357
- }
2358
-
2359
- function _class_call_check$o(instance, Constructor) {
2360
- if (!(instance instanceof Constructor)) {
2361
- throw new TypeError("Cannot call a class as a function");
2362
- }
2363
- }
2364
- function _defineProperties$f(target, props) {
2365
- for(var i = 0; i < props.length; i++){
2366
- var descriptor = props[i];
2367
- descriptor.enumerable = descriptor.enumerable || false;
2368
- descriptor.configurable = true;
2369
- if ("value" in descriptor) descriptor.writable = true;
2370
- Object.defineProperty(target, descriptor.key, descriptor);
2371
- }
2372
- }
2373
- function _create_class$f(Constructor, protoProps, staticProps) {
2374
- if (protoProps) _defineProperties$f(Constructor.prototype, protoProps);
2375
- return Constructor;
2376
- }
2377
- function _define_property$v(obj, key, value) {
2378
- if (key in obj) {
2379
- Object.defineProperty(obj, key, {
2380
- value: value,
2381
- enumerable: true,
2382
- configurable: true,
2383
- writable: true
2384
- });
2385
- } else {
2386
- obj[key] = value;
2731
+ */ function assertContextHasAuth(context) {
2732
+ if (!isContextWithAuthData(context)) {
2733
+ throw unauthenticatedContextHasNoUidError();
2387
2734
  }
2388
- return obj;
2389
2735
  }
2390
- // MARK: Accessor
2391
2736
  /**
2392
- * Google Cloud Firestore implementation of {@link FirestoreDocumentDataAccessor} that queues
2393
- * all write operations (create, set, update, delete) into a {@link WriteBatch}.
2737
+ * Loads the snapshot data from a Firestore document, throwing if the document does not exist.
2394
2738
  *
2395
- * Writes are not committed until the batch is explicitly committed. Read operations
2396
- * (get, exists) bypass the batch and read directly from Firestore.
2397
- */ var WriteBatchFirestoreDocumentDataAccessor = /*#__PURE__*/ function() {
2398
- function WriteBatchFirestoreDocumentDataAccessor(batch, documentRef) {
2399
- _class_call_check$o(this, WriteBatchFirestoreDocumentDataAccessor);
2400
- _define_property$v(this, "documentRef", void 0);
2401
- _define_property$v(this, "_batch", void 0);
2402
- this.documentRef = documentRef;
2403
- this._batch = batch;
2404
- }
2405
- _create_class$f(WriteBatchFirestoreDocumentDataAccessor, [
2406
- {
2407
- key: "batch",
2408
- get: function get() {
2409
- return this._batch;
2410
- }
2411
- },
2412
- {
2413
- key: "stream",
2414
- value: function stream() {
2415
- return from(this.get()); // todo
2416
- }
2417
- },
2418
- {
2419
- key: "create",
2420
- value: function create(data) {
2421
- this.batch.create(this.documentRef, data);
2422
- return Promise.resolve();
2423
- }
2424
- },
2425
- {
2426
- key: "exists",
2427
- value: function exists() {
2428
- return this.get().then(function(x) {
2429
- return x.exists;
2430
- });
2431
- }
2432
- },
2433
- {
2434
- key: "get",
2435
- value: function get() {
2436
- return this.documentRef.get();
2437
- }
2438
- },
2439
- {
2440
- key: "getWithConverter",
2441
- value: function getWithConverter(converter) {
2442
- return this.documentRef.withConverter(converter).get();
2443
- }
2444
- },
2445
- {
2446
- key: "delete",
2447
- value: function _delete(params) {
2448
- this.batch.delete(this.documentRef, params === null || params === void 0 ? void 0 : params.precondition);
2449
- return Promise.resolve();
2450
- }
2451
- },
2452
- {
2453
- key: "set",
2454
- value: function set(data) {
2455
- this.batch.set(this.documentRef, data);
2456
- return Promise.resolve();
2457
- }
2458
- },
2459
- {
2460
- key: "increment",
2461
- value: function increment(data, params) {
2462
- return this.update(firestoreServerIncrementUpdateToUpdateData(data), params);
2463
- }
2464
- },
2465
- {
2466
- key: "arrayUpdate",
2467
- value: function arrayUpdate(data, params) {
2468
- return this.update(firestoreServerArrayUpdateToUpdateData(data), params);
2469
- }
2470
- },
2471
- {
2472
- key: "update",
2473
- value: function update(data, params) {
2474
- if ((params === null || params === void 0 ? void 0 : params.precondition) != null) {
2475
- this.batch.update(this.documentRef, data, params.precondition);
2476
- } else {
2477
- this.batch.update(this.documentRef, data);
2478
- }
2479
- return Promise.resolve();
2480
- }
2481
- }
2482
- ]);
2483
- return WriteBatchFirestoreDocumentDataAccessor;
2484
- }();
2485
- /**
2486
- * Creates a {@link FirestoreDocumentDataAccessorFactory} that produces batch-backed accessors.
2487
- *
2488
- * All accessors created from this factory share the same {@link WriteBatch}, so committing
2489
- * the batch applies all queued writes atomically.
2490
- *
2491
- * @param writeBatch - The Google Cloud WriteBatch to queue operations into.
2492
- * @returns A factory that creates batch-backed accessors sharing the given WriteBatch.
2739
+ * @param document - The Firestore document to load data from.
2740
+ * @param message - Optional custom error message.
2741
+ * @returns The document's snapshot data.
2742
+ * @throws {HttpsError} Throws a {@link modelNotAvailableError} (404) if the document has no data.
2493
2743
  *
2494
2744
  * @example
2495
2745
  * ```typescript
2496
- * const batch = firestore.batch();
2497
- * const factory = writeBatchAccessorFactory<User>(batch);
2498
- * const accessor = factory.accessorFor(userDocRef);
2499
- * await accessor.set({ name: 'Alice' });
2500
- * await batch.commit();
2746
+ * const userData = await assertSnapshotData(userDocument);
2501
2747
  * ```
2502
- */ function writeBatchAccessorFactory(writeBatch) {
2503
- return {
2504
- accessorFor: function accessorFor(ref) {
2505
- return new WriteBatchFirestoreDocumentDataAccessor(writeBatch, ref);
2506
- }
2507
- };
2748
+ */ function assertSnapshotData(document, message) {
2749
+ return _async_to_generator$f(function() {
2750
+ var data;
2751
+ return _ts_generator$f(this, function(_state) {
2752
+ switch(_state.label){
2753
+ case 0:
2754
+ return [
2755
+ 4,
2756
+ document.snapshotData()
2757
+ ];
2758
+ case 1:
2759
+ data = _state.sent();
2760
+ if (data == null) {
2761
+ throw modelNotAvailableError({
2762
+ message: message !== null && message !== void 0 ? message : "The ".concat(document.modelType, " was unavailable.")
2763
+ });
2764
+ }
2765
+ return [
2766
+ 2,
2767
+ data
2768
+ ];
2769
+ }
2770
+ });
2771
+ })();
2508
2772
  }
2509
- // MARK: Context
2510
2773
  /**
2511
- * A {@link FirestoreDocumentContext} backed by a Google Cloud {@link WriteBatch}.
2774
+ * Loads snapshot data and attaches the document's `id` and `key` to the result.
2512
2775
  *
2513
- * All document accessors created from this context queue writes into the same batch.
2514
- */ var WriteBatchFirestoreDocumentContext = /*#__PURE__*/ function() {
2515
- function WriteBatchFirestoreDocumentContext(batch) {
2516
- _class_call_check$o(this, WriteBatchFirestoreDocumentContext);
2517
- _define_property$v(this, "_batch", void 0);
2518
- _define_property$v(this, "contextType", FirestoreDocumentContextType.BATCH);
2519
- _define_property$v(this, "accessorFactory", void 0);
2520
- this._batch = batch;
2521
- this.accessorFactory = writeBatchAccessorFactory(batch);
2522
- }
2523
- _create_class$f(WriteBatchFirestoreDocumentContext, [
2524
- {
2525
- key: "batch",
2526
- get: function get() {
2527
- return this._batch;
2776
+ * Combines {@link assertSnapshotData} with {@link setIdAndKeyFromKeyIdRefOnDocumentData}.
2777
+ *
2778
+ * @param document - The Firestore document to load data from.
2779
+ * @param message - Optional custom error message.
2780
+ * @returns The document's snapshot data with `id` and `key` attached.
2781
+ * @throws {HttpsError} Throws a {@link modelNotAvailableError} (404) if the document has no data.
2782
+ */ function assertSnapshotDataWithKey(document, message) {
2783
+ return _async_to_generator$f(function() {
2784
+ var data;
2785
+ return _ts_generator$f(this, function(_state) {
2786
+ switch(_state.label){
2787
+ case 0:
2788
+ return [
2789
+ 4,
2790
+ assertSnapshotData(document, message)
2791
+ ];
2792
+ case 1:
2793
+ data = _state.sent();
2794
+ return [
2795
+ 2,
2796
+ setIdAndKeyFromKeyIdRefOnDocumentData(data, document)
2797
+ ];
2528
2798
  }
2529
- }
2530
- ]);
2531
- return WriteBatchFirestoreDocumentContext;
2532
- }();
2799
+ });
2800
+ })();
2801
+ }
2533
2802
  /**
2534
- * Creates a {@link WriteBatchFirestoreDocumentContext} wrapping the given batch.
2803
+ * Asserts that the Firestore document exists without loading its data.
2535
2804
  *
2536
- * @param batch - The Google Cloud WriteBatch to use.
2537
- * @returns A new {@link WriteBatchFirestoreDocumentContext} for the given batch.
2538
- */ function writeBatchDocumentContext(batch) {
2539
- return new WriteBatchFirestoreDocumentContext(batch);
2540
- }
2541
-
2542
- function _class_call_check$n(instance, Constructor) {
2543
- if (!(instance instanceof Constructor)) {
2544
- throw new TypeError("Cannot call a class as a function");
2545
- }
2546
- }
2547
- function _defineProperties$e(target, props) {
2548
- for(var i = 0; i < props.length; i++){
2549
- var descriptor = props[i];
2550
- descriptor.enumerable = descriptor.enumerable || false;
2551
- descriptor.configurable = true;
2552
- if ("value" in descriptor) descriptor.writable = true;
2553
- Object.defineProperty(target, descriptor.key, descriptor);
2554
- }
2555
- }
2556
- function _create_class$e(Constructor, protoProps, staticProps) {
2557
- if (protoProps) _defineProperties$e(Constructor.prototype, protoProps);
2558
- return Constructor;
2559
- }
2560
- function _define_property$u(obj, key, value) {
2561
- if (key in obj) {
2562
- Object.defineProperty(obj, key, {
2563
- value: value,
2564
- enumerable: true,
2565
- configurable: true,
2566
- writable: true
2805
+ * @param document - The Firestore document to check.
2806
+ * @param message - Optional custom error message.
2807
+ * @throws {HttpsError} Throws a {@link modelNotAvailableError} (404) if the document does not exist.
2808
+ */ function assertDocumentExists(document, message) {
2809
+ return _async_to_generator$f(function() {
2810
+ var exists;
2811
+ return _ts_generator$f(this, function(_state) {
2812
+ switch(_state.label){
2813
+ case 0:
2814
+ return [
2815
+ 4,
2816
+ document.exists()
2817
+ ];
2818
+ case 1:
2819
+ exists = _state.sent();
2820
+ if (!exists) {
2821
+ throw documentModelNotAvailableError(document, message);
2822
+ }
2823
+ return [
2824
+ 2
2825
+ ];
2826
+ }
2567
2827
  });
2568
- } else {
2569
- obj[key] = value;
2570
- }
2571
- return obj;
2828
+ })();
2572
2829
  }
2573
- // MARK: Accessor
2574
2830
  /**
2575
- * Default Google Cloud Firestore implementation of {@link FirestoreDocumentDataAccessor}.
2831
+ * Creates a {@link modelNotAvailableError} for the given document's model type.
2576
2832
  *
2577
- * Performs all operations directly against the Firestore document reference without
2578
- * batching or transactional context. Supports real-time streaming via `onSnapshot`.
2579
- */ var DefaultFirestoreDocumentDataAccessor = /*#__PURE__*/ function() {
2580
- function DefaultFirestoreDocumentDataAccessor(documentRef) {
2581
- _class_call_check$n(this, DefaultFirestoreDocumentDataAccessor);
2582
- _define_property$u(this, "_documentRef", void 0);
2583
- this._documentRef = documentRef;
2584
- }
2585
- _create_class$e(DefaultFirestoreDocumentDataAccessor, [
2586
- {
2587
- key: "documentRef",
2588
- get: function get() {
2589
- return this._documentRef;
2590
- }
2591
- },
2592
- {
2593
- key: "stream",
2594
- value: function stream() {
2595
- var _this = this;
2596
- return streamFromOnSnapshot(function(param) {
2597
- var next = param.next, error = param.error;
2598
- return _this.documentRef.onSnapshot(next, error);
2599
- });
2600
- }
2601
- },
2602
- {
2603
- key: "create",
2604
- value: function create(data) {
2605
- return this.documentRef.create(data);
2606
- }
2607
- },
2608
- {
2609
- key: "exists",
2610
- value: function exists() {
2611
- return this.get().then(function(x) {
2612
- return x.exists;
2613
- });
2614
- }
2615
- },
2616
- {
2617
- key: "get",
2618
- value: function get() {
2619
- return this.documentRef.get();
2620
- }
2621
- },
2622
- {
2623
- key: "getWithConverter",
2624
- value: function getWithConverter(converter) {
2625
- return this.documentRef.withConverter(converter).get();
2626
- }
2627
- },
2628
- {
2629
- key: "delete",
2630
- value: function _delete(params) {
2631
- return this.documentRef.delete(params === null || params === void 0 ? void 0 : params.precondition);
2632
- }
2633
- },
2634
- {
2635
- key: "set",
2636
- value: function set(data, options) {
2637
- return options ? this.documentRef.set(data, options) : this.documentRef.set(data);
2638
- }
2639
- },
2640
- {
2641
- key: "increment",
2642
- value: function increment(data, params) {
2643
- return this.update(firestoreServerIncrementUpdateToUpdateData(data), params);
2644
- }
2645
- },
2646
- {
2647
- key: "arrayUpdate",
2648
- value: function arrayUpdate(data, params) {
2649
- return this.update(firestoreServerArrayUpdateToUpdateData(data), params);
2650
- }
2651
- },
2652
- {
2653
- key: "update",
2654
- value: function update(data, params) {
2655
- return (params === null || params === void 0 ? void 0 : params.precondition) ? this.documentRef.update(data, params.precondition) : this.documentRef.update(data);
2656
- }
2657
- }
2658
- ]);
2659
- return DefaultFirestoreDocumentDataAccessor;
2660
- }();
2661
- /**
2662
- * Creates a {@link FirestoreDocumentDataAccessorFactory} that produces default (non-batched, non-transactional) accessors.
2833
+ * Used by {@link assertDocumentExists} and other assertion functions.
2663
2834
  *
2664
- * @returns A factory that creates default (non-batched, non-transactional) accessors.
2835
+ * @param document - The document (or object with `modelType`) to generate the error for.
2836
+ * @param message - Optional custom error message.
2837
+ * @returns A {@link modelNotAvailableError} with the document's model type in the message.
2838
+ */ function documentModelNotAvailableError(document, message) {
2839
+ return modelNotAvailableError({
2840
+ message: message !== null && message !== void 0 ? message : "The ".concat(document.modelType, " was unavailable.")
2841
+ });
2842
+ }
2843
+
2844
+ /**
2845
+ * Error code for when a phone number is already registered in Firebase Auth.
2846
+ */ var PHONE_NUMBER_ALREADY_EXISTS_ERROR_CODE = 'PHONE_NUMBER_ALREADY_EXISTS';
2847
+ /**
2848
+ * Creates a precondition conflict (409) error indicating the phone number already exists.
2665
2849
  *
2666
- * @example
2667
- * ```typescript
2668
- * const factory = defaultFirestoreAccessorFactory<User>();
2669
- * const accessor = factory.accessorFor(userDocRef);
2670
- * ```
2671
- */ function defaultFirestoreAccessorFactory() {
2672
- return {
2673
- accessorFor: function accessorFor(ref) {
2674
- return new DefaultFirestoreDocumentDataAccessor(ref);
2675
- }
2676
- };
2850
+ * @returns A new precondition-conflict (409) {@link HttpsError} with the phone-number-exists code.
2851
+ */ function phoneNumberAlreadyExistsError() {
2852
+ return preconditionConflictError({
2853
+ code: PHONE_NUMBER_ALREADY_EXISTS_ERROR_CODE,
2854
+ message: 'This phone number already exists in the system.'
2855
+ });
2677
2856
  }
2678
- // MARK: Context
2679
2857
  /**
2680
- * Creates a {@link FirestoreDocumentContext} with no special execution context (no batch, no transaction).
2858
+ * Handles Firebase Auth errors by mapping known error codes to typed HTTP errors.
2681
2859
  *
2682
- * Operations performed through this context execute immediately against Firestore.
2860
+ * Currently maps `auth/phone-number-already-exists` to a 409 conflict error.
2861
+ * Unknown error codes are forwarded to the optional handler.
2683
2862
  *
2684
- * @returns A {@link FirestoreDocumentContext} for direct Firestore operations.
2685
- */ function defaultFirestoreDocumentContext() {
2686
- return {
2687
- contextType: FirestoreDocumentContextType.NONE,
2688
- accessorFactory: defaultFirestoreAccessorFactory()
2689
- };
2863
+ * @param e - The caught error.
2864
+ * @param handleUnknownCode - Optional handler for Firebase errors with unrecognized codes.
2865
+ */ function handleFirebaseAuthError(e, handleUnknownCode) {
2866
+ handleFirebaseError(e, function(firebaseError) {
2867
+ switch(firebaseError.code){
2868
+ case FIREBASE_AUTH_PHONE_NUMBER_ALREADY_EXISTS_ERROR:
2869
+ throw phoneNumberAlreadyExistsError();
2870
+ default:
2871
+ handleUnknownCode === null || handleUnknownCode === void 0 ? void 0 : handleUnknownCode(firebaseError);
2872
+ break;
2873
+ }
2874
+ });
2690
2875
  }
2691
2876
 
2692
- function _class_call_check$m(instance, Constructor) {
2693
- if (!(instance instanceof Constructor)) {
2694
- throw new TypeError("Cannot call a class as a function");
2877
+ function asyncGeneratorStep$e(gen, resolve, reject, _next, _throw, key, arg) {
2878
+ try {
2879
+ var info = gen[key](arg);
2880
+ var value = info.value;
2881
+ } catch (error) {
2882
+ reject(error);
2883
+ return;
2695
2884
  }
2696
- }
2697
- function _defineProperties$d(target, props) {
2698
- for(var i = 0; i < props.length; i++){
2699
- var descriptor = props[i];
2700
- descriptor.enumerable = descriptor.enumerable || false;
2701
- descriptor.configurable = true;
2702
- if ("value" in descriptor) descriptor.writable = true;
2703
- Object.defineProperty(target, descriptor.key, descriptor);
2885
+ if (info.done) {
2886
+ resolve(value);
2887
+ } else {
2888
+ Promise.resolve(value).then(_next, _throw);
2704
2889
  }
2705
2890
  }
2706
- function _create_class$d(Constructor, protoProps, staticProps) {
2707
- if (protoProps) _defineProperties$d(Constructor.prototype, protoProps);
2708
- return Constructor;
2709
- }
2710
- function _define_property$t(obj, key, value) {
2711
- if (key in obj) {
2712
- Object.defineProperty(obj, key, {
2713
- value: value,
2714
- enumerable: true,
2715
- configurable: true,
2716
- writable: true
2891
+ function _async_to_generator$e(fn) {
2892
+ return function() {
2893
+ var self = this, args = arguments;
2894
+ return new Promise(function(resolve, reject) {
2895
+ var gen = fn.apply(self, args);
2896
+ function _next(value) {
2897
+ asyncGeneratorStep$e(gen, resolve, reject, _next, _throw, "next", value);
2898
+ }
2899
+ function _throw(err) {
2900
+ asyncGeneratorStep$e(gen, resolve, reject, _next, _throw, "throw", err);
2901
+ }
2902
+ _next(undefined);
2717
2903
  });
2904
+ };
2905
+ }
2906
+ function _instanceof$2(left, right) {
2907
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
2908
+ return !!right[Symbol.hasInstance](left);
2718
2909
  } else {
2719
- obj[key] = value;
2910
+ return left instanceof right;
2720
2911
  }
2721
- return obj;
2722
2912
  }
2723
- // MARK: Accessor
2724
- /**
2725
- * Google Cloud Firestore implementation of {@link FirestoreDocumentDataAccessor} that executes
2726
- * all operations within a Firestore {@link Transaction}.
2727
- *
2728
- * Reads performed through this accessor are included in the transaction's read set, ensuring
2729
- * consistency. Writes are committed atomically when the transaction completes.
2730
- */ var TransactionFirestoreDocumentDataAccessor = /*#__PURE__*/ function() {
2731
- function TransactionFirestoreDocumentDataAccessor(transaction, documentRef) {
2732
- _class_call_check$m(this, TransactionFirestoreDocumentDataAccessor);
2733
- _define_property$t(this, "_transaction", void 0);
2734
- _define_property$t(this, "_documentRef", void 0);
2735
- this._transaction = transaction;
2736
- this._documentRef = documentRef;
2737
- }
2738
- _create_class$d(TransactionFirestoreDocumentDataAccessor, [
2739
- {
2740
- key: "transaction",
2741
- get: function get() {
2742
- return this._transaction;
2743
- }
2744
- },
2745
- {
2746
- key: "documentRef",
2747
- get: function get() {
2748
- return this._documentRef;
2749
- }
2750
- },
2751
- {
2752
- key: "stream",
2753
- value: function stream() {
2754
- return from(this.get());
2755
- }
2756
- },
2757
- {
2758
- key: "create",
2759
- value: function create(data) {
2760
- this.transaction.create(this.documentRef, data);
2761
- return Promise.resolve();
2762
- }
2763
- },
2764
- {
2765
- key: "exists",
2766
- value: function exists() {
2767
- return this.get().then(function(x) {
2768
- return x.exists;
2769
- });
2770
- }
2771
- },
2772
- {
2773
- key: "get",
2774
- value: function get() {
2775
- return this.transaction.get(this.documentRef);
2776
- }
2777
- },
2778
- {
2779
- key: "getWithConverter",
2780
- value: function getWithConverter(converter) {
2781
- return this.transaction.get(this.documentRef.withConverter(converter));
2782
- }
2783
- },
2784
- {
2785
- key: "delete",
2786
- value: function _delete() {
2787
- this.transaction.delete(this.documentRef);
2788
- return Promise.resolve();
2789
- }
2790
- },
2791
- {
2792
- key: "set",
2793
- value: function set(data, options) {
2794
- this.transaction.set(this.documentRef, data, options);
2795
- return Promise.resolve();
2796
- }
2797
- },
2798
- {
2799
- key: "increment",
2800
- value: function increment(data, params) {
2801
- return this.update(firestoreServerIncrementUpdateToUpdateData(data), params);
2802
- }
2803
- },
2804
- {
2805
- key: "arrayUpdate",
2806
- value: function arrayUpdate(data, params) {
2807
- return this.update(firestoreServerArrayUpdateToUpdateData(data), params);
2808
- }
2809
- },
2810
- {
2811
- key: "update",
2812
- value: function update(data, params) {
2813
- if (params === null || params === void 0 ? void 0 : params.precondition) {
2814
- this.transaction.update(this.documentRef, data, params.precondition);
2815
- } else {
2816
- this.transaction.update(this.documentRef, data);
2817
- }
2818
- return Promise.resolve();
2819
- }
2820
- }
2821
- ]);
2822
- return TransactionFirestoreDocumentDataAccessor;
2823
- }();
2824
- /**
2825
- * Creates a {@link FirestoreDocumentDataAccessorFactory} that produces transaction-backed accessors.
2826
- *
2827
- * All accessors share the same transaction, so reads and writes participate in the same
2828
- * atomic operation.
2829
- *
2830
- * @param transaction - The Google Cloud Transaction to execute operations within.
2831
- * @returns A factory that creates transaction-backed accessors sharing the given transaction.
2832
- *
2833
- * @example
2834
- * ```typescript
2835
- * await firestore.runTransaction(async (transaction) => {
2836
- * const factory = transactionAccessorFactory<User>(transaction);
2837
- * const accessor = factory.accessorFor(userDocRef);
2838
- * const snapshot = await accessor.get();
2839
- * await accessor.update({ name: 'Updated' });
2840
- * });
2841
- * ```
2842
- */ function transactionAccessorFactory(transaction) {
2843
- return {
2844
- accessorFor: function accessorFor(ref) {
2845
- return new TransactionFirestoreDocumentDataAccessor(transaction, ref);
2846
- }
2847
- };
2848
- }
2849
- // MARK: Context
2850
- /**
2851
- * A {@link FirestoreDocumentContext} backed by a Google Cloud {@link Transaction}.
2852
- *
2853
- * All document accessors created from this context operate within the same transaction.
2854
- */ var TransactionFirestoreDocumentContext = /*#__PURE__*/ function() {
2855
- function TransactionFirestoreDocumentContext(transaction) {
2856
- _class_call_check$m(this, TransactionFirestoreDocumentContext);
2857
- _define_property$t(this, "_transaction", void 0);
2858
- _define_property$t(this, "contextType", FirestoreDocumentContextType.TRANSACTION);
2859
- _define_property$t(this, "accessorFactory", void 0);
2860
- this._transaction = transaction;
2861
- this.accessorFactory = transactionAccessorFactory(transaction);
2862
- }
2863
- _create_class$d(TransactionFirestoreDocumentContext, [
2864
- {
2865
- key: "transaction",
2866
- get: function get() {
2867
- return this._transaction;
2868
- }
2869
- }
2870
- ]);
2871
- return TransactionFirestoreDocumentContext;
2872
- }();
2873
- /**
2874
- * Creates a {@link TransactionFirestoreDocumentContext} wrapping the given transaction.
2875
- *
2876
- * @param transaction - The Google Cloud Transaction to use.
2877
- * @returns A new {@link TransactionFirestoreDocumentContext} for the given transaction.
2878
- */ function transactionDocumentContext(transaction) {
2879
- return new TransactionFirestoreDocumentContext(transaction);
2880
- }
2881
-
2882
- function _array_like_to_array$c(arr, len) {
2883
- if (len == null || len > arr.length) len = arr.length;
2884
- for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
2885
- return arr2;
2886
- }
2887
- function _array_with_holes$3(arr) {
2888
- if (Array.isArray(arr)) return arr;
2889
- }
2890
- function asyncGeneratorStep$e(gen, resolve, reject, _next, _throw, key, arg) {
2891
- try {
2892
- var info = gen[key](arg);
2893
- var value = info.value;
2894
- } catch (error) {
2895
- reject(error);
2896
- return;
2897
- }
2898
- if (info.done) {
2899
- resolve(value);
2900
- } else {
2901
- Promise.resolve(value).then(_next, _throw);
2902
- }
2903
- }
2904
- function _async_to_generator$e(fn) {
2905
- return function() {
2906
- var self = this, args = arguments;
2907
- return new Promise(function(resolve, reject) {
2908
- var gen = fn.apply(self, args);
2909
- function _next(value) {
2910
- asyncGeneratorStep$e(gen, resolve, reject, _next, _throw, "next", value);
2911
- }
2912
- function _throw(err) {
2913
- asyncGeneratorStep$e(gen, resolve, reject, _next, _throw, "throw", err);
2914
- }
2915
- _next(undefined);
2916
- });
2917
- };
2918
- }
2919
- function _iterable_to_array_limit$3(arr, i) {
2920
- var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
2921
- if (_i == null) return;
2922
- var _arr = [];
2923
- var _n = true;
2924
- var _d = false;
2925
- var _s, _e;
2926
- try {
2927
- for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
2928
- _arr.push(_s.value);
2929
- if (i && _arr.length === i) break;
2930
- }
2931
- } catch (err) {
2932
- _d = true;
2933
- _e = err;
2934
- } finally{
2935
- try {
2936
- if (!_n && _i["return"] != null) _i["return"]();
2937
- } finally{
2938
- if (_d) throw _e;
2939
- }
2940
- }
2941
- return _arr;
2942
- }
2943
- function _non_iterable_rest$3() {
2944
- throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
2945
- }
2946
- function _sliced_to_array$3(arr, i) {
2947
- return _array_with_holes$3(arr) || _iterable_to_array_limit$3(arr, i) || _unsupported_iterable_to_array$c(arr, i) || _non_iterable_rest$3();
2948
- }
2949
- function _unsupported_iterable_to_array$c(o, minLen) {
2950
- if (!o) return;
2951
- if (typeof o === "string") return _array_like_to_array$c(o, minLen);
2952
- var n = Object.prototype.toString.call(o).slice(8, -1);
2953
- if (n === "Object" && o.constructor) n = o.constructor.name;
2954
- if (n === "Map" || n === "Set") return Array.from(n);
2955
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$c(o, minLen);
2956
- }
2957
- function _ts_generator$e(thisArg, body) {
2958
- var f, y, t, _ = {
2959
- label: 0,
2960
- sent: function() {
2961
- if (t[0] & 1) throw t[1];
2962
- return t[1];
2913
+ function _ts_generator$e(thisArg, body) {
2914
+ var f, y, t, _ = {
2915
+ label: 0,
2916
+ sent: function() {
2917
+ if (t[0] & 1) throw t[1];
2918
+ return t[1];
2963
2919
  },
2964
2920
  trys: [],
2965
2921
  ops: []
@@ -3054,133 +3010,626 @@ function _ts_generator$e(thisArg, body) {
3054
3010
  }
3055
3011
  }
3056
3012
  /**
3057
- * Resolves a Firestore {@link CollectionReference} from a starting point and optional additional path segments.
3013
+ * Wraps an async function that uses {@link FirebaseServerUserPasswordResetService} methods,
3014
+ * catching password-reset-specific errors and re-throwing them as appropriate {@link HttpsError} instances
3015
+ * suitable for returning to clients.
3058
3016
  *
3059
- * Supports nested subcollection paths by processing segments in pairs (doc ID, collection name).
3017
+ * Error mapping:
3018
+ * - {@link FirebaseServerAuthPasswordResetInvalidCodeError} → permission-denied (403)
3019
+ * - {@link FirebaseServerAuthPasswordResetNoResetConfigError} → bad-request (400)
3020
+ * - {@link FirebaseServerAuthPasswordResetThrottleError} → unavailable (503)
3021
+ * - {@link FirebaseServerAuthPasswordResetSendOnceError} → bad-request (400)
3060
3022
  *
3061
- * @param start - A Firestore object that can resolve collection paths (e.g., Firestore instance, DocumentReference).
3062
- * @param path - The initial collection path.
3063
- * @param pathSegments - Optional pairs of [docId, collectionName] for subcollection traversal.
3064
- * @returns The resolved {@link CollectionReference} at the given path.
3065
- * @throws Error if pathSegments length is odd (segments must come in pairs).
3023
+ * @param fn - The async function to execute.
3024
+ * @returns The result of the function.
3025
+ */ function catchAndThrowPasswordResetServerErrors(fn) {
3026
+ return _async_to_generator$e(function() {
3027
+ var result, error;
3028
+ return _ts_generator$e(this, function(_state) {
3029
+ switch(_state.label){
3030
+ case 0:
3031
+ _state.trys.push([
3032
+ 0,
3033
+ 2,
3034
+ ,
3035
+ 3
3036
+ ]);
3037
+ return [
3038
+ 4,
3039
+ fn()
3040
+ ];
3041
+ case 1:
3042
+ result = _state.sent();
3043
+ return [
3044
+ 3,
3045
+ 3
3046
+ ];
3047
+ case 2:
3048
+ error = _state.sent();
3049
+ if (_instanceof$2(error, FirebaseServerAuthPasswordResetInvalidCodeError)) {
3050
+ throw authServicePasswordResetInvalidCodeError();
3051
+ } else if (_instanceof$2(error, FirebaseServerAuthPasswordResetNoResetConfigError)) {
3052
+ throw authServicePasswordResetNoConfigError();
3053
+ } else if (_instanceof$2(error, FirebaseServerAuthPasswordResetThrottleError)) {
3054
+ throw authServicePasswordResetThrottleError();
3055
+ } else if (_instanceof$2(error, FirebaseServerAuthPasswordResetSendOnceError)) {
3056
+ throw authServicePasswordResetSendOnceError();
3057
+ }
3058
+ throw error;
3059
+ case 3:
3060
+ return [
3061
+ 2,
3062
+ result
3063
+ ];
3064
+ }
3065
+ });
3066
+ })();
3067
+ }
3068
+ /**
3069
+ * Creates a permission-denied (403) server error for an invalid or expired password reset code.
3070
+ *
3071
+ * @returns An {@link HttpsError} with code `permission-denied`.
3072
+ */ function authServicePasswordResetInvalidCodeError() {
3073
+ return permissionDeniedError({
3074
+ code: DBX_FIREBASE_SERVER_PASSWORD_RESET_INVALID_CODE_ERROR_CODE,
3075
+ message: 'Invalid or expired reset password code.'
3076
+ });
3077
+ }
3078
+ /**
3079
+ * Creates a bad-request (400) server error when no active password reset exists for the user.
3080
+ *
3081
+ * @returns An {@link HttpsError} with code `invalid-argument`.
3082
+ */ function authServicePasswordResetNoConfigError() {
3083
+ return badRequestError({
3084
+ code: DBX_FIREBASE_SERVER_PASSWORD_RESET_NO_CONFIG_ERROR_CODE,
3085
+ message: 'No active password reset for this user.'
3086
+ });
3087
+ }
3088
+ /**
3089
+ * Creates an unavailable (503) server error when password reset email sending is throttled.
3090
+ *
3091
+ * @returns An {@link HttpsError} with code `unavailable`.
3092
+ */ function authServicePasswordResetThrottleError() {
3093
+ return unavailableError({
3094
+ code: DBX_FIREBASE_SERVER_PASSWORD_RESET_THROTTLE_ERROR_CODE,
3095
+ message: 'Password reset email was recently sent. Try again later.'
3096
+ });
3097
+ }
3098
+ /**
3099
+ * Creates a bad-request (400) server error when the password reset email has already been sent
3100
+ * and the send-once constraint is active.
3101
+ *
3102
+ * @returns An {@link HttpsError} with code `invalid-argument`.
3103
+ */ function authServicePasswordResetSendOnceError() {
3104
+ return badRequestError({
3105
+ code: DBX_FIREBASE_SERVER_PASSWORD_RESET_SEND_ONCE_ERROR_CODE,
3106
+ message: 'Password reset email has already been sent.'
3107
+ });
3108
+ }
3109
+
3110
+ // MARK: Tokens
3111
+ /**
3112
+ * Token to access a configured FirebaseServerEnvironmentServiceConfig for the app.
3113
+ */ var FIREBASE_SERVER_ENV_TOKEN = 'FIREBASE_SERVER_ENV_TOKEN';
3114
+ /**
3115
+ * Creates a NestJS provider that binds the given config to the {@link FIREBASE_SERVER_ENV_TOKEN} injection token.
3116
+ *
3117
+ * @param env - The Firebase server environment configuration.
3118
+ * @returns A NestJS provider binding the config to the {@link FIREBASE_SERVER_ENV_TOKEN} token.
3066
3119
  *
3067
3120
  * @example
3068
3121
  * ```typescript
3069
- * const ref = collectionRefForPath<User>(firestore, 'users');
3070
- * const subRef = collectionRefForPath<Comment>(firestore, 'users', ['user123', 'comments']);
3122
+ * const provider = firebaseServerEnvTokenProvider({ appUrl: 'https://myapp.com', ... });
3071
3123
  * ```
3072
- */ function collectionRefForPath(start, path, pathSegments) {
3073
- var ref = start.collection(path);
3074
- if (pathSegments === null || pathSegments === void 0 ? void 0 : pathSegments.length) {
3075
- if (pathSegments.length % 2 !== 0) {
3076
- throw new Error('Invalid number of path segments provided for collection. Path: "'.concat(path, '" + "').concat(pathSegments, '"'));
3124
+ */ function firebaseServerEnvTokenProvider(env) {
3125
+ return {
3126
+ provide: FIREBASE_SERVER_ENV_TOKEN,
3127
+ useValue: env
3128
+ };
3129
+ }
3130
+ /**
3131
+ * Creates NestJS providers that bind the given config to both {@link FIREBASE_SERVER_ENV_TOKEN}
3132
+ * and the base {@link SERVER_ENV_TOKEN} from `@dereekb/nestjs`.
3133
+ *
3134
+ * Use this when the NestJS app needs the config accessible via either token.
3135
+ *
3136
+ * @param env - The Firebase server environment configuration.
3137
+ * @returns An array of providers binding the config to both Firebase and base server env tokens.
3138
+ *
3139
+ * @example
3140
+ * ```typescript
3141
+ * @Module({
3142
+ * providers: [...firebaseServerEnvTokenProviders(myEnvConfig)]
3143
+ * })
3144
+ * export class AppModule {}
3145
+ * ```
3146
+ */ function firebaseServerEnvTokenProviders(env) {
3147
+ return [
3148
+ firebaseServerEnvTokenProvider(env),
3149
+ {
3150
+ provide: SERVER_ENV_TOKEN,
3151
+ useExisting: FIREBASE_SERVER_ENV_TOKEN
3152
+ }
3153
+ ];
3154
+ }
3155
+
3156
+ function _class_call_check$p(instance, Constructor) {
3157
+ if (!(instance instanceof Constructor)) {
3158
+ throw new TypeError("Cannot call a class as a function");
3159
+ }
3160
+ }
3161
+ /**
3162
+ * Abstract service providing Firebase server environment information such as deployment stage,
3163
+ * feature flags, and app URL.
3164
+ *
3165
+ * Implementations are typically injected via {@link FIREBASE_SERVER_ENV_TOKEN} and
3166
+ * backed by a {@link FirebaseServerEnvironmentConfig}.
3167
+ */ var FirebaseServerEnvService = function FirebaseServerEnvService() {
3168
+ _class_call_check$p(this, FirebaseServerEnvService);
3169
+ }
3170
+ ;
3171
+
3172
+ /**
3173
+ * Converts a {@link FirestoreAccessorIncrementUpdate} into Firestore {@link UpdateData} using
3174
+ * Google Cloud Firestore's {@link FieldValue.increment}.
3175
+ *
3176
+ * Each field in the input maps to an atomic increment operation. Null/undefined values default to 0.
3177
+ *
3178
+ * @param input - The increment specification mapping field names to numeric deltas.
3179
+ * @returns Firestore {@link UpdateData} with atomic increment operations.
3180
+ *
3181
+ * @example
3182
+ * ```typescript
3183
+ * const updateData = firestoreServerIncrementUpdateToUpdateData<Stats>({
3184
+ * viewCount: 1,
3185
+ * likeCount: -1
3186
+ * });
3187
+ * ```
3188
+ */ function firestoreServerIncrementUpdateToUpdateData(input) {
3189
+ return mapObjectMap(input, function(incrementValue) {
3190
+ return FieldValue.increment(incrementValue !== null && incrementValue !== void 0 ? incrementValue : 0);
3191
+ });
3192
+ }
3193
+
3194
+ function _array_like_to_array$d(arr, len) {
3195
+ if (len == null || len > arr.length) len = arr.length;
3196
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
3197
+ return arr2;
3198
+ }
3199
+ function _array_without_holes$9(arr) {
3200
+ if (Array.isArray(arr)) return _array_like_to_array$d(arr);
3201
+ }
3202
+ function _define_property$w(obj, key, value) {
3203
+ if (key in obj) {
3204
+ Object.defineProperty(obj, key, {
3205
+ value: value,
3206
+ enumerable: true,
3207
+ configurable: true,
3208
+ writable: true
3209
+ });
3210
+ } else {
3211
+ obj[key] = value;
3212
+ }
3213
+ return obj;
3214
+ }
3215
+ function _iterable_to_array$9(iter) {
3216
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
3217
+ }
3218
+ function _non_iterable_spread$9() {
3219
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
3220
+ }
3221
+ function _object_spread$h(target) {
3222
+ for(var i = 1; i < arguments.length; i++){
3223
+ var source = arguments[i] != null ? arguments[i] : {};
3224
+ var ownKeys = Object.keys(source);
3225
+ if (typeof Object.getOwnPropertySymbols === "function") {
3226
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
3227
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
3228
+ }));
3229
+ }
3230
+ ownKeys.forEach(function(key) {
3231
+ _define_property$w(target, key, source[key]);
3232
+ });
3233
+ }
3234
+ return target;
3235
+ }
3236
+ function _to_consumable_array$9(arr) {
3237
+ return _array_without_holes$9(arr) || _iterable_to_array$9(arr) || _unsupported_iterable_to_array$d(arr) || _non_iterable_spread$9();
3238
+ }
3239
+ function _unsupported_iterable_to_array$d(o, minLen) {
3240
+ if (!o) return;
3241
+ if (typeof o === "string") return _array_like_to_array$d(o, minLen);
3242
+ var n = Object.prototype.toString.call(o).slice(8, -1);
3243
+ if (n === "Object" && o.constructor) n = o.constructor.name;
3244
+ if (n === "Map" || n === "Set") return Array.from(n);
3245
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$d(o, minLen);
3246
+ }
3247
+ /**
3248
+ * Converts a {@link FirestoreAccessorArrayUpdate} into Firestore {@link UpdateData} using
3249
+ * Google Cloud Firestore's {@link FieldValue.arrayUnion} and {@link FieldValue.arrayRemove}.
3250
+ *
3251
+ * @param input - The array update specification with `union` and/or `remove` field maps.
3252
+ * @returns Firestore {@link UpdateData} with array union/remove operations.
3253
+ *
3254
+ * @example
3255
+ * ```typescript
3256
+ * const updateData = firestoreServerArrayUpdateToUpdateData<User>({
3257
+ * union: { tags: ['new-tag'] },
3258
+ * remove: { tags: ['old-tag'] }
3259
+ * });
3260
+ * ```
3261
+ */ function firestoreServerArrayUpdateToUpdateData(input) {
3262
+ var union = input.union;
3263
+ var remove = input.remove;
3264
+ function createUpdatesWithArrayFunction(fieldUpdate, arrayUpdateFunction) {
3265
+ var result;
3266
+ if (fieldUpdate) {
3267
+ result = mapObjectMap(fieldUpdate, function(arrayUpdate) {
3268
+ var result;
3269
+ if (arrayUpdate) {
3270
+ result = arrayUpdateFunction.apply(void 0, _to_consumable_array$9(arrayUpdate)); // use spread operator to insert each value as an argument, as "nested arrays" are not allowed in the Firestore
3271
+ }
3272
+ return result;
3273
+ });
3274
+ }
3275
+ return result;
3276
+ }
3277
+ var updateData = _object_spread$h({}, createUpdatesWithArrayFunction(union, FieldValue.arrayUnion), createUpdatesWithArrayFunction(remove, FieldValue.arrayRemove));
3278
+ return updateData;
3279
+ }
3280
+
3281
+ function _class_call_check$o(instance, Constructor) {
3282
+ if (!(instance instanceof Constructor)) {
3283
+ throw new TypeError("Cannot call a class as a function");
3284
+ }
3285
+ }
3286
+ function _defineProperties$f(target, props) {
3287
+ for(var i = 0; i < props.length; i++){
3288
+ var descriptor = props[i];
3289
+ descriptor.enumerable = descriptor.enumerable || false;
3290
+ descriptor.configurable = true;
3291
+ if ("value" in descriptor) descriptor.writable = true;
3292
+ Object.defineProperty(target, descriptor.key, descriptor);
3293
+ }
3294
+ }
3295
+ function _create_class$f(Constructor, protoProps, staticProps) {
3296
+ if (protoProps) _defineProperties$f(Constructor.prototype, protoProps);
3297
+ return Constructor;
3298
+ }
3299
+ function _define_property$v(obj, key, value) {
3300
+ if (key in obj) {
3301
+ Object.defineProperty(obj, key, {
3302
+ value: value,
3303
+ enumerable: true,
3304
+ configurable: true,
3305
+ writable: true
3306
+ });
3307
+ } else {
3308
+ obj[key] = value;
3309
+ }
3310
+ return obj;
3311
+ }
3312
+ // MARK: Accessor
3313
+ /**
3314
+ * Google Cloud Firestore implementation of {@link FirestoreDocumentDataAccessor} that queues
3315
+ * all write operations (create, set, update, delete) into a {@link WriteBatch}.
3316
+ *
3317
+ * Writes are not committed until the batch is explicitly committed. Read operations
3318
+ * (get, exists) bypass the batch and read directly from Firestore.
3319
+ */ var WriteBatchFirestoreDocumentDataAccessor = /*#__PURE__*/ function() {
3320
+ function WriteBatchFirestoreDocumentDataAccessor(batch, documentRef) {
3321
+ _class_call_check$o(this, WriteBatchFirestoreDocumentDataAccessor);
3322
+ _define_property$v(this, "documentRef", void 0);
3323
+ _define_property$v(this, "_batch", void 0);
3324
+ this.documentRef = documentRef;
3325
+ this._batch = batch;
3326
+ }
3327
+ _create_class$f(WriteBatchFirestoreDocumentDataAccessor, [
3328
+ {
3329
+ key: "batch",
3330
+ get: function get() {
3331
+ return this._batch;
3332
+ }
3333
+ },
3334
+ {
3335
+ key: "stream",
3336
+ value: function stream() {
3337
+ return from(this.get()); // todo
3338
+ }
3339
+ },
3340
+ {
3341
+ key: "create",
3342
+ value: function create(data) {
3343
+ this.batch.create(this.documentRef, data);
3344
+ return Promise.resolve();
3345
+ }
3346
+ },
3347
+ {
3348
+ key: "exists",
3349
+ value: function exists() {
3350
+ return this.get().then(function(x) {
3351
+ return x.exists;
3352
+ });
3353
+ }
3354
+ },
3355
+ {
3356
+ key: "get",
3357
+ value: function get() {
3358
+ return this.documentRef.get();
3359
+ }
3360
+ },
3361
+ {
3362
+ key: "getWithConverter",
3363
+ value: function getWithConverter(converter) {
3364
+ return this.documentRef.withConverter(converter).get();
3365
+ }
3366
+ },
3367
+ {
3368
+ key: "delete",
3369
+ value: function _delete(params) {
3370
+ this.batch.delete(this.documentRef, params === null || params === void 0 ? void 0 : params.precondition);
3371
+ return Promise.resolve();
3372
+ }
3373
+ },
3374
+ {
3375
+ key: "set",
3376
+ value: function set(data) {
3377
+ this.batch.set(this.documentRef, data);
3378
+ return Promise.resolve();
3379
+ }
3380
+ },
3381
+ {
3382
+ key: "increment",
3383
+ value: function increment(data, params) {
3384
+ return this.update(firestoreServerIncrementUpdateToUpdateData(data), params);
3385
+ }
3386
+ },
3387
+ {
3388
+ key: "arrayUpdate",
3389
+ value: function arrayUpdate(data, params) {
3390
+ return this.update(firestoreServerArrayUpdateToUpdateData(data), params);
3391
+ }
3392
+ },
3393
+ {
3394
+ key: "update",
3395
+ value: function update(data, params) {
3396
+ if ((params === null || params === void 0 ? void 0 : params.precondition) != null) {
3397
+ this.batch.update(this.documentRef, data, params.precondition);
3398
+ } else {
3399
+ this.batch.update(this.documentRef, data);
3400
+ }
3401
+ return Promise.resolve();
3402
+ }
3403
+ }
3404
+ ]);
3405
+ return WriteBatchFirestoreDocumentDataAccessor;
3406
+ }();
3407
+ /**
3408
+ * Creates a {@link FirestoreDocumentDataAccessorFactory} that produces batch-backed accessors.
3409
+ *
3410
+ * All accessors created from this factory share the same {@link WriteBatch}, so committing
3411
+ * the batch applies all queued writes atomically.
3412
+ *
3413
+ * @param writeBatch - The Google Cloud WriteBatch to queue operations into.
3414
+ * @returns A factory that creates batch-backed accessors sharing the given WriteBatch.
3415
+ *
3416
+ * @example
3417
+ * ```typescript
3418
+ * const batch = firestore.batch();
3419
+ * const factory = writeBatchAccessorFactory<User>(batch);
3420
+ * const accessor = factory.accessorFor(userDocRef);
3421
+ * await accessor.set({ name: 'Alice' });
3422
+ * await batch.commit();
3423
+ * ```
3424
+ */ function writeBatchAccessorFactory(writeBatch) {
3425
+ return {
3426
+ accessorFor: function accessorFor(ref) {
3427
+ return new WriteBatchFirestoreDocumentDataAccessor(writeBatch, ref);
3428
+ }
3429
+ };
3430
+ }
3431
+ // MARK: Context
3432
+ /**
3433
+ * A {@link FirestoreDocumentContext} backed by a Google Cloud {@link WriteBatch}.
3434
+ *
3435
+ * All document accessors created from this context queue writes into the same batch.
3436
+ */ var WriteBatchFirestoreDocumentContext = /*#__PURE__*/ function() {
3437
+ function WriteBatchFirestoreDocumentContext(batch) {
3438
+ _class_call_check$o(this, WriteBatchFirestoreDocumentContext);
3439
+ _define_property$v(this, "_batch", void 0);
3440
+ _define_property$v(this, "contextType", FirestoreDocumentContextType.BATCH);
3441
+ _define_property$v(this, "accessorFactory", void 0);
3442
+ this._batch = batch;
3443
+ this.accessorFactory = writeBatchAccessorFactory(batch);
3444
+ }
3445
+ _create_class$f(WriteBatchFirestoreDocumentContext, [
3446
+ {
3447
+ key: "batch",
3448
+ get: function get() {
3449
+ return this._batch;
3450
+ }
3451
+ }
3452
+ ]);
3453
+ return WriteBatchFirestoreDocumentContext;
3454
+ }();
3455
+ /**
3456
+ * Creates a {@link WriteBatchFirestoreDocumentContext} wrapping the given batch.
3457
+ *
3458
+ * @param batch - The Google Cloud WriteBatch to use.
3459
+ * @returns A new {@link WriteBatchFirestoreDocumentContext} for the given batch.
3460
+ */ function writeBatchDocumentContext(batch) {
3461
+ return new WriteBatchFirestoreDocumentContext(batch);
3462
+ }
3463
+
3464
+ function _class_call_check$n(instance, Constructor) {
3465
+ if (!(instance instanceof Constructor)) {
3466
+ throw new TypeError("Cannot call a class as a function");
3467
+ }
3468
+ }
3469
+ function _defineProperties$e(target, props) {
3470
+ for(var i = 0; i < props.length; i++){
3471
+ var descriptor = props[i];
3472
+ descriptor.enumerable = descriptor.enumerable || false;
3473
+ descriptor.configurable = true;
3474
+ if ("value" in descriptor) descriptor.writable = true;
3475
+ Object.defineProperty(target, descriptor.key, descriptor);
3476
+ }
3477
+ }
3478
+ function _create_class$e(Constructor, protoProps, staticProps) {
3479
+ if (protoProps) _defineProperties$e(Constructor.prototype, protoProps);
3480
+ return Constructor;
3481
+ }
3482
+ function _define_property$u(obj, key, value) {
3483
+ if (key in obj) {
3484
+ Object.defineProperty(obj, key, {
3485
+ value: value,
3486
+ enumerable: true,
3487
+ configurable: true,
3488
+ writable: true
3489
+ });
3490
+ } else {
3491
+ obj[key] = value;
3492
+ }
3493
+ return obj;
3494
+ }
3495
+ // MARK: Accessor
3496
+ /**
3497
+ * Default Google Cloud Firestore implementation of {@link FirestoreDocumentDataAccessor}.
3498
+ *
3499
+ * Performs all operations directly against the Firestore document reference without
3500
+ * batching or transactional context. Supports real-time streaming via `onSnapshot`.
3501
+ */ var DefaultFirestoreDocumentDataAccessor = /*#__PURE__*/ function() {
3502
+ function DefaultFirestoreDocumentDataAccessor(documentRef) {
3503
+ _class_call_check$n(this, DefaultFirestoreDocumentDataAccessor);
3504
+ _define_property$u(this, "_documentRef", void 0);
3505
+ this._documentRef = documentRef;
3506
+ }
3507
+ _create_class$e(DefaultFirestoreDocumentDataAccessor, [
3508
+ {
3509
+ key: "documentRef",
3510
+ get: function get() {
3511
+ return this._documentRef;
3512
+ }
3513
+ },
3514
+ {
3515
+ key: "stream",
3516
+ value: function stream() {
3517
+ var _this = this;
3518
+ return streamFromOnSnapshot(function(param) {
3519
+ var next = param.next, error = param.error;
3520
+ return _this.documentRef.onSnapshot(next, error);
3521
+ });
3522
+ }
3523
+ },
3524
+ {
3525
+ key: "create",
3526
+ value: function create(data) {
3527
+ return this.documentRef.create(data);
3528
+ }
3529
+ },
3530
+ {
3531
+ key: "exists",
3532
+ value: function exists() {
3533
+ return this.get().then(function(x) {
3534
+ return x.exists;
3535
+ });
3536
+ }
3537
+ },
3538
+ {
3539
+ key: "get",
3540
+ value: function get() {
3541
+ return this.documentRef.get();
3542
+ }
3543
+ },
3544
+ {
3545
+ key: "getWithConverter",
3546
+ value: function getWithConverter(converter) {
3547
+ return this.documentRef.withConverter(converter).get();
3548
+ }
3549
+ },
3550
+ {
3551
+ key: "delete",
3552
+ value: function _delete(params) {
3553
+ return this.documentRef.delete(params === null || params === void 0 ? void 0 : params.precondition);
3554
+ }
3555
+ },
3556
+ {
3557
+ key: "set",
3558
+ value: function set(data, options) {
3559
+ return options ? this.documentRef.set(data, options) : this.documentRef.set(data);
3560
+ }
3561
+ },
3562
+ {
3563
+ key: "increment",
3564
+ value: function increment(data, params) {
3565
+ return this.update(firestoreServerIncrementUpdateToUpdateData(data), params);
3566
+ }
3567
+ },
3568
+ {
3569
+ key: "arrayUpdate",
3570
+ value: function arrayUpdate(data, params) {
3571
+ return this.update(firestoreServerArrayUpdateToUpdateData(data), params);
3572
+ }
3573
+ },
3574
+ {
3575
+ key: "update",
3576
+ value: function update(data, params) {
3577
+ return (params === null || params === void 0 ? void 0 : params.precondition) ? this.documentRef.update(data, params.precondition) : this.documentRef.update(data);
3578
+ }
3077
3579
  }
3078
- var batches = batch(pathSegments, 2); // batch to tuple [string, string]
3079
- batches.forEach(function(x) {
3080
- var _x = _sliced_to_array$3(x, 2), first = _x[0], second = _x[1];
3081
- ref = ref.doc(first).collection(second);
3082
- });
3083
- }
3084
- return ref;
3085
- }
3580
+ ]);
3581
+ return DefaultFirestoreDocumentDataAccessor;
3582
+ }();
3086
3583
  /**
3087
- * Resolves a Firestore {@link DocumentReference} from a starting point, optional document path, and additional path segments.
3088
- *
3089
- * If no path is provided, auto-generates a document ID. Supports nested subcollection
3090
- * traversal via path segment pairs.
3584
+ * Creates a {@link FirestoreDocumentDataAccessorFactory} that produces default (non-batched, non-transactional) accessors.
3091
3585
  *
3092
- * @param start - A Firestore object that can resolve document paths (e.g., CollectionReference).
3093
- * @param path - Optional document ID or path within the collection.
3094
- * @param pathSegments - Optional pairs of [collectionName, docId] for subcollection traversal.
3095
- * @returns The resolved {@link DocumentReference} at the given path.
3586
+ * @returns A factory that creates default (non-batched, non-transactional) accessors.
3096
3587
  *
3097
3588
  * @example
3098
3589
  * ```typescript
3099
- * const ref = docRefForPath<User>(usersCollection, 'user123');
3100
- * const autoRef = docRefForPath<User>(usersCollection); // auto-generated ID
3590
+ * const factory = defaultFirestoreAccessorFactory<User>();
3591
+ * const accessor = factory.accessorFor(userDocRef);
3101
3592
  * ```
3102
- */ function docRefForPath(start, path, pathSegments) {
3103
- var doc = path ? start.doc(path) : start.doc();
3104
- if (pathSegments === null || pathSegments === void 0 ? void 0 : pathSegments.length) {
3105
- var batches = batch(pathSegments, 2); // batch to tuple [string, string]
3106
- batches.forEach(function(x) {
3107
- var _x = _sliced_to_array$3(x, 2), first = _x[0], second = _x[1];
3108
- var collection = doc.collection(first);
3109
- doc = second ? collection.doc(second) : collection.doc();
3110
- });
3111
- }
3112
- return doc;
3593
+ */ function defaultFirestoreAccessorFactory() {
3594
+ return {
3595
+ accessorFor: function accessorFor(ref) {
3596
+ return new DefaultFirestoreDocumentDataAccessor(ref);
3597
+ }
3598
+ };
3113
3599
  }
3600
+ // MARK: Context
3114
3601
  /**
3115
- * Creates a {@link FirestoreAccessorDriver} for Google Cloud Firestore (Admin SDK).
3116
- *
3117
- * Implements document/collection resolution, transaction/batch factories, and context factories
3118
- * using the `@google-cloud/firestore` library.
3602
+ * Creates a {@link FirestoreDocumentContext} with no special execution context (no batch, no transaction).
3119
3603
  *
3120
- * @returns A {@link FirestoreAccessorDriver} for the Google Cloud Admin SDK.
3604
+ * Operations performed through this context execute immediately against Firestore.
3121
3605
  *
3122
- * @example
3123
- * ```typescript
3124
- * const accessorDriver = googleCloudFirestoreAccessorDriver();
3125
- * ```
3126
- */ function googleCloudFirestoreAccessorDriver() {
3606
+ * @returns A {@link FirestoreDocumentContext} for direct Firestore operations.
3607
+ */ function defaultFirestoreDocumentContext() {
3127
3608
  return {
3128
- doc: function doc(collection, path) {
3129
- for(var _len = arguments.length, pathSegments = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++){
3130
- pathSegments[_key - 2] = arguments[_key];
3131
- }
3132
- return docRefForPath(collection, path, pathSegments);
3133
- },
3134
- docAtPath: function docAtPath(firestore, fullPath) {
3135
- return firestore.doc(fullPath);
3136
- },
3137
- collectionGroup: function collectionGroup(firestore, collectionId) {
3138
- return firestore.collectionGroup(collectionId);
3139
- },
3140
- collection: function collection(firestore, path) {
3141
- for(var _len = arguments.length, pathSegments = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++){
3142
- pathSegments[_key - 2] = arguments[_key];
3143
- }
3144
- return collectionRefForPath(firestore, path, pathSegments);
3145
- },
3146
- subcollection: function subcollection(document, path) {
3147
- for(var _len = arguments.length, pathSegments = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++){
3148
- pathSegments[_key - 2] = arguments[_key];
3149
- }
3150
- return collectionRefForPath(document, path, pathSegments);
3151
- },
3152
- transactionFactoryForFirestore: function transactionFactoryForFirestore(firestore) {
3153
- return function(fn) {
3154
- return _async_to_generator$e(function() {
3155
- return _ts_generator$e(this, function(_state) {
3156
- return [
3157
- 2,
3158
- firestore.runTransaction(fn)
3159
- ];
3160
- });
3161
- })();
3162
- };
3163
- },
3164
- writeBatchFactoryForFirestore: function writeBatchFactoryForFirestore(firestore) {
3165
- return function() {
3166
- return firestore.batch();
3167
- };
3168
- },
3169
- defaultContextFactory: defaultFirestoreDocumentContext,
3170
- transactionContextFactory: transactionDocumentContext,
3171
- writeBatchContextFactory: writeBatchDocumentContext
3609
+ contextType: FirestoreDocumentContextType.NONE,
3610
+ accessorFactory: defaultFirestoreAccessorFactory()
3172
3611
  };
3173
3612
  }
3174
3613
 
3175
- function _array_like_to_array$b(arr, len) {
3176
- if (len == null || len > arr.length) len = arr.length;
3177
- for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
3178
- return arr2;
3614
+ function _class_call_check$m(instance, Constructor) {
3615
+ if (!(instance instanceof Constructor)) {
3616
+ throw new TypeError("Cannot call a class as a function");
3617
+ }
3179
3618
  }
3180
- function _array_without_holes$8(arr) {
3181
- if (Array.isArray(arr)) return _array_like_to_array$b(arr);
3619
+ function _defineProperties$d(target, props) {
3620
+ for(var i = 0; i < props.length; i++){
3621
+ var descriptor = props[i];
3622
+ descriptor.enumerable = descriptor.enumerable || false;
3623
+ descriptor.configurable = true;
3624
+ if ("value" in descriptor) descriptor.writable = true;
3625
+ Object.defineProperty(target, descriptor.key, descriptor);
3626
+ }
3182
3627
  }
3183
- function _define_property$s(obj, key, value) {
3628
+ function _create_class$d(Constructor, protoProps, staticProps) {
3629
+ if (protoProps) _defineProperties$d(Constructor.prototype, protoProps);
3630
+ return Constructor;
3631
+ }
3632
+ function _define_property$t(obj, key, value) {
3184
3633
  if (key in obj) {
3185
3634
  Object.defineProperty(obj, key, {
3186
3635
  value: value,
@@ -3193,242 +3642,173 @@ function _define_property$s(obj, key, value) {
3193
3642
  }
3194
3643
  return obj;
3195
3644
  }
3196
- function _iterable_to_array$8(iter) {
3197
- if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
3198
- }
3199
- function _non_iterable_spread$8() {
3200
- throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
3201
- }
3202
- function _object_spread$g(target) {
3203
- for(var i = 1; i < arguments.length; i++){
3204
- var source = arguments[i] != null ? arguments[i] : {};
3205
- var ownKeys = Object.keys(source);
3206
- if (typeof Object.getOwnPropertySymbols === "function") {
3207
- ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
3208
- return Object.getOwnPropertyDescriptor(source, sym).enumerable;
3209
- }));
3210
- }
3211
- ownKeys.forEach(function(key) {
3212
- _define_property$s(target, key, source[key]);
3213
- });
3214
- }
3215
- return target;
3216
- }
3217
- function ownKeys$d(object, enumerableOnly) {
3218
- var keys = Object.keys(object);
3219
- if (Object.getOwnPropertySymbols) {
3220
- var symbols = Object.getOwnPropertySymbols(object);
3221
- keys.push.apply(keys, symbols);
3222
- }
3223
- return keys;
3224
- }
3225
- function _object_spread_props$d(target, source) {
3226
- source = source != null ? source : {};
3227
- if (Object.getOwnPropertyDescriptors) {
3228
- Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
3229
- } else {
3230
- ownKeys$d(Object(source)).forEach(function(key) {
3231
- Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
3232
- });
3233
- }
3234
- return target;
3235
- }
3236
- function _to_consumable_array$8(arr) {
3237
- return _array_without_holes$8(arr) || _iterable_to_array$8(arr) || _unsupported_iterable_to_array$b(arr) || _non_iterable_spread$8();
3238
- }
3239
- function _unsupported_iterable_to_array$b(o, minLen) {
3240
- if (!o) return;
3241
- if (typeof o === "string") return _array_like_to_array$b(o, minLen);
3242
- var n = Object.prototype.toString.call(o).slice(8, -1);
3243
- if (n === "Object" && o.constructor) n = o.constructor.name;
3244
- if (n === "Map" || n === "Set") return Array.from(n);
3245
- if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$b(o, minLen);
3246
- }
3247
- var _builder, _builder1;
3248
- var _obj;
3249
- /**
3250
- * Maps each abstract query constraint type to its Google Cloud Firestore implementation.
3251
- *
3252
- * Used by {@link firestoreClientQueryConstraintFunctionsDriver} to build the server-side query driver.
3253
- */ var FIRESTORE_CLIENT_QUERY_CONSTRAINT_HANDLER_MAPPING = (_obj = {}, _define_property$s(_obj, FIRESTORE_LIMIT_QUERY_CONSTRAINT_TYPE, function(builder, data) {
3254
- return builder.limit(data.limit);
3255
- }), _define_property$s(_obj, FIRESTORE_LIMIT_TO_LAST_QUERY_CONSTRAINT_TYPE, function(builder, data) {
3256
- return builder.limitToLast(data.limit);
3257
- }), _define_property$s(_obj, FIRESTORE_ORDER_BY_QUERY_CONSTRAINT_TYPE, function(builder, data) {
3258
- return builder.orderBy(data.fieldPath, data.directionStr);
3259
- }), _define_property$s(_obj, FIRESTORE_ORDER_BY_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE, function(builder, data) {
3260
- return builder.orderBy(FieldPath.documentId(), data.directionStr);
3261
- }), _define_property$s(_obj, FIRESTORE_WHERE_QUERY_CONSTRAINT_TYPE, function(builder, data) {
3262
- return builder.where(data.fieldPath, data.opStr, data.value);
3263
- }), _define_property$s(_obj, FIRESTORE_WHERE_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE, function(builder, data) {
3264
- return builder.where(FieldPath.documentId(), data.opStr, data.value);
3265
- }), _define_property$s(_obj, FIRESTORE_OFFSET_QUERY_CONSTRAINT_TYPE, function(builder, data) {
3266
- return builder.offset(data.offset);
3267
- }), _define_property$s(_obj, FIRESTORE_START_AT_QUERY_CONSTRAINT_TYPE, function(builder, data) {
3268
- return builder.startAt(data.snapshot);
3269
- }), _define_property$s(_obj, FIRESTORE_START_AT_VALUE_QUERY_CONSTRAINT_TYPE, function(builder, data) {
3270
- return (_builder = builder).startAt.apply(_builder, _to_consumable_array$8(data.fieldValues));
3271
- }), _define_property$s(_obj, FIRESTORE_START_AFTER_QUERY_CONSTRAINT_TYPE, function(builder, data) {
3272
- return builder.startAfter(data.snapshot);
3273
- }), _define_property$s(_obj, FIRESTORE_END_AT_QUERY_CONSTRAINT_TYPE, function(builder, data) {
3274
- return builder.endAt(data.snapshot);
3275
- }), _define_property$s(_obj, FIRESTORE_END_AT_VALUE_QUERY_CONSTRAINT_TYPE, function(builder, data) {
3276
- return (_builder1 = builder).endAt.apply(_builder1, _to_consumable_array$8(data.fieldValues));
3277
- }), _define_property$s(_obj, FIRESTORE_END_BEFORE_QUERY_CONSTRAINT_TYPE, function(builder, data) {
3278
- return builder.endBefore(data.snapshot);
3279
- }), _obj);
3645
+ // MARK: Accessor
3280
3646
  /**
3281
- * Creates a {@link FirestoreQueryConstraintFunctionsDriver} for the Google Cloud Firestore server SDK.
3282
- *
3283
- * Translates abstract query constraints into Google Cloud Firestore query builder calls.
3647
+ * Google Cloud Firestore implementation of {@link FirestoreDocumentDataAccessor} that executes
3648
+ * all operations within a Firestore {@link Transaction}.
3284
3649
  *
3285
- * @returns A {@link FirestoreQueryConstraintFunctionsDriver} for the server SDK.
3286
- */ function firestoreClientQueryConstraintFunctionsDriver() {
3287
- return makeFirestoreQueryConstraintFunctionsDriver({
3288
- mapping: FIRESTORE_CLIENT_QUERY_CONSTRAINT_HANDLER_MAPPING,
3289
- init: function init(query) {
3290
- return query;
3650
+ * Reads performed through this accessor are included in the transaction's read set, ensuring
3651
+ * consistency. Writes are committed atomically when the transaction completes.
3652
+ */ var TransactionFirestoreDocumentDataAccessor = /*#__PURE__*/ function() {
3653
+ function TransactionFirestoreDocumentDataAccessor(transaction, documentRef) {
3654
+ _class_call_check$m(this, TransactionFirestoreDocumentDataAccessor);
3655
+ _define_property$t(this, "_transaction", void 0);
3656
+ _define_property$t(this, "_documentRef", void 0);
3657
+ this._transaction = transaction;
3658
+ this._documentRef = documentRef;
3659
+ }
3660
+ _create_class$d(TransactionFirestoreDocumentDataAccessor, [
3661
+ {
3662
+ key: "transaction",
3663
+ get: function get() {
3664
+ return this._transaction;
3665
+ }
3666
+ },
3667
+ {
3668
+ key: "documentRef",
3669
+ get: function get() {
3670
+ return this._documentRef;
3671
+ }
3672
+ },
3673
+ {
3674
+ key: "stream",
3675
+ value: function stream() {
3676
+ return from(this.get());
3677
+ }
3678
+ },
3679
+ {
3680
+ key: "create",
3681
+ value: function create(data) {
3682
+ this.transaction.create(this.documentRef, data);
3683
+ return Promise.resolve();
3684
+ }
3291
3685
  },
3292
- build: function build(query) {
3293
- return query;
3686
+ {
3687
+ key: "exists",
3688
+ value: function exists() {
3689
+ return this.get().then(function(x) {
3690
+ return x.exists;
3691
+ });
3692
+ }
3294
3693
  },
3295
- documentIdFieldPath: function documentIdFieldPath() {
3296
- return FieldPath.documentId();
3297
- }
3298
- });
3299
- }
3300
- /**
3301
- * Creates a complete {@link FirestoreQueryDriver} for Google Cloud Firestore (Admin SDK).
3302
- *
3303
- * Supports query execution (getDocs), document counting (countDocs), and real-time
3304
- * streaming (streamDocs) via `onSnapshot`. Transaction-aware reads are supported
3305
- * through the optional transaction parameter in `getDocs`.
3306
- *
3307
- * @returns A complete {@link FirestoreQueryDriver} for the Google Cloud Admin SDK.
3308
- *
3309
- * @example
3310
- * ```typescript
3311
- * const queryDriver = googleCloudFirestoreQueryDriver();
3312
- * ```
3313
- */ function googleCloudFirestoreQueryDriver() {
3314
- return _object_spread_props$d(_object_spread$g({}, firestoreClientQueryConstraintFunctionsDriver()), {
3315
- countDocs: function countDocs(query) {
3316
- return query.count().get().then(function(x) {
3317
- return x.data().count;
3318
- });
3694
+ {
3695
+ key: "get",
3696
+ value: function get() {
3697
+ return this.transaction.get(this.documentRef);
3698
+ }
3319
3699
  },
3320
- getDocs: function getDocs(query, transaction) {
3321
- var result;
3322
- if (transaction) {
3323
- result = transaction.get(query);
3324
- } else {
3325
- result = query.get();
3700
+ {
3701
+ key: "getWithConverter",
3702
+ value: function getWithConverter(converter) {
3703
+ return this.transaction.get(this.documentRef.withConverter(converter));
3326
3704
  }
3327
- return result;
3328
3705
  },
3329
- streamDocs: function streamDocs(query) {
3330
- return streamFromOnSnapshot(function(param) {
3331
- var next = param.next, error = param.error;
3332
- return query.onSnapshot(next, error);
3333
- });
3706
+ {
3707
+ key: "delete",
3708
+ value: function _delete() {
3709
+ this.transaction.delete(this.documentRef);
3710
+ return Promise.resolve();
3711
+ }
3712
+ },
3713
+ {
3714
+ key: "set",
3715
+ value: function set(data, options) {
3716
+ this.transaction.set(this.documentRef, data, options);
3717
+ return Promise.resolve();
3718
+ }
3719
+ },
3720
+ {
3721
+ key: "increment",
3722
+ value: function increment(data, params) {
3723
+ return this.update(firestoreServerIncrementUpdateToUpdateData(data), params);
3724
+ }
3725
+ },
3726
+ {
3727
+ key: "arrayUpdate",
3728
+ value: function arrayUpdate(data, params) {
3729
+ return this.update(firestoreServerArrayUpdateToUpdateData(data), params);
3730
+ }
3731
+ },
3732
+ {
3733
+ key: "update",
3734
+ value: function update(data, params) {
3735
+ if (params === null || params === void 0 ? void 0 : params.precondition) {
3736
+ this.transaction.update(this.documentRef, data, params.precondition);
3737
+ } else {
3738
+ this.transaction.update(this.documentRef, data);
3739
+ }
3740
+ return Promise.resolve();
3741
+ }
3334
3742
  }
3335
- });
3336
- }
3337
-
3743
+ ]);
3744
+ return TransactionFirestoreDocumentDataAccessor;
3745
+ }();
3338
3746
  /**
3339
- * Creates a complete set of {@link FirestoreDrivers} for Google Cloud Firestore (Admin SDK).
3747
+ * Creates a {@link FirestoreDocumentDataAccessorFactory} that produces transaction-backed accessors.
3340
3748
  *
3341
- * Bundles the server-side accessor driver and query driver, identified as `@google-cloud/firestore`.
3749
+ * All accessors share the same transaction, so reads and writes participate in the same
3750
+ * atomic operation.
3342
3751
  *
3343
- * @returns A complete set of {@link FirestoreDrivers} for the Google Cloud Admin SDK.
3752
+ * @param transaction - The Google Cloud Transaction to execute operations within.
3753
+ * @returns A factory that creates transaction-backed accessors sharing the given transaction.
3344
3754
  *
3345
3755
  * @example
3346
3756
  * ```typescript
3347
- * const drivers = googleCloudFirestoreDrivers();
3348
- * const context = firestoreContextFactory(drivers);
3757
+ * await firestore.runTransaction(async (transaction) => {
3758
+ * const factory = transactionAccessorFactory<User>(transaction);
3759
+ * const accessor = factory.accessorFor(userDocRef);
3760
+ * const snapshot = await accessor.get();
3761
+ * await accessor.update({ name: 'Updated' });
3762
+ * });
3349
3763
  * ```
3350
- */ function googleCloudFirestoreDrivers() {
3764
+ */ function transactionAccessorFactory(transaction) {
3351
3765
  return {
3352
- firestoreDriverIdentifier: '@google-cloud/firestore',
3353
- firestoreDriverType: 'production',
3354
- firestoreAccessorDriver: googleCloudFirestoreAccessorDriver(),
3355
- firestoreQueryDriver: googleCloudFirestoreQueryDriver()
3766
+ accessorFor: function accessorFor(ref) {
3767
+ return new TransactionFirestoreDocumentDataAccessor(transaction, ref);
3768
+ }
3356
3769
  };
3357
3770
  }
3358
-
3359
- /**
3360
- * Pre-configured {@link FirestoreContextFactory} for Google Cloud Firestore (Admin SDK) usage.
3361
- *
3362
- * Wires the server-side Firestore drivers into the abstract {@link FirestoreContextFactory}
3363
- * so that collections, documents, queries, and transactions all use the Admin SDK implementation.
3364
- *
3365
- * @example
3366
- * ```ts
3367
- * const context = googleCloudFirestoreContextFactory(firestore);
3368
- * ```
3369
- */ var googleCloudFirestoreContextFactory = firestoreContextFactory(googleCloudFirestoreDrivers());
3370
-
3371
- // MARK: Field Converters
3771
+ // MARK: Context
3372
3772
  /**
3373
- * Creates a Firestore field mapping that encrypts/decrypts a JSON-serializable value
3374
- * using AES-256-GCM. The value is stored in Firestore as a base64-encoded string.
3375
- *
3376
- * The encryption key is resolved from the configured secret source on each read/write,
3377
- * allowing for key rotation via environment variable changes.
3378
- *
3379
- * @example
3380
- * ```typescript
3381
- * const jwksField = firestoreEncryptedField<JWKSet>({
3382
- * secret: process.env['FIRESTORE_ENCRYPTION_KEY']!,
3383
- * default: () => ({ keys: [] })
3384
- * });
3385
- * ```
3773
+ * A {@link FirestoreDocumentContext} backed by a Google Cloud {@link Transaction}.
3386
3774
  *
3387
- * @template T - The JSON-serializable value type.
3388
- * @param config - Encryption field configuration.
3389
- * @returns A field mapping configuration for encrypted values.
3390
- */ function firestoreEncryptedField(config) {
3391
- var secret = config.secret, defaultValue = config.default;
3392
- var getKey = resolveEncryptionKey(secret);
3393
- return firestoreField({
3394
- default: defaultValue,
3395
- fromData: function fromData(data) {
3396
- return decryptValue(data, getKey());
3397
- },
3398
- toData: function toData(value) {
3399
- return encryptValue(value, getKey());
3775
+ * All document accessors created from this context operate within the same transaction.
3776
+ */ var TransactionFirestoreDocumentContext = /*#__PURE__*/ function() {
3777
+ function TransactionFirestoreDocumentContext(transaction) {
3778
+ _class_call_check$m(this, TransactionFirestoreDocumentContext);
3779
+ _define_property$t(this, "_transaction", void 0);
3780
+ _define_property$t(this, "contextType", FirestoreDocumentContextType.TRANSACTION);
3781
+ _define_property$t(this, "accessorFactory", void 0);
3782
+ this._transaction = transaction;
3783
+ this.accessorFactory = transactionAccessorFactory(transaction);
3784
+ }
3785
+ _create_class$d(TransactionFirestoreDocumentContext, [
3786
+ {
3787
+ key: "transaction",
3788
+ get: function get() {
3789
+ return this._transaction;
3790
+ }
3400
3791
  }
3401
- });
3402
- }
3792
+ ]);
3793
+ return TransactionFirestoreDocumentContext;
3794
+ }();
3403
3795
  /**
3404
- * Creates a Firestore field mapping for an optional encrypted field.
3405
- *
3406
- * When the value is null/undefined, it is stored/read as null. When present, it is
3407
- * encrypted/decrypted using AES-256-GCM.
3408
- *
3409
- * @example
3410
- * ```typescript
3411
- * const optionalSecretField = optionalFirestoreEncryptedField<OAuthClientSecret>({
3412
- * secret: process.env['FIRESTORE_ENCRYPTION_KEY']!
3413
- * });
3414
- * ```
3796
+ * Creates a {@link TransactionFirestoreDocumentContext} wrapping the given transaction.
3415
3797
  *
3416
- * @template T - The JSON-serializable value type.
3417
- * @param config - Encryption field configuration.
3418
- * @returns A field mapping configuration for optional encrypted values.
3419
- */ function optionalFirestoreEncryptedField(config) {
3420
- var secret = config.secret;
3421
- var getKey = resolveEncryptionKey(secret);
3422
- return optionalFirestoreField({
3423
- transformFromData: function transformFromData(data) {
3424
- return decryptValue(data, getKey());
3425
- },
3426
- transformToData: function transformToData(value) {
3427
- return encryptValue(value, getKey());
3428
- }
3429
- });
3798
+ * @param transaction - The Google Cloud Transaction to use.
3799
+ * @returns A new {@link TransactionFirestoreDocumentContext} for the given transaction.
3800
+ */ function transactionDocumentContext(transaction) {
3801
+ return new TransactionFirestoreDocumentContext(transaction);
3430
3802
  }
3431
3803
 
3804
+ function _array_like_to_array$c(arr, len) {
3805
+ if (len == null || len > arr.length) len = arr.length;
3806
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
3807
+ return arr2;
3808
+ }
3809
+ function _array_with_holes$3(arr) {
3810
+ if (Array.isArray(arr)) return arr;
3811
+ }
3432
3812
  function asyncGeneratorStep$d(gen, resolve, reject, _next, _throw, key, arg) {
3433
3813
  try {
3434
3814
  var info = gen[key](arg);
@@ -3443,20 +3823,58 @@ function asyncGeneratorStep$d(gen, resolve, reject, _next, _throw, key, arg) {
3443
3823
  Promise.resolve(value).then(_next, _throw);
3444
3824
  }
3445
3825
  }
3446
- function _async_to_generator$d(fn) {
3447
- return function() {
3448
- var self = this, args = arguments;
3449
- return new Promise(function(resolve, reject) {
3450
- var gen = fn.apply(self, args);
3451
- function _next(value) {
3452
- asyncGeneratorStep$d(gen, resolve, reject, _next, _throw, "next", value);
3453
- }
3454
- function _throw(err) {
3455
- asyncGeneratorStep$d(gen, resolve, reject, _next, _throw, "throw", err);
3456
- }
3457
- _next(undefined);
3458
- });
3459
- };
3826
+ function _async_to_generator$d(fn) {
3827
+ return function() {
3828
+ var self = this, args = arguments;
3829
+ return new Promise(function(resolve, reject) {
3830
+ var gen = fn.apply(self, args);
3831
+ function _next(value) {
3832
+ asyncGeneratorStep$d(gen, resolve, reject, _next, _throw, "next", value);
3833
+ }
3834
+ function _throw(err) {
3835
+ asyncGeneratorStep$d(gen, resolve, reject, _next, _throw, "throw", err);
3836
+ }
3837
+ _next(undefined);
3838
+ });
3839
+ };
3840
+ }
3841
+ function _iterable_to_array_limit$3(arr, i) {
3842
+ var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
3843
+ if (_i == null) return;
3844
+ var _arr = [];
3845
+ var _n = true;
3846
+ var _d = false;
3847
+ var _s, _e;
3848
+ try {
3849
+ for(_i = _i.call(arr); !(_n = (_s = _i.next()).done); _n = true){
3850
+ _arr.push(_s.value);
3851
+ if (i && _arr.length === i) break;
3852
+ }
3853
+ } catch (err) {
3854
+ _d = true;
3855
+ _e = err;
3856
+ } finally{
3857
+ try {
3858
+ if (!_n && _i["return"] != null) _i["return"]();
3859
+ } finally{
3860
+ if (_d) throw _e;
3861
+ }
3862
+ }
3863
+ return _arr;
3864
+ }
3865
+ function _non_iterable_rest$3() {
3866
+ throw new TypeError("Invalid attempt to destructure non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
3867
+ }
3868
+ function _sliced_to_array$3(arr, i) {
3869
+ return _array_with_holes$3(arr) || _iterable_to_array_limit$3(arr, i) || _unsupported_iterable_to_array$c(arr, i) || _non_iterable_rest$3();
3870
+ }
3871
+ function _unsupported_iterable_to_array$c(o, minLen) {
3872
+ if (!o) return;
3873
+ if (typeof o === "string") return _array_like_to_array$c(o, minLen);
3874
+ var n = Object.prototype.toString.call(o).slice(8, -1);
3875
+ if (n === "Object" && o.constructor) n = o.constructor.name;
3876
+ if (n === "Map" || n === "Set") return Array.from(n);
3877
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$c(o, minLen);
3460
3878
  }
3461
3879
  function _ts_generator$d(thisArg, body) {
3462
3880
  var f, y, t, _ = {
@@ -3550,166 +3968,385 @@ function _ts_generator$d(thisArg, body) {
3550
3968
  } finally{
3551
3969
  f = t = 0;
3552
3970
  }
3553
- if (op[0] & 5) throw op[1];
3554
- return {
3555
- value: op[0] ? op[1] : void 0,
3556
- done: true
3557
- };
3558
- }
3971
+ if (op[0] & 5) throw op[1];
3972
+ return {
3973
+ value: op[0] ? op[1] : void 0,
3974
+ done: true
3975
+ };
3976
+ }
3977
+ }
3978
+ /**
3979
+ * Resolves a Firestore {@link CollectionReference} from a starting point and optional additional path segments.
3980
+ *
3981
+ * Supports nested subcollection paths by processing segments in pairs (doc ID, collection name).
3982
+ *
3983
+ * @param start - A Firestore object that can resolve collection paths (e.g., Firestore instance, DocumentReference).
3984
+ * @param path - The initial collection path.
3985
+ * @param pathSegments - Optional pairs of [docId, collectionName] for subcollection traversal.
3986
+ * @returns The resolved {@link CollectionReference} at the given path.
3987
+ * @throws Error if pathSegments length is odd (segments must come in pairs).
3988
+ *
3989
+ * @example
3990
+ * ```typescript
3991
+ * const ref = collectionRefForPath<User>(firestore, 'users');
3992
+ * const subRef = collectionRefForPath<Comment>(firestore, 'users', ['user123', 'comments']);
3993
+ * ```
3994
+ */ function collectionRefForPath(start, path, pathSegments) {
3995
+ var ref = start.collection(path);
3996
+ if (pathSegments === null || pathSegments === void 0 ? void 0 : pathSegments.length) {
3997
+ if (pathSegments.length % 2 !== 0) {
3998
+ throw new Error('Invalid number of path segments provided for collection. Path: "'.concat(path, '" + "').concat(pathSegments, '"'));
3999
+ }
4000
+ var batches = batch(pathSegments, 2); // batch to tuple [string, string]
4001
+ batches.forEach(function(x) {
4002
+ var _x = _sliced_to_array$3(x, 2), first = _x[0], second = _x[1];
4003
+ ref = ref.doc(first).collection(second);
4004
+ });
4005
+ }
4006
+ return ref;
4007
+ }
4008
+ /**
4009
+ * Resolves a Firestore {@link DocumentReference} from a starting point, optional document path, and additional path segments.
4010
+ *
4011
+ * If no path is provided, auto-generates a document ID. Supports nested subcollection
4012
+ * traversal via path segment pairs.
4013
+ *
4014
+ * @param start - A Firestore object that can resolve document paths (e.g., CollectionReference).
4015
+ * @param path - Optional document ID or path within the collection.
4016
+ * @param pathSegments - Optional pairs of [collectionName, docId] for subcollection traversal.
4017
+ * @returns The resolved {@link DocumentReference} at the given path.
4018
+ *
4019
+ * @example
4020
+ * ```typescript
4021
+ * const ref = docRefForPath<User>(usersCollection, 'user123');
4022
+ * const autoRef = docRefForPath<User>(usersCollection); // auto-generated ID
4023
+ * ```
4024
+ */ function docRefForPath(start, path, pathSegments) {
4025
+ var doc = path ? start.doc(path) : start.doc();
4026
+ if (pathSegments === null || pathSegments === void 0 ? void 0 : pathSegments.length) {
4027
+ var batches = batch(pathSegments, 2); // batch to tuple [string, string]
4028
+ batches.forEach(function(x) {
4029
+ var _x = _sliced_to_array$3(x, 2), first = _x[0], second = _x[1];
4030
+ var collection = doc.collection(first);
4031
+ doc = second ? collection.doc(second) : collection.doc();
4032
+ });
4033
+ }
4034
+ return doc;
4035
+ }
4036
+ /**
4037
+ * Creates a {@link FirestoreAccessorDriver} for Google Cloud Firestore (Admin SDK).
4038
+ *
4039
+ * Implements document/collection resolution, transaction/batch factories, and context factories
4040
+ * using the `@google-cloud/firestore` library.
4041
+ *
4042
+ * @returns A {@link FirestoreAccessorDriver} for the Google Cloud Admin SDK.
4043
+ *
4044
+ * @example
4045
+ * ```typescript
4046
+ * const accessorDriver = googleCloudFirestoreAccessorDriver();
4047
+ * ```
4048
+ */ function googleCloudFirestoreAccessorDriver() {
4049
+ return {
4050
+ doc: function doc(collection, path) {
4051
+ for(var _len = arguments.length, pathSegments = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++){
4052
+ pathSegments[_key - 2] = arguments[_key];
4053
+ }
4054
+ return docRefForPath(collection, path, pathSegments);
4055
+ },
4056
+ docAtPath: function docAtPath(firestore, fullPath) {
4057
+ return firestore.doc(fullPath);
4058
+ },
4059
+ collectionGroup: function collectionGroup(firestore, collectionId) {
4060
+ return firestore.collectionGroup(collectionId);
4061
+ },
4062
+ collection: function collection(firestore, path) {
4063
+ for(var _len = arguments.length, pathSegments = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++){
4064
+ pathSegments[_key - 2] = arguments[_key];
4065
+ }
4066
+ return collectionRefForPath(firestore, path, pathSegments);
4067
+ },
4068
+ subcollection: function subcollection(document, path) {
4069
+ for(var _len = arguments.length, pathSegments = new Array(_len > 2 ? _len - 2 : 0), _key = 2; _key < _len; _key++){
4070
+ pathSegments[_key - 2] = arguments[_key];
4071
+ }
4072
+ return collectionRefForPath(document, path, pathSegments);
4073
+ },
4074
+ transactionFactoryForFirestore: function transactionFactoryForFirestore(firestore) {
4075
+ return function(fn) {
4076
+ return _async_to_generator$d(function() {
4077
+ return _ts_generator$d(this, function(_state) {
4078
+ return [
4079
+ 2,
4080
+ firestore.runTransaction(fn)
4081
+ ];
4082
+ });
4083
+ })();
4084
+ };
4085
+ },
4086
+ writeBatchFactoryForFirestore: function writeBatchFactoryForFirestore(firestore) {
4087
+ return function() {
4088
+ return firestore.batch();
4089
+ };
4090
+ },
4091
+ defaultContextFactory: defaultFirestoreDocumentContext,
4092
+ transactionContextFactory: transactionDocumentContext,
4093
+ writeBatchContextFactory: writeBatchDocumentContext
4094
+ };
4095
+ }
4096
+
4097
+ function _array_like_to_array$b(arr, len) {
4098
+ if (len == null || len > arr.length) len = arr.length;
4099
+ for(var i = 0, arr2 = new Array(len); i < len; i++)arr2[i] = arr[i];
4100
+ return arr2;
4101
+ }
4102
+ function _array_without_holes$8(arr) {
4103
+ if (Array.isArray(arr)) return _array_like_to_array$b(arr);
4104
+ }
4105
+ function _define_property$s(obj, key, value) {
4106
+ if (key in obj) {
4107
+ Object.defineProperty(obj, key, {
4108
+ value: value,
4109
+ enumerable: true,
4110
+ configurable: true,
4111
+ writable: true
4112
+ });
4113
+ } else {
4114
+ obj[key] = value;
4115
+ }
4116
+ return obj;
4117
+ }
4118
+ function _iterable_to_array$8(iter) {
4119
+ if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter);
4120
+ }
4121
+ function _non_iterable_spread$8() {
4122
+ throw new TypeError("Invalid attempt to spread non-iterable instance.\\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.");
4123
+ }
4124
+ function _object_spread$g(target) {
4125
+ for(var i = 1; i < arguments.length; i++){
4126
+ var source = arguments[i] != null ? arguments[i] : {};
4127
+ var ownKeys = Object.keys(source);
4128
+ if (typeof Object.getOwnPropertySymbols === "function") {
4129
+ ownKeys = ownKeys.concat(Object.getOwnPropertySymbols(source).filter(function(sym) {
4130
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
4131
+ }));
4132
+ }
4133
+ ownKeys.forEach(function(key) {
4134
+ _define_property$s(target, key, source[key]);
4135
+ });
4136
+ }
4137
+ return target;
4138
+ }
4139
+ function ownKeys$d(object, enumerableOnly) {
4140
+ var keys = Object.keys(object);
4141
+ if (Object.getOwnPropertySymbols) {
4142
+ var symbols = Object.getOwnPropertySymbols(object);
4143
+ keys.push.apply(keys, symbols);
4144
+ }
4145
+ return keys;
4146
+ }
4147
+ function _object_spread_props$d(target, source) {
4148
+ source = source != null ? source : {};
4149
+ if (Object.getOwnPropertyDescriptors) {
4150
+ Object.defineProperties(target, Object.getOwnPropertyDescriptors(source));
4151
+ } else {
4152
+ ownKeys$d(Object(source)).forEach(function(key) {
4153
+ Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key));
4154
+ });
4155
+ }
4156
+ return target;
4157
+ }
4158
+ function _to_consumable_array$8(arr) {
4159
+ return _array_without_holes$8(arr) || _iterable_to_array$8(arr) || _unsupported_iterable_to_array$b(arr) || _non_iterable_spread$8();
4160
+ }
4161
+ function _unsupported_iterable_to_array$b(o, minLen) {
4162
+ if (!o) return;
4163
+ if (typeof o === "string") return _array_like_to_array$b(o, minLen);
4164
+ var n = Object.prototype.toString.call(o).slice(8, -1);
4165
+ if (n === "Object" && o.constructor) n = o.constructor.name;
4166
+ if (n === "Map" || n === "Set") return Array.from(n);
4167
+ if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _array_like_to_array$b(o, minLen);
4168
+ }
4169
+ var _builder, _builder1;
4170
+ var _obj;
4171
+ /**
4172
+ * Maps each abstract query constraint type to its Google Cloud Firestore implementation.
4173
+ *
4174
+ * Used by {@link firestoreClientQueryConstraintFunctionsDriver} to build the server-side query driver.
4175
+ */ var FIRESTORE_CLIENT_QUERY_CONSTRAINT_HANDLER_MAPPING = (_obj = {}, _define_property$s(_obj, FIRESTORE_LIMIT_QUERY_CONSTRAINT_TYPE, function(builder, data) {
4176
+ return builder.limit(data.limit);
4177
+ }), _define_property$s(_obj, FIRESTORE_LIMIT_TO_LAST_QUERY_CONSTRAINT_TYPE, function(builder, data) {
4178
+ return builder.limitToLast(data.limit);
4179
+ }), _define_property$s(_obj, FIRESTORE_ORDER_BY_QUERY_CONSTRAINT_TYPE, function(builder, data) {
4180
+ return builder.orderBy(data.fieldPath, data.directionStr);
4181
+ }), _define_property$s(_obj, FIRESTORE_ORDER_BY_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE, function(builder, data) {
4182
+ return builder.orderBy(FieldPath.documentId(), data.directionStr);
4183
+ }), _define_property$s(_obj, FIRESTORE_WHERE_QUERY_CONSTRAINT_TYPE, function(builder, data) {
4184
+ return builder.where(data.fieldPath, data.opStr, data.value);
4185
+ }), _define_property$s(_obj, FIRESTORE_WHERE_DOCUMENT_ID_QUERY_CONSTRAINT_TYPE, function(builder, data) {
4186
+ return builder.where(FieldPath.documentId(), data.opStr, data.value);
4187
+ }), _define_property$s(_obj, FIRESTORE_OFFSET_QUERY_CONSTRAINT_TYPE, function(builder, data) {
4188
+ return builder.offset(data.offset);
4189
+ }), _define_property$s(_obj, FIRESTORE_START_AT_QUERY_CONSTRAINT_TYPE, function(builder, data) {
4190
+ return builder.startAt(data.snapshot);
4191
+ }), _define_property$s(_obj, FIRESTORE_START_AT_VALUE_QUERY_CONSTRAINT_TYPE, function(builder, data) {
4192
+ return (_builder = builder).startAt.apply(_builder, _to_consumable_array$8(data.fieldValues));
4193
+ }), _define_property$s(_obj, FIRESTORE_START_AFTER_QUERY_CONSTRAINT_TYPE, function(builder, data) {
4194
+ return builder.startAfter(data.snapshot);
4195
+ }), _define_property$s(_obj, FIRESTORE_END_AT_QUERY_CONSTRAINT_TYPE, function(builder, data) {
4196
+ return builder.endAt(data.snapshot);
4197
+ }), _define_property$s(_obj, FIRESTORE_END_AT_VALUE_QUERY_CONSTRAINT_TYPE, function(builder, data) {
4198
+ return (_builder1 = builder).endAt.apply(_builder1, _to_consumable_array$8(data.fieldValues));
4199
+ }), _define_property$s(_obj, FIRESTORE_END_BEFORE_QUERY_CONSTRAINT_TYPE, function(builder, data) {
4200
+ return builder.endBefore(data.snapshot);
4201
+ }), _obj);
4202
+ /**
4203
+ * Creates a {@link FirestoreQueryConstraintFunctionsDriver} for the Google Cloud Firestore server SDK.
4204
+ *
4205
+ * Translates abstract query constraints into Google Cloud Firestore query builder calls.
4206
+ *
4207
+ * @returns A {@link FirestoreQueryConstraintFunctionsDriver} for the server SDK.
4208
+ */ function firestoreClientQueryConstraintFunctionsDriver() {
4209
+ return makeFirestoreQueryConstraintFunctionsDriver({
4210
+ mapping: FIRESTORE_CLIENT_QUERY_CONSTRAINT_HANDLER_MAPPING,
4211
+ init: function init(query) {
4212
+ return query;
4213
+ },
4214
+ build: function build(query) {
4215
+ return query;
4216
+ },
4217
+ documentIdFieldPath: function documentIdFieldPath() {
4218
+ return FieldPath.documentId();
4219
+ }
4220
+ });
3559
4221
  }
3560
4222
  /**
3561
- * Asserts that the callable context contains auth data with a valid UID.
4223
+ * Creates a complete {@link FirestoreQueryDriver} for Google Cloud Firestore (Admin SDK).
3562
4224
  *
3563
- * @param context - The callable context to check for auth data.
3564
- * @throws {HttpsError} Throws unauthenticated error if no auth data is present.
4225
+ * Supports query execution (getDocs), document counting (countDocs), and real-time
4226
+ * streaming (streamDocs) via `onSnapshot`. Transaction-aware reads are supported
4227
+ * through the optional transaction parameter in `getDocs`.
4228
+ *
4229
+ * @returns A complete {@link FirestoreQueryDriver} for the Google Cloud Admin SDK.
3565
4230
  *
3566
4231
  * @example
3567
4232
  * ```typescript
3568
- * assertContextHasAuth(context);
3569
- * // Safe to access context.auth.uid
4233
+ * const queryDriver = googleCloudFirestoreQueryDriver();
3570
4234
  * ```
3571
- */ function assertContextHasAuth(context) {
3572
- if (!isContextWithAuthData(context)) {
3573
- throw unauthenticatedContextHasNoUidError();
3574
- }
4235
+ */ function googleCloudFirestoreQueryDriver() {
4236
+ return _object_spread_props$d(_object_spread$g({}, firestoreClientQueryConstraintFunctionsDriver()), {
4237
+ countDocs: function countDocs(query) {
4238
+ return query.count().get().then(function(x) {
4239
+ return x.data().count;
4240
+ });
4241
+ },
4242
+ getDocs: function getDocs(query, transaction) {
4243
+ var result;
4244
+ if (transaction) {
4245
+ result = transaction.get(query);
4246
+ } else {
4247
+ result = query.get();
4248
+ }
4249
+ return result;
4250
+ },
4251
+ streamDocs: function streamDocs(query) {
4252
+ return streamFromOnSnapshot(function(param) {
4253
+ var next = param.next, error = param.error;
4254
+ return query.onSnapshot(next, error);
4255
+ });
4256
+ }
4257
+ });
3575
4258
  }
4259
+
3576
4260
  /**
3577
- * Loads the snapshot data from a Firestore document, throwing if the document does not exist.
4261
+ * Creates a complete set of {@link FirestoreDrivers} for Google Cloud Firestore (Admin SDK).
3578
4262
  *
3579
- * @param document - The Firestore document to load data from.
3580
- * @param message - Optional custom error message.
3581
- * @returns The document's snapshot data.
3582
- * @throws {HttpsError} Throws a {@link modelNotAvailableError} (404) if the document has no data.
4263
+ * Bundles the server-side accessor driver and query driver, identified as `@google-cloud/firestore`.
4264
+ *
4265
+ * @returns A complete set of {@link FirestoreDrivers} for the Google Cloud Admin SDK.
3583
4266
  *
3584
4267
  * @example
3585
4268
  * ```typescript
3586
- * const userData = await assertSnapshotData(userDocument);
4269
+ * const drivers = googleCloudFirestoreDrivers();
4270
+ * const context = firestoreContextFactory(drivers);
3587
4271
  * ```
3588
- */ function assertSnapshotData(document, message) {
3589
- return _async_to_generator$d(function() {
3590
- var data;
3591
- return _ts_generator$d(this, function(_state) {
3592
- switch(_state.label){
3593
- case 0:
3594
- return [
3595
- 4,
3596
- document.snapshotData()
3597
- ];
3598
- case 1:
3599
- data = _state.sent();
3600
- if (data == null) {
3601
- throw modelNotAvailableError({
3602
- message: message !== null && message !== void 0 ? message : "The ".concat(document.modelType, " was unavailable.")
3603
- });
3604
- }
3605
- return [
3606
- 2,
3607
- data
3608
- ];
3609
- }
3610
- });
3611
- })();
4272
+ */ function googleCloudFirestoreDrivers() {
4273
+ return {
4274
+ firestoreDriverIdentifier: '@google-cloud/firestore',
4275
+ firestoreDriverType: 'production',
4276
+ firestoreAccessorDriver: googleCloudFirestoreAccessorDriver(),
4277
+ firestoreQueryDriver: googleCloudFirestoreQueryDriver()
4278
+ };
3612
4279
  }
4280
+
3613
4281
  /**
3614
- * Loads snapshot data and attaches the document's `id` and `key` to the result.
4282
+ * Pre-configured {@link FirestoreContextFactory} for Google Cloud Firestore (Admin SDK) usage.
3615
4283
  *
3616
- * Combines {@link assertSnapshotData} with {@link setIdAndKeyFromKeyIdRefOnDocumentData}.
4284
+ * Wires the server-side Firestore drivers into the abstract {@link FirestoreContextFactory}
4285
+ * so that collections, documents, queries, and transactions all use the Admin SDK implementation.
3617
4286
  *
3618
- * @param document - The Firestore document to load data from.
3619
- * @param message - Optional custom error message.
3620
- * @returns The document's snapshot data with `id` and `key` attached.
3621
- * @throws {HttpsError} Throws a {@link modelNotAvailableError} (404) if the document has no data.
3622
- */ function assertSnapshotDataWithKey(document, message) {
3623
- return _async_to_generator$d(function() {
3624
- var data;
3625
- return _ts_generator$d(this, function(_state) {
3626
- switch(_state.label){
3627
- case 0:
3628
- return [
3629
- 4,
3630
- assertSnapshotData(document, message)
3631
- ];
3632
- case 1:
3633
- data = _state.sent();
3634
- return [
3635
- 2,
3636
- setIdAndKeyFromKeyIdRefOnDocumentData(data, document)
3637
- ];
3638
- }
3639
- });
3640
- })();
3641
- }
4287
+ * @example
4288
+ * ```ts
4289
+ * const context = googleCloudFirestoreContextFactory(firestore);
4290
+ * ```
4291
+ */ var googleCloudFirestoreContextFactory = firestoreContextFactory(googleCloudFirestoreDrivers());
4292
+
4293
+ // MARK: Field Converters
3642
4294
  /**
3643
- * Asserts that the Firestore document exists without loading its data.
4295
+ * Creates a Firestore field mapping that encrypts/decrypts a JSON-serializable value
4296
+ * using AES-256-GCM. The value is stored in Firestore as a base64-encoded string.
3644
4297
  *
3645
- * @param document - The Firestore document to check.
3646
- * @param message - Optional custom error message.
3647
- * @throws {HttpsError} Throws a {@link modelNotAvailableError} (404) if the document does not exist.
3648
- */ function assertDocumentExists(document, message) {
3649
- return _async_to_generator$d(function() {
3650
- var exists;
3651
- return _ts_generator$d(this, function(_state) {
3652
- switch(_state.label){
3653
- case 0:
3654
- return [
3655
- 4,
3656
- document.exists()
3657
- ];
3658
- case 1:
3659
- exists = _state.sent();
3660
- if (!exists) {
3661
- throw documentModelNotAvailableError(document, message);
3662
- }
3663
- return [
3664
- 2
3665
- ];
3666
- }
3667
- });
3668
- })();
3669
- }
3670
- /**
3671
- * Creates a {@link modelNotAvailableError} for the given document's model type.
4298
+ * The encryption key is resolved from the configured secret source on each read/write,
4299
+ * allowing for key rotation via environment variable changes.
3672
4300
  *
3673
- * Used by {@link assertDocumentExists} and other assertion functions.
4301
+ * @example
4302
+ * ```typescript
4303
+ * const jwksField = firestoreEncryptedField<JWKSet>({
4304
+ * secret: process.env['FIRESTORE_ENCRYPTION_KEY']!,
4305
+ * default: () => ({ keys: [] })
4306
+ * });
4307
+ * ```
3674
4308
  *
3675
- * @param document - The document (or object with `modelType`) to generate the error for.
3676
- * @param message - Optional custom error message.
3677
- * @returns A {@link modelNotAvailableError} with the document's model type in the message.
3678
- */ function documentModelNotAvailableError(document, message) {
3679
- return modelNotAvailableError({
3680
- message: message !== null && message !== void 0 ? message : "The ".concat(document.modelType, " was unavailable.")
4309
+ * @template T - The JSON-serializable value type.
4310
+ * @param config - Encryption field configuration.
4311
+ * @returns A field mapping configuration for encrypted values.
4312
+ */ function firestoreEncryptedField(config) {
4313
+ var secret = config.secret, defaultValue = config.default;
4314
+ var getKey = resolveEncryptionKey(secret);
4315
+ return firestoreField({
4316
+ default: defaultValue,
4317
+ fromData: function fromData(data) {
4318
+ return decryptValue(data, getKey());
4319
+ },
4320
+ toData: function toData(value) {
4321
+ return encryptValue(value, getKey());
4322
+ }
3681
4323
  });
3682
4324
  }
3683
-
3684
- /**
3685
- * Error code for when a phone number is already registered in Firebase Auth.
3686
- */ var PHONE_NUMBER_ALREADY_EXISTS_ERROR_CODE = 'PHONE_NUMBER_ALREADY_EXISTS';
3687
4325
  /**
3688
- * Creates a precondition conflict (409) error indicating the phone number already exists.
4326
+ * Creates a Firestore field mapping for an optional encrypted field.
3689
4327
  *
3690
- * @returns A new precondition-conflict (409) {@link HttpsError} with the phone-number-exists code.
3691
- */ function phoneNumberAlreadyExistsError() {
3692
- return preconditionConflictError({
3693
- code: PHONE_NUMBER_ALREADY_EXISTS_ERROR_CODE,
3694
- message: 'This phone number already exists in the system.'
3695
- });
3696
- }
3697
- /**
3698
- * Handles Firebase Auth errors by mapping known error codes to typed HTTP errors.
4328
+ * When the value is null/undefined, it is stored/read as null. When present, it is
4329
+ * encrypted/decrypted using AES-256-GCM.
3699
4330
  *
3700
- * Currently maps `auth/phone-number-already-exists` to a 409 conflict error.
3701
- * Unknown error codes are forwarded to the optional handler.
4331
+ * @example
4332
+ * ```typescript
4333
+ * const optionalSecretField = optionalFirestoreEncryptedField<OAuthClientSecret>({
4334
+ * secret: process.env['FIRESTORE_ENCRYPTION_KEY']!
4335
+ * });
4336
+ * ```
3702
4337
  *
3703
- * @param e - The caught error.
3704
- * @param handleUnknownCode - Optional handler for Firebase errors with unrecognized codes.
3705
- */ function handleFirebaseAuthError(e, handleUnknownCode) {
3706
- handleFirebaseError(e, function(firebaseError) {
3707
- switch(firebaseError.code){
3708
- case FIREBASE_AUTH_PHONE_NUMBER_ALREADY_EXISTS_ERROR:
3709
- throw phoneNumberAlreadyExistsError();
3710
- default:
3711
- handleUnknownCode === null || handleUnknownCode === void 0 ? void 0 : handleUnknownCode(firebaseError);
3712
- break;
4338
+ * @template T - The JSON-serializable value type.
4339
+ * @param config - Encryption field configuration.
4340
+ * @returns A field mapping configuration for optional encrypted values.
4341
+ */ function optionalFirestoreEncryptedField(config) {
4342
+ var secret = config.secret;
4343
+ var getKey = resolveEncryptionKey(secret);
4344
+ return optionalFirestoreField({
4345
+ transformFromData: function transformFromData(data) {
4346
+ return decryptValue(data, getKey());
4347
+ },
4348
+ transformToData: function transformToData(value) {
4349
+ return encryptValue(value, getKey());
3713
4350
  }
3714
4351
  });
3715
4352
  }
@@ -4758,9 +5395,8 @@ function resolveAnalyticsFromApiDetails(apiDetails, call, modelType, specifier)
4758
5395
  if (handler != null) {
4759
5396
  assertRequestRequiresAuthForFunction(handler, request);
4760
5397
  return handler(request);
4761
- } else {
4762
- throw unknownModelCrudFunctionSpecifierError(specifier);
4763
5398
  }
5399
+ throw unknownModelCrudFunctionSpecifierError(specifier);
4764
5400
  };
4765
5401
  fn._requireAuth = false;
4766
5402
  // Aggregate _apiDetails from handler functions in the config
@@ -4982,9 +5618,8 @@ function _object_spread_props$c(target, source) {
4982
5618
  specifier: specifier,
4983
5619
  data: request.data.data
4984
5620
  }));
4985
- } else {
4986
- throw throwOnUnknownModelType(modelType);
4987
5621
  }
5622
+ throw throwOnUnknownModelType(modelType);
4988
5623
  };
4989
5624
  // Aggregate _apiDetails from model type handlers in the map
4990
5625
  var crudModelApiDetails = aggregateCrudModelApiDetails(map);
@@ -7489,9 +8124,8 @@ function _object_spread_props$8(target, source) {
7489
8124
  specifier: specifier,
7490
8125
  data: request.data.data
7491
8126
  }));
7492
- } else {
7493
- throw developmentUnknownSpecifierError(specifier);
7494
8127
  }
8128
+ throw developmentUnknownSpecifierError(specifier);
7495
8129
  };
7496
8130
  }
7497
8131
  /**
@@ -11980,4 +12614,4 @@ function _define_property(obj, key, value) {
11980
12614
  }
11981
12615
  ();
11982
12616
 
11983
- export { AbstractFirebaseNestContext, AbstractFirebaseServerActionsContext, AbstractFirebaseServerAuthContext, AbstractFirebaseServerAuthService, AbstractFirebaseServerAuthUserContext, AbstractFirebaseServerNewUserService, AbstractNestContext, AbstractServerFirebaseNestContext, ConfigureFirebaseAppCheckMiddlewareModule, ConfigureFirebaseWebhookMiddlewareModule, DEFAULT_FIREBASE_PASSWORD_NUMBER_GENERATOR, DEFAULT_SERVER_ASSETS_BASE_PATH, DEFAULT_SETUP_COM_THROTTLE_TIME, DefaultFirebaseServerEnvService, FIREBASE_APP_TOKEN, FIREBASE_AUTH_TOKEN, FIREBASE_FIRESTORE_CONTEXT_TOKEN, FIREBASE_FIRESTORE_TOKEN, FIREBASE_SERVER_ENV_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, FirebaseAppCheckMiddleware, FirebaseAppCheckMiddlewareConfig, FirebaseNestServerRootModule, FirebaseRawBodyMiddleware, FirebaseServerAnalyticsSegmentListenerService, FirebaseServerAnalyticsSegmentModule, FirebaseServerAnalyticsService, FirebaseServerAnalyticsServiceListener, FirebaseServerAuthModule, FirebaseServerAuthNewUserSendSetupDetailsNoSetupConfigError, FirebaseServerAuthNewUserSendSetupDetailsSendOnceError, FirebaseServerAuthNewUserSendSetupDetailsThrottleError, FirebaseServerAuthService, FirebaseServerAuthUserBadInputError, FirebaseServerAuthUserExistsError, FirebaseServerEnvService, FirebaseServerFirestoreContextModule, FirebaseServerFirestoreModule, FirebaseServerStorageContextModule, FirebaseServerStorageModule, FirebaseServerStorageService, GlobalRoutePrefixConfig, MAX_MODEL_ACCESS_MULTI_READ_KEYS, MODEL_API_NEST_APPLICATION_CONTEXT, ModelApiCallModelDispatchService, ModelApiController, ModelApiDispatchConfig, ModelApiGetService, NO_RUN_NAME_SPECIFIED_FOR_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_CODE, NoSetupContentFirebaseServerNewUserService, ON_CALL_MODEL_ANALYTICS_HANDLER, ON_CALL_MODEL_ANALYTICS_SERVICE, OnCallModelAnalyticsService, PHONE_NUMBER_ALREADY_EXISTS_ERROR_CODE, SkipAppCheck, UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_NAME_CODE, UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_TYPE_CODE, _onCallWithCallTypeFunction, aggregateCrudModelApiDetails, aggregateModelApiDetails, aggregateSpecifierApiDetails, alreadyExistsError, appAnalyticsModuleMetadata, appFirestoreModuleMetadata, assertContextHasAuth, assertDocumentExists, assertHasRolesInRequest, assertHasSignedTosInRequest, assertIsAdminInRequest, assertIsAdminOrTargetUserInRequestData, assertIsContextWithAuthData, assertRequestRequiresAuthForFunction, assertSnapshotData, assertSnapshotDataWithKey, badRequestError, blockingFunctionHandlerWithNestContextFactory, buildNestServerRootModule, callWithAnalytics, cloudEventHandlerWithNestContextFactory, collectionRefForPath, createModelUnknownModelTypeError, defaultFirebaseServerActionsTransformFactoryLogErrorFunction, defaultProvideFirebaseServerStorageServiceSimple, deleteModelUnknownModelTypeError, developmentUnknownSpecifierError, docRefForPath, documentModelNotAvailableError, executeOnCallQuery, firebaseAuthTokenFromDecodedIdToken, firebaseServerActionsContext, firebaseServerActionsTransformContext, firebaseServerActionsTransformFactory, firebaseServerAppTokenProvider, firebaseServerAuthModuleMetadata, firebaseServerDevFunctions, firebaseServerEnvTokenProvider, firebaseServerEnvTokenProviders, firebaseServerErrorInfo, firebaseServerErrorInfoCodePair, firebaseServerErrorInfoServerErrorCodePair, firebaseServerErrorInfoServerErrorPair, firebaseServerFirestoreContextModuleMetadata, firebaseServerStorageDefaultBucketIdTokenProvider, firebaseServerStorageModuleMetadata, firebaseServerValidationError, firebaseServerValidationServerError, firestoreClientQueryConstraintFunctionsDriver, firestoreEncryptedField, firestoreServerIncrementUpdateToUpdateData, forbiddenError, getAuthUserOrUndefined, getModelApiDetails, googleCloudFileMetadataToStorageMetadata, googleCloudFirebaseStorageContextFactory, googleCloudFirebaseStorageDrivers, googleCloudFirestoreAccessorDriver, googleCloudFirestoreContextFactory, googleCloudFirestoreDrivers, googleCloudFirestoreQueryDriver, googleCloudStorageAccessorFile, googleCloudStorageAccessorFolder, googleCloudStorageBucketForStorageFilePath, googleCloudStorageFileForStorageFilePath, googleCloudStorageFirebaseStorageAccessorDriver, googleCloudStorageFromFirebaseAdminStorage, googleCloudStorageListFilesResultFactory, handleFirebaseAuthError, handleFirebaseError, hasAuthRolesInRequest, hasNewUserSetupPasswordInRequest, hasSignedTosInRequest, inAuthContext, injectNestApplicationContextIntoRequest, injectNestIntoRequest, internalServerError, isActualSpecifier, isAdminInRequest, isAdminOrTargetUserInRequestData, isContextWithAuthData, isFirebaseError, isFirebaseHttpsError, isOnCallCrudModelApiDetails, isOnCallHandlerApiDetails, isOnCallModelTypeApiDetails, isOnCallSpecifierApiDetails, makeBlockingFunctionWithHandler, makeOnScheduleHandlerWithNestApplicationRequest, makeScheduledFunctionDevelopmentFunction, modelApiModuleMetadata, modelNotAvailableError, nestAppHasDevelopmentSchedulerEnabled, nestAppIsProductionEnvironment, nestFirebaseDoesNotExistError, nestFirebaseForbiddenPermissionError, nestServerInstance, noRunNameSpecifiedForScheduledFunctionDevelopmentFunction, noopFirebaseServerAnalyticsServiceListener, noopOnCallModelAnalyticsService, notFoundError, onCallAnalyticsEmitterInstance, onCallCreateModel, onCallDeleteModel, onCallDevelopmentFunction, onCallHandlerWithNestApplicationFactory, onCallHandlerWithNestContextFactory, onCallModel, onCallModelMissingCallTypeError, onCallModelUnknownCallTypeError, onCallQueryModel, onCallReadModel, onCallSpecifierHandler, onCallUpdateModel, onScheduleHandlerWithNestApplicationFactory, onScheduleHandlerWithNestContextFactory, optionalAuthContext, optionalFirestoreEncryptedField, permissionDeniedError, phoneNumberAlreadyExistsError, preconditionConflictError, provideAppFirestoreCollections, provideFirebaseServerAuthService, provideFirebaseServerStorageService, queryModelBadCursorError, queryModelUnknownModelTypeError, readApiDetails, readModelUnknownModelTypeError, resolveAdminOnlyValue, resolveAnalyticsFromApiDetails, setNestContextOnRequest, setNestContextOnScheduleRequest, taskQueueFunctionHandlerWithNestContextFactory, unauthenticatedContextHasNoAuthData, unauthenticatedContextHasNoUidError, unauthenticatedError, unavailableError, unavailableOrDeactivatedFunctionError, unknownModelCrudFunctionSpecifierError, unknownScheduledFunctionDevelopmentFunctionName, unknownScheduledFunctionDevelopmentFunctionType, updateModelUnknownModelTypeError, userContextFromUid, verifyAppCheckInRequest, withApiDetails };
12617
+ export { AbstractFirebaseNestContext, AbstractFirebaseServerActionsContext, AbstractFirebaseServerAuthContext, AbstractFirebaseServerAuthService, AbstractFirebaseServerAuthUserContext, AbstractFirebaseServerNewUserService, AbstractFirebaseServerUserPasswordResetService, AbstractNestContext, AbstractServerFirebaseNestContext, ConfigureFirebaseAppCheckMiddlewareModule, ConfigureFirebaseWebhookMiddlewareModule, DEFAULT_FIREBASE_PASSWORD_NUMBER_GENERATOR, DEFAULT_RESET_COM_THROTTLE_TIME, DEFAULT_SERVER_ASSETS_BASE_PATH, DEFAULT_SETUP_COM_THROTTLE_TIME, DefaultFirebaseServerEnvService, FIREBASE_APP_TOKEN, FIREBASE_AUTH_TOKEN, FIREBASE_FIRESTORE_CONTEXT_TOKEN, FIREBASE_FIRESTORE_TOKEN, FIREBASE_SERVER_ENV_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, FirebaseAppCheckMiddleware, FirebaseAppCheckMiddlewareConfig, FirebaseNestServerRootModule, FirebaseRawBodyMiddleware, FirebaseServerAnalyticsSegmentListenerService, FirebaseServerAnalyticsSegmentModule, FirebaseServerAnalyticsService, FirebaseServerAnalyticsServiceListener, FirebaseServerAuthModule, FirebaseServerAuthNewUserSendSetupDetailsNoSetupConfigError, FirebaseServerAuthNewUserSendSetupDetailsSendOnceError, FirebaseServerAuthNewUserSendSetupDetailsThrottleError, FirebaseServerAuthPasswordResetInvalidCodeError, FirebaseServerAuthPasswordResetNoResetConfigError, FirebaseServerAuthPasswordResetSendOnceError, FirebaseServerAuthPasswordResetThrottleError, FirebaseServerAuthService, FirebaseServerAuthUserBadInputError, FirebaseServerAuthUserExistsError, FirebaseServerEnvService, FirebaseServerFirestoreContextModule, FirebaseServerFirestoreModule, FirebaseServerStorageContextModule, FirebaseServerStorageModule, FirebaseServerStorageService, GlobalRoutePrefixConfig, MAX_MODEL_ACCESS_MULTI_READ_KEYS, MODEL_API_NEST_APPLICATION_CONTEXT, ModelApiCallModelDispatchService, ModelApiController, ModelApiDispatchConfig, ModelApiGetService, NO_RUN_NAME_SPECIFIED_FOR_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_CODE, NoContentFirebaseServerUserPasswordResetService, NoSetupContentFirebaseServerNewUserService, ON_CALL_MODEL_ANALYTICS_HANDLER, ON_CALL_MODEL_ANALYTICS_SERVICE, OnCallModelAnalyticsService, PHONE_NUMBER_ALREADY_EXISTS_ERROR_CODE, SkipAppCheck, UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_NAME_CODE, UNKNOWN_SCHEDULED_FUNCTION_DEVELOPMENT_FUNCTION_TYPE_CODE, _onCallWithCallTypeFunction, aggregateCrudModelApiDetails, aggregateModelApiDetails, aggregateSpecifierApiDetails, alreadyExistsError, appAnalyticsModuleMetadata, appFirestoreModuleMetadata, assertContextHasAuth, assertDocumentExists, assertHasRolesInRequest, assertHasSignedTosInRequest, assertIsAdminInRequest, assertIsAdminOrTargetUserInRequestData, assertIsContextWithAuthData, assertRequestRequiresAuthForFunction, assertSnapshotData, assertSnapshotDataWithKey, authServicePasswordResetInvalidCodeError, authServicePasswordResetNoConfigError, authServicePasswordResetSendOnceError, authServicePasswordResetThrottleError, badRequestError, blockingFunctionHandlerWithNestContextFactory, buildNestServerRootModule, callWithAnalytics, catchAndThrowPasswordResetServerErrors, cloudEventHandlerWithNestContextFactory, collectionRefForPath, createModelUnknownModelTypeError, defaultFirebaseServerActionsTransformFactoryLogErrorFunction, defaultProvideFirebaseServerStorageServiceSimple, deleteModelUnknownModelTypeError, developmentUnknownSpecifierError, docRefForPath, documentModelNotAvailableError, executeOnCallQuery, firebaseAuthTokenFromDecodedIdToken, firebaseServerActionsContext, firebaseServerActionsTransformContext, firebaseServerActionsTransformFactory, firebaseServerAppTokenProvider, firebaseServerAuthModuleMetadata, firebaseServerDevFunctions, firebaseServerEnvTokenProvider, firebaseServerEnvTokenProviders, firebaseServerErrorInfo, firebaseServerErrorInfoCodePair, firebaseServerErrorInfoServerErrorCodePair, firebaseServerErrorInfoServerErrorPair, firebaseServerFirestoreContextModuleMetadata, firebaseServerStorageDefaultBucketIdTokenProvider, firebaseServerStorageModuleMetadata, firebaseServerValidationError, firebaseServerValidationServerError, firestoreClientQueryConstraintFunctionsDriver, firestoreEncryptedField, firestoreServerIncrementUpdateToUpdateData, forbiddenError, getAuthUserOrUndefined, getModelApiDetails, googleCloudFileMetadataToStorageMetadata, googleCloudFirebaseStorageContextFactory, googleCloudFirebaseStorageDrivers, googleCloudFirestoreAccessorDriver, googleCloudFirestoreContextFactory, googleCloudFirestoreDrivers, googleCloudFirestoreQueryDriver, googleCloudStorageAccessorFile, googleCloudStorageAccessorFolder, googleCloudStorageBucketForStorageFilePath, googleCloudStorageFileForStorageFilePath, googleCloudStorageFirebaseStorageAccessorDriver, googleCloudStorageFromFirebaseAdminStorage, googleCloudStorageListFilesResultFactory, handleFirebaseAuthError, handleFirebaseError, hasAuthRolesInRequest, hasNewUserSetupPasswordInRequest, hasSignedTosInRequest, inAuthContext, injectNestApplicationContextIntoRequest, injectNestIntoRequest, internalServerError, isActualSpecifier, isAdminInRequest, isAdminOrTargetUserInRequestData, isContextWithAuthData, isFirebaseError, isFirebaseHttpsError, isOnCallCrudModelApiDetails, isOnCallHandlerApiDetails, isOnCallModelTypeApiDetails, isOnCallSpecifierApiDetails, makeBlockingFunctionWithHandler, makeOnScheduleHandlerWithNestApplicationRequest, makeScheduledFunctionDevelopmentFunction, modelApiModuleMetadata, modelNotAvailableError, nestAppHasDevelopmentSchedulerEnabled, nestAppIsProductionEnvironment, nestFirebaseDoesNotExistError, nestFirebaseForbiddenPermissionError, nestServerInstance, noRunNameSpecifiedForScheduledFunctionDevelopmentFunction, noopFirebaseServerAnalyticsServiceListener, noopOnCallModelAnalyticsService, notFoundError, onCallAnalyticsEmitterInstance, onCallCreateModel, onCallDeleteModel, onCallDevelopmentFunction, onCallHandlerWithNestApplicationFactory, onCallHandlerWithNestContextFactory, onCallModel, onCallModelMissingCallTypeError, onCallModelUnknownCallTypeError, onCallQueryModel, onCallReadModel, onCallSpecifierHandler, onCallUpdateModel, onScheduleHandlerWithNestApplicationFactory, onScheduleHandlerWithNestContextFactory, optionalAuthContext, optionalFirestoreEncryptedField, permissionDeniedError, phoneNumberAlreadyExistsError, preconditionConflictError, provideAppFirestoreCollections, provideFirebaseServerAuthService, provideFirebaseServerStorageService, queryModelBadCursorError, queryModelUnknownModelTypeError, readApiDetails, readModelUnknownModelTypeError, resolveAdminOnlyValue, resolveAnalyticsFromApiDetails, setNestContextOnRequest, setNestContextOnScheduleRequest, taskQueueFunctionHandlerWithNestContextFactory, unauthenticatedContextHasNoAuthData, unauthenticatedContextHasNoUidError, unauthenticatedError, unavailableError, unavailableOrDeactivatedFunctionError, unknownModelCrudFunctionSpecifierError, unknownScheduledFunctionDevelopmentFunctionName, unknownScheduledFunctionDevelopmentFunctionType, updateModelUnknownModelTypeError, userContextFromUid, verifyAppCheckInRequest, withApiDetails };