@dereekb/firebase-server 13.6.9 → 13.6.11

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.
@@ -1,6 +1,6 @@
1
- import { mapObjectKeysToLowercase, multiValueMapBuilder, batch, runAsyncTasksForValues, asArray, pushArrayItemsIntoArray, UNSET_INDEX_NUMBER, areEqualPOJOValues, performAsyncTasks, removeValuesAtIndexesFromArrayCopy, takeFront, makeModelMap, computeNextFreeIndexOnSortedValuesFunction, readIndexNumber, asPromise, dateOrMillisecondsToDate, filterOnlyUndefinedValues, iterablesAreSetEquivalent, mapIdentityFunction, makeValuesGroupMap, separateValues, filterMaybeArrayValues, cutStringFunction, takeLast, unique, mergeSlashPaths, ModelRelationUtility, isThrottled, isPast, unixDateTimeSecondsNumberFromDate, slashPathDetails, expirationDetails, MS_IN_MINUTE, dateFromDateOrTimeMillisecondsNumber, cachedGetter, MS_IN_HOUR, documentFileExtensionForMimeType, useCallback, ZIP_FILE_MIME_TYPE, MAP_IDENTITY, pushItemOrArrayItemsIntoArray, asDecisionFunction } from '@dereekb/util';
1
+ import { mapObjectKeysToLowercase, multiValueMapBuilder, batch, runAsyncTasksForValues, asArray, pushArrayItemsIntoArray, UNSET_INDEX_NUMBER, areEqualPOJOValues, performAsyncTasks, removeValuesAtIndexesFromArrayCopy, takeFront, makeModelMap, computeNextFreeIndexOnSortedValuesFunction, readIndexNumber, asPromise, dateOrMillisecondsToDate, filterOnlyUndefinedValues, iterablesAreSetEquivalent, mapIdentityFunction, makeValuesGroupMap, separateValues, filterMaybeArrayValues, cutStringFunction, takeLast, unique, mergeSlashPaths, ModelRelationUtility, isThrottled, isPast, unixDateTimeSecondsNumberFromDate, slashPathDetails, MS_IN_MINUTE, expirationDetails, dateFromDateOrTimeMillisecondsNumber, cachedGetter, MS_IN_HOUR, documentFileExtensionForMimeType, useCallback, ZIP_FILE_MIME_TYPE, MAP_IDENTITY, pushItemOrArrayItemsIntoArray, asDecisionFunction } from '@dereekb/util';
2
2
  import { yearWeekCode, isSameDate, findMaxDate, findMinDate } from '@dereekb/date';
3
- import { CREATE_NOTIFICATION_ID_REQUIRED_ERROR_CODE, NOTIFICATION_BOX_DOES_NOT_EXIST_ERROR_CODE, NOTIFICATION_BOX_EXCLUSION_TARGET_INVALID_ERROR_CODE, NOTIFICATION_BOX_EXISTS_FOR_MODEL_ERROR_CODE, NOTIFICATION_BOX_RECIPIENT_DOES_NOT_EXIST_ERROR_CODE, NOTIFICATION_MODEL_ALREADY_INITIALIZED_ERROR_CODE, NOTIFICATION_USER_BLOCKED_FROM_BEING_ADD_TO_RECIPIENTS_ERROR_CODE, NOTIFICATION_USER_INVALID_UID_FOR_CREATE_ERROR_CODE, NOTIFICATION_USER_LOCKED_CONFIG_FROM_BEING_UPDATED_ERROR_CODE, firestoreDummyKey, mergeNotificationBoxRecipients, mergeNotificationUserNotificationBoxRecipientConfigs, applyExclusionsToNotificationUserNotificationBoxRecipientConfigs, mergeNotificationBoxRecipientTemplateConfigs, effectiveNotificationBoxRecipientTemplateConfig, notificationSendExclusionCanSendFunction, mergeNotificationUserDefaultNotificationBoxRecipientConfig, DEFAULT_NOTIFICATION_TEMPLATE_TYPE, NotificationRecipientSendFlag, allowedNotificationRecipients, loadDocumentsForIds, getDocumentSnapshotDataPairsWithData, cleanupSentNotificationsParamsType, createNotificationBoxParamsType, createNotificationSummaryParamsType, createNotificationUserParamsType, resyncNotificationUserParamsType, sendNotificationParamsType, sendQueuedNotificationsParamsType, updateNotificationBoxParamsType, updateNotificationBoxRecipientParamsType, updateNotificationSummaryParamsType, updateNotificationUserParamsType, updateNotificationUserDefaultNotificationBoxRecipientConfig, effectiveNotificationBoxRecipientConfig, updateNotificationUserNotificationBoxRecipientConfigs, calculateNsForNotificationUserNotificationBoxRecipientConfigs, getDocumentSnapshotDataPairs, iterateFirestoreDocumentSnapshotPairs, notificationUsersFlaggedForNeedsSyncQuery, notificationSummaryIdForModel, loadNotificationBoxDocumentForReferencePair, updateNotificationUserNotificationSendExclusions, notificationBoxRecipientTemplateConfigArrayToRecord, updateNotificationRecipient, setIdAndKeyFromKeyIdRefOnDocumentData, inferKeyFromTwoWayFlatFirestoreModelKey, NotificationSendType, getDocumentSnapshotData, notificationSendFlagsImplyIsComplete, NotificationSendState, mergeNotificationSendMessagesResult, notificationsPastSendAtTimeQuery, shouldSaveNotificationToNotificationWeek, loadDocumentsForDocumentReferencesFromValues, notificationsReadyForCleanupQuery, initializeAllApplicableNotificationBoxesParamsType, initializeAllApplicableNotificationSummariesParamsType, initializeNotificationModelParamsType, firestoreModelKeyCollectionName, notificationBoxesFlaggedForNeedsInitializationQuery, notificationSummariesFlaggedForNeedsInitializationQuery, noContentNotificationMessageFunctionFactory, _createNotificationDocumentFromPair, createNotificationDocumentPair, NOTIFICATION_SUMMARY_EMBEDDED_NOTIFICATION_ITEM_SUBJECT_MAX_LENGTH, NOTIFICATION_SUMMARY_EMBEDDED_NOTIFICATION_ITEM_MESSAGE_MAX_LENGTH, sortNotificationItemsFunction, NOTIFICATION_SUMMARY_ITEM_LIMIT, NOTIFICATION_TASK_SUBTASK_CHECKPOINT_PROCESSING, NOTIFICATION_TASK_SUBTASK_CHECKPOINT_CLEANUP, completeSubtaskProcessingAndScheduleCleanupTaskResult, delayCompletion, notificationTaskComplete, notificationTaskDelayRetry, DEFAULT_NOTIFICATION_TASK_SUBTASK_CLEANUP_RETRY_DELAY, DEFAULT_NOTIFICATION_TASK_SUBTASK_CLEANUP_RETRY_ATTEMPTS, STORAGE_FILE_GROUP_CREATE_INPUT_ERROR_CODE, STORAGE_FILE_ALREADY_PROCESSED_ERROR_CODE, STORAGE_FILE_CANNOT_BE_DELETED_YET_ERROR_CODE, STORAGE_FILE_GROUP_QUEUED_FOR_INITIALIZATION_ERROR_CODE, STORAGE_FILE_MODEL_ALREADY_INITIALIZED_ERROR_CODE, STORAGE_FILE_NOT_FLAGGED_FOR_DELETION_ERROR_CODE, STORAGE_FILE_NOT_FLAGGED_FOR_GROUPS_SYNC_ERROR_CODE, STORAGE_FILE_PROCESSING_NOT_ALLOWED_FOR_INVALID_STATE_ERROR_CODE, STORAGE_FILE_PROCESSING_NOT_AVAILABLE_FOR_TYPE_ERROR_CODE, STORAGE_FILE_PROCESSING_NOT_QUEUED_FOR_PROCESSING_ERROR_CODE, UPLOADED_FILE_DOES_NOT_EXIST_ERROR_CODE, UPLOADED_FILE_INITIALIZATION_DISCARDED_ERROR_CODE, UPLOADED_FILE_INITIALIZATION_FAILED_ERROR_CODE, UPLOADED_FILE_NOT_ALLOWED_TO_BE_INITIALIZED_ERROR_CODE, createStorageFileParamsType, createStorageFileGroupParamsType, deleteAllQueuedStorageFilesParamsType, deleteStorageFileParamsType, downloadStorageFileParamsType, initializeAllStorageFilesFromUploadsParamsType, initializeStorageFileFromUploadParamsType, processAllQueuedStorageFilesParamsType, processStorageFileParamsType, regenerateAllFlaggedStorageFileGroupsContentParamsType, regenerateStorageFileGroupContentParamsType, syncAllFlaggedStorageFilesWithGroupsParamsType, syncStorageFileWithGroupsParamsType, updateStorageFileParamsType, updateStorageFileGroupParamsType, UPLOADS_FOLDER_PATH, iterateStorageListFilesByEachFile, StorageFileProcessingState, storageFilesQueuedForProcessingQuery, STORAGE_FILE_PROCESSING_STUCK_THROTTLE_CHECK_MS, StorageFileState, createNotificationDocument, storageFileProcessingNotificationTaskTemplate, storageFilesQueuedForDeleteQuery, loadStorageFileGroupDocumentForReferencePair, calculateStorageFileGroupEmbeddedFileUpdate, iterateFirestoreDocumentSnapshotPairBatches, storageFileFlaggedForSyncWithGroupsQuery, createStorageFileDocumentPairFactory, StorageFileCreationType, calculateStorageFileGroupRegeneration, storageFileGroupZipFileStoragePath, STORAGE_FILE_GROUP_ZIP_STORAGE_FILE_PURPOSE, getDocumentSnapshotDataPair, storageFileGroupsFlaggedForContentRegenerationQuery, initializeAllApplicableStorageFileGroupsParamsType, initializeStorageFileModelParamsType, storageFileGroupsFlaggedForNeedsInitializationQuery, STORAGE_FILE_GROUP_ZIP_STORAGE_FILE_PURPOSE_CREATE_ZIP_SUBTASK, storedFileReaderFactory, STORAGE_FILE_PROCESSING_NOTIFICATION_TASK_TYPE, copyStoragePath, notificationSubtaskComplete, STORAGE_FILE_GROUP_ZIP_INFO_JSON_FILE_NAME, limitUploadFileTypeDeterminer, combineUploadFileTypeDeterminers, STORAGEFILE_RELATED_FILE_METADATA_KEY, storageFilePurposeAndUserQuery } from '@dereekb/firebase';
3
+ import { CREATE_NOTIFICATION_ID_REQUIRED_ERROR_CODE, NOTIFICATION_BOX_DOES_NOT_EXIST_ERROR_CODE, NOTIFICATION_BOX_EXCLUSION_TARGET_INVALID_ERROR_CODE, NOTIFICATION_BOX_EXISTS_FOR_MODEL_ERROR_CODE, NOTIFICATION_BOX_RECIPIENT_DOES_NOT_EXIST_ERROR_CODE, NOTIFICATION_MODEL_ALREADY_INITIALIZED_ERROR_CODE, NOTIFICATION_USER_BLOCKED_FROM_BEING_ADD_TO_RECIPIENTS_ERROR_CODE, NOTIFICATION_USER_INVALID_UID_FOR_CREATE_ERROR_CODE, NOTIFICATION_USER_LOCKED_CONFIG_FROM_BEING_UPDATED_ERROR_CODE, firestoreDummyKey, mergeNotificationBoxRecipients, mergeNotificationUserNotificationBoxRecipientConfigs, applyExclusionsToNotificationUserNotificationBoxRecipientConfigs, mergeNotificationBoxRecipientTemplateConfigs, effectiveNotificationBoxRecipientTemplateConfig, notificationSendExclusionCanSendFunction, mergeNotificationUserDefaultNotificationBoxRecipientConfig, DEFAULT_NOTIFICATION_TEMPLATE_TYPE, NotificationRecipientSendFlag, allowedNotificationRecipients, loadDocumentsForIds, getDocumentSnapshotDataPairsWithData, cleanupSentNotificationsParamsType, createNotificationBoxParamsType, createNotificationSummaryParamsType, createNotificationUserParamsType, resyncNotificationUserParamsType, sendNotificationParamsType, sendQueuedNotificationsParamsType, updateNotificationBoxParamsType, updateNotificationBoxRecipientParamsType, updateNotificationSummaryParamsType, updateNotificationUserParamsType, updateNotificationUserDefaultNotificationBoxRecipientConfig, effectiveNotificationBoxRecipientConfig, updateNotificationUserNotificationBoxRecipientConfigs, calculateNsForNotificationUserNotificationBoxRecipientConfigs, getDocumentSnapshotDataPairs, iterateFirestoreDocumentSnapshotPairs, notificationUsersFlaggedForNeedsSyncQuery, notificationSummaryIdForModel, loadNotificationBoxDocumentForReferencePair, updateNotificationUserNotificationSendExclusions, notificationBoxRecipientTemplateConfigArrayToRecord, updateNotificationRecipient, setIdAndKeyFromKeyIdRefOnDocumentData, inferKeyFromTwoWayFlatFirestoreModelKey, NotificationSendType, getDocumentSnapshotData, notificationSendFlagsImplyIsComplete, NotificationSendState, mergeNotificationSendMessagesResult, notificationsPastSendAtTimeQuery, shouldSaveNotificationToNotificationWeek, loadDocumentsForDocumentReferencesFromValues, notificationsReadyForCleanupQuery, initializeAllApplicableNotificationBoxesParamsType, initializeAllApplicableNotificationSummariesParamsType, initializeNotificationModelParamsType, firestoreModelKeyCollectionName, notificationBoxesFlaggedForNeedsInitializationQuery, notificationSummariesFlaggedForNeedsInitializationQuery, noContentNotificationMessageFunctionFactory, _createNotificationDocumentFromPair, createNotificationDocumentPair, NOTIFICATION_SUMMARY_EMBEDDED_NOTIFICATION_ITEM_SUBJECT_MAX_LENGTH, NOTIFICATION_SUMMARY_EMBEDDED_NOTIFICATION_ITEM_MESSAGE_MAX_LENGTH, sortNotificationItemsFunction, NOTIFICATION_SUMMARY_ITEM_LIMIT, NOTIFICATION_TASK_SUBTASK_CHECKPOINT_PROCESSING, NOTIFICATION_TASK_SUBTASK_CHECKPOINT_CLEANUP, completeSubtaskProcessingAndScheduleCleanupTaskResult, delayCompletion, notificationTaskComplete, notificationTaskDelayRetry, DEFAULT_NOTIFICATION_TASK_SUBTASK_CLEANUP_RETRY_DELAY, DEFAULT_NOTIFICATION_TASK_SUBTASK_CLEANUP_RETRY_ATTEMPTS, STORAGE_FILE_GROUP_CREATE_INPUT_ERROR_CODE, STORAGE_FILE_ALREADY_PROCESSED_ERROR_CODE, STORAGE_FILE_CANNOT_BE_DELETED_YET_ERROR_CODE, STORAGE_FILE_GROUP_QUEUED_FOR_INITIALIZATION_ERROR_CODE, STORAGE_FILE_MODEL_ALREADY_INITIALIZED_ERROR_CODE, STORAGE_FILE_NOT_FLAGGED_FOR_DELETION_ERROR_CODE, STORAGE_FILE_NOT_FLAGGED_FOR_GROUPS_SYNC_ERROR_CODE, STORAGE_FILE_PROCESSING_NOT_ALLOWED_FOR_INVALID_STATE_ERROR_CODE, STORAGE_FILE_PROCESSING_NOT_AVAILABLE_FOR_TYPE_ERROR_CODE, STORAGE_FILE_PROCESSING_NOT_QUEUED_FOR_PROCESSING_ERROR_CODE, UPLOADED_FILE_DOES_NOT_EXIST_ERROR_CODE, UPLOADED_FILE_INITIALIZATION_DISCARDED_ERROR_CODE, UPLOADED_FILE_INITIALIZATION_FAILED_ERROR_CODE, UPLOADED_FILE_NOT_ALLOWED_TO_BE_INITIALIZED_ERROR_CODE, createStorageFileParamsType, createStorageFileGroupParamsType, deleteAllQueuedStorageFilesParamsType, deleteStorageFileParamsType, downloadMultipleStorageFilesParamsType, downloadStorageFileParamsType, initializeAllStorageFilesFromUploadsParamsType, initializeStorageFileFromUploadParamsType, processAllQueuedStorageFilesParamsType, processStorageFileParamsType, regenerateAllFlaggedStorageFileGroupsContentParamsType, regenerateStorageFileGroupContentParamsType, syncAllFlaggedStorageFilesWithGroupsParamsType, syncStorageFileWithGroupsParamsType, updateStorageFileParamsType, updateStorageFileGroupParamsType, UPLOADS_FOLDER_PATH, iterateStorageListFilesByEachFile, StorageFileProcessingState, storageFilesQueuedForProcessingQuery, STORAGE_FILE_PROCESSING_STUCK_THROTTLE_CHECK_MS, StorageFileState, createNotificationDocument, storageFileProcessingNotificationTaskTemplate, storageFilesQueuedForDeleteQuery, loadStorageFileGroupDocumentForReferencePair, calculateStorageFileGroupEmbeddedFileUpdate, iterateFirestoreDocumentSnapshotPairBatches, storageFileFlaggedForSyncWithGroupsQuery, createStorageFileDocumentPairFactory, StorageFileCreationType, calculateStorageFileGroupRegeneration, storageFileGroupZipFileStoragePath, STORAGE_FILE_GROUP_ZIP_STORAGE_FILE_PURPOSE, getDocumentSnapshotDataPair, storageFileGroupsFlaggedForContentRegenerationQuery, initializeAllApplicableStorageFileGroupsParamsType, initializeStorageFileModelParamsType, storageFileGroupsFlaggedForNeedsInitializationQuery, STORAGE_FILE_GROUP_ZIP_STORAGE_FILE_PURPOSE_CREATE_ZIP_SUBTASK, storedFileReaderFactory, STORAGE_FILE_PROCESSING_NOTIFICATION_TASK_TYPE, copyStoragePath, notificationSubtaskComplete, STORAGE_FILE_GROUP_ZIP_INFO_JSON_FILE_NAME, limitUploadFileTypeDeterminer, combineUploadFileTypeDeterminers, STORAGEFILE_RELATED_FILE_METADATA_KEY, storageFilePurposeAndUserQuery } from '@dereekb/firebase';
4
4
  import { preconditionConflictError, assertSnapshotData, internalServerError } from '@dereekb/firebase-server';
5
5
  import { hoursToMilliseconds, addHours, isFuture, addMinutes, addSeconds, addDays } from 'date-fns';
6
6
  import { Optional, Inject, Injectable, Module, Global } from '@nestjs/common';
@@ -7190,7 +7190,7 @@ function _inherits(subClass, superClass) {
7190
7190
  });
7191
7191
  if (superClass) _set_prototype_of(subClass, superClass);
7192
7192
  }
7193
- function _instanceof(left, right) {
7193
+ function _instanceof$1(left, right) {
7194
7194
  if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
7195
7195
  return !!right[Symbol.hasInstance](left);
7196
7196
  } else {
@@ -7575,7 +7575,7 @@ function _ts_generator$5(thisArg, body) {
7575
7575
  ];
7576
7576
  case 4:
7577
7577
  e = _state.sent();
7578
- if (_instanceof(e, NotificationTaskSubTaskMissingRequiredDataTermination)) {
7578
+ if (_instanceof$1(e, NotificationTaskSubTaskMissingRequiredDataTermination)) {
7579
7579
  // Task is complete if the required data no longer exists. Nothing to cleanup.
7580
7580
  result = notificationTaskComplete();
7581
7581
  } else {
@@ -8015,6 +8015,13 @@ function _define_property$4(obj, key, value) {
8015
8015
  }
8016
8016
  return obj;
8017
8017
  }
8018
+ function _instanceof(left, right) {
8019
+ if (right != null && typeof Symbol !== "undefined" && right[Symbol.hasInstance]) {
8020
+ return !!right[Symbol.hasInstance](left);
8021
+ } else {
8022
+ return left instanceof right;
8023
+ }
8024
+ }
8018
8025
  function _iterable_to_array_limit(arr, i) {
8019
8026
  var _i = arr == null ? null : typeof Symbol !== "undefined" && arr[Symbol.iterator] || arr["@@iterator"];
8020
8027
  if (_i == null) return;
@@ -8238,6 +8245,7 @@ function _ts_generator$4(thisArg, body) {
8238
8245
  deleteAllQueuedStorageFiles: deleteAllQueuedStorageFilesFactory(context),
8239
8246
  deleteStorageFile: deleteStorageFileFactory(context),
8240
8247
  downloadStorageFile: downloadStorageFileFactory(context),
8248
+ downloadMultipleStorageFiles: downloadMultipleStorageFilesFactory(context),
8241
8249
  createStorageFileGroup: createStorageFileGroupFactory(context),
8242
8250
  updateStorageFileGroup: updateStorageFileGroupFactory(context),
8243
8251
  syncStorageFileWithGroups: syncStorageFileWithGroupsFactory(context),
@@ -9465,91 +9473,172 @@ function _ts_generator$4(thisArg, body) {
9465
9473
  })();
9466
9474
  });
9467
9475
  }
9476
+ /**
9477
+ * Default maximum number of concurrent download operations when batch-downloading StorageFiles.
9478
+ */ var DEFAULT_DOWNLOAD_MULTIPLE_STORAGE_FILES_MAX_PARALLEL_TASKS = 5;
9479
+ /**
9480
+ * Internal factory that generates signed download URLs for one or more StorageFiles.
9481
+ *
9482
+ * Uses {@link performAsyncTasks} with concurrency limiting to avoid overwhelming Cloud Storage.
9483
+ * Shared expiration/disposition/content-type options are applied uniformly to all items.
9484
+ * When `throwOnFirstError` is true, the first failure throws immediately (single-download behavior).
9485
+ * When false, failures are collected in the errors array (batch behavior).
9486
+ *
9487
+ * @param context - the storage file server actions context
9488
+ * @returns an async function that processes a {@link DownloadMultipleStorageFilesFactoryInput} and returns a {@link DownloadMultipleStorageFilesResult}
9489
+ */ function _downloadMultipleStorageFilesFactory(context) {
9490
+ var storageService = context.storageService, storageFileCollection = context.storageFileCollection;
9491
+ return function(input) {
9492
+ return _async_to_generator$4(function() {
9493
+ var items, asAdmin, expiresAt, inputExpiresIn, responseDisposition, responseContentType, throwOnFirstError, inputMaxParallelTasks, taskResult, success, errors;
9494
+ return _ts_generator$4(this, function(_state) {
9495
+ switch(_state.label){
9496
+ case 0:
9497
+ items = input.items, asAdmin = input.asAdmin, expiresAt = input.expiresAt, inputExpiresIn = input.expiresIn, responseDisposition = input.responseDisposition, responseContentType = input.responseContentType, throwOnFirstError = input.throwOnFirstError, inputMaxParallelTasks = input.maxParallelTasks;
9498
+ return [
9499
+ 4,
9500
+ performAsyncTasks(items, function(item) {
9501
+ return _async_to_generator$4(function() {
9502
+ var _item_storageFileDocument, _item_responseDisposition, _item_responseContentType, _ref, _item_expiresIn, _item_expiresAt, storageFileDocument, storageFile, fileAccessor, itemResponseDisposition, itemResponseContentType, expiresIn, expires, downloadUrlExpiresAt, maxExpirationDate, _ref1, downloadUrl, metadata;
9503
+ return _ts_generator$4(this, function(_state) {
9504
+ switch(_state.label){
9505
+ case 0:
9506
+ // Load document from key if not provided
9507
+ storageFileDocument = (_item_storageFileDocument = item.storageFileDocument) !== null && _item_storageFileDocument !== void 0 ? _item_storageFileDocument : storageFileCollection.documentAccessor().loadDocumentForKey(item.key);
9508
+ return [
9509
+ 4,
9510
+ assertSnapshotData(storageFileDocument)
9511
+ ];
9512
+ case 1:
9513
+ storageFile = _state.sent();
9514
+ fileAccessor = storageService.file(storageFile);
9515
+ if (!fileAccessor.getSignedUrl) {
9516
+ throw internalServerError('Signed url function appears to not be available.');
9517
+ }
9518
+ // Per-item options override defaults
9519
+ itemResponseDisposition = (_item_responseDisposition = item.responseDisposition) !== null && _item_responseDisposition !== void 0 ? _item_responseDisposition : responseDisposition;
9520
+ itemResponseContentType = (_item_responseContentType = item.responseContentType) !== null && _item_responseContentType !== void 0 ? _item_responseContentType : responseContentType;
9521
+ expiresIn = (_ref = (_item_expiresIn = item.expiresIn) !== null && _item_expiresIn !== void 0 ? _item_expiresIn : inputExpiresIn) !== null && _ref !== void 0 ? _ref : MS_IN_MINUTE * 30;
9522
+ expires = expirationDetails({
9523
+ defaultExpiresFromDateToNow: true,
9524
+ expiresAt: (_item_expiresAt = item.expiresAt) !== null && _item_expiresAt !== void 0 ? _item_expiresAt : expiresAt,
9525
+ expiresIn: expiresIn
9526
+ });
9527
+ downloadUrlExpiresAt = expires.getExpirationDate(); // always returns a Date when defaultExpiresFromDateToNow and expiresIn are set
9528
+ // if they're not an admin, limit the expiration to a max of 30 days.
9529
+ if (!asAdmin) {
9530
+ maxExpirationDate = addDays(new Date(), 30);
9531
+ downloadUrlExpiresAt = findMinDate([
9532
+ downloadUrlExpiresAt,
9533
+ maxExpirationDate
9534
+ ]);
9535
+ }
9536
+ return [
9537
+ 4,
9538
+ Promise.all([
9539
+ fileAccessor.getSignedUrl({
9540
+ action: 'read',
9541
+ expiresAt: downloadUrlExpiresAt,
9542
+ responseDisposition: itemResponseDisposition !== null && itemResponseDisposition !== void 0 ? itemResponseDisposition : undefined,
9543
+ responseType: asAdmin ? itemResponseContentType !== null && itemResponseContentType !== void 0 ? itemResponseContentType : undefined : undefined // can only be set by admins
9544
+ }),
9545
+ fileAccessor.getMetadata()
9546
+ ])
9547
+ ];
9548
+ case 2:
9549
+ _ref1 = _sliced_to_array.apply(void 0, [
9550
+ _state.sent(),
9551
+ 2
9552
+ ]), downloadUrl = _ref1[0], metadata = _ref1[1];
9553
+ return [
9554
+ 2,
9555
+ {
9556
+ key: item.key,
9557
+ url: downloadUrl,
9558
+ fileName: metadata.name ? slashPathDetails(metadata.name).end : undefined,
9559
+ mimeType: itemResponseContentType !== null && itemResponseContentType !== void 0 ? itemResponseContentType : metadata.contentType,
9560
+ expiresAt: unixDateTimeSecondsNumberFromDate(downloadUrlExpiresAt)
9561
+ }
9562
+ ];
9563
+ }
9564
+ });
9565
+ })();
9566
+ }, {
9567
+ throwError: throwOnFirstError !== null && throwOnFirstError !== void 0 ? throwOnFirstError : false,
9568
+ maxParallelTasks: inputMaxParallelTasks !== null && inputMaxParallelTasks !== void 0 ? inputMaxParallelTasks : DEFAULT_DOWNLOAD_MULTIPLE_STORAGE_FILES_MAX_PARALLEL_TASKS
9569
+ })
9570
+ ];
9571
+ case 1:
9572
+ taskResult = _state.sent();
9573
+ success = taskResult.results.map(function(param) {
9574
+ var _param = _sliced_to_array(param, 2), result = _param[1];
9575
+ return result;
9576
+ });
9577
+ errors = taskResult.errors.map(function(param) {
9578
+ var _param = _sliced_to_array(param, 2), item = _param[0], error = _param[1];
9579
+ return {
9580
+ key: item.key,
9581
+ error: _instanceof(error, Error) ? error.message : 'Download failed'
9582
+ };
9583
+ });
9584
+ return [
9585
+ 2,
9586
+ {
9587
+ success: success,
9588
+ errors: errors
9589
+ }
9590
+ ];
9591
+ }
9592
+ });
9593
+ })();
9594
+ };
9595
+ }
9468
9596
  /**
9469
9597
  * Factory for the `downloadStorageFile` action.
9470
9598
  *
9471
9599
  * Generates a signed download URL for a {@link StorageFile}'s associated Cloud Storage file.
9472
- * The URL expires after the configured duration. Supports loading the storage file document
9473
- * by key if not provided directly.
9600
+ * Delegates to {@link _downloadMultipleStorageFilesFactory} with a single item and `throwOnFirstError: true`.
9474
9601
  *
9475
9602
  * @param context - the storage file server actions context
9476
9603
  * @returns an async transform-and-validate function that generates a signed download URL
9477
9604
  */ function downloadStorageFileFactory(context) {
9478
- var storageService = context.storageService, firebaseServerActionTransformFunctionFactory = context.firebaseServerActionTransformFunctionFactory, storageFileCollection = context.storageFileCollection;
9605
+ var firebaseServerActionTransformFunctionFactory = context.firebaseServerActionTransformFunctionFactory;
9606
+ var downloadMultipleStorageFiles = _downloadMultipleStorageFilesFactory(context);
9479
9607
  return firebaseServerActionTransformFunctionFactory(downloadStorageFileParamsType, function(params) {
9480
9608
  return _async_to_generator$4(function() {
9481
- var targetStorageFileDocumentKey, asAdmin, expiresAt, inputExpiresIn, responseDisposition, responseContentType;
9609
+ var key, asAdmin, expiresAt, expiresIn, responseDisposition, responseContentType;
9482
9610
  return _ts_generator$4(this, function(_state) {
9483
- targetStorageFileDocumentKey = params.key, asAdmin = params.asAdmin, expiresAt = params.expiresAt, inputExpiresIn = params.expiresIn, responseDisposition = params.responseDisposition, responseContentType = params.responseContentType;
9611
+ key = params.key, asAdmin = params.asAdmin, expiresAt = params.expiresAt, expiresIn = params.expiresIn, responseDisposition = params.responseDisposition, responseContentType = params.responseContentType;
9484
9612
  return [
9485
9613
  2,
9486
9614
  function(storageFileDocument) {
9487
9615
  return _async_to_generator$4(function() {
9488
- var storageFile, fileAccessor, result, expiresIn, expires, downloadUrlExpiresAt, maxExpirationDate, _ref, downloadUrl, metadata;
9616
+ var result;
9489
9617
  return _ts_generator$4(this, function(_state) {
9490
9618
  switch(_state.label){
9491
9619
  case 0:
9492
- // if the StorageFileDocument was not provided, set it from the target key
9493
- storageFileDocument !== null && storageFileDocument !== void 0 ? storageFileDocument : storageFileDocument = storageFileCollection.documentAccessor().loadDocumentForKey(targetStorageFileDocumentKey);
9494
9620
  return [
9495
9621
  4,
9496
- assertSnapshotData(storageFileDocument)
9622
+ downloadMultipleStorageFiles({
9623
+ items: [
9624
+ {
9625
+ key: key,
9626
+ storageFileDocument: storageFileDocument
9627
+ }
9628
+ ],
9629
+ asAdmin: asAdmin,
9630
+ expiresAt: expiresAt,
9631
+ expiresIn: expiresIn,
9632
+ responseDisposition: responseDisposition,
9633
+ responseContentType: responseContentType,
9634
+ throwOnFirstError: true
9635
+ })
9497
9636
  ];
9498
9637
  case 1:
9499
- storageFile = _state.sent();
9500
- fileAccessor = storageService.file(storageFile);
9501
- if (!fileAccessor.getSignedUrl) return [
9502
- 3,
9503
- 3
9504
- ];
9505
- expiresIn = inputExpiresIn !== null && inputExpiresIn !== void 0 ? inputExpiresIn : MS_IN_MINUTE * 30;
9506
- expires = expirationDetails({
9507
- defaultExpiresFromDateToNow: true,
9508
- expiresAt: expiresAt,
9509
- expiresIn: expiresIn
9510
- });
9511
- downloadUrlExpiresAt = expires.getExpirationDate(); // always returns a Date when defaultExpiresFromDateToNow and expiresIn are set
9512
- // if they're not an admin, limit the expiration to a max of 30 days.
9513
- if (!asAdmin) {
9514
- maxExpirationDate = addDays(new Date(), 30);
9515
- downloadUrlExpiresAt = findMinDate([
9516
- downloadUrlExpiresAt,
9517
- maxExpirationDate
9518
- ]);
9519
- }
9520
- return [
9521
- 4,
9522
- Promise.all([
9523
- fileAccessor.getSignedUrl({
9524
- action: 'read',
9525
- expiresAt: downloadUrlExpiresAt,
9526
- responseDisposition: responseDisposition !== null && responseDisposition !== void 0 ? responseDisposition : undefined,
9527
- responseType: asAdmin ? responseContentType !== null && responseContentType !== void 0 ? responseContentType : undefined : undefined // can only be set by admins
9528
- }),
9529
- fileAccessor.getMetadata()
9530
- ])
9531
- ];
9532
- case 2:
9533
- _ref = _sliced_to_array.apply(void 0, [
9534
- _state.sent(),
9535
- 2
9536
- ]), downloadUrl = _ref[0], metadata = _ref[1];
9537
- result = {
9538
- url: downloadUrl,
9539
- fileName: metadata.name ? slashPathDetails(metadata.name).end : undefined,
9540
- mimeType: responseContentType !== null && responseContentType !== void 0 ? responseContentType : metadata.contentType,
9541
- expiresAt: unixDateTimeSecondsNumberFromDate(downloadUrlExpiresAt)
9542
- };
9543
- return [
9544
- 3,
9545
- 4
9546
- ];
9547
- case 3:
9548
- throw internalServerError('Signed url function appears to not be avalable.');
9549
- case 4:
9638
+ result = _state.sent();
9550
9639
  return [
9551
9640
  2,
9552
- result
9641
+ result.success[0]
9553
9642
  ];
9554
9643
  }
9555
9644
  });
@@ -9560,6 +9649,59 @@ function _ts_generator$4(thisArg, body) {
9560
9649
  })();
9561
9650
  });
9562
9651
  }
9652
+ /**
9653
+ * Factory for the `downloadMultipleStorageFiles` action.
9654
+ *
9655
+ * Generates signed download URLs for multiple {@link StorageFile} documents in a single call.
9656
+ * By default, individual failures are collected in the errors array rather than failing the entire batch.
9657
+ * Set `throwOnFirstError` in params to throw on the first failure instead.
9658
+ *
9659
+ * @param context - the storage file server actions context
9660
+ * @returns an async transform-and-validate function that generates signed download URLs for multiple files
9661
+ */ function downloadMultipleStorageFilesFactory(context) {
9662
+ var firebaseServerActionTransformFunctionFactory = context.firebaseServerActionTransformFunctionFactory;
9663
+ var downloadMultipleStorageFiles = _downloadMultipleStorageFilesFactory(context);
9664
+ return firebaseServerActionTransformFunctionFactory(downloadMultipleStorageFilesParamsType, function(params) {
9665
+ return _async_to_generator$4(function() {
9666
+ var files, asAdmin, expiresAt, expiresIn, responseDisposition, responseContentType, throwOnFirstError;
9667
+ return _ts_generator$4(this, function(_state) {
9668
+ files = params.files, asAdmin = params.asAdmin, expiresAt = params.expiresAt, expiresIn = params.expiresIn, responseDisposition = params.responseDisposition, responseContentType = params.responseContentType, throwOnFirstError = params.throwOnFirstError;
9669
+ return [
9670
+ 2,
9671
+ function(storageFileDocuments) {
9672
+ return _async_to_generator$4(function() {
9673
+ var items;
9674
+ return _ts_generator$4(this, function(_state) {
9675
+ items = files.map(function(file, i) {
9676
+ return {
9677
+ key: file.key,
9678
+ storageFileDocument: storageFileDocuments === null || storageFileDocuments === void 0 ? void 0 : storageFileDocuments[i],
9679
+ expiresAt: file.expiresAt,
9680
+ expiresIn: file.expiresIn,
9681
+ responseDisposition: file.responseDisposition,
9682
+ responseContentType: file.responseContentType
9683
+ };
9684
+ });
9685
+ return [
9686
+ 2,
9687
+ downloadMultipleStorageFiles({
9688
+ items: items,
9689
+ asAdmin: asAdmin,
9690
+ expiresAt: expiresAt,
9691
+ expiresIn: expiresIn,
9692
+ responseDisposition: responseDisposition,
9693
+ responseContentType: responseContentType,
9694
+ throwOnFirstError: throwOnFirstError !== null && throwOnFirstError !== void 0 ? throwOnFirstError : false
9695
+ })
9696
+ ];
9697
+ });
9698
+ })();
9699
+ }
9700
+ ];
9701
+ });
9702
+ })();
9703
+ });
9704
+ }
9563
9705
  /**
9564
9706
  * Internal factory that creates a function for creating a {@link StorageFileGroup} document
9565
9707
  * within a Firestore transaction.
@@ -12415,4 +12557,4 @@ function _ts_generator(thisArg, body) {
12415
12557
  };
12416
12558
  }
12417
12559
 
12418
- export { AbstractAppNotificationModule, BASE_NOTIFICATION_SERVER_ACTION_CONTEXT_TOKEN, BASE_STORAGE_FILE_SERVER_ACTION_CONTEXT_TOKEN, GlobalNotificationModule, KNOWN_BUT_UNCONFIGURED_NOTIFICATION_TEMPLATE_TYPE_DELETE_AFTER_RETRY_ATTEMPTS, KNOWN_BUT_UNCONFIGURED_NOTIFICATION_TEMPLATE_TYPE_HOURS_DELAY, MAILGUN_NOTIFICATION_EMAIL_SEND_SERVICE_DEFAULT_MAX_BATCH_SIZE_PER_REQUEST, MAKE_TEMPLATE_FOR_NOTIFICATION_RELATED_MODEL_INITIALIZATION_FUNCTION_DELETE_RESPONSE, MAKE_TEMPLATE_FOR_STORAGEFILE_RELATED_MODEL_INITIALIZATION_FUNCTION_DELETE_RESPONSE, MutableNotificationExpediteService, NOTIFICATION_BOX_NOT_INITIALIZED_DELAY_MINUTES, NOTIFICATION_INIT_SERVER_ACTIONS_CONTEXT_CONFIG_TOKEN, NOTIFICATION_MAX_SEND_ATTEMPTS, NOTIFICATION_SERVER_ACTION_CONTEXT_TOKEN, NOTIFICATION_TASK_MINIMUM_SET_AT_THROTTLE_TIME_MINUTES, NOTIFICATION_TASK_TYPE_FAILURE_DELAY_HOURS, NOTIFICATION_TASK_TYPE_FAILURE_DELAY_MS, NOTIFICATION_TASK_TYPE_MAX_SEND_ATTEMPTS, NOTIFICATION_TEMPLATE_SERVICE_CONFIGS_ARRAY_TOKEN, NOTIFICATION_TEMPLATE_SERVICE_DEFAULTS_OVERRIDE_TOKEN, NotificationExpediteService, NotificationInitServerActions, NotificationSendService, NotificationServerActions, NotificationTaskService, NotificationTaskSubTaskMissingRequiredDataTermination, NotificationTemplateService, SEND_QUEUE_NOTIFICATIONS_TASK_EXCESS_THRESHOLD, STORAGE_FILE_INIT_SERVER_ACTIONS_CONTEXT_CONFIG_TOKEN, STORAGE_FILE_SERVER_ACTION_CONTEXT_TOKEN, StorageFileInitServerActions, StorageFileInitializeFromUploadService, StorageFileServerActions, UNKNOWN_NOTIFICATION_TASK_TYPE_DELETE_AFTER_RETRY_ATTEMPTS, UNKNOWN_NOTIFICATION_TASK_TYPE_HOURS_DELAY, UNKNOWN_NOTIFICATION_TEMPLATE_TYPE_DELETE_AFTER_RETRY_ATTEMPTS, UNKNOWN_NOTIFICATION_TEMPLATE_TYPE_HOURS_DELAY, _initializeStorageFileFromUploadFileFactory, _processStorageFileInTransactionFactory, _syncStorageFileWithGroupsInTransactionFactory, allStorageFileGroupStorageFileProcessingPurposeSubtaskProcessors, appNotificationModuleMetadata, appStorageFileModuleMetadata, cleanupSentNotificationsFactory, createNotificationBoxFactory, createNotificationBoxInTransactionFactory, createNotificationIdRequiredError, createNotificationSummaryFactory, createNotificationUserFactory, createOrRunUniqueNotificationDocument, createStorageFileFactory, createStorageFileGroupFactory, createStorageFileGroupInTransactionFactory, createStorageFileGroupInputError, deleteAllQueuedStorageFilesFactory, deleteStorageFileFactory, downloadStorageFileFactory, expandNotificationRecipients, exportMutableNotificationExpediteService, firestoreNotificationSummarySendService, ignoreSendNotificationTextSendService, initializeAllApplicableNotificationBoxesFactory, initializeAllApplicableNotificationSummariesFactory, initializeAllApplicableStorageFileGroupsFactory, initializeAllStorageFilesFromUploadsFactory, initializeNotificationBoxFactory, initializeNotificationBoxInTransactionFactory, initializeNotificationModelInTransaction, initializeNotificationSummaryFactory, initializeNotificationSummaryInTransactionFactory, initializeStorageFileFromUploadFactory, initializeStorageFileGroupFactory, initializeStorageFileGroupInTransactionFactory, initializeStorageFileModelInTransaction, mailgunNotificationEmailSendService, makeNewNotificationSummaryTemplate, markStorageFileForDeleteTemplate, notificationBoxDoesNotExist, notificationBoxExclusionTargetInvalidError, notificationBoxExistsForModelError, notificationBoxRecipientDoesNotExistsError, notificationBoxUnregistredModelTypeInitializationError, notificationExpediteServiceInstance, notificationInitServerActions, notificationInitServerActionsFactory, notificationModelAlreadyInitializedError, notificationServerActions, notificationServerActionsContextFactory, notificationServerActionsFactory, notificationTaskService, notificationTaskSubTaskMissingRequiredDataTermination, notificationTaskSubtaskNotificationTaskHandlerFactory, notificationTemplateServiceInstance, notificationUserBlockedFromBeingAddedToRecipientsError, notificationUserInvalidUidForCreateError, notificationUserLockedConfigFromBeingUpdatedError, processAllQueuedStorageFilesFactory, processStorageFileFactory, provideMutableNotificationExpediteService, queryAndFlagStorageFilesForDelete, regenerateAllFlaggedStorageFileGroupsContentFactory, regenerateStorageFileGroupContentFactory, resyncAllNotificationUsersFactory, resyncNotificationUserFactory, sendNotificationFactory, sendQueuedNotificationsFactory, storageFileAlreadyProcessedError, storageFileCannotBeDeletedYetError, storageFileGroupQueuedForInitializationError, storageFileGroupZipStorageFileProcessingPurposeSubtaskProcessor, storageFileInitServerActions, storageFileInitServerActionsFactory, storageFileInitializeFromUploadService, storageFileInitializeFromUploadServiceInitializerResultPermanentFailure, storageFileModelAlreadyInitializedError, storageFileNotFlaggedForDeletionError, storageFileNotFlaggedForGroupsSyncError, storageFileProcessingNotAllowedForInvalidStateError, storageFileProcessingNotAvailableForTypeError, storageFileProcessingNotQueuedForProcessingError, storageFileProcessingNotificationTaskHandler, storageFileProcessingNotificationTaskHandlerDefaultCleanup, storageFileServerActions, storageFileServerActionsContextFactory, storageFileServerActionsFactory, syncAllFlaggedStorageFilesWithGroupsFactory, syncStorageFileWithGroupsFactory, updateNotificationBoxFactory, updateNotificationBoxRecipientExclusionInTransactionFactory, updateNotificationBoxRecipientFactory, updateNotificationBoxRecipientInTransactionFactory, updateNotificationSummaryFactory, updateNotificationUserFactory, updateNotificationUserNotificationBoxRecipientConfig, updateStorageFileFactory, updateStorageFileGroupFactory, uploadedFileDoesNotExistError, uploadedFileInitializationDiscardedError, uploadedFileInitializationFailedError, uploadedFileIsNotAllowedToBeInitializedError };
12560
+ export { AbstractAppNotificationModule, BASE_NOTIFICATION_SERVER_ACTION_CONTEXT_TOKEN, BASE_STORAGE_FILE_SERVER_ACTION_CONTEXT_TOKEN, DEFAULT_DOWNLOAD_MULTIPLE_STORAGE_FILES_MAX_PARALLEL_TASKS, GlobalNotificationModule, KNOWN_BUT_UNCONFIGURED_NOTIFICATION_TEMPLATE_TYPE_DELETE_AFTER_RETRY_ATTEMPTS, KNOWN_BUT_UNCONFIGURED_NOTIFICATION_TEMPLATE_TYPE_HOURS_DELAY, MAILGUN_NOTIFICATION_EMAIL_SEND_SERVICE_DEFAULT_MAX_BATCH_SIZE_PER_REQUEST, MAKE_TEMPLATE_FOR_NOTIFICATION_RELATED_MODEL_INITIALIZATION_FUNCTION_DELETE_RESPONSE, MAKE_TEMPLATE_FOR_STORAGEFILE_RELATED_MODEL_INITIALIZATION_FUNCTION_DELETE_RESPONSE, MutableNotificationExpediteService, NOTIFICATION_BOX_NOT_INITIALIZED_DELAY_MINUTES, NOTIFICATION_INIT_SERVER_ACTIONS_CONTEXT_CONFIG_TOKEN, NOTIFICATION_MAX_SEND_ATTEMPTS, NOTIFICATION_SERVER_ACTION_CONTEXT_TOKEN, NOTIFICATION_TASK_MINIMUM_SET_AT_THROTTLE_TIME_MINUTES, NOTIFICATION_TASK_TYPE_FAILURE_DELAY_HOURS, NOTIFICATION_TASK_TYPE_FAILURE_DELAY_MS, NOTIFICATION_TASK_TYPE_MAX_SEND_ATTEMPTS, NOTIFICATION_TEMPLATE_SERVICE_CONFIGS_ARRAY_TOKEN, NOTIFICATION_TEMPLATE_SERVICE_DEFAULTS_OVERRIDE_TOKEN, NotificationExpediteService, NotificationInitServerActions, NotificationSendService, NotificationServerActions, NotificationTaskService, NotificationTaskSubTaskMissingRequiredDataTermination, NotificationTemplateService, SEND_QUEUE_NOTIFICATIONS_TASK_EXCESS_THRESHOLD, STORAGE_FILE_INIT_SERVER_ACTIONS_CONTEXT_CONFIG_TOKEN, STORAGE_FILE_SERVER_ACTION_CONTEXT_TOKEN, StorageFileInitServerActions, StorageFileInitializeFromUploadService, StorageFileServerActions, UNKNOWN_NOTIFICATION_TASK_TYPE_DELETE_AFTER_RETRY_ATTEMPTS, UNKNOWN_NOTIFICATION_TASK_TYPE_HOURS_DELAY, UNKNOWN_NOTIFICATION_TEMPLATE_TYPE_DELETE_AFTER_RETRY_ATTEMPTS, UNKNOWN_NOTIFICATION_TEMPLATE_TYPE_HOURS_DELAY, _initializeStorageFileFromUploadFileFactory, _processStorageFileInTransactionFactory, _syncStorageFileWithGroupsInTransactionFactory, allStorageFileGroupStorageFileProcessingPurposeSubtaskProcessors, appNotificationModuleMetadata, appStorageFileModuleMetadata, cleanupSentNotificationsFactory, createNotificationBoxFactory, createNotificationBoxInTransactionFactory, createNotificationIdRequiredError, createNotificationSummaryFactory, createNotificationUserFactory, createOrRunUniqueNotificationDocument, createStorageFileFactory, createStorageFileGroupFactory, createStorageFileGroupInTransactionFactory, createStorageFileGroupInputError, deleteAllQueuedStorageFilesFactory, deleteStorageFileFactory, downloadMultipleStorageFilesFactory, downloadStorageFileFactory, expandNotificationRecipients, exportMutableNotificationExpediteService, firestoreNotificationSummarySendService, ignoreSendNotificationTextSendService, initializeAllApplicableNotificationBoxesFactory, initializeAllApplicableNotificationSummariesFactory, initializeAllApplicableStorageFileGroupsFactory, initializeAllStorageFilesFromUploadsFactory, initializeNotificationBoxFactory, initializeNotificationBoxInTransactionFactory, initializeNotificationModelInTransaction, initializeNotificationSummaryFactory, initializeNotificationSummaryInTransactionFactory, initializeStorageFileFromUploadFactory, initializeStorageFileGroupFactory, initializeStorageFileGroupInTransactionFactory, initializeStorageFileModelInTransaction, mailgunNotificationEmailSendService, makeNewNotificationSummaryTemplate, markStorageFileForDeleteTemplate, notificationBoxDoesNotExist, notificationBoxExclusionTargetInvalidError, notificationBoxExistsForModelError, notificationBoxRecipientDoesNotExistsError, notificationBoxUnregistredModelTypeInitializationError, notificationExpediteServiceInstance, notificationInitServerActions, notificationInitServerActionsFactory, notificationModelAlreadyInitializedError, notificationServerActions, notificationServerActionsContextFactory, notificationServerActionsFactory, notificationTaskService, notificationTaskSubTaskMissingRequiredDataTermination, notificationTaskSubtaskNotificationTaskHandlerFactory, notificationTemplateServiceInstance, notificationUserBlockedFromBeingAddedToRecipientsError, notificationUserInvalidUidForCreateError, notificationUserLockedConfigFromBeingUpdatedError, processAllQueuedStorageFilesFactory, processStorageFileFactory, provideMutableNotificationExpediteService, queryAndFlagStorageFilesForDelete, regenerateAllFlaggedStorageFileGroupsContentFactory, regenerateStorageFileGroupContentFactory, resyncAllNotificationUsersFactory, resyncNotificationUserFactory, sendNotificationFactory, sendQueuedNotificationsFactory, storageFileAlreadyProcessedError, storageFileCannotBeDeletedYetError, storageFileGroupQueuedForInitializationError, storageFileGroupZipStorageFileProcessingPurposeSubtaskProcessor, storageFileInitServerActions, storageFileInitServerActionsFactory, storageFileInitializeFromUploadService, storageFileInitializeFromUploadServiceInitializerResultPermanentFailure, storageFileModelAlreadyInitializedError, storageFileNotFlaggedForDeletionError, storageFileNotFlaggedForGroupsSyncError, storageFileProcessingNotAllowedForInvalidStateError, storageFileProcessingNotAvailableForTypeError, storageFileProcessingNotQueuedForProcessingError, storageFileProcessingNotificationTaskHandler, storageFileProcessingNotificationTaskHandlerDefaultCleanup, storageFileServerActions, storageFileServerActionsContextFactory, storageFileServerActionsFactory, syncAllFlaggedStorageFilesWithGroupsFactory, syncStorageFileWithGroupsFactory, updateNotificationBoxFactory, updateNotificationBoxRecipientExclusionInTransactionFactory, updateNotificationBoxRecipientFactory, updateNotificationBoxRecipientInTransactionFactory, updateNotificationSummaryFactory, updateNotificationUserFactory, updateNotificationUserNotificationBoxRecipientConfig, updateStorageFileFactory, updateStorageFileGroupFactory, uploadedFileDoesNotExistError, uploadedFileInitializationDiscardedError, uploadedFileInitializationFailedError, uploadedFileIsNotAllowedToBeInitializedError };
@@ -1,15 +1,15 @@
1
1
  {
2
2
  "name": "@dereekb/firebase-server/model",
3
- "version": "13.6.9",
3
+ "version": "13.6.11",
4
4
  "peerDependencies": {
5
- "@dereekb/analytics": "13.6.9",
6
- "@dereekb/date": "13.6.9",
7
- "@dereekb/firebase": "13.6.9",
8
- "@dereekb/firebase-server": "13.6.9",
9
- "@dereekb/model": "13.6.9",
10
- "@dereekb/nestjs": "13.6.9",
11
- "@dereekb/rxjs": "13.6.9",
12
- "@dereekb/util": "13.6.9",
5
+ "@dereekb/analytics": "13.6.11",
6
+ "@dereekb/date": "13.6.11",
7
+ "@dereekb/firebase": "13.6.11",
8
+ "@dereekb/firebase-server": "13.6.11",
9
+ "@dereekb/model": "13.6.11",
10
+ "@dereekb/nestjs": "13.6.11",
11
+ "@dereekb/rxjs": "13.6.11",
12
+ "@dereekb/util": "13.6.11",
13
13
  "@nestjs/common": "^11.1.17",
14
14
  "@nestjs/config": "^4.0.3",
15
15
  "archiver": "^7.0.0",
@@ -1,10 +1,10 @@
1
- import { type FirestoreContextReference, type InitializeStorageFileFromUploadParams, type AsyncStorageFileCreateAction, type StorageFileFirestoreCollections, type ProcessStorageFileParams, type StorageFileDocument, type ProcessStorageFileResult, type CreateStorageFileParams, type AsyncStorageFileUpdateAction, type UpdateStorageFileParams, type NotificationFirestoreCollections, type FirebaseStorageAccessorFile, type InitializeAllStorageFilesFromUploadsResult, type InitializeAllStorageFilesFromUploadsParams, type ProcessAllQueuedStorageFilesParams, type ProcessAllQueuedStorageFilesResult, type DeleteAllQueuedStorageFilesParams, type DeleteAllQueuedStorageFilesResult, type DeleteStorageFileParams, type AsyncStorageFileDeleteAction, type StorageFile, type DownloadStorageFileParams, type DownloadStorageFileResult, type SyncStorageFileWithGroupsParams, type SyncAllFlaggedStorageFilesWithGroupsParams, type SyncAllFlaggedStorageFilesWithGroupsResult, type SyncStorageFileWithGroupsResult, type RegenerateAllFlaggedStorageFileGroupsContentParams, type RegenerateAllFlaggedStorageFileGroupsContentResult, type RegenerateStorageFileGroupContentParams, type RegenerateStorageFileGroupContentResult, type StorageFileGroupDocument, type AsyncStorageFileGroupCreateAction, type CreateStorageFileGroupParams, type Transaction, type StorageFileGroup, type StorageFileGroupDocumentReferencePair, type StorageFileGroupId, type UpdateStorageFileGroupParams } from '@dereekb/firebase';
1
+ import { type FirestoreContextReference, type InitializeStorageFileFromUploadParams, type AsyncStorageFileCreateAction, type StorageFileFirestoreCollections, type ProcessStorageFileParams, type StorageFileDocument, type ProcessStorageFileResult, type CreateStorageFileParams, type AsyncStorageFileUpdateAction, type UpdateStorageFileParams, type NotificationFirestoreCollections, type FirebaseStorageAccessorFile, type InitializeAllStorageFilesFromUploadsResult, type InitializeAllStorageFilesFromUploadsParams, type ProcessAllQueuedStorageFilesParams, type ProcessAllQueuedStorageFilesResult, type DeleteAllQueuedStorageFilesParams, type DeleteAllQueuedStorageFilesResult, type DeleteStorageFileParams, type AsyncStorageFileDeleteAction, type StorageFile, type DownloadStorageFileParams, type DownloadStorageFileResult, type DownloadMultipleStorageFilesParams, type DownloadMultipleStorageFilesResult, type DownloadMultipleStorageFileSuccessItem, type FirestoreModelKey, type SyncStorageFileWithGroupsParams, type SyncAllFlaggedStorageFilesWithGroupsParams, type SyncAllFlaggedStorageFilesWithGroupsResult, type SyncStorageFileWithGroupsResult, type RegenerateAllFlaggedStorageFileGroupsContentParams, type RegenerateAllFlaggedStorageFileGroupsContentResult, type RegenerateStorageFileGroupContentParams, type RegenerateStorageFileGroupContentResult, type StorageFileGroupDocument, type AsyncStorageFileGroupCreateAction, type CreateStorageFileGroupParams, type Transaction, type StorageFileGroup, type StorageFileGroupDocumentReferencePair, type StorageFileGroupId, type UpdateStorageFileGroupParams } from '@dereekb/firebase';
2
2
  import { type FirebaseServerStorageServiceRef, type FirebaseServerActionsContext, type FirebaseServerAuthServiceRef } from '@dereekb/firebase-server';
3
3
  import { type TransformAndValidateFunctionResult } from '@dereekb/model';
4
4
  import { type InjectionToken } from '@nestjs/common';
5
5
  import { type NotificationExpediteServiceInstance, type NotificationExpediteServiceRef } from '../notification';
6
6
  import { type StorageFileInitializeFromUploadServiceRef } from './storagefile.upload.service';
7
- import { type Maybe } from '@dereekb/util';
7
+ import { type ContentDispositionString, type ContentTypeMimeType, type Maybe, type Milliseconds } from '@dereekb/util';
8
8
  /**
9
9
  * NestJS injection token for the {@link BaseStorageFileServerActionsContext}, providing
10
10
  * Firebase infrastructure, storage service, notification collections, and Firestore collections
@@ -53,6 +53,7 @@ export declare abstract class StorageFileServerActions {
53
53
  abstract deleteAllQueuedStorageFiles(params: DeleteAllQueuedStorageFilesParams): Promise<TransformAndValidateFunctionResult<DeleteAllQueuedStorageFilesParams, () => Promise<DeleteAllQueuedStorageFilesResult>>>;
54
54
  abstract deleteStorageFile(params: DeleteStorageFileParams): AsyncStorageFileDeleteAction<DeleteStorageFileParams>;
55
55
  abstract downloadStorageFile(params: DownloadStorageFileParams): Promise<TransformAndValidateFunctionResult<DownloadStorageFileParams, (storageFileDocument?: Maybe<StorageFileDocument>) => Promise<DownloadStorageFileResult>>>;
56
+ abstract downloadMultipleStorageFiles(params: DownloadMultipleStorageFilesParams): Promise<TransformAndValidateFunctionResult<DownloadMultipleStorageFilesParams, (storageFileDocuments?: Maybe<StorageFileDocument[]>) => Promise<DownloadMultipleStorageFilesResult>>>;
56
57
  abstract createStorageFileGroup(params: CreateStorageFileGroupParams): AsyncStorageFileGroupCreateAction<CreateStorageFileGroupParams>;
57
58
  abstract updateStorageFileGroup(params: UpdateStorageFileGroupParams): Promise<TransformAndValidateFunctionResult<UpdateStorageFileGroupParams, (storageFileGroupDocument: StorageFileGroupDocument) => Promise<StorageFileGroupDocument>>>;
58
59
  abstract syncStorageFileWithGroups(params: SyncStorageFileWithGroupsParams): Promise<TransformAndValidateFunctionResult<SyncStorageFileWithGroupsParams, (storageFileDocument: StorageFileDocument) => Promise<SyncStorageFileWithGroupsResult>>>;
@@ -216,17 +217,80 @@ export declare function deleteAllQueuedStorageFilesFactory(context: StorageFileS
216
217
  * @returns an async transform-and-validate function that deletes a StorageFile and its storage object
217
218
  */
218
219
  export declare function deleteStorageFileFactory(context: StorageFileServerActionsContext): import("@dereekb/model").TransformAndValidateFunctionResultFunction<DeleteStorageFileParams, (inputStorageFileDocument: StorageFileDocument) => Promise<void>, object, unknown>;
220
+ /**
221
+ * Per-item input for the internal multiple-download factory.
222
+ *
223
+ * Per-file options override the defaults from {@link DownloadMultipleStorageFilesFactoryInput}.
224
+ * `asAdmin` is not per-file — it is controlled at the batch level only.
225
+ */
226
+ export interface DownloadMultipleStorageFilesFactoryInputItem {
227
+ readonly key: FirestoreModelKey;
228
+ readonly storageFileDocument?: Maybe<StorageFileDocument>;
229
+ readonly expiresAt?: Maybe<Date>;
230
+ readonly expiresIn?: Maybe<Milliseconds>;
231
+ readonly responseDisposition?: Maybe<ContentDispositionString>;
232
+ readonly responseContentType?: Maybe<ContentTypeMimeType>;
233
+ }
234
+ /**
235
+ * Input configuration for {@link _downloadMultipleStorageFilesFactory}.
236
+ *
237
+ * Top-level options serve as defaults. Per-item options in {@link DownloadMultipleStorageFilesFactoryInputItem}
238
+ * override them when defined.
239
+ *
240
+ * @example
241
+ * ```ts
242
+ * const result = await downloadMultipleStorageFiles({
243
+ * items: [{ key: 'storageFile/abc' }],
244
+ * expiresIn: 1800000,
245
+ * throwOnFirstError: true
246
+ * });
247
+ * ```
248
+ */
249
+ export interface DownloadMultipleStorageFilesFactoryInput {
250
+ readonly items: DownloadMultipleStorageFilesFactoryInputItem[];
251
+ readonly asAdmin?: Maybe<boolean>;
252
+ readonly expiresAt?: Maybe<Date>;
253
+ readonly expiresIn?: Maybe<Milliseconds>;
254
+ readonly responseDisposition?: Maybe<ContentDispositionString>;
255
+ readonly responseContentType?: Maybe<ContentTypeMimeType>;
256
+ /**
257
+ * When true, throws on the first download failure instead of collecting errors.
258
+ *
259
+ * Used by the single-download path ({@link downloadStorageFileFactory}).
260
+ */
261
+ readonly throwOnFirstError?: Maybe<boolean>;
262
+ /**
263
+ * Maximum number of concurrent download operations.
264
+ *
265
+ * Defaults to {@link DEFAULT_DOWNLOAD_MULTIPLE_STORAGE_FILES_MAX_PARALLEL_TASKS}.
266
+ */
267
+ readonly maxParallelTasks?: Maybe<number>;
268
+ }
269
+ /**
270
+ * Default maximum number of concurrent download operations when batch-downloading StorageFiles.
271
+ */
272
+ export declare const DEFAULT_DOWNLOAD_MULTIPLE_STORAGE_FILES_MAX_PARALLEL_TASKS = 5;
219
273
  /**
220
274
  * Factory for the `downloadStorageFile` action.
221
275
  *
222
276
  * Generates a signed download URL for a {@link StorageFile}'s associated Cloud Storage file.
223
- * The URL expires after the configured duration. Supports loading the storage file document
224
- * by key if not provided directly.
277
+ * Delegates to {@link _downloadMultipleStorageFilesFactory} with a single item and `throwOnFirstError: true`.
225
278
  *
226
279
  * @param context - the storage file server actions context
227
280
  * @returns an async transform-and-validate function that generates a signed download URL
228
281
  */
229
- export declare function downloadStorageFileFactory(context: StorageFileServerActionsContext): import("@dereekb/model").TransformAndValidateFunctionResultFunction<DownloadStorageFileParams, (storageFileDocument?: Maybe<StorageFileDocument>) => Promise<DownloadStorageFileResult>, object, unknown>;
282
+ export declare function downloadStorageFileFactory(context: StorageFileServerActionsContext): import("@dereekb/model").TransformAndValidateFunctionResultFunction<DownloadStorageFileParams, (storageFileDocument?: Maybe<StorageFileDocument>) => Promise<DownloadMultipleStorageFileSuccessItem>, object, unknown>;
283
+ /**
284
+ * Factory for the `downloadMultipleStorageFiles` action.
285
+ *
286
+ * Generates signed download URLs for multiple {@link StorageFile} documents in a single call.
287
+ * By default, individual failures are collected in the errors array rather than failing the entire batch.
288
+ * Set `throwOnFirstError` in params to throw on the first failure instead.
289
+ *
290
+ * @param context - the storage file server actions context
291
+ * @returns an async transform-and-validate function that generates signed download URLs for multiple files
292
+ */
293
+ export declare function downloadMultipleStorageFilesFactory(context: StorageFileServerActionsContext): import("@dereekb/model").TransformAndValidateFunctionResultFunction<DownloadMultipleStorageFilesParams, (storageFileDocuments?: Maybe<StorageFileDocument[]>) => Promise<DownloadMultipleStorageFilesResult>, object, unknown>;
230
294
  /**
231
295
  * Used for creating a new NotificationBox within a transaction.
232
296
  *
package/oidc/package.json CHANGED
@@ -1,16 +1,16 @@
1
1
  {
2
2
  "name": "@dereekb/firebase-server/oidc",
3
- "version": "13.6.9",
3
+ "version": "13.6.11",
4
4
  "peerDependencies": {
5
- "@dereekb/analytics": "13.6.9",
6
- "@dereekb/date": "13.6.9",
7
- "@dereekb/firebase": "13.6.9",
8
- "@dereekb/firebase-server": "13.6.9",
9
- "@dereekb/model": "13.6.9",
10
- "@dereekb/nestjs": "13.6.9",
11
- "@dereekb/rxjs": "13.6.9",
12
- "@dereekb/util": "13.6.9",
13
- "@dereekb/zoho": "13.6.9",
5
+ "@dereekb/analytics": "13.6.11",
6
+ "@dereekb/date": "13.6.11",
7
+ "@dereekb/firebase": "13.6.11",
8
+ "@dereekb/firebase-server": "13.6.11",
9
+ "@dereekb/model": "13.6.11",
10
+ "@dereekb/nestjs": "13.6.11",
11
+ "@dereekb/rxjs": "13.6.11",
12
+ "@dereekb/util": "13.6.11",
13
+ "@dereekb/zoho": "13.6.11",
14
14
  "@nestjs/common": "^11.1.17",
15
15
  "@nestjs/config": "^4.0.3",
16
16
  "express": "^5.0.0",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@dereekb/firebase-server",
3
- "version": "13.6.9",
3
+ "version": "13.6.11",
4
4
  "exports": {
5
5
  "./test": {
6
6
  "module": "./test/index.esm.js",
@@ -43,15 +43,15 @@
43
43
  "main": "./index.cjs.js",
44
44
  "types": "./src/index.d.ts",
45
45
  "peerDependencies": {
46
- "@dereekb/analytics": "13.6.9",
47
- "@dereekb/date": "13.6.9",
48
- "@dereekb/dbx-core": "13.6.9",
49
- "@dereekb/firebase": "13.6.9",
50
- "@dereekb/model": "13.6.9",
51
- "@dereekb/nestjs": "13.6.9",
52
- "@dereekb/rxjs": "13.6.9",
53
- "@dereekb/util": "13.6.9",
54
- "@dereekb/zoho": "13.6.9",
46
+ "@dereekb/analytics": "13.6.11",
47
+ "@dereekb/date": "13.6.11",
48
+ "@dereekb/dbx-core": "13.6.11",
49
+ "@dereekb/firebase": "13.6.11",
50
+ "@dereekb/model": "13.6.11",
51
+ "@dereekb/nestjs": "13.6.11",
52
+ "@dereekb/rxjs": "13.6.11",
53
+ "@dereekb/util": "13.6.11",
54
+ "@dereekb/zoho": "13.6.11",
55
55
  "@google-cloud/firestore": "^7.11.6",
56
56
  "@google-cloud/storage": "^7.19.0",
57
57
  "@nestjs/common": "^11.1.17",
@@ -1,10 +1,11 @@
1
- import { type ClassType, type Getter, type WebsitePath } from '@dereekb/util';
1
+ import { type ClassType, type Getter, Maybe, type WebsitePath } from '@dereekb/util';
2
2
  import { type INestApplication, type INestApplicationContext, type NestApplicationOptions, type Provider } from '@nestjs/common';
3
3
  import express from 'express';
4
4
  import type * as admin from 'firebase-admin';
5
5
  import { type StorageBucketId } from '@dereekb/firebase';
6
6
  import { type FirebaseServerEnvironmentConfig } from '../env/env.config';
7
7
  import { type GlobalRoutePrefixConfig } from './middleware/globalprefix';
8
+ import { type NestServerAssetConfig } from './app.module';
8
9
  /**
9
10
  * A running NestJS server instance backed by Express, paired with a lazy promise getter for the NestJS application context.
10
11
  */
@@ -102,6 +103,13 @@ export interface NestServerInstanceConfig<T> {
102
103
  * Optional configuration function
103
104
  */
104
105
  readonly configureNestServerInstance?: ConfigureNestServerInstanceFunction;
106
+ /**
107
+ * Optional asset loader configuration.
108
+ *
109
+ * When provided, configures the {@link AssetLoader} with the given settings.
110
+ * The AssetLoader is always provided globally regardless of this config.
111
+ */
112
+ readonly assets?: Maybe<NestServerAssetConfig>;
105
113
  }
106
114
  export interface NestFirebaseServerEnvironmentConfig {
107
115
  readonly environment: FirebaseServerEnvironmentConfig;