@bdelab/roar-firekit
Version:
A library to facilitate Firebase authentication and Cloud Firestore interaction for ROAR apps
106 lines (105 loc) • 6.3 kB
JavaScript
"use strict";
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.RoarTaskVariant = void 0;
const firestore_1 = require("firebase/firestore");
const util_1 = require("../util");
/**
* Class representing a ROAR task.
*/
class RoarTaskVariant {
/** Create a ROAR task
* @param {TaskVariantInput} input
* @param {Firestore} input.db - The assessment Firestore instance to which this task'data will be written
* @param {string} input.taskId - The ID of the parent task. Should be a short initialism, e.g. "swr" or "sre"
* @param {string} input.taskName - The name of the parent task
* @param {string} input.taskDescription - The description of the task
* @param {string} input.variantName - The name of the task variant
* @param {string} input.variantDescription - The description of the variant
* @param {object} input.variantParams - The parameters of the task variant
* @param {TaskVariantDataFlags} input.testData = Boolean flags indicating test data
* @param {TaskVariantDataFlags} input.demoData = Boolean flags indicating demo data
*/
constructor({ db, taskId, taskName, taskDescription, taskImage, taskURL, gameConfig, taskVersion = undefined, registered, external, variantName, variantDescription, variantParams = {}, testData = { task: false, variant: false }, demoData = { task: false, variant: false }, }) {
this.db = db;
this.taskId = taskId.toLowerCase();
this.taskName = taskName;
this.taskDescription = taskDescription;
this.taskImage = taskImage;
this.taskURL = taskURL;
this.taskVersion = taskVersion;
this.gameConfig = gameConfig;
this.registered = registered;
this.external = external;
this.variantName = variantName;
this.variantDescription = variantDescription;
this.variantParams = variantParams;
this.testData = testData;
this.demoData = demoData;
this.taskRef = (0, firestore_1.doc)(this.db, 'tasks', this.taskId);
this.variantsCollectionRef = (0, firestore_1.collection)(this.taskRef, 'variants');
this.variantId = undefined;
this.variantRef = undefined;
}
/**
* Push the trial and trial variant to Firestore
* @method
* @async
*/
toFirestore() {
return __awaiter(this, void 0, void 0, function* () {
// Push/update the task using the user provided task ID
const taskData = Object.assign(Object.assign({ name: this.taskName, description: this.taskDescription, image: this.taskImage, taskURL: this.taskURL, gameConfig: this.gameConfig, registered: this.registered, external: this.external, lastUpdated: (0, firestore_1.serverTimestamp)() }, (this.testData.task && { testData: true })), (this.demoData.task && { demoData: true }));
yield (0, firestore_1.setDoc)(this.taskRef, (0, util_1.removeUndefined)(taskData), { merge: true });
// Check to see if variant exists already by querying for a match on the params.
const q = (0, firestore_1.query)(this.variantsCollectionRef, (0, firestore_1.where)('params', '==', this.variantParams), (0, firestore_1.orderBy)('lastUpdated', 'desc'), (0, firestore_1.limit)(1));
const querySnapshot = yield (0, firestore_1.getDocs)(q);
let foundVariantWithCurrentParams = false;
// If this query snapshot yielded results, then we can use it and
// update the timestamp
querySnapshot.forEach((docRef) => {
this.variantId = docRef.id;
this.variantRef = (0, firestore_1.doc)(this.variantsCollectionRef, this.variantId);
foundVariantWithCurrentParams = true;
(0, firestore_1.updateDoc)(this.variantRef, (0, util_1.removeUndefined)({
description: this.variantDescription,
lastUpdated: (0, firestore_1.serverTimestamp)(),
}));
});
const variantData = Object.assign(Object.assign({ name: this.variantName, description: this.variantDescription, taskURL: this.taskURL, registered: this.registered, external: this.external, params: this.variantParams, lastUpdated: (0, firestore_1.serverTimestamp)() }, (this.testData.variant && { testData: true })), (this.demoData.variant && { demoData: true }));
if (!foundVariantWithCurrentParams) {
this.variantRef = (0, firestore_1.doc)(this.variantsCollectionRef);
yield (0, firestore_1.setDoc)(this.variantRef, (0, util_1.removeUndefined)(variantData));
this.variantId = this.variantRef.id;
}
});
}
/**
* Update variant params in Firestore
* @method
* @param {object} newParams - The parameters of the task variant
* @async
*/
updateTaskParams(newParams) {
return __awaiter(this, void 0, void 0, function* () {
if (this.variantRef === undefined) {
throw new Error('Cannot update task params before writing task to Firestore. Please call `.toFirestore()` first.');
}
const oldParams = (0, util_1.replaceValues)(this.variantParams);
const cleanParams = (0, util_1.replaceValues)(newParams);
// Only allow updating the task params if we are updating previously null values.
const { merged } = (0, util_1.mergeGameParams)(oldParams, cleanParams);
this.variantParams = merged;
yield this.toFirestore();
});
}
}
exports.RoarTaskVariant = RoarTaskVariant;