/** * CONSOLIDATED Tool utility functions for consistent tool operations across the app * Works in both server (Node.js) and client (browser) environments */ export interface Tool { name: string; type?: 'software' | 'method' | 'concept'; projectUrl?: string | null; license?: string; knowledgebase?: boolean; domains?: string[]; phases?: string[]; platforms?: string[]; skillLevel?: string; description?: string; tags?: string[]; related_concepts?: string[]; } /** * Creates a URL-safe slug from a tool name * Used for URLs, IDs, and file names consistently across the app */ export function createToolSlug(toolName: string): string { if (!toolName || typeof toolName !== 'string') { console.warn('[toolHelpers] Invalid toolName provided to createToolSlug:', toolName); return ''; } return toolName.toLowerCase() .replace(/[^a-z0-9\s-]/g, '') // Remove special characters .replace(/\s+/g, '-') // Replace spaces with hyphens .replace(/-+/g, '-') // Remove duplicate hyphens .replace(/^-|-$/g, ''); // Remove leading/trailing hyphens } /** * Finds a tool by name or slug from tools array */ export function findToolByIdentifier(tools: Tool[], identifier: string): Tool | undefined { if (!identifier || !Array.isArray(tools)) return undefined; return tools.find(tool => tool.name === identifier || createToolSlug(tool.name) === identifier.toLowerCase() ); } /** * Checks if tool has a valid project URL (hosted on CC24 server) */ export function isToolHosted(tool: Tool): boolean { return tool.projectUrl !== undefined && tool.projectUrl !== null && tool.projectUrl !== "" && tool.projectUrl.trim() !== ""; } /** * Determines tool category for styling/logic */ export function getToolCategory(tool: Tool): 'concept' | 'method' | 'hosted' | 'oss' | 'proprietary' { if (tool.type === 'concept') return 'concept'; if (tool.type === 'method') return 'method'; if (isToolHosted(tool)) return 'hosted'; if (tool.license && tool.license !== 'Proprietary') return 'oss'; return 'proprietary'; }