All files / src/app/api/admin/dev-tools/lint route.ts

0% Statements 0/105
100% Branches 0/0
0% Functions 0/1
0% Lines 0/105

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                                                                                                                                                                                                                   
/**
 * Lint Checker API
 * POST /api/admin/dev-tools/lint - Run ESLint
 * GET /api/admin/dev-tools/lint - Get lint status
 */

import { NextRequest, NextResponse } from 'next/server';
import { } from 'next-auth';
import {
  withAdmin,
  withErrorHandling,
  successResponse,
  ApiError,
  ApiSuccessResponse,
  ApiErrorResponse } from '@/lib/api';
import { } from '@/lib/api/middleware';
import { runLint, isProcessRunning, killProcess } from '@/lib/dev-tools/command-runner';
import { parseEslintOutput } from '@/lib/dev-tools/output-parsers';
import type { CommandStatusResponse } from '@/lib/dev-tools/types';

const PROCESS_ID = 'dev-tools-lint';

// Store last result
let lastResult: CommandStatusResponse = { status: 'idle' };

/**
 * POST - Run lint
 */
async function handlePost(request: NextRequest): Promise<NextResponse<ApiSuccessResponse<unknown> | ApiErrorResponse>> {
  // Check if lint is already running
  if (isProcessRunning(PROCESS_ID)) {
    throw ApiError.conflict('Lint is already running');
  }

  const body = await request.json().catch(() => ({}));
  const { path, fix } = body as { path?: string; fix?: boolean };

  // Update status to running
  lastResult = {
    status: 'running',
    startedAt: new Date().toISOString() };

  // Run lint asynchronously
  runLint({ path, fix, processId: PROCESS_ID })
    .then((result) => {
      const parsedResult = parseEslintOutput(result.output + result.error, result.exitCode);
      lastResult = {
        status: result.success ? 'completed' : 'failed',
        output: result.output + result.error,
        result: parsedResult,
        startedAt: lastResult.startedAt,
        completedAt: new Date().toISOString() };
    })
    .catch((error) => {
      lastResult = {
        status: 'failed',
        output: error.message,
        startedAt: lastResult.startedAt,
        completedAt: new Date().toISOString() };
    });

  return successResponse({
    success: true,
    message: fix ? 'Lint with fix started' : 'Lint started',
    status: 'running' });
}

/**
 * GET - Get lint status
 */
async function handleGet(): Promise<NextResponse<ApiSuccessResponse<CommandStatusResponse> | ApiErrorResponse>> {
  // Check if still running
  if (lastResult.status === 'running' && !isProcessRunning(PROCESS_ID)) {
    lastResult.status = 'failed';
    lastResult.completedAt = new Date().toISOString();
  }

  return successResponse(lastResult);
}

/**
 * DELETE - Stop running lint
 */
async function handleDelete(): Promise<NextResponse<ApiSuccessResponse<{ success: boolean; message: string }> | ApiErrorResponse>> {
  if (!isProcessRunning(PROCESS_ID)) {
    throw ApiError.notFound('No lint running');
  }

  const killed = killProcess(PROCESS_ID);
  if (killed) {
    lastResult = {
      status: 'failed',
      output: 'Lint cancelled by user',
      startedAt: lastResult.startedAt,
      completedAt: new Date().toISOString() };
    return successResponse({ success: true, message: 'Lint stopped' });
  }

  throw ApiError.internal('Failed to stop lint');
}

// Export handlers wrapped with middleware
export const GET = withErrorHandling(withAdmin(handleGet));
export const POST = withErrorHandling(withAdmin(handlePost));
export const DELETE = withErrorHandling(withAdmin(handleDelete));