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
This commit is contained in:
Ilia Mashkov
2026-06-02 23:02:30 +03:00
parent 771bda745c
commit b390efdabe
9 changed files with 149 additions and 43 deletions
+83 -22
View File
@@ -1,29 +1,90 @@
export * from './domain'; export {
export * from './lib'; computeLineRenderModel,
export * from './ui'; DualFontLayout,
findSplitIndex,
} from './domain';
export type {
ComparisonLine,
ComparisonResult,
LineRenderModel,
} from './domain';
// Pure model surface (types + constants) is part of the convenient top-level export {
// API. Stateful stores are deliberately excluded — see below. createFontRowSizeResolver,
export * from './model/const/const'; FontNetworkError,
export * from './model/types'; 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 * `./api` (proxy clients: `fetchProxyFonts`, `seedFontCache`, …) is intentionally
* NOT re-exported here. Those clients import `$shared/api/queryClient`, whose * NOT re-exported here — those are not part of the entity's consumed surface and
* module eval runs `new QueryClient()` and loads `@tanstack/query-core`. Funneling * importing them eagerly constructs the TanStack `queryClient`. Import via the
* them through this barrel made every consumer of `$entities/Font` — including * segment: `import { fetchProxyFonts } from '$entities/Font/api'`.
* 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';
*/ */
// `./testing` is intentionally not re-exported: fixtures must not leak into the // `./testing` is intentionally not re-exported: fixtures must not leak into the
+49 -4
View File
@@ -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 type {
export * from './types'; FilterGroup,
FilterType,
FontCategory,
FontCollectionFilters,
FontCollectionSort,
FontCollectionState,
FontFeatures,
FontFilters,
FontLoadRequestConfig,
FontLoadStatus,
FontMetadata,
FontProvider,
FontStyleUrls,
FontSubset,
FontVariant,
FontWeight,
FontWeightItalic,
UnifiedFont,
UnifiedFontVariant,
} from './types';
+5 -2
View File
@@ -1,9 +1,12 @@
// Font lifecycle manager (browser-side load + cache + eviction) // Font lifecycle manager (browser-side load + cache + eviction)
export * from './fontLifecycleManager/fontLifecycleManager.svelte'; export {
__resetFontLifecycleManager,
FontLifecycleManager,
getFontLifecycleManager,
} from './fontLifecycleManager/fontLifecycleManager.svelte';
// Paginated catalog // Paginated catalog
export { getFontCatalog } from './fontCatalogStore/fontCatalogStore.svelte'; export { getFontCatalog } from './fontCatalogStore/fontCatalogStore.svelte';
export type { FontCatalogStore } from './fontCatalogStore/fontCatalogStore.svelte'; export type { FontCatalogStore } from './fontCatalogStore/fontCatalogStore.svelte';
// Batch fetch by IDs (detail-cache seeding) // Batch fetch by IDs (detail-cache seeding)
+4 -1
View File
@@ -23,4 +23,7 @@ export type {
FontCollectionState, FontCollectionState,
} from './store'; } from './store';
export * from './store/fontLifecycle'; export type {
FontLoadRequestConfig,
FontLoadStatus,
} from './store/fontLifecycle';
@@ -9,7 +9,7 @@
* observer, so it lives at module scope, not in any individual widget. * 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 { untrack } from 'svelte';
import { mapAppliedFiltersToParams } from '../../lib/mapper/mapAppliedFiltersToParams'; import { mapAppliedFiltersToParams } from '../../lib/mapper/mapAppliedFiltersToParams';
import { mapFilterMetadataToGroups } from '../../lib/mapper/mapFilterMetadataToGroups'; import { mapFilterMetadataToGroups } from '../../lib/mapper/mapFilterMetadataToGroups';
@@ -13,18 +13,16 @@
* - Slider position for character-by-character morphing * - Slider position for character-by-character morphing
*/ */
import {
type FontLoadRequestConfig,
type UnifiedFont,
getFontUrl,
} from '$entities/Font';
import { import {
type FontCatalogStore, type FontCatalogStore,
type FontLifecycleManager, type FontLifecycleManager,
type FontLoadRequestConfig,
FontsByIdsStore, FontsByIdsStore,
type UnifiedFont,
getFontCatalog, getFontCatalog,
getFontLifecycleManager, getFontLifecycleManager,
} from '$entities/Font/model'; getFontUrl,
} from '$entities/Font';
import { import {
type TypographySettingsStore, type TypographySettingsStore,
getTypographySettingsStore, getTypographySettingsStore,
@@ -9,11 +9,9 @@ import {
FontVirtualList, FontVirtualList,
type UnifiedFont, type UnifiedFont,
VIRTUAL_INDEX_NOT_LOADED, VIRTUAL_INDEX_NOT_LOADED,
} from '$entities/Font';
import {
getFontCatalog, getFontCatalog,
getFontLifecycleManager, getFontLifecycleManager,
} from '$entities/Font/model'; } from '$entities/Font';
import { getSkeletonWidth } from '$shared/lib/utils'; import { getSkeletonWidth } from '$shared/lib/utils';
import { import {
Button, Button,
@@ -8,11 +8,9 @@
import { import {
FontVirtualList, FontVirtualList,
createFontRowSizeResolver, createFontRowSizeResolver,
} from '$entities/Font';
import {
getFontCatalog, getFontCatalog,
getFontLifecycleManager, getFontLifecycleManager,
} from '$entities/Font/model'; } from '$entities/Font';
import { import {
TypographyMenu, TypographyMenu,
getTypographySettingsStore, getTypographySettingsStore,
@@ -3,7 +3,7 @@
Wraps SampleList with a Section component Wraps SampleList with a Section component
--> -->
<script lang="ts"> <script lang="ts">
import { getFontCatalog } from '$entities/Font/model'; import { getFontCatalog } from '$entities/Font';
import { NavigationWrapper } from '$features/Breadcrumb'; import { NavigationWrapper } from '$features/Breadcrumb';
import type { ResponsiveManager } from '$shared/lib'; import type { ResponsiveManager } from '$shared/lib';
import { cn } from '$shared/lib'; import { cn } from '$shared/lib';