the reminder not showing content on the card at dashboard view and the quizes are hardcoded must move to the db make api's for it
114 lines
3.3 KiB
JavaScript
114 lines
3.3 KiB
JavaScript
'use strict';
|
|
|
|
var inspect = require('object-inspect');
|
|
|
|
var $TypeError = require('es-errors/type');
|
|
|
|
/*
|
|
* This function traverses the list returning the node corresponding to the given key.
|
|
*
|
|
* That node is also moved to the head of the list, so that if it's accessed again we don't need to traverse the whole list.
|
|
* By doing so, all the recently used nodes can be accessed relatively quickly.
|
|
*/
|
|
/** @type {import('./list.d.ts').listGetNode} */
|
|
// eslint-disable-next-line consistent-return
|
|
var listGetNode = function (list, key, isDelete) {
|
|
/** @type {typeof list | NonNullable<(typeof list)['next']>} */
|
|
var prev = list;
|
|
/** @type {(typeof list)['next']} */
|
|
var curr;
|
|
// eslint-disable-next-line eqeqeq
|
|
for (; (curr = prev.next) != null; prev = curr) {
|
|
if (curr.key === key) {
|
|
prev.next = curr.next;
|
|
if (!isDelete) {
|
|
// eslint-disable-next-line no-extra-parens
|
|
curr.next = /** @type {NonNullable<typeof list.next>} */ (list.next);
|
|
list.next = curr; // eslint-disable-line no-param-reassign
|
|
}
|
|
return curr;
|
|
}
|
|
}
|
|
};
|
|
|
|
/** @type {import('./list.d.ts').listGet} */
|
|
var listGet = function (objects, key) {
|
|
if (!objects) {
|
|
return void undefined;
|
|
}
|
|
var node = listGetNode(objects, key);
|
|
return node && node.value;
|
|
};
|
|
/** @type {import('./list.d.ts').listSet} */
|
|
var listSet = function (objects, key, value) {
|
|
var node = listGetNode(objects, key);
|
|
if (node) {
|
|
node.value = value;
|
|
} else {
|
|
// Prepend the new node to the beginning of the list
|
|
objects.next = /** @type {import('./list.d.ts').ListNode<typeof value, typeof key>} */ ({ // eslint-disable-line no-param-reassign, no-extra-parens
|
|
key: key,
|
|
next: objects.next,
|
|
value: value
|
|
});
|
|
}
|
|
};
|
|
/** @type {import('./list.d.ts').listHas} */
|
|
var listHas = function (objects, key) {
|
|
if (!objects) {
|
|
return false;
|
|
}
|
|
return !!listGetNode(objects, key);
|
|
};
|
|
/** @type {import('./list.d.ts').listDelete} */
|
|
// eslint-disable-next-line consistent-return
|
|
var listDelete = function (objects, key) {
|
|
if (objects) {
|
|
return listGetNode(objects, key, true);
|
|
}
|
|
};
|
|
|
|
/** @type {import('.')} */
|
|
module.exports = function getSideChannelList() {
|
|
/** @typedef {ReturnType<typeof getSideChannelList>} Channel */
|
|
/** @typedef {Parameters<Channel['get']>[0]} K */
|
|
/** @typedef {Parameters<Channel['set']>[1]} V */
|
|
|
|
/** @type {import('./list.d.ts').RootNode<V, K> | undefined} */ var $o;
|
|
|
|
/** @type {Channel} */
|
|
var channel = {
|
|
assert: function (key) {
|
|
if (!channel.has(key)) {
|
|
throw new $TypeError('Side channel does not contain ' + inspect(key));
|
|
}
|
|
},
|
|
'delete': function (key) {
|
|
var root = $o && $o.next;
|
|
var deletedNode = listDelete($o, key);
|
|
if (deletedNode && root && root === deletedNode) {
|
|
$o = void undefined;
|
|
}
|
|
return !!deletedNode;
|
|
},
|
|
get: function (key) {
|
|
return listGet($o, key);
|
|
},
|
|
has: function (key) {
|
|
return listHas($o, key);
|
|
},
|
|
set: function (key, value) {
|
|
if (!$o) {
|
|
// Initialize the linked list as an empty node, so that we don't have to special-case handling of the first node: we can always refer to it as (previous node).next, instead of something like (list).head
|
|
$o = {
|
|
next: void undefined
|
|
};
|
|
}
|
|
// eslint-disable-next-line no-extra-parens
|
|
listSet(/** @type {NonNullable<typeof $o>} */ ($o), key, value);
|
|
}
|
|
};
|
|
// @ts-expect-error TODO: figure out why this is erroring
|
|
return channel;
|
|
};
|