perf: convert sync file I/O to async in API routes (P0-2)
Replace all readFileSync/existsSync/readdirSync with fs.promises equivalents to unblock the Node event loop under concurrency. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
1 parent
f3c49a9e49
commit
128ccf951c
6 files changed
+41
-31
No files matched your search
@@ -1,16 +1,16 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import fs from 'fs';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import type { ErrorResponse } from '@/types';
|
||||
|
||||
function getWindowsDrives(): string[] {
|
||||
async function getWindowsDrives(): Promise<string[]> {
|
||||
if (process.platform !== 'win32') return [];
|
||||
const drives: string[] = [];
|
||||
for (let i = 65; i <= 90; i++) {
|
||||
const drive = String.fromCharCode(i) + ':\\';
|
||||
try {
|
||||
fs.accessSync(drive);
|
||||
await fs.access(drive);
|
||||
drives.push(drive);
|
||||
} catch {
|
||||
// drive not available
|
||||
@@ -26,7 +26,9 @@ export async function GET(request: NextRequest) {
|
||||
|
||||
const resolvedDir = path.resolve(dir);
|
||||
|
||||
if (!fs.existsSync(resolvedDir)) {
|
||||
try {
|
||||
await fs.access(resolvedDir);
|
||||
} catch {
|
||||
return NextResponse.json<ErrorResponse>(
|
||||
{ error: 'Directory does not exist' },
|
||||
{ status: 404 }
|
||||
@@ -34,7 +36,7 @@ export async function GET(request: NextRequest) {
|
||||
}
|
||||
|
||||
try {
|
||||
const entries = fs.readdirSync(resolvedDir, { withFileTypes: true });
|
||||
const entries = await fs.readdir(resolvedDir, { withFileTypes: true });
|
||||
const directories = entries
|
||||
.filter((e) => e.isDirectory() && !e.name.startsWith('.'))
|
||||
.map((e) => ({
|
||||
@@ -43,7 +45,7 @@ export async function GET(request: NextRequest) {
|
||||
}))
|
||||
.sort((a, b) => a.name.localeCompare(b.name));
|
||||
|
||||
const drives = getWindowsDrives();
|
||||
const drives = await getWindowsDrives();
|
||||
|
||||
return NextResponse.json({
|
||||
current: resolvedDir,
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import { readFilePreview, isPathSafe } from '@/lib/files';
|
||||
import type { FilePreviewResponse, ErrorResponse } from '@/types';
|
||||
|
||||
@@ -14,8 +16,6 @@ export async function GET(request: NextRequest) {
|
||||
);
|
||||
}
|
||||
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const resolvedPath = path.resolve(filePath);
|
||||
const homeDir = os.homedir();
|
||||
|
||||
@@ -52,7 +52,7 @@ export async function GET(request: NextRequest) {
|
||||
}
|
||||
|
||||
try {
|
||||
const preview = readFilePreview(resolvedPath, Math.min(maxLines, 1000));
|
||||
const preview = await readFilePreview(resolvedPath, Math.min(maxLines, 1000));
|
||||
return NextResponse.json<FilePreviewResponse>({ preview });
|
||||
} catch (error) {
|
||||
return NextResponse.json<ErrorResponse>(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NextRequest } from 'next/server';
|
||||
import fs from 'fs';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import { isPathSafe } from '@/lib/files';
|
||||
@@ -104,14 +104,16 @@ export async function GET(request: NextRequest) {
|
||||
});
|
||||
}
|
||||
|
||||
if (!fs.existsSync(resolved)) {
|
||||
try {
|
||||
await fs.access(resolved);
|
||||
} catch {
|
||||
return new Response(JSON.stringify({ error: 'File not found' }), {
|
||||
status: 404,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
}
|
||||
|
||||
const stat = fs.statSync(resolved);
|
||||
const stat = await fs.stat(resolved);
|
||||
if (!stat.isFile()) {
|
||||
return new Response(JSON.stringify({ error: 'Not a file' }), {
|
||||
status: 400,
|
||||
@@ -119,7 +121,7 @@ export async function GET(request: NextRequest) {
|
||||
});
|
||||
}
|
||||
|
||||
const buffer = fs.readFileSync(resolved);
|
||||
const buffer = await fs.readFile(resolved);
|
||||
const ext = path.extname(resolved).toLowerCase();
|
||||
const contentType = MIME_TYPES[ext] || 'application/octet-stream';
|
||||
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
import { NextRequest, NextResponse } from 'next/server';
|
||||
import path from 'path';
|
||||
import os from 'os';
|
||||
import { scanDirectory, isPathSafe } from '@/lib/files';
|
||||
import type { FileTreeResponse, ErrorResponse } from '@/types';
|
||||
|
||||
@@ -14,8 +16,6 @@ export async function GET(request: NextRequest) {
|
||||
);
|
||||
}
|
||||
|
||||
const path = require('path');
|
||||
const os = require('os');
|
||||
const resolvedDir = path.resolve(dir);
|
||||
const homeDir = os.homedir();
|
||||
|
||||
@@ -52,7 +52,7 @@ export async function GET(request: NextRequest) {
|
||||
}
|
||||
|
||||
try {
|
||||
const tree = scanDirectory(resolvedDir, Math.min(depth, 5));
|
||||
const tree = await scanDirectory(resolvedDir, Math.min(depth, 5));
|
||||
return NextResponse.json<FileTreeResponse>({ tree, root: resolvedDir });
|
||||
} catch (error) {
|
||||
return NextResponse.json<ErrorResponse>(
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
import { NextRequest } from 'next/server';
|
||||
import fs from 'fs';
|
||||
import fs from 'fs/promises';
|
||||
import path from 'path';
|
||||
|
||||
export const runtime = 'nodejs';
|
||||
@@ -42,14 +42,16 @@ export async function GET(request: NextRequest) {
|
||||
});
|
||||
}
|
||||
|
||||
if (!fs.existsSync(resolved)) {
|
||||
try {
|
||||
await fs.access(resolved);
|
||||
} catch {
|
||||
return new Response(JSON.stringify({ error: 'File not found' }), {
|
||||
status: 404,
|
||||
headers: { 'Content-Type': 'application/json' },
|
||||
});
|
||||
}
|
||||
|
||||
const buffer = fs.readFileSync(resolved);
|
||||
const buffer = await fs.readFile(resolved);
|
||||
const ext = path.extname(resolved).toLowerCase();
|
||||
const contentType = MIME_TYPES[ext] || 'application/octet-stream';
|
||||
|
||||
|
||||
Reference in new issue
Block a user