Press n or j to go to the next uncovered block, b, p or k for the previous block.
| 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 | 1x 1x 1x 1x 13x 13x 13x 1x 1x 4x 4x 4x 4x 4x 3x 4x 1x 1x 1x 1x 1x 1x 4x 4x 4x 4x 3x 4x 1x 1x 1x 1x 1x 4x 4x 4x 4x 4x 3x 3x 3x 4x 1x 1x 1x 1x 1x 1x 1x 1x 1x 4x 4x 4x 4x 4x 1x 1x 1x 1x 1x 1x 1x 5x 5x 4x 4x 4x 1x | import { CACHE } from '@/constants/common';
import { cstorage } from '@/utils/storage';
import type { Migration } from '../types';
/**
* Narrows an unknown value to a plain (non-array) object record.
* @param value - The value to test.
* @returns `true` when `value` is a non-null, non-array object.
* @source
*/
function isRecord(value: unknown): value is Record<string, unknown> {
return typeof value === 'object' && value !== null && !Array.isArray(value);
}
/**
* Rewrites the legacy flat settings keys into the 1.7.0 nested shape:
* - `caching` (boolean) + `cacheTtlMinutes` + `doNotCacheEmptyResults`
* → `caching: { enabled, ttlMinutes, doNotCacheEmptyResults }`
* - `trackPriceHistory` + `priceHistoryMaxPoints` → `priceTracking: { enabled, maxDataPoints }`
* - `suppliers` (array) + `disabledSuppliers` + `excludeNonShippingSuppliers` +
* `supplierResultLimit` → `suppliers: { enabled, disabled, excludeNonShipping, resultLimit }`
*
* Idempotent (already-nested input passes through) and non-mutating. Non-object
* input is returned unchanged.
* @param raw - The stored `user_settings` value.
* @returns The migrated settings object, or `raw` when it isn't an object.
* @example
* ```ts
* nestSettings({ caching: true, cacheTtlMinutes: 60 });
* // => { caching: { enabled: true, doNotCacheEmptyResults: undefined, ttlMinutes: 60 } }
* ```
* @source
*/
function nestSettings(raw: unknown): unknown {
if (!isRecord(raw)) return raw;
const out: Record<string, unknown> = { ...raw };
if (
!isRecord(out.caching) &&
('caching' in out || 'cacheTtlMinutes' in out || 'doNotCacheEmptyResults' in out)
) {
out.caching = {
enabled: typeof raw.caching === 'boolean' ? raw.caching : undefined,
doNotCacheEmptyResults: raw.doNotCacheEmptyResults,
ttlMinutes: raw.cacheTtlMinutes,
};
}
delete out.cacheTtlMinutes;
delete out.doNotCacheEmptyResults;
if (
!isRecord(out.priceTracking) &&
('trackPriceHistory' in out || 'priceHistoryMaxPoints' in out)
) {
out.priceTracking = {
enabled: raw.trackPriceHistory,
maxDataPoints: raw.priceHistoryMaxPoints,
};
}
delete out.trackPriceHistory;
delete out.priceHistoryMaxPoints;
const legacyEnabled = Array.isArray(raw.suppliers) ? raw.suppliers : undefined;
if (
legacyEnabled ||
'disabledSuppliers' in out ||
'excludeNonShippingSuppliers' in out ||
'supplierResultLimit' in out
) {
const existing = isRecord(out.suppliers) ? out.suppliers : {};
out.suppliers = {
...existing,
enabled: legacyEnabled ?? existing.enabled,
disabled: raw.disabledSuppliers ?? existing.disabled,
excludeNonShipping: raw.excludeNonShippingSuppliers ?? existing.excludeNonShipping,
resultLimit: raw.supplierResultLimit ?? existing.resultLimit,
};
}
delete out.disabledSuppliers;
delete out.excludeNonShippingSuppliers;
delete out.supplierResultLimit;
return out;
}
/**
* 1.7.0 groups the flat cache, price-history, and supplier settings into nested
* `caching` / `priceTracking` / `suppliers` objects. This step rewrites the
* `user_settings` record in `chrome.storage.local` into that shape (dropping the
* old flat keys) so existing users keep their saved preferences on upgrade.
*
* It transforms `chrome.storage.local` rather than the IndexedDB `db` handle —
* user settings don't live in the cache. The popup applies pending steps before
* loading settings, so it reads the migrated shape.
*
* @source
*/
export const migration: Migration = {
from: '1.6.1',
to: '1.7.0',
description: 'Group cache, price-tracking, and supplier settings into nested objects',
async up({ logger }) {
const stored = (await cstorage.local.get([CACHE.USER_SETTINGS]))[CACHE.USER_SETTINGS];
if (typeof stored !== 'object' || stored === null) return;
await cstorage.local.set({ [CACHE.USER_SETTINGS]: nestSettings(stored) });
logger.info('Migrated user_settings to the nested 1.7.0 shape');
},
};
|