bootstrap과 feature 어댑터가 어댑터 내부 파일을 직접 겨누던 15곳을 그룹 배럴로 바꾼다. 커널(platform/**) 간선과 그룹 내부 import는 파일 경로를 유지한다 — check:adapter-inventory가 그 경로를 직접 검증한다. 번들 영향 없음: 초기 JS가 도입 전후 모두 181114 gzip bytes로 동일하다. sideEffects 선언 없이도 재수출이 트리셰이킹된다. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
124 lines
3.6 KiB
TypeScript
124 lines
3.6 KiB
TypeScript
import type { Preview } from "@storybook/react-vite";
|
|
import { QueryClientProvider } from "@tanstack/react-query";
|
|
import { MemoryRouter } from "react-router-dom";
|
|
|
|
import { createAnonymousSessionAdapter } from "../src/adapters/auth/index.ts";
|
|
import { createQueryClient } from "../src/adapters/query-cache/index.ts";
|
|
import { createApplication } from "../src/application/create-application.ts";
|
|
import { LocaleProvider } from "../src/presentation/i18n/index.ts";
|
|
import { ApplicationProvider } from "../src/presentation/providers/application-provider.tsx";
|
|
import { SessionProvider } from "../src/presentation/providers/session-provider.tsx";
|
|
import { ThemeProvider } from "../src/presentation/providers/theme-provider.tsx";
|
|
import "../src/presentation/styles/theme.css";
|
|
import { resolveProductFeatures } from "../src/contracts/product-features.ts";
|
|
import {
|
|
COMPILED_PRODUCT_FEATURE_IDS,
|
|
INSTALLED_PRODUCT_FEATURE_IDS,
|
|
} from "../src/features/installed-product-manifest.ts";
|
|
|
|
const preferences = new Map<string, unknown>();
|
|
const application = createApplication({
|
|
session: createAnonymousSessionAdapter(),
|
|
preferences: {
|
|
read: (name) => ({ ok: true, value: preferences.get(name) }),
|
|
write: (name, value) => {
|
|
preferences.set(name, structuredClone(value));
|
|
return { ok: true };
|
|
},
|
|
remove: (name) => {
|
|
preferences.delete(name);
|
|
return { ok: true };
|
|
},
|
|
},
|
|
diagnostics: { record() {} },
|
|
telemetry: { emit() {} },
|
|
releaseInfo: {
|
|
getCurrent: async () => ({
|
|
buildId: "storybook-build",
|
|
releaseId: "storybook-release",
|
|
configSchemaVersion: "1",
|
|
apiContractVersion: "1",
|
|
assetManifestHash: "storybook-assets",
|
|
routeChunks: {},
|
|
}),
|
|
refresh: async () => ({
|
|
buildId: "storybook-build",
|
|
releaseId: "storybook-release",
|
|
configSchemaVersion: "1",
|
|
apiContractVersion: "1",
|
|
assetManifestHash: "storybook-assets",
|
|
routeChunks: {},
|
|
}),
|
|
},
|
|
// Storybook renders components, not a product: every declared feature is
|
|
// shown as active so a story is never blank because of a deployment switch.
|
|
productFeatures: {
|
|
getSnapshot: () =>
|
|
resolveProductFeatures(
|
|
COMPILED_PRODUCT_FEATURE_IDS,
|
|
INSTALLED_PRODUCT_FEATURE_IDS,
|
|
),
|
|
isActive: () => true,
|
|
},
|
|
runtimeCapabilities: {
|
|
getSnapshot: () =>
|
|
Object.freeze(
|
|
(
|
|
[
|
|
"REALTIME",
|
|
"WEB_WORKER",
|
|
"SERVICE_WORKER",
|
|
"OFFLINE_COMMANDS",
|
|
] as const
|
|
).map((capabilityId) =>
|
|
Object.freeze({
|
|
capabilityId,
|
|
selected: 0,
|
|
active: 0,
|
|
override: "DEFAULT" as const,
|
|
}),
|
|
),
|
|
),
|
|
},
|
|
navigation: { reload() {} },
|
|
});
|
|
const queryClient = createQueryClient();
|
|
|
|
const preview: Preview = {
|
|
decorators: [
|
|
(Story) => (
|
|
<ApplicationProvider application={application}>
|
|
<QueryClientProvider client={queryClient}>
|
|
<MemoryRouter>
|
|
<LocaleProvider>
|
|
<ThemeProvider>
|
|
<SessionProvider>
|
|
<div id="portal-root" />
|
|
<main className="ui-page" style={{ padding: "1rem" }}>
|
|
<Story />
|
|
</main>
|
|
</SessionProvider>
|
|
</ThemeProvider>
|
|
</LocaleProvider>
|
|
</MemoryRouter>
|
|
</QueryClientProvider>
|
|
</ApplicationProvider>
|
|
),
|
|
],
|
|
parameters: {
|
|
a11y: {
|
|
test: "error",
|
|
},
|
|
controls: {
|
|
expanded: true,
|
|
},
|
|
options: {
|
|
storySort: {
|
|
order: ["Platform"],
|
|
},
|
|
},
|
|
},
|
|
};
|
|
|
|
export default preview;
|