import * as yup from "yup"; import * as isRegex from "is-regex"; export const appTitleValidation = yup .string() .label("App title") .max(26) .matches( /^[\w\-\s]+$/, "App title may contain letters, numbers, spaces and dashes only" ) .matches(/^[^\s]+(\s+[^\s]+)*$/, "App title may not begin or end with space") .required(); export const iconValidation = yup .string() .label("Icon") .url() .required("You must upload an icon for your app"); export const urlValidation = yup .string() .matches( /^(?:([a-z0-9+.-]+):\/\/)(?:\S+(?::\S*)?@)?(?:(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]-*)*[a-z\u00a1-\uffff0-9]+)*\.?)(?::\d{2,5})?(?:[/?#]\S*)?$/, { message: "Invalid URL. Don't forget to include the protocol (e.g.. https://).", excludeEmptyString: true, } ) .label("Website URL") .required(); export const urlValidationForm = yup.object().shape({ url: urlValidation, }); export const heightValidation = yup .number() .label("Height") .moreThan(100) .lessThan(2000) .required(); export const widthValidation = yup .number() .label("Width") .moreThan(200) .lessThan(3000) .required(); export const internalAppRegexValidation = yup .string() .required() .label("Internal URLs") .test( "escape-forward-slash", "a forward-slash ('/') must be escaped with a back-slash ('\\')", (value: string) => { if (value.includes("/")) { let forwardSlashCount = value .split("") .map((char) => char === "/") .filter((isTrue) => isTrue).length; let backSlashEscapeCount = ((value || "").match(/(?=\\\/)/g) || []) .length; return forwardSlashCount === backSlashEscapeCount; } return true; } ) .test( "is-regex", "${path} must be valid regular expression", (value: string) => isRegex(RegExp(value)) ); export const appProtocolValidation = yup .string() .required() .label("App Protocol") .test( "ends-with-protocol", "Protocols must end with `://`", (value: string) => value.endsWith("://") ) .matches( /^[a-zA-Z\-]+\:\/\/$/, "Protocols contain letters and dashes (-) only" ) .min(5); export const appConfigValidation = yup.object({ id: yup.string().required(), name: appTitleValidation, url: urlValidation, isFrameBlocked: yup.boolean().required(), iconUrl: iconValidation, disableDevTools: yup.boolean().required(), singleInstance: yup.boolean().required(), customUserAgent: yup.string().required(), internalURLs: yup.string().required(), secret: yup.string().required(), windowOptions: yup .object({ startInFullscreenMode: yup.boolean().required(), isResizable: yup.boolean().required(), width: yup.number().required(), height: yup.number().required(), hasMinWidth: yup.boolean().required(), hasMinHeight: yup.boolean().required(), hasMaxWidth: yup.boolean().required(), hasMaxHeight: yup.boolean().required(), minWidth: yup.number().required(), minHeight: yup.number().required(), maxWidth: yup.number().required(), maxHeight: yup.number().required(), isMaximizable: yup.boolean().required(), isMinimizable: yup.boolean().required(), isFullscreenable: yup.boolean().required(), transparentTitlebar: yup.boolean().required(), alwaysOnTop: yup.boolean().required(), transparentInsetTitlebar: yup.boolean().required(), }) .required(), meta: yup .object({ schemaVersion: yup.number().required(), hasAppChanged: yup.boolean().required(), appIterations: yup.number().required(), publishedVersions: yup.object({ electron: yup.string().notRequired(), desktopify: yup.string().notRequired(), version: yup.string().notRequired(), }), }) .required(), });