tethys.backend/app/models/file.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

183 lines
5.2 KiB
TypeScript

import { DateTime } from 'luxon';
import { column, hasMany, belongsTo, SnakeCaseNamingStrategy, computed } from '@adonisjs/lucid/orm';
import HashValue from './hash_value.js';
import Dataset from './dataset.js';
import BaseModel from './base_model.js';
import * as fs from 'fs';
import crypto from 'crypto';
// import Drive from '@ioc:Adonis/Core/Drive';
// import Drive from '@adonisjs/drive';
import drive from '#services/drive';
import type { HasMany } from "@adonisjs/lucid/types/relations";
import type { BelongsTo } from "@adonisjs/lucid/types/relations";
// import { TransactionClientContract } from "@adonisjs/lucid/database";
import { TransactionClientContract } from '@adonisjs/lucid/types/database';
export default class File extends BaseModel {
// private readonly _data: Uint8Array;
// private readonly _type: string;
// private readonly _size: number;
public static namingStrategy = new SnakeCaseNamingStrategy();
public static primaryKey = 'id';
public static table = 'document_files';
public static selfAssignPrimaryKey = false;
@column({
isPrimary: true,
})
public id: number;
@column({})
public document_id: number;
@column({})
public pathName: string;
@column()
public label: string;
@column()
public comment: string;
@column()
public mimeType: string;
@column()
public language: string;
@column()
public fileSize: number;
@column()
public visibleInOai: boolean;
@column()
public visibleInFrontdoor: boolean;
@column()
public sortOrder: number;
@column.dateTime({ autoCreate: true })
public createdAt: DateTime;
@column.dateTime({ autoCreate: true, autoUpdate: true })
public updatedAt: DateTime;
// public function dataset()
// {
// return $this->belongsTo(Dataset::class, 'document_id', 'id');
// }
@belongsTo(() => Dataset, {
foreignKey: 'document_id',
})
public dataset: BelongsTo<typeof Dataset>;
@hasMany(() => HashValue, {
foreignKey: 'file_id',
})
public hashvalues: HasMany<typeof HashValue>;
@computed({
serializeAs: 'filePath',
})
public get filePath() {
return `/storage/app/public/${this.pathName}`;
// const mainTitle = this.titles?.find((title) => title.type === 'Main');
// return mainTitle ? mainTitle.value : null;
}
@computed({
serializeAs: 'size',
})
public get size() {
return this.fileSize;
}
@computed({
serializeAs: 'type',
})
public get type() {
return this.mimeType;
}
@computed({
serializeAs: 'name',
})
get name(): string {
return this.label;
}
@computed({
serializeAs: 'lastModified',
})
get lastModified(): number {
return this.updatedAt.toUnixInteger(); //.toFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");
}
readonly webkitRelativePath: string = '';
// @computed({
// serializeAs: 'fileData',
// })
// public get fileData(): string {
// try {
// const fileContent: Buffer = fs.readFileSync(this.filePath);
// // Create a Blob from the file content
// // const blob = new Blob([fileContent], { type: this.type }); // Adjust
// // let fileSrc = URL.createObjectURL(blob);
// // return fileSrc;
// // create a JSON string that contains the data in the property "blob"
// const json = JSON.stringify({ blob: fileContent.toString('base64') });
// return json;
// } catch (err) {
// // console.error(`Error reading file: ${err}`);
// return '';
// }
// }
public async createHashValues(trx?: TransactionClientContract) {
const hashtypes: string[] = ['md5', 'sha512'];
for (const type of hashtypes) {
const hash = new HashValue();
hash.type = type;
const hashString = await this._checksumFile(this.filePath, type); // Assuming getRealHash is a method in the same model
hash.value = hashString;
// https://github.com/adonisjs/core/discussions/1872#discussioncomment-132289
const file: File = this;
if (trx) {
await file.useTransaction(trx).related('hashvalues').save(hash); // Save the hash value to the database
} else {
await file.related('hashvalues').save(hash); // Save the hash value to the database
}
}
}
public async delete() {
if (this.pathName) {
// Delete file from additional storage
await drive.delete(this.pathName);
}
// Call the original delete method of the BaseModel to remove the record from the database
await super.delete();
}
private async _checksumFile(path: string, hashName = 'md5'): Promise<string> {
return new Promise((resolve, reject) => {
const hash = crypto.createHash(hashName);
const stream = fs.createReadStream(path);
stream.on('error', (err) => reject(err));
stream.on('data', (chunk) => hash.update(chunk));
stream.on('end', () => resolve(hash.digest('hex')));
});
}
}