mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat(api): section-prefix all custom tool route literals
This commit is contained in:
@@ -131,7 +131,7 @@ registerAiJobHandler("ai-canvas-expand", async (input, data, ctx) => {
|
|||||||
|
|
||||||
export function registerAiCanvasExpand(app: FastifyInstance) {
|
export function registerAiCanvasExpand(app: FastifyInstance) {
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/ai-canvas-expand",
|
"/api/v1/tools/image/ai-canvas-expand",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "ai-canvas-expand";
|
const toolId = "ai-canvas-expand";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
|
|||||||
@@ -90,7 +90,7 @@ registerAiJobHandler("auto-subtitles", async (input, data, ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export function registerAutoSubtitles(app: FastifyInstance) {
|
export function registerAutoSubtitles(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/auto-subtitles", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/video/auto-subtitles", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "auto-subtitles";
|
const toolId = "auto-subtitles";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
const bundle = getBundleForTool(toolId);
|
const bundle = getBundleForTool(toolId);
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ registerAiJobHandler("background-replace", async (input, data, ctx) => {
|
|||||||
|
|
||||||
export function registerBackgroundReplace(app: FastifyInstance) {
|
export function registerBackgroundReplace(app: FastifyInstance) {
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/background-replace",
|
"/api/v1/tools/image/background-replace",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "background-replace";
|
const toolId = "background-replace";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
|
|||||||
@@ -19,7 +19,7 @@ const settingsSchema = z.object({
|
|||||||
*/
|
*/
|
||||||
export function registerBarcodeGenerate(app: FastifyInstance) {
|
export function registerBarcodeGenerate(app: FastifyInstance) {
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/barcode-generate",
|
"/api/v1/tools/image/barcode-generate",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
let body: unknown;
|
let body: unknown;
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ function buildOverlaySvg(
|
|||||||
* Read barcodes (all 1D + 2D types) from uploaded images using zxing-wasm.
|
* Read barcodes (all 1D + 2D types) from uploaded images using zxing-wasm.
|
||||||
*/
|
*/
|
||||||
export function registerBarcodeRead(app: FastifyInstance) {
|
export function registerBarcodeRead(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/barcode-read", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/image/barcode-read", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
let filename = "image";
|
let filename = "image";
|
||||||
let settingsRaw: string | null = null;
|
let settingsRaw: string | null = null;
|
||||||
|
|||||||
@@ -245,7 +245,7 @@ export async function processBeautify(
|
|||||||
|
|
||||||
export function registerBeautify(app: FastifyInstance) {
|
export function registerBeautify(app: FastifyInstance) {
|
||||||
// Custom HTTP route (multi-file upload: main image + optional background image)
|
// Custom HTTP route (multi-file upload: main image + optional background image)
|
||||||
app.post("/api/v1/tools/beautify", async (request, reply) => {
|
app.post("/api/v1/tools/image/beautify", async (request, reply) => {
|
||||||
let mainBuffer: Buffer | null = null;
|
let mainBuffer: Buffer | null = null;
|
||||||
let bgImageBuffer: Buffer | null = null;
|
let bgImageBuffer: Buffer | null = null;
|
||||||
let filename = "image";
|
let filename = "image";
|
||||||
|
|||||||
@@ -80,7 +80,7 @@ registerAiJobHandler("blur-background", async (input, data, ctx) => {
|
|||||||
|
|
||||||
export function registerBlurBackground(app: FastifyInstance) {
|
export function registerBlurBackground(app: FastifyInstance) {
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/blur-background",
|
"/api/v1/tools/image/blur-background",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "blur-background";
|
const toolId = "blur-background";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
|
|||||||
@@ -65,7 +65,7 @@ registerAiJobHandler("blur-faces", async (input, data, ctx) => {
|
|||||||
|
|
||||||
/** Face detection and blurring route. */
|
/** Face detection and blurring route. */
|
||||||
export function registerBlurFaces(app: FastifyInstance) {
|
export function registerBlurFaces(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/blur-faces", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/image/blur-faces", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "blur-faces";
|
const toolId = "blur-faces";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
const bundle = getBundleForTool(toolId);
|
const bundle = getBundleForTool(toolId);
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ const settingsSchema = z.object({
|
|||||||
* No image processing - just renames.
|
* No image processing - just renames.
|
||||||
*/
|
*/
|
||||||
export function registerBulkRename(app: FastifyInstance) {
|
export function registerBulkRename(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/bulk-rename", async (request, reply) => {
|
app.post("/api/v1/tools/image/bulk-rename", async (request, reply) => {
|
||||||
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
||||||
let settingsRaw: string | null = null;
|
let settingsRaw: string | null = null;
|
||||||
|
|
||||||
|
|||||||
@@ -421,7 +421,7 @@ function getAspectMultiplier(ar: string): number | null {
|
|||||||
// ── Route registration ────────────���─────────────────────────────────
|
// ── Route registration ────────────���─────────────────────────────────
|
||||||
|
|
||||||
export function registerCollage(app: FastifyInstance) {
|
export function registerCollage(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/collage", async (request, reply) => {
|
app.post("/api/v1/tools/image/collage", async (request, reply) => {
|
||||||
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
||||||
let settingsRaw: string | null = null;
|
let settingsRaw: string | null = null;
|
||||||
|
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ function extractColors(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function registerColorPalette(app: FastifyInstance) {
|
export function registerColorPalette(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/color-palette", async (request, reply) => {
|
app.post("/api/v1/tools/image/color-palette", async (request, reply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
let filename = "image";
|
let filename = "image";
|
||||||
let rawSettings: string | undefined;
|
let rawSettings: string | undefined;
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ registerAiJobHandler("colorize", async (input, data, ctx) => {
|
|||||||
* with OpenCV DNN fallback.
|
* with OpenCV DNN fallback.
|
||||||
*/
|
*/
|
||||||
export function registerColorize(app: FastifyInstance) {
|
export function registerColorize(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/colorize", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/image/colorize", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "colorize";
|
const toolId = "colorize";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
const bundle = getBundleForTool(toolId);
|
const bundle = getBundleForTool(toolId);
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ import { decompressSvgz, sanitizeSvg } from "../../lib/svg-sanitize.js";
|
|||||||
* Compare two images: compute a pixel-level diff and similarity score.
|
* Compare two images: compute a pixel-level diff and similarity score.
|
||||||
*/
|
*/
|
||||||
export function registerCompare(app: FastifyInstance) {
|
export function registerCompare(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/compare", async (request, reply) => {
|
app.post("/api/v1/tools/image/compare", async (request, reply) => {
|
||||||
let bufferA: Buffer | null = null;
|
let bufferA: Buffer | null = null;
|
||||||
let bufferB: Buffer | null = null;
|
let bufferB: Buffer | null = null;
|
||||||
|
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ const settingsSchema = z.object({
|
|||||||
});
|
});
|
||||||
|
|
||||||
export function registerCompose(app: FastifyInstance) {
|
export function registerCompose(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/compose", async (request, reply) => {
|
app.post("/api/v1/tools/image/compose", async (request, reply) => {
|
||||||
let baseBuffer: Buffer | null = null;
|
let baseBuffer: Buffer | null = null;
|
||||||
let overlayBuffer: Buffer | null = null;
|
let overlayBuffer: Buffer | null = null;
|
||||||
let filename = "image";
|
let filename = "image";
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ type Settings = z.infer<typeof settingsSchema>;
|
|||||||
/** Content-aware resize (seam carving via caire) route. */
|
/** Content-aware resize (seam carving via caire) route. */
|
||||||
export function registerContentAwareResize(app: FastifyInstance) {
|
export function registerContentAwareResize(app: FastifyInstance) {
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/content-aware-resize",
|
"/api/v1/tools/image/content-aware-resize",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
let filename = "image";
|
let filename = "image";
|
||||||
|
|||||||
@@ -68,7 +68,7 @@ const BROWSER_PREVIEWABLE = new Set([
|
|||||||
export function registerEditMetadata(app: FastifyInstance) {
|
export function registerEditMetadata(app: FastifyInstance) {
|
||||||
// Inspect endpoint - returns parsed metadata via ExifTool
|
// Inspect endpoint - returns parsed metadata via ExifTool
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/edit-metadata/inspect",
|
"/api/v1/tools/image/edit-metadata/inspect",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
let filename = "image";
|
let filename = "image";
|
||||||
@@ -109,7 +109,7 @@ export function registerEditMetadata(app: FastifyInstance) {
|
|||||||
);
|
);
|
||||||
|
|
||||||
// Edit endpoint - writes metadata in-place using ExifTool (no pixel re-encoding)
|
// Edit endpoint - writes metadata in-place using ExifTool (no pixel re-encoding)
|
||||||
app.post("/api/v1/tools/edit-metadata", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/image/edit-metadata", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
let filename = "image";
|
let filename = "image";
|
||||||
let settingsRaw: string | null = null;
|
let settingsRaw: string | null = null;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ registerAiJobHandler("enhance-faces", async (input, data, ctx) => {
|
|||||||
|
|
||||||
/** Face enhancement route using GFPGAN/CodeFormer. */
|
/** Face enhancement route using GFPGAN/CodeFormer. */
|
||||||
export function registerEnhanceFaces(app: FastifyInstance) {
|
export function registerEnhanceFaces(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/enhance-faces", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/image/enhance-faces", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "enhance-faces";
|
const toolId = "enhance-faces";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
const bundle = getBundleForTool(toolId);
|
const bundle = getBundleForTool(toolId);
|
||||||
|
|||||||
@@ -33,7 +33,7 @@ const settingsSchema = z.object({
|
|||||||
* via getObjectBuffer(data.inputRefs[1]) inside the handler.
|
* via getObjectBuffer(data.inputRefs[1]) inside the handler.
|
||||||
*/
|
*/
|
||||||
export function registerEraseObject(app: FastifyInstance) {
|
export function registerEraseObject(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/erase-object", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/image/erase-object", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "erase-object";
|
const toolId = "erase-object";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
const bundle = getBundleForTool(toolId);
|
const bundle = getBundleForTool(toolId);
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ interface UploadedFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function registerFavicon(app: FastifyInstance) {
|
export function registerFavicon(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/favicon", async (request, reply) => {
|
app.post("/api/v1/tools/image/favicon", async (request, reply) => {
|
||||||
const uploadedFiles: UploadedFile[] = [];
|
const uploadedFiles: UploadedFile[] = [];
|
||||||
let settingsRaw: string | null = null;
|
let settingsRaw: string | null = null;
|
||||||
|
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ async function extractFileInfo(file: FileData): Promise<FileInfo> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function registerFindDuplicates(app: FastifyInstance) {
|
export function registerFindDuplicates(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/find-duplicates", async (request, reply) => {
|
app.post("/api/v1/tools/image/find-duplicates", async (request, reply) => {
|
||||||
const files: FileData[] = [];
|
const files: FileData[] = [];
|
||||||
let settingsRaw: string | null = null;
|
let settingsRaw: string | null = null;
|
||||||
|
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ const settingsSchema = z.object({
|
|||||||
|
|
||||||
export function registerGifTools(app: FastifyInstance) {
|
export function registerGifTools(app: FastifyInstance) {
|
||||||
// ── Metadata endpoint ───────────────────────────────────────────
|
// ── Metadata endpoint ───────────────────────────────────────────
|
||||||
app.post("/api/v1/tools/gif-tools/info", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/image/gif-tools/info", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
|||||||
@@ -34,7 +34,7 @@ const settingsSchema = z
|
|||||||
|
|
||||||
export function registerHtmlToImage(app: FastifyInstance) {
|
export function registerHtmlToImage(app: FastifyInstance) {
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/html-to-image",
|
"/api/v1/tools/image/html-to-image",
|
||||||
{
|
{
|
||||||
config: {
|
config: {
|
||||||
rateLimit: { max: 120, timeWindow: "1 hour" },
|
rateLimit: { max: 120, timeWindow: "1 hour" },
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ export function registerImageEnhancement(app: FastifyInstance) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/image-enhancement/analyze",
|
"/api/v1/tools/image/image-enhancement/analyze",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
let filename = "image";
|
let filename = "image";
|
||||||
|
|||||||
@@ -54,7 +54,7 @@ function detectMimeType(format: string): string {
|
|||||||
|
|
||||||
export function registerImageToBase64(app: FastifyInstance) {
|
export function registerImageToBase64(app: FastifyInstance) {
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/image-to-base64",
|
"/api/v1/tools/image/image-to-base64",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
||||||
let settings = {};
|
let settings = {};
|
||||||
|
|||||||
@@ -97,7 +97,7 @@ async function flattenAlpha(buf: Buffer): Promise<Buffer> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function registerImageToPdf(app: FastifyInstance) {
|
export function registerImageToPdf(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/image-to-pdf", async (request, reply) => {
|
app.post("/api/v1/tools/image/image-to-pdf", async (request, reply) => {
|
||||||
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
||||||
let settingsRaw: string | null = null;
|
let settingsRaw: string | null = null;
|
||||||
|
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ const execFileAsync = promisify(execFile);
|
|||||||
* Does NOT use createToolRoute since it doesn't produce a processed file.
|
* Does NOT use createToolRoute since it doesn't produce a processed file.
|
||||||
*/
|
*/
|
||||||
export function registerInfo(app: FastifyInstance) {
|
export function registerInfo(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/info", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/image/info", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
let filename = "image";
|
let filename = "image";
|
||||||
|
|
||||||
|
|||||||
@@ -217,7 +217,7 @@ export function registerMemeGenerator(app: FastifyInstance) {
|
|||||||
},
|
},
|
||||||
});
|
});
|
||||||
|
|
||||||
app.post("/api/v1/tools/meme-generator", async (request, reply) => {
|
app.post("/api/v1/tools/image/meme-generator", async (request, reply) => {
|
||||||
const contentTypeHeader = request.headers["content-type"] ?? "";
|
const contentTypeHeader = request.headers["content-type"] ?? "";
|
||||||
const isMultipart = contentTypeHeader.includes("multipart/form-data");
|
const isMultipart = contentTypeHeader.includes("multipart/form-data");
|
||||||
|
|
||||||
|
|||||||
@@ -69,7 +69,7 @@ registerAiJobHandler("noise-removal", async (input, data, ctx) => {
|
|||||||
* Uses the Python sidecar for multi-tier denoising.
|
* Uses the Python sidecar for multi-tier denoising.
|
||||||
*/
|
*/
|
||||||
export function registerNoiseRemoval(app: FastifyInstance) {
|
export function registerNoiseRemoval(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/noise-removal", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/image/noise-removal", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "noise-removal";
|
const toolId = "noise-removal";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
const bundle = getBundleForTool(toolId);
|
const bundle = getBundleForTool(toolId);
|
||||||
|
|||||||
@@ -57,7 +57,7 @@ registerAiJobHandler("ocr-pdf", async (input, data, ctx) => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
export function registerOcrPdf(app: FastifyInstance) {
|
export function registerOcrPdf(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/ocr-pdf", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/pdf/ocr-pdf", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "ocr-pdf";
|
const toolId = "ocr-pdf";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
const bundle = getBundleForTool(toolId);
|
const bundle = getBundleForTool(toolId);
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ const settingsSchema = z.object({
|
|||||||
* Returns JSON with extracted text rather than an image.
|
* Returns JSON with extracted text rather than an image.
|
||||||
*/
|
*/
|
||||||
export function registerOcr(app: FastifyInstance) {
|
export function registerOcr(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/ocr", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/image/ocr", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "ocr";
|
const toolId = "ocr";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
const bundle = getBundleForTool(toolId);
|
const bundle = getBundleForTool(toolId);
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ async function processImage(inputBuffer: Buffer, settings: Settings, filename: s
|
|||||||
export function registerOptimizeForWeb(app: FastifyInstance) {
|
export function registerOptimizeForWeb(app: FastifyInstance) {
|
||||||
// Lightweight preview route for live parameter tuning
|
// Lightweight preview route for live parameter tuning
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/optimize-for-web/preview",
|
"/api/v1/tools/image/optimize-for-web/preview",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
let filename = "image";
|
let filename = "image";
|
||||||
|
|||||||
@@ -131,7 +131,7 @@ async function generatePrintSheet(
|
|||||||
export function registerPassportPhoto(app: FastifyInstance) {
|
export function registerPassportPhoto(app: FastifyInstance) {
|
||||||
// ── Phase 1: Analyze (face landmarks + bg removal) ────────────────
|
// ── Phase 1: Analyze (face landmarks + bg removal) ────────────────
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/passport-photo/analyze",
|
"/api/v1/tools/image/passport-photo/analyze",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "passport-photo";
|
const toolId = "passport-photo";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
@@ -310,7 +310,7 @@ export function registerPassportPhoto(app: FastifyInstance) {
|
|||||||
|
|
||||||
// ── Base route: return 501 so generic callers don't get 404 ──────
|
// ── Base route: return 501 so generic callers don't get 404 ──────
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/passport-photo",
|
"/api/v1/tools/image/passport-photo",
|
||||||
async (_request: FastifyRequest, reply: FastifyReply) => {
|
async (_request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "passport-photo";
|
const toolId = "passport-photo";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
@@ -324,14 +324,14 @@ export function registerPassportPhoto(app: FastifyInstance) {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
return reply.status(400).send({
|
return reply.status(400).send({
|
||||||
error: "Use /api/v1/tools/passport-photo/analyze or /generate",
|
error: "Use /api/v1/tools/image/passport-photo/analyze or /generate",
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
// ── Phase 2: Generate (crop + resize + tile) ─────────────────────
|
// ── Phase 2: Generate (crop + resize + tile) ─────────────────────
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/passport-photo/generate",
|
"/api/v1/tools/image/passport-photo/generate",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const parseResult = generateSettingsSchema.safeParse(request.body);
|
const parseResult = generateSettingsSchema.safeParse(request.body);
|
||||||
if (!parseResult.success) {
|
if (!parseResult.success) {
|
||||||
|
|||||||
@@ -181,7 +181,7 @@ function isPdfBuffer(buf: Buffer): boolean {
|
|||||||
// ── Route registration ───────────────────────────────────────────
|
// ── Route registration ───────────────────────────────────────────
|
||||||
export function registerPdfToImage(app: FastifyInstance) {
|
export function registerPdfToImage(app: FastifyInstance) {
|
||||||
// ── Info endpoint ────────────────────────────────────────────
|
// ── Info endpoint ────────────────────────────────────────────
|
||||||
app.post("/api/v1/tools/pdf-to-image/info", async (request, reply) => {
|
app.post("/api/v1/tools/pdf/pdf-to-image/info", async (request, reply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
try {
|
try {
|
||||||
const result = await readPdfFromParts(request);
|
const result = await readPdfFromParts(request);
|
||||||
@@ -223,7 +223,7 @@ export function registerPdfToImage(app: FastifyInstance) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ── Preview endpoint (thumbnails) ─────────────────────────────
|
// ── Preview endpoint (thumbnails) ─────────────────────────────
|
||||||
app.post("/api/v1/tools/pdf-to-image/preview", async (request, reply) => {
|
app.post("/api/v1/tools/pdf/pdf-to-image/preview", async (request, reply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
try {
|
try {
|
||||||
const result = await readPdfFromParts(request);
|
const result = await readPdfFromParts(request);
|
||||||
@@ -288,7 +288,7 @@ export function registerPdfToImage(app: FastifyInstance) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// ── Main processing endpoint ─────────────────────────────────
|
// ── Main processing endpoint ─────────────────────────────────
|
||||||
app.post("/api/v1/tools/pdf-to-image", async (request, reply) => {
|
app.post("/api/v1/tools/pdf/pdf-to-image", async (request, reply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
let settingsRaw: string | null = null;
|
let settingsRaw: string | null = null;
|
||||||
|
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ const settingsSchema = z.object({
|
|||||||
* images from text input, not from uploaded files.
|
* images from text input, not from uploaded files.
|
||||||
*/
|
*/
|
||||||
export function registerQrGenerate(app: FastifyInstance) {
|
export function registerQrGenerate(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/qr-generate", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/image/qr-generate", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
let body: unknown;
|
let body: unknown;
|
||||||
try {
|
try {
|
||||||
body = request.body;
|
body = request.body;
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ registerAiJobHandler("red-eye-removal", async (input, data, ctx) => {
|
|||||||
/** Red eye detection and removal route. */
|
/** Red eye detection and removal route. */
|
||||||
export function registerRedEyeRemoval(app: FastifyInstance) {
|
export function registerRedEyeRemoval(app: FastifyInstance) {
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/red-eye-removal",
|
"/api/v1/tools/image/red-eye-removal",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "red-eye-removal";
|
const toolId = "red-eye-removal";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
|
|||||||
@@ -92,7 +92,7 @@ registerAiJobHandler("remove-background", async (input, data, ctx) => {
|
|||||||
export function registerRemoveBackground(app: FastifyInstance) {
|
export function registerRemoveBackground(app: FastifyInstance) {
|
||||||
// ── Phase 1: Background removal ──────────────────────────────────
|
// ── Phase 1: Background removal ──────────────────────────────────
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/remove-background",
|
"/api/v1/tools/image/remove-background",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "remove-background";
|
const toolId = "remove-background";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
@@ -229,7 +229,7 @@ export function registerRemoveBackground(app: FastifyInstance) {
|
|||||||
|
|
||||||
// ── Phase 2: Effects-only (no AI re-run) ─────────────────────────
|
// ── Phase 2: Effects-only (no AI re-run) ─────────────────────────
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/remove-background/effects",
|
"/api/v1/tools/image/remove-background/effects",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
let settingsRaw: string | null = null;
|
let settingsRaw: string | null = null;
|
||||||
let bgImageBuffer: Buffer | null = null;
|
let bgImageBuffer: Buffer | null = null;
|
||||||
|
|||||||
@@ -83,7 +83,7 @@ registerAiJobHandler("restore-photo", async (input, data, ctx) => {
|
|||||||
* optional colorization.
|
* optional colorization.
|
||||||
*/
|
*/
|
||||||
export function registerRestorePhoto(app: FastifyInstance) {
|
export function registerRestorePhoto(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/restore-photo", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/image/restore-photo", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
if (!isToolInstalled("restore-photo")) {
|
if (!isToolInstalled("restore-photo")) {
|
||||||
const bundle = getBundleForTool("restore-photo");
|
const bundle = getBundleForTool("restore-photo");
|
||||||
return reply.status(501).send({
|
return reply.status(501).send({
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ function resolveOutputFormat(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function registerSplit(app: FastifyInstance) {
|
export function registerSplit(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/split", async (request, reply) => {
|
app.post("/api/v1/tools/image/split", async (request, reply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
let filename = "image";
|
let filename = "image";
|
||||||
let settingsRaw: string | null = null;
|
let settingsRaw: string | null = null;
|
||||||
|
|||||||
@@ -44,7 +44,7 @@ interface PreparedImage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function registerStitch(app: FastifyInstance) {
|
export function registerStitch(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/stitch", async (request, reply) => {
|
app.post("/api/v1/tools/image/stitch", async (request, reply) => {
|
||||||
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
const files: Array<{ buffer: Buffer; filename: string }> = [];
|
||||||
let settingsRaw: string | null = null;
|
let settingsRaw: string | null = null;
|
||||||
|
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ function parseIccProfile(iccBuffer: Buffer): Record<string, string> {
|
|||||||
export function registerStripMetadata(app: FastifyInstance) {
|
export function registerStripMetadata(app: FastifyInstance) {
|
||||||
// Inspect endpoint — returns parsed metadata as JSON
|
// Inspect endpoint — returns parsed metadata as JSON
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/strip-metadata/inspect",
|
"/api/v1/tools/image/strip-metadata/inspect",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
let filename = "image";
|
let filename = "image";
|
||||||
|
|||||||
@@ -105,7 +105,7 @@ async function convertSvg(
|
|||||||
*/
|
*/
|
||||||
export function registerSvgToRaster(app: FastifyInstance) {
|
export function registerSvgToRaster(app: FastifyInstance) {
|
||||||
// --- Batch endpoint (registered first for route priority) ---
|
// --- Batch endpoint (registered first for route priority) ---
|
||||||
app.post("/api/v1/tools/svg-to-raster/batch", async (request, reply) => {
|
app.post("/api/v1/tools/image/svg-to-raster/batch", async (request, reply) => {
|
||||||
const files: ParsedSvgFile[] = [];
|
const files: ParsedSvgFile[] = [];
|
||||||
let settingsRaw: string | null = null;
|
let settingsRaw: string | null = null;
|
||||||
let clientJobId: string | null = null;
|
let clientJobId: string | null = null;
|
||||||
@@ -347,7 +347,7 @@ export function registerSvgToRaster(app: FastifyInstance) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// --- Single-file endpoint ---
|
// --- Single-file endpoint ---
|
||||||
app.post("/api/v1/tools/svg-to-raster", async (request, reply) => {
|
app.post("/api/v1/tools/image/svg-to-raster", async (request, reply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
let filename = "output";
|
let filename = "output";
|
||||||
let settingsRaw: string | null = null;
|
let settingsRaw: string | null = null;
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ registerAiJobHandler("transcribe-audio", async (input, data, ctx) => {
|
|||||||
|
|
||||||
export function registerTranscribeAudio(app: FastifyInstance) {
|
export function registerTranscribeAudio(app: FastifyInstance) {
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/transcribe-audio",
|
"/api/v1/tools/audio/transcribe-audio",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "transcribe-audio";
|
const toolId = "transcribe-audio";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
|
|||||||
@@ -152,7 +152,7 @@ registerAiJobHandler("transparency-fixer", async (input, data, ctx) => {
|
|||||||
|
|
||||||
export function registerTransparencyFixer(app: FastifyInstance) {
|
export function registerTransparencyFixer(app: FastifyInstance) {
|
||||||
app.post(
|
app.post(
|
||||||
"/api/v1/tools/transparency-fixer",
|
"/api/v1/tools/image/transparency-fixer",
|
||||||
async (request: FastifyRequest, reply: FastifyReply) => {
|
async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
if (!isToolInstalled(TOOL_ID)) {
|
if (!isToolInstalled(TOOL_ID)) {
|
||||||
const bundle = getBundleForTool(TOOL_ID);
|
const bundle = getBundleForTool(TOOL_ID);
|
||||||
|
|||||||
@@ -116,7 +116,7 @@ registerAiJobHandler("upscale", async (input, data, ctx) => {
|
|||||||
* Uses Real-ESRGAN when available, falls back to Lanczos.
|
* Uses Real-ESRGAN when available, falls back to Lanczos.
|
||||||
*/
|
*/
|
||||||
export function registerUpscale(app: FastifyInstance) {
|
export function registerUpscale(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/upscale", async (request: FastifyRequest, reply: FastifyReply) => {
|
app.post("/api/v1/tools/image/upscale", async (request: FastifyRequest, reply: FastifyReply) => {
|
||||||
const toolId = "upscale";
|
const toolId = "upscale";
|
||||||
if (!isToolInstalled(toolId)) {
|
if (!isToolInstalled(toolId)) {
|
||||||
const bundle = getBundleForTool(toolId);
|
const bundle = getBundleForTool(toolId);
|
||||||
|
|||||||
@@ -98,7 +98,7 @@ async function vectorizeBuffer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export function registerVectorize(app: FastifyInstance) {
|
export function registerVectorize(app: FastifyInstance) {
|
||||||
app.post("/api/v1/tools/vectorize", async (request, reply) => {
|
app.post("/api/v1/tools/image/vectorize", async (request, reply) => {
|
||||||
let fileBuffer: Buffer | null = null;
|
let fileBuffer: Buffer | null = null;
|
||||||
let filename = "output";
|
let filename = "output";
|
||||||
let settingsRaw: string | null = null;
|
let settingsRaw: string | null = null;
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ const settingsSchema = z.object({
|
|||||||
|
|
||||||
export function registerWatermarkImage(app: FastifyInstance) {
|
export function registerWatermarkImage(app: FastifyInstance) {
|
||||||
// Custom route since we need two file uploads
|
// Custom route since we need two file uploads
|
||||||
app.post("/api/v1/tools/watermark-image", async (request, reply) => {
|
app.post("/api/v1/tools/image/watermark-image", async (request, reply) => {
|
||||||
let mainBuffer: Buffer | null = null;
|
let mainBuffer: Buffer | null = null;
|
||||||
let watermarkBuffer: Buffer | null = null;
|
let watermarkBuffer: Buffer | null = null;
|
||||||
let filename = "image";
|
let filename = "image";
|
||||||
|
|||||||
Reference in New Issue
Block a user