From b390efdabecabadddee551f32055d2805b7030b6 Mon Sep 17 00:00:00 2001 From: Ilia Mashkov Date: Tue, 2 Jun 2026 23:02:30 +0300 Subject: [PATCH] refactor(entities/Font): named public API and expose stores via root barrel Stores were only reachable by deep-importing $entities/Font/model, so consumers reached past the slice public API (FSD anti-pattern D, B-3/D-2). - convert the Font barrels (root, model, model/store, model/types) to explicit named exports with export/export type split (B-1) - re-export the lazy store accessors/classes from the root barrel so the entity public API is complete and inert at import (construction stays lazy; the root already loads tanstack via ./ui) - repoint all consumers (SampleList, SampleListSection, FontList, comparisonStore, bindings) from $entities/Font/model to $entities/Font --- src/entities/Font/index.ts | 105 ++++++++++++++---- src/entities/Font/model/index.ts | 53 ++++++++- src/entities/Font/model/store/index.ts | 7 +- src/entities/Font/model/types/index.ts | 5 +- .../model/store/bindings.svelte.ts | 2 +- .../model/stores/comparisonStore.svelte.ts | 10 +- .../ui/FontList/FontList.svelte | 4 +- .../ui/SampleList/SampleList.svelte | 4 +- .../SampleListSection.svelte | 2 +- 9 files changed, 149 insertions(+), 43 deletions(-) diff --git a/src/entities/Font/index.ts b/src/entities/Font/index.ts index d25188a..af4d2b2 100644 --- a/src/entities/Font/index.ts +++ b/src/entities/Font/index.ts @@ -1,29 +1,90 @@ -export * from './domain'; -export * from './lib'; -export * from './ui'; +export { + computeLineRenderModel, + DualFontLayout, + findSplitIndex, +} from './domain'; +export type { + ComparisonLine, + ComparisonResult, + LineRenderModel, +} from './domain'; -// Pure model surface (types + constants) is part of the convenient top-level -// API. Stateful stores are deliberately excluded — see below. -export * from './model/const/const'; -export * from './model/types'; +export { + createFontRowSizeResolver, + FontNetworkError, + FontResponseError, + getFontUrl, +} from './lib'; +export type { FontRowSizeResolverOptions } from './lib'; + +export { + FontApplicator, + FontVirtualList, +} from './ui'; + +// Pure model surface (types + constants). +export { + DEFAULT_FONT_SIZE, + DEFAULT_FONT_WEIGHT, + DEFAULT_LETTER_SPACING, + DEFAULT_LINE_HEIGHT, + FONT_SIZE_STEP, + FONT_WEIGHT_STEP, + LETTER_SPACING_STEP, + LINE_HEIGHT_STEP, + MAX_FONT_SIZE, + MAX_FONT_WEIGHT, + MAX_LETTER_SPACING, + MAX_LINE_HEIGHT, + MIN_FONT_SIZE, + MIN_FONT_WEIGHT, + MIN_LETTER_SPACING, + MIN_LINE_HEIGHT, + VIRTUAL_INDEX_NOT_LOADED, +} from './model/const/const'; +export type { + FilterGroup, + FilterType, + FontCategory, + FontCollectionFilters, + FontCollectionSort, + FontCollectionState, + FontFeatures, + FontFilters, + FontLoadRequestConfig, + FontLoadStatus, + FontMetadata, + FontProvider, + FontStyleUrls, + FontSubset, + FontVariant, + FontWeight, + FontWeightItalic, + UnifiedFont, + UnifiedFontVariant, +} from './model/types'; + +/* + * Stores are exposed as lazy accessors / classes (not eager singletons): the + * entity's public API is complete, so consumers go through this barrel instead + * of deep-importing `./model` (FSD public-API boundary). Construction happens on + * first call, so this is inert at import. The slice root already transitively + * loads `@tanstack/query-core` via `./ui` (FontVirtualList), so surfacing the + * stores here adds no new eager cost. + */ +export { + FontLifecycleManager, + FontsByIdsStore, + getFontCatalog, + getFontLifecycleManager, +} from './model'; +export type { FontCatalogStore } from './model'; /* * `./api` (proxy clients: `fetchProxyFonts`, `seedFontCache`, …) is intentionally - * NOT re-exported here. Those clients import `$shared/api/queryClient`, whose - * module eval runs `new QueryClient()` and loads `@tanstack/query-core`. Funneling - * them through this barrel made every consumer of `$entities/Font` — including - * pure-domain and type-only importers — eager-load TanStack and construct the - * client (notably in unit specs). Import API clients via the segment: - * import { fetchProxyFonts } from '$entities/Font/api'; - */ - -/* - * Stores (`fontCatalogStore`, `fontLifecycleManager`, `FontsByIdsStore`) are - * intentionally NOT re-exported here. They instantiate module-level singletons - * and pull `@tanstack/query-core`, so funneling them through this barrel would - * make every consumer of `$entities/Font` eager-instantiate stores (and break - * tree-shaking / test init-order). Import them via the model segment: - * import { fontCatalogStore } from '$entities/Font/model'; + * NOT re-exported here — those are not part of the entity's consumed surface and + * importing them eagerly constructs the TanStack `queryClient`. Import via the + * segment: `import { fetchProxyFonts } from '$entities/Font/api'`. */ // `./testing` is intentionally not re-exported: fixtures must not leak into the diff --git a/src/entities/Font/model/index.ts b/src/entities/Font/model/index.ts index 36cbda2..d605aeb 100644 --- a/src/entities/Font/model/index.ts +++ b/src/entities/Font/model/index.ts @@ -1,6 +1,51 @@ -export * from './const/const'; +export { + DEFAULT_FONT_SIZE, + DEFAULT_FONT_WEIGHT, + DEFAULT_LETTER_SPACING, + DEFAULT_LINE_HEIGHT, + FONT_SIZE_STEP, + FONT_WEIGHT_STEP, + LETTER_SPACING_STEP, + LINE_HEIGHT_STEP, + MAX_FONT_SIZE, + MAX_FONT_WEIGHT, + MAX_LETTER_SPACING, + MAX_LINE_HEIGHT, + MIN_FONT_SIZE, + MIN_FONT_WEIGHT, + MIN_LETTER_SPACING, + MIN_LINE_HEIGHT, + VIRTUAL_INDEX_NOT_LOADED, +} from './const/const'; -export { getFontCatalog } from './store'; +// Stores (lazy accessors + classes) +export { + __resetFontLifecycleManager, + FontLifecycleManager, + FontsByIdsStore, + getFontCatalog, + getFontLifecycleManager, +} from './store'; +export type { FontCatalogStore } from './store'; -export * from './store'; -export * from './types'; +export type { + FilterGroup, + FilterType, + FontCategory, + FontCollectionFilters, + FontCollectionSort, + FontCollectionState, + FontFeatures, + FontFilters, + FontLoadRequestConfig, + FontLoadStatus, + FontMetadata, + FontProvider, + FontStyleUrls, + FontSubset, + FontVariant, + FontWeight, + FontWeightItalic, + UnifiedFont, + UnifiedFontVariant, +} from './types'; diff --git a/src/entities/Font/model/store/index.ts b/src/entities/Font/model/store/index.ts index d0d0024..3f05f83 100644 --- a/src/entities/Font/model/store/index.ts +++ b/src/entities/Font/model/store/index.ts @@ -1,9 +1,12 @@ // Font lifecycle manager (browser-side load + cache + eviction) -export * from './fontLifecycleManager/fontLifecycleManager.svelte'; +export { + __resetFontLifecycleManager, + FontLifecycleManager, + getFontLifecycleManager, +} from './fontLifecycleManager/fontLifecycleManager.svelte'; // Paginated catalog export { getFontCatalog } from './fontCatalogStore/fontCatalogStore.svelte'; - export type { FontCatalogStore } from './fontCatalogStore/fontCatalogStore.svelte'; // Batch fetch by IDs (detail-cache seeding) diff --git a/src/entities/Font/model/types/index.ts b/src/entities/Font/model/types/index.ts index fd43b4d..18b2443 100644 --- a/src/entities/Font/model/types/index.ts +++ b/src/entities/Font/model/types/index.ts @@ -23,4 +23,7 @@ export type { FontCollectionState, } from './store'; -export * from './store/fontLifecycle'; +export type { + FontLoadRequestConfig, + FontLoadStatus, +} from './store/fontLifecycle'; diff --git a/src/features/FilterAndSortFonts/model/store/bindings.svelte.ts b/src/features/FilterAndSortFonts/model/store/bindings.svelte.ts index f5491bb..ddb0c6c 100644 --- a/src/features/FilterAndSortFonts/model/store/bindings.svelte.ts +++ b/src/features/FilterAndSortFonts/model/store/bindings.svelte.ts @@ -9,7 +9,7 @@ * observer, so it lives at module scope, not in any individual widget. */ -import { getFontCatalog } from '$entities/Font/model'; +import { getFontCatalog } from '$entities/Font'; import { untrack } from 'svelte'; import { mapAppliedFiltersToParams } from '../../lib/mapper/mapAppliedFiltersToParams'; import { mapFilterMetadataToGroups } from '../../lib/mapper/mapFilterMetadataToGroups'; diff --git a/src/widgets/ComparisonView/model/stores/comparisonStore.svelte.ts b/src/widgets/ComparisonView/model/stores/comparisonStore.svelte.ts index 4b84354..4be6115 100644 --- a/src/widgets/ComparisonView/model/stores/comparisonStore.svelte.ts +++ b/src/widgets/ComparisonView/model/stores/comparisonStore.svelte.ts @@ -13,18 +13,16 @@ * - Slider position for character-by-character morphing */ -import { - type FontLoadRequestConfig, - type UnifiedFont, - getFontUrl, -} from '$entities/Font'; import { type FontCatalogStore, type FontLifecycleManager, + type FontLoadRequestConfig, FontsByIdsStore, + type UnifiedFont, getFontCatalog, getFontLifecycleManager, -} from '$entities/Font/model'; + getFontUrl, +} from '$entities/Font'; import { type TypographySettingsStore, getTypographySettingsStore, diff --git a/src/widgets/ComparisonView/ui/FontList/FontList.svelte b/src/widgets/ComparisonView/ui/FontList/FontList.svelte index 817b863..396b31f 100644 --- a/src/widgets/ComparisonView/ui/FontList/FontList.svelte +++ b/src/widgets/ComparisonView/ui/FontList/FontList.svelte @@ -9,11 +9,9 @@ import { FontVirtualList, type UnifiedFont, VIRTUAL_INDEX_NOT_LOADED, -} from '$entities/Font'; -import { getFontCatalog, getFontLifecycleManager, -} from '$entities/Font/model'; +} from '$entities/Font'; import { getSkeletonWidth } from '$shared/lib/utils'; import { Button, diff --git a/src/widgets/SampleList/ui/SampleList/SampleList.svelte b/src/widgets/SampleList/ui/SampleList/SampleList.svelte index fab8af8..b6a63ed 100644 --- a/src/widgets/SampleList/ui/SampleList/SampleList.svelte +++ b/src/widgets/SampleList/ui/SampleList/SampleList.svelte @@ -8,11 +8,9 @@ import { FontVirtualList, createFontRowSizeResolver, -} from '$entities/Font'; -import { getFontCatalog, getFontLifecycleManager, -} from '$entities/Font/model'; +} from '$entities/Font'; import { TypographyMenu, getTypographySettingsStore, diff --git a/src/widgets/SampleList/ui/SampleListSection/SampleListSection.svelte b/src/widgets/SampleList/ui/SampleListSection/SampleListSection.svelte index 6651fd4..477e623 100644 --- a/src/widgets/SampleList/ui/SampleListSection/SampleListSection.svelte +++ b/src/widgets/SampleList/ui/SampleListSection/SampleListSection.svelte @@ -3,7 +3,7 @@ Wraps SampleList with a Section component -->