import { type Type } from 'arktype'; import { type TargetModelParams, type OnCallCreateModelResult, type FirestoreModelKey } from '../../common'; import { type ModelFirebaseCrudFunction, type FirebaseFunctionTypeConfigMap, type ModelFirebaseCrudFunctionConfigMap, type ModelFirebaseFunctionMap, type ModelFirebaseCreateFunction } from '../../client'; import { type StorageFileSignedDownloadUrl, type StorageFileTypes } from './storagefile'; import { type StorageFileUploadScope } from './storagefile.upload'; import { type StorageFileKey, type StorageFileId, type StorageFilePurpose } from './storagefile.id'; import { type StorageBucketId, type StorageMetadata, type StoragePath, type StorageSlashPath } from '../../common/storage'; import { type ContentDispositionString, type ContentTypeMimeType, type Maybe, type Milliseconds, type SlashPath, type SlashPathFile, type UnixDateTimeMillisecondsNumber, type UnixDateTimeSecondsNumber } from '@dereekb/util'; import { type SendNotificationResult } from '../notification/notification.api'; export declare const DOWNLOAD_MULTIPLE_STORAGE_FILES_MIN_FILES = 1; export declare const DOWNLOAD_MULTIPLE_STORAGE_FILES_MAX_FILES = 50; /** * Parameters for directly creating a new StorageFile document (no upload initialization). * * Typically used server-side or for testing. Validated with {@link createStorageFileParamsType}. */ export interface CreateStorageFileParams { } export declare const createStorageFileParamsType: Type; /** * Parameters for batch-initializing all files found in the uploads folder. * * Scans the uploads folder (or a custom path) and runs the upload determination/initialization * pipeline for each file found. Validated with {@link initializeAllStorageFilesFromUploadsParamsType}. */ export interface InitializeAllStorageFilesFromUploadsParams { readonly maxFilesToInitialize?: Maybe; readonly folderPath?: Maybe; readonly overrideUploadsFolderPath?: Maybe; /** * Whether to expedite processing of each initialized file that ends up queued for it. * * The same option {@link InitializeStorageFileFromUploadParams} already offers for a single file. Without * it a file initialized by this sweep waits for the next `processAllQueuedStorageFiles` pass, which is a * whole scheduling tick of latency for a purpose whose processing the uploader is waiting on. */ readonly expediteProcessing?: Maybe; } export declare const initializeAllStorageFilesFromUploadsParamsType: Type; /** * Result of batch upload initialization, reporting visit and success/failure counts. */ export interface InitializeAllStorageFilesFromUploadsResult extends OnCallCreateModelResult { readonly filesVisited: number; readonly initializationsSuccessCount: number; readonly initializationsFailureCount: number; } /** * Parameters for initializing a single StorageFile from an uploaded file at a specific storage path. * * The file is run through the upload type determination pipeline and, if matched, * creates a corresponding StorageFile document. Validated with {@link initializeStorageFileFromUploadParamsType}. */ export interface InitializeStorageFileFromUploadParams extends Pick { readonly bucketId?: Maybe; readonly pathString: StorageSlashPath; readonly expediteProcessing?: Maybe; } export declare const initializeStorageFileFromUploadParamsType: Type; /** * Parameters for triggering processing of a specific StorageFile. * * Which flag is required depends on the file's current processing state. A `FAILED` file * restarts with no flag, while a `SUCCESS` file needs `processAgainIfSuccessful` (or * `forceRestartProcessing`) — note that a file whose processor ran to completion is `SUCCESS` * even when the outcome was a rejection, so re-validating a rejected file normally needs one of * those flags. `ARCHIVED` and `DO_NOT_PROCESS` files cannot be processed at all. * * Validated with {@link processStorageFileParamsType}. */ export interface ProcessStorageFileParams extends TargetModelParams { /** * Runs the first step of the processing task inline instead of waiting for the scheduled task runner. */ readonly runImmediately?: Maybe; /** * Checks an in-flight `PROCESSING` task immediately, instead of waiting for it to age past the * stuck-check throttle. */ readonly checkRetryProcessing?: Maybe; /** * Abandons the file's existing processing task and begins a new one, clearing the completed * checkpoints so the flow runs again from the start. For a `PROCESSING` file this is only applied * once the retry check runs, so pair it with `checkRetryProcessing` to force a restart while the * existing task is still within the stuck-check throttle. */ readonly forceRestartProcessing?: Maybe; /** * Allows processing a file that has already finished processing and is in the `SUCCESS` state. */ readonly processAgainIfSuccessful?: Maybe; } export declare const processStorageFileParamsType: Type; export interface ProcessStorageFileResult { readonly runImmediately: boolean; readonly expediteResult: Maybe; } /** * Processes all StorageFiles that are queued for processing. */ export interface ProcessAllQueuedStorageFilesParams { } export declare const processAllQueuedStorageFilesParamsType: Type; export interface ProcessAllQueuedStorageFilesResult { readonly storageFilesVisited: number; readonly storageFilesProcessStarted: number; readonly storageFilesFailedStarting: number; } export interface UpdateStorageFileParams extends TargetModelParams { readonly sdat?: Maybe; } export declare const updateStorageFileParamsType: Type; export interface DeleteStorageFileParams extends TargetModelParams { readonly force?: Maybe; } export declare const deleteStorageFileParamsType: Type; /** * Processes all StorageFiles that are queued for processing. */ export interface DeleteAllQueuedStorageFilesParams { } export declare const deleteAllQueuedStorageFilesParamsType: Type; export interface DeleteAllQueuedStorageFilesResult { readonly storageFilesVisited: number; readonly storageFilesDeleted: number; readonly storageFilesFailedDeleting: number; } /** * Shared download options for StorageFile downloads. * * Supports custom expiration, content disposition, and content type overrides. * Admin downloads (`asAdmin`) allow longer expiration times. */ export interface DownloadStorageFileOptions { readonly expiresAt?: Maybe; readonly expiresIn?: Maybe; readonly responseDisposition?: Maybe; readonly responseContentType?: Maybe; readonly asAdmin?: Maybe; } /** * Parameters for generating a signed download URL for a single StorageFile. * * Extends {@link DownloadStorageFileOptions} with target model key. * Validated with {@link downloadStorageFileParamsType}. */ export interface DownloadStorageFileParams extends TargetModelParams, DownloadStorageFileOptions { } export declare const downloadStorageFileParamsType: Type; /** * Result of downloading a StorageFile. */ export interface DownloadStorageFileResult { readonly url: StorageFileSignedDownloadUrl; readonly fileName?: Maybe; readonly mimeType?: Maybe; readonly expiresAt?: Maybe; } /** * Per-file download options, excluding `asAdmin` which is controlled at the batch level. * * Each per-file option overrides the corresponding default from the parent {@link DownloadMultipleStorageFilesParams}. */ export interface DownloadMultipleStorageFilesFileParams extends TargetModelParams, Omit { } export declare const downloadMultipleStorageFilesFileParamsType: Type; /** * Success item in a batch download result. * * Extends the single-file {@link DownloadStorageFileResult} with the document key for correlation. */ export interface DownloadMultipleStorageFileSuccessItem extends DownloadStorageFileResult { readonly key: StorageFileKey; } /** * Error item in a batch download result. * * Includes the document key and a human-readable error message. */ export interface DownloadMultipleStorageFileErrorItem { readonly key: StorageFileKey; readonly error: string; } /** * Parameters for batch-downloading multiple StorageFiles. * * Top-level {@link DownloadStorageFileOptions} serve as defaults for all files. * Each item in `files` can override per-file options (except `asAdmin`, which is root-level only). * Validated with {@link downloadMultipleStorageFilesParamsType}. * * @example * ```ts * const params: DownloadMultipleStorageFilesParams = { * expiresIn: 1800000, * files: [ * { key: 'storageFile/abc' }, * { key: 'storageFile/def', expiresIn: 60000 } * ] * }; * ``` */ export interface DownloadMultipleStorageFilesParams extends DownloadStorageFileOptions { readonly files: DownloadMultipleStorageFilesFileParams[]; /** * When true, throws on the first download failure instead of collecting it in the errors array. */ readonly throwOnFirstError?: Maybe; } export declare const downloadMultipleStorageFilesParamsType: Type; /** * Result of a batch StorageFile download. * * Contains separate arrays for successful downloads and failures. * Individual download errors do not fail the entire batch. */ export interface DownloadMultipleStorageFilesResult { readonly success: DownloadMultipleStorageFileSuccessItem[]; readonly errors: DownloadMultipleStorageFileErrorItem[]; } /** * Parameters for reading the underlying Cloud Storage object metadata of a single StorageFile. * * Unlike {@link DownloadStorageFileParams}, no signed URL is minted — only the object's * {@link StorageMetadata} (size, md5Hash, generation, content headers, custom metadata, etc.) is returned. * `asAdmin` only selects the read role used for permission gating. Validated with {@link readStorageFileMetadataParamsType}. */ export interface ReadStorageFileMetadataParams extends TargetModelParams { readonly asAdmin?: Maybe; } export declare const readStorageFileMetadataParamsType: Type; /** * Result of reading a StorageFile's underlying Cloud Storage object metadata. * * When the underlying object does not exist, `exists` is false and `metadata` is omitted * instead of the call throwing — useful for polling whether an upload has landed. */ export interface ReadStorageFileMetadataResult { readonly exists: boolean; readonly metadata?: Maybe; } /** * Per-file parameters for a batch metadata read. Carries only the target model key. */ export interface ReadMultipleStorageFilesMetadataFileParams extends TargetModelParams { } export declare const readMultipleStorageFilesMetadataFileParamsType: Type; /** * Success item in a batch metadata read result. * * Extends the single-file {@link ReadStorageFileMetadataResult} with the document key for correlation. */ export interface ReadMultipleStorageFileMetadataSuccessItem extends ReadStorageFileMetadataResult { readonly key: StorageFileKey; } /** * Error item in a batch metadata read result. * * Includes the document key and a human-readable error message. */ export interface ReadMultipleStorageFileMetadataErrorItem { readonly key: StorageFileKey; readonly error: string; } /** * Parameters for batch-reading the Cloud Storage metadata of multiple StorageFiles. * * `asAdmin` selects the read role for the whole batch. Validated with {@link readMultipleStorageFilesMetadataParamsType}. */ export interface ReadMultipleStorageFilesMetadataParams { readonly files: ReadMultipleStorageFilesMetadataFileParams[]; readonly asAdmin?: Maybe; /** * When true, throws on the first failure instead of collecting it in the errors array. */ readonly throwOnFirstError?: Maybe; } export declare const readMultipleStorageFilesMetadataParamsType: Type; /** * Result of a batch StorageFile metadata read. * * Contains separate arrays for successful reads and failures. * Individual read errors do not fail the entire batch. */ export interface ReadMultipleStorageFilesMetadataResult { readonly success: ReadMultipleStorageFileMetadataSuccessItem[]; readonly errors: ReadMultipleStorageFileMetadataErrorItem[]; } /** * Lower bound for caller-supplied `expiresInMs` on signed-upload-url generation. * * Anything shorter than 30 seconds is unrealistic for a caller to pick up a * URL, perform the PUT, and acknowledge before the URL expires. */ export declare const CREATE_STORAGE_FILE_SIGNED_UPLOAD_URL_MIN_EXPIRES_IN_MS: Milliseconds; /** * Upper bound for caller-supplied `expiresInMs` on signed-upload-url generation. * * 10 minutes is the longest acceptable window for a one-shot upload URL. Any * legitimate caller should be uploading within this window; longer windows * increase the blast radius if the URL leaks. */ export declare const CREATE_STORAGE_FILE_SIGNED_UPLOAD_URL_MAX_EXPIRES_IN_MS: Milliseconds; /** * Default `expiresInMs` applied when the caller does not supply one. */ export declare const DEFAULT_CREATE_STORAGE_FILE_SIGNED_UPLOAD_URL_EXPIRES_IN_MS: Milliseconds; /** * Maximum length of a caller-supplied filename. Enforced both at the ArkType * layer and again by the handler's sanitizer. */ export declare const CREATE_STORAGE_FILE_SIGNED_UPLOAD_URL_MAX_FILENAME_LENGTH = 200; /** * Parameters for creating a short-lived signed PUT URL for a StorageFile upload. * * The resulting URL is restricted to a specific {@link StorageFilePurpose}, MIME * type, and file size and lands the bytes inside the authenticated caller's * `/uploads/u/{uid}/...` namespace. Once uploaded, the existing * `StorageFileInitializeFromUploadService` flow picks the file up and creates * the matching `StorageFile` document. */ export interface CreateStorageFileSignedUploadUrlParams { /** * The {@link StorageFilePurpose} to upload as. Must be supported by the * app's signed-upload-url policy registry. The chosen policy decides where * the file lands and which content-types/sizes are allowed. */ readonly purpose: StorageFilePurpose; /** * The MIME type the client intends to PUT. Validated against the policy's * `allowedMimeTypes` and signed into the URL so GCS rejects any PUT with a * different `Content-Type`. */ readonly contentType: ContentTypeMimeType; /** * Filename to place inside the policy's upload folder. Required when the * policy has `requiresFilenameInput: true`. Sanitized server-side — must not * contain `/`, `..`, or NUL bytes; capped at * {@link CREATE_STORAGE_FILE_SIGNED_UPLOAD_URL_MAX_FILENAME_LENGTH} chars. */ readonly filename?: Maybe; /** * Client-declared size in bytes for the upload. Validated against the * policy's `maxFileSizeBytes` cap. The storage rules independently enforce * the same cap via `request.resource.size`. */ readonly fileSizeBytes: number; /** * Lifetime of the signed URL in milliseconds. Clamped to * [{@link CREATE_STORAGE_FILE_SIGNED_UPLOAD_URL_MIN_EXPIRES_IN_MS}, * {@link CREATE_STORAGE_FILE_SIGNED_UPLOAD_URL_MAX_EXPIRES_IN_MS}]. * Defaults to {@link DEFAULT_CREATE_STORAGE_FILE_SIGNED_UPLOAD_URL_EXPIRES_IN_MS} * when omitted. */ readonly expiresInMs?: Maybe; /** * The model, and optionally the slot within it, this upload belongs to. Required when the resolved * policy sets `requiresScopeInput: true` (e.g. a FormSpace upload, which is keyed by space and slot * rather than by the uid alone). */ readonly scope?: Maybe; } /** * Arktype for a {@link StorageFileUploadScope}. */ export declare const storageFileUploadScopeType: Type; export declare const createStorageFileSignedUploadUrlParamsType: Type; /** * Result of creating a signed upload URL. * * The caller PUTs the file bytes to {@link uploadUrl} with the headers in * {@link requiredHeaders}. The existing initializer flow then picks the file * up from {@link uploadPath} and creates the StorageFile document. * * `modelKeys` is intentionally empty — minting the URL does not create a * StorageFile document; the document is created later by the upload-complete * pipeline. */ export interface CreateStorageFileSignedUploadUrlResult extends OnCallCreateModelResult { readonly modelKeys: []; /** * Short-lived, content-type-pinned PUT URL. */ readonly uploadUrl: string; /** * The full storage path the URL writes to (inside `/uploads/u/{uid}/...`). * Returned so the caller can confirm where the file landed. */ readonly uploadPath: SlashPath; /** * Unix millisecond timestamp at which the URL expires. */ readonly expiresAt: UnixDateTimeMillisecondsNumber; /** * Headers the caller MUST send on the PUT for the signature to validate. * At minimum, the `content-type` matches the signed value. */ readonly requiredHeaders: Readonly>; /** * Echo of the policy's `maxFileSizeBytes` cap, for caller-side validation. */ readonly maxFileSizeBytes: number; /** * The resolved {@link StorageFilePurpose}. */ readonly purpose: StorageFilePurpose; } /** * Used for creating or initializing a new StorageFileGroup for a StorageFile. * * Mainly used for testing. Not exposed to the API. * * The preferred way is to create a StorageFileGroup through a StorageFile. */ export interface CreateStorageFileGroupParams { readonly model?: Maybe; readonly storageFileId?: Maybe; } export declare const createStorageFileGroupParamsType: Type; export interface SyncStorageFileWithGroupsParams extends TargetModelParams { readonly force?: Maybe; } export declare const syncStorageFileWithGroupsParamsType: Type; export interface SyncStorageFileWithGroupsResult { readonly storageFilesGroupsCreated: number; readonly storageFilesGroupsUpdated: number; } export interface SyncAllFlaggedStorageFilesWithGroupsParams { } export declare const syncAllFlaggedStorageFilesWithGroupsParamsType: Type; export interface SyncAllFlaggedStorageFilesWithGroupsResult { readonly storageFilesSynced: number; readonly storageFilesGroupsCreated: number; readonly storageFilesGroupsUpdated: number; } export interface UpdateStorageFileGroupEntryParams { readonly s: StorageFileId; readonly n?: Maybe; } export declare const updateStorageFileGroupEntryParamsType: Type; export interface UpdateStorageFileGroupParams extends TargetModelParams { readonly entries?: Maybe; } export declare const updateStorageFileGroupParamsType: Type; export interface RegenerateStorageFileGroupContentParams extends TargetModelParams { readonly force?: Maybe; } export declare const regenerateStorageFileGroupContentParamsType: Type; export interface RegenerateStorageFileGroupContentResult { readonly contentStorageFilesFlaggedForProcessing: number; } export interface RegenerateAllFlaggedStorageFileGroupsContentParams { } export declare const regenerateAllFlaggedStorageFileGroupsContentParamsType: Type; export interface RegenerateAllFlaggedStorageFileGroupsContentResult { readonly storageFileGroupsUpdated: number; readonly contentStorageFilesFlaggedForProcessing: number; } /** * Used for initializing an uninitialized model like NotificationBox or NotificationSummary. */ export interface InitializeStorageFileModelParams extends TargetModelParams { readonly throwErrorIfAlreadyInitialized?: Maybe; } export declare const initializeStorageFileModelParamsType: Type; export interface InitializeAllApplicableStorageFileGroupsParams { } export declare const initializeAllApplicableStorageFileGroupsParamsType: Type; export interface InitializeAllApplicableStorageFileGroupsResult { readonly storageFileGroupsVisited: number; readonly storageFileGroupsSucceeded: number; readonly storageFileGroupsFailed: number; readonly storageFileGroupsAlreadyInitialized: number; } /** * Custom (non-CRUD) function type map for StorageFile. Currently empty — all operations use CRUD functions. */ export type StorageFileFunctionTypeMap = {}; export declare const STORAGE_FILE_FUNCTION_TYPE_CONFIG_MAP: FirebaseFunctionTypeConfigMap; /** * CRUD function configuration map for the StorageFile model family. * * Defines all callable cloud function endpoints for StorageFile and StorageFileGroup, * including creation (direct, from upload, batch), processing, sync, download, and deletion. * * Used by {@link StorageFileFunctions} and {@link storageFileFunctionMap} to generate * typed callable function references. */ export type StorageFileModelCrudFunctionsConfig = { readonly storageFile: { create: { _: CreateStorageFileParams; fromUpload: InitializeStorageFileFromUploadParams; allFromUpload: [InitializeAllStorageFilesFromUploadsParams, InitializeAllStorageFilesFromUploadsResult]; signedUploadUrl: [CreateStorageFileSignedUploadUrlParams, CreateStorageFileSignedUploadUrlResult]; }; update: { _: UpdateStorageFileParams; process: [ProcessStorageFileParams, ProcessStorageFileResult]; syncWithGroups: [SyncStorageFileWithGroupsParams, SyncStorageFileWithGroupsResult]; }; read: { download: [DownloadStorageFileParams, DownloadStorageFileResult]; downloadMultiple: [DownloadMultipleStorageFilesParams, DownloadMultipleStorageFilesResult]; metadata: [ReadStorageFileMetadataParams, ReadStorageFileMetadataResult]; metadataMultiple: [ReadMultipleStorageFilesMetadataParams, ReadMultipleStorageFilesMetadataResult]; }; delete: { _: DeleteStorageFileParams; }; }; readonly storageFileGroup: { update: { _: UpdateStorageFileGroupParams; regenerateContent: [RegenerateStorageFileGroupContentParams, RegenerateStorageFileGroupContentResult]; }; }; }; export declare const STORAGE_FILE_MODEL_CRUD_FUNCTIONS_CONFIG: ModelFirebaseCrudFunctionConfigMap; /** * Abstract class defining all callable StorageFile cloud functions. * * Implement this in your app module to wire up the function endpoints. * Use {@link storageFileFunctionMap} to create a client-side callable map. */ export declare abstract class StorageFileFunctions implements ModelFirebaseFunctionMap { abstract storageFile: { createStorageFile: { create: ModelFirebaseCreateFunction; fromUpload: ModelFirebaseCreateFunction; allFromUpload: ModelFirebaseCrudFunction; signedUploadUrl: ModelFirebaseCreateFunction; }; updateStorageFile: { update: ModelFirebaseCrudFunction; process: ModelFirebaseCrudFunction; syncWithGroups: ModelFirebaseCrudFunction; }; readStorageFile: { download: ModelFirebaseCrudFunction; downloadMultiple: ModelFirebaseCrudFunction; metadata: ModelFirebaseCrudFunction; metadataMultiple: ModelFirebaseCrudFunction; }; deleteStorageFile: { delete: ModelFirebaseCrudFunction; }; }; abstract storageFileGroup: { updateStorageFileGroup: { update: ModelFirebaseCrudFunction; regenerateContent: ModelFirebaseCrudFunction; }; }; } /** * Client-side callable function map factory for all StorageFile and StorageFileGroup CRUD operations. * * @example * ```ts * const functions = storageFileFunctionMap(callableFactory); * const result = await functions.storageFile.createStorageFile.fromUpload({ pathString: 'uploads/u/123/avatar.png' }); * ``` */ export declare const storageFileFunctionMap: import("../..").ModelFirebaseFunctionMapFactory;