Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 | 1x 14x 2x 12x 11x 8x 11x 8x 8x 3x 3x 2x 2x 11x 8x | /**
* Topic Lookup/Cache Utility (Story 5.2a - Event Batch Import with Topics)
*
* Provides efficient topic lookup by category with caching to minimize API calls
* during batch event imports.
*
* Features:
* - In-memory cache (category → topicId mapping)
* - On-demand topic creation when category doesn't exist
* - Cache management utilities for testing
*
* Usage:
* ```typescript
* const topicId = await getOrCreateTopicByCategory('Frontend & UI');
* ```
*/
import { topicService } from '@/services/topicService';
import type { CreateTopicRequest } from '@/types/topic.types';
/**
* In-memory cache: category → topicId
* Cleared between batch imports to ensure fresh data
*/
const topicCache = new Map<string, string>();
/**
* Get or create topic by title
*
* This function:
* 1. Checks cache first for performance
* 2. Fetches from API by title (not category) if not cached
* 3. Creates new topic if not found
* 4. Caches result for subsequent calls
*
* NOTE: The JSON file's "category" field represents the topic TITLE, not the topic's category field.
* We filter by title to find existing topics.
*
* @param topicTitle Topic title (e.g., "Frontend & UI", "Cloud & Infrastructure")
* @returns Topic ID (UUID)
* @throws Error if API call fails or topic creation fails
*
* @example
* ```typescript
* // First call fetches from API
* const id1 = await getOrCreateTopicByCategory('Security');
*
* // Second call uses cache (no API call)
* const id2 = await getOrCreateTopicByCategory('Security');
* ```
*/
export async function getOrCreateTopicByCategory(topicTitle: string): Promise<string> {
// Check cache first
if (topicCache.has(topicTitle)) {
return topicCache.get(topicTitle)!;
}
// Fetch all topics and find by title (API doesn't support title filter yet)
const response = await topicService.getTopics({
limit: 100, // Get all topics to search by title
});
// Find topic by title (case-insensitive match)
const matchingTopic = response.data.find(
(topic) => topic.title.toLowerCase() === topicTitle.toLowerCase()
);
if (matchingTopic) {
topicCache.set(topicTitle, matchingTopic.topicCode);
return matchingTopic.topicCode;
}
// Topic doesn't exist - create it
// Use 'technical' as default category since we can't infer from title alone
const createRequest: CreateTopicRequest = {
title: topicTitle,
category: 'technical', // Default to technical category
description: `Topic: ${topicTitle}`,
};
const newTopic = await topicService.createTopic(createRequest);
// Cache newly created topic
topicCache.set(topicTitle, newTopic.topicCode);
return newTopic.topicCode;
}
/**
* Clear the topic cache
*
* Useful for:
* - Testing (clear cache between tests)
* - Forcing fresh API lookups
* - Memory management for long-running imports
*
* @example
* ```typescript
* clearTopicCache(); // All subsequent lookups will hit API
* ```
*/
export function clearTopicCache(): void {
topicCache.clear();
}
/**
* Get current size of topic cache
*
* Useful for:
* - Monitoring cache efficiency
* - Testing cache behavior
* - Debugging import issues
*
* @returns Number of cached category → topicId mappings
*
* @example
* ```typescript
* console.log(`Cached ${getTopicCacheSize()} topics`);
* ```
*/
export function getTopicCacheSize(): number {
return topicCache.size;
}
|