UNPKG

screenshotone-validations

Version:

Validation schemes for the ScreenshotOne API requests.

428 lines (427 loc) 20.2 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); const joi_1 = __importDefault(require("joi")); const screenshotone_devices_1 = __importDefault(require("screenshotone-devices")); const validationOptions = { abortEarly: false }; const accessKeyScheme = { access_key: joi_1.default.string().optional(), }; const signatureScheme = { signature: joi_1.default.string().optional(), }; const createUriValidator = (fieldName) => { return (value, helper) => { try { if (!value) { return helper.message(`"${fieldName}" must be specified`); } if (value.trim().length === 0 || value.trim() !== value) { return helper.message(`"${fieldName}" must be specified without leading and trailing white spaces`); } const u = new URL(value); if (u.protocol !== "http:" && u.protocol !== "https:") { return helper.message(`"${fieldName}" must be a valid URI with a scheme matching the http|https pattern`); } const withoutProtocol = value.substring((u.protocol + "//").length); if (withoutProtocol.startsWith("http://") || withoutProtocol.startsWith("https://")) { return helper.message(`"${fieldName}" must be a valid URI with a scheme matching the http|https pattern`); } return value; } catch (e) { return helper.message(`"${fieldName}" must be a valid URI`); } }; }; const validUri = createUriValidator("url"); const screenshotScheme = { // image options image_quality: joi_1.default.when("format", { is: joi_1.default.valid("jpeg", "jpg", "webp", "png", "tiff", "jp2", "avif", "heif"), then: joi_1.default.number().integer().min(0).max(100).default(100), otherwise: joi_1.default.forbidden(), }), image_width: joi_1.default.number().integer().optional(), image_height: joi_1.default.number().integer().optional(), omit_background: joi_1.default.when("format", { is: joi_1.default.valid("png"), then: joi_1.default.boolean().default(false), otherwise: joi_1.default.forbidden(), }).messages({ "any.unknown": 'The "omit_background" option is only allowed to use with image formats that support transparent backgrounds, like PNG.', }), // full page options full_page: joi_1.default.boolean().default(false), full_page_scroll: joi_1.default.when("full_page", { is: true, then: joi_1.default.boolean().default(true), otherwise: joi_1.default.forbidden(), }), full_page_scroll_delay: joi_1.default.when("full_page_scroll", { is: true, then: joi_1.default.number().integer().positive().min(100).default(400), otherwise: joi_1.default.forbidden(), }), full_page_scroll_by: joi_1.default.when("full_page_scroll", { is: true, then: joi_1.default.number().integer().positive(), otherwise: joi_1.default.forbidden(), }), full_page_max_height: joi_1.default.when("full_page", { is: true, then: joi_1.default.number().integer().positive().optional(), otherwise: joi_1.default.forbidden(), }), full_page_algorithm: joi_1.default.when("full_page", { is: true, then: joi_1.default.string().valid("by_sections", "default").default("default"), otherwise: joi_1.default.forbidden(), }), capture_beyond_viewport: joi_1.default.when("selector", { is: joi_1.default.string().required(), then: joi_1.default.boolean().default(true), otherwise: joi_1.default.boolean().default(joi_1.default.ref("full_page")), }), selector: joi_1.default.when("format", { is: joi_1.default.valid("pdf"), then: joi_1.default.forbidden(), otherwise: joi_1.default.string().optional(), }).messages({ "any.unknown": 'Rendering PDFs by "selector" is not allowed.', }), selector_algorithm: joi_1.default.when("selector", { is: joi_1.default.string().required(), then: joi_1.default.string().valid("clip", "default").default("default"), otherwise: joi_1.default.forbidden(), }), selector_scroll_into_view: joi_1.default.when("selector", { is: joi_1.default.string().required(), then: joi_1.default.boolean().default(true), otherwise: joi_1.default.forbidden(), }), error_on_selector_not_found: joi_1.default.boolean().default(false), scroll_into_view: joi_1.default.string().optional(), scroll_into_view_adjust_top: joi_1.default.number().integer().default(0), format: joi_1.default.string() .trim() .lowercase() .valid("png", "jpeg", "jpg", "webp", "gif", "jp2", "tiff", "avif", "heif", "html", "pdf", "markdown") .default("jpg"), metadata_image_size: joi_1.default.boolean().default(false), clip_x: joi_1.default.number().integer().optional(), clip_y: joi_1.default.number().integer().optional(), clip_width: joi_1.default.number().integer().optional(), clip_height: joi_1.default.number().integer().optional(), vision_prompt: joi_1.default.string().optional(), vision_max_tokens: joi_1.default.number().integer().optional(), openai_api_key: joi_1.default.string().optional(), pdf_margin: joi_1.default.string().optional(), pdf_margin_top: joi_1.default.string().optional(), pdf_margin_right: joi_1.default.string().optional(), pdf_margin_bottom: joi_1.default.string().optional(), pdf_margin_left: joi_1.default.string().optional(), pdf_print_background: joi_1.default.boolean().optional(), pdf_fit_one_page: joi_1.default.boolean().optional(), pdf_landscape: joi_1.default.boolean().optional(), pdf_paper_format: joi_1.default.string() .valid("a0", "a1", "a2", "a3", "a4", "a5", "a6", "legal", "letter", "tabloid") .optional(), }; const commonOptionsScheme = joi_1.default.object({ // URL or HTML is required url: joi_1.default.string().custom(validUri).optional(), html: joi_1.default.string().optional(), markdown: joi_1.default.string().optional(), response_type: joi_1.default.string() .trim() .lowercase() .valid("by_format", "empty", "json") .default("by_format"), request_gpu_rendering: joi_1.default.boolean().default(false), fail_if_gpu_rendering_fails: joi_1.default.boolean().default(false), include_shadow_dom: joi_1.default.boolean().default(false), // emulation dark_mode: joi_1.default.boolean().optional(), reduced_motion: joi_1.default.boolean().optional(), media_type: joi_1.default.string() .trim() .lowercase() .valid("screen", "print") .optional(), // customization options scripts: joi_1.default.string().optional(), scripts_wait_until: joi_1.default.array() .items(joi_1.default.string().valid("load", "domcontentloaded", "networkidle0", "networkidle2")) .default([]), styles: joi_1.default.string().optional(), hide_selectors: joi_1.default.array().items(), click: joi_1.default.string().optional(), error_on_click_selector_not_found: joi_1.default.boolean().default(true), // viewport options viewport_device: joi_1.default.string() .valid(...screenshotone_devices_1.default.names) .optional(), viewport_width: joi_1.default.number().integer().optional(), viewport_height: joi_1.default.number().integer().optional(), device_scale_factor: joi_1.default.number().min(1).max(5).optional(), viewport_mobile: joi_1.default.boolean().optional(), viewport_has_touch: joi_1.default.boolean().optional(), viewport_landscape: joi_1.default.boolean().optional(), // geolocation options geolocation_latitude: joi_1.default.number().min(-90).max(90).optional(), geolocation_longitude: joi_1.default.number().min(-180).max(180).optional(), geolocation_accuracy: joi_1.default.number().integer().positive().optional(), // location options ip_country_code: joi_1.default.string() .valid("us", "gb", "de", "it", "fr", "cn", "ca", "es", "jp", "kr", "in", "au", "br", "mx", "nz", "pe", "is", "ie") .optional(), servers_region: joi_1.default.string().valid("us-east").default("us-east"), // blocking options block_annoyances: joi_1.default.boolean().default(false), block_cookie_banners: joi_1.default.boolean().default(false), block_banners_by_heuristics: joi_1.default.boolean().default(false), block_chats: joi_1.default.boolean().default(false), block_ads: joi_1.default.boolean().default(false), block_socials: joi_1.default.boolean().default(false), block_trackers: joi_1.default.boolean().default(false), block_requests: joi_1.default.array().items(joi_1.default.string()).default([]), block_resources: joi_1.default.array() .items(joi_1.default.string().valid("document", "stylesheet", "image", "media", "font", "script", "texttrack", "xhr", "fetch", "eventsource", "websocket", "manifest", "other")) .default([]), // cache options cache: joi_1.default.boolean().default(false).optional(), cache_ttl: joi_1.default.when("cache", { is: true, then: joi_1.default.number() .integer() .min(14400) // 4 hours .max(2592000) // 1 month .default(14400) .optional(), otherwise: joi_1.default.forbidden().messages({ "any.unknown": "The `cache_ttl` option cannot be used when the `cache` option is false or not set.", }), }), cache_key: joi_1.default.when("cache", { is: true, then: joi_1.default.string().alphanum().min(1).max(250).optional(), otherwise: joi_1.default.forbidden().messages({ "any.unknown": "The `cache_key` option cannot be used when the `cache` option is false or not set.", }), }), // request options user_agent: joi_1.default.string().optional(), authorization: joi_1.default.string().optional(), headers: joi_1.default.array().items(), cookies: joi_1.default.array().items(), proxy: joi_1.default.string() // `encodeUri` allows to specify Unicode characters in the proxy URI // it is useful when targeting is used in proxies and cities or countries are specified // with special characters .uri({ scheme: ["http"], encodeUri: true }) // makes sense to double-check it, since it will be anyway validated and fail if not correct .custom(createUriValidator("proxy")) .optional(), attachment_name: joi_1.default.string().optional(), bypass_csp: joi_1.default.boolean().default(false).optional(), time_zone: joi_1.default.string().valid("America/Belize", "America/Cayman", "America/Chicago", "America/Costa_Rica", "America/Denver", "America/Edmonton", "America/El_Salvador", "America/Guatemala", "America/Guayaquil", "America/Hermosillo", "America/Jamaica", "America/Los_Angeles", "America/Mexico_City", "America/Nassau", "America/New_York", "America/Panama", "America/Port-au-Prince", "America/Santiago", "America/Tegucigalpa", "America/Tijuana", "America/Toronto", "America/Vancouver", "America/Winnipeg", "Asia/Kuala_Lumpur", "Asia/Shanghai", "Asia/Tashkent", "Europe/Berlin", "Europe/Kiev", "Europe/Lisbon", "Europe/London", "Europe/Madrid", "Pacific/Auckland", "Pacific/Majuro"), // wait, timeout delay: joi_1.default.number() .integer() .min(0) .when("timeout", { is: joi_1.default.number().greater(300), then: joi_1.default.number().max(300), otherwise: joi_1.default.number().max(30), }) .optional(), timeout: joi_1.default.number().when("async", { is: true, then: joi_1.default.number().integer().min(0).max(600).default(600), otherwise: joi_1.default.number().integer().min(0).max(90).default(60), }), navigation_timeout: joi_1.default.number().integer().min(0).max(30).default(30), wait_until: joi_1.default.array() .items(joi_1.default.string().valid("load", "domcontentloaded", "networkidle0", "networkidle2")) .default([]), wait_for_selector: joi_1.default.string().optional(), wait_for_selector_algorithm: joi_1.default.string() .valid("at_least_one", "at_least_by_count") .default("at_least_one") .optional(), fail_if_content_contains: joi_1.default.array() .items(joi_1.default.string().optional()) .default([]), fail_if_content_missing: joi_1.default.array() .items(joi_1.default.string().optional()) .default([]), fail_if_request_failed: joi_1.default.array() .items(joi_1.default.string().optional()) .default([]), async: joi_1.default.boolean().default(false), webhook_url: joi_1.default.string() .trim() .custom(validUri) .when("response_type", { is: joi_1.default.string().valid("json", "by_format"), then: joi_1.default.optional(), otherwise: joi_1.default.forbidden(), }), webhook_sign: joi_1.default.boolean().default(true), webhook_errors: joi_1.default.boolean().default(false), external_identifier: joi_1.default.string().alphanum().min(1).max(64).optional(), // store store: joi_1.default.boolean().optional(), storage_bucket: joi_1.default.string().optional(), storage_path: joi_1.default.string().when("store", { is: true, then: joi_1.default.required(), otherwise: joi_1.default.forbidden(), }), storage_endpoint: joi_1.default.string().uri().optional(), storage_access_key_id: joi_1.default.string().optional(), storage_secret_access_key: joi_1.default.string().optional(), storage_acl: joi_1.default.string().valid("public-read", "").default(""), storage_class: joi_1.default.string() .valid("standard", "reduced_redundancy", "standard_ia", "onezone_ia", "intelligent_tiering", "glacier", "deep_archive", "outposts", "glacier_ir") .default("standard"), storage_return_location: joi_1.default.boolean().default(false), ignore_host_errors: joi_1.default.boolean().default(false), metadata_fonts: joi_1.default.boolean().default(false), metadata_content: joi_1.default.boolean().default(false), metadata_page_title: joi_1.default.boolean().default(false), metadata_open_graph: joi_1.default.boolean().default(false), metadata_http_response_status_code: joi_1.default.boolean() .default(false) .when("url", { is: joi_1.default.exist(), then: joi_1.default.boolean(), otherwise: joi_1.default.forbidden(), }), metadata_http_response_headers: joi_1.default.boolean().default(false).when("url", { is: joi_1.default.exist(), then: joi_1.default.boolean(), otherwise: joi_1.default.forbidden(), }), metadata_icon: joi_1.default.boolean().default(false), }).oxor("ip_country_code", "proxy"); const optionsScheme = commonOptionsScheme.append(screenshotScheme); const withEssentialsOptionsScheme = optionsScheme.or("html", "url", "markdown"); const bulkScheme = joi_1.default.object({ optimize: joi_1.default.boolean().default(false), execute: joi_1.default.boolean().default(false), options: joi_1.default.object(), requests: joi_1.default.array().items(withEssentialsOptionsScheme).min(1).max(20), }); const withHtmlOrUrlOrMarkdownRequired = commonOptionsScheme.or("html", "url", "markdown"); const animateScheme = withHtmlOrUrlOrMarkdownRequired .append({ format: joi_1.default.string() .trim() .lowercase() .valid("mp4", "avi", "mov", "webm", "gif") .default("mp4"), duration: joi_1.default.number().min(1).max(30).default(5), omit_background: joi_1.default.when("format", { is: joi_1.default.valid("mov"), then: joi_1.default.boolean().default(false), otherwise: joi_1.default.forbidden(), }), width: joi_1.default.number().integer().optional(), height: joi_1.default.number().integer().optional(), aspect_ratio: joi_1.default.string() .trim() .lowercase() .valid("4:3", "16:9") .default("4:3"), scenario: joi_1.default.string() .trim() .lowercase() .valid("", "default", "scroll") .default("default"), // scroll scenario parameters scroll_duration: joi_1.default.number().min(100).default(1500), scroll_delay: joi_1.default.number().min(0).default(500), scroll_by: joi_1.default.number().min(1).default(1000), scroll_start_immediately: joi_1.default.boolean().default(true), scroll_start_delay: joi_1.default.number().min(0).default(0), scroll_complete: joi_1.default.boolean().default(true), scroll_back_after_duration: joi_1.default.number().integer().optional(), scroll_back: joi_1.default.boolean().default(true), scroll_back_algorithm: joi_1.default.string() .trim() .lowercase() .valid("once", "repeat") .default("once"), scroll_stop_after_duration: joi_1.default.when("scroll_back", { is: false, then: joi_1.default.number().integer().optional(), otherwise: joi_1.default.forbidden(), }), scroll_till_selector: joi_1.default.string().optional(), scroll_till_selector_adjust_top: joi_1.default.number().integer().optional(), scroll_try_navigate: joi_1.default.boolean().default(false).optional(), scroll_navigate_after: joi_1.default.number().integer().optional(), scroll_navigate_to_url: joi_1.default.string().custom(validUri).optional(), scroll_navigate_link_hints: joi_1.default.array() .items(joi_1.default.string().trim()) .default(["pricing", "about", "customers"]) .optional(), scroll_to_end_after: joi_1.default.when("scenario", { is: joi_1.default.valid("scroll"), then: joi_1.default.number().integer().optional(), otherwise: joi_1.default.forbidden(), }), clip_x: joi_1.default.when("format", { is: joi_1.default.valid("gif"), then: joi_1.default.number().integer().optional(), otherwise: joi_1.default.forbidden(), }), clip_y: joi_1.default.when("format", { is: joi_1.default.valid("gif"), then: joi_1.default.number().integer().optional(), otherwise: joi_1.default.forbidden(), }), clip_height: joi_1.default.when("format", { is: joi_1.default.valid("gif"), then: joi_1.default.number().integer().optional(), otherwise: joi_1.default.forbidden(), }), clip_width: joi_1.default.when("format", { is: joi_1.default.valid("gif"), then: joi_1.default.number().integer().optional(), otherwise: joi_1.default.forbidden(), }), scroll_easing: joi_1.default.string() .trim() .lowercase() .valid("linear", "ease_in_quad", "ease_out_quad", "ease_in_out_quad", "ease_in_cubic", "ease_out_cubic", "ease_in_out_cubic", "ease_in_quart", "ease_out_quart", "ease_in_out_quart", "ease_in_quint", "ease_out_quint", "ease_in_out_quint") .default("ease_in_out_quint"), }) .oxor("scroll_stop_after_duration", "scroll_back_after_duration"); exports.default = { animate: { getScheme: animateScheme.append({ ...accessKeyScheme, ...signatureScheme, }), postScheme: animateScheme.append({ ...accessKeyScheme }), validationOptions, }, bulk: { postScheme: bulkScheme.append(accessKeyScheme), validationOptions, }, take: { getScheme: withEssentialsOptionsScheme.append({ ...accessKeyScheme, ...signatureScheme, }), postScheme: withEssentialsOptionsScheme.append({ ...accessKeyScheme }), validationOptions, }, };