import { IMetadataProvider, UserInfo } from '@memberjunction/core'; import { BaseSingleton } from '@memberjunction/global'; import { FileStorageEngineBase, StorageAccountWithProvider, MJFileStorageAccountEntity, MJFileStorageProviderEntity } from '@memberjunction/core-entities'; import { FileStorageBase } from './generic/FileStorageBase.js'; /** * Options for uploading a file to MJ Storage. */ export interface UploadFileOptions { /** Raw file content as a Buffer */ content: Buffer; /** File name (used for the MJ: Files record and the storage path) */ fileName: string; /** MIME type of the file (e.g., 'application/pdf') */ mimeType: string; /** User context for DB operations and credential access */ contextUser: UserInfo; /** * Optional pre-resolved FileStorageAccount ID. * When provided, the file is uploaded to this specific account. * Otherwise, the first active account is used. */ storageAccountId?: string; /** * Optional metadata provider. Defaults to `Metadata.Provider`. */ provider?: IMetadataProvider; /** * Optional path prefix within the storage bucket. * Defaults to `'artifacts//'`. */ pathPrefix?: string; } /** * Result returned by {@link FileStorageEngine.UploadFile}. */ export interface UploadFileResult { /** The newly created MJ: Files record ID */ FileID: string; /** The storage path (ProviderKey) where the file was stored */ StoragePath: string; /** The storage account that was used */ Account: MJFileStorageAccountEntity; /** The storage provider that was used */ Provider: MJFileStorageProviderEntity; } /** * Server-side file storage engine providing high-level operations for uploading, * downloading, and managing files in MJ Storage. * * Follows the containment pattern (like AIEngine wraps AIEngineBase): * - Delegates all metadata access to {@link FileStorageEngineBase} * - Adds server-side methods: {@link UploadFile}, {@link GetDriver}, {@link ResolveStorageAccount} * * **Client-side code** should use `FileStorageEngineBase` from `@memberjunction/core-entities` * for metadata-only access (accounts, providers, lookups). * * Usage: * ```typescript * import { FileStorageEngine } from '@memberjunction/storage'; * * const engine = FileStorageEngine.Instance; * await engine.Config(false, contextUser); * * // Upload a file * const result = await engine.UploadFile({ * content: Buffer.from(base64Data, 'base64'), * fileName: 'report.pdf', * mimeType: 'application/pdf', * contextUser * }); * * // Get a driver for direct operations * const driver = await engine.GetDriver(accountId, contextUser); * const objects = await driver.ListObjects('/'); * ``` */ export declare class FileStorageEngine extends BaseSingleton { private _loaded; private _loading; private _loadingPromise; private _contextUser; private _driverCache; /** * Returns the global singleton instance. */ static get Instance(): FileStorageEngine; /** Access to the underlying metadata-only engine. */ protected get Base(): FileStorageEngineBase; /** Returns true if the engine has been configured. */ get Loaded(): boolean; /** Gets all file storage accounts (cached). */ get Accounts(): MJFileStorageAccountEntity[]; /** Gets all file storage providers (cached). */ get Providers(): MJFileStorageProviderEntity[]; /** Gets all storage accounts combined with their provider details (cached). */ get AccountsWithProviders(): StorageAccountWithProvider[]; /** Whether any storage accounts are configured. */ get HasStorageAccounts(): boolean; /** Gets a file storage account by its ID. */ GetAccountById(accountId: string): MJFileStorageAccountEntity | undefined; /** Gets a file storage provider by its ID. */ GetProviderById(providerId: string): MJFileStorageProviderEntity | undefined; /** Gets a file storage account by its name (case-insensitive). */ GetAccountByName(name: string): MJFileStorageAccountEntity | undefined; /** Gets file storage accounts linked to a given provider ID. */ GetAccountsByProviderID(providerId: string): MJFileStorageAccountEntity[]; /** Gets a storage account with its provider details by account ID. */ GetAccountWithProvider(accountId: string): StorageAccountWithProvider | null; /** * Configures the engine by loading the underlying metadata cache and any * server-specific state. Safe to call multiple times — uses cached data * unless `forceRefresh` is true. Concurrent callers share a single loading * promise to avoid redundant work. */ Config(forceRefresh?: boolean, contextUser?: UserInfo, provider?: IMetadataProvider): Promise; /** * Internal loading logic — separated for clean promise management. * First ensures the base metadata cache is loaded, then loads any * server-specific state (extensible for future needs). */ private innerLoad; /** * Initializes storage drivers for all active accounts and caches them. * Called automatically during Config(). Can also be called independently to * re-initialize drivers without reloading metadata (e.g., after credential rotation). * Accounts that fail to initialize are logged and skipped — they will fall back to * on-demand initialization when GetDriver() is called. */ RefreshDriverCache(): Promise; /** * Resolves a storage account to use for file operations. * * Resolution logic: * 1. If `accountId` is provided, returns that specific account * 2. Otherwise, returns the first active account * 3. If no active accounts exist, returns the first account regardless of active status * * @param accountId - Optional explicit account ID * @returns The resolved account with provider, or null if no accounts are configured */ ResolveStorageAccount(accountId?: string): StorageAccountWithProvider | null; /** * Returns an authenticated storage driver for a given account. * * Checks the pre-initialized driver cache first (populated during Config()). * If the account wasn't cached (e.g., it failed during Config or was added after), * falls back to on-demand initialization. * * This handles: * - Looking up the account and provider from cached metadata * - Decrypting credentials via the Credential Engine * - Setting up OAuth token refresh callbacks for providers like Box * * @param accountId - The FileStorageAccount ID to get a driver for * @param contextUser - User context for credential decryption (used for on-demand init) * @returns An initialized, ready-to-use FileStorageBase driver * @throws Error if the account is not found or driver initialization fails */ GetDriver(accountId: string, contextUser: UserInfo): Promise; /** * Uploads a file to MJ Storage and creates an `MJ: Files` entity record. * * This is the primary high-level method for storing files. It handles: * 1. Resolving which storage account to use * 2. Initializing an authenticated driver * 3. Uploading the file content * 4. Creating the `MJ: Files` database record * * @param options - Upload options (content, fileName, mimeType, contextUser, etc.) * @returns Upload result containing the file ID, storage path, and account/provider used * @throws Error if no storage accounts are configured or the upload/save fails * * @example * ```typescript * const result = await FileStorageEngine.Instance.UploadFile({ * content: Buffer.from(base64Data, 'base64'), * fileName: 'report.pdf', * mimeType: 'application/pdf', * contextUser, * storageAccountId: resolvedAccountId // optional * }); * console.log('Created file:', result.FileID); * ``` */ UploadFile(options: UploadFileOptions): Promise; } //# sourceMappingURL=FileStorageEngine.d.ts.map