refactor(Font): rename fontStore and appliedFontsManager
Both names were vague or overloaded: - fontStore / FontStore -> fontCatalogStore / FontCatalogStore Three font-related stores live in this slice; the new name names the paginated catalog specifically. - appliedFontsManager / AppliedFontsManager -> fontLifecycleManager / FontLifecycleManager "Applied" collided with the filter-side appliedFilterStore (different meaning). The class actually orchestrates a load-use-evict lifecycle with FontBufferCache + FontEvictionPolicy + FontLoadQueue collaborators, so "Manager" is justified. Companion types file moved alongside (appliedFonts.ts -> fontLifecycle.ts). Directories, file basenames, factory (createFontStore -> createFontCatalogStore), and the AppliedFontsManagerDeps interface all renamed. All consumers (ComparisonView, SampleList, FontList, FontApplicator, FontVirtualList, FilterAndSortFonts bindings, createFontRowSizeResolver, mocks) updated.
This commit is contained in:
+9
-9
@@ -17,7 +17,7 @@ import {
|
||||
generateMockFonts,
|
||||
} from '../../../lib/mocks/fonts.mock';
|
||||
import type { UnifiedFont } from '../../types';
|
||||
import { FontStore } from './fontStore.svelte';
|
||||
import { FontCatalogStore } from './fontCatalogStore.svelte';
|
||||
|
||||
vi.mock('$shared/api/queryClient', () => ({
|
||||
queryClient: new QueryClient({
|
||||
@@ -44,7 +44,7 @@ const makeResponse = (
|
||||
});
|
||||
|
||||
function makeStore(params = {}) {
|
||||
return new FontStore({ limit: 10, ...params });
|
||||
return new FontCatalogStore({ limit: 10, ...params });
|
||||
}
|
||||
|
||||
async function fetchedStore(params = {}, fonts = generateMockFonts(5), meta: Parameters<typeof makeResponse>[1] = {}) {
|
||||
@@ -55,7 +55,7 @@ async function fetchedStore(params = {}, fonts = generateMockFonts(5), meta: Par
|
||||
return store;
|
||||
}
|
||||
|
||||
describe('FontStore', () => {
|
||||
describe('FontCatalogStore', () => {
|
||||
afterEach(() => {
|
||||
queryClient.clear();
|
||||
vi.resetAllMocks();
|
||||
@@ -69,7 +69,7 @@ describe('FontStore', () => {
|
||||
});
|
||||
|
||||
it('defaults limit to 50 when not provided', () => {
|
||||
const store = new FontStore();
|
||||
const store = new FontCatalogStore();
|
||||
expect(store.params.limit).toBe(50);
|
||||
store.destroy();
|
||||
});
|
||||
@@ -390,11 +390,11 @@ describe('FontStore', () => {
|
||||
});
|
||||
|
||||
describe('nextPage', () => {
|
||||
let store: FontStore;
|
||||
let store: FontCatalogStore;
|
||||
|
||||
beforeEach(async () => {
|
||||
fetch.mockResolvedValue(makeResponse(generateMockFonts(10), { total: 30, limit: 10, offset: 0 }));
|
||||
store = new FontStore({ limit: 10 });
|
||||
store = new FontCatalogStore({ limit: 10 });
|
||||
await store.refetch();
|
||||
flushSync();
|
||||
});
|
||||
@@ -415,7 +415,7 @@ describe('FontStore', () => {
|
||||
// Set up a store where all fonts fit in one page (hasMore = false)
|
||||
queryClient.clear();
|
||||
fetch.mockResolvedValue(makeResponse(generateMockFonts(10), { total: 10, limit: 10, offset: 0 }));
|
||||
store = new FontStore({ limit: 10 });
|
||||
store = new FontCatalogStore({ limit: 10 });
|
||||
await store.refetch();
|
||||
flushSync();
|
||||
|
||||
@@ -454,7 +454,7 @@ describe('FontStore', () => {
|
||||
describe('getCachedData / setQueryData', () => {
|
||||
it('getCachedData returns undefined before any fetch', () => {
|
||||
queryClient.clear();
|
||||
const store = new FontStore({ limit: 10 });
|
||||
const store = new FontCatalogStore({ limit: 10 });
|
||||
expect(store.getCachedData()).toBeUndefined();
|
||||
store.destroy();
|
||||
});
|
||||
@@ -502,7 +502,7 @@ describe('FontStore', () => {
|
||||
});
|
||||
|
||||
describe('filter shortcut methods', () => {
|
||||
let store: FontStore;
|
||||
let store: FontCatalogStore;
|
||||
|
||||
beforeEach(() => {
|
||||
store = makeStore();
|
||||
+4
-4
@@ -25,7 +25,7 @@ type FontStoreParams = Omit<ProxyFontsParams, 'offset'>;
|
||||
|
||||
type FontStoreResult = InfiniteQueryObserverResult<InfiniteData<ProxyFontsResponse, PageParam>, Error>;
|
||||
|
||||
export class FontStore {
|
||||
export class FontCatalogStore {
|
||||
#params = $state<FontStoreParams>({ limit: 50 });
|
||||
#result = $state<FontStoreResult>({} as FontStoreResult);
|
||||
#observer: InfiniteQueryObserver<
|
||||
@@ -459,8 +459,8 @@ export class FontStore {
|
||||
}
|
||||
}
|
||||
|
||||
export function createFontStore(params: FontStoreParams = {}): FontStore {
|
||||
return new FontStore(params);
|
||||
export function createFontCatalogStore(params: FontStoreParams = {}): FontCatalogStore {
|
||||
return new FontCatalogStore(params);
|
||||
}
|
||||
|
||||
export const fontStore = new FontStore({ limit: 50 });
|
||||
export const fontCatalogStore = new FontCatalogStore({ limit: 50 });
|
||||
+4
-4
@@ -17,7 +17,7 @@ import { FontBufferCache } from './utils/fontBufferCache/FontBufferCache';
|
||||
import { FontEvictionPolicy } from './utils/fontEvictionPolicy/FontEvictionPolicy';
|
||||
import { FontLoadQueue } from './utils/fontLoadQueue/FontLoadQueue';
|
||||
|
||||
interface AppliedFontsManagerDeps {
|
||||
interface FontLifecycleManagerDeps {
|
||||
cache?: FontBufferCache;
|
||||
eviction?: FontEvictionPolicy;
|
||||
queue?: FontLoadQueue;
|
||||
@@ -46,7 +46,7 @@ interface AppliedFontsManagerDeps {
|
||||
*
|
||||
* **Browser APIs Used:** `scheduler.yield()`, `isInputPending()`, `requestIdleCallback`, Cache API, Network Information API
|
||||
*/
|
||||
export class AppliedFontsManager {
|
||||
export class FontLifecycleManager {
|
||||
// Injected collaborators - each handles one concern for better testability
|
||||
readonly #cache: FontBufferCache;
|
||||
readonly #eviction: FontEvictionPolicy;
|
||||
@@ -78,7 +78,7 @@ export class AppliedFontsManager {
|
||||
// Starts periodic cleanup timer (browser-only).
|
||||
constructor(
|
||||
{ cache = new FontBufferCache(), eviction = new FontEvictionPolicy(), queue = new FontLoadQueue() }:
|
||||
AppliedFontsManagerDeps = {},
|
||||
FontLifecycleManagerDeps = {},
|
||||
) {
|
||||
// Inject collaborators - defaults provided for production, fakes for testing
|
||||
this.#cache = cache;
|
||||
@@ -396,4 +396,4 @@ export class AppliedFontsManager {
|
||||
/**
|
||||
* Singleton instance — use throughout the application for unified font loading state.
|
||||
*/
|
||||
export const appliedFontsManager = new AppliedFontsManager();
|
||||
export const fontLifecycleManager = new FontLifecycleManager();
|
||||
+8
-8
@@ -1,8 +1,8 @@
|
||||
/**
|
||||
* @vitest-environment jsdom
|
||||
*/
|
||||
import { AppliedFontsManager } from './appliedFontsStore.svelte';
|
||||
import { FontFetchError } from './errors';
|
||||
import { FontLifecycleManager } from './fontLifecycleManager.svelte';
|
||||
import { FontEvictionPolicy } from './utils/fontEvictionPolicy/FontEvictionPolicy';
|
||||
|
||||
class FakeBufferCache {
|
||||
@@ -32,8 +32,8 @@ const makeConfig = (id: string, overrides: Partial<{ weight: number; isVariable:
|
||||
...overrides,
|
||||
});
|
||||
|
||||
describe('AppliedFontsManager', () => {
|
||||
let manager: AppliedFontsManager;
|
||||
describe('FontLifecycleManager', () => {
|
||||
let manager: FontLifecycleManager;
|
||||
let eviction: FontEvictionPolicy;
|
||||
let mockFontFaceSet: { add: ReturnType<typeof vi.fn>; delete: ReturnType<typeof vi.fn> };
|
||||
|
||||
@@ -55,7 +55,7 @@ describe('AppliedFontsManager', () => {
|
||||
});
|
||||
vi.stubGlobal('FontFace', MockFontFace);
|
||||
|
||||
manager = new AppliedFontsManager({ cache: new FakeBufferCache() as any, eviction });
|
||||
manager = new FontLifecycleManager({ cache: new FakeBufferCache() as any, eviction });
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
@@ -101,7 +101,7 @@ describe('AppliedFontsManager', () => {
|
||||
|
||||
it('skips fonts that have exhausted retries', async () => {
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const failManager = new AppliedFontsManager({ cache: new FailingBufferCache() as any, eviction });
|
||||
const failManager = new FontLifecycleManager({ cache: new FailingBufferCache() as any, eviction });
|
||||
|
||||
// exhaust all 3 retries
|
||||
for (let i = 0; i < 3; i++) {
|
||||
@@ -160,7 +160,7 @@ describe('AppliedFontsManager', () => {
|
||||
describe('Phase 1 — fetch', () => {
|
||||
it('sets status to error on fetch failure', async () => {
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const failManager = new AppliedFontsManager({ cache: new FailingBufferCache() as any, eviction });
|
||||
const failManager = new FontLifecycleManager({ cache: new FailingBufferCache() as any, eviction });
|
||||
|
||||
failManager.touch([makeConfig('broken')]);
|
||||
await vi.advanceTimersByTimeAsync(50);
|
||||
@@ -171,7 +171,7 @@ describe('AppliedFontsManager', () => {
|
||||
|
||||
it('logs a console error on fetch failure', async () => {
|
||||
const consoleSpy = vi.spyOn(console, 'error').mockImplementation(() => {});
|
||||
const failManager = new AppliedFontsManager({ cache: new FailingBufferCache() as any, eviction });
|
||||
const failManager = new FontLifecycleManager({ cache: new FailingBufferCache() as any, eviction });
|
||||
|
||||
failManager.touch([makeConfig('broken')]);
|
||||
await vi.advanceTimersByTimeAsync(50);
|
||||
@@ -189,7 +189,7 @@ describe('AppliedFontsManager', () => {
|
||||
evict() {},
|
||||
clear() {},
|
||||
};
|
||||
const abortManager = new AppliedFontsManager({ cache: abortingCache as any, eviction });
|
||||
const abortManager = new FontLifecycleManager({ cache: abortingCache as any, eviction });
|
||||
|
||||
abortManager.touch([makeConfig('aborted')]);
|
||||
await vi.advanceTimersByTimeAsync(50);
|
||||
@@ -1,9 +1,9 @@
|
||||
// Applied fonts manager
|
||||
export * from './appliedFontsStore/appliedFontsStore.svelte';
|
||||
// Font lifecycle manager (browser-side load + cache + eviction)
|
||||
export * from './fontLifecycleManager/fontLifecycleManager.svelte';
|
||||
|
||||
// Single FontStore
|
||||
// Paginated catalog
|
||||
export {
|
||||
createFontStore,
|
||||
FontStore,
|
||||
fontStore,
|
||||
} from './fontStore/fontStore.svelte';
|
||||
createFontCatalogStore,
|
||||
FontCatalogStore,
|
||||
fontCatalogStore,
|
||||
} from './fontCatalogStore/fontCatalogStore.svelte';
|
||||
|
||||
Reference in New Issue
Block a user