89 lines
3.1 KiB
JavaScript
89 lines
3.1 KiB
JavaScript
(function (root, factory) {
|
|
const api = factory();
|
|
if (typeof module !== 'undefined' && module.exports) module.exports = api;
|
|
else root.createOfflineWorkStore = api;
|
|
})(typeof self !== 'undefined' ? self : this, function () {
|
|
'use strict';
|
|
|
|
const ENABLED_KEY = 'stackchain.offline-work.enabled.v1';
|
|
const SNAPSHOT_KEY = 'stackchain.offline-work.snapshot.v1';
|
|
const VERSION = 1;
|
|
const DEFAULT_MAX_AGE_MS = 7 * 24 * 60 * 60 * 1000;
|
|
const ITEM_FIELDS = [
|
|
'id', 'number', 'title', 'state', 'repository', 'labels', 'assignees',
|
|
'updated_at', 'due_date', 'milestone', 'url', 'work_reasons',
|
|
];
|
|
const NOTIFICATION_FIELDS = [
|
|
'id', 'number', 'title', 'unread', 'repository', 'subject_type', 'updated_at', 'url',
|
|
];
|
|
|
|
function pick(source, fields) {
|
|
const output = {};
|
|
fields.forEach(field => {
|
|
if (source && source[field] !== undefined) output[field] = source[field];
|
|
});
|
|
return output;
|
|
}
|
|
|
|
function createOfflineWorkStore({ storage, now = () => new Date(), maxAgeMs = DEFAULT_MAX_AGE_MS }) {
|
|
function enabled() {
|
|
try { return storage.getItem(ENABLED_KEY) === 'true'; }
|
|
catch (_) { return false; }
|
|
}
|
|
|
|
function clear() {
|
|
try { storage.removeItem(SNAPSHOT_KEY); }
|
|
catch (_) { return false; }
|
|
return true;
|
|
}
|
|
|
|
function setEnabled(value) {
|
|
try {
|
|
storage.setItem(ENABLED_KEY, value ? 'true' : 'false');
|
|
if (!value) clear();
|
|
return true;
|
|
} catch (_) { return false; }
|
|
}
|
|
|
|
function save(snapshot) {
|
|
if (!enabled() || !snapshot?.user?.login) return false;
|
|
const record = {
|
|
version: VERSION,
|
|
user_login: String(snapshot.user.login),
|
|
saved_at: now().toISOString(),
|
|
data: {
|
|
user: pick(snapshot.user, ['login', 'full_name']),
|
|
issues: (snapshot.issues || []).map(item => pick(item, ITEM_FIELDS)),
|
|
pull_requests: (snapshot.pull_requests || []).map(item => pick(item, ITEM_FIELDS)),
|
|
notifications: (snapshot.notifications || []).map(item => pick(item, NOTIFICATION_FIELDS)),
|
|
work_pagination: snapshot.work_pagination || {},
|
|
notification_pagination: snapshot.notification_pagination || {},
|
|
},
|
|
};
|
|
try { storage.setItem(SNAPSHOT_KEY, JSON.stringify(record)); }
|
|
catch (_) { return false; }
|
|
return true;
|
|
}
|
|
|
|
function load(expectedLogin) {
|
|
let record;
|
|
try { record = JSON.parse(storage.getItem(SNAPSHOT_KEY) || 'null'); }
|
|
catch (_) { clear(); return null; }
|
|
const savedAt = Date.parse(record?.saved_at || '');
|
|
const invalid = record?.version !== VERSION || !record?.user_login || !record?.data ||
|
|
!Number.isFinite(savedAt);
|
|
const expired = Number.isFinite(savedAt) && now().getTime() - savedAt > maxAgeMs;
|
|
if (invalid || expired) {
|
|
clear();
|
|
return null;
|
|
}
|
|
if (expectedLogin && record.user_login !== expectedLogin) return null;
|
|
return { ...record.data, saved_at: record.saved_at };
|
|
}
|
|
|
|
return { enabled, setEnabled, save, load, clear };
|
|
}
|
|
|
|
return createOfflineWorkStore;
|
|
});
|