diff --git a/adonisrc.ts b/adonisrc.ts index 6d58ae6..4fda7b1 100644 --- a/adonisrc.ts +++ b/adonisrc.ts @@ -25,15 +25,9 @@ export default defineConfig({ preloads: [ () => import('./start/routes.js'), () => import('./start/kernel.js'), - // { - // file: () => import('./start/inertia.js'), - // environment: ["web"], - // }, - // () => import('#start/events'), - // { - // file: () => import('./start/validator.js'), - // environment: ["web"], - // } + () => import('#start/validator'), + () => import('#start/rules/unique'), + () => import('#start/rules/translated_language') ], /* |-------------------------------------------------------------------------- @@ -68,8 +62,9 @@ export default defineConfig({ () => import('#providers/stardust_provider'), () => import('#providers/query_builder_provider'), () => import('#providers/token_worker_provider'), - () => import('#providers/validator_provider'), - () => import('#providers/drive/provider/drive_provider') + // () => import('#providers/validator_provider'), + () => import('#providers/drive/provider/drive_provider'), + () => import('@adonisjs/core/providers/vinejs_provider') ], metaFiles: [ { @@ -90,21 +85,21 @@ export default defineConfig({ | and add additional suites. | */ -tests: { - suites: [ - { - files: ['tests/unit/**/*.spec(.ts|.js)'], - name: 'unit', - timeout: 2000, - }, - { - files: ['tests/functional/**/*.spec(.ts|.js)'], - name: 'functional', - timeout: 30000, - }, - ], - forceExit: false, -}, + tests: { + suites: [ + { + files: ['tests/unit/**/*.spec(.ts|.js)'], + name: 'unit', + timeout: 2000, + }, + { + files: ['tests/functional/**/*.spec(.ts|.js)'], + name: 'functional', + timeout: 30000, + }, + ], + forceExit: false, + }, diff --git a/app/Controllers/Http/Admin/AdminuserController.ts b/app/Controllers/Http/Admin/AdminuserController.ts index e755eb7..aca3d76 100644 --- a/app/Controllers/Http/Admin/AdminuserController.ts +++ b/app/Controllers/Http/Admin/AdminuserController.ts @@ -1,15 +1,13 @@ import type { HttpContext } from '@adonisjs/core/http'; import User from '#models/user'; import Role from '#models/role'; -import { ModelQueryBuilderContract } from "@adonisjs/lucid/types/model"; -import CreateUserValidator from '#validators/create_user_validator'; -import UpdateUserValidator from '#validators/update_user_validator'; +import { ModelQueryBuilderContract } from '@adonisjs/lucid/types/model'; +import { createUserValidator, updateUserValidator } from '#validators/user'; // import { schema, rules } from '@ioc:Adonis/Core/Validator'; // import Hash from '@ioc:Adonis/Core/Hash'; // import { schema, rules } from '@ioc:Adonis/Core/Validator'; export default class AdminuserController { - public async index({ auth, request, inertia }: HttpContext) { const page = request.input('page', 1); // const limit = 10 @@ -48,7 +46,7 @@ export default class AdminuserController { // .preload('focusInterests') // .preload('role') .paginate(page, 5); - + // var test = request.all(); return inertia.render('Admin/User/Index', { @@ -79,7 +77,8 @@ export default class AdminuserController { // node ace make:validator CreateUser try { // Step 2 - Validate request body against the schema - await request.validate(CreateUserValidator); + // await request.validate(CreateUserValidator); + await request.validateUsing(createUserValidator); // console.log({ payload }); } catch (error) { // Step 3 - Handle errors @@ -94,7 +93,7 @@ export default class AdminuserController { } session.flash('message', 'User has been created successfully'); - return response.redirect().toRoute('user.index'); + return response.redirect().toRoute('settings.user.index'); } public async show({ request, inertia }: HttpContext) { @@ -133,7 +132,11 @@ export default class AdminuserController { const user = await User.query().where('id', id).firstOrFail(); // validate update form - await request.validate(UpdateUserValidator); + await request.validateUsing(updateUserValidator, { + meta: { + userId: user.id, + }, + }); // password is optional let input; @@ -160,7 +163,7 @@ export default class AdminuserController { await user.delete(); session.flash('message', `User ${user.login} has been deleted.`); - return response.redirect().toRoute('user.index'); + return response.redirect().toRoute('settings.user.index'); } // private async syncRoles(userId: number, roleIds: Array) { diff --git a/app/Controllers/Http/Admin/RoleController.ts b/app/Controllers/Http/Admin/RoleController.ts index 0b9cfaf..1c4ab7a 100644 --- a/app/Controllers/Http/Admin/RoleController.ts +++ b/app/Controllers/Http/Admin/RoleController.ts @@ -1,9 +1,8 @@ import type { HttpContext } from '@adonisjs/core/http'; import Role from '#models/role'; import Permission from '#models/permission'; -import CreateRoleValidator from '#validators/create_role_validator'; -import UpdateRoleValidator from '#validators/update_role_validator'; -import type { ModelQueryBuilderContract } from "@adonisjs/lucid/types/model"; +import { createRoleValidator, updateRoleValidator } from '#validators/role'; +import type { ModelQueryBuilderContract } from '@adonisjs/lucid/types/model'; // import { schema, rules } from '@ioc:Adonis/Core/Validator'; @@ -59,7 +58,8 @@ export default class RoleController { // node ace make:validator CreateUser try { // Step 2 - Validate request body against the schema - await request.validate(CreateRoleValidator); + // await request.validate(CreateRoleValidator); + await request.validateUsing(createRoleValidator); // await request.validate({ schema: roleSchema }); // console.log({ payload }); } catch (error) { @@ -76,7 +76,7 @@ export default class RoleController { } session.flash('message', `Role ${role.name} has been created successfully`); - return response.redirect().toRoute('role.index'); + return response.redirect().toRoute('settings.role.index'); } public async show({ request, inertia }: HttpContext) { @@ -115,7 +115,12 @@ export default class RoleController { const role = await Role.query().where('id', id).firstOrFail(); // validate update form - await request.validate(UpdateRoleValidator); + // await request.validate(UpdateRoleValidator); + await request.validateUsing(updateRoleValidator, { + meta: { + roleId: role.id, + }, + }); // password is optional @@ -138,6 +143,6 @@ export default class RoleController { await role.delete(); session.flash('message', `Role ${role.name} has been deleted.`); - return response.redirect().toRoute('role.index'); + return response.redirect().toRoute('settings.role.index'); } } diff --git a/app/Controllers/Http/Auth/AuthController.ts b/app/Controllers/Http/Auth/AuthController.ts index 5bf8ffc..16153b5 100644 --- a/app/Controllers/Http/Auth/AuthController.ts +++ b/app/Controllers/Http/Auth/AuthController.ts @@ -2,7 +2,7 @@ import type { HttpContext } from '@adonisjs/core/http'; import User from '#models/user'; // import Hash from '@ioc:Adonis/Core/Hash'; // import InvalidCredentialException from 'App/Exceptions/InvalidCredentialException'; -import AuthValidator from '#validators/auth_validator'; +import { authValidator } from '#validators/auth'; import TwoFactorAuthProvider from '#app/services/TwoFactorAuthProvider'; // import { Authenticator } from '@adonisjs/auth'; @@ -18,7 +18,8 @@ export default class AuthController { // console.log({ // registerBody: request.body(), // }); - await request.validate(AuthValidator); + // await request.validate(AuthValidator); + await request.validateUsing(authValidator); // const plainPassword = await request.input('password'); // const email = await request.input('email'); diff --git a/app/Controllers/Http/Auth/UserController.ts b/app/Controllers/Http/Auth/UserController.ts index cef0ebe..54794f4 100644 --- a/app/Controllers/Http/Auth/UserController.ts +++ b/app/Controllers/Http/Auth/UserController.ts @@ -3,7 +3,8 @@ import User from '#models/user'; // import { RenderResponse } from '@ioc:EidelLev/Inertia'; import TwoFactorAuthProvider from '#app/services/TwoFactorAuthProvider'; import hash from '@adonisjs/core/services/hash'; -import { schema, rules } from '@adonisjs/validator'; +// import { schema, rules } from '@adonisjs/validator'; +import vine, { SimpleMessagesProvider } from '@vinejs/vine'; // Here we are generating secret and recovery codes for the user that’s enabling 2FA and storing them to our database. export default class UserController { @@ -26,13 +27,23 @@ export default class UserController { } public async accountInfoStore({ auth, request, response, session }: HttpContext) { - const passwordSchema = schema.create({ - old_password: schema.string({ trim: true }, [rules.required()]), - new_password: schema.string({ trim: true }, [rules.minLength(8), rules.maxLength(255), rules.confirmed('confirm_password')]), - confirm_password: schema.string({ trim: true }, [rules.required()]), + // const passwordSchema = schema.create({ + // old_password: schema.string({ trim: true }, [rules.required()]), + // new_password: schema.string({ trim: true }, [rules.minLength(8), rules.maxLength(255), rules.confirmed('confirm_password')]), + // confirm_password: schema.string({ trim: true }, [rules.required()]), + // }); + const passwordSchema = vine.object({ + // first step + old_password: vine + .string() + .trim() + .regex(/^[a-zA-Z0-9]+$/), + new_password: vine.string().confirmed({ confirmationField: 'confirm_password' }).trim().minLength(8).maxLength(255), }); try { - await request.validate({ schema: passwordSchema }); + // await request.validate({ schema: passwordSchema }); + const validator = vine.compile(passwordSchema); + await request.validateUsing(validator); } catch (error) { // return response.badRequest(error.messages); throw error; @@ -58,7 +69,7 @@ export default class UserController { // return response.status(200).send({ message: 'Password updated successfully.' }); session.flash({ message: 'Password updated successfully.' }); - return response.redirect().toRoute('settings.user.index'); + return response.redirect().toRoute('settings.user'); } catch (error) { // return response.status(500).send({ message: 'Internal server error.' }); return response.flash('warning', `Invalid server state. Internal server error.`).redirect().back(); diff --git a/app/Controllers/Http/Editor/DatasetController.ts b/app/Controllers/Http/Editor/DatasetController.ts index 1ba53fa..22bca8d 100644 --- a/app/Controllers/Http/Editor/DatasetController.ts +++ b/app/Controllers/Http/Editor/DatasetController.ts @@ -8,7 +8,6 @@ import { XMLBuilder } from 'xmlbuilder2/lib/interfaces.js'; import { create } from 'xmlbuilder2'; import { readFileSync } from 'fs'; import SaxonJS from 'saxon-js'; -import { schema } from '@adonisjs/validator'; import { DateTime } from 'luxon'; import Index from '#app/Library/Utils/Index'; import { getDomain } from '#app/utils/utility-functions'; @@ -17,14 +16,14 @@ import DoiClientException from '#app/exceptions/DoiClientException'; import logger from '@adonisjs/core/services/logger'; import { HttpException } from 'node-exceptions'; import { ModelQueryBuilderContract } from "@adonisjs/lucid/types/model"; -import { CustomMessages } from "@adonisjs/validator/types"; +import vine, { SimpleMessagesProvider } from '@vinejs/vine'; // Create a new instance of the client const client = new Client({ node: 'http://localhost:9200' }); // replace with your OpenSearch endpoint export default class DatasetsController { private proc; - public messages: CustomMessages = { + public messages = { // 'required': '{{ field }} is required', // 'licenses.minLength': 'at least {{ options.minLength }} permission must be defined', 'reviewer_id.required': 'reviewer_id must be defined', @@ -184,11 +183,13 @@ export default class DatasetsController { } public async approveUpdate({ request, response }: HttpContext) { - const approveDatasetSchema = schema.create({ - reviewer_id: schema.number(), + const approveDatasetSchema = vine.object({ + reviewer_id: vine.number(), }); try { - await request.validate({ schema: approveDatasetSchema, messages: this.messages }); + // await request.validate({ schema: approveDatasetSchema, messages: this.messages }); + const validator = vine.compile(approveDatasetSchema); + await request.validateUsing(validator, { messagesProvider: new SimpleMessagesProvider(this.messages) }); } catch (error) { // return response.badRequest(error.messages); throw error; @@ -252,13 +253,14 @@ export default class DatasetsController { } public async publishUpdate({ request, response }: HttpContext) { - const publishDatasetSchema = schema.create({ - publisher_name: schema.string({ trim: true }), + const publishDatasetSchema = vine.object({ + publisher_name: vine.string().alphaNumeric().trim(), }); try { - await request.validate({ schema: publishDatasetSchema, messages: this.messages }); + // await request.validate({ schema: publishDatasetSchema, messages: this.messages }); + const validator = vine.compile(publishDatasetSchema); + await request.validateUsing(validator, { messagesProvider: new SimpleMessagesProvider(this.messages) }); } catch (error) { - // return response.badRequest(error.messages); throw error; } const id = request.param('id'); diff --git a/app/Controllers/Http/Reviewer/DatasetController.ts b/app/Controllers/Http/Reviewer/DatasetController.ts index 9ee52c4..dcadce0 100644 --- a/app/Controllers/Http/Reviewer/DatasetController.ts +++ b/app/Controllers/Http/Reviewer/DatasetController.ts @@ -4,8 +4,8 @@ import Dataset from '#models/dataset'; import Field from '#app/Library/Field'; import BaseModel from '#models/base_model'; import { DateTime } from 'luxon'; -import { schema, rules } from '@adonisjs/validator'; import { ModelQueryBuilderContract } from "@adonisjs/lucid/types/model"; +import vine from '@vinejs/vine'; interface Dictionary { [index: string]: string; @@ -227,13 +227,19 @@ export default class DatasetsController { }) .firstOrFail(); - const newSchema = schema.create({ - server_state: schema.string({ trim: true }), - reject_reviewer_note: schema.string({ trim: true }, [rules.minLength(10), rules.maxLength(500)]), + // const newSchema = schema.create({ + // server_state: schema.string({ trim: true }), + // reject_reviewer_note: schema.string({ trim: true }, [rules.minLength(10), rules.maxLength(500)]), + // }); + const newSchema = vine.object({ + server_state: vine.string().trim(), + reject_reviewer_note: vine.string().trim().minLength(10).maxLength(500), }); try { - await request.validate({ schema: newSchema }); + // await request.validate({ schema: newSchema }); + const validator = vine.compile(newSchema); + await request.validateUsing(validator); } catch (error) { // return response.badRequest(error.messages); throw error; diff --git a/app/Controllers/Http/Submitter/DatasetController.ts b/app/Controllers/Http/Submitter/DatasetController.ts index b44d9f4..f03c661 100644 --- a/app/Controllers/Http/Submitter/DatasetController.ts +++ b/app/Controllers/Http/Submitter/DatasetController.ts @@ -8,15 +8,14 @@ import Description from '#models/description'; import Language from '#models/language'; import Coverage from '#models/coverage'; import Collection from '#models/collection'; -import { schema, rules } from '@adonisjs/validator'; -import { CustomMessages } from '@adonisjs/validator/types'; import dayjs from 'dayjs'; import Person from '#models/person'; import db from '@adonisjs/lucid/services/db'; import { TransactionClientContract } from '@adonisjs/lucid/types/database'; import Subject from '#models/subject'; -import CreateDatasetValidator from '#validators/create_dataset_validator'; -import UpdateDatasetValidator from '#validators/update_dataset_validator'; +// import CreateDatasetValidator from '#validators/create_dataset_validator'; +import { createDatasetValidator, updateDatasetValidator } from '#validators/dataset'; +// import UpdateDatasetValidator from '#validators/update_dataset_validator'; import { TitleTypes, DescriptionTypes, @@ -32,7 +31,7 @@ import DatasetReference from '#models/dataset_reference'; import { cuid } from '@adonisjs/core/helpers'; import File from '#models/file'; import ClamScan from 'clamscan'; -import { ValidationException } from '@adonisjs/validator'; +// import { ValidationException } from '@adonisjs/validator'; // import Drive from '@ioc:Adonis/Core/Drive'; import drive from '#services/drive'; import { Exception } from '@adonisjs/core/exceptions'; @@ -41,6 +40,7 @@ import * as crypto from 'crypto'; interface Dictionary { [index: string]: string; } +import vine, { SimpleMessagesProvider, errors } from '@vinejs/vine'; export default class DatasetController { public async index({ auth, request, inertia }: HttpContext) { @@ -125,8 +125,6 @@ export default class DatasetController { // mixedtype: 'Mixed Type', // vocabulary: 'Vocabulary', // }; - - // const languages = await Database.from('languages').select('*').where('active', true); return inertia.render('Submitter/Dataset/Create', { licenses: licenses, doctypes: DatasetTypes, @@ -146,75 +144,98 @@ export default class DatasetController { } public async firstStep({ request, response }: HttpContext) { - const newDatasetSchema = schema.create({ - 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')]), + // const newDatasetSchema = schema.create({ + // 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')]), + // }); + const newDatasetSchema = vine.object({ + // first step + language: vine + .string() + .trim() + .regex(/^[a-zA-Z0-9]+$/), + licenses: vine.array(vine.number()).minLength(1), // define at least one license for the new dataset + rights: vine.string().in(['true']), }); - // await request.validate({ schema: newDatasetSchema, messages: this.messages }); try { // Step 2 - Validate request body against the schema - - await request.validate({ schema: newDatasetSchema, messages: this.messages }); - // console.log({ payload }); + // await request.validate({ schema: newDatasetSchema, messages: this.messages }); + const validator = vine.compile(newDatasetSchema); + await request.validateUsing(validator, { messagesProvider: new SimpleMessagesProvider(this.messages) }); } catch (error) { // Step 3 - Handle errors - // return response.badRequest(error.messages); throw error; } return response.redirect().back(); } public async secondStep({ request, response }: HttpContext) { - const newDatasetSchema = schema.create({ + const newDatasetSchema = vine.object({ // 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')]), + language: vine + .string() + .trim() + .regex(/^[a-zA-Z0-9]+$/), + licenses: vine.array(vine.number()).minLength(1), // define at least one license for the new dataset + rights: vine.string().in(['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)), - }), - ), - // project_id: schema.number(), + type: vine.string().trim().minLength(3).maxLength(255), + creating_corporation: vine.string().trim().minLength(3).maxLength(255), + titles: vine + .array( + vine.object({ + value: vine.string().trim().minLength(3).maxLength(255), + type: vine.enum(Object.values(TitleTypes)), + language: vine + .string() + .trim() + .minLength(2) + .maxLength(255) + .translatedLanguage({ mainLanguageField: 'language', typeField: 'type' }), + }), + ) + .minLength(1), + descriptions: vine + .array( + vine.object({ + value: vine.string().trim().minLength(3).maxLength(255), + type: vine.enum(Object.values(DescriptionTypes)), + language: vine + .string() + .trim() + .minLength(2) + .maxLength(255) + .translatedLanguage({ mainLanguageField: 'language', typeField: 'type' }), + }), + ) + .minLength(1), + authors: vine + .array( + vine.object({ + email: vine.string().trim().maxLength(255).email().normalizeEmail(), + }), + ) + .minLength(1), + contributors: vine + .array( + vine.object({ + email: vine.string().trim().maxLength(255).email().normalizeEmail(), + pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)), + }), + ) + .optional(), + project_id: vine.number().optional(), }); try { // Step 2 - Validate request body against the schema - await request.validate({ schema: newDatasetSchema, messages: this.messages }); - // console.log({ payload }); + // await request.validate({ schema: newDatasetSchema, messages: this.messages }); + const validator = vine.compile(newDatasetSchema); + await request.validateUsing(validator, { messagesProvider: new SimpleMessagesProvider(this.messages) }); } catch (error) { // Step 3 - Handle errors // return response.badRequest(error.messages); @@ -224,84 +245,112 @@ export default class DatasetController { } public async thirdStep({ request, response }: HttpContext) { - const newDatasetSchema = schema.create({ + const newDatasetSchema = vine.object({ // 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')]), + language: vine + .string() + .trim() + .regex(/^[a-zA-Z0-9]+$/), + licenses: vine.array(vine.number()).minLength(1), // define at least one license for the new dataset + rights: vine.string().in(['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)), - }), - ), + type: vine.string().trim().minLength(3).maxLength(255), + creating_corporation: vine.string().trim().minLength(3).maxLength(255), + titles: vine + .array( + vine.object({ + value: vine.string().trim().minLength(3).maxLength(255), + type: vine.enum(Object.values(TitleTypes)), + language: vine + .string() + .trim() + .minLength(2) + .maxLength(255) + .translatedLanguage({ mainLanguageField: 'language', typeField: 'type' }), + }), + ) + .minLength(1), + descriptions: vine + .array( + vine.object({ + value: vine.string().trim().minLength(3).maxLength(255), + type: vine.enum(Object.values(DescriptionTypes)), + language: vine + .string() + .trim() + .minLength(2) + .maxLength(255) + .translatedLanguage({ mainLanguageField: 'language', typeField: 'type' }), + }), + ) + .minLength(1), + authors: vine + .array( + vine.object({ + email: vine.string().trim().maxLength(255).email().normalizeEmail(), + }), + ) + .minLength(1), + contributors: vine + .array( + vine.object({ + email: vine.string().trim().maxLength(255).email().normalizeEmail(), + pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)), + }), + ) + .optional(), // 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')]), + project_id: vine.number().optional(), + // embargo_date: schema.date.optional({ format: 'yyyy-MM-dd' }, [rules.after(10, 'days')]), + embargo_date: vine + .date({ + formats: ['YYYY-MM-DD'], + }) + .afterOrEqual((_field) => { + return dayjs().add(10, 'day').format('YYYY-MM-DD'); + }) + .optional(), + coverage: vine.object({ + x_min: vine.number(), + x_max: vine.number(), + y_min: vine.number(), + y_max: vine.number(), + elevation_absolut: vine.number().optional(), + elevation_min: vine.number().optional().requiredIfExists('elevation_max'), + elevation_max: vine.number().optional().requiredIfExists('elevation_min'), + // type: vine.enum(Object.values(DescriptionTypes)), + depth_absolut: vine.number().optional(), + depth_min: vine.number().optional().requiredIfExists('depth_max'), + depth_max: vine.number().optional().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)]), - }), - ), + references: vine + .array( + vine.object({ + value: vine.string().trim().minLength(3).maxLength(255), + type: vine.enum(Object.values(ReferenceIdentifierTypes)), + relation: vine.enum(Object.values(RelationTypes)), + label: vine.string().trim().minLength(2).maxLength(255), + }), + ) + .optional(), + subjects: vine + .array( + vine.object({ + value: vine.string().trim().minLength(3).maxLength(255), + // pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)), + language: vine.string().trim().minLength(2).maxLength(255), + }), + ) + .minLength(3) + .distinct('value') + .optional(), }); try { - // Step 2 - Validate request body against the schema - await request.validate({ schema: newDatasetSchema, messages: this.messages }); + // Step 3 - Validate request body against the schema + // await request.validate({ schema: newDatasetSchema, messages: this.messages }); + const validator = vine.compile(newDatasetSchema); + await request.validateUsing(validator, { messagesProvider: new SimpleMessagesProvider(this.messages) }); // console.log({ payload }); } catch (error) { // Step 3 - Handle errors @@ -316,7 +365,8 @@ export default class DatasetController { try { // Step 2 - Validate request body against the schema // await request.validate({ schema: newDatasetSchema, messages: this.messages }); - await request.validate(CreateDatasetValidator); + // await request.validate(CreateDatasetValidator); + await request.validateUsing(createDatasetValidator); // console.log({ payload }); } catch (error) { // Step 3 - Handle errors @@ -505,13 +555,15 @@ export default class DatasetController { const { file, isInfected, viruses } = await clamscan.isInfected(filePath); if (isInfected) { console.log(`${file} is infected with ${viruses}!`); - reject(new ValidationException(true, { 'upload error': `File ${file} is infected!` })); + // reject(new ValidationException(true, { 'upload error': `File ${file} is infected!` })); + reject(new errors.E_VALIDATION_ERROR({ 'upload error': `File ${file} is infected!` })); } else { resolve(); } } catch (error) { // If there's an error scanning the file, throw a validation exception - reject(new ValidationException(true, { 'upload error': `${error.message}` })); + // reject(new ValidationException(true, { 'upload error': `${error.message}` })); + reject(new errors.E_VALIDATION_ERROR({ 'upload error': `${error.message}!` })); } }); } @@ -553,24 +605,24 @@ export default class DatasetController { return pivotAttributes; } - public messages: CustomMessages = { - 'minLength': '{{ field }} must be at least {{ options.minLength }} characters long', - 'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long', + public messages = { + 'minLength': '{{ field }} must be at least {{ min }} characters long', + 'maxLength': '{{ field }} must be less then {{ max }} 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 }} permission must be defined', + 'licenses.minLength': 'at least {{ min }} permission must be defined', 'licenses.*.number': 'Define roles as valid numbers', - 'rights.equalTo': 'you must agree to continue', + 'rights.in': 'you must agree to continue', - 'titles.0.value.minLength': 'Main Title must be at least {{ options.minLength }} characters long', + 'titles.0.value.minLength': 'Main Title must be at least {{ min }} 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.minLength': 'Main Abstract must be at least {{ min }} 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', @@ -578,26 +630,26 @@ export default class DatasetController { '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', + 'authors.array.minLength': 'at least {{ min }} 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.array.minLength': 'at least {{ min }} keywords must be defined', 'subjects.*.value.required': 'keyword value is required', - 'subjects.*.value.minLength': 'keyword value must be at least {{ options.minLength }} characters long', + 'subjects.*.value.minLength': 'keyword value must be at least {{ min }} characters long', 'subjects.*.type.required': 'keyword type is required', 'subjects.*.language.required': 'language of keyword is required', + 'subjects.distinct': 'The {{ field }} array must have unique values based on the {{ fields }} attribute.', '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.array.minLength': 'At least {{ min }} file upload is required.', 'files.*.size': 'file size is to big', - 'files.extnames': 'file extension is not supported', + 'files.*.extnames': 'file extension is not supported', }; // public async release({ params, view }) { @@ -654,16 +706,18 @@ export default class DatasetController { const preferredReviewerEmail = request.input('preferred_reviewer_email'); if (preferation === 'yes_preferation') { - const newSchema = schema.create({ - preferred_reviewer: schema.string({ trim: true }, [rules.minLength(3), rules.maxLength(255)]), - preferred_reviewer_email: schema.string([rules.email()]), + const newSchema = vine.object({ + preferred_reviewer: vine.string().alphaNumeric().trim().minLength(3).maxLength(255), + preferred_reviewer_email: vine.string().maxLength(255).email().normalizeEmail(), }); try { - await request.validate({ - schema: newSchema, - // reporter: validator.reporters.vanilla, - }); + // await request.validate({ + // schema: newSchema, + // // reporter: validator.reporters.vanilla, + // }); + const validator = vine.compile(newSchema); + await request.validateUsing(validator); } catch (error) { // return response.badRequest(error.messages); throw error; @@ -799,8 +853,8 @@ export default class DatasetController { public async update({ request, response, session }: HttpContext) { try { - // await request.validate({ schema: newDatasetSchema, messages: this.messages }); - await request.validate(UpdateDatasetValidator); + // await request.validate(UpdateDatasetValidator); + await request.validateUsing(updateDatasetValidator); } catch (error) { // - Handle errors // return response.badRequest(error.messages); @@ -1068,7 +1122,7 @@ export default class DatasetController { } } } catch (error) { - if (error instanceof ValidationException) { + if (error instanceof errors.E_VALIDATION_ERROR) { // Validation exception handling throw error; } else if (error instanceof Exception) { diff --git a/app/middleware/SilentAuth.ts b/app/middleware/silent_auth.ts similarity index 100% rename from app/middleware/SilentAuth.ts rename to app/middleware/silent_auth.ts diff --git a/app/models/mime_type.ts b/app/models/mime_type.ts new file mode 100644 index 0000000..66613c0 --- /dev/null +++ b/app/models/mime_type.ts @@ -0,0 +1,34 @@ +import { column, SnakeCaseNamingStrategy } from '@adonisjs/lucid/orm'; +import BaseModel from './base_model.js'; + +export default class MimeType extends BaseModel { + public static namingStrategy = new SnakeCaseNamingStrategy(); + public static primaryKey = 'id'; + public static table = 'mime_types'; + public static fillable: string[] = ['name', 'file_extension', 'enabled']; + + @column({ + isPrimary: true, + }) + public id: number; + + @column({}) + public name: string; + + @column({}) + public file_extension: string; + + @column({}) + public enabled: boolean; + + @column({}) + public visible_frontdoor: boolean; + + + public visible_oai: boolean; + + // @hasMany(() => Collection, { + // foreignKey: 'role_id', + // }) + // public collections: HasMany; +} diff --git a/app/validators/auth.ts b/app/validators/auth.ts new file mode 100644 index 0000000..9eb9313 --- /dev/null +++ b/app/validators/auth.ts @@ -0,0 +1,20 @@ +import vine from '@vinejs/vine'; + +// public schema = schema.create({ +// email: schema.string({ trim: true }, [ +// rules.email(), +// // rules.unique({ table: 'accounts', column: 'email' }) +// ]), +// password: schema.string({}, [rules.minLength(6)]), +// }); + +/** + * Validates the role's creation action + * node ace make:validator role + */ +export const authValidator = vine.compile( + vine.object({ + email: vine.string().maxLength(255).email().normalizeEmail(), + password: vine.string().trim().minLength(6), + }), +); diff --git a/app/validators/auth_validator.ts b/app/validators/auth_validator.ts deleted file mode 100644 index 3c86ded..0000000 --- a/app/validators/auth_validator.ts +++ /dev/null @@ -1,47 +0,0 @@ -import { schema, rules } from '@adonisjs/validator'; -import type { HttpContext } from '@adonisjs/core/http'; -import { CustomMessages } from "@adonisjs/validator/types"; - -export default class AuthValidator { - 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({ - email: schema.string({ trim: true }, [ - rules.email(), - // rules.unique({ table: 'accounts', column: 'email' }) - ]), - password: schema.string({}, [rules.minLength(6)]), - }); - - /** - * 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 = {}; -} diff --git a/app/validators/create_dataset_validator.ts b/app/validators/create_dataset_validator.ts deleted file mode 100644 index f732946..0000000 --- a/app/validators/create_dataset_validator.ts +++ /dev/null @@ -1,179 +0,0 @@ -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', - }; -} diff --git a/app/validators/create_role_validator.ts b/app/validators/create_role_validator.ts deleted file mode 100644 index f9ab8c4..0000000 --- a/app/validators/create_role_validator.ts +++ /dev/null @@ -1,70 +0,0 @@ -import { schema, rules } from '@adonisjs/validator'; -import type { HttpContext } from '@adonisjs/core/http'; -import { CustomMessages } from "@adonisjs/validator/types"; - -export default class CreateRoleValidator { - 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({ - name: schema.string({ trim: true }, [ - rules.minLength(3), - rules.maxLength(255), - rules.unique({ table: 'roles', column: 'name' }), - rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores - ]), - display_name: schema.string.optional({ trim: true }, [ - rules.minLength(3), - rules.maxLength(255), - rules.unique({ table: 'roles', column: 'name' }), - rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores - ]), - description: schema.string.optional({}, [rules.minLength(3), rules.maxLength(255)]), - permissions: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one role for the new role - }); - - // emails: schema - // .array([rules.minLength(1)]) - // .members( - // schema.object().members({ email: schema.string({}, [rules.email()]) }) - // ), - - /** - * 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', - 'permissions.minLength': 'at least {{ options.minLength }} permission must be defined', - 'permissions.*.number': 'Define roles as valid numbers', - }; -} diff --git a/app/validators/create_user_validator.ts b/app/validators/create_user_validator.ts deleted file mode 100644 index 73ad814..0000000 --- a/app/validators/create_user_validator.ts +++ /dev/null @@ -1,65 +0,0 @@ -import { schema, rules } from '@adonisjs/validator'; -import type { HttpContext } from '@adonisjs/core/http'; -import { CustomMessages } from "@adonisjs/validator/types"; - -export default class CreateUserValidator { - 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({ - login: schema.string({ trim: true }, [ - rules.minLength(3), - rules.maxLength(50), - rules.unique({ table: 'accounts', column: 'login' }), - rules.regex(/^[a-zA-Z0-9-_]+$/), //Must be alphanumeric with hyphens or underscores - ]), - email: schema.string({}, [rules.email(), rules.unique({ table: 'accounts', column: 'email' })]), - password: schema.string([rules.confirmed(), rules.minLength(6)]), - roles: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one role for the new user - }); - - // emails: schema - // .array([rules.minLength(1)]) - // .members( - // schema.object().members({ email: schema.string({}, [rules.email()]) }) - // ), - - /** - * 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', - 'roles.minLength': 'at least {{ options.minLength }} role must be defined', - 'roles.*.number': 'Define roles as valid numbers', - }; -} diff --git a/app/validators/dataset.ts b/app/validators/dataset.ts new file mode 100644 index 0000000..0b6ef41 --- /dev/null +++ b/app/validators/dataset.ts @@ -0,0 +1,296 @@ +import vine, { SimpleMessagesProvider } from '@vinejs/vine'; +import { TitleTypes, DescriptionTypes, ContributorTypes, ReferenceIdentifierTypes, RelationTypes } from '#contracts/enums'; +import dayjs from 'dayjs'; +import MimeType from '#models/mime_type'; + +const enabledExtensions = await MimeType.query().select('file_extension').where('enabled', true).exec(); +const extensions = enabledExtensions.map((extension)=> { + return extension.file_extension.split('|') +}).flat(); + +/** + * Validates the dataset's creation action + * node ace make:validator dataset + */ +export const createDatasetValidator = vine.compile( + vine.object({ + // first step + language: vine + .string() + .trim() + .regex(/^[a-zA-Z0-9]+$/), + licenses: vine.array(vine.number()).minLength(1), // define at least one license for the new dataset + rights: vine.string().in(['true']), + // second step + type: vine.string().trim().minLength(3).maxLength(255), + creating_corporation: vine.string().trim().minLength(3).maxLength(255), + titles: vine + .array( + vine.object({ + value: vine.string().trim().minLength(3).maxLength(255), + type: vine.enum(Object.values(TitleTypes)), + language: vine + .string() + .trim() + .minLength(2) + .maxLength(255) + .translatedLanguage({ mainLanguageField: 'language', typeField: 'type' }), + }), + ) + .minLength(1), + descriptions: vine + .array( + vine.object({ + value: vine.string().trim().minLength(3).maxLength(255), + type: vine.enum(Object.values(DescriptionTypes)), + language: vine + .string() + .trim() + .minLength(2) + .maxLength(255) + .translatedLanguage({ mainLanguageField: 'language', typeField: 'type' }), + }), + ) + .minLength(1), + authors: vine + .array( + vine.object({ + email: vine.string().trim().maxLength(255).email().normalizeEmail(), + }), + ) + .minLength(1), + contributors: vine + .array( + vine.object({ + email: vine.string().trim().maxLength(255).email().normalizeEmail(), + pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)), + }), + ) + .optional(), + // third step + project_id: vine.number().optional(), + // embargo_date: schema.date.optional({ format: 'yyyy-MM-dd' }, [rules.after(10, 'days')]), + embargo_date: vine + .date({ + formats: ['YYYY-MM-DD'], + }) + .afterOrEqual((_field) => { + return dayjs().add(10, 'day').format('YYYY-MM-DD'); + }) + .optional(), + coverage: vine.object({ + x_min: vine.number(), + x_max: vine.number(), + y_min: vine.number(), + y_max: vine.number(), + elevation_absolut: vine.number().optional(), + elevation_min: vine.number().optional().requiredIfExists('elevation_max'), + elevation_max: vine.number().optional().requiredIfExists('elevation_min'), + // type: vine.enum(Object.values(DescriptionTypes)), + depth_absolut: vine.number().optional(), + depth_min: vine.number().optional().requiredIfExists('depth_max'), + depth_max: vine.number().optional().requiredIfExists('depth_min'), + }), + references: vine + .array( + vine.object({ + value: vine.string().trim().minLength(3).maxLength(255), + type: vine.enum(Object.values(ReferenceIdentifierTypes)), + relation: vine.enum(Object.values(RelationTypes)), + label: vine.string().trim().minLength(2).maxLength(255), + }), + ) + .optional(), + subjects: vine + .array( + vine.object({ + value: vine.string().trim().minLength(3).maxLength(255), + // pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)), + language: vine.string().trim().minLength(2).maxLength(255), + }), + ) + .minLength(3) + .distinct('value'), + // last step + files: vine + .array( + vine.file({ + size: '512mb', + extnames: extensions, + }), + ) + .minLength(1), + }), +); + +/** + * Validates the dataset's update action + */ +export const updateDatasetValidator = vine.compile( + vine.object({ + // first step + language: vine + .string() + .trim() + .regex(/^[a-zA-Z0-9]+$/), + licenses: vine.array(vine.number()).minLength(1), // define at least one license for the new dataset + rights: vine.string().in(['true']), + // second step + type: vine.string().trim().minLength(3).maxLength(255), + creating_corporation: vine.string().trim().minLength(3).maxLength(255), + titles: vine + .array( + vine.object({ + value: vine.string().trim().minLength(3).maxLength(255), + type: vine.enum(Object.values(TitleTypes)), + language: vine + .string() + .trim() + .minLength(2) + .maxLength(255) + .translatedLanguage({ mainLanguageField: 'language', typeField: 'type' }), + }), + ) + .minLength(1), + descriptions: vine + .array( + vine.object({ + value: vine.string().trim().minLength(3).maxLength(255), + type: vine.enum(Object.values(DescriptionTypes)), + language: vine + .string() + .trim() + .minLength(2) + .maxLength(255) + .translatedLanguage({ mainLanguageField: 'language', typeField: 'type' }), + }), + ) + .minLength(1), + authors: vine + .array( + vine.object({ + email: vine.string().trim().maxLength(255).email().normalizeEmail(), + }), + ) + .minLength(1), + contributors: vine + .array( + vine.object({ + email: vine.string().trim().maxLength(255).email().normalizeEmail(), + pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)), + }), + ) + .optional(), + // third step + project_id: vine.number().optional(), + // embargo_date: schema.date.optional({ format: 'yyyy-MM-dd' }, [rules.after(10, 'days')]), + embargo_date: vine + .date({ + formats: ['YYYY-MM-DD'], + }) + .afterOrEqual((_field) => { + return dayjs().add(10, 'day').format('YYYY-MM-DD'); + }) + .optional(), + coverage: vine.object({ + x_min: vine.number(), + x_max: vine.number(), + y_min: vine.number(), + y_max: vine.number(), + elevation_absolut: vine.number().optional(), + elevation_min: vine.number().optional().requiredIfExists('elevation_max'), + elevation_max: vine.number().optional().requiredIfExists('elevation_min'), + // type: vine.enum(Object.values(DescriptionTypes)), + depth_absolut: vine.number().optional(), + depth_min: vine.number().optional().requiredIfExists('depth_max'), + depth_max: vine.number().optional().requiredIfExists('depth_min'), + }), + references: vine + .array( + vine.object({ + value: vine.string().trim().minLength(3).maxLength(255), + type: vine.enum(Object.values(ReferenceIdentifierTypes)), + relation: vine.enum(Object.values(RelationTypes)), + label: vine.string().trim().minLength(2).maxLength(255), + }), + ) + .optional(), + subjects: vine + .array( + vine.object({ + value: vine.string().trim().minLength(3).maxLength(255), + // pivot_contributor_type: vine.enum(Object.keys(ContributorTypes)), + language: vine.string().trim().minLength(2).maxLength(255), + }), + ) + .minLength(3) + .distinct('value'), + // last step + files: vine + .array( + vine.file({ + size: '512mb', + extnames: extensions, + }), + ), + // .minLength(1), + }), +); + +// 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'], +// }), +// ), + +let messagesProvider = new SimpleMessagesProvider({ + 'minLength': '{{ field }} must be at least {{ min }} characters long', + 'maxLength': '{{ field }} must be less then {{ max }} 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 {{ min }} permission must be defined', + 'licenses.*.number': 'Define roles as valid numbers', + 'rights.in': 'you must agree to continue', + + 'titles.0.value.minLength': 'Main Title must be at least {{ min }} 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 {{ min }} 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.array.minLength': 'at least {{ min }} 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.array.minLength': 'at least {{ min }} keywords must be defined', + 'subjects.*.value.required': 'keyword value is required', + 'subjects.*.value.minLength': 'keyword value must be at least {{ min }} characters long', + 'subjects.*.type.required': 'keyword type is required', + 'subjects.*.language.required': 'language of keyword is required', + 'subjects.distinct': 'The {{ field }} array must have unique values based on the {{ fields }} attribute.', + + '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.array.minLength': 'At least {{ min }} file upload is required.', + 'files.*.size': 'file size is to big', + 'files.*.extnames': 'file extension is not supported', +}); + +createDatasetValidator.messagesProvider = messagesProvider; +updateDatasetValidator.messagesProvider = messagesProvider; +// export default createDatasetValidator; diff --git a/app/validators/role.ts b/app/validators/role.ts new file mode 100644 index 0000000..f2d4911 --- /dev/null +++ b/app/validators/role.ts @@ -0,0 +1,64 @@ +import vine, { SimpleMessagesProvider } from '@vinejs/vine'; + +/** + * Validates the role's creation action + * node ace make:validator role + */ +export const createRoleValidator = vine.compile( + vine.object({ + name: vine + .string() + .isUnique({ table: 'roles', column: 'name' }) + .trim() + .minLength(3) + .maxLength(255) + .regex(/^[a-zA-Z0-9]+$/), //Must be alphanumeric with hyphens or underscores + display_name: vine + .string() + .isUnique({ table: 'roles', column: 'display_name' }) + .trim() + .minLength(3) + .maxLength(255) + .regex(/^[a-zA-Z0-9]+$/), + description: vine.string().trim().escape().minLength(3).maxLength(255).optional(), + permissions: vine.array(vine.number()).minLength(1), // define at least one permission for the new role + }), +); + +export const updateRoleValidator = vine.withMetaData<{ roleId: number }>().compile( + vine.object({ + name: vine + .string() + // .unique(async (db, value, field) => { + // const result = await db.from('roles').select('id').whereNot('id', field.meta.roleId).where('name', value).first(); + // return result.length ? false : true; + // }) + .isUnique({ + table: 'roles', + column: 'name', + whereNot: (field) => field.meta.roleId, + }) + .trim() + .minLength(3) + .maxLength(255), + + description: vine.string().trim().escape().minLength(3).maxLength(255).optional(), + permissions: vine.array(vine.number()).minLength(1), // define at least one permission for the new role + }), +); + +let messagesProvider = new SimpleMessagesProvider({ + // Applicable for all fields + 'required': 'The {{ field }} field is required', + 'unique': '{{ field }} must be unique, and this value is already taken', + 'string': 'The value of {{ field }} field must be a string', + 'email': 'The value is not a valid email address', + + // 'contacts.0.email.required': 'The primary email of the contact is required', + // 'contacts.*.email.required': 'Contact email is required', + 'permissions.minLength': 'at least {{ options.minLength }} permission must be defined', + 'permissions.*.number': 'Define permissions as valid numbers', +}); + +createRoleValidator.messagesProvider = messagesProvider; +updateRoleValidator.messagesProvider = messagesProvider; diff --git a/app/validators/update_dataset_validator.ts b/app/validators/update_dataset_validator.ts deleted file mode 100644 index 6784ca8..0000000 --- a/app/validators/update_dataset_validator.ts +++ /dev/null @@ -1,180 +0,0 @@ -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 UpdateDatasetValidator { - 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.optional().members( - schema.file({ - size: '100mb', - extnames: ['jpg', 'gif', 'png', 'tif', 'pdf'], - }), - ) - - // 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', - }; -} diff --git a/app/validators/update_role_validator.ts b/app/validators/update_role_validator.ts deleted file mode 100644 index 656d086..0000000 --- a/app/validators/update_role_validator.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { schema, rules } from '@adonisjs/validator'; -import type { HttpContext } from '@adonisjs/core/http'; -import { CustomMessages } from "@adonisjs/validator/types"; - -// import { Request } from '@adonisjs/core/build/standalone'; - -export default class UpdateRoleValidator { - protected ctx: HttpContext; - public schema; - - constructor(ctx: HttpContext) { - this.ctx = ctx; - this.schema = this.createSchema(); - } - - // public get schema() { - // return this._schema; - // } - - private createSchema() { - return schema.create({ - name: schema.string({ trim: true }, [ - rules.minLength(3), - rules.maxLength(50), - rules.unique({ - table: 'roles', - column: 'name', - whereNot: { id: this.ctx?.params.id }, - }), - rules.regex(/^[a-zA-Z0-9-_]+$/), - //Must be alphanumeric with hyphens or underscores - ]), - description: schema.string.optional({}, [rules.minLength(3), rules.maxLength(255)]), - permissions: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one permission for the new role - }); - } - - /* - * 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 refs = schema.refs({ - // id: this.ctx.params.id - // }) - - // public schema = schema.create({ - // login: schema.string({ trim: true }, [ - // rules.minLength(3), - // rules.maxLength(50), - // rules.unique({ - // table: 'accounts', - // column: 'login', - // // whereNot: { id: this.refs.id } - // whereNot: { id: this.ctx?.params.id }, - // }), - // // rules.regex(/^[a-zA-Z0-9-_]+$/), - // //Must be alphanumeric with hyphens or underscores - // ]), - // email: schema.string({}, [rules.email(), rules.unique({ table: 'accounts', column: 'email' })]), - // password: schema.string.optional([rules.confirmed(), rules.minLength(6)]), - // roles: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one role for the new user - // }); - - /** - * 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', - 'permissions.minLength': 'at least {{ options.minLength }} permission must be defined', - 'permissions.*.number': 'Define permissions as valid numbers', - }; -} diff --git a/app/validators/update_user_validator.ts b/app/validators/update_user_validator.ts deleted file mode 100644 index 0059b6f..0000000 --- a/app/validators/update_user_validator.ts +++ /dev/null @@ -1,105 +0,0 @@ -import { schema, rules } from '@adonisjs/validator'; -import type { HttpContext } from '@adonisjs/core/http'; -import { CustomMessages } from "@adonisjs/validator/types"; - -// import { Request } from '@adonisjs/core/build/standalone'; - -export default class UpdateUserValidator { - protected ctx: HttpContext; - public schema; - - constructor(ctx: HttpContext) { - this.ctx = ctx; - this.schema = this.createSchema(); - } - - // public get schema() { - // return this._schema; - // } - - private createSchema() { - return schema.create({ - login: schema.string({ trim: true }, [ - rules.minLength(3), - rules.maxLength(50), - rules.unique({ - table: 'accounts', - column: 'login', - // whereNot: { id: this.refs.id } - whereNot: { id: this.ctx?.params.id }, - }), - // rules.regex(/^[a-zA-Z0-9-_]+$/), - //Must be alphanumeric with hyphens or underscores - ]), - email: schema.string({}, [ - rules.email(), - rules.unique({ table: 'accounts', column: 'email', whereNot: { id: this.ctx?.params.id } }), - ]), - password: schema.string.optional([rules.confirmed(), rules.minLength(6)]), - roles: schema.array.optional([rules.minLength(1)]).members(schema.number()), // define at least one role for the new user - }); - } - - /* - * 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 refs = schema.refs({ - // id: this.ctx.params.id - // }) - - // public schema = schema.create({ - // login: schema.string({ trim: true }, [ - // rules.minLength(3), - // rules.maxLength(50), - // rules.unique({ - // table: 'accounts', - // column: 'login', - // // whereNot: { id: this.refs.id } - // whereNot: { id: this.ctx?.params.id }, - // }), - // // rules.regex(/^[a-zA-Z0-9-_]+$/), - // //Must be alphanumeric with hyphens or underscores - // ]), - // email: schema.string({}, [rules.email(), rules.unique({ table: 'accounts', column: 'email' })]), - // password: schema.string.optional([rules.confirmed(), rules.minLength(6)]), - // roles: schema.array([rules.minLength(1)]).members(schema.number()), // define at least one role for the new user - // }); - - /** - * 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', - 'roles.minLength': 'at least {{ options.minLength }} role must be defined', - 'roles.*.number': 'Define roles as valid numbers', - }; -} diff --git a/app/validators/user.ts b/app/validators/user.ts new file mode 100644 index 0000000..dd6e047 --- /dev/null +++ b/app/validators/user.ts @@ -0,0 +1,60 @@ +import vine, { SimpleMessagesProvider } from '@vinejs/vine'; + +/** + * Validates the role's creation action + * node ace make:validator user + */ +export const createUserValidator = vine.compile( + vine.object({ + login: vine + .string() + .trim() + .minLength(3) + .maxLength(20) + .isUnique({ table: 'accounts', column: 'login' }) + .regex(/^[a-zA-Z0-9]+$/), //Must be alphanumeric with hyphens or underscores + email: vine.string().maxLength(255).email().normalizeEmail().isUnique({ table: 'accounts', column: 'email' }), + password: vine.string().confirmed().trim().minLength(3).maxLength(60), + roles: vine.array(vine.number()).minLength(1), // define at least one role for the new user + }), +); + +/** + * Validates the role's update action + * node ace make:validator user + */ +export const updateUserValidator = vine.withMetaData<{ userId: number }>().compile( + vine.object({ + login: vine + .string() + .trim() + .minLength(3) + .maxLength(20) + .isUnique({ table: 'accounts', column: 'login', whereNot: (field) => field.meta.userId }) + .regex(/^[a-zA-Z0-9]+$/), //Must be alphanumeric with hyphens or underscores + email: vine + .string() + .maxLength(255) + .email() + .normalizeEmail() + .isUnique({ table: 'accounts', column: 'email', whereNot: (field) => field.meta.userId }), + password: vine.string().confirmed().trim().minLength(3).maxLength(60), + roles: vine.array(vine.number()).minLength(1), // define at least one role for the new user + }), +); + +let messagesProvider = new SimpleMessagesProvider({ + // Applicable for all fields + 'required': 'The {{ field }} field is required', + 'unique': '{{ field }} must be unique, and this value is already taken', + 'string': 'The value of {{ field }} field must be a string', + 'email': 'The value is not a valid email address', + 'minLength': '{{ field }} must be at least {{ options.minLength }} characters long', + 'maxLength': '{{ field }} must be less then {{ options.maxLength }} characters long', + 'confirmed': 'Oops! The confirmation of {{ field }} is not correct. Please double-check and ensure they match.', + 'roles.minLength': 'at least {{ options.minLength }} role must be defined', + 'roles.*.number': 'Define roles as valid numbers', +}); + +createUserValidator.messagesProvider = messagesProvider; +updateUserValidator.messagesProvider = messagesProvider; diff --git a/app/validators/vanilla_error_reporter.ts b/app/validators/vanilla_error_reporter.ts new file mode 100644 index 0000000..2cc606f --- /dev/null +++ b/app/validators/vanilla_error_reporter.ts @@ -0,0 +1,169 @@ +// import { ValidationError } from '../errors/validation_error.js'; +import { errors } from '@vinejs/vine'; +import type { ErrorReporterContract, FieldContext } from '@vinejs/vine/types'; +import string from '@poppinss/utils/string'; + +/** + * Shape of the Vanilla error node + */ +export type VanillaErrorNode = { + [field: string]: string[]; +}; +export interface MessagesBagContract { + get(pointer: string, rule: string, message: string, arrayExpressionPointer?: string, args?: any): string; +} +/** + * Message bag exposes the API to pull the most appropriate message for a + * given validation failure. + */ +export class MessagesBag implements MessagesBagContract { + messages; + wildCardCallback; + constructor(messages: string[]) { + this.messages = messages; + this.wildCardCallback = typeof this.messages['*'] === 'function' ? this.messages['*'] : undefined; + } + /** + * Transform message by replace placeholders with runtime values + */ + transform(message: any, rule: string, pointer: string, args: any) { + /** + * No interpolation required + */ + if (!message.includes('{{')) { + return message; + } + return string.interpolate(message, { rule, field: pointer, options: args || {} }); + } + /** + * Returns the most appropriate message for the validation failure. + */ + get(pointer: string, rule: string, message: string, arrayExpressionPointer: string, args: any) { + let validationMessage = this.messages[`${pointer}.${rule}`]; + /** + * Fetch message for the array expression pointer if it exists + */ + if (!validationMessage && arrayExpressionPointer) { + validationMessage = this.messages[`${arrayExpressionPointer}.${rule}`]; + } + /** + * Fallback to the message for the rule + */ + if (!validationMessage) { + validationMessage = this.messages[rule]; + } + /** + * Transform and return message. The wildcard callback is invoked when custom message + * is not defined + */ + return validationMessage + ? this.transform(validationMessage, rule, pointer, args) + : this.wildCardCallback + ? this.wildCardCallback(pointer, rule, arrayExpressionPointer, args) + : message; + } +} +/** + * Shape of the error message collected by the SimpleErrorReporter + */ +// type SimpleError = { +// message: string; +// field: string; +// rule: string; +// index?: number; +// meta?: Record; +// }; +/** + * Simple error reporter collects error messages as an array of object. + * Each object has following properties. + * + * - message: string + * - field: string + * - rule: string + * - index?: number (in case of an array member) + * - args?: Record + */ +export class VanillaErrorReporter implements ErrorReporterContract { + private messages; + // private bail; + /** + * Boolean to know one or more errors have been reported + */ + hasErrors: boolean = false; + /** + * Collection of errors + */ + // errors: SimpleError[] = []; + errors = {}; + /** + * Report an error. + */ + + // constructor(messages: MessagesBagContract) { + // this.messages = messages; + // } + + report(message: string, rule: string, field: FieldContext, meta?: Record | undefined): void { + // const error: SimpleError = { + // message, + // rule, + // field: field.getFieldPath() + // }; + // if (meta) { + // error.meta = meta; + // } + // if (field.isArrayMember) { + // error.index = field.name as number; + // } + // this.errors.push(error); + this.hasErrors = true; + const error = { + message, + rule, + field: field.getFieldPath(), + }; + // field: 'titles.0.value' + // message: 'Main Title is required' + // rule: 'required' "required" + if (meta) { + error.meta = meta; + } + // if (field.isArrayMember) { + // error.index = field.name; + // } + this.hasErrors = true; + // this.errors.push(error); + if (this.errors[error.field]) { + this.errors[error.field]?.push(message); + } else { + this.errors[error.field] = [message]; + } + + /** + * Collecting errors as per the JSONAPI spec + */ + // this.errors.push({ + // code: rule, + // detail: message, + // source: { + // pointer: field.wildCardPath, + // }, + // ...(meta ? { meta } : {}), + // }); + + // let pointer: string = field.wildCardPath as string; //'display_name' + // // if (field.isArrayMember) { + // // this.errors[pointer] = field.name; + // // } + // this.errors[pointer] = this.errors[pointer] || []; + // // this.errors[pointer].push(message); + // this.errors[pointer].push(this.messages.get(pointer, rule, message, arrayExpressionPointer, args)); + } + /** + * Returns an instance of the validation error + */ + createError() { + return new errors.E_VALIDATION_ERROR(this.errors); + } +} +export {}; diff --git a/package-lock.json b/package-lock.json index 43b6b74..687e9e2 100644 --- a/package-lock.json +++ b/package-lock.json @@ -19,7 +19,6 @@ "@adonisjs/session": "^7.1.1", "@adonisjs/shield": "^8.1.1", "@adonisjs/static": "^1.1.1", - "@adonisjs/validator": "^13.0.2", "@eidellev/adonis-stardust": "^3.0.0", "@fontsource/archivo-black": "^5.0.1", "@fontsource/inter": "^5.0.1", @@ -27,6 +26,7 @@ "@inertiajs/vue3": "^1.0.0", "@opensearch-project/opensearch": "^2.4.0", "@phc/format": "^1.0.0", + "@vinejs/vine": "^2.0.0", "bcrypt": "^5.1.1", "bcryptjs": "^2.4.3", "clamscan": "^2.1.2", @@ -66,7 +66,7 @@ "@mdi/js": "^7.1.96", "@poppinss/utils": "^6.7.2", "@swc/core": "^1.4.2", - "@symfony/webpack-encore": "^4.5.0", + "@symfony/webpack-encore": "^4.6.1", "@tailwindcss/forms": "^0.5.2", "@types/bcryptjs": "^2.4.6", "@types/clamscan": "^2.0.4", @@ -82,15 +82,14 @@ "babel-preset-typescript-vue3": "^2.0.17", "chart.js": "^4.2.0", "dotenv-webpack": "^8.0.1", - "eslint": "^8.32.0", + "eslint": "^8.57.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-adonis": "^2.1.1", "eslint-plugin-prettier": "^5.0.0-alpha.2", - "naive-ui": "^2.35.0", "numeral": "^2.0.6", "pinia": "^2.0.30", "pino-pretty": "^11.0.0", - "postcss-loader": "^7.3.0", + "postcss-loader": "^7.3.4", "prettier": "^3.0.0", "supertest": "^6.3.3", "tailwindcss": "^3.2.4", @@ -174,9 +173,9 @@ } }, "node_modules/@adonisjs/assembler": { - "version": "7.5.1", - "resolved": "https://registry.npmjs.org/@adonisjs/assembler/-/assembler-7.5.1.tgz", - "integrity": "sha512-ggVicFJWOpGKl+Aye1qx/3Z6lkwxj3z7Em0zqgBD+iukjYLUYfVo0J8+7h44cI5+h49rT6xwlbhPKqV2QlDjtw==", + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/@adonisjs/assembler/-/assembler-7.5.2.tgz", + "integrity": "sha512-wuyfcVaQfDlTlaowkbtL+wcUSb3PhI+NPtEmgFrhTsOmHL+OgP0wQu9K0JZcoTYLLJqfwyYPndTVHa1gHwFGXQ==", "devOptional": true, "dependencies": { "@adonisjs/env": "^6.0.0", @@ -299,16 +298,16 @@ } }, "node_modules/@adonisjs/core": { - "version": "6.8.0", - "resolved": "https://registry.npmjs.org/@adonisjs/core/-/core-6.8.0.tgz", - "integrity": "sha512-aIdnmAk19i1xThRQPF1qAaI2xDoSH9TBZnQS1BhbaCZ8Dy8w98uszVLPzh+Bq0LWGZDU0KGE1Q1HfoC2vGEcAw==", + "version": "6.9.0", + "resolved": "https://registry.npmjs.org/@adonisjs/core/-/core-6.9.0.tgz", + "integrity": "sha512-T9BtI2PzvoB/YJcYS02ok5K2NX9RO61L+QEoxBAvNlXb4ItP/ubdPqbFEH1KcxeWktFkFKdxfV50lj/+7IiwZw==", "dependencies": { "@adonisjs/ace": "^13.0.0", "@adonisjs/application": "^8.2.2", "@adonisjs/bodyparser": "^10.0.2", "@adonisjs/config": "^5.0.2", "@adonisjs/encryption": "^6.0.2", - "@adonisjs/env": "^6.0.1", + "@adonisjs/env": "^6.1.0", "@adonisjs/events": "^9.0.2", "@adonisjs/fold": "^10.1.2", "@adonisjs/hash": "^9.0.3", @@ -904,12 +903,12 @@ } }, "node_modules/@adonisjs/inertia": { - "version": "1.0.0-26", - "resolved": "https://registry.npmjs.org/@adonisjs/inertia/-/inertia-1.0.0-26.tgz", - "integrity": "sha512-TYhKIjr6V4H+gyw3hT9T9Hl2PmzbbpUquTl4k4HCqMxzML+bPDboJauv1MT7cQEHOXA91643zCFq4JDQdhvqCA==", + "version": "1.0.0-27", + "resolved": "https://registry.npmjs.org/@adonisjs/inertia/-/inertia-1.0.0-27.tgz", + "integrity": "sha512-T3G4s8mzdPv1+JEGvq7AAgc62kBB8n0DmrQAQHy8M5vzYy0swNcKjdNwiSdG6ChJSys/yX91QwcUoyRltUAtZA==", "dependencies": { "@poppinss/utils": "^6.7.3", - "@tuyau/utils": "^0.0.2", + "@tuyau/utils": "^0.0.3", "crc-32": "^1.2.2", "edge-error": "^4.0.1", "html-entities": "^2.5.2", @@ -979,22 +978,22 @@ } }, "node_modules/@adonisjs/lucid": { - "version": "20.5.1", - "resolved": "https://registry.npmjs.org/@adonisjs/lucid/-/lucid-20.5.1.tgz", - "integrity": "sha512-PXzeRTbkPFhf5ttRv6LbKYbtXXWrYUWxrVmXecHvNbrKZSlP7XQOm45Pgk75lStAXBkEqxgvlC9PRHgM+Bdrog==", + "version": "20.6.0", + "resolved": "https://registry.npmjs.org/@adonisjs/lucid/-/lucid-20.6.0.tgz", + "integrity": "sha512-LTHc3xjGukjEcy0972l4DUkmlnhXuzvlMGt7zqyfbbn4XmRk6b6RczYPhjUEVqUvNzx845L7RnqTJ8mblHHnmQ==", "dependencies": { - "@adonisjs/presets": "^2.2.5", + "@adonisjs/presets": "^2.4.0", "@faker-js/faker": "^8.4.1", - "@poppinss/hooks": "^7.2.2", - "@poppinss/macroable": "^1.0.1", - "@poppinss/utils": "^6.7.2", + "@poppinss/hooks": "^7.2.3", + "@poppinss/macroable": "^1.0.2", + "@poppinss/utils": "^6.7.3", "fast-deep-equal": "^3.1.3", "igniculus": "^1.5.0", "kleur": "^4.1.5", "knex": "^3.1.0", "knex-dynamic-connection": "^3.1.1", "pretty-hrtime": "^1.0.3", - "qs": "^6.11.2", + "qs": "^6.12.1", "slash": "^5.1.0", "tarn": "^3.0.2" }, @@ -1191,26 +1190,6 @@ "integrity": "sha512-+nOykDG44b4JSAdsrTdh5HuZqJpr6F+dHpfNYgHfYsFJIEtZo8plHilZAM7iabCRN5R49SPv5p8Ixcp47Rr50g==", "dev": true }, - "node_modules/@adonisjs/validator": { - "version": "13.0.2", - "resolved": "https://registry.npmjs.org/@adonisjs/validator/-/validator-13.0.2.tgz", - "integrity": "sha512-gec1SiJP6Y/SUbm1Co6Z0kh9euUWZnEioWHKJ/XdoX31rTI6qoET1EYX/NGuzT6axsk/zBWmgENhMv/WwNwZ7Q==", - "dependencies": { - "@poppinss/utils": "^6.7.1", - "@types/luxon": "^3.4.2", - "@types/validator": "^13.11.8", - "luxon": "^3.4.4", - "normalize-url": "^8.0.0", - "tmp-cache": "^1.1.0", - "validator": "^13.11.0" - }, - "engines": { - "node": ">=18.16.0" - }, - "peerDependencies": { - "@adonisjs/core": "^6.2.0" - } - }, "node_modules/@adonisjs/vite": { "version": "3.0.0-11", "resolved": "https://registry.npmjs.org/@adonisjs/vite/-/vite-3.0.0-11.tgz", @@ -3220,24 +3199,6 @@ "@jridgewell/sourcemap-codec": "^1.4.10" } }, - "node_modules/@css-render/plugin-bem": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/@css-render/plugin-bem/-/plugin-bem-0.15.12.tgz", - "integrity": "sha512-Lq2jSOZn+wYQtsyaFj6QRz2EzAnd3iW5fZeHO1WSXQdVYwvwGX0ZiH3X2JQgtgYLT1yeGtrwrqJdNdMEUD2xTw==", - "dev": true, - "peerDependencies": { - "css-render": "~0.15.12" - } - }, - "node_modules/@css-render/vue3-ssr": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/@css-render/vue3-ssr/-/vue3-ssr-0.15.12.tgz", - "integrity": "sha512-AQLGhhaE0F+rwybRCkKUdzBdTEM/5PZBYy+fSYe1T9z9+yxMuV/k7ZRqa4M69X+EI1W8pa4kc9Iq2VjQkZx4rg==", - "dev": true, - "peerDependencies": { - "vue": "^3.0.11" - } - }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", @@ -3259,12 +3220,6 @@ "@adonisjs/core": ">=5" } }, - "node_modules/@emotion/hash": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.8.0.tgz", - "integrity": "sha512-kBJtf7PH6aWwZ6fka3zQ0p6SBYzx4fl1LoZXE2RrnYST9Xljm7WfKJrU4g/Xr3Beg72MLrp1AWNUmuYJTL7Cow==", - "dev": true - }, "node_modules/@esbuild/aix-ppc64": { "version": "0.20.2", "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", @@ -4235,12 +4190,6 @@ "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", "dev": true }, - "node_modules/@juggle/resize-observer": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz", - "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA==", - "dev": true - }, "node_modules/@kurkle/color": { "version": "0.3.2", "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", @@ -4425,9 +4374,9 @@ } }, "node_modules/@opensearch-project/opensearch": { - "version": "2.7.0", - "resolved": "https://registry.npmjs.org/@opensearch-project/opensearch/-/opensearch-2.7.0.tgz", - "integrity": "sha512-ee4XEU0CSwbThGgKcROmQPwG48QjMaMJzJdgUaGqeIeni7YMJqlZ6g4pbPD7iDE19Y1e2/OEzeW54DE/Fyky2g==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/@opensearch-project/opensearch/-/opensearch-2.8.0.tgz", + "integrity": "sha512-VgYq5WQCHHotUlk8fUXAkisCjeiw6eNKg/z9elBHuFnNVEUEhSzl3UAuPS3Y9TUd9uTvUbAZ8kkuA5y3Te9rsw==", "dependencies": { "aws4": "^1.11.0", "debug": "^4.3.1", @@ -4937,14 +4886,14 @@ } }, "node_modules/@swc/core": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.4.17.tgz", - "integrity": "sha512-tq+mdWvodMBNBBZbwFIMTVGYHe9N7zvEaycVVjfvAx20k1XozHbHhRv+9pEVFJjwRxLdXmtvFZd3QZHRAOpoNQ==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core/-/core-1.5.7.tgz", + "integrity": "sha512-U4qJRBefIJNJDRCCiVtkfa/hpiZ7w0R6kASea+/KLp+vkus3zcLSB8Ub8SvKgTIxjWpwsKcZlPf5nrv4ls46SQ==", "dev": true, "hasInstallScript": true, "dependencies": { "@swc/counter": "^0.1.2", - "@swc/types": "^0.1.5" + "@swc/types": "0.1.7" }, "engines": { "node": ">=10" @@ -4954,16 +4903,16 @@ "url": "https://opencollective.com/swc" }, "optionalDependencies": { - "@swc/core-darwin-arm64": "1.4.17", - "@swc/core-darwin-x64": "1.4.17", - "@swc/core-linux-arm-gnueabihf": "1.4.17", - "@swc/core-linux-arm64-gnu": "1.4.17", - "@swc/core-linux-arm64-musl": "1.4.17", - "@swc/core-linux-x64-gnu": "1.4.17", - "@swc/core-linux-x64-musl": "1.4.17", - "@swc/core-win32-arm64-msvc": "1.4.17", - "@swc/core-win32-ia32-msvc": "1.4.17", - "@swc/core-win32-x64-msvc": "1.4.17" + "@swc/core-darwin-arm64": "1.5.7", + "@swc/core-darwin-x64": "1.5.7", + "@swc/core-linux-arm-gnueabihf": "1.5.7", + "@swc/core-linux-arm64-gnu": "1.5.7", + "@swc/core-linux-arm64-musl": "1.5.7", + "@swc/core-linux-x64-gnu": "1.5.7", + "@swc/core-linux-x64-musl": "1.5.7", + "@swc/core-win32-arm64-msvc": "1.5.7", + "@swc/core-win32-ia32-msvc": "1.5.7", + "@swc/core-win32-x64-msvc": "1.5.7" }, "peerDependencies": { "@swc/helpers": "^0.5.0" @@ -4975,9 +4924,9 @@ } }, "node_modules/@swc/core-darwin-arm64": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.4.17.tgz", - "integrity": "sha512-HVl+W4LezoqHBAYg2JCqR+s9ife9yPfgWSj37iIawLWzOmuuJ7jVdIB7Ee2B75bEisSEKyxRlTl6Y1Oq3owBgw==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-arm64/-/core-darwin-arm64-1.5.7.tgz", + "integrity": "sha512-bZLVHPTpH3h6yhwVl395k0Mtx8v6CGhq5r4KQdAoPbADU974Mauz1b6ViHAJ74O0IVE5vyy7tD3OpkQxL/vMDQ==", "cpu": [ "arm64" ], @@ -4991,9 +4940,9 @@ } }, "node_modules/@swc/core-darwin-x64": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.4.17.tgz", - "integrity": "sha512-WYRO9Fdzq4S/he8zjW5I95G1zcvyd9yyD3Tgi4/ic84P5XDlSMpBDpBLbr/dCPjmSg7aUXxNQqKqGkl6dQxYlA==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-darwin-x64/-/core-darwin-x64-1.5.7.tgz", + "integrity": "sha512-RpUyu2GsviwTc2qVajPL0l8nf2vKj5wzO3WkLSHAHEJbiUZk83NJrZd1RVbEknIMO7+Uyjh54hEh8R26jSByaw==", "cpu": [ "x64" ], @@ -5007,9 +4956,9 @@ } }, "node_modules/@swc/core-linux-arm-gnueabihf": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.4.17.tgz", - "integrity": "sha512-cgbvpWOvtMH0XFjvwppUCR+Y+nf6QPaGu6AQ5hqCP+5Lv2zO5PG0RfasC4zBIjF53xgwEaaWmGP5/361P30X8Q==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm-gnueabihf/-/core-linux-arm-gnueabihf-1.5.7.tgz", + "integrity": "sha512-cTZWTnCXLABOuvWiv6nQQM0hP6ZWEkzdgDvztgHI/+u/MvtzJBN5lBQ2lue/9sSFYLMqzqff5EHKlFtrJCA9dQ==", "cpu": [ "arm" ], @@ -5023,9 +4972,9 @@ } }, "node_modules/@swc/core-linux-arm64-gnu": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.4.17.tgz", - "integrity": "sha512-l7zHgaIY24cF9dyQ/FOWbmZDsEj2a9gRFbmgx2u19e3FzOPuOnaopFj0fRYXXKCmtdx+anD750iBIYnTR+pq/Q==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-gnu/-/core-linux-arm64-gnu-1.5.7.tgz", + "integrity": "sha512-hoeTJFBiE/IJP30Be7djWF8Q5KVgkbDtjySmvYLg9P94bHg9TJPSQoC72tXx/oXOgXvElDe/GMybru0UxhKx4g==", "cpu": [ "arm64" ], @@ -5039,9 +4988,9 @@ } }, "node_modules/@swc/core-linux-arm64-musl": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.4.17.tgz", - "integrity": "sha512-qhH4gr9gAlVk8MBtzXbzTP3BJyqbAfUOATGkyUtohh85fPXQYuzVlbExix3FZXTwFHNidGHY8C+ocscI7uDaYw==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-arm64-musl/-/core-linux-arm64-musl-1.5.7.tgz", + "integrity": "sha512-+NDhK+IFTiVK1/o7EXdCeF2hEzCiaRSrb9zD7X2Z7inwWlxAntcSuzZW7Y6BRqGQH89KA91qYgwbnjgTQ22PiQ==", "cpu": [ "arm64" ], @@ -5055,9 +5004,9 @@ } }, "node_modules/@swc/core-linux-x64-gnu": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.4.17.tgz", - "integrity": "sha512-vRDFATL1oN5oZMImkwbgSHEkp8xG1ofEASBypze01W1Tqto8t+yo6gsp69wzCZBlxldsvPpvFZW55Jq0Rn+UnA==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-gnu/-/core-linux-x64-gnu-1.5.7.tgz", + "integrity": "sha512-25GXpJmeFxKB+7pbY7YQLhWWjkYlR+kHz5I3j9WRl3Lp4v4UD67OGXwPe+DIcHqcouA1fhLhsgHJWtsaNOMBNg==", "cpu": [ "x64" ], @@ -5071,9 +5020,9 @@ } }, "node_modules/@swc/core-linux-x64-musl": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.4.17.tgz", - "integrity": "sha512-zQNPXAXn3nmPqv54JVEN8k2JMEcMTQ6veVuU0p5O+A7KscJq+AGle/7ZQXzpXSfUCXlLMX4wvd+rwfGhh3J4cw==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-linux-x64-musl/-/core-linux-x64-musl-1.5.7.tgz", + "integrity": "sha512-0VN9Y5EAPBESmSPPsCJzplZHV26akC0sIgd3Hc/7S/1GkSMoeuVL+V9vt+F/cCuzr4VidzSkqftdP3qEIsXSpg==", "cpu": [ "x64" ], @@ -5087,9 +5036,9 @@ } }, "node_modules/@swc/core-win32-arm64-msvc": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.4.17.tgz", - "integrity": "sha512-z86n7EhOwyzxwm+DLE5NoLkxCTme2lq7QZlDjbQyfCxOt6isWz8rkW5QowTX8w9Rdmk34ncrjSLvnHOeLY17+w==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-win32-arm64-msvc/-/core-win32-arm64-msvc-1.5.7.tgz", + "integrity": "sha512-RtoNnstBwy5VloNCvmvYNApkTmuCe4sNcoYWpmY7C1+bPR+6SOo8im1G6/FpNem8AR5fcZCmXHWQ+EUmRWJyuA==", "cpu": [ "arm64" ], @@ -5103,9 +5052,9 @@ } }, "node_modules/@swc/core-win32-ia32-msvc": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.4.17.tgz", - "integrity": "sha512-JBwuSTJIgiJJX6wtr4wmXbfvOswHFj223AumUrK544QV69k60FJ9q2adPW9Csk+a8wm1hLxq4HKa2K334UHJ/g==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-win32-ia32-msvc/-/core-win32-ia32-msvc-1.5.7.tgz", + "integrity": "sha512-Xm0TfvcmmspvQg1s4+USL3x8D+YPAfX2JHygvxAnCJ0EHun8cm2zvfNBcsTlnwYb0ybFWXXY129aq1wgFC9TpQ==", "cpu": [ "ia32" ], @@ -5119,9 +5068,9 @@ } }, "node_modules/@swc/core-win32-x64-msvc": { - "version": "1.4.17", - "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.4.17.tgz", - "integrity": "sha512-jFkOnGQamtVDBm3MF5Kq1lgW8vx4Rm1UvJWRUfg+0gx7Uc3Jp3QMFeMNw/rDNQYRDYPG3yunCC+2463ycd5+dg==", + "version": "1.5.7", + "resolved": "https://registry.npmjs.org/@swc/core-win32-x64-msvc/-/core-win32-x64-msvc-1.5.7.tgz", + "integrity": "sha512-tp43WfJLCsKLQKBmjmY/0vv1slVywR5Q4qKjF5OIY8QijaEW7/8VwPyUyVoJZEnDgv9jKtUTG5PzqtIYPZGnyg==", "cpu": [ "x64" ], @@ -5141,9 +5090,9 @@ "dev": true }, "node_modules/@swc/types": { - "version": "0.1.6", - "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.6.tgz", - "integrity": "sha512-/JLo/l2JsT/LRd80C3HfbmVpxOAJ11FO2RCEslFrgzLltoP9j8XIbsyDcfCt2WWyX+CM96rBoNM+IToAkFOugg==", + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/@swc/types/-/types-0.1.7.tgz", + "integrity": "sha512-scHWahbHF0eyj3JsxG9CFJgFdFNaVQCNAimBlT6PzS3n/HptxqREjsm4OH6AN3lYcffZYSPxXW8ua2BEHp0lJQ==", "dev": true, "dependencies": { "@swc/counter": "^0.1.3" @@ -5474,9 +5423,9 @@ "dev": true }, "node_modules/@tuyau/utils": { - "version": "0.0.2", - "resolved": "https://registry.npmjs.org/@tuyau/utils/-/utils-0.0.2.tgz", - "integrity": "sha512-l9ogTcydt+OSxIy0871LiazY+22Bc+AQ1b9nVf4HbYYnjEcZOCM0v3ZmSOcrXZyrlU/MPW/QLjzYjgWvyZRB2w==" + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/@tuyau/utils/-/utils-0.0.3.tgz", + "integrity": "sha512-/BFxr+RqHT0JhPSxBoh254cEOAkVrct3EQABiuXrBNicfRZPDltgB0/lh+V/MCpOcmbL/8LrbLLa7gyE0FEJYw==" }, "node_modules/@types/bcryptjs": { "version": "2.4.6", @@ -5509,9 +5458,9 @@ "integrity": "sha512-A0uYgOj3zNc4hNjHc5lYUfJQ/HVyBXiUMKdXd7ysclaE6k9oJdavQzODHuwjpUu2/boCP8afjQYi8z/GtvNCWA==" }, "node_modules/@types/chai": { - "version": "4.3.14", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.14.tgz", - "integrity": "sha512-Wj71sXE4Q4AkGdG9Tvq1u/fquNz9EdG4LIJMwVVII7ashjD/8cf8fyIfJAjRr6YcsXnSE8cOGQPq1gqeR8z+3w==", + "version": "4.3.16", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.16.tgz", + "integrity": "sha512-PatH4iOdyh3MyWtmHVFXLWCCIhUbopaltqddG9BzB+gMIzee2MJrvd+jouii9Z3wzQJruGWAm7WOMjgfG8hQlQ==", "dev": true }, "node_modules/@types/clamscan": { @@ -5675,12 +5624,6 @@ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true }, - "node_modules/@types/katex": { - "version": "0.16.7", - "resolved": "https://registry.npmjs.org/@types/katex/-/katex-0.16.7.tgz", - "integrity": "sha512-HMwFiRujE5PjrgwHQ25+bsLJgowjGjm5Z8FVSf0N6PwgJrwxH0QxzHYDcKsTfV3wva0vzrpqMTJS2jXPr5BMEQ==", - "dev": true - }, "node_modules/@types/leaflet": { "version": "1.9.12", "resolved": "https://registry.npmjs.org/@types/leaflet/-/leaflet-1.9.12.tgz", @@ -5690,25 +5633,11 @@ "@types/geojson": "*" } }, - "node_modules/@types/lodash": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.0.tgz", - "integrity": "sha512-t7dhREVv6dbNj0q17X12j7yDG4bD/DHYX7o5/DbDxobP0HnGPgpRz2Ej77aL7TZT3DSw13fqUTj8J4mMnqa7WA==", - "dev": true - }, - "node_modules/@types/lodash-es": { - "version": "4.17.12", - "resolved": "https://registry.npmjs.org/@types/lodash-es/-/lodash-es-4.17.12.tgz", - "integrity": "sha512-0NgftHUcV4v34VhXm8QBSftKVXtbkBG3ViCjs6+eJ5a6y6Mi/jiFGPc1sC7QK+9BFhWrURE3EOggmWaSxL9OzQ==", - "dev": true, - "dependencies": { - "@types/lodash": "*" - } - }, "node_modules/@types/luxon": { "version": "3.4.2", "resolved": "https://registry.npmjs.org/@types/luxon/-/luxon-3.4.2.tgz", - "integrity": "sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==" + "integrity": "sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==", + "dev": true }, "node_modules/@types/methods": { "version": "1.1.4", @@ -5729,9 +5658,9 @@ "dev": true }, "node_modules/@types/node": { - "version": "20.12.7", - "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.7.tgz", - "integrity": "sha512-wq0cICSkRLVaf3UGLMGItu/PtdY7oaXaI/RVU+xliKVOtRna3PRY57ZDfztpDL0n11vfymMUnXv8QwYCO7L1wg==", + "version": "20.12.12", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.12.12.tgz", + "integrity": "sha512-eWLDGF/FOSPtAvEqeRAQ4C8LSA7M1I7i0ky1I8U7kD1J5ITyW3AsRhQrKVoWf5pFKZ2kILsEGJhsI9r93PYnOw==", "dependencies": { "undici-types": "~5.26.4" } @@ -5886,9 +5815,9 @@ "dev": true }, "node_modules/@types/superagent": { - "version": "8.1.6", - "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.6.tgz", - "integrity": "sha512-yzBOv+6meEHSzV2NThYYOA6RtqvPr3Hbob9ZLp3i07SH27CrYVfm8CrF7ydTmidtelsFiKx2I4gZAiAOamGgvQ==", + "version": "8.1.7", + "resolved": "https://registry.npmjs.org/@types/superagent/-/superagent-8.1.7.tgz", + "integrity": "sha512-NmIsd0Yj4DDhftfWvvAku482PZum4DBW7U51OvS8gvOkDDY0WT1jsVyDV3hK+vplrsYw8oDwi9QxOM7U68iwww==", "devOptional": true, "dependencies": { "@types/cookiejar": "^2.1.5", @@ -5907,9 +5836,9 @@ } }, "node_modules/@types/validator": { - "version": "13.11.9", - "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.9.tgz", - "integrity": "sha512-FCTsikRozryfayPuiI46QzH3fnrOoctTjvOYZkho9BTFLCOZ2rgZJHMOVgCOfttjPJcgOx52EpkY0CMfy87MIw==" + "version": "13.11.10", + "resolved": "https://registry.npmjs.org/@types/validator/-/validator-13.11.10.tgz", + "integrity": "sha512-e2PNXoXLr6Z+dbfx5zSh9TRlXJrELycxiaXznp4S5+D2M3b9bqJEitNHA5923jhnB2zzFiZHa2f0SI1HoIahpg==" }, "node_modules/@types/ws": { "version": "8.5.10", @@ -5935,67 +5864,6 @@ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", "dev": true }, - "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", - "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", - "dev": true, - "dependencies": { - "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/type-utils": "5.62.0", - "@typescript-eslint/utils": "5.62.0", - "debug": "^4.3.4", - "graphemer": "^1.4.0", - "ignore": "^5.2.0", - "natural-compare-lite": "^1.4.0", - "semver": "^7.3.7", - "tsutils": "^3.21.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "@typescript-eslint/parser": "^5.0.0", - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, - "node_modules/@typescript-eslint/parser": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", - "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", - "dev": true, - "dependencies": { - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "debug": "^4.3.4" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } - } - }, "node_modules/@typescript-eslint/scope-manager": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.62.0.tgz", @@ -6040,6 +5908,54 @@ } } }, + "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/@typescript-eslint/type-utils/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/@typescript-eslint/types": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.62.0.tgz", @@ -6109,54 +6025,6 @@ "node": ">=8" } }, - "node_modules/@typescript-eslint/utils": { - "version": "5.62.0", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", - "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", - "dev": true, - "dependencies": { - "@eslint-community/eslint-utils": "^4.2.0", - "@types/json-schema": "^7.0.9", - "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.62.0", - "@typescript-eslint/types": "5.62.0", - "@typescript-eslint/typescript-estree": "5.62.0", - "eslint-scope": "^5.1.1", - "semver": "^7.3.7" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/typescript-eslint" - }, - "peerDependencies": { - "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", - "dev": true, - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" - }, - "engines": { - "node": ">=8.0.0" - } - }, - "node_modules/@typescript-eslint/utils/node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "engines": { - "node": ">=4.0" - } - }, "node_modules/@typescript-eslint/visitor-keys": { "version": "5.62.0", "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.62.0.tgz", @@ -6194,37 +6062,63 @@ "vite": "^2.8.1 || 3 || 4 || 5" } }, + "node_modules/@vinejs/compiler": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@vinejs/compiler/-/compiler-2.5.0.tgz", + "integrity": "sha512-hg4ekaB5Y2zh+IWzBiC/WCDWrIfpVnKu/ubUvelKlidc/VbulsexoFRw5kJGHZenPVI5YzNnDeTdYSALkTV7jQ==", + "engines": { + "node": ">=18.0.0" + } + }, + "node_modules/@vinejs/vine": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@vinejs/vine/-/vine-2.0.0.tgz", + "integrity": "sha512-NqgT4B2uo4mMsGI8LJdpuXNnan7F3xm10+kHaXpqI0PCYpn7+Xiic6av586mmj747/qZ3iR8o4C9cL54WU1fWw==", + "dependencies": { + "@poppinss/macroable": "^1.0.2", + "@types/validator": "^13.11.9", + "@vinejs/compiler": "^2.5.0", + "camelcase": "^8.0.0", + "dayjs": "^1.11.10", + "dlv": "^1.1.3", + "normalize-url": "^8.0.1", + "validator": "^13.11.0" + }, + "engines": { + "node": ">=18.16.0" + } + }, "node_modules/@vue/compiler-core": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.26.tgz", - "integrity": "sha512-N9Vil6Hvw7NaiyFUFBPXrAyETIGlQ8KcFMkyk6hW1Cl6NvoqvP+Y8p1Eqvx+UdqsnrnI9+HMUEJegzia3mhXmQ==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.27.tgz", + "integrity": "sha512-E+RyqY24KnyDXsCuQrI+mlcdW3ALND6U7Gqa/+bVwbcpcR3BRRIckFoz7Qyd4TTlnugtwuI7YgjbvsLmxb+yvg==", "dependencies": { "@babel/parser": "^7.24.4", - "@vue/shared": "3.4.26", + "@vue/shared": "3.4.27", "entities": "^4.5.0", "estree-walker": "^2.0.2", "source-map-js": "^1.2.0" } }, "node_modules/@vue/compiler-dom": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.26.tgz", - "integrity": "sha512-4CWbR5vR9fMg23YqFOhr6t6WB1Fjt62d6xdFPyj8pxrYub7d+OgZaObMsoxaF9yBUHPMiPFK303v61PwAuGvZA==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.27.tgz", + "integrity": "sha512-kUTvochG/oVgE1w5ViSr3KUBh9X7CWirebA3bezTbB5ZKBQZwR2Mwj9uoSKRMFcz4gSMzzLXBPD6KpCLb9nvWw==", "dependencies": { - "@vue/compiler-core": "3.4.26", - "@vue/shared": "3.4.26" + "@vue/compiler-core": "3.4.27", + "@vue/shared": "3.4.27" } }, "node_modules/@vue/compiler-sfc": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.26.tgz", - "integrity": "sha512-It1dp+FAOCgluYSVYlDn5DtZBxk1NCiJJfu2mlQqa/b+k8GL6NG/3/zRbJnHdhV2VhxFghaDq5L4K+1dakW6cw==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.27.tgz", + "integrity": "sha512-nDwntUEADssW8e0rrmE0+OrONwmRlegDA1pD6QhVeXxjIytV03yDqTey9SBDiALsvAd5U4ZrEKbMyVXhX6mCGA==", "dependencies": { "@babel/parser": "^7.24.4", - "@vue/compiler-core": "3.4.26", - "@vue/compiler-dom": "3.4.26", - "@vue/compiler-ssr": "3.4.26", - "@vue/shared": "3.4.26", + "@vue/compiler-core": "3.4.27", + "@vue/compiler-dom": "3.4.27", + "@vue/compiler-ssr": "3.4.27", + "@vue/shared": "3.4.27", "estree-walker": "^2.0.2", "magic-string": "^0.30.10", "postcss": "^8.4.38", @@ -6232,12 +6126,12 @@ } }, "node_modules/@vue/compiler-ssr": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.26.tgz", - "integrity": "sha512-FNwLfk7LlEPRY/g+nw2VqiDKcnDTVdCfBREekF8X74cPLiWHUX6oldktf/Vx28yh4STNy7t+/yuLoMBBF7YDiQ==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.27.tgz", + "integrity": "sha512-CVRzSJIltzMG5FcidsW0jKNQnNRYC8bT21VegyMMtHmhW3UOI7knmUehzswXLrExDLE6lQCZdrhD4ogI7c+vuw==", "dependencies": { - "@vue/compiler-dom": "3.4.26", - "@vue/shared": "3.4.26" + "@vue/compiler-dom": "3.4.27", + "@vue/shared": "3.4.27" } }, "node_modules/@vue/devtools-api": { @@ -6247,48 +6141,48 @@ "dev": true }, "node_modules/@vue/reactivity": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.26.tgz", - "integrity": "sha512-E/ynEAu/pw0yotJeLdvZEsp5Olmxt+9/WqzvKff0gE67tw73gmbx6tRkiagE/eH0UCubzSlGRebCbidB1CpqZQ==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.27.tgz", + "integrity": "sha512-kK0g4NknW6JX2yySLpsm2jlunZJl2/RJGZ0H9ddHdfBVHcNzxmQ0sS0b09ipmBoQpY8JM2KmUw+a6sO8Zo+zIA==", "dependencies": { - "@vue/shared": "3.4.26" + "@vue/shared": "3.4.27" } }, "node_modules/@vue/runtime-core": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.26.tgz", - "integrity": "sha512-AFJDLpZvhT4ujUgZSIL9pdNcO23qVFh7zWCsNdGQBw8ecLNxOOnPcK9wTTIYCmBJnuPHpukOwo62a2PPivihqw==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.27.tgz", + "integrity": "sha512-7aYA9GEbOOdviqVvcuweTLe5Za4qBZkUY7SvET6vE8kyypxVgaT1ixHLg4urtOlrApdgcdgHoTZCUuTGap/5WA==", "dependencies": { - "@vue/reactivity": "3.4.26", - "@vue/shared": "3.4.26" + "@vue/reactivity": "3.4.27", + "@vue/shared": "3.4.27" } }, "node_modules/@vue/runtime-dom": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.26.tgz", - "integrity": "sha512-UftYA2hUXR2UOZD/Fc3IndZuCOOJgFxJsWOxDkhfVcwLbsfh2CdXE2tG4jWxBZuDAs9J9PzRTUFt1PgydEtItw==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.27.tgz", + "integrity": "sha512-ScOmP70/3NPM+TW9hvVAz6VWWtZJqkbdf7w6ySsws+EsqtHvkhxaWLecrTorFxsawelM5Ys9FnDEMt6BPBDS0Q==", "dependencies": { - "@vue/runtime-core": "3.4.26", - "@vue/shared": "3.4.26", + "@vue/runtime-core": "3.4.27", + "@vue/shared": "3.4.27", "csstype": "^3.1.3" } }, "node_modules/@vue/server-renderer": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.26.tgz", - "integrity": "sha512-xoGAqSjYDPGAeRWxeoYwqJFD/gw7mpgzOvSxEmjWaFO2rE6qpbD1PC172YRpvKhrihkyHJkNDADFXTfCyVGhKw==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.27.tgz", + "integrity": "sha512-dlAMEuvmeA3rJsOMJ2J1kXU7o7pOxgsNHVr9K8hB3ImIkSuBrIdy0vF66h8gf8Tuinf1TK3mPAz2+2sqyf3KzA==", "dependencies": { - "@vue/compiler-ssr": "3.4.26", - "@vue/shared": "3.4.26" + "@vue/compiler-ssr": "3.4.27", + "@vue/shared": "3.4.27" }, "peerDependencies": { - "vue": "3.4.26" + "vue": "3.4.27" } }, "node_modules/@vue/shared": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.26.tgz", - "integrity": "sha512-Fg4zwR0GNnjzodMt3KRy2AWGMKQXByl56+4HjN87soxLNU9P5xcJkstAlIeEF3cU6UYOzmJl1tV0dVPGIljCnQ==" + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.27.tgz", + "integrity": "sha512-DL3NmY2OFlqmYYrzp39yi3LDkKxa5vZVwxWdQ3rG0ekuWscHraeIbnI8t+aZK7qhYqEqWKTUdijadunb9pnrgA==" }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", @@ -7054,6 +6948,18 @@ "webpack": ">=5.0.0" } }, + "node_modules/assets-webpack-plugin/node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/astring": { "version": "1.8.6", "resolved": "https://registry.npmjs.org/astring/-/astring-1.8.6.tgz", @@ -7071,12 +6977,6 @@ "retry": "0.13.1" } }, - "node_modules/async-validator": { - "version": "4.2.5", - "resolved": "https://registry.npmjs.org/async-validator/-/async-validator-4.2.5.tgz", - "integrity": "sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==", - "dev": true - }, "node_modules/asynckit": { "version": "0.4.0", "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", @@ -7544,12 +7444,11 @@ } }, "node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", - "dev": true, + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", "engines": { - "node": ">=10" + "node": ">=16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -7577,9 +7476,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001614", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001614.tgz", - "integrity": "sha512-jmZQ1VpmlRwHgdP1/uiKzgiAuGOfLEJsYFP4+GBou/QQ4U6IOJCB4NP1c+1p9RGLpwObcT94jA5/uO+F1vBbog==", + "version": "1.0.30001618", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001618.tgz", + "integrity": "sha512-p407+D1tIkDvsEAPS22lJxLQQaG8OTBEqo0KhzfABGk0TU4juBNDSfH0hyAp/HRyx+M8L17z/ltyhxh27FTfQg==", "dev": true, "funding": [ { @@ -7618,13 +7517,13 @@ } }, "node_modules/chai": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.0.tgz", - "integrity": "sha512-kDZ7MZyM6Q1DhR9jy7dalKohXQ2yrlXkk59CR52aRKxJrobmlBNqnFQxX9xOX8w+4mz8SYlKJa/7D7ddltFXCw==", + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/chai/-/chai-5.1.1.tgz", + "integrity": "sha512-pT1ZgP8rPNqUgieVaEY+ryQr6Q4HXNg8Ei9UnLUrjN4IA7dvQC5JB+/kxVcPNDHyBcc/26CXPkbNzq3qwrOEKA==", "dev": true, "dependencies": { "assertion-error": "^2.0.1", - "check-error": "^2.0.0", + "check-error": "^2.1.1", "deep-eql": "^5.0.1", "loupe": "^3.1.0", "pathval": "^2.0.0" @@ -7718,9 +7617,9 @@ } }, "node_modules/check-error": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.0.0.tgz", - "integrity": "sha512-tjLAOBHKVxtPoHe/SA7kNOMvhCRdCJ3vETdeY0RuAc9popf+hyaSV6ZEg9hr4cpWF7jmo/JSWEnLDrnijS9Tog==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/check-error/-/check-error-2.1.1.tgz", + "integrity": "sha512-OAlb+T7V4Op9OwdkjmguYRqncdlx5JiofwOAUkmTF+jNdHwzTaTs4sRAGpzLF3oOz5xAyDGrPgeIDFQmDOTiJw==", "dev": true, "engines": { "node": ">= 16" @@ -7864,9 +7763,9 @@ } }, "node_modules/cli-table3": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.4.tgz", - "integrity": "sha512-Lm3L0p+/npIQWNIiyF/nAn7T5dnOwR3xNTHXYEBFBFVPXzCVNZ5lqEC/1eo/EVfpDsQ1I+TX4ORPQgp+UI0CRw==", + "version": "0.6.5", + "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", + "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", "dependencies": { "string-width": "^4.2.0" }, @@ -8307,9 +8206,9 @@ } }, "node_modules/core-js-compat": { - "version": "3.37.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.0.tgz", - "integrity": "sha512-vYq4L+T8aS5UuFg4UwDhc7YNRWVeVZwltad9C/jV3R2LgVOpS9BDr7l/WL6BN0dbV3k1XejPTHqqEzJgsa0frA==", + "version": "3.37.1", + "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.37.1.tgz", + "integrity": "sha512-9TNiImhKvQqSUkOvk/mMRZzOANTiEVC7WaBNhHcKM7x+/5E1l5NvsysR19zuDQScE8k+kfQXWRN3AtS/eOSHpg==", "dev": true, "dependencies": { "browserslist": "^4.23.0" @@ -8568,22 +8467,6 @@ "url": "https://github.com/chalk/supports-color?sponsor=1" } }, - "node_modules/css-render": { - "version": "0.15.12", - "resolved": "https://registry.npmjs.org/css-render/-/css-render-0.15.12.tgz", - "integrity": "sha512-eWzS66patiGkTTik+ipO9qNGZ+uNuGyTmnz6/+EJIiFg8+3yZRpnMwgFo8YdXhQRsiePzehnusrxVvugNjXzbw==", - "dev": true, - "dependencies": { - "@emotion/hash": "~0.8.0", - "csstype": "~3.0.5" - } - }, - "node_modules/css-render/node_modules/csstype": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.0.11.tgz", - "integrity": "sha512-sa6P2wJ+CAbgyy4KFssIb/JNMLxFvKF1pCYCSXS8ZMuqZnMsrxqI2E5sPyoTpxoPU/gVZMzr2zjOfg8GIZOMsw==", - "dev": true - }, "node_modules/css-select": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", @@ -8819,31 +8702,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/date-fns": { - "version": "2.30.0", - "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz", - "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==", - "dev": true, - "dependencies": { - "@babel/runtime": "^7.21.0" - }, - "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" - } - }, - "node_modules/date-fns-tz": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/date-fns-tz/-/date-fns-tz-2.0.1.tgz", - "integrity": "sha512-fJCG3Pwx8HUoLhkepdsP7Z5RsucUi+ZBOxyM5d0ZZ6c4SdYustq0VMmOu6Wf7bli+yS/Jwp91TOCqn9jMcVrUA==", - "dev": true, - "peerDependencies": { - "date-fns": "2.x" - } - }, "node_modules/dateformat": { "version": "4.6.3", "resolved": "https://registry.npmjs.org/dateformat/-/dateformat-4.6.3.tgz", @@ -9293,8 +9151,7 @@ "node_modules/dlv": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz", - "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==", - "dev": true + "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==" }, "node_modules/dns-packet": { "version": "5.6.1", @@ -9514,9 +9371,9 @@ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==" }, "node_modules/electron-to-chromium": { - "version": "1.4.751", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.751.tgz", - "integrity": "sha512-2DEPi++qa89SMGRhufWTiLmzqyuGmNF3SK4+PQetW1JKiZdEpF4XQonJXJCzyuYSA6mauiMhbyVhqYAP45Hvfw==", + "version": "1.4.769", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.769.tgz", + "integrity": "sha512-bZu7p623NEA2rHTc9K1vykl57ektSPQYFFqQir8BOYf6EKOB+yIsbFB9Kpm7Cgt6tsLr9sRkqfqSZUw7LP1XxQ==", "dev": true }, "node_modules/emittery": { @@ -9566,9 +9423,9 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.16.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.0.tgz", - "integrity": "sha512-O+QWCviPNSSLAD9Ucn8Awv+poAkqn3T1XY5/N7kR7rQO9yfSGWkYZDwpJ+iKF7B8rxaQKWngSqACpgzeapSyoA==", + "version": "5.16.1", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.16.1.tgz", + "integrity": "sha512-4U5pNsuDl0EhuZpq46M5xPslstkviJuhrdobaRDBk2Jy2KO37FDAJl4lb2KlNabxT0m4MTK2UHNrsAcphE8nyw==", "dev": true, "dependencies": { "graceful-fs": "^4.2.4", @@ -9916,6 +9773,115 @@ "eslint": "^8.0.0" } }, + "node_modules/eslint-plugin-adonis/node_modules/@typescript-eslint/eslint-plugin": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.62.0.tgz", + "integrity": "sha512-TiZzBSJja/LbhNPvk6yc0JrX9XqhQ0hdh6M2svYfsHGejaKFIAGd9MQ+ERIMzLGlN/kZoYIgdxFV0PuljTKXag==", + "dev": true, + "dependencies": { + "@eslint-community/regexpp": "^4.4.0", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/type-utils": "5.62.0", + "@typescript-eslint/utils": "5.62.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.0", + "natural-compare-lite": "^1.4.0", + "semver": "^7.3.7", + "tsutils": "^3.21.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^5.0.0", + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-adonis/node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.62.0.tgz", + "integrity": "sha512-n8oxjeb5aIbPFEtmQxQYOLI0i9n5ySBEY/ZEHHZqKQSFnxio1rv6dthascc9dLuwrL0RC5mPCxB7vnAVGAYWAQ==", + "dev": true, + "dependencies": { + "@eslint-community/eslint-utils": "^4.2.0", + "@types/json-schema": "^7.0.9", + "@types/semver": "^7.3.12", + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "eslint-scope": "^5.1.1", + "semver": "^7.3.7" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/eslint-plugin-adonis/node_modules/@typescript-eslint/parser": { + "version": "5.62.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.62.0.tgz", + "integrity": "sha512-VlJEV0fOQ7BExOsHYAGrgbEiZoi8D+Bl2+f6V2RrXerRSylnp+ZBHmPvaIa8cz0Ajx7WO7Z5RqfgYg7ED1nRhA==", + "dev": true, + "dependencies": { + "@typescript-eslint/scope-manager": "5.62.0", + "@typescript-eslint/types": "5.62.0", + "@typescript-eslint/typescript-estree": "5.62.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^6.0.0 || ^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } + } + }, + "node_modules/eslint-plugin-adonis/node_modules/eslint-scope": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", + "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "dev": true, + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^4.1.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/eslint-plugin-adonis/node_modules/estraverse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", + "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", + "dev": true, + "engines": { + "node": ">=4.0" + } + }, "node_modules/eslint-plugin-prettier": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.1.3.tgz", @@ -10206,12 +10172,6 @@ "node": ">=0.8.x" } }, - "node_modules/evtd": { - "version": "0.2.4", - "resolved": "https://registry.npmjs.org/evtd/-/evtd-0.2.4.tgz", - "integrity": "sha512-qaeGN5bx63s/AXgQo8gj6fBkxge+OoLddLniox5qtLAEY5HSnuSlISXVPxnSae1dWblvTh4/HoMIB+mbMsvZzw==", - "dev": true - }, "node_modules/execa": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", @@ -10780,9 +10740,9 @@ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" }, "node_modules/fs-monkey": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.5.tgz", - "integrity": "sha512-8uMbBjrhzW76TYgEV27Y5E//W2f/lTFmx78P2w19FZSxarhI/798APGQyuGCwmkNxgwGRhrLfvWyLBvNtuOmew==" + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz", + "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==" }, "node_modules/fs-readdir-recursive": { "version": "1.1.0", @@ -11271,15 +11231,6 @@ "node": ">=8" } }, - "node_modules/highlight.js": { - "version": "11.9.0", - "resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-11.9.0.tgz", - "integrity": "sha512-fJ7cW7fQGCYAkgv4CPfwFHrfd/cLS4Hau96JuJ+ZTOWhjnhoeN1ub1tFmALm/+lW5z4WCAuAV9bm05AP0mS6Gw==", - "dev": true, - "engines": { - "node": ">=12.0.0" - } - }, "node_modules/hpack.js": { "version": "2.1.6", "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz", @@ -12872,12 +12823,6 @@ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==" }, - "node_modules/lodash-es": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", - "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", - "dev": true - }, "node_modules/lodash.clonedeep": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.clonedeep/-/lodash.clonedeep-4.5.0.tgz", @@ -13024,9 +12969,9 @@ } }, "node_modules/loupe": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.0.tgz", - "integrity": "sha512-qKl+FrLXUhFuHUoDJG7f8P8gEMHq9NFS0c6ghXG1J0rldmZFQZoNVv/vyirE9qwCIhWZDsvEFd1sbFu3GvRQFg==", + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/loupe/-/loupe-3.1.1.tgz", + "integrity": "sha512-edNu/8D5MKVfGVFRhFf8aAxiTM6Wumfz5XsaatSxlD3w4R1d/WEKUTydCdPGbl9K7QG/Ca3GnDV2sIKIpXRQcw==", "dev": true, "dependencies": { "get-func-name": "^2.0.1" @@ -13405,36 +13350,6 @@ "thenify-all": "^1.0.0" } }, - "node_modules/naive-ui": { - "version": "2.38.1", - "resolved": "https://registry.npmjs.org/naive-ui/-/naive-ui-2.38.1.tgz", - "integrity": "sha512-AnU1FQ7K/CbhguAX++V4kCFjk7h7RvWt4nvZPRjORMpq+fUIlzD+EcQ5Cv1VqDloNF8+eMv4Akc2Ogacc9S+5A==", - "dev": true, - "dependencies": { - "@css-render/plugin-bem": "^0.15.12", - "@css-render/vue3-ssr": "^0.15.12", - "@types/katex": "^0.16.2", - "@types/lodash": "^4.14.198", - "@types/lodash-es": "^4.17.9", - "async-validator": "^4.2.5", - "css-render": "^0.15.12", - "csstype": "^3.1.3", - "date-fns": "^2.30.0", - "date-fns-tz": "^2.0.0", - "evtd": "^0.2.4", - "highlight.js": "^11.8.0", - "lodash": "^4.17.21", - "lodash-es": "^4.17.21", - "seemly": "^0.3.8", - "treemate": "^0.3.11", - "vdirs": "^0.1.8", - "vooks": "^0.2.12", - "vueuc": "^0.4.58" - }, - "peerDependencies": { - "vue": "^3.0.0" - } - }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -13976,11 +13891,11 @@ } }, "node_modules/parse-imports": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-1.1.2.tgz", - "integrity": "sha512-UgTSNWlBvx+f4nxVSH3fOyJPJKol8GkFuG8mN8q9FqtmJgwaEx0azPRlXXX0klNlRxoP2gwme00TPDSm6rm/IA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/parse-imports/-/parse-imports-1.2.0.tgz", + "integrity": "sha512-K5aG9cextqjAlyevwuSMjWPbBr+X8xGgfHS4VopbKC1u3jLndRGl2CoUHMTvuD6LIg4di5TzH/Pw9+XZyTjI/w==", "dependencies": { - "es-module-lexer": "^1.3.0", + "es-module-lexer": "^1.5.2", "slashes": "^3.0.12" }, "engines": { @@ -14073,16 +13988,16 @@ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" }, "node_modules/path-scurry": { - "version": "1.10.2", - "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.10.2.tgz", - "integrity": "sha512-7xTavNy5RQXnsjANvVvMkEjvloOinkAjv/Z6Ildz9v2RinZ4SBKTWFOVRbaF8p0vpHnyjV/UwNDdKuUv6M5qcA==", + "version": "1.11.1", + "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz", + "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==", "dev": true, "dependencies": { "lru-cache": "^10.2.0", "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -14220,9 +14135,9 @@ } }, "node_modules/picocolors": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.0.tgz", - "integrity": "sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==" + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.0.1.tgz", + "integrity": "sha512-anP1Z8qwhkbmu7MFP5iTt+wQKXgwzf7zTyGlcdzabySa9vd0Xt392U0rVmz9poOaBj0uHJKyyo9/upk0HrEQew==" }, "node_modules/picomatch": { "version": "4.0.2", @@ -16092,12 +16007,6 @@ "resolved": "https://registry.npmjs.org/secure-json-parse/-/secure-json-parse-2.7.0.tgz", "integrity": "sha512-6aU+Rwsezw7VR8/nyvKTx8QpWH9FrcYiXXlqC4z5d5XQBDRqtbfsRjnwGyqbi3gddNtWHuEk9OANUotL26qKUw==" }, - "node_modules/seemly": { - "version": "0.3.8", - "resolved": "https://registry.npmjs.org/seemly/-/seemly-0.3.8.tgz", - "integrity": "sha512-MW8Qs6vbzo0pHmDpFSYPna+lwpZ6Zk1ancbajw/7E8TKtHdV+1DfZZD+kKJEhG/cAoB/i+LiT+5msZOqj0DwRA==", - "dev": true - }, "node_modules/select-hose": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz", @@ -16118,12 +16027,9 @@ } }, "node_modules/semver": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.0.tgz", - "integrity": "sha512-EnwXhrlwXMk9gKu5/flx5sv/an57AkRplG3hTK68W7FRDN+k+OWBj65M7719OkA82XLBxrcX0KSHj+X5COhOVg==", - "dependencies": { - "lru-cache": "^6.0.0" - }, + "version": "7.6.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.2.tgz", + "integrity": "sha512-FNAIBWCx9qcRhoHcgcJ0gvU7SN1lYU2ZXuSfl04bSC5OpvDHFyJCjdNHomPXxjQlCBU67YW64PzY7/VIEH7F2w==", "bin": { "semver": "bin/semver.js" }, @@ -16131,22 +16037,6 @@ "node": ">=10" } }, - "node_modules/semver/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==" - }, "node_modules/send": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz", @@ -16922,22 +16812,22 @@ } }, "node_modules/sucrase/node_modules/glob": { - "version": "10.3.12", - "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.12.tgz", - "integrity": "sha512-TCNv8vJ+xz4QiqTpfOJA7HvYv+tNIRHKfUWw/q+v2jdgN4ebz+KY9tGx5J4rHP0o84mNP+ApH66HRX8us3Khqg==", + "version": "10.3.15", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.3.15.tgz", + "integrity": "sha512-0c6RlJt1TICLyvJYIApxb8GsXoai0KUP7AxKKAtsYXdgJR1mGEUa7DgwShbdk1nly0PYoZj01xd4hzbq3fsjpw==", "dev": true, "dependencies": { "foreground-child": "^3.1.0", "jackspeak": "^2.3.6", "minimatch": "^9.0.1", "minipass": "^7.0.4", - "path-scurry": "^1.10.2" + "path-scurry": "^1.11.0" }, "bin": { "glob": "dist/esm/bin.mjs" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=16 || 14 >=14.18" }, "funding": { "url": "https://github.com/sponsors/isaacs" @@ -16959,9 +16849,9 @@ } }, "node_modules/sucrase/node_modules/minipass": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.0.4.tgz", - "integrity": "sha512-jYofLM5Dam9279rdkWzqHozUo4ybjdZmCsDHePy5V/PbBcVMiSZR97gmAy45aqi8CK1lG2ECd356FU86avfwUQ==", + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.1.tgz", + "integrity": "sha512-UZ7eQ+h8ywIRAW1hIEl2AqdwzJucU/Kp59+8kkZeSvafXhZjul247BvIJjEVFVeON6d7lM46XX1HXCduKAS8VA==", "dev": true, "engines": { "node": ">=16 || 14 >=14.17" @@ -17037,9 +16927,9 @@ } }, "node_modules/svgo": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.2.0.tgz", - "integrity": "sha512-4PP6CMW/V7l/GmKRKzsLR8xxjdHTV4IMvhTnpuHwwBazSIlw5W/5SmPjN8Dwyt7lKbSJrRDgp4t9ph0HgChFBQ==", + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-3.3.2.tgz", + "integrity": "sha512-OoohrmuUlBs8B8o6MB2Aevn+pRIH9zDALSR+6hhqVfa6fRwG/Qw9VUMSMW9VNg2CFc/MTIfabtdOVl9ODIJjpw==", "dev": true, "dependencies": { "@trysound/sax": "0.2.0", @@ -17561,12 +17451,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/treemate": { - "version": "0.3.11", - "resolved": "https://registry.npmjs.org/treemate/-/treemate-0.3.11.tgz", - "integrity": "sha512-M8RGFoKtZ8dF+iwJfAJTOH/SM4KluKOKRJpjCMhI8bG3qB74zrFoArKZ62ll0Fr3mqkMJiQOmWYkdYgDeITYQg==", - "dev": true - }, "node_modules/truncatise": { "version": "0.0.8", "resolved": "https://registry.npmjs.org/truncatise/-/truncatise-0.0.8.tgz", @@ -17999,9 +17883,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz", - "integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==", + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.16.tgz", + "integrity": "sha512-KVbTxlBYlckhF5wgfyZXTWnMn7MMZjMu9XG8bPlliUOP9ThaF4QnhP8qrjrH7DRzHfSk0oQv1wToW+iA5GajEQ==", "dev": true, "funding": [ { @@ -18018,8 +17902,8 @@ } ], "dependencies": { - "escalade": "^3.1.1", - "picocolors": "^1.0.0" + "escalade": "^3.1.2", + "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" @@ -18095,9 +17979,9 @@ "dev": true }, "node_modules/validator": { - "version": "13.11.0", - "resolved": "https://registry.npmjs.org/validator/-/validator-13.11.0.tgz", - "integrity": "sha512-Ii+sehpSfZy+At5nPdnyMhx78fEoPDkR2XW/zimHEL3MyGJQOCQ7WeP20jPYRz7ZCpcKLB21NxuXHF3bxjStBQ==", + "version": "13.12.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-13.12.0.tgz", + "integrity": "sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==", "engines": { "node": ">= 0.10" } @@ -18110,22 +17994,10 @@ "node": ">= 0.8" } }, - "node_modules/vdirs": { - "version": "0.1.8", - "resolved": "https://registry.npmjs.org/vdirs/-/vdirs-0.1.8.tgz", - "integrity": "sha512-H9V1zGRLQZg9b+GdMk8MXDN2Lva0zx72MPahDKc30v+DtwKjfyOSXWRIX4t2mhDubM1H09gPhWeth/BJWPHGUw==", - "dev": true, - "dependencies": { - "evtd": "^0.2.2" - }, - "peerDependencies": { - "vue": "^3.0.11" - } - }, "node_modules/vite": { - "version": "5.2.10", - "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.10.tgz", - "integrity": "sha512-PAzgUZbP7msvQvqdSD+ErD5qGnSFiGOoWmV5yAKUEI0kdhjbH6nMWVyZQC/hSc4aXwc0oJ9aEdIiF9Oje0JFCw==", + "version": "5.2.11", + "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.11.tgz", + "integrity": "sha512-HndV31LWW05i1BLPMUCE1B9E9GFbOu1MbenhS58FuK6owSO5qHm7GiCotrNY1YE5rMeQSFBGmT5ZaLEjFizgiQ==", "peer": true, "dependencies": { "esbuild": "^0.20.1", @@ -18192,28 +18064,16 @@ "vite": "^2.9.0 || ^3.0.0 || ^4.0.0 || ^5.0.0" } }, - "node_modules/vooks": { - "version": "0.2.12", - "resolved": "https://registry.npmjs.org/vooks/-/vooks-0.2.12.tgz", - "integrity": "sha512-iox0I3RZzxtKlcgYaStQYKEzWWGAduMmq+jS7OrNdQo1FgGfPMubGL3uGHOU9n97NIvfFDBGnpSvkWyb/NSn/Q==", - "dev": true, - "dependencies": { - "evtd": "^0.2.2" - }, - "peerDependencies": { - "vue": "^3.0.0" - } - }, "node_modules/vue": { - "version": "3.4.26", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.26.tgz", - "integrity": "sha512-bUIq/p+VB+0xrJubaemrfhk1/FiW9iX+pDV+62I/XJ6EkspAO9/DXEjbDFoe8pIfOZBqfk45i9BMc41ptP/uRg==", + "version": "3.4.27", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.27.tgz", + "integrity": "sha512-8s/56uK6r01r1icG/aEOHqyMVxd1bkYcSe9j8HcKtr/xTOFWvnzIVTehNW+5Yt89f+DLBe4A569pnZLS5HzAMA==", "dependencies": { - "@vue/compiler-dom": "3.4.26", - "@vue/compiler-sfc": "3.4.26", - "@vue/runtime-dom": "3.4.26", - "@vue/server-renderer": "3.4.26", - "@vue/shared": "3.4.26" + "@vue/compiler-dom": "3.4.27", + "@vue/compiler-sfc": "3.4.27", + "@vue/runtime-dom": "3.4.27", + "@vue/server-renderer": "3.4.27", + "@vue/shared": "3.4.27" }, "peerDependencies": { "typescript": "*" @@ -18327,24 +18187,6 @@ "vue": "^3.0.1" } }, - "node_modules/vueuc": { - "version": "0.4.58", - "resolved": "https://registry.npmjs.org/vueuc/-/vueuc-0.4.58.tgz", - "integrity": "sha512-Wnj/N8WbPRSxSt+9ji1jtDHPzda5h2OH/0sFBhvdxDRuyCZbjGg3/cKMaKqEoe+dErTexG2R+i6Q8S/Toq1MYg==", - "dev": true, - "dependencies": { - "@css-render/vue3-ssr": "^0.15.10", - "@juggle/resize-observer": "^3.3.1", - "css-render": "^0.15.10", - "evtd": "^0.2.4", - "seemly": "^0.3.6", - "vdirs": "^0.1.4", - "vooks": "^0.2.4" - }, - "peerDependencies": { - "vue": "^3.0.11" - } - }, "node_modules/watchpack": { "version": "2.4.1", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.1.tgz", diff --git a/package.json b/package.json index 4e24515..f5e99eb 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "@mdi/js": "^7.1.96", "@poppinss/utils": "^6.7.2", "@swc/core": "^1.4.2", - "@symfony/webpack-encore": "^4.5.0", + "@symfony/webpack-encore": "^4.6.1", "@tailwindcss/forms": "^0.5.2", "@types/bcryptjs": "^2.4.6", "@types/clamscan": "^2.0.4", @@ -53,15 +53,14 @@ "babel-preset-typescript-vue3": "^2.0.17", "chart.js": "^4.2.0", "dotenv-webpack": "^8.0.1", - "eslint": "^8.32.0", + "eslint": "^8.57.0", "eslint-config-prettier": "^9.0.0", "eslint-plugin-adonis": "^2.1.1", "eslint-plugin-prettier": "^5.0.0-alpha.2", - "naive-ui": "^2.35.0", "numeral": "^2.0.6", "pinia": "^2.0.30", "pino-pretty": "^11.0.0", - "postcss-loader": "^7.3.0", + "postcss-loader": "^7.3.4", "prettier": "^3.0.0", "supertest": "^6.3.3", "tailwindcss": "^3.2.4", @@ -85,7 +84,6 @@ "@adonisjs/session": "^7.1.1", "@adonisjs/shield": "^8.1.1", "@adonisjs/static": "^1.1.1", - "@adonisjs/validator": "^13.0.2", "@eidellev/adonis-stardust": "^3.0.0", "@fontsource/archivo-black": "^5.0.1", "@fontsource/inter": "^5.0.1", @@ -93,6 +91,7 @@ "@inertiajs/vue3": "^1.0.0", "@opensearch-project/opensearch": "^2.4.0", "@phc/format": "^1.0.0", + "@vinejs/vine": "^2.0.0", "bcrypt": "^5.1.1", "bcryptjs": "^2.4.3", "clamscan": "^2.1.2", diff --git a/resources/js/Pages/Admin/Role/Edit.vue b/resources/js/Pages/Admin/Role/Edit.vue index e7814de..29e88d4 100644 --- a/resources/js/Pages/Admin/Role/Edit.vue +++ b/resources/js/Pages/Admin/Role/Edit.vue @@ -88,6 +88,10 @@ const submit = async () => { +
+ + {{ form.errors.permissions.join(', ') }} +