import { type NeedsSyncBoolean, type Maybe } from '@dereekb/util'; import { type GrantedReadRole, type GrantedUpdateRole } from '@dereekb/model'; import { AbstractFirestoreDocument, type CollectionReference, type FirestoreCollection, type FirestoreContext, type FirebaseAuthUserId, type FirebaseAuthOwnershipKey, type StoragePath, type StorageSignedDownloadUrl, type StorageDownloadUrl, type SavedToFirestoreIfTrue, type OneWayFlatFirestoreModelKey, type FirestoreCollectionModelKey } from '../../common'; import { type StorageFilePurposeSubgroup, type StorageFileGroupId, type StorageFileGroupRelatedStorageFilePurpose, type StorageFileId, type StorageFileMetadata, type StorageFilePurpose, type StorageFileDisplayName } from './storagefile.id'; import { type NotificationKey } from '../notification'; /** * @module storagefile * * Defines the StorageFile and StorageFileGroup Firestore models for managing files in Google Cloud Storage. * * **StorageFile** tracks individual files with ownership, state machine (INIT → OK → QUEUED_FOR_DELETE), * processing lifecycle (INIT_OR_NONE → QUEUED → PROCESSING → SUCCESS/FAILED), and group membership. * Files are created either directly, from uploads, or for a {@link StorageFileGroup}. * * **StorageFileGroup** aggregates multiple StorageFiles around a related model (e.g., a user or entity). * Groups support automatic zip generation and content regeneration via the `re` flag. * * Server-side processing is handled via NotificationTask integration — see `@dereekb/firebase-server/model` * for the StorageFile action service. */ /** * Abstract base providing access to StorageFile and StorageFileGroup Firestore collections. * * Implement this in your app module to wire up the collections for dependency injection. * * @dbxModelGroup StorageFile */ export declare abstract class StorageFileFirestoreCollections { abstract readonly storageFileCollection: StorageFileFirestoreCollection; abstract readonly storageFileGroupCollection: StorageFileGroupFirestoreCollection; } /** * Union of all StorageFile-related model identity types. */ export type StorageFileTypes = typeof storageFileIdentity | typeof storageFileGroupIdentity; /** * StorageFile-related model that is initialized asynchronously at a later time. * * Examples: StorageFileGroup */ export interface InitializedStorageFileModel { /** * True if this model needs to be sync'd/initialized with the original model. * * Is set false if/when "fi" is set true. * * @dbxModelVariable needsSync */ s?: Maybe; /** * True if this model has been flagged invalid. * * This is for cases where the model cannot be properly initiialized. * * Typically this results in this model and related data being deleted. * * @dbxModelVariable flaggedInvalid */ fi?: Maybe; } export declare const storageFileIdentity: import("../..").RootFirestoreModelIdentity<"storageFile", "sf">; /** * The key for a StorageFile that is generated/related to a StorageFileGroup. * * For example, a StorageFile id for the Zip file generated by a StorageFileGroup with id "123" and the zip purpose "sfg_zip" would be "sfg_zip_sf123". */ export type StorageFileGroupCreatedStorageFileKey

= FirestoreCollectionModelKey; /** * Creates a StorageFileGroupCreatedStorageFileKey from the input StorageFileGroupId and purpose. * * @param purpose - the purpose identifying the type of file within the group * @param storageFileGroupId - the ID of the parent StorageFileGroup * @returns a deterministic FirestoreCollectionModelKey for the storage file */ export declare function storageFileGroupCreatedStorageFileKey

(purpose: P, storageFileGroupId: StorageFileGroupId): StorageFileGroupCreatedStorageFileKey

; /** * Creates a StorageFileGroupCreatedStorageFileKey from the input StorageFileGroupId and pre-configured purpose. */ export type StorageFileGroupCreateStorageFileKeyFactory

= (storageFileGroupId: StorageFileGroupId) => StorageFileGroupCreatedStorageFileKey

; /** * Creates a factory function for generating StorageFileGroupCreatedStorageFileKey values using the input purpose. * * @param purpose The purpose of the StorageFileGroupCreatedStorageFileKey. * @returns A factory function that takes a StorageFileGroupId and returns a StorageFileGroupCreatedStorageFileKey. */ export declare function storageFileGroupCreateStorageFileKeyFactory

(purpose: P): StorageFileGroupCreateStorageFileKeyFactory

; /** * This key is used in the CustomStorageMetadata of a Firebase Storage file that is associated with a StorageFile to link the file to the StorageFile. */ export declare const STORAGEFILE_RELATED_FILE_METADATA_KEY = "__sf__"; /** * CustomStorageMetadata interface that is assigned to files that are associated with a StorageFile. */ export interface StorageFileRelatedFileMetadata { /** * The StorageFile id that this file is associated with. */ readonly [STORAGEFILE_RELATED_FILE_METADATA_KEY]?: Maybe; } /** * How a StorageFile was created, which affects document ID generation and initialization behavior. * * When {@link FOR_STORAGE_FILE_GROUP} is used, the StorageFile ID is derived deterministically * from the parent StorageFileGroup, enabling predictable document references. */ export declare enum StorageFileCreationType { /** * No info about how this file was created. */ NONE = 0, /** * The StorageFile was directly created. */ DIRECTLY_CREATED = 1, /** * The StorageFile was initialized from an uploaded file. */ INIT_FROM_UPLOAD = 2, /** * This StorageFile was created by/for a StorageFileGroup. * * When creating a StorageFile via createStorageFileDocumentPairFactory(), this flag changes the behavior to use a parent * StorageFileGroup to derive the created StorageFile's identifier. */ FOR_STORAGE_FILE_GROUP = 3 } /** * Lifecycle state of a StorageFile document. * * State transitions: * - `INIT` → `OK` (successful initialization) or `INVALID` (failed initialization) * - `OK` → `QUEUED_FOR_DELETE` (flagged for deletion) * - `INVALID` → (deleted after a period) * - `QUEUED_FOR_DELETE` → (deleted once `sdat` is reached) */ export declare enum StorageFileState { /** * The StorageFile has no state, or is just being initialized. */ INIT = 0, /** * The StorageFile failed to initialize properly and is considered invalid. * * StorageFiles that are marked invalid are deleted after a period of time. * * Files that are invalid cannot be processed. */ INVALID = 1, /** * The StorageFile has been initialized and is ok. */ OK = 2, /** * A previously OK file that is now queued for deletion. */ QUEUED_FOR_DELETE = 3 } /** * Processing lifecycle state for a StorageFile. * * Processing is driven by NotificationTask integration. State transitions: * - `INIT_OR_NONE` → `QUEUED_FOR_PROCESSING` (flagged for processing) * - `QUEUED_FOR_PROCESSING` → `PROCESSING` (NotificationTask created) * - `PROCESSING` → `SUCCESS` or `FAILED` * - `FAILED` → `QUEUED_FOR_PROCESSING` (retry) or `DO_NOT_PROCESS` * - `SUCCESS` → `QUEUED_FOR_PROCESSING` (reprocess) or `ARCHIVED` * - `ARCHIVED` and `DO_NOT_PROCESS` are terminal states. * * Use {@link canQueueStorageFileForProcessing} to check if a file can be re-queued. */ export declare enum StorageFileProcessingState { /** * The StorageFile has no processing state or is just being initialized. */ INIT_OR_NONE = 0, /** * The StorageFile is flagged for processing, which will create a NotificationTask for it. */ QUEUED_FOR_PROCESSING = 1, /** * The StorageFile has an associated NotificationTask for it. */ PROCESSING = 2, /** * The StorageFile has encountered an error during processing. * * It can be queued for reprocessing. */ FAILED = 3, /** * The StorageFile has been processed or required no processing and is done. * * It can be queued for reprocessing. */ SUCCESS = 4, /** * The StorageFile has been archived. * * It cannot be queued for reprocessing. */ ARCHIVED = 5, /** * The StorageFile shouldn't be processed. * * It cannot be queued for reprocessing. */ DO_NOT_PROCESS = 6 } /** * Checks whether a StorageFile can safely be re-queued for processing. * * A file is eligible when it has a purpose set and its processing state allows re-queuing * (INIT_OR_NONE, FAILED, or SUCCESS). Files that are already QUEUED/PROCESSING, ARCHIVED, * or DO_NOT_PROCESS are not eligible. * * @param storageFile - the file's processing state (`ps`) and purpose (`p`) fields * @returns true if the file can be queued for processing * * @example * ```ts * if (canQueueStorageFileForProcessing(storageFile)) { * // safe to set ps = QUEUED_FOR_PROCESSING * } * ``` */ export declare function canQueueStorageFileForProcessing(storageFile: Pick): boolean; /** * Throttle duration (3 hours) after which a PROCESSING-state file is considered "stuck" * and eligible for retry checks. */ export declare const STORAGE_FILE_PROCESSING_STUCK_THROTTLE_CHECK_MS: number; /** * A Google Cloud public download URL for a StorageFile. * * This URL is not protected by authentication and is the permanent URL for the file. * * Consider using a StorageFileSignedDownloadUrl if the file should be protected. */ export type StorageFilePublicDownloadUrl = StorageDownloadUrl; /** * A Google Cloud signed download URL for a StorageFile. * * It expires after a period of time. */ export type StorageFileSignedDownloadUrl = StorageSignedDownloadUrl; /** * A download URL for a StorageFile. * * This can be a public download URL or a signed download URL. */ export type StorageFileDownloadUrl = StorageFilePublicDownloadUrl | StorageFileSignedDownloadUrl; /** * A StorageFile Firestore document that references a file in Google Cloud Storage. * * Tracks file ownership, lifecycle state ({@link StorageFileState}), processing state * ({@link StorageFileProcessingState}), group membership, and arbitrary metadata. Extends * {@link StoragePath} to carry the bucket and path of the underlying storage object. * * Server-side processing is driven by the NotificationTask system — see * `StorageFileActionServerActions` in `@dereekb/firebase-server/model`. * * @template M - type of the arbitrary metadata stored in the `d` field * @dbxModel */ export interface StorageFile extends StoragePath { /** * Created at date. * * @dbxModelVariable createdAt */ cat: Date; /** * Arbitrary display name for the file. * * This name is used in StorageFileGroup composite file generations, instead * of the file's normal path file name, if available. * * @dbxModelVariable displayName */ n?: Maybe; /** * Type of creation. * * @dbxModelVariable creationType */ ct?: Maybe; /** * State of the storage file. * * @dbxModelVariable fileState */ fs: StorageFileState; /** * Processing state of the storage file. * * The state is important for managing the processing of the StorageFile. * * Once processing is finished, the state determines whether or not the StorageFile can be processed again. * * @dbxModelVariable processingState */ ps: StorageFileProcessingState; /** * The NotificationTask key for this storage file. * * Set only if the StorageFile has an associated NotificationTask. * * Cleared once the processing stage is no longer PROCESSING. * * @dbxModelVariable processingNotificationKey */ pn?: Maybe; /** * The date that state was last updated to PROCESSING. * * Is used as a way to track if processing should be checked on. * * @dbxModelVariable processingAt */ pat?: Maybe; /** * The date that the cleanup step of the processing task was run, and the notification ended. * * @dbxModelVariable processingCleanupAt */ pcat?: Maybe; /** * User this file is associated with, if applicable. * * @dbxModelVariable userId */ u?: Maybe; /** * User who uploaded this file, if applicable. * * @dbxModelVariable uploadedBy */ uby?: Maybe; /** * Ownership key, if applicable. * * @dbxModelVariable ownerKey */ o?: Maybe; /** * Purpose of the file, if applicable. * * Is required for processing a StorageFile. * * @dbxModelVariable purpose */ p?: Maybe; /** * Subgroup of the purpose of the file, if applicable. * * If a StorageFilePurpose should have subgroups, then all StorageFiles should have subgroups too. * * @dbxModelVariable purposeSubgroup */ pg?: Maybe; /** * Arbitrary metadata attached to the StorageFile. * * @dbxModelVariable data */ d?: Maybe; /** * Scheduled delete at date. The StorageFile cannot be deleted before this set time. * * Is the main trigger for determining a StorageFile should be deleted. * * @dbxModelVariable scheduledDeleteAt */ sdat?: Maybe; /** * StorageFileGroup id(s) that this StorageFile should be associated with. * * These StorageFileGroup do not need to exist, and will be created when synchronization occurs. * * These groups by design should typically be pre-determined at the time the StorageFile is created and remain unchanged; timely removal of data from groups is not part of the design spec. * * When a StorageFile is updated to remove groups, the removal is eventually propogated to the StorageFileGroup(s) that it was associated with, * but there is no gurantee about timeliness when this will happen. StorageFiles, when deleted, are removed from StorageFileGroups immediately, which are flagged for another regeneration automatically. * * In cases where you need to have the StorageFileGroup be updated promptly, you should manually handle those cases. * * @dbxModelVariable groupIds */ g: StorageFileGroupId[]; /** * If true, this file should be re-synced with each StorageFileGroup that it references. * * @dbxModelVariable groupsNeedSync */ gs?: Maybe; } /** * Granted roles for creating a download link to the StorageFile's file. * * The admin_download role allows specifying additional parameters and longer expiration times. */ export type StorageFileDownloadRole = 'download' | 'admin_download'; /** * All available permission roles for StorageFile operations. * * Includes download roles, sync/processing roles, and standard CRUD roles. */ export type StorageFileRoles = StorageFileDownloadRole | 'forceSyncWithGroups' | 'syncWithGroups' | 'process' | GrantedUpdateRole | GrantedReadRole; /** * Firestore document wrapper for a {@link StorageFile}. */ export declare class StorageFileDocument extends AbstractFirestoreDocument { get modelIdentity(): import("../..").RootFirestoreModelIdentity<"storageFile", "sf">; } /** * Snapshot converter for {@link StorageFile} documents, handling field-level serialization * between the application model and Firestore storage format. */ export declare const storageFileConverter: import("../..").SnapshotConverterFunctions>>, Partial>>, import("@dereekb/util").MaybeMap, any>>>; /** * Returns the raw Firestore CollectionReference for the StorageFile collection. * * @example * ```ts * const colRef = storageFileCollectionReference(firestoreContext); * ``` * * @param context - the Firestore context to use * @returns the CollectionReference for StorageFile documents */ export declare function storageFileCollectionReference(context: FirestoreContext): CollectionReference; /** * Typed FirestoreCollection for {@link StorageFile} documents. */ export type StorageFileFirestoreCollection = FirestoreCollection; /** * Creates a fully configured {@link StorageFileFirestoreCollection} with snapshot conversion and document factory. * * @example * ```ts * const collection = storageFileFirestoreCollection(firestoreContext); * const doc = collection.documentAccessor().newDocument(); * ``` * * @param firestoreContext - the Firestore context to use * @returns a configured StorageFileFirestoreCollection */ export declare function storageFileFirestoreCollection(firestoreContext: FirestoreContext): StorageFileFirestoreCollection; /** * Model identity for the StorageFileGroup collection (collection name: `storageFileGroup`, prefix: `sfg`). */ export declare const storageFileGroupIdentity: import("../..").RootFirestoreModelIdentity<"storageFileGroup", "sfg">; /** * Represents a single StorageFile's embedding within a {@link StorageFileGroup}. * * Tracks when the file was added to the group and when it was last included in a zip archive. */ export interface StorageFileGroupEmbeddedFile { /** * StorageFile id. * * @dbxModelVariable storageFileId */ s: StorageFileId; /** * Overrides the display name for this file within the group when generating * a composite file (zip, etc.). * * @dbxModelVariable displayName */ n?: Maybe; /** * The time number it was added to the group. * * @dbxModelVariable addedAt */ sat: Date; /** * The first time the StorageFile's file was added to the zip, if applicable. * * @dbxModelVariable zippedAt */ zat?: Maybe; } /** * Firestore sub-object converter for {@link StorageFileGroupEmbeddedFile}, handling date serialization * of `sat` and `zat` fields as Unix timestamp seconds. */ export declare const storageFileGroupEmbeddedFile: import("../..").FirestoreSubObjectFieldMapFunctionsConfig, any>>>; /** * A group of {@link StorageFile}s aggregated around a related model or common identifier. * * Groups are identified by a two-way flat key derived from the related model's key * (see {@link storageFileGroupIdForModel}). They support automatic zip file generation * via the `z` flag and content regeneration via the `re` flag. * * Implements {@link InitializedStorageFileModel} for async initialization tracking — * the `s` (needs sync) flag is set on creation and cleared once initialized. * * @dbxModel */ export interface StorageFileGroup extends InitializedStorageFileModel { /** * List of embedded files in this group currently. * * @dbxModelVariable files */ f: StorageFileGroupEmbeddedFile[]; /** * Created at date. * * @dbxModelVariable createdAt */ cat: Date; /** * Ownership key, if applicable. * * @dbxModelVariable ownerKey */ o?: Maybe; /** * True if a zip file should be generated for this group. * * This should remain true while a zip file * * @dbxModelVariable shouldZip */ z?: Maybe; /** * StorageFile that contains the zip file for this group. * * @dbxModelVariable zipStorageFileId */ zsf?: Maybe; /** * The last date the zip file was regenerated for this group. * * @dbxModelVariable zippedAt */ zat?: Maybe; /** * True if this StorageFileGroup should flag regeneration of output StorageFiles/content. * * @dbxModelVariable shouldRegenerate */ re?: Maybe; /** * True if this StorageFileGroup should clean up file references. * * This cleanup process will occur during the next regeneration. * * @dbxModelVariable shouldCleanup */ c?: Maybe; } /** * Subset of {@link StorageFileGroup} fields controlling content generation flags. */ export type StorageFileGroupContentFlagsData = Pick; /** * Permission roles for StorageFileGroup operations. */ export type StorageFileGroupRoles = 'regenerate' | GrantedReadRole; /** * Firestore document wrapper for a {@link StorageFileGroup}. * * Provides a convenience getter to infer the related model key from the group's own ID. */ export declare class StorageFileGroupDocument extends AbstractFirestoreDocument { get modelIdentity(): import("../..").RootFirestoreModelIdentity<"storageFileGroup", "sfg">; get storageFileGroupRelatedModelKey(): string; } /** * Snapshot converter for {@link StorageFileGroup} documents, including nested * {@link StorageFileGroupEmbeddedFile} array conversion. */ export declare const storageFileGroupConverter: import("../..").SnapshotConverterFunctions, any>>>; /** * Returns the raw Firestore CollectionReference for the StorageFileGroup collection. * * @example * ```ts * const colRef = storageFileGroupCollectionReference(firestoreContext); * ``` * * @param context - the Firestore context to use * @returns the CollectionReference for StorageFileGroup documents */ export declare function storageFileGroupCollectionReference(context: FirestoreContext): CollectionReference; /** * Typed FirestoreCollection for {@link StorageFileGroup} documents. */ export type StorageFileGroupFirestoreCollection = FirestoreCollection; /** * Creates a fully configured {@link StorageFileGroupFirestoreCollection} with snapshot conversion and document factory. * * @example * ```ts * const collection = storageFileGroupFirestoreCollection(firestoreContext); * const doc = collection.documentAccessor().loadDocumentForId(groupId); * ``` * * @param firestoreContext - the Firestore context to use * @returns a configured StorageFileGroupFirestoreCollection */ export declare function storageFileGroupFirestoreCollection(firestoreContext: FirestoreContext): StorageFileGroupFirestoreCollection;