Transform qualifying scenarios into marketing-ready use cases with: - AI-generated titles, descriptions, ROI estimates, business value - Persona/industry/category taxonomy for targeting - Browseable feed with filtering and ranking - SEO-optimized case study pages - Daily cron job for generation and ranking Database: - Add Persona, Industry, Category lookup tables - Add UseCase model with marketing content fields - Add junction tables for personas/industries/categories - Add SocialProof model for cached metrics API: - GET /api/use-cases - Global directory with filtering - GET /api/use-cases/[id] - Individual use case details - GET /api/public/users/[username]/collections/[slug]/use-cases - POST /api/cron/use-cases - Nightly generation job Frontend: - /use-cases - Global feed with persona dropdown - /use-cases/[slug] - SEO case study page - /[username]/collections/[slug]/use-cases - Collection feed - UseCasesFeed component - Sortable table component - UseCaseCaseStudy component - Full case study layout
135 lines
3.2 KiB
TypeScript
135 lines
3.2 KiB
TypeScript
import * as fs from 'node:fs';
|
|
import * as os from 'node:os';
|
|
import * as path from 'node:path';
|
|
import Conf from 'conf';
|
|
|
|
export interface TpmConfig {
|
|
apiUrl?: string;
|
|
defaultOutput?: 'human' | 'json';
|
|
verbose?: boolean;
|
|
analytics?: boolean;
|
|
env?: Record<string, string>;
|
|
}
|
|
|
|
export interface TpmCredentials {
|
|
apiKey?: string;
|
|
refreshToken?: string;
|
|
expiresAt?: string;
|
|
}
|
|
|
|
const CONFIG_DIR = path.join(os.homedir(), '.tpmjs');
|
|
const CREDENTIALS_FILE = path.join(CONFIG_DIR, 'credentials.json');
|
|
const HISTORY_DIR = path.join(CONFIG_DIR, 'history');
|
|
|
|
// Ensure config directory exists
|
|
function ensureConfigDir(): void {
|
|
if (!fs.existsSync(CONFIG_DIR)) {
|
|
fs.mkdirSync(CONFIG_DIR, { recursive: true, mode: 0o700 });
|
|
}
|
|
}
|
|
|
|
// Config store using Conf
|
|
const configStore = new Conf<TpmConfig>({
|
|
projectName: 'tpmjs',
|
|
cwd: CONFIG_DIR,
|
|
configName: 'config',
|
|
defaults: {
|
|
apiUrl: 'https://tpmjs.com/api',
|
|
defaultOutput: 'human',
|
|
verbose: false,
|
|
analytics: false,
|
|
},
|
|
});
|
|
|
|
export function getConfig(): TpmConfig {
|
|
return configStore.store;
|
|
}
|
|
|
|
export function setConfig(config: Partial<TpmConfig>): void {
|
|
for (const [key, value] of Object.entries(config)) {
|
|
if (value !== undefined) {
|
|
configStore.set(key, value);
|
|
}
|
|
}
|
|
}
|
|
|
|
export function getConfigValue<K extends keyof TpmConfig>(key: K): TpmConfig[K] {
|
|
return configStore.get(key);
|
|
}
|
|
|
|
export function setConfigValue<K extends keyof TpmConfig>(key: K, value: TpmConfig[K]): void {
|
|
configStore.set(key, value);
|
|
}
|
|
|
|
export function resetConfig(): void {
|
|
configStore.clear();
|
|
}
|
|
|
|
// Credentials management with secure file permissions
|
|
export function loadCredentials(): TpmCredentials | null {
|
|
ensureConfigDir();
|
|
|
|
if (!fs.existsSync(CREDENTIALS_FILE)) {
|
|
return null;
|
|
}
|
|
|
|
try {
|
|
const content = fs.readFileSync(CREDENTIALS_FILE, 'utf-8');
|
|
return JSON.parse(content) as TpmCredentials;
|
|
} catch {
|
|
return null;
|
|
}
|
|
}
|
|
|
|
export function saveCredentials(credentials: TpmCredentials): void {
|
|
ensureConfigDir();
|
|
|
|
const content = JSON.stringify(credentials, null, 2);
|
|
fs.writeFileSync(CREDENTIALS_FILE, content, { mode: 0o600 });
|
|
}
|
|
|
|
export function deleteCredentials(): void {
|
|
if (fs.existsSync(CREDENTIALS_FILE)) {
|
|
fs.unlinkSync(CREDENTIALS_FILE);
|
|
}
|
|
}
|
|
|
|
export function hasCredentials(): boolean {
|
|
const creds = loadCredentials();
|
|
return creds !== null && !!creds.apiKey;
|
|
}
|
|
|
|
// Get API key from multiple sources (priority order)
|
|
export function getApiKey(): string | undefined {
|
|
// 1. Environment variable
|
|
if (process.env.TPMJS_API_KEY) {
|
|
return process.env.TPMJS_API_KEY;
|
|
}
|
|
|
|
// 2. Credentials file
|
|
const creds = loadCredentials();
|
|
if (creds?.apiKey) {
|
|
return creds.apiKey;
|
|
}
|
|
|
|
return undefined;
|
|
}
|
|
|
|
// Get API URL
|
|
export function getApiUrl(): string {
|
|
return process.env.TPMJS_API_URL ?? getConfigValue('apiUrl') ?? 'https://tpmjs.com/api';
|
|
}
|
|
|
|
// History directory for conversation caching
|
|
export function getHistoryDir(): string {
|
|
if (!fs.existsSync(HISTORY_DIR)) {
|
|
fs.mkdirSync(HISTORY_DIR, { recursive: true, mode: 0o700 });
|
|
}
|
|
return HISTORY_DIR;
|
|
}
|
|
|
|
// Config directory path
|
|
export function getConfigDir(): string {
|
|
ensureConfigDir();
|
|
return CONFIG_DIR;
|
|
}
|