@variance-authority/storybook-collector 0.1.1 → 0.2.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/CHANGELOG.md +74 -0
- package/README.md +40 -38
- package/dist/contract.d.ts +23 -1
- package/dist/contract.js.map +1 -1
- package/dist/execution.d.ts +2 -2
- package/dist/execution.js +1 -1
- package/dist/execution.js.map +1 -1
- package/dist/index.d.ts +2 -132
- package/dist/index.js +140 -154
- package/dist/index.js.map +1 -1
- package/dist/options.d.ts +146 -0
- package/dist/options.js +2 -0
- package/dist/options.js.map +1 -0
- package/dist/page-agent-entry.js +2 -1
- package/dist/page-agent-entry.js.map +1 -1
- package/dist/page-agent.bundle.js +908 -541
- package/dist/page-agent.d.ts +27 -1
- package/dist/page-agent.js +16 -3
- package/dist/page-agent.js.map +1 -1
- package/dist/read.d.ts +44 -0
- package/dist/read.js +151 -0
- package/dist/read.js.map +1 -0
- package/dist/source.d.ts +1 -1
- package/dist/source.js +1 -1
- package/dist/source.js.map +1 -1
- package/dist/world.d.ts +59 -0
- package/dist/world.js +33 -0
- package/dist/world.js.map +1 -0
- package/package.json +9 -9
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,79 @@
|
|
|
1
1
|
# @variance-authority/storybook-collector
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- 8efba76: A run that changed ten files stops rewriting the whole selection index
|
|
8
|
+
|
|
9
|
+
Every run after the first reads the selection index, lays its own recording over
|
|
10
|
+
it, and writes it back. At a repository's scale almost all of that was spent
|
|
11
|
+
making objects nobody reads: a run that re-records ten modules of twenty thousand
|
|
12
|
+
decoded six hundred thousand regions into a model, merged ten of them, and
|
|
13
|
+
encoded the model back — the other 99.95% of the index materialized and
|
|
14
|
+
re-serialized to arrive at the bytes it was read from.
|
|
15
|
+
|
|
16
|
+
`layerTestCoverage` does the merge and the encode as one pass over the columns
|
|
17
|
+
the previous snapshot is already stored in. A module the run did not touch is
|
|
18
|
+
never made an object: its rows are copied column to column as integers, its
|
|
19
|
+
strings blob to blob as bytes, and the only thing that happens to either is the
|
|
20
|
+
renumbering the new dictionary implies. Objects are made for what the merge has
|
|
21
|
+
to reason about — the tests, the modules this run re-recorded, and the carried
|
|
22
|
+
modules whose text moved on disk. Over twenty thousand modules that is 1855 ms to
|
|
23
|
+
616, and it is byte for byte the same file, which a gate asserts across every
|
|
24
|
+
case the merge distinguishes.
|
|
25
|
+
|
|
26
|
+
The columns are now zstd rather than brotli, at two levels, because the runs are
|
|
27
|
+
two kinds of data. A varint run is a dense stream of small integers and answers
|
|
28
|
+
to a long search; a run of the string blob is file paths and hex digests, which
|
|
29
|
+
zstd finds most of at level 1 and nothing more of above it. Against the brotli
|
|
30
|
+
quality 4 it replaces, over the same snapshot: 319 ms to compress became 120, and
|
|
31
|
+
the file got 86 KB smaller.
|
|
32
|
+
|
|
33
|
+
`zlib.zstdCompressSync` arrived in Node 22.15, so that is the floor these
|
|
34
|
+
packages declare. The snapshot's layout version moved with the codec, which means
|
|
35
|
+
an index written by an earlier build is refused at its header and rebuilt — one
|
|
36
|
+
full run, and nothing a reader has to think about.
|
|
37
|
+
|
|
38
|
+
### Patch Changes
|
|
39
|
+
|
|
40
|
+
- e546e21: Where the JSX settings live under Vite 8
|
|
41
|
+
|
|
42
|
+
Vite 8 transforms with oxc, so `esbuild: { jsx, jsxDev, jsxImportSource }` becomes
|
|
43
|
+
`oxc: { jsx: { runtime, development, importSource } }`, and `esbuild.keepNames`
|
|
44
|
+
becomes `build.rolldownOptions.output.keepNames`. A config keeps whichever keys it
|
|
45
|
+
is given and reads only the ones its own major knows, so the wrong block is not an
|
|
46
|
+
error, not a warning and not a log line: the plugin installs, the bundle runs,
|
|
47
|
+
every subject renders, and every report names the line a component is declared on
|
|
48
|
+
instead of the line that wrote the element. It fails in the direction that looks
|
|
49
|
+
like it worked.
|
|
50
|
+
|
|
51
|
+
The `jsx-source` README carries a table of where the two settings live per
|
|
52
|
+
transform, both spellings on every copyable snippet, and the reminder to read
|
|
53
|
+
`provenanceOf`'s result rather than the config — the config cannot tell you.
|
|
54
|
+
`storybook-collector` gets the same for `keepNames`, on the symptom it produces: a
|
|
55
|
+
confident report naming a component that appears nowhere in your source.
|
|
56
|
+
- Updated dependencies [e546e21]
|
|
57
|
+
- Updated dependencies [8efba76]
|
|
58
|
+
- Updated dependencies [e546e21]
|
|
59
|
+
- Updated dependencies [d50e020]
|
|
60
|
+
- Updated dependencies [f4b328b]
|
|
61
|
+
- Updated dependencies [e546e21]
|
|
62
|
+
- Updated dependencies [e546e21]
|
|
63
|
+
- Updated dependencies [f4b328b]
|
|
64
|
+
- Updated dependencies [0718464]
|
|
65
|
+
- Updated dependencies [0718464]
|
|
66
|
+
- Updated dependencies [0718464]
|
|
67
|
+
- Updated dependencies [e546e21]
|
|
68
|
+
- Updated dependencies [e546e21]
|
|
69
|
+
- Updated dependencies [0718464]
|
|
70
|
+
- @variance-authority/core@0.2.0
|
|
71
|
+
- @variance-authority/sense@0.2.0
|
|
72
|
+
- @variance-authority/playwright@0.2.0
|
|
73
|
+
- @variance-authority/dom@0.2.0
|
|
74
|
+
- @variance-authority/react@0.2.0
|
|
75
|
+
- @variance-authority/storybook@0.2.0
|
|
76
|
+
|
|
3
77
|
## 0.1.1
|
|
4
78
|
|
|
5
79
|
### Patch Changes
|
package/README.md
CHANGED
|
@@ -56,26 +56,24 @@ still name components, but it cannot point to their declarations.
|
|
|
56
56
|
|
|
57
57
|
Against a built Storybook those names arrive minified — a run reports the cause
|
|
58
58
|
as `Ce`, not `Button`, because the bundler renamed it and nothing in the browser
|
|
59
|
-
remembers otherwise.
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
`@variance-authority/jsx-source` plugin in your `viteFinal` with
|
|
70
|
-
`esbuild.jsxDev` on; a report prefers the exact location wherever it comes
|
|
71
|
-
from, and this collector makes it repository-relative. The plugin does not
|
|
72
|
-
take `jsxImportSource`, so a Storybook already compiling against Emotion or
|
|
73
|
-
theme-ui keeps doing exactly that.
|
|
59
|
+
remembers otherwise. Preserve component names when the report must use them.
|
|
60
|
+
|
|
61
|
+
That scan names where a component is *declared* — one line however many times
|
|
62
|
+
that component is rendered.
|
|
63
|
+
|
|
64
|
+
For the line the changed element is actually written on, a **development**
|
|
65
|
+
Storybook needs no instrumentation. A **built** Storybook can opt into that
|
|
66
|
+
extra precision with `@variance-authority/jsx-source`; collection, comparison
|
|
67
|
+
and declaration-level attribution work without it. The build must emit
|
|
68
|
+
automatic development JSX, and the plugin belongs in `viteFinal`:
|
|
74
69
|
|
|
75
70
|
```bash
|
|
76
71
|
npm install --save-dev @variance-authority/jsx-source
|
|
77
72
|
```
|
|
78
73
|
|
|
74
|
+
See [`@variance-authority/jsx-source`](../jsx-source) for the Vite configuration
|
|
75
|
+
and for builds that already use Emotion, theme-ui or another custom JSX runtime.
|
|
76
|
+
|
|
79
77
|
### 3. Point the CLI at the Storybook index and collector
|
|
80
78
|
|
|
81
79
|
In `variance.config.json`, the index is the built file and `collector` is the
|
|
@@ -107,20 +105,19 @@ npx variance run --config variance.config.json
|
|
|
107
105
|
|
|
108
106
|
Each run writes `.variance/report.json`, the artifact everything else reads.
|
|
109
107
|
Run `npx variance report --config variance.config.json --format html >
|
|
110
|
-
.variance/report.html` and open the result in a browser to see before
|
|
111
|
-
images per changed story, grouped by cause rather than by story. The page
|
|
108
|
+
.variance/report.html` and open the result in a browser to see the before, diff and
|
|
109
|
+
after images per changed story, grouped by cause rather than by story. The page
|
|
112
110
|
references its images relatively, so it belongs beside the `report` path this
|
|
113
|
-
config declares; written anywhere else it shows broken images.
|
|
111
|
+
config declares; written anywhere else, it shows broken images.
|
|
114
112
|
|
|
115
113
|
The first successful run exits `1` and reports each story as `new`; a
|
|
116
|
-
baseline — the stored snapshot a subject is compared against — nobody
|
|
114
|
+
baseline — the stored snapshot a subject is compared against — that nobody
|
|
117
115
|
approved is not a pass. Review the candidates, accept the intended subjects,
|
|
118
|
-
and run again. The next unchanged run exits `0` without
|
|
119
|
-
|
|
120
|
-
not move.
|
|
116
|
+
and run again. The next unchanged run exits `0` without repainting the subjects
|
|
117
|
+
whose stored document digest already proves they did not change.
|
|
121
118
|
|
|
122
|
-
The executable `storybook-case` demonstrates the
|
|
123
|
-
|
|
119
|
+
The executable `storybook-case` demonstrates the complete cycle against a
|
|
120
|
+
Storybook-built artifact: new → accept → unchanged → a
|
|
124
121
|
`Button` edit changing exactly the five stories that render it.
|
|
125
122
|
|
|
126
123
|
## Options
|
|
@@ -135,6 +132,9 @@ complete cycle against a Storybook-built artifact: new → accept → unchanged
|
|
|
135
132
|
| `baseUrl` | Storybook is already running. | Omitted; the directory containing `subjects.index` is served on loopback for the run. |
|
|
136
133
|
| `headless` | You need to watch collection while debugging. | `true`; set `false` locally. |
|
|
137
134
|
| `network` | Asset bytes at stable URLs must participate in render identity. | `true`; set `false` only when asset URLs are already content-addressed. |
|
|
135
|
+
| `hashAssets` | Your asset URLs already carry their own content hash. | `true`. Read only while `network` is on, so GIF freezing and blanking survive it — this, not `network: false`, is the setting for a content-addressed build. |
|
|
136
|
+
| `wiring` | Your preview's renderer is not React, so the fiber walk buys an absent band. | `true`. A band of its own; turning it off changes no stored digest. |
|
|
137
|
+
| `holdings` | Application values behind the nodes are evidence you want carried. | `false`. Changes `structureHash` — an inert wrapper survives the collapse — so both sides of a comparison must be read the same way. |
|
|
138
138
|
| `roots` | Your preview mounts somewhere other than the standard roots. | `['#storybook-root', '#root']`, tightest match first. |
|
|
139
139
|
| `tests` | The next run should be able to skip stories whose code nothing touched. | `false`. Requires a preview built with `testSelectionProbes()` from `@variance-authority/sense/journal`; without a collector in the page the run says so on stderr and records nothing. |
|
|
140
140
|
|
|
@@ -146,8 +146,8 @@ source and page-agent shapes.
|
|
|
146
146
|
|
|
147
147
|
`tests` accepts `true` or `StoryExecutionOptions`: `root` is the repository root
|
|
148
148
|
the recorded paths are relative to, `label` must match the one the preview's
|
|
149
|
-
`testSelectionProbes()` was given, and `
|
|
150
|
-
the repository-keyed cache paths for the block
|
|
149
|
+
`testSelectionProbes()` was given, and `cacheRoot` and `coverageFile` override
|
|
150
|
+
the repository-keyed cache paths for the block records and the coverage index. A
|
|
151
151
|
story is its own owner in the recorded index — Storybook is an execution surface
|
|
152
152
|
this tool drives one subject at a time — and a story that did not render still
|
|
153
153
|
contributes its crossings while never justifying a later skip.
|
|
@@ -171,9 +171,8 @@ has already fired — the story function returned. A story still showing a
|
|
|
171
171
|
fallback when the wait runs out is reported as **not collected**, naming the open
|
|
172
172
|
boundaries and the components that wrote them, rather than recorded as a
|
|
173
173
|
baseline. A skeleton on a slow machine and the component on a fast one is a
|
|
174
|
-
difference no one authored, and every band — the severity category
|
|
175
|
-
accessibility down to sub-pixel noise
|
|
176
|
-
both.
|
|
174
|
+
difference no one authored, and every band — the severity category a change is filed
|
|
175
|
+
under, from accessibility down to sub-pixel noise — agrees with both.
|
|
177
176
|
|
|
178
177
|
Declare the exception when the fallback is the subject:
|
|
179
178
|
|
|
@@ -199,16 +198,19 @@ the other side.
|
|
|
199
198
|
resolved. Fix what it awaits, or add the story to `loading` if the fallback is
|
|
200
199
|
what you intend to review.
|
|
201
200
|
- **Components have names but no source lines:** add or correct `source.dirs`.
|
|
202
|
-
Production minification must also preserve component function names
|
|
203
|
-
|
|
201
|
+
Production minification must also preserve component function names. Vite 8
|
|
202
|
+
spells that `build.rolldownOptions.output.keepNames: true`; Vite 7 and below,
|
|
203
|
+
including the worked case, spell it `esbuild.keepNames: true`. A config
|
|
204
|
+
carrying the other major's key is read by nothing and warns about nothing, so
|
|
205
|
+
the symptom is a confident report naming a component that appears nowhere in
|
|
206
|
+
your source.
|
|
204
207
|
- **Elements report their component's declaration rather than their own line:**
|
|
205
|
-
|
|
206
|
-
`
|
|
207
|
-
|
|
208
|
-
Storybook nothing needs installing
|
|
209
|
-
its development build, the dev server
|
|
210
|
-
|
|
211
|
-
either mechanism to read.
|
|
208
|
+
this is the expected fallback for an uninstrumented built Storybook. Install
|
|
209
|
+
`jsx-source` only when the report must distinguish the exact element instance,
|
|
210
|
+
and make that build emit automatic development JSX. Against a development
|
|
211
|
+
Storybook nothing normally needs installing; missing lines there mean React
|
|
212
|
+
is not its development build, the dev server emits no source maps, or React 18
|
|
213
|
+
is still compiled to classic `createElement` calls.
|
|
212
214
|
- **Images change without a document change:** leave `network` enabled so asset
|
|
213
215
|
response bodies participate in the environment key. Disable it only when the
|
|
214
216
|
URL already identifies the bytes.
|
package/dist/contract.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { CallSiteResolver,
|
|
1
|
+
import type { CallSiteResolver, SourceIndex } from '@variance-authority/core/attribute';
|
|
2
|
+
import type { RenderDocument, SemanticSnapshot, SubjectRef, Viewport } from '@variance-authority/core/format';
|
|
2
3
|
/**
|
|
3
4
|
* The contract a collector satisfies, restated here rather than imported.
|
|
4
5
|
*
|
|
@@ -130,6 +131,27 @@ export interface Collector {
|
|
|
130
131
|
* this bounded, and a suite's subjects share their modules.
|
|
131
132
|
*/
|
|
132
133
|
readonly callSites?: CallSiteResolver;
|
|
134
|
+
/**
|
|
135
|
+
* Collect this subject again, in a world nothing else has touched.
|
|
136
|
+
*
|
|
137
|
+
* The saving this whole tool is built on is that the world is *not* rebuilt
|
|
138
|
+
* between subjects (ADR-0009): one browser, one page, one Storybook, for the
|
|
139
|
+
* length of a run. What it buys is the possibility that story B renders
|
|
140
|
+
* differently because story A ran first — and a comparison cannot tell that
|
|
141
|
+
* apart from a regression, because both arrive as "the pixels moved".
|
|
142
|
+
*
|
|
143
|
+
* One clean collection settles it. If the difference is gone with nothing else
|
|
144
|
+
* in the world, the baseline was right and the session moved this subject, and
|
|
145
|
+
* the run reports `order-dependent` rather than asking anybody to accept it.
|
|
146
|
+
*
|
|
147
|
+
* Optional in the contract the CLI declares, because a collector holding a
|
|
148
|
+
* single page open has no clean world to offer and the run says so rather than
|
|
149
|
+
* reading silence as "nothing leaked". This collector implements it: a
|
|
150
|
+
* Storybook preview can be opened twice, and the second one costs a browser
|
|
151
|
+
* launch — which is why the run only spends it on subjects it already called
|
|
152
|
+
* `changed`, up to `alone.limit`.
|
|
153
|
+
*/
|
|
154
|
+
collectAlone?(subject: PlannedSubject): Promise<Collected>;
|
|
133
155
|
close(): Promise<void>;
|
|
134
156
|
}
|
|
135
157
|
//# sourceMappingURL=contract.d.ts.map
|
package/dist/contract.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"","sourcesContent":["import type {\n
|
|
1
|
+
{"version":3,"file":"contract.js","sourceRoot":"","sources":["../src/contract.ts"],"names":[],"mappings":"","sourcesContent":["import type { CallSiteResolver, SourceIndex } from '@variance-authority/core/attribute';\nimport type {\n RenderDocument,\n SemanticSnapshot,\n SubjectRef,\n Viewport,\n} from '@variance-authority/core/format';\n\n/**\n * The contract a collector satisfies, restated here rather than imported.\n *\n * The CLI declares the same shapes and this package does not depend on it — a\n * surface package pulling in the binary would put a config parser, a docket and\n * six commands into an adopter's dependency tree to describe four values\n * (ADR-0024). What keeps the two copies honest is that the CLI imports *this*\n * collector in its own tests, so a drift between them fails a build rather than\n * a run.\n */\n\n/** The subset of a run's configuration this collector reads. */\nexport interface CollectorConfig {\n readonly viewport: Viewport;\n readonly fonts?: readonly string[];\n /**\n * Subtrees this project excludes, from `config.ignore` (spec 0024).\n *\n * Only the two fields a page needs: a rule id to record the mark under, and a\n * selector to find it with. Everything else about a rule — its reason, its\n * expiry, the bands it narrows to — is decided after collection, where a clock\n * and the whole run's diffs are available and a browser is not.\n */\n readonly ignore?: readonly {\n readonly id: string;\n readonly select?: string;\n /**\n * Subjects the rule names. Read here to decide what to send, and never sent.\n *\n * A page can resolve a selector and cannot know which subject it is one of,\n * so scoping has to happen on this side of the boundary. Without it a rule\n * written for one route marks its element in every subject that renders the\n * same shared layout, and a real regression inside that element is absorbed\n * everywhere — an ignore silencing more than it says, which is the one thing\n * the mechanism must not do.\n */\n readonly subjects?: readonly string[];\n\n /** Tags the subject must carry. Read here to decide what to send, never sent. */\n readonly tags?: readonly string[];\n }[];\n\n /**\n * Images to serve as nothing, from `config.blank`.\n *\n * Handed to the driver rather than to the page, because it is enforced on the\n * wire — before a byte is decoded, and therefore before the layout it would\n * have participated in exists. Not scoped by subject, and it cannot be: a\n * request carries no idea which subject will end up using it, which is the\n * same reason the asset map is per page rather than per subject.\n */\n readonly blank?: readonly {\n readonly id: string;\n readonly url?: string;\n readonly minPixels?: number;\n readonly maxPixels?: number;\n }[];\n\n /**\n * The subjects section of the config, as the operator wrote it.\n *\n * `index` is optional because it belongs to `subjects.kind: \"storybook\"`, and\n * a config naming any other kind still reaches this collector — the kind is\n * chosen in the config and the collector is chosen in the config, and nothing\n * makes the operator pick a matching pair. Typed as always present, the first\n * thing to read it hands `undefined` to `node:path` and the adopter gets a\n * TypeError about an argument instead of a sentence naming the wrong word.\n */\n readonly subjects: { readonly index?: string };\n}\n\nexport interface PlannedSubject {\n readonly subject: SubjectRef;\n readonly viewport?: Viewport;\n\n /**\n * What the subject declares itself to be, from the artifact that produced it.\n *\n * Storybook's built index carries `tags` and does not carry a story's\n * `parameters`, so a tag is the only per-story declaration that survives a\n * build — and it is the right one anyway: what a subject *is* belongs in its\n * own name, next to it, rather than in a central file repeating every id.\n *\n * Selection lives here; definition lives in the config. A tag is a word a\n * story wears, and what that word *means* is the operator's to write down\n * once, where a typo can be refused by name.\n */\n readonly tags?: readonly string[];\n}\n\nexport interface Plan {\n readonly subjects: readonly PlannedSubject[];\n readonly notObserved: readonly unknown[];\n readonly warnings: readonly string[];\n}\n\nexport type Collected =\n | {\n readonly ok: true;\n readonly document: RenderDocument;\n readonly snapshot?: SemanticSnapshot;\n readonly source?: SourceIndex;\n\n /**\n * Stabilization tricks applied to the page before this subject was read.\n *\n * Reported so a run can say what it did to somebody else's page. The\n * digest of the same list is in the environment key, which is what makes a\n * differently-stabilized baseline `incomparable`; this is the half a\n * person reads.\n */\n readonly stabilization?: readonly string[];\n }\n | { readonly ok: false; readonly because: string };\n\nexport interface CollectorContext {\n readonly config: CollectorConfig;\n /** Computed by the run from the story index. Returned unchanged. */\n readonly plan?: Plan;\n}\n\nexport interface Collector {\n plan(): Promise<Plan>;\n collect(subject: PlannedSubject): Promise<Collected>;\n\n /**\n * The frames a snapshot carries, spent on demand.\n *\n * Present when the collector drives a browser, because resolving a frame means\n * fetching the module it names and the page is the only place that request is\n * already correct. Absent otherwise, and absence is not a degradation: it means\n * either that nothing captured frames, or that the run has no live page to\n * fetch through — and both are a report without call sites rather than a\n * report that is wrong.\n *\n * Handed to `locateSites` with the few nodes a region or a finding names. The\n * resolver is per collector rather than per subject: the cache is what makes\n * this bounded, and a suite's subjects share their modules.\n */\n readonly callSites?: CallSiteResolver;\n\n /**\n * Collect this subject again, in a world nothing else has touched.\n *\n * The saving this whole tool is built on is that the world is *not* rebuilt\n * between subjects (ADR-0009): one browser, one page, one Storybook, for the\n * length of a run. What it buys is the possibility that story B renders\n * differently because story A ran first — and a comparison cannot tell that\n * apart from a regression, because both arrive as \"the pixels moved\".\n *\n * One clean collection settles it. If the difference is gone with nothing else\n * in the world, the baseline was right and the session moved this subject, and\n * the run reports `order-dependent` rather than asking anybody to accept it.\n *\n * Optional in the contract the CLI declares, because a collector holding a\n * single page open has no clean world to offer and the run says so rather than\n * reading silence as \"nothing leaked\". This collector implements it: a\n * Storybook preview can be opened twice, and the second one costs a browser\n * launch — which is why the run only spends it on subjects it already called\n * `changed`, up to `alone.limit`.\n */\n collectAlone?(subject: PlannedSubject): Promise<Collected>;\n\n close(): Promise<void>;\n}\n"]}
|
package/dist/execution.d.ts
CHANGED
|
@@ -19,8 +19,8 @@ export interface StoryExecutionOptions {
|
|
|
19
19
|
readonly root?: string;
|
|
20
20
|
/** Matches the `label` the build's `testSelectionProbes()` used. Defaults to `build`. */
|
|
21
21
|
readonly label?: string;
|
|
22
|
-
/**
|
|
23
|
-
readonly
|
|
22
|
+
/** Where the build wrote its block records. Defaults to the user cache. */
|
|
23
|
+
readonly cacheRoot?: string;
|
|
24
24
|
/** Coverage index. Defaults to the repository-keyed cache the runner seams share. */
|
|
25
25
|
readonly coverageFile?: string;
|
|
26
26
|
}
|
package/dist/execution.js
CHANGED
|
@@ -63,7 +63,7 @@ export async function createStoryRecorder(index, options) {
|
|
|
63
63
|
root,
|
|
64
64
|
subjects: observed,
|
|
65
65
|
...(options.label === undefined ? {} : { label: options.label }),
|
|
66
|
-
...(options.
|
|
66
|
+
...(options.cacheRoot === undefined ? {} : { cacheRoot: options.cacheRoot }),
|
|
67
67
|
...(options.coverageFile === undefined ? {} : { coverageFile: options.coverageFile }),
|
|
68
68
|
});
|
|
69
69
|
}
|
package/dist/execution.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"execution.js","sourceRoot":"","sources":["../src/execution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,GAGhB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAAa,EACb,OAA8B;IAE9B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,IAAI,IAAI,GAAG,KAAK,CAAC;IAEjB,OAAO;QACL,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE;YACxC,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,OAAO,KAAK,SAAS;gBAAE,OAAO;YAClC,IAAI,GAAG,IAAI,CAAC;YACZ,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YACjD,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACrC,MAAM,YAAY,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACvF,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,SAAS;gBAChB,OAAO;gBACP,QAAQ;gBACR,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC;aACzE,CAAC,CAAC;QACL,CAAC;QAED,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,+EAA+E;oBAC7E,+DAA+D;oBAC/D,sEAAsE;oBACtE,cAAc,CACjB,CAAC;gBACF,OAAO;YACT,CAAC;YACD,0EAA0E;YAC1E,0EAA0E;YAC1E,uEAAuE;YACvE,mDAAmD;YACnD,EAAE;YACF,wEAAwE;YACxE,uEAAuE;YACvE,uEAAuE;YACvE,uEAAuE;YACvE,yEAAyE;YACzE,uEAAuE;YACvE,oBAAoB;YACpB,IAAI,MAAmD,CAAC;YACxD,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,eAAe,CAAC;oBAC7B,IAAI;oBACJ,QAAQ,EAAE,QAAQ;oBAClB,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;oBAChE,GAAG,CAAC,OAAO,CAAC,
|
|
1
|
+
{"version":3,"file":"execution.js","sourceRoot":"","sources":["../src/execution.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAEH,OAAO,EAAE,QAAQ,EAAE,MAAM,kBAAkB,CAAC;AAC5C,OAAO,EACL,cAAc,EACd,cAAc,EACd,eAAe,GAGhB,MAAM,mCAAmC,CAAC;AAC3C,OAAO,EAAE,eAAe,EAAE,MAAM,+BAA+B,CAAC;AAChE,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AA4BpC,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,KAAa,EACb,OAA8B;IAE9B,MAAM,IAAI,GAAG,OAAO,CAAC,OAAO,CAAC,IAAI,IAAI,OAAO,CAAC,GAAG,EAAE,CAAC,CAAC;IACpD,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,QAAQ,GAAsB,EAAE,CAAC;IACvC,IAAI,IAAI,GAAG,KAAK,CAAC;IAEjB,OAAO;QACL,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,SAAS,EAAE,QAAQ,EAAE,EAAE;YACxC,MAAM,OAAO,GAAG,MAAM,cAAc,CAAC,IAAI,CAAC,CAAC;YAC3C,IAAI,OAAO,KAAK,SAAS;gBAAE,OAAO;YAClC,IAAI,GAAG,IAAI,CAAC;YACZ,MAAM,OAAO,GAAG,SAAS,CAAC,OAAO,CAAC,SAAS,EAAE,EAAE,CAAC,CAAC;YACjD,MAAM,IAAI,GAAG,UAAU,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC;YACrC,MAAM,YAAY,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,cAAc,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;YACvF,QAAQ,CAAC,IAAI,CAAC;gBACZ,KAAK,EAAE,SAAS;gBAChB,OAAO;gBACP,QAAQ;gBACR,GAAG,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,aAAa,EAAE,CAAC,YAAY,CAAC,EAAE,CAAC;aACzE,CAAC,CAAC;QACL,CAAC;QAED,KAAK,EAAE,KAAK,IAAI,EAAE;YAChB,IAAI,CAAC,IAAI,EAAE,CAAC;gBACV,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,+EAA+E;oBAC7E,+DAA+D;oBAC/D,sEAAsE;oBACtE,cAAc,CACjB,CAAC;gBACF,OAAO;YACT,CAAC;YACD,0EAA0E;YAC1E,0EAA0E;YAC1E,uEAAuE;YACvE,mDAAmD;YACnD,EAAE;YACF,wEAAwE;YACxE,uEAAuE;YACvE,uEAAuE;YACvE,uEAAuE;YACvE,yEAAyE;YACzE,uEAAuE;YACvE,oBAAoB;YACpB,IAAI,MAAmD,CAAC;YACxD,IAAI,CAAC;gBACH,MAAM,GAAG,MAAM,eAAe,CAAC;oBAC7B,IAAI;oBACJ,QAAQ,EAAE,QAAQ;oBAClB,GAAG,CAAC,OAAO,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,OAAO,CAAC,KAAK,EAAE,CAAC;oBAChE,GAAG,CAAC,OAAO,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,OAAO,CAAC,SAAS,EAAE,CAAC;oBAC5E,GAAG,CAAC,OAAO,CAAC,YAAY,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,YAAY,EAAE,OAAO,CAAC,YAAY,EAAE,CAAC;iBACtF,CAAC,CAAC;YACL,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,6EAA6E;oBAC3E,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,gBAAgB;oBACzE,yDAAyD,CAC5D,CAAC;gBACF,OAAO;YACT,CAAC;YACD,IAAI,CAAC,MAAM,CAAC,QAAQ,EAAE,CAAC;gBACrB,OAAO,CAAC,MAAM,CAAC,KAAK,CAClB,qDAAqD,MAAM,CAAC,OAAO,IAAI,CACxE,CAAC;YACJ,CAAC;QACH,CAAC;KACF,CAAC;AACJ,CAAC;AAED;;;;;;GAMG;AACH,KAAK,UAAU,cAAc,CAAC,KAAa;IACzC,MAAM,MAAM,GAAG,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC;IACjF,OAAO,IAAI,GAAG,CAAC,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,EAAE,EAAE,KAAK,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;AAC9E,CAAC","sourcesContent":["/**\n * What each story executed, recorded for the next run's selection.\n *\n * The instrument is the one `@variance-authority/sense` already uses; only the\n * transport differs, which is the rule\n * [spec 0028](../../../docs/specs/0028-the-instrument.md) states. The preview is\n * built with `testSelectionProbes()`, the page counts block crossings, and this\n * closes one window per story and joins them at the end of the run.\n *\n * A story is its own owner. Storybook is an execution surface this tool drives\n * one subject at a time, so — unlike a test runner, where the file is the\n * smallest thing a runner can be asked to execute — the crossings of one story\n * belong to that story and to nothing else.\n */\n\nimport { readFile } from 'node:fs/promises';\nimport {\n drainExecution,\n preconditionOf,\n recordExecution,\n type EvaluatingPage,\n type ObservedSubject,\n} from '@variance-authority/sense/journal';\nimport { parseStoryIndex } from '@variance-authority/storybook';\nimport { resolve } from 'node:path';\n\n/** Where a story run's execution evidence is joined, read and kept. */\nexport interface StoryExecutionOptions {\n /** Repository root the recorded paths are relative to. Defaults to the cwd. */\n readonly root?: string;\n /** Matches the `label` the build's `testSelectionProbes()` used. Defaults to `build`. */\n readonly label?: string;\n /** Where the build wrote its block records. Defaults to the user cache. */\n readonly cacheRoot?: string;\n /** Coverage index. Defaults to the repository-keyed cache the runner seams share. */\n readonly coverageFile?: string;\n}\n\n/** One run's accumulation: a window per story, written once at the end. */\nexport interface StoryRecorder {\n /**\n * Close one story's window.\n *\n * `complete` is false for a story this run refused. A refused story still\n * executed code, so its crossings are kept — what it may never do is justify\n * excluding itself from a later run.\n */\n readonly note: (page: EvaluatingPage, subjectId: string, complete: boolean) => Promise<void>;\n /** Merge the run into the index, or say on stderr why it could not. */\n readonly close: () => Promise<void>;\n}\n\nexport async function createStoryRecorder(\n index: string,\n options: StoryExecutionOptions,\n): Promise<StoryRecorder> {\n const root = resolve(options.root ?? process.cwd());\n const storyFiles = await storyFilesFrom(index);\n const observed: ObservedSubject[] = [];\n let seen = false;\n\n return {\n note: async (page, subjectId, complete) => {\n const journal = await drainExecution(page);\n if (journal === undefined) return;\n seen = true;\n const storyId = subjectId.replace(/^story:/, '');\n const file = storyFiles.get(storyId);\n const precondition = file === undefined ? undefined : await preconditionOf(root, file);\n observed.push({\n owner: subjectId,\n journal,\n complete,\n ...(precondition === undefined ? {} : { preconditions: [precondition] }),\n });\n },\n\n close: async () => {\n if (!seen) {\n process.stderr.write(\n 'variance-authority: `tests` is on and the Storybook preview has no execution ' +\n 'collector in it — build it with `testSelectionProbes()` from ' +\n '`@variance-authority/sense/journal`, or the next `--since` will run ' +\n 'everything\\n',\n );\n return;\n }\n // A refusal is written and the run continues. Recording is an addition to\n // a visual run: losing it costs the *next* selection its narrowing, which\n // is a full suite — the safe direction — while failing the run over it\n // would cost this one its baselines, which is not.\n //\n // That holds for a throw as much as for a refusal. The recorder reports\n // what it declined in `because`, but it is a file format, a lock and a\n // filesystem underneath, and any of them can raise something it has no\n // sentence for. Letting that escape ends the run *after* every subject\n // has been rendered and compared — the most expensive possible moment to\n // lose a set of baselines, and over the half of the work that was only\n // ever an addition.\n let record: Awaited<ReturnType<typeof recordExecution>>;\n try {\n record = await recordExecution({\n root,\n subjects: observed,\n ...(options.label === undefined ? {} : { label: options.label }),\n ...(options.cacheRoot === undefined ? {} : { cacheRoot: options.cacheRoot }),\n ...(options.coverageFile === undefined ? {} : { coverageFile: options.coverageFile }),\n });\n } catch (error) {\n process.stderr.write(\n 'variance-authority: recorded no story execution — the recorder failed with ' +\n `${error instanceof Error ? error.message : String(error)}; this run is ` +\n 'unaffected and the next `--since` will run everything\\n',\n );\n return;\n }\n if (!record.recorded) {\n process.stderr.write(\n `variance-authority: recorded no story execution — ${record.because}\\n`,\n );\n }\n },\n };\n}\n\n/**\n * Story id to the file that declares it, from the index the run is driving.\n *\n * The one route from a subject back to a file, and the reason a story's own\n * `.stories` file can select it: nothing *enters* a story file the way execution\n * enters a module, so without this a commit that edits one selects nothing.\n */\nasync function storyFilesFrom(index: string): Promise<Map<string, string>> {\n const parsed = parseStoryIndex(JSON.parse(await readFile(index, 'utf8')), index);\n return new Map(parsed.stories.map((story) => [story.id, story.importPath]));\n}\n"]}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,137 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import type { StorybookCollectorOptions } from './options.js';
|
|
2
2
|
export type { Collected, Collector, CollectorConfig, CollectorContext, Plan, PlannedSubject, } from './contract.js';
|
|
3
3
|
import type { Collector, CollectorContext } from './contract.js';
|
|
4
|
-
import { type SourceScan } from './source.js';
|
|
5
|
-
/**
|
|
6
|
-
* The Storybook collector, shipped.
|
|
7
|
-
*
|
|
8
|
-
* ## Why this package exists, stated as the thing it retracts
|
|
9
|
-
*
|
|
10
|
-
* This repository's position was that mounting is the adopter's, once, per
|
|
11
|
-
* project — and it measured the cost honestly at 341 lines rather than the
|
|
12
|
-
* "about thirty" the source had guessed. That position is right about React
|
|
13
|
-
* applications and wrong about Storybook, for a reason the measurement itself
|
|
14
|
-
* shows: of those 341 lines, the parts that were genuinely *this project's* were
|
|
15
|
-
* a map of three ready selectors, a directory to scan for components, and a
|
|
16
|
-
* static server. Everything else was Storybook's own contract being re-typed.
|
|
17
|
-
*
|
|
18
|
-
* A story index is a documented artifact. A preview owns its own mount and
|
|
19
|
-
* exposes a channel for switching stories. So for this one subject source the
|
|
20
|
-
* mounting problem is already solved by somebody else, and asking every adopter
|
|
21
|
-
* to re-solve it was charging them for our boundary rather than for their
|
|
22
|
-
* project.
|
|
23
|
-
*
|
|
24
|
-
* **What stays theirs.** Readiness per story, because Storybook's `storyRendered`
|
|
25
|
-
* fires when the story function returns — which for a component that defers work
|
|
26
|
-
* is *before the component exists*. That is knowledge about a component, and a
|
|
27
|
-
* project-wide default would be a guess about all of them.
|
|
28
|
-
*
|
|
29
|
-
* ## What it does not make generic
|
|
30
|
-
*
|
|
31
|
-
* Nothing outside Storybook. A Playwright suite, a route table or a bespoke
|
|
32
|
-
* mount is still a collector somebody writes — see
|
|
33
|
-
* [`@variance-authority/playwright-test`](../playwright-test) for the surface
|
|
34
|
-
* where the adopter's own test body plays that part instead.
|
|
35
|
-
*/
|
|
36
|
-
export interface StorybookCollectorOptions {
|
|
37
|
-
/**
|
|
38
|
-
* Story id to the selector that says it is ready.
|
|
39
|
-
*
|
|
40
|
-
* Per story, not per project, and that is the design rather than an
|
|
41
|
-
* ergonomics gap. A button needs no marker and demanding one from it would
|
|
42
|
-
* time out every story to solve a problem one of them has. A story that
|
|
43
|
-
* declares a marker and never attaches it times out saying which selector it
|
|
44
|
-
* waited for — there is no fallback, because falling back is how you
|
|
45
|
-
* photograph a spinner and call it a component.
|
|
46
|
-
*/
|
|
47
|
-
readonly ready?: Readonly<Record<string, string>>;
|
|
48
|
-
/**
|
|
49
|
-
* Where the components live, for `file:line` attribution.
|
|
50
|
-
*
|
|
51
|
-
* Omitted, the report names components and no files — which is still ahead of
|
|
52
|
-
* every product in the category and is not what this is for.
|
|
53
|
-
*/
|
|
54
|
-
readonly source?: SourceScan;
|
|
55
|
-
/**
|
|
56
|
-
* A Storybook that is already served, e.g. `http://localhost:6006`.
|
|
57
|
-
*
|
|
58
|
-
* Preferred when it exists: then nothing here has an opinion about how the
|
|
59
|
-
* build is hosted. Omitted, the directory holding `subjects.index` is served
|
|
60
|
-
* on a loopback port for the life of the run.
|
|
61
|
-
*/
|
|
62
|
-
readonly baseUrl?: string;
|
|
63
|
-
/** Defaults to `true`. Set false to watch a run by hand. */
|
|
64
|
-
readonly headless?: boolean;
|
|
65
|
-
/**
|
|
66
|
-
* Watch the wire: hash asset bodies into the environment key, and serve
|
|
67
|
-
* animated GIFs as their first frame. Defaults to `true`.
|
|
68
|
-
*
|
|
69
|
-
* On, this is what closes a false `unchanged` that a page cannot see about
|
|
70
|
-
* itself. A logo re-exported at the same URL is the same markup, the same CSS
|
|
71
|
-
* and the same document — so every tier settles, and the run reports that
|
|
72
|
-
* nothing moved while the image on the page is different bytes. Only the party
|
|
73
|
-
* that saw the response knows otherwise.
|
|
74
|
-
*
|
|
75
|
-
* The assets are narrowed **per story** before they reach a key, from the URLs
|
|
76
|
-
* that story's own subtree references (`assetsFor`). Without that, a run that
|
|
77
|
-
* reads three hundred stories out of one page would give story 200 a key that
|
|
78
|
-
* depends on which stories ran before it, and sharding the suite would change
|
|
79
|
-
* every baseline's identity.
|
|
80
|
-
*
|
|
81
|
-
* Off is a position for a build whose asset URLs already contain their own
|
|
82
|
-
* content hash: the URL is then the identity, and hashing the bytes again buys
|
|
83
|
-
* a read and nothing else.
|
|
84
|
-
*/
|
|
85
|
-
readonly network?: boolean;
|
|
86
|
-
/** Overrides the roots the story is read from. Tightest first. */
|
|
87
|
-
readonly roots?: readonly string[];
|
|
88
|
-
/** Milliseconds for Storybook or a declared marker to report readiness. Defaults to 15000. */
|
|
89
|
-
readonly readyTimeoutMs?: number;
|
|
90
|
-
/**
|
|
91
|
-
* Milliseconds to wait for a story's Suspense boundaries. Defaults to 5000.
|
|
92
|
-
*
|
|
93
|
-
* Paid only by stories that are actually waiting: a subtree with no boundary
|
|
94
|
-
* in it returns on the first read. `0` turns the wait off and keeps the
|
|
95
|
-
* reading, which is a position for a project whose readiness markers already
|
|
96
|
-
* cover its data — the refusal below still fires, so the boundary is reported
|
|
97
|
-
* rather than photographed.
|
|
98
|
-
*/
|
|
99
|
-
readonly suspenseTimeoutMs?: number;
|
|
100
|
-
/**
|
|
101
|
-
* Record what each story executed, into the shared test-selection index.
|
|
102
|
-
*
|
|
103
|
-
* Off unless asked for, and it asks something of the build rather than of this
|
|
104
|
-
* package: the Storybook preview has to have been built with
|
|
105
|
-
* `testSelectionProbes()` from `@variance-authority/sense/journal`, which is
|
|
106
|
-
* what puts probes in the source and writes down what their ordinals mean.
|
|
107
|
-
* Without it a run records nothing and says so on stderr — the next selection
|
|
108
|
-
* then runs everything, which is the direction every uncertainty here
|
|
109
|
-
* resolves.
|
|
110
|
-
*
|
|
111
|
-
* A story is its own owner in that index. Storybook is an execution surface
|
|
112
|
-
* this tool drives one subject at a time, so unlike a test runner — where the
|
|
113
|
-
* file is the smallest thing a runner can be asked to execute — the crossings
|
|
114
|
-
* of one story belong to that story and to nothing else.
|
|
115
|
-
*/
|
|
116
|
-
readonly tests?: boolean | StoryExecutionOptions;
|
|
117
|
-
/**
|
|
118
|
-
* Stories whose *loading* state is the subject, as id globs.
|
|
119
|
-
*
|
|
120
|
-
* The escape hatch, and the only one. A story left showing its fallback is
|
|
121
|
-
* otherwise refused, because a subject that records a skeleton on a slow
|
|
122
|
-
* machine and a component on a fast one is a flake nobody wrote — so a
|
|
123
|
-
* skeleton somebody *does* want a baseline over has to be said out loud.
|
|
124
|
-
*
|
|
125
|
-
* Declared here rather than sensed, and checked in both directions: a story
|
|
126
|
-
* named by this that turns out to settle is refused too. A declaration that
|
|
127
|
-
* outlived its subject is the same nondeterminism arriving from the other side.
|
|
128
|
-
*
|
|
129
|
-
* Matched against the story id and the subject id both, so
|
|
130
|
-
* `case-surface--feed` and `story:case-surface--feed` name the same story —
|
|
131
|
-
* `ready` above is keyed by the first.
|
|
132
|
-
*/
|
|
133
|
-
readonly loading?: readonly string[];
|
|
134
|
-
}
|
|
135
4
|
/**
|
|
136
5
|
* Build the module a `subjects.collector` path should default-export.
|
|
137
6
|
*
|
|
@@ -149,6 +18,7 @@ export interface StorybookCollectorOptions {
|
|
|
149
18
|
* ```
|
|
150
19
|
*/
|
|
151
20
|
export declare function storybookCollector(options?: StorybookCollectorOptions): (context: CollectorContext) => Promise<Collector>;
|
|
21
|
+
export type { StorybookCollectorOptions } from './options.js';
|
|
152
22
|
export type { StoryExecutionOptions } from './execution.js';
|
|
153
23
|
export type { SourceScan } from './source.js';
|
|
154
24
|
export type { AcquireRequest, Acquired } from './page-agent.js';
|