feat(backend): Verwerking van leerobjecten in ZIP-formaat.
This commit is contained in:
parent
509dd6bfab
commit
86ba4ea11e
4 changed files with 192 additions and 1 deletions
|
@ -2,7 +2,13 @@ import dwengoApiLearningObjectProvider from './dwengo-api-learning-object-provid
|
|||
import { LearningObjectProvider } from './learning-object-provider.js';
|
||||
import { envVars, getEnvVar } from '../../util/envVars.js';
|
||||
import databaseLearningObjectProvider from './database-learning-object-provider.js';
|
||||
import { FilteredLearningObject, LearningObjectIdentifierDTO, LearningPathIdentifier } from '@dwengo-1/common/interfaces/learning-content';
|
||||
import {
|
||||
FilteredLearningObject,
|
||||
LearningObjectIdentifierDTO,
|
||||
LearningPathIdentifier
|
||||
} from '@dwengo-1/common/interfaces/learning-content';
|
||||
import {getLearningObjectRepository} from "../../data/repositories";
|
||||
import {processLearningObjectZip} from "./learning-object-zip-processing-service";
|
||||
|
||||
function getProvider(id: LearningObjectIdentifierDTO): LearningObjectProvider {
|
||||
if (id.hruid.startsWith(getEnvVar(envVars.UserContentPrefix))) {
|
||||
|
@ -42,6 +48,21 @@ const learningObjectService = {
|
|||
async getLearningObjectHTML(id: LearningObjectIdentifierDTO): Promise<string | null> {
|
||||
return getProvider(id).getLearningObjectHTML(id);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Store the learning object in the given zip file in the database.
|
||||
*/
|
||||
async storeLearningObject(learningObjectPath: string): Promise<void> {
|
||||
const learningObjectRepository = getLearningObjectRepository();
|
||||
const learningObject = await processLearningObjectZip(learningObjectPath);
|
||||
|
||||
if (!learningObject.hruid.startsWith(getEnvVar(envVars.UserContentPrefix))) {
|
||||
throw Error("Learning object name must start with the user content prefix!");
|
||||
}
|
||||
|
||||
await learningObjectRepository.save(learningObject, {preventOverwrite: true});
|
||||
}
|
||||
};
|
||||
|
||||
export default learningObjectService;
|
||||
|
|
|
@ -0,0 +1,63 @@
|
|||
import unzipper from 'unzipper';
|
||||
import mime from 'mime-types';
|
||||
import {LearningObjectMetadata} from "@dwengo-1/common/dist/interfaces/learning-content";
|
||||
import {LearningObject} from "../../entities/content/learning-object.entity";
|
||||
import {getAttachmentRepository, getLearningObjectRepository} from "../../data/repositories";
|
||||
|
||||
/**
|
||||
* Process an uploaded zip file and construct a LearningObject from its contents.
|
||||
* @param filePath Path of the zip file to process.
|
||||
*/
|
||||
export async function processLearningObjectZip(filePath: string): Promise<LearningObject> {
|
||||
const learningObjectRepo = getLearningObjectRepository();
|
||||
const attachmentRepo = getAttachmentRepository();
|
||||
|
||||
const zip = await unzipper.Open.file(filePath);
|
||||
|
||||
let metadata: LearningObjectMetadata | null = null;
|
||||
const attachments: {name: string, content: Buffer}[] = [];
|
||||
let content: Buffer | null = null;
|
||||
|
||||
for (const file of zip.files) {
|
||||
if (file.type === "Directory") {
|
||||
throw Error("The learning object zip file should not contain directories.");
|
||||
} else if (file.path === "metadata.json") {
|
||||
metadata = await processMetadataJson(file);
|
||||
} else if (file.path.startsWith("index.")) {
|
||||
content = await processFile(file);
|
||||
} else {
|
||||
attachments.push({
|
||||
name: file.path,
|
||||
content: await processFile(file)
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
if (!metadata) {
|
||||
throw Error("Missing metadata.json file");
|
||||
}
|
||||
if (!content) {
|
||||
throw Error("Missing index file");
|
||||
}
|
||||
|
||||
const learningObject = learningObjectRepo.create(metadata);
|
||||
const attachmentEntities = attachments.map(it => attachmentRepo.create({
|
||||
name: it.name,
|
||||
content: it.content,
|
||||
mimeType: mime.lookup(it.name) || "text/plain",
|
||||
learningObject
|
||||
}))
|
||||
learningObject.attachments.push(...attachmentEntities);
|
||||
|
||||
return learningObject;
|
||||
}
|
||||
|
||||
async function processMetadataJson(file: unzipper.File): LearningObjectMetadata {
|
||||
const buf = await file.buffer();
|
||||
const content = buf.toString();
|
||||
return JSON.parse(content);
|
||||
}
|
||||
|
||||
async function processFile(file: unzipper.File): Promise<Buffer> {
|
||||
return await file.buffer();
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue