UNPKG

gpii-universal

Version:

Cross platform, core components of the GPII personalization infrastructure.

109 lines (95 loc) 3.9 kB
/** * GPII JournalIdParser.js * * Responsible for journalling the state of the system's settings in order to be able to recover from system crashes or corruption of the settings state * * Copyright 2016 Raising the Floor - International * * Licensed under the New BSD license. You may not use this file except in * compliance with this License. * */ "use strict"; var fluid = fluid || require("infusion"); var gpii = fluid.registerNamespace("gpii"); fluid.registerNamespace("gpii.journal"); gpii.journal.idFormatError = fluid.freezeRecursive({ isError: true, message: "The only supported formats for journalId are HEAD, HEAD~, HEAD~2, etc. or <1995-10-9T10:11:12, >2009-11-29T01:02:59, etc." }); gpii.journal.parseHeadId = function (journalId) { var index = journalId.substring("HEAD".length), depth = NaN; if (index.length > 0) { if (index.charAt(0) === "~") { var depthString = index.substring(1); depth = depthString.length === 0 ? 1 : fluid.parseInteger(depthString); } else { return gpii.journal.idFormatError; } } else { depth = 0; } if (Number.isNaN(depth)) { return gpii.journal.idFormatError; } else { return { type: "HEAD", depth: depth }; } }; gpii.journal.parseDateId = function (journalId) { var date = Date.parse(journalId.substring(1)); return Number.isNaN(date) ? gpii.journal.idFormatError : { type: "DATE", before: journalId.charAt(0) === "<" ? 1 : -1, date: date }; }; gpii.journal.idParsers = { "HEAD": gpii.journal.parseHeadId, ">": gpii.journal.parseDateId, "<": gpii.journal.parseDateId }; /** Parse a journalId specification string into a JSON form * @param {String} journalId - A journalId string beginning with HEAD, < or >. * @return {Object} A {ParsedJournalId} holding a field `type` (either "HEAD" or "DATE") and other type-specific fields. */ gpii.journal.parseId = function (journalId) { var togo = gpii.journal.idFormatError; fluid.each(gpii.journal.idParsers, function (func, start) { if (journalId.startsWith(start)) { togo = func(journalId); } }); return togo; }; /** Dereference a journalId given an array of journal files * @param {Array<JournalFile>} journalFiles - An array of JournalFile objects, sorted into increasing order of age. * @param {Object} parsed - A {ParsedJournalId} as returned from `gpii.journal.parseId` which will be used to index into `journalFiles. * @return {JournalFile|undefined} One of the JournalFile entries supplied, or undefined if the supplied journalId does not match. */ gpii.journal.fetchJournal = function (journalFiles, parsed) { if (parsed.type === "HEAD") { return journalFiles[parsed.depth]; } else { var before = parsed.before; var toSearch = before === 1 ? journalFiles : fluid.makeArray(journalFiles).reverse(); // For "before" - stop on the first one in reverse order (original) which is before // For "after" - stop on the first one in forward order (reversed) which is after return fluid.find_if(toSearch, function (journal) { return journal.createTime * before <= parsed.date * before; }); } }; /** Formats a millisecond timestamp into an ISO-8601 date string which is safe to * appear in a filename * @param {Number} time - A millisecond timestamp, as dispensed from `Date.now()`. * @return {String} An ISO-8601 date stamp without colon characters, e.g. 2016-07-05T220712.549Z. */ gpii.journal.formatTimestamp = function (time) { var date = new Date(time); var stamp = date.toISOString(); var safeStamp = stamp.replace(/:/g, ""); // This is still a valid ISO-8601 date string, but Date.parse() will no longer parse it return safeStamp; };