import { schema, rules } from '@adonisjs/validator'; import type { HttpContext } from '@adonisjs/core/http'; import dayjs from 'dayjs'; import { TitleTypes, DescriptionTypes, RelationTypes, ReferenceIdentifierTypes, ContributorTypes } from '#contracts/enums'; import { CustomMessages } from "@adonisjs/validator/types"; export default class CreateDatasetValidator { constructor(protected ctx: HttpContext) {} /* * Define schema to validate the "shape", "type", "formatting" and "integrity" of data. * * For example: * 1. The username must be of data type string. But then also, it should * not contain special characters or numbers. * ``` * schema.string({}, [ rules.alpha() ]) * ``` * * 2. The email must be of data type string, formatted as a valid * email. But also, not used by any other user. * ``` * schema.string({}, [ * rules.email(), * rules.unique({ table: 'users', column: 'email' }), * ]) * ``` */ public schema = schema.create({ // first step language: schema.string({ trim: true }, [ rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores ]), licenses: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one license for the new dataset rights: schema.string([rules.equalTo('true')]), // second step type: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]), creating_corporation: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]), titles: schema.array([rules.minLength(1)]).members( schema.object().members({ value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]), type: schema.enum(Object.values(TitleTypes)), language: schema.string({ trim: true }, [ rules.minLength(2), rules.maxLength(255), rules.translatedLanguage('/language', 'type'), ]), }), ), descriptions: schema.array([rules.minLength(1)]).members( schema.object().members({ value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]), type: schema.enum(Object.values(DescriptionTypes)), language: schema.string({ trim: true }, [ rules.minLength(2), rules.maxLength(255), rules.translatedLanguage('/language', 'type'), ]), }), ), authors: schema.array([rules.minLength(1)]).members(schema.object().members({ email: schema.string({ trim: true }) })), contributors: schema.array.optional().members( schema.object().members({ email: schema.string({ trim: true }), pivot_contributor_type: schema.enum(Object.keys(ContributorTypes)), }), ), // third step project_id: schema.number.optional(), embargo_date: schema.date.optional({ format: 'yyyy-MM-dd' }, [rules.after(10, 'days')]), coverage: schema.object().members({ x_min: schema.number(), x_max: schema.number(), y_min: schema.number(), y_max: schema.number(), elevation_absolut: schema.number.optional(), elevation_min: schema.number.optional([rules.requiredIfExists('elevation_max')]), elevation_max: schema.number.optional([rules.requiredIfExists('elevation_min')]), depth_absolut: schema.number.optional(), depth_min: schema.number.optional([rules.requiredIfExists('depth_max')]), depth_max: schema.number.optional([rules.requiredIfExists('depth_min')]), }), references: schema.array.optional([rules.uniqueArray('value')]).members( schema.object().members({ value: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]), type: schema.enum(Object.values(ReferenceIdentifierTypes)), relation: schema.enum(Object.values(RelationTypes)), label: schema.string({ trim: true }, [rules.minLength(2), rules.maxLength(255)]), }), ), subjects: schema.array([rules.minLength(3), rules.uniqueArray('value')]).members( schema.object().members({ value: schema.string({ trim: true }, [ rules.minLength(3), rules.maxLength(255), // rules.unique({ table: 'dataset_subjects', column: 'value' }), ]), // type: schema.enum(Object.values(TitleTypes)), language: schema.string({ trim: true }, [rules.minLength(2), rules.maxLength(255)]), }), ), // file: schema.file({ // size: '100mb', // extnames: ['jpg', 'gif', 'png'], // }), files: schema.array([rules.minLength(1)]).members( schema.file({ size: '512mb', extnames: ['jpg', 'gif', 'png', 'tif', 'pdf', 'zip', 'fgb', 'nc', 'qml', 'ovr', 'gpkg', 'gml', 'gpx', 'kml', 'kmz', 'json'], }), ), // upload: schema.object().members({ // label: schema.string({ trim: true }, [rules.maxLength(255)]), // // label: schema.string({ trim: true }, [ // // // rules.minLength(3), // // // rules.maxLength(255), // // ]), // }), }); /** * Custom messages for validation failures. You can make use of dot notation `(.)` * for targeting nested fields and array expressions `(*)` for targeting all * children of an array. For example: * * { * 'profile.username.required': 'Username is required', * 'scores.*.number': 'Define scores as valid numbers' * } * */ public messages: CustomMessages = { 'minLength': '{{ field }} must be at least {{ options.minLength }} characters long', 'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long', 'required': '{{ field }} is required', 'unique': '{{ field }} must be unique, and this value is already taken', // 'confirmed': '{{ field }} is not correct', 'licenses.minLength': 'at least {{ options.minLength }} licenses must be defined', 'licenses.*.number': 'Define licences as valid numbers', 'rights.equalTo': 'you must agree to continue', 'titles.0.value.minLength': 'Main Title must be at least {{ options.minLength }} characters long', 'titles.0.value.required': 'Main Title is required', 'titles.*.value.required': 'Additional title is required, if defined', 'titles.*.type.required': 'Additional title type is required', 'titles.*.language.required': 'Additional title language is required', 'titles.*.language.translatedLanguage': 'The language of the translated title must be different from the language of the dataset', 'descriptions.0.value.minLength': 'Main Abstract must be at least {{ options.minLength }} characters long', 'descriptions.0.value.required': 'Main Abstract is required', 'descriptions.*.value.required': 'Additional description is required, if defined', 'descriptions.*.type.required': 'Additional description type is required', 'descriptions.*.language.required': 'Additional description language is required', 'descriptions.*.language.translatedLanguage': 'The language of the translated description must be different from the language of the dataset', 'authors.minLength': 'at least {{ options.minLength }} author must be defined', 'contributors.*.pivot_contributor_type.required': 'contributor type is required, if defined', 'after': `{{ field }} must be older than ${dayjs().add(10, 'day')}`, 'subjects.minLength': 'at least {{ options.minLength }} keywords must be defined', 'subjects.uniqueArray': 'The {{ options.array }} array must have unique values based on the {{ options.field }} attribute.', 'subjects.*.value.required': 'keyword value is required', 'subjects.*.value.minLength': 'keyword value must be at least {{ options.minLength }} characters long', 'subjects.*.type.required': 'keyword type is required', 'subjects.*.language.required': 'language of keyword is required', 'references.*.value.required': 'Additional reference value is required, if defined', 'references.*.type.required': 'Additional reference identifier type is required', 'references.*.relation.required': 'Additional reference relation type is required', 'references.*.label.required': 'Additional reference label is required', 'files.minLength': 'At least {{ options.minLength }} file upload is required.', 'files.*.size': 'file size is to big', 'files.extnames': 'file extension is not supported', }; }