tethys.backend/providers/vinejs_provider.ts
Arno Kaimbacher 4c5a8f5a42
All checks were successful
CI / container-job (push) Successful in 43s
feat: update to vite.js, Refactor configuration files, remove unused assets, and clean up commented code:
- ace.js: use ts-node-maintained
- adonisrc.ts: load vite_provider, sett assetBundler to false, addd hooks property
- Dockerfile: change to node version 22
- package.json: remove babel depencies; add @swc/wasm, add vitejs/plugin-vue, add hot-hook, add vite,  update eslint-config-prettier, tailwindcss, ts-node-maintained
- new vite.config.js and config/vite.ts
- inertia.js
- improved own vinejs_provider.ts
- adapted app.css needed for vitejs
- adapted app.ts: new resolve method neede for vitejs
relocated resources/js/logo.svg
- remove Buffer import into FileUpload.vue
- Create.vue: improved submit needed for @inertiajs/vue3 form helper
- Edit.vue: mproved submit needed for @inertiajs/vue3 form helper
- kernel.ts: load vite_middleware
- formated rotes.ts file
- rewritten allowed_extensions_mimetypes.ts file (removed typescript errors)
2025-02-07 10:14:57 +01:00

192 lines
6.5 KiB
TypeScript

/*
|--------------------------------------------------------------------------
| Provider File - node ace make:provider vinejsProvider
|--------------------------------------------------------------------------
|*/
import type { ApplicationService } from '@adonisjs/core/types';
import vine, { symbols, BaseLiteralType, Vine } from '@vinejs/vine';
import type { FieldContext, FieldOptions } from '@vinejs/vine/types';
// import type { MultipartFile, FileValidationOptions } from '@adonisjs/bodyparser/types';
import type { MultipartFile } from '@adonisjs/core/bodyparser';
import type { FileValidationOptions } from '@adonisjs/core/types/bodyparser';
import { Request, RequestValidator } from '@adonisjs/core/http';
import MimeType from '#models/mime_type';
/**
* Validation options accepted by the "file" rule
*/
export type FileRuleValidationOptions = Partial<FileValidationOptions> | ((field: FieldContext) => Partial<FileValidationOptions>);
/**
* Extend VineJS
*/
declare module '@vinejs/vine' {
interface Vine {
myfile(options?: FileRuleValidationOptions): VineMultipartFile;
}
}
/**
* Extend HTTP request class
*/
declare module '@adonisjs/core/http' {
interface Request extends RequestValidator {}
}
/**
* Checks if the value is an instance of multipart file
* from bodyparser.
*/
export function isBodyParserFile(file: MultipartFile | unknown): boolean {
return !!(file && typeof file === 'object' && 'isMultipartFile' in file);
}
export async function getEnabledExtensions() {
const enabledExtensions = await MimeType.query().select('file_extension').where('enabled', true).exec();
const extensions = enabledExtensions
.map((extension) => {
return extension.file_extension.split('|');
})
.flat();
return extensions;
}
/**
* VineJS validation rule that validates the file to be an
* instance of BodyParser MultipartFile class.
*/
const isMultipartFile = vine.createRule(async (file: MultipartFile | unknown, options: FileRuleValidationOptions, field: FieldContext) => {
/**
* Report error when value is not a field multipart
* file object
*/
if (!isBodyParserFile(file)) {
field.report('The {{ field }} must be a file', 'file', field);
return;
}
// At this point, you can use type assertion to explicitly tell TypeScript that file is of type MultipartFile
const validatedFile = file as MultipartFile;
const validationOptions = typeof options === 'function' ? options(field) : options;
/**
* Set size when it's defined in the options and missing
* on the file instance
*/
if (validatedFile.sizeLimit === undefined && validationOptions.size) {
validatedFile.sizeLimit = validationOptions.size;
}
/**
* Set extensions when it's defined in the options and missing
* on the file instance
*/
// if (validatedFile.allowedExtensions === undefined && validationOptions.extnames) {
// validatedFile.allowedExtensions = validationOptions.extnames;
// }
if (validatedFile.allowedExtensions === undefined && validationOptions.extnames) {
validatedFile.allowedExtensions = await getEnabledExtensions();
}
/**
* wieder löschen
* Set extensions when it's defined in the options and missing
* on the file instance
*/
// if (file.clientNameSizeLimit === undefined && validationOptions.clientNameSizeLimit) {
// file.clientNameSizeLimit = validationOptions.clientNameSizeLimit;
// }
/**
* Validate file
*/
validatedFile.validate();
/**
* Report errors
*/
validatedFile.errors.forEach((error) => {
field.report(error.message, `file.${error.type}`, field, validationOptions);
});
});
const MULTIPART_FILE: typeof symbols.SUBTYPE = symbols.SUBTYPE;
export class VineMultipartFile extends BaseLiteralType<MultipartFile, MultipartFile, MultipartFile> {
[MULTIPART_FILE]: string;
// constructor(validationOptions?: FileRuleValidationOptions, options?: FieldOptions) {
// super(options, [isMultipartFile(validationOptions || {})]);
// this.validationOptions = validationOptions;
// this.#private = true;
// }
// clone(): this {
// return new VineMultipartFile(this.validationOptions, this.cloneOptions()) as this;
// }
// #private;
// constructor(validationOptions?: FileRuleValidationOptions, options?: FieldOptions, validations?: Validation<any>[]);
// clone(): this;
public validationOptions;
// extnames: (18) ['gpkg', 'htm', 'html', 'csv', 'txt', 'asc', 'c', 'cc', 'h', 'srt', 'tiff', 'pdf', 'png', 'zip', 'jpg', 'jpeg', 'jpe', 'xlsx']
// size: '512mb'
// public constructor(validationOptions?: FileRuleValidationOptions, options?: FieldOptions, validations?: Validation<any>[]) {
public constructor(validationOptions?: FileRuleValidationOptions, options?: FieldOptions) {
// super(options, validations);
super(options, [isMultipartFile(validationOptions || {})]);
this.validationOptions = validationOptions;
}
public clone(): any {
// return new VineMultipartFile(this.validationOptions, this.cloneOptions(), this.cloneValidations());
return new VineMultipartFile(this.validationOptions, this.cloneOptions());
}
}
export default class VinejsProvider {
protected app: ApplicationService;
constructor(app: ApplicationService) {
this.app = app;
this.app.usingVineJS = true;
}
/**
* Register bindings to the container
*/
register() {}
/**
* The container bindings have booted
*/
boot(): void {
// VineString.macro('translatedLanguage', function (this: VineString, options: Options) {
// return this.use(translatedLanguageRule(options));
// });
Vine.macro('myfile', function (this: Vine, options) {
return new VineMultipartFile(options);
});
/**
* The validate method can be used to validate the request
* data for the current request using VineJS validators
*/
Request.macro('validateUsing', function (this: Request, ...args) {
if (!this.ctx) {
throw new Error('HttpContext is not available');
}
return new RequestValidator(this.ctx).validateUsing(...args);
});
}
/**
* The application has been booted
*/
async start() {}
/**
* The process has been started
*/
async ready() {}
/**
* Preparing to shutdown the app
*/
async shutdown() {}
}