feat(ui): expose grouped component entrypoints

This commit is contained in:
vince 2026-06-20 07:31:35 +02:00
parent cb446e2a6e
commit 6a0c57e93c
7 changed files with 105 additions and 0 deletions

View file

@ -100,6 +100,43 @@ describe("Storybook inventory", () => {
}
});
test("exposes grouped package entrypoints for each component domain", () => {
const packageJson = JSON.parse(readFileSync(join(packageRoot, "package.json"), "utf8")) as {
exports?: Record<string, WorkspacePackageExport>;
};
const rootIndexSource = readFileSync(join(packageRoot, "src/index.ts"), "utf8");
const componentsByDomain = new Map<(typeof allowedComponentDomains)[number], string[]>();
for (const domain of allowedComponentDomains) {
componentsByDomain.set(domain, []);
}
for (const component of componentInventory()) {
componentsByDomain.get(component.domain)?.push(component.name);
}
for (const domain of allowedComponentDomains) {
const domainIndexPath = join(componentsDir, domain, "index.ts");
const domainIndexSource = existsSync(domainIndexPath)
? readFileSync(domainIndexPath, "utf8")
: "";
expect(existsSync(domainIndexPath), `${domain} index is missing`).toBe(true);
expect(rootIndexSource).toContain(`export * from "./components/${domain}";`);
expect(packageJson.exports?.[`./${domain}`]).toMatchObject({
types: `./dist/components/${domain}/index.d.ts`,
development: `./src/components/${domain}/index.ts`,
default: `./dist/components/${domain}/index.js`,
});
for (const componentName of componentsByDomain.get(domain) ?? []) {
expect(domainIndexSource).toContain(
`export { ${componentName} } from "./${componentName}";`,
);
}
}
});
test("keeps Storybook fixtures generic and content-free", () => {
const storyText = readdirSync(storiesDir)
.filter((filename) => filename.endsWith(".tsx") || filename.endsWith(".ts"))
@ -174,12 +211,21 @@ function requiredComponentPath(component: string): string {
}
interface ComponentInventoryItem {
domain: (typeof allowedComponentDomains)[number];
name: string;
path: string;
relativeExportPath: string;
storyFile: string;
}
type WorkspacePackageExport =
| string
| {
types?: string;
development?: string;
default?: string;
};
function componentInventory(): ComponentInventoryItem[] {
const components = allowedComponentDomains
.flatMap((domain) => collectComponentFiles(join(componentsDir, domain)))
@ -208,12 +254,17 @@ function collectComponentFiles(directory: string): ComponentInventoryItem[] {
}
const name = basename(entry.name, ".tsx");
const relativeComponentPath = relative(componentsDir, entryPath).replace(/\\/g, "/");
const domain = relativeComponentPath.split(
"/",
)[0] as (typeof allowedComponentDomains)[number];
const relativeExportPath = `./${relative(join(packageRoot, "src"), entryPath)
.replace(/\\/g, "/")
.replace(/\.tsx$/, "")}`;
return [
{
domain,
name,
path: entryPath,
relativeExportPath,