41 lines
2.2 KiB
JavaScript
41 lines
2.2 KiB
JavaScript
// C2-06 (design 5.2): the business file's replyLimits, read by the citation guard and written only
|
|
// by the human's library.limits.set. Pure, so the business package's organization writer imports it.
|
|
|
|
export const plain = value => value !== null && typeof value === 'object' && !Array.isArray(value);
|
|
|
|
// The replyLimits keys, their defaults and their valid values. A key is read only when Object.hasOwn
|
|
// finds it and its value passes `valid`; anything else is the default (webby-0144 R3).
|
|
export const REPLY_LIMITS = Object.freeze({
|
|
requireCitation: { default: false, valid: v => typeof v === 'boolean' },
|
|
citationsPerReply: { default: 20, valid: v => Number.isInteger(v) && v >= 1 && v <= 1000 },
|
|
});
|
|
|
|
// `read` is { readable: false } when the business file is missing, unreadable, not JSON or not an
|
|
// object at check time, else { readable: true, document }. An unreadable file checks at the defaults
|
|
// except requireCitation, which is true so a setting she turned on doesn't fail open (webby-0151 R2).
|
|
export function resolveReplyLimits(read) {
|
|
const limits = {}, fallback = [];
|
|
const unreadable = !read?.readable || !plain(read.document);
|
|
const raw = unreadable ? undefined : read.document.replyLimits;
|
|
for (const [key, { default: value, valid }] of Object.entries(REPLY_LIMITS)) {
|
|
if (plain(raw) && Object.hasOwn(raw, key) && valid(raw[key])) limits[key] = raw[key];
|
|
else {
|
|
limits[key] = value;
|
|
// A key fell back when replyLimits is there but isn't an object, or holds the key with a value
|
|
// outside the table. A key left out is simply its default.
|
|
if (raw !== undefined && (!plain(raw) || Object.hasOwn(raw, key))) fallback.push(key);
|
|
}
|
|
}
|
|
if (unreadable) limits.requireCitation = true;
|
|
return { ...limits, fallback, unreadable };
|
|
}
|
|
|
|
// library.limits.set's check: the whole object is replaced, a key left out means its default, and an
|
|
// unknown key or a value outside the table refuses. Returns the object to write.
|
|
export function checkReplyLimits(value) {
|
|
if (!plain(value)) return null;
|
|
for (const [key, v] of Object.entries(value))
|
|
if (!Object.hasOwn(REPLY_LIMITS, key) || !REPLY_LIMITS[key].valid(v)) return null;
|
|
return structuredClone(value);
|
|
}
|