managarten/apps-archived/memoro/apps/mobile/features/credits/utils/insufficient-credits-handler.ts
Till-JS 61d181fbc2 chore: archive inactive projects to apps-archived/
Move inactive projects out of active workspace:
- bauntown (community website)
- maerchenzauber (AI story generation)
- memoro (voice memo app)
- news (news aggregation)
- nutriphi (nutrition tracking)
- reader (reading app)
- uload (URL shortener)
- wisekeep (AI wisdom extraction)

Update CLAUDE.md documentation:
- Add presi to active projects
- Document archived projects section
- Update workspace configuration

Archived apps can be re-activated by moving back to apps/

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-29 07:03:59 +01:00

103 lines
2.9 KiB
TypeScript

/**
* Handles insufficient credits errors with the new standardized format
*/
interface InsufficientCreditsError {
error: {
code: string;
message: string;
details: {
requiredCredits: number;
availableCredits: number;
creditType: 'user' | 'space';
operation: string;
operationCost: number;
spaceId?: string;
suggestions?: string[];
};
};
statusCode: number;
timestamp: string;
path: string;
}
/**
* Check if an error response is an insufficient credits error
*/
export function isInsufficientCreditsError(error: any): error is InsufficientCreditsError {
return (
error?.statusCode === 402 ||
error?.error?.code === 'INSUFFICIENT_CREDITS' ||
(error?.message && error.message.includes('Insufficient credits')) ||
(error?.message && error.message.includes('Nicht genügend Mana'))
);
}
/**
* Parse error response to extract credit information
*/
export function parseInsufficientCreditsError(error: any): {
requiredCredits?: number;
availableCredits?: number;
creditType?: 'user' | 'space';
operation?: string;
spaceId?: string;
suggestions?: string[];
} {
// Handle new standardized format from memoro-service
if (error?.details) {
return {
requiredCredits: error.details.requiredCredits,
availableCredits: error.details.availableCredits,
creditType: error.details.creditType,
operation: error.details.operation,
spaceId: error.details.spaceId,
suggestions: error.details.suggestions,
};
}
// Handle nested error object
if (error?.error?.details) {
return {
requiredCredits: error.error.details.requiredCredits,
availableCredits: error.error.details.availableCredits,
creditType: error.error.details.creditType,
operation: error.error.details.operation,
spaceId: error.error.details.spaceId,
suggestions: error.error.details.suggestions,
};
}
// Handle legacy format with message parsing
const message = error?.message || error?.error?.message || '';
if (message) {
const requiredMatch = message.match(/Required:\s*(\d+)/);
const availableMatch = message.match(/Available:\s*(\d+)/);
return {
requiredCredits: requiredMatch ? parseInt(requiredMatch[1]) : undefined,
availableCredits: availableMatch ? parseInt(availableMatch[1]) : undefined,
creditType: message.includes('space') ? 'space' : 'user',
operation: 'transcription', // Default operation
};
}
return {};
}
/**
* Format insufficient credits message for display
*/
export function formatInsufficientCreditsMessage(
errorData: ReturnType<typeof parseInsufficientCreditsError>,
t: (key: string, fallback: string) => string
): string {
if (errorData.requiredCredits && errorData.availableCredits !== undefined) {
return t(
'credits.insufficient_detailed',
`Du benötigst ${errorData.requiredCredits} Mana, hast aber nur ${errorData.availableCredits} verfügbar.`
);
}
return t('credits.insufficient_message', 'Du hast nicht genügend Mana für diese Operation.');
}