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:
Ilia Mashkov
2026-05-24 20:00:43 +03:00
parent 07d044f4d6
commit 728380498b
38 changed files with 105 additions and 105 deletions
@@ -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();
@@ -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 });
@@ -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();
@@ -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);
+7 -7
View File
@@ -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';
+1 -1
View File
@@ -23,5 +23,5 @@ export type {
FontCollectionState,
} from './store';
export * from './store/appliedFonts';
export * from './store/fontLifecycle';
export * from './typography';