/** * Type definitions for the ProtoPedia in-memory repository interface. * * @module */ import type { EventEmitter } from 'events'; import type { ListPrototypesParams } from 'protopedia-api-v2-client'; import type { Logger, LogLevel } from '../../logger/index.js'; import type { PrototypeInMemoryStats, PrototypeInMemoryStoreConfig } from '../../store/index.js'; import type { NormalizedPrototype } from '../../types/index.js'; import type { PrototypeAnalysisResult } from './analysis.types.js'; import type { SerializableSnapshot } from './serialization.types.js'; import type { SnapshotOperationResult } from './snapshot-operation.types.js'; /** * Configuration options for the ProtoPedia in-memory repository. */ export type ProtopediaInMemoryRepositoryConfig = { /** * Custom logger instance for repository operations. * * @remarks * - If provided, the logger will be used as-is * - If provided with logLevel, the level will be updated if logger is mutable * - If not provided, creates a ConsoleLogger with the specified logLevel * * @default undefined (creates ConsoleLogger with 'info' level) */ readonly logger?: Logger; /** * Log level for creating a default ConsoleLogger. * * @remarks * - Only used when `logger` is NOT provided * - Creates a new ConsoleLogger with this level * - If logger is provided and mutable, updates its level property * * @default 'info' */ readonly logLevel?: LogLevel; /** * Enable event notifications for snapshot operations. * * When enabled, the repository will create an EventEmitter instance and * emit events during snapshot operations (snapshotStarted, snapshotCompleted, snapshotFailed). * * @remarks * - Events are disabled by default to minimize overhead for CLI/script users * - When enabled, access events via the `events` property * - Always call `dispose()` to clean up event listeners when done * - Designed primarily for WebApp/SPA scenarios * * @default false * * @see {@link RepositoryEvents} for available event types * @see {@link https://github.com/F88/promidas/issues/19 | Issue #19: Event Notification System} */ readonly enableEvents?: boolean; }; /** * In-memory, snapshot-based repository for ProtoPedia prototypes. * * This repository hides HTTP and caching details behind a simple * snapshot API: * * - `setupSnapshot` / `refreshSnapshot` populate or update the snapshot * by calling the ProtoPedia API under the hood. * - Read methods (`getPrototypeFromSnapshotById`, * `getRandomPrototypeFromSnapshot`) access only the current in-memory * snapshot and never perform HTTP calls. * - `getStats` exposes enough information (size, cachedAt, isExpired) to * implement TTL-based refresh strategies in the calling code. */ export interface ProtopediaInMemoryRepository { /** * Event emitter for snapshot operation notifications. * * This property is only defined when `enableEvents: true` is set in the repository configuration. * Use optional chaining (`events?.on(...)`) to safely access event methods. * * @remarks * **Available Events:** * - `snapshotStarted` - Emitted when setupSnapshot or refreshSnapshot begins * - `snapshotCompleted` - Emitted when snapshot operation succeeds (includes stats) * - `snapshotFailed` - Emitted when snapshot operation fails (includes error details) * * **Cleanup:** * Always call `dispose()` to remove all event listeners and prevent memory leaks. * * @example * ```typescript * const repo = new PromidasRepositoryBuilder() * .setRepositoryConfig({ enableEvents: true }) * .build(); * * repo.events?.on('snapshotCompleted', (stats) => { * console.log(`Updated: ${stats.size} prototypes`); * }); * * // Cleanup * repo.dispose(); * ``` * * @see {@link RepositoryEvents} for event type definitions * @see {@link dispose} for cleanup method */ readonly events?: EventEmitter; /** * Retrieve the configuration used to initialize the underlying store. * * Returns the TTL and maximum data size settings (logger is excluded). */ getConfig(): Omit, 'logger'>; /** * Stats for the current snapshot, including TTL-related information. * * Callers can use this to implement strategies such as: * - refreshing when `isExpired` is true, or * - refreshing when `cachedAt` is older than a given threshold. * * This method never throws due to ProtoPedia API failures; it only * reports the current in-memory state. */ getStats(): PrototypeInMemoryStats; /** * Fetch prototypes from ProtoPedia and populate the in-memory snapshot. * * Typical usage: call once on startup, or before the first read. The * concrete fetch strategy (all vs partial, page size, filters, etc.) is * an implementation detail of this repository. * * Returns a Result type indicating success with stats or failure with error details. * In case of failure, any existing in-memory snapshot remains unchanged. * * @returns SnapshotOperationResult with ok: true and stats on success, * or ok: false with error details on failure */ setupSnapshot(params: ListPrototypesParams): Promise; /** * Refresh the snapshot using the same parameters as the last successful * {@link ProtopediaInMemoryRepository.setupSnapshot | setupSnapshot} call. * * **Prerequisite**: `setupSnapshot()` must have been called successfully at least once. * If called before `setupSnapshot()`, returns an error with code `REPOSITORY_INVALID_STATE`. * * Returns a Result type indicating success with stats or failure with error details. * In case of failure, the current in-memory snapshot is preserved. * * @returns SnapshotOperationResult with ok: true and stats on success, * or ok: false with error details on failure */ refreshSnapshot(): Promise; /** * Analyze prototypes from the current snapshot to extract ID range. * * Returns the minimum and maximum prototype IDs from the current snapshot. * This method does NOT perform HTTP calls. * * @returns {@link PrototypeAnalysisResult} containing min and max IDs, or null values if snapshot is empty */ analyzePrototypes(): Promise; /** * Get all prototypes from the current in-memory snapshot. * * Returns all prototypes currently cached in the snapshot. * The returned data is read-only and reflects the state at the time of the call. * * This method does NOT perform HTTP calls. * It does not throw due to ProtoPedia API failures; it only reflects * the current in-memory state of the snapshot. * * @returns Read-only array of all prototypes. Returns an empty array if the snapshot is empty. * * @remarks * **Performance Warning**: This method returns a reference to the internal array. * While efficient (O(1)), iterating over very large arrays may impact performance. */ getAllFromSnapshot(): Promise; /** * Get all prototype IDs from the current in-memory snapshot. * * Returns an array of all prototype IDs currently cached in the snapshot. * Useful for operations that only need IDs, such as: * - Exporting available prototype IDs to clients * - ID-based filtering or statistics * - Checking if specific IDs exist without loading full objects * * This method does NOT perform HTTP calls. * It does not throw due to ProtoPedia API failures; it only reflects * the current in-memory state of the snapshot. * * @returns Read-only array of prototype IDs. Returns an empty array if the snapshot is empty. */ getPrototypeIdsFromSnapshot(): Promise; /** * Get a prototype from the current in-memory snapshot by id. * * Returns the prototype when it exists in the snapshot, or null when * the id is not present in the current snapshot. * * This method does NOT perform HTTP calls. * It does not throw due to ProtoPedia API failures; it only reflects * the current in-memory state of the snapshot. * * @param prototypeId - The prototype ID to retrieve * @returns The prototype if found, or null if not found * @throws {ValidationError} If prototypeId is not a positive integer */ getPrototypeFromSnapshotByPrototypeId(prototypeId: number): Promise; /** * Get a random prototype from the current in-memory snapshot. * * Returns a random prototype when the snapshot is not empty, or null * when the snapshot is empty. * * This method does NOT perform HTTP calls. * It does not throw due to ProtoPedia API failures; it only reflects * the current in-memory state of the snapshot. */ getRandomPrototypeFromSnapshot(): Promise; /** * Get random samples from the current in-memory snapshot. * * Returns up to `size` random prototypes without duplicates. * If `size` exceeds the available data, returns all prototypes in random order. * Returns an empty array when `size <= 0` or when the snapshot is empty. * * This method does NOT perform HTTP calls. * It does not throw due to ProtoPedia API failures; it only reflects * the current in-memory state of the snapshot. * * @param size - Maximum number of random samples to return * @returns Read-only array of random prototypes. Returns an empty array when `size <= 0` or the snapshot is empty. If `size` exceeds available data, all available prototypes are returned in a random order. * @throws {ValidationError} If size is not an integer * * @remarks * **Performance Note**: This method uses a hybrid algorithm (Set-based vs Fisher-Yates) * depending on the sample size ratio to optimize performance. */ getRandomSampleFromSnapshot(size: number): Promise; /** * Get current snapshot as a serializable object. * * Returns a plain JavaScript object containing all prototypes from the current * snapshot along with metadata. The returned object can be passed to * JSON.stringify() for persistence. * * This method does NOT perform file I/O or JSON.stringify(). * The caller is responsible for serialization and storage. * * This method does NOT perform HTTP calls. * It only reflects the current in-memory state of the snapshot. * * @returns Serializable snapshot object with version, timestamp, and prototypes. * If the snapshot is empty, prototypes will be an empty array. * * @remarks * **Memory Warning**: This method creates deep copies of all prototypes to ensure * serialization safety (removing readonly constraints). For very large datasets, * this may cause high memory usage. * * @example * ```typescript * // Export to file * const snapshot = repo.getSerializableSnapshot(); * const json = JSON.stringify(snapshot, null, 2); * await fs.writeFile('snapshot.json', json, 'utf-8'); * * // Check content * console.log(`Version: ${snapshot.version}`); * console.log(`Serialized: ${snapshot.serializedAt}`); * console.log(`Count: ${snapshot.prototypes.length}`); * ``` * * @see {@link setupSnapshotFromSerializedData} for importing serialized snapshots * @see {@link SerializableSnapshot} for the data structure */ getSerializableSnapshot(): SerializableSnapshot; /** * Setup snapshot from previously serialized data. * * Alternative to setupSnapshot(params) for offline/cached initialization. * Validates the data structure and populates the in-memory store. * * This method does NOT perform file I/O or JSON.parse(). * The caller is responsible for loading and parsing the data. * * Returns a Result type indicating success with stats or failure with error details. * Validation errors are returned as VALIDATION_ERROR type. * * @param data - Serializable snapshot object (previously exported) * @returns SnapshotOperationResult with ok: true and stats on success, * or ok: false with error details on validation/import failure * * @example * ```typescript * // Import from file * const json = await fs.readFile('snapshot.json', 'utf-8'); * const data = JSON.parse(json); * const result = repo.setupSnapshotFromSerializedData(data); * * if (result.ok) { * console.log(`Loaded ${result.stats.size} prototypes`); * } else { * console.error(`Import failed: ${result.message}`); * } * ``` * * @see {@link getSerializableSnapshot} for exporting snapshots * @see {@link setupSnapshot} for API-based initialization * @see {@link SerializableSnapshot} for the expected data structure */ setupSnapshotFromSerializedData(data: SerializableSnapshot): SnapshotOperationResult; /** * Clean up event listeners and release resources. * * This method removes all event listeners from the internal EventEmitter. * Always call this method in cleanup paths to prevent memory leaks. * * @remarks * **When to call:** * - Test cleanup (`afterEach` in test suites) * - Component unmounting (React `useEffect` cleanup) * - Before creating a new repository instance * - When the repository is no longer needed * * **Safety:** * - Safe to call even when events are disabled (`enableEvents: false`) * - Safe to call multiple times * - Does nothing if no event listeners exist * * @example * ```typescript * // In tests * afterEach(() => { * repo.dispose(); * }); * * // In React components * useEffect(() => { * repo.events?.on('snapshotCompleted', handleComplete); * return () => repo.dispose(); * }, []); * ``` * * @see {@link events} for event emitter property */ dispose(): void; } //# sourceMappingURL=repository.types.d.ts.map