mirror of
https://github.com/snapotter-hq/SnapOtter.git
synced 2026-08-03 07:46:42 +02:00
feat: widen all Zod schema constraints for power users
Raise all artificially low max values on tool settings: - stitch: grid→100, gap→1000, border/radius→500 - split: grid→100x100 - collage: zoom→10, gap→500, radius→500 - watermark: fontSize→1000 - border: width→2000, radius→2000, shadow→200 - qr: size→10000 - gif: dimensions→16384 - passport: dpi→1200 - sharpening: amount→1000 - pdf/svg: dpi→2400, dimensions→65536 - vectorize: precision→16 - bulk-rename: pattern→1000 - image-to-pdf: margin→500 - pipeline: name→255, description→2000
This commit is contained in:
@@ -44,8 +44,8 @@ const pipelineDefinitionSchema = z.object({
|
|||||||
|
|
||||||
/** Schema for saving a pipeline. */
|
/** Schema for saving a pipeline. */
|
||||||
const savePipelineSchema = z.object({
|
const savePipelineSchema = z.object({
|
||||||
name: z.string().min(1, "Pipeline name is required").max(100),
|
name: z.string().min(1, "Pipeline name is required").max(255),
|
||||||
description: z.string().max(500).optional(),
|
description: z.string().max(2000).optional(),
|
||||||
steps: z
|
steps: z
|
||||||
.array(pipelineStepSchema)
|
.array(pipelineStepSchema)
|
||||||
.min(1, "Pipeline must have at least one step")
|
.min(1, "Pipeline must have at least one step")
|
||||||
|
|||||||
@@ -6,13 +6,13 @@ import { createToolRoute } from "../tool-factory.js";
|
|||||||
const hexColor = z.string().regex(/^#[0-9a-fA-F]{6}$/);
|
const hexColor = z.string().regex(/^#[0-9a-fA-F]{6}$/);
|
||||||
|
|
||||||
const settingsSchema = z.object({
|
const settingsSchema = z.object({
|
||||||
borderWidth: z.number().min(0).max(200).default(10),
|
borderWidth: z.number().min(0).max(2000).default(10),
|
||||||
borderColor: hexColor.default("#000000"),
|
borderColor: hexColor.default("#000000"),
|
||||||
padding: z.number().min(0).max(200).default(0),
|
padding: z.number().min(0).max(200).default(0),
|
||||||
paddingColor: hexColor.default("#FFFFFF"),
|
paddingColor: hexColor.default("#FFFFFF"),
|
||||||
cornerRadius: z.number().min(0).max(500).default(0),
|
cornerRadius: z.number().min(0).max(2000).default(0),
|
||||||
shadow: z.boolean().default(false),
|
shadow: z.boolean().default(false),
|
||||||
shadowBlur: z.number().min(1).max(50).default(15),
|
shadowBlur: z.number().min(1).max(200).default(15),
|
||||||
shadowOffsetX: z.number().min(-50).max(50).default(0),
|
shadowOffsetX: z.number().min(-50).max(50).default(0),
|
||||||
shadowOffsetY: z.number().min(-50).max(50).default(5),
|
shadowOffsetY: z.number().min(-50).max(50).default(5),
|
||||||
shadowColor: hexColor.default("#000000"),
|
shadowColor: hexColor.default("#000000"),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { z } from "zod";
|
|||||||
import { formatZodErrors } from "../../lib/errors.js";
|
import { formatZodErrors } from "../../lib/errors.js";
|
||||||
|
|
||||||
const settingsSchema = z.object({
|
const settingsSchema = z.object({
|
||||||
pattern: z.string().min(1).max(200).default("image-{{index}}"),
|
pattern: z.string().min(1).max(1000).default("image-{{index}}"),
|
||||||
startIndex: z.number().min(0).default(1),
|
startIndex: z.number().min(0).default(1),
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|||||||
@@ -321,15 +321,15 @@ const cellSchema = z.object({
|
|||||||
imageIndex: z.number().int().min(0),
|
imageIndex: z.number().int().min(0),
|
||||||
panX: z.number().min(-100).max(100).default(0),
|
panX: z.number().min(-100).max(100).default(0),
|
||||||
panY: z.number().min(-100).max(100).default(0),
|
panY: z.number().min(-100).max(100).default(0),
|
||||||
zoom: z.number().min(1).max(3).default(1),
|
zoom: z.number().min(1).max(10).default(1),
|
||||||
objectFit: z.enum(["cover", "contain"]).default("cover"),
|
objectFit: z.enum(["cover", "contain"]).default("cover"),
|
||||||
});
|
});
|
||||||
|
|
||||||
const settingsSchema = z.object({
|
const settingsSchema = z.object({
|
||||||
templateId: z.string(),
|
templateId: z.string(),
|
||||||
cells: z.array(cellSchema).optional(),
|
cells: z.array(cellSchema).optional(),
|
||||||
gap: z.number().min(0).max(50).default(8),
|
gap: z.number().min(0).max(500).default(8),
|
||||||
cornerRadius: z.number().min(0).max(30).default(0),
|
cornerRadius: z.number().min(0).max(500).default(0),
|
||||||
backgroundColor: z.string().default("#FFFFFF"),
|
backgroundColor: z.string().default("#FFFFFF"),
|
||||||
aspectRatio: z.string().default("free"),
|
aspectRatio: z.string().default("free"),
|
||||||
outputFormat: z.enum(["png", "jpeg", "webp"]).default("png"),
|
outputFormat: z.enum(["png", "jpeg", "webp"]).default("png"),
|
||||||
|
|||||||
@@ -65,8 +65,8 @@ const settingsSchema = z.object({
|
|||||||
mode: z.enum(["resize", "optimize", "speed", "reverse", "extract", "rotate"]).default("resize"),
|
mode: z.enum(["resize", "optimize", "speed", "reverse", "extract", "rotate"]).default("resize"),
|
||||||
|
|
||||||
// Resize
|
// Resize
|
||||||
width: z.number().min(1).max(4096).optional(),
|
width: z.number().min(1).max(16384).optional(),
|
||||||
height: z.number().min(1).max(4096).optional(),
|
height: z.number().min(1).max(16384).optional(),
|
||||||
percentage: z.number().min(1).max(500).optional(),
|
percentage: z.number().min(1).max(500).optional(),
|
||||||
|
|
||||||
// Optimize
|
// Optimize
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import { createWorkspace } from "../../lib/workspace.js";
|
|||||||
const settingsSchema = z.object({
|
const settingsSchema = z.object({
|
||||||
pageSize: z.enum(["A4", "Letter", "A3", "A5"]).default("A4"),
|
pageSize: z.enum(["A4", "Letter", "A3", "A5"]).default("A4"),
|
||||||
orientation: z.enum(["portrait", "landscape"]).default("portrait"),
|
orientation: z.enum(["portrait", "landscape"]).default("portrait"),
|
||||||
margin: z.number().min(0).max(100).default(20),
|
margin: z.number().min(0).max(500).default(20),
|
||||||
});
|
});
|
||||||
|
|
||||||
const PAGE_SIZES: Record<string, [number, number]> = {
|
const PAGE_SIZES: Record<string, [number, number]> = {
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ const generateSettingsSchema = z.object({
|
|||||||
bgColor: z.string().default("#FFFFFF"),
|
bgColor: z.string().default("#FFFFFF"),
|
||||||
printLayout: z.string().default("none"),
|
printLayout: z.string().default("none"),
|
||||||
maxFileSizeKb: z.number().default(0),
|
maxFileSizeKb: z.number().default(0),
|
||||||
dpi: z.number().min(72).max(600).default(300),
|
dpi: z.number().min(72).max(1200).default(300),
|
||||||
customWidthMm: z.number().optional(),
|
customWidthMm: z.number().optional(),
|
||||||
customHeightMm: z.number().optional(),
|
customHeightMm: z.number().optional(),
|
||||||
zoom: z.number().min(0.5).max(3).default(1),
|
zoom: z.number().min(0.5).max(3).default(1),
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import { createWorkspace } from "../../lib/workspace.js";
|
|||||||
// ── Settings schema ──────────────────────────────────────────────
|
// ── Settings schema ──────────────────────────────────────────────
|
||||||
const settingsSchema = z.object({
|
const settingsSchema = z.object({
|
||||||
format: z.enum(["png", "jpg", "webp", "avif", "tiff", "gif", "heic", "heif"]).default("png"),
|
format: z.enum(["png", "jpg", "webp", "avif", "tiff", "gif", "heic", "heif"]).default("png"),
|
||||||
dpi: z.number().min(36).max(1200).default(150),
|
dpi: z.number().min(36).max(2400).default(150),
|
||||||
quality: z.number().min(1).max(100).default(85),
|
quality: z.number().min(1).max(100).default(85),
|
||||||
colorMode: z.enum(["color", "grayscale", "bw"]).default("color"),
|
colorMode: z.enum(["color", "grayscale", "bw"]).default("color"),
|
||||||
pages: z.string().default("all"),
|
pages: z.string().default("all"),
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ import { createWorkspace } from "../../lib/workspace.js";
|
|||||||
|
|
||||||
const settingsSchema = z.object({
|
const settingsSchema = z.object({
|
||||||
text: z.string().min(1).max(2000),
|
text: z.string().min(1).max(2000),
|
||||||
size: z.number().min(100).max(2000).default(400),
|
size: z.number().min(100).max(10000).default(400),
|
||||||
errorCorrection: z.enum(["L", "M", "Q", "H"]).default("M"),
|
errorCorrection: z.enum(["L", "M", "Q", "H"]).default("M"),
|
||||||
foreground: z
|
foreground: z
|
||||||
.string()
|
.string()
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ const settingsSchema = z.object({
|
|||||||
y2: z.number().min(0).max(50).default(12),
|
y2: z.number().min(0).max(50).default(12),
|
||||||
y3: z.number().min(0).max(50).default(20),
|
y3: z.number().min(0).max(50).default(20),
|
||||||
// Unsharp Mask
|
// Unsharp Mask
|
||||||
amount: z.number().min(0).max(500).default(100),
|
amount: z.number().min(0).max(1000).default(100),
|
||||||
radius: z.number().min(0.1).max(5).default(1.0),
|
radius: z.number().min(0.1).max(5).default(1.0),
|
||||||
threshold: z.number().min(0).max(255).default(0),
|
threshold: z.number().min(0).max(255).default(0),
|
||||||
// High-Pass
|
// High-Pass
|
||||||
|
|||||||
@@ -9,8 +9,8 @@ import { formatZodErrors } from "../../lib/errors.js";
|
|||||||
import { ensureSharpCompat } from "../../lib/heic-converter.js";
|
import { ensureSharpCompat } from "../../lib/heic-converter.js";
|
||||||
|
|
||||||
const settingsSchema = z.object({
|
const settingsSchema = z.object({
|
||||||
columns: z.number().min(1).max(20).default(3),
|
columns: z.number().min(1).max(100).default(3),
|
||||||
rows: z.number().min(1).max(20).default(3),
|
rows: z.number().min(1).max(100).default(3),
|
||||||
tileWidth: z.number().min(10).optional(),
|
tileWidth: z.number().min(10).optional(),
|
||||||
tileHeight: z.number().min(10).optional(),
|
tileHeight: z.number().min(10).optional(),
|
||||||
outputFormat: z.enum(["original", "png", "jpg", "webp"]).default("original"),
|
outputFormat: z.enum(["original", "png", "jpg", "webp"]).default("original"),
|
||||||
@@ -89,8 +89,8 @@ export function registerSplit(app: FastifyInstance) {
|
|||||||
cols = Math.max(1, Math.ceil(fullW / settings.tileWidth));
|
cols = Math.max(1, Math.ceil(fullW / settings.tileWidth));
|
||||||
rows = Math.max(1, Math.ceil(fullH / settings.tileHeight));
|
rows = Math.max(1, Math.ceil(fullH / settings.tileHeight));
|
||||||
}
|
}
|
||||||
cols = Math.min(cols, 20);
|
cols = Math.min(cols, 100);
|
||||||
rows = Math.min(rows, 20);
|
rows = Math.min(rows, 100);
|
||||||
|
|
||||||
const cellW = Math.floor(fullW / cols);
|
const cellW = Math.floor(fullW / cols);
|
||||||
const cellH = Math.floor(fullH / rows);
|
const cellH = Math.floor(fullH / rows);
|
||||||
|
|||||||
@@ -14,12 +14,12 @@ const MAX_CANVAS_PIXELS = 100_000_000;
|
|||||||
|
|
||||||
const settingsSchema = z.object({
|
const settingsSchema = z.object({
|
||||||
direction: z.enum(["horizontal", "vertical", "grid"]).default("horizontal"),
|
direction: z.enum(["horizontal", "vertical", "grid"]).default("horizontal"),
|
||||||
gridColumns: z.number().int().min(2).max(10).default(2),
|
gridColumns: z.number().int().min(2).max(100).default(2),
|
||||||
resizeMode: z.enum(["fit", "original", "stretch", "crop"]).default("fit"),
|
resizeMode: z.enum(["fit", "original", "stretch", "crop"]).default("fit"),
|
||||||
alignment: z.enum(["start", "center", "end"]).default("center"),
|
alignment: z.enum(["start", "center", "end"]).default("center"),
|
||||||
gap: z.number().min(0).max(200).default(0),
|
gap: z.number().min(0).max(1000).default(0),
|
||||||
border: z.number().min(0).max(50).default(0),
|
border: z.number().min(0).max(500).default(0),
|
||||||
cornerRadius: z.number().min(0).max(50).default(0),
|
cornerRadius: z.number().min(0).max(500).default(0),
|
||||||
backgroundColor: z
|
backgroundColor: z
|
||||||
.string()
|
.string()
|
||||||
.regex(/^#[0-9a-fA-F]{6}$/)
|
.regex(/^#[0-9a-fA-F]{6}$/)
|
||||||
|
|||||||
@@ -17,9 +17,9 @@ import { updateJobProgress } from "../progress.js";
|
|||||||
const NON_PREVIEWABLE = new Set(["tiff", "heif"]);
|
const NON_PREVIEWABLE = new Set(["tiff", "heif"]);
|
||||||
|
|
||||||
const settingsSchema = z.object({
|
const settingsSchema = z.object({
|
||||||
width: z.number().min(1).max(16384).optional(),
|
width: z.number().min(1).max(65536).optional(),
|
||||||
height: z.number().min(1).max(16384).optional(),
|
height: z.number().min(1).max(65536).optional(),
|
||||||
dpi: z.number().min(36).max(1200).default(300),
|
dpi: z.number().min(36).max(2400).default(300),
|
||||||
quality: z.number().min(1).max(100).default(90),
|
quality: z.number().min(1).max(100).default(90),
|
||||||
backgroundColor: z
|
backgroundColor: z
|
||||||
.string()
|
.string()
|
||||||
|
|||||||
@@ -14,9 +14,9 @@ import { createWorkspace } from "../../lib/workspace.js";
|
|||||||
const settingsSchema = z.object({
|
const settingsSchema = z.object({
|
||||||
colorMode: z.enum(["bw", "color"]).default("bw"),
|
colorMode: z.enum(["bw", "color"]).default("bw"),
|
||||||
threshold: z.number().min(0).max(255).default(128),
|
threshold: z.number().min(0).max(255).default(128),
|
||||||
colorPrecision: z.number().min(1).max(8).default(6),
|
colorPrecision: z.number().min(1).max(16).default(6),
|
||||||
layerDifference: z.number().min(1).max(64).default(6),
|
layerDifference: z.number().min(1).max(128).default(6),
|
||||||
filterSpeckle: z.number().min(1).max(128).default(4),
|
filterSpeckle: z.number().min(1).max(256).default(4),
|
||||||
pathMode: z.enum(["none", "polygon", "spline"]).default("spline"),
|
pathMode: z.enum(["none", "polygon", "spline"]).default("spline"),
|
||||||
cornerThreshold: z.number().min(0).max(180).default(60),
|
cornerThreshold: z.number().min(0).max(180).default(60),
|
||||||
invert: z.boolean().default(false),
|
invert: z.boolean().default(false),
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ import { createToolRoute } from "../tool-factory.js";
|
|||||||
|
|
||||||
const settingsSchema = z.object({
|
const settingsSchema = z.object({
|
||||||
text: z.string().min(1).max(500),
|
text: z.string().min(1).max(500),
|
||||||
fontSize: z.number().min(8).max(200).default(48),
|
fontSize: z.number().min(8).max(1000).default(48),
|
||||||
color: z
|
color: z
|
||||||
.string()
|
.string()
|
||||||
.regex(/^#[0-9a-fA-F]{6}$/)
|
.regex(/^#[0-9a-fA-F]{6}$/)
|
||||||
|
|||||||
Reference in New Issue
Block a user