@storyshelf/affected 0.7.0 → 0.8.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/git.d.mts +0 -2
- package/dist/git.mjs +1 -2
- package/dist/index.d.mts +0 -2
- package/dist/index.mjs +1 -2
- package/dist/select.d.mts +0 -2
- package/dist/select.mjs +1 -2
- package/dist/stats.d.mts +0 -2
- package/dist/stats.mjs +2 -4
- package/dist/stats.mjs.map +1 -1
- package/dist/trace.d.mts +0 -2
- package/dist/trace.mjs +1 -2
- package/dist/types.d.mts +0 -2
- package/dist/usage.d.mts +0 -2
- package/dist/usage.mjs +1 -2
- package/package.json +2 -2
package/dist/git.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
//#region src/git.d.ts
|
|
4
3
|
/** Upper bound on changed files before falling back to a full render. */
|
|
5
4
|
declare const MAX_CHANGED_FILES = 10000;
|
|
6
5
|
/** Prefix marking CLI-synthesized identities for checkouts without git. */
|
|
@@ -42,6 +41,5 @@ declare function gitHeadSha(cwd: string): string | null;
|
|
|
42
41
|
declare function gitBranchName(cwd: string): string | null;
|
|
43
42
|
/** Synthesize a unique local sha for checkouts without git. */
|
|
44
43
|
declare function localSha(): string;
|
|
45
|
-
//#endregion
|
|
46
44
|
export { GitRepoStatus, LOCAL_BRANCH, LOCAL_SHA_PREFIX, MAX_CHANGED_FILES, changedFiles, gitBranchName, gitHeadSha, gitRepoStatus, isShallowRepo, localSha };
|
|
47
45
|
//# sourceMappingURL=git.d.mts.map
|
package/dist/git.mjs
CHANGED
|
@@ -3,7 +3,7 @@ import "node:url";
|
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { execFileSync } from "node:child_process";
|
|
5
5
|
import { randomUUID } from "node:crypto";
|
|
6
|
-
|
|
6
|
+
// src/git.ts
|
|
7
7
|
/** Upper bound on changed files before falling back to a full render. */
|
|
8
8
|
const MAX_CHANGED_FILES = 1e4;
|
|
9
9
|
/** Prefix marking CLI-synthesized identities for checkouts without git. */
|
|
@@ -115,7 +115,6 @@ function gitBranchName(cwd) {
|
|
|
115
115
|
function localSha() {
|
|
116
116
|
return `${LOCAL_SHA_PREFIX}${randomUUID().replaceAll("-", "").slice(0, 12)}`;
|
|
117
117
|
}
|
|
118
|
-
//#endregion
|
|
119
118
|
export { LOCAL_BRANCH, LOCAL_SHA_PREFIX, MAX_CHANGED_FILES, changedFiles, gitBranchName, gitHeadSha, gitRepoStatus, isShallowRepo, localSha };
|
|
120
119
|
|
|
121
120
|
//# sourceMappingURL=git.mjs.map
|
package/dist/index.d.mts
CHANGED
|
@@ -6,7 +6,6 @@ import { STATS_FILENAME, buildGraph, graphModulesFor, loadDepGraph, loadStoryImp
|
|
|
6
6
|
import { matchesAnyGlob, traceAffected } from "./trace.mjs";
|
|
7
7
|
import { StoryPartition, selectAffectedStories } from "./select.mjs";
|
|
8
8
|
import { PackageUsage, TrackedPackage, extractPackageUsage } from "./usage.mjs";
|
|
9
|
-
//#region src/index.d.ts
|
|
10
9
|
/**
|
|
11
10
|
* Compute the affected story set for an upload. Never throws: every failure
|
|
12
11
|
* degrades to a full render with a machine-readable `fullReason`, so
|
|
@@ -15,6 +14,5 @@ import { PackageUsage, TrackedPackage, extractPackageUsage } from "./usage.mjs";
|
|
|
15
14
|
* @param input - Repository root, build dir, revisions, and trace options.
|
|
16
15
|
*/
|
|
17
16
|
declare function computeAffected(input: AffectedInput): Promise<AffectedResult>;
|
|
18
|
-
//#endregion
|
|
19
17
|
export { type AffectedInput, type AffectedResult, type DepGraph, type GitRepoStatus, LOCAL_BRANCH, LOCAL_SHA_PREFIX, MAX_CHANGED_FILES, type PackageUsage, STATS_FILENAME, type StoryLike, type StoryPartition, type TraceOptions, type TrackedPackage, buildGraph, changedFiles, computeAffected, extractPackageUsage, gitBranchName, gitHeadSha, gitRepoStatus, graphModulesFor, isShallowRepo, loadDepGraph, loadStoryImportPaths, localSha, matchesAnyGlob, normalizePath, selectAffectedStories, statsPathFor, traceAffected };
|
|
20
18
|
//# sourceMappingURL=index.d.mts.map
|
package/dist/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { STATS_FILENAME, buildGraph, graphModulesFor, loadDepGraph, loadStoryImp
|
|
|
6
6
|
import { matchesAnyGlob, traceAffected } from "./trace.mjs";
|
|
7
7
|
import { selectAffectedStories } from "./select.mjs";
|
|
8
8
|
import { extractPackageUsage } from "./usage.mjs";
|
|
9
|
-
|
|
9
|
+
// src/index.ts
|
|
10
10
|
/**
|
|
11
11
|
* Compute the affected story set for an upload. Never throws: every failure
|
|
12
12
|
* degrades to a full render with a machine-readable `fullReason`, so
|
|
@@ -70,7 +70,6 @@ async function computeSelective(input) {
|
|
|
70
70
|
return fullResult(changed, input.baseSha, reason);
|
|
71
71
|
}
|
|
72
72
|
}
|
|
73
|
-
//#endregion
|
|
74
73
|
export { LOCAL_BRANCH, LOCAL_SHA_PREFIX, MAX_CHANGED_FILES, STATS_FILENAME, buildGraph, changedFiles, computeAffected, extractPackageUsage, gitBranchName, gitHeadSha, gitRepoStatus, graphModulesFor, isShallowRepo, loadDepGraph, loadStoryImportPaths, localSha, matchesAnyGlob, normalizePath, selectAffectedStories, statsPathFor, traceAffected };
|
|
75
74
|
|
|
76
75
|
//# sourceMappingURL=index.mjs.map
|
package/dist/select.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
import { StoryLike } from "./types.mjs";
|
|
4
|
-
//#region src/select.d.ts
|
|
5
4
|
/** Stories split into render-now versus inherit-from-baseline sets. */
|
|
6
5
|
interface StoryPartition<T> {
|
|
7
6
|
/** Stories to capture in this build. */
|
|
@@ -19,6 +18,5 @@ interface StoryPartition<T> {
|
|
|
19
18
|
* @param affectedImportPaths - Affected import paths, or `null` for full.
|
|
20
19
|
*/
|
|
21
20
|
declare function selectAffectedStories<T extends StoryLike>(stories: readonly T[], affectedImportPaths: readonly string[] | null): StoryPartition<T>;
|
|
22
|
-
//#endregion
|
|
23
21
|
export { StoryPartition, selectAffectedStories };
|
|
24
22
|
//# sourceMappingURL=select.d.mts.map
|
package/dist/select.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import "node:path";
|
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { normalizePath } from "./stats.mjs";
|
|
5
|
-
|
|
5
|
+
// src/select.ts
|
|
6
6
|
/** Sort stories into render versus inherit buckets for an affected set. */
|
|
7
7
|
function partitionByPath(stories, affected, render, inherit) {
|
|
8
8
|
for (const story of stories) {
|
|
@@ -38,7 +38,6 @@ function selectAffectedStories(stories, affectedImportPaths) {
|
|
|
38
38
|
inherit
|
|
39
39
|
};
|
|
40
40
|
}
|
|
41
|
-
//#endregion
|
|
42
41
|
export { selectAffectedStories };
|
|
43
42
|
|
|
44
43
|
//# sourceMappingURL=select.mjs.map
|
package/dist/stats.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
import { DepGraph } from "./types.mjs";
|
|
4
|
-
//#region src/stats.d.ts
|
|
5
4
|
/** Basename of the Vite stats file emitted next to a built Storybook. */
|
|
6
5
|
declare const STATS_FILENAME = "preview-stats.json";
|
|
7
6
|
/** A single module entry in a stats file (Vite or Webpack shape). */
|
|
@@ -42,6 +41,5 @@ declare function statsPathFor(cwd: string, buildDir: string, override?: string):
|
|
|
42
41
|
declare function loadStoryImportPaths(cwd: string, buildDir: string): Promise<string[]>;
|
|
43
42
|
/** Find graph modules referring to repo-relative file `target`. */
|
|
44
43
|
declare function graphModulesFor(graph: DepGraph, target: string): string[];
|
|
45
|
-
//#endregion
|
|
46
44
|
export { STATS_FILENAME, buildGraph, graphModulesFor, loadDepGraph, loadStoryImportPaths, normalizePath, statsPathFor };
|
|
47
45
|
//# sourceMappingURL=stats.d.mts.map
|
package/dist/stats.mjs
CHANGED
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import "node:path";
|
|
1
|
+
import { join, resolve } from "node:path";
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { readFile } from "node:fs/promises";
|
|
5
|
-
|
|
6
|
-
//#region src/stats.ts
|
|
5
|
+
// src/stats.ts
|
|
7
6
|
/** Basename of the Vite stats file emitted next to a built Storybook. */
|
|
8
7
|
const STATS_FILENAME = "preview-stats.json";
|
|
9
8
|
/** Candidate index files listing a built Storybook's stories. */
|
|
@@ -166,7 +165,6 @@ function graphModulesFor(graph, target) {
|
|
|
166
165
|
for (const file of Object.keys(graph.importedBy)) if (matchesFile(file, target) && !matched.includes(file)) matched.push(file);
|
|
167
166
|
return matched;
|
|
168
167
|
}
|
|
169
|
-
//#endregion
|
|
170
168
|
export { STATS_FILENAME, buildGraph, graphModulesFor, loadDepGraph, loadStoryImportPaths, normalizePath, statsPathFor, stripQueryAndLoader };
|
|
171
169
|
|
|
172
170
|
//# sourceMappingURL=stats.mjs.map
|
package/dist/stats.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"stats.mjs","names":["record"],"sources":["../src/stats.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport type { DepGraph } from \"./types.ts\";\n\n/** Basename of the Vite stats file emitted next to a built Storybook. */\nexport const STATS_FILENAME = \"preview-stats.json\";\n\n/** Candidate index files listing a built Storybook's stories. */\nconst INDEX_CANDIDATES = [\"stories.json\", \"index.json\"];\n\n/** A single module entry in a stats file (Vite or Webpack shape). */\ninterface StatsModule {\n id?: unknown;\n name?: unknown;\n identifier?: unknown;\n imported?: unknown;\n importedIds?: unknown;\n dependencies?: unknown;\n reasons?: unknown;\n}\n\ninterface StoryIndex {\n entries?: Record<string, { importPath?: unknown }>;\n}\n\n/**\n * Strip bundler module-id decoration so sub-modules fold into their file:\n * webpack loader chains (`a-loader!b-loader??opts!./Button.vue`) keep only\n * the resource after the last `!`, and `?query` suffixes\n * (`Button.vue?vue&type=script`, `Card.svelte?svelte&type=style`) are dropped.\n */\nexport function stripQueryAndLoader(value: string): string {\n const resource = value.slice(value.lastIndexOf(\"!\") + 1);\n const queryStart = resource.indexOf(\"?\");\n return queryStart === -1 ? resource : resource.slice(0, queryStart);\n}\n\n/** Normalize a stats path to a repo-relative posix form for comparison. */\nexport function normalizePath(value: string): string {\n return stripQueryAndLoader(value)\n .replaceAll(\"\\\\\", \"/\")\n .replaceAll(/^\\.\\//gu, \"\")\n .replaceAll(/^\\//gu, \"\");\n}\n\n/** True when stats module `candidate` refers to repo-relative file `target`. */\nfunction matchesFile(candidate: string, target: string): boolean {\n if (candidate === target) {\n return true;\n }\n return candidate.endsWith(`/${target}`);\n}\n\n/** Coerce an unknown stats value to a list of normalized paths. */\nfunction asPathList(value: unknown): string[] {\n if (!Array.isArray(value)) {\n return [];\n }\n const paths: string[] = [];\n for (const entry of value) {\n if (typeof entry === \"string\" && entry.length > 0) {\n paths.push(normalizePath(entry));\n }\n }\n return paths;\n}\n\n/** Read a non-empty string field from a stats module entry. */\nfunction stringField(entry: StatsModule, key: \"id\" | \"name\" | \"identifier\"): string | null {\n const value = entry[key];\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\n/** Read the file a stats module entry refers to, if any. */\nfunction moduleFile(entry: StatsModule): string | null {\n const raw =\n stringField(entry, \"id\") ?? stringField(entry, \"name\") ?? stringField(entry, \"identifier\");\n return raw === null ? null : normalizePath(raw);\n}\n\n/** Forward imports declared by a stats module entry, if any. */\nfunction moduleImports(entry: StatsModule): string[] {\n return asPathList(entry.imported ?? entry.importedIds ?? entry.dependencies);\n}\n\n/** Dependent names declared via Webpack-style `reasons`, if any. */\nfunction moduleReasonNames(entry: StatsModule): string[] {\n if (!Array.isArray(entry.reasons)) {\n return [];\n }\n const names: string[] = [];\n for (const reason of entry.reasons) {\n if (typeof reason === \"object\" && reason !== null) {\n const record = reason as Record<string, unknown>;\n const name = record[\"moduleName\"] ?? record[\"module\"];\n if (typeof name === \"string\" && name.length > 0) {\n names.push(normalizePath(name));\n }\n }\n }\n return names;\n}\n\n/** Attach a record-shaped module entry to its name. */\nfunction entryWithName(name: string, value: unknown): StatsModule {\n if (typeof value === \"object\" && value !== null) {\n return { name, ...(value as StatsModule) };\n }\n return { name };\n}\n\n/** Extract module entries from a parsed stats document of unknown shape. */\nfunction moduleEntries(document: unknown): StatsModule[] {\n if (typeof document !== \"object\" || document === null) {\n return [];\n }\n const record = document as Record<string, unknown>;\n const raw = record[\"modules\"];\n if (Array.isArray(raw)) {\n return raw.filter((entry): entry is StatsModule => typeof entry === \"object\");\n }\n if (typeof raw === \"object\" && raw !== null) {\n return Object.entries(raw as Record<string, unknown>).map(([name, value]) =>\n entryWithName(name, value),\n );\n }\n return [];\n}\n\n/** Record one directed edge in the graph under construction. */\nfunction addEdge(\n imports: Map<string, Set<string>>,\n importedBy: Map<string, Set<string>>,\n from: string,\n to: string,\n): void {\n if (from === to) {\n return;\n }\n const forward = imports.get(from) ?? new Set<string>();\n forward.add(to);\n imports.set(from, forward);\n const reverse = importedBy.get(to) ?? new Set<string>();\n reverse.add(from);\n importedBy.set(to, reverse);\n}\n\n/** Add one stats entry's edges to the graph under construction. */\nfunction addEntryEdges(\n imports: Map<string, Set<string>>,\n importedBy: Map<string, Set<string>>,\n entry: StatsModule,\n): void {\n const file = moduleFile(entry);\n if (!file) {\n return;\n }\n for (const imported of moduleImports(entry)) {\n addEdge(imports, importedBy, file, imported);\n }\n for (const dependent of moduleReasonNames(entry)) {\n addEdge(imports, importedBy, dependent, file);\n }\n}\nfunction toGraph(\n imports: Map<string, Set<string>>,\n importedBy: Map<string, Set<string>>,\n): DepGraph {\n return {\n imports: Object.fromEntries([...imports].map(([file, set]) => [file, [...set].toSorted()])),\n importedBy: Object.fromEntries(\n [...importedBy].map(([file, set]) => [file, [...set].toSorted()]),\n ),\n };\n}\n\n/**\n * Build a bidirectional dependency graph from parsed stats modules.\n *\n * @param entries - Module entries from a Vite or Webpack stats document.\n * @returns Bidirectional graph, or `null` when no usable edges exist.\n */\nexport function buildGraph(entries: StatsModule[]): DepGraph | null {\n const imports = new Map<string, Set<string>>();\n const importedBy = new Map<string, Set<string>>();\n for (const entry of entries) {\n addEntryEdges(imports, importedBy, entry);\n }\n if (imports.size === 0) {\n return null;\n }\n return toGraph(imports, importedBy);\n}\n\n/**\n * Load and parse a stats file into a dependency graph.\n *\n * @param statsPath - Absolute or cwd-relative path to the stats JSON file.\n * @returns Graph, or `null` when the file is missing or unrecognized.\n */\nexport async function loadDepGraph(statsPath: string): Promise<DepGraph | null> {\n let raw: string;\n try {\n raw = await readFile(statsPath, \"utf8\");\n } catch {\n return null;\n }\n let document: unknown;\n try {\n document = JSON.parse(raw) as unknown;\n } catch {\n return null;\n }\n return buildGraph(moduleEntries(document));\n}\n\n/** Resolve the stats file path for a built Storybook directory. */\nexport function statsPathFor(cwd: string, buildDir: string, override?: string): string {\n if (override) {\n return resolve(cwd, override);\n }\n return join(resolve(cwd, buildDir), STATS_FILENAME);\n}\n\n/**\n * Load the deduplicated story import paths from a built Storybook's index.\n *\n * @param cwd - Repository root.\n * @param buildDir - Built Storybook directory.\n * @returns Normalized import paths; throws when no index is readable.\n */\nexport async function loadStoryImportPaths(cwd: string, buildDir: string): Promise<string[]> {\n const root = resolve(cwd, buildDir);\n const documents = await Promise.all(\n INDEX_CANDIDATES.map(async (name) => {\n try {\n return JSON.parse(await readFile(join(root, name), \"utf8\")) as StoryIndex;\n } catch {\n return null;\n }\n }),\n );\n const found = documents.find((document) => document !== null);\n if (!found?.entries) {\n throw new Error(`No Storybook index found in ${root}`);\n }\n const paths = new Set<string>();\n for (const entry of Object.values(found.entries)) {\n if (typeof entry.importPath === \"string\" && entry.importPath.length > 0) {\n paths.add(normalizePath(entry.importPath));\n }\n }\n return [...paths].toSorted();\n}\n\n/** Find graph modules referring to repo-relative file `target`. */\nexport function graphModulesFor(graph: DepGraph, target: string): string[] {\n const matched: string[] = [];\n for (const file of Object.keys(graph.imports)) {\n if (matchesFile(file, target)) {\n matched.push(file);\n }\n }\n for (const file of Object.keys(graph.importedBy)) {\n if (matchesFile(file, target) && !matched.includes(file)) {\n matched.push(file);\n }\n }\n return matched;\n}\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"stats.mjs","names":["record"],"sources":["../src/stats.ts"],"sourcesContent":["import { readFile } from \"node:fs/promises\";\nimport { join, resolve } from \"node:path\";\nimport type { DepGraph } from \"./types.ts\";\n\n/** Basename of the Vite stats file emitted next to a built Storybook. */\nexport const STATS_FILENAME = \"preview-stats.json\";\n\n/** Candidate index files listing a built Storybook's stories. */\nconst INDEX_CANDIDATES = [\"stories.json\", \"index.json\"];\n\n/** A single module entry in a stats file (Vite or Webpack shape). */\ninterface StatsModule {\n id?: unknown;\n name?: unknown;\n identifier?: unknown;\n imported?: unknown;\n importedIds?: unknown;\n dependencies?: unknown;\n reasons?: unknown;\n}\n\ninterface StoryIndex {\n entries?: Record<string, { importPath?: unknown }>;\n}\n\n/**\n * Strip bundler module-id decoration so sub-modules fold into their file:\n * webpack loader chains (`a-loader!b-loader??opts!./Button.vue`) keep only\n * the resource after the last `!`, and `?query` suffixes\n * (`Button.vue?vue&type=script`, `Card.svelte?svelte&type=style`) are dropped.\n */\nexport function stripQueryAndLoader(value: string): string {\n const resource = value.slice(value.lastIndexOf(\"!\") + 1);\n const queryStart = resource.indexOf(\"?\");\n return queryStart === -1 ? resource : resource.slice(0, queryStart);\n}\n\n/** Normalize a stats path to a repo-relative posix form for comparison. */\nexport function normalizePath(value: string): string {\n return stripQueryAndLoader(value)\n .replaceAll(\"\\\\\", \"/\")\n .replaceAll(/^\\.\\//gu, \"\")\n .replaceAll(/^\\//gu, \"\");\n}\n\n/** True when stats module `candidate` refers to repo-relative file `target`. */\nfunction matchesFile(candidate: string, target: string): boolean {\n if (candidate === target) {\n return true;\n }\n return candidate.endsWith(`/${target}`);\n}\n\n/** Coerce an unknown stats value to a list of normalized paths. */\nfunction asPathList(value: unknown): string[] {\n if (!Array.isArray(value)) {\n return [];\n }\n const paths: string[] = [];\n for (const entry of value) {\n if (typeof entry === \"string\" && entry.length > 0) {\n paths.push(normalizePath(entry));\n }\n }\n return paths;\n}\n\n/** Read a non-empty string field from a stats module entry. */\nfunction stringField(entry: StatsModule, key: \"id\" | \"name\" | \"identifier\"): string | null {\n const value = entry[key];\n return typeof value === \"string\" && value.length > 0 ? value : null;\n}\n\n/** Read the file a stats module entry refers to, if any. */\nfunction moduleFile(entry: StatsModule): string | null {\n const raw =\n stringField(entry, \"id\") ?? stringField(entry, \"name\") ?? stringField(entry, \"identifier\");\n return raw === null ? null : normalizePath(raw);\n}\n\n/** Forward imports declared by a stats module entry, if any. */\nfunction moduleImports(entry: StatsModule): string[] {\n return asPathList(entry.imported ?? entry.importedIds ?? entry.dependencies);\n}\n\n/** Dependent names declared via Webpack-style `reasons`, if any. */\nfunction moduleReasonNames(entry: StatsModule): string[] {\n if (!Array.isArray(entry.reasons)) {\n return [];\n }\n const names: string[] = [];\n for (const reason of entry.reasons) {\n if (typeof reason === \"object\" && reason !== null) {\n const record = reason as Record<string, unknown>;\n const name = record[\"moduleName\"] ?? record[\"module\"];\n if (typeof name === \"string\" && name.length > 0) {\n names.push(normalizePath(name));\n }\n }\n }\n return names;\n}\n\n/** Attach a record-shaped module entry to its name. */\nfunction entryWithName(name: string, value: unknown): StatsModule {\n if (typeof value === \"object\" && value !== null) {\n return { name, ...(value as StatsModule) };\n }\n return { name };\n}\n\n/** Extract module entries from a parsed stats document of unknown shape. */\nfunction moduleEntries(document: unknown): StatsModule[] {\n if (typeof document !== \"object\" || document === null) {\n return [];\n }\n const record = document as Record<string, unknown>;\n const raw = record[\"modules\"];\n if (Array.isArray(raw)) {\n return raw.filter((entry): entry is StatsModule => typeof entry === \"object\");\n }\n if (typeof raw === \"object\" && raw !== null) {\n return Object.entries(raw as Record<string, unknown>).map(([name, value]) =>\n entryWithName(name, value),\n );\n }\n return [];\n}\n\n/** Record one directed edge in the graph under construction. */\nfunction addEdge(\n imports: Map<string, Set<string>>,\n importedBy: Map<string, Set<string>>,\n from: string,\n to: string,\n): void {\n if (from === to) {\n return;\n }\n const forward = imports.get(from) ?? new Set<string>();\n forward.add(to);\n imports.set(from, forward);\n const reverse = importedBy.get(to) ?? new Set<string>();\n reverse.add(from);\n importedBy.set(to, reverse);\n}\n\n/** Add one stats entry's edges to the graph under construction. */\nfunction addEntryEdges(\n imports: Map<string, Set<string>>,\n importedBy: Map<string, Set<string>>,\n entry: StatsModule,\n): void {\n const file = moduleFile(entry);\n if (!file) {\n return;\n }\n for (const imported of moduleImports(entry)) {\n addEdge(imports, importedBy, file, imported);\n }\n for (const dependent of moduleReasonNames(entry)) {\n addEdge(imports, importedBy, dependent, file);\n }\n}\nfunction toGraph(\n imports: Map<string, Set<string>>,\n importedBy: Map<string, Set<string>>,\n): DepGraph {\n return {\n imports: Object.fromEntries([...imports].map(([file, set]) => [file, [...set].toSorted()])),\n importedBy: Object.fromEntries(\n [...importedBy].map(([file, set]) => [file, [...set].toSorted()]),\n ),\n };\n}\n\n/**\n * Build a bidirectional dependency graph from parsed stats modules.\n *\n * @param entries - Module entries from a Vite or Webpack stats document.\n * @returns Bidirectional graph, or `null` when no usable edges exist.\n */\nexport function buildGraph(entries: StatsModule[]): DepGraph | null {\n const imports = new Map<string, Set<string>>();\n const importedBy = new Map<string, Set<string>>();\n for (const entry of entries) {\n addEntryEdges(imports, importedBy, entry);\n }\n if (imports.size === 0) {\n return null;\n }\n return toGraph(imports, importedBy);\n}\n\n/**\n * Load and parse a stats file into a dependency graph.\n *\n * @param statsPath - Absolute or cwd-relative path to the stats JSON file.\n * @returns Graph, or `null` when the file is missing or unrecognized.\n */\nexport async function loadDepGraph(statsPath: string): Promise<DepGraph | null> {\n let raw: string;\n try {\n raw = await readFile(statsPath, \"utf8\");\n } catch {\n return null;\n }\n let document: unknown;\n try {\n document = JSON.parse(raw) as unknown;\n } catch {\n return null;\n }\n return buildGraph(moduleEntries(document));\n}\n\n/** Resolve the stats file path for a built Storybook directory. */\nexport function statsPathFor(cwd: string, buildDir: string, override?: string): string {\n if (override) {\n return resolve(cwd, override);\n }\n return join(resolve(cwd, buildDir), STATS_FILENAME);\n}\n\n/**\n * Load the deduplicated story import paths from a built Storybook's index.\n *\n * @param cwd - Repository root.\n * @param buildDir - Built Storybook directory.\n * @returns Normalized import paths; throws when no index is readable.\n */\nexport async function loadStoryImportPaths(cwd: string, buildDir: string): Promise<string[]> {\n const root = resolve(cwd, buildDir);\n const documents = await Promise.all(\n INDEX_CANDIDATES.map(async (name) => {\n try {\n return JSON.parse(await readFile(join(root, name), \"utf8\")) as StoryIndex;\n } catch {\n return null;\n }\n }),\n );\n const found = documents.find((document) => document !== null);\n if (!found?.entries) {\n throw new Error(`No Storybook index found in ${root}`);\n }\n const paths = new Set<string>();\n for (const entry of Object.values(found.entries)) {\n if (typeof entry.importPath === \"string\" && entry.importPath.length > 0) {\n paths.add(normalizePath(entry.importPath));\n }\n }\n return [...paths].toSorted();\n}\n\n/** Find graph modules referring to repo-relative file `target`. */\nexport function graphModulesFor(graph: DepGraph, target: string): string[] {\n const matched: string[] = [];\n for (const file of Object.keys(graph.imports)) {\n if (matchesFile(file, target)) {\n matched.push(file);\n }\n }\n for (const file of Object.keys(graph.importedBy)) {\n if (matchesFile(file, target) && !matched.includes(file)) {\n matched.push(file);\n }\n }\n return matched;\n}\n"],"mappings":"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"}
|
package/dist/trace.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
import { DepGraph, TraceOptions } from "./types.mjs";
|
|
4
|
-
//#region src/trace.d.ts
|
|
5
4
|
/** True when `path` matches any of the given glob patterns. */
|
|
6
5
|
declare function matchesAnyGlob(path: string, patterns: readonly string[]): boolean;
|
|
7
6
|
/**
|
|
@@ -14,6 +13,5 @@ declare function matchesAnyGlob(path: string, patterns: readonly string[]): bool
|
|
|
14
13
|
* @returns Affected story files, or `null` when everything must render.
|
|
15
14
|
*/
|
|
16
15
|
declare function traceAffected(graph: DepGraph, changedFiles: string[], storyFiles: readonly string[], options?: TraceOptions): string[] | null;
|
|
17
|
-
//#endregion
|
|
18
16
|
export { matchesAnyGlob, traceAffected };
|
|
19
17
|
//# sourceMappingURL=trace.d.mts.map
|
package/dist/trace.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import "node:path";
|
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { graphModulesFor } from "./stats.mjs";
|
|
5
|
-
|
|
5
|
+
// src/trace.ts
|
|
6
6
|
/** Basenames whose change invalidates every story (global render setup). */
|
|
7
7
|
const GLOBAL_BASENAMES = /* @__PURE__ */ new Set([
|
|
8
8
|
"preview.js",
|
|
@@ -160,7 +160,6 @@ function traceAffected(graph, changedFiles, storyFiles, options = {}) {
|
|
|
160
160
|
const storyOf = storyNodeMap(graph, storyFiles);
|
|
161
161
|
return [...reachableStories(graph, traceRoots(graph, relevant, storyOf), storyOf)].toSorted();
|
|
162
162
|
}
|
|
163
|
-
//#endregion
|
|
164
163
|
export { matchesAnyGlob, traceAffected };
|
|
165
164
|
|
|
166
165
|
//# sourceMappingURL=trace.mjs.map
|
package/dist/types.d.mts
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
|
-
//#region src/types.d.ts
|
|
4
3
|
/**
|
|
5
4
|
* Shared types for affected capture: dependency graphs, trace inputs, and
|
|
6
5
|
* the affected-set result. Zero runtime dependencies by design — both the
|
|
@@ -52,6 +51,5 @@ interface AffectedResult {
|
|
|
52
51
|
interface StoryLike {
|
|
53
52
|
importPath?: string | null;
|
|
54
53
|
}
|
|
55
|
-
//#endregion
|
|
56
54
|
export { AffectedInput, AffectedResult, DepGraph, StoryLike, TraceOptions };
|
|
57
55
|
//# sourceMappingURL=types.d.mts.map
|
package/dist/usage.d.mts
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import __tsdown_shims_path from 'node:path';
|
|
2
2
|
import __tsdown_shims_url from 'node:url';
|
|
3
3
|
import { DepGraph } from "./types.mjs";
|
|
4
|
-
//#region src/usage.d.ts
|
|
5
4
|
/** A dependency package a story file reaches, and the first module that reaches it. */
|
|
6
5
|
interface PackageUsage {
|
|
7
6
|
/** Story file (repo-relative, as given by the Storybook index). */
|
|
@@ -26,6 +25,5 @@ interface TrackedPackage {
|
|
|
26
25
|
* @param packages - Packages to track (e.g. the project's declared dependencies).
|
|
27
26
|
*/
|
|
28
27
|
declare function extractPackageUsage(graph: DepGraph, storyFiles: readonly string[], packages: Record<string, TrackedPackage>): PackageUsage[];
|
|
29
|
-
//#endregion
|
|
30
28
|
export { PackageUsage, TrackedPackage, extractPackageUsage };
|
|
31
29
|
//# sourceMappingURL=usage.d.mts.map
|
package/dist/usage.mjs
CHANGED
|
@@ -2,7 +2,7 @@ import "node:path";
|
|
|
2
2
|
import "node:url";
|
|
3
3
|
import.meta.url;
|
|
4
4
|
import { graphModulesFor } from "./stats.mjs";
|
|
5
|
-
|
|
5
|
+
// src/usage.ts
|
|
6
6
|
const NODE_MODULES = "node_modules/";
|
|
7
7
|
/** Package name for a `…/node_modules/<pkg>/…` module path, handling scopes. */
|
|
8
8
|
function nodeModulesPackage(module) {
|
|
@@ -60,7 +60,6 @@ function extractPackageUsage(graph, storyFiles, packages) {
|
|
|
60
60
|
const tracked = new Map(Object.entries(packages));
|
|
61
61
|
return storyFiles.flatMap((storyFile) => usageForStory(graph, storyFile, graphModulesFor(graph, storyFile), tracked));
|
|
62
62
|
}
|
|
63
|
-
//#endregion
|
|
64
63
|
export { extractPackageUsage };
|
|
65
64
|
|
|
66
65
|
//# sourceMappingURL=usage.mjs.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@storyshelf/affected",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.8.0",
|
|
4
4
|
"description": "Affected capture for StoryShelf: dependency-graph tracing that selects the stories impacted by a change.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"affected",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"oxlint-tsgolint": "^7.0.2001",
|
|
61
61
|
"tsdown": "^0.22.14",
|
|
62
62
|
"typescript": "^7.0.2",
|
|
63
|
-
"vitest": "^5.0.
|
|
63
|
+
"vitest": "^5.0.5"
|
|
64
64
|
},
|
|
65
65
|
"engines": {
|
|
66
66
|
"node": ">=24"
|