@levante-framework/firekit
Version:
A library to facilitate Firebase authentication and Firestore interaction for LEVANTE apps
125 lines (124 loc) • 5.92 kB
JavaScript
"use strict";
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
*/
constructor({ db, taskId, taskName, taskDescription, taskImage, taskURL, gameConfig, taskVersion = undefined, registered, external, variantName, variantParams = {}, }) {
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.variantParams = variantParams;
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
*/
async toFirestore() {
// Check if task document exists to determine if we should set createdAt
const taskDocSnap = await (0, firestore_1.getDoc)(this.taskRef);
const taskExists = taskDocSnap.exists();
// Push/update the task using the user provided task ID
const taskData = {
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)(),
updatedAt: (0, firestore_1.serverTimestamp)(),
// Only set createdAt if this is a new document
...((!taskExists) && { createdAt: (0, firestore_1.serverTimestamp)() }),
};
try {
await (0, firestore_1.setDoc)(this.taskRef, (0, util_1.removeUndefined)(taskData), { merge: true });
}
catch (error) {
console.error('RoarTaskVariant toFirestore: error saving task to firestore', {
error,
errorMessage: error instanceof Error ? error.message : String(error),
errorCode: error?.code,
taskId: this.taskId,
taskRefPath: this.taskRef?.path,
});
throw error;
}
// 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)('updatedAt', 'desc'), (0, firestore_1.limit)(1));
const querySnapshot = await (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)({
lastUpdated: (0, firestore_1.serverTimestamp)(),
updatedAt: (0, firestore_1.serverTimestamp)(),
}));
});
if (!foundVariantWithCurrentParams) {
// Create new variant with both createdAt and updatedAt
const variantData = {
name: this.variantName,
taskURL: this.taskURL,
registered: this.registered,
external: this.external,
params: this.variantParams,
lastUpdated: (0, firestore_1.serverTimestamp)(),
createdAt: (0, firestore_1.serverTimestamp)(),
updatedAt: (0, firestore_1.serverTimestamp)(),
};
this.variantRef = (0, firestore_1.doc)(this.variantsCollectionRef);
await (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
*/
async updateTaskParams(newParams) {
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;
await this.toFirestore();
}
}
exports.RoarTaskVariant = RoarTaskVariant;