Files
cosmos-explorer/src/workers/upload/index.ts
2021-01-20 09:15:01 -06:00

147 lines
4.3 KiB
TypeScript

import "babel-polyfill";
import { DocumentClientParams, UploadDetailsRecord, UploadDetails } from "./definitions";
import { client } from "../../Common/CosmosClient";
import { configContext, updateConfigContext } from "../../ConfigContext";
import { updateUserContext } from "../../UserContext";
import { getErrorMessage } from "../../Common/ErrorHandlingUtils";
let numUploadsSuccessful = 0;
let numUploadsFailed = 0;
let numDocuments = 0;
let numFiles = 0;
let numFilesProcessed = 0;
let fileUploadDetails: { [key: string]: UploadDetailsRecord } = {};
let databaseId: string;
let containerId: string;
onerror = (event: ProgressEvent) => {
postMessage(
{
numUploadsSuccessful: numUploadsSuccessful,
numUploadsFailed: numUploadsFailed,
uploadDetails: transformDetailsMap(fileUploadDetails),
// TODO: Typescript complains about event.error below
runtimeError: (event as any).error.message,
},
undefined
);
};
onmessage = (event: MessageEvent) => {
const files: FileList = event.data.files;
const clientParams: DocumentClientParams = event.data.documentClientParams;
containerId = clientParams.containerId;
databaseId = clientParams.databaseId;
updateUserContext({
masterKey: clientParams.masterKey,
endpoint: clientParams.endpoint,
accessToken: clientParams.accessToken,
databaseAccount: clientParams.databaseAccount,
});
updateConfigContext({
platform: clientParams.platform,
});
if (!!files && files.length > 0) {
numFiles = files.length;
for (let i = 0; i < numFiles; i++) {
fileUploadDetails[files[i].name] = {
fileName: files[i].name,
numSucceeded: 0,
numFailed: 0,
errors: [],
};
uploadFile(files[i]);
}
} else {
postMessage(
{
runtimeError: "No files specified",
},
undefined
);
}
};
function uploadFile(file: File): void {
const reader = new FileReader();
reader.onload = (evt: any): void => {
numFilesProcessed++;
const fileData: string = evt.target.result;
createDocumentsFromFile(file.name, fileData);
};
reader.onerror = (evt: ProgressEvent): void => {
numFilesProcessed++;
// TODO: Typescript complains about event.error below
recordUploadDetailErrorForFile(file.name, (evt as any).error.message);
transmitResultIfUploadComplete();
};
reader.readAsText(file);
}
function createDocumentsFromFile(fileName: string, documentContent: string): void {
try {
const content = JSON.parse(documentContent);
const triggerCreateDocument: (documentContent: any) => void = (documentContent: any) => {
client()
.database(databaseId)
.container(containerId)
.items.create(documentContent)
.then((savedDoc) => {
fileUploadDetails[fileName].numSucceeded++;
numUploadsSuccessful++;
})
.catch((error) => {
console.error(error);
recordUploadDetailErrorForFile(fileName, getErrorMessage(error));
numUploadsFailed++;
})
.finally(() => {
transmitResultIfUploadComplete();
});
};
if (Array.isArray(content)) {
numDocuments = numDocuments + content.length;
for (let i = 0; i < content.length; i++) {
triggerCreateDocument(content[i]);
}
} else {
numDocuments = numDocuments + 1;
triggerCreateDocument(content);
}
} catch (e) {
console.log(e);
recordUploadDetailErrorForFile(fileName, e.message);
transmitResultIfUploadComplete();
}
}
function transmitResultIfUploadComplete(): void {
if (numFilesProcessed === numFiles && numUploadsFailed + numUploadsSuccessful === numDocuments) {
postMessage(
{
numUploadsSuccessful: numUploadsSuccessful,
numUploadsFailed: numUploadsFailed,
uploadDetails: transformDetailsMap(fileUploadDetails),
},
undefined
);
}
}
function recordUploadDetailErrorForFile(fileName: string, error: any): void {
fileUploadDetails[fileName].errors.push(error);
fileUploadDetails[fileName].numFailed++;
}
function transformDetailsMap(map: any): UploadDetails {
let transformedResult: UploadDetailsRecord[] = [];
Object.keys(map).forEach((key: string) => {
transformedResult.push(map[key]);
});
return { data: transformedResult };
}