@setsquare/review-sdk 0.0.1
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/LICENSE +202 -0
- package/NOTICE +57 -0
- package/README.md +338 -0
- package/THIRD-PARTY-NOTICES.md +61 -0
- package/dist/autoscan.d.ts +25 -0
- package/dist/autoscan.d.ts.map +1 -0
- package/dist/autoscan.js +332 -0
- package/dist/autoscan.js.map +1 -0
- package/dist/axe.d.ts +96 -0
- package/dist/axe.d.ts.map +1 -0
- package/dist/axe.js +210 -0
- package/dist/axe.js.map +1 -0
- package/dist/bin/setsquare.d.ts +3 -0
- package/dist/bin/setsquare.d.ts.map +1 -0
- package/dist/bin/setsquare.js +21 -0
- package/dist/bin/setsquare.js.map +1 -0
- package/dist/brand.d.ts +84 -0
- package/dist/brand.d.ts.map +1 -0
- package/dist/brand.js +335 -0
- package/dist/brand.js.map +1 -0
- package/dist/checks/dynamic.d.ts +57 -0
- package/dist/checks/dynamic.d.ts.map +1 -0
- package/dist/checks/dynamic.js +184 -0
- package/dist/checks/dynamic.js.map +1 -0
- package/dist/checks/rule-pack.d.ts +34 -0
- package/dist/checks/rule-pack.d.ts.map +1 -0
- package/dist/checks/rule-pack.js +270 -0
- package/dist/checks/rule-pack.js.map +1 -0
- package/dist/checks/versions.d.ts +28 -0
- package/dist/checks/versions.d.ts.map +1 -0
- package/dist/checks/versions.js +45 -0
- package/dist/checks/versions.js.map +1 -0
- package/dist/ci.d.ts +37 -0
- package/dist/ci.d.ts.map +1 -0
- package/dist/ci.js +199 -0
- package/dist/ci.js.map +1 -0
- package/dist/contract.d.ts +334 -0
- package/dist/contract.d.ts.map +1 -0
- package/dist/contract.js +35 -0
- package/dist/contract.js.map +1 -0
- package/dist/dedupe.d.ts +79 -0
- package/dist/dedupe.d.ts.map +1 -0
- package/dist/dedupe.js +102 -0
- package/dist/dedupe.js.map +1 -0
- package/dist/document.d.ts +29 -0
- package/dist/document.d.ts.map +1 -0
- package/dist/document.js +94 -0
- package/dist/document.js.map +1 -0
- package/dist/envelope.d.ts +124 -0
- package/dist/envelope.d.ts.map +1 -0
- package/dist/envelope.js +337 -0
- package/dist/envelope.js.map +1 -0
- package/dist/escape.d.ts +14 -0
- package/dist/escape.d.ts.map +1 -0
- package/dist/escape.js +20 -0
- package/dist/escape.js.map +1 -0
- package/dist/findings.d.ts +47 -0
- package/dist/findings.d.ts.map +1 -0
- package/dist/findings.js +229 -0
- package/dist/findings.js.map +1 -0
- package/dist/fixture.d.ts +7 -0
- package/dist/fixture.d.ts.map +1 -0
- package/dist/fixture.js +237 -0
- package/dist/fixture.js.map +1 -0
- package/dist/group.d.ts +214 -0
- package/dist/group.d.ts.map +1 -0
- package/dist/group.js +709 -0
- package/dist/group.js.map +1 -0
- package/dist/html-report.d.ts +68 -0
- package/dist/html-report.d.ts.map +1 -0
- package/dist/html-report.js +649 -0
- package/dist/html-report.js.map +1 -0
- package/dist/human.d.ts +65 -0
- package/dist/human.d.ts.map +1 -0
- package/dist/human.js +111 -0
- package/dist/human.js.map +1 -0
- package/dist/index.d.ts +34 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +33 -0
- package/dist/index.js.map +1 -0
- package/dist/infer.d.ts +65 -0
- package/dist/infer.d.ts.map +1 -0
- package/dist/infer.js +67 -0
- package/dist/infer.js.map +1 -0
- package/dist/insights.d.ts +140 -0
- package/dist/insights.d.ts.map +1 -0
- package/dist/insights.js +483 -0
- package/dist/insights.js.map +1 -0
- package/dist/install.d.ts +8 -0
- package/dist/install.d.ts.map +1 -0
- package/dist/install.js +114 -0
- package/dist/install.js.map +1 -0
- package/dist/links.d.ts +45 -0
- package/dist/links.d.ts.map +1 -0
- package/dist/links.js +45 -0
- package/dist/links.js.map +1 -0
- package/dist/mask.d.ts +85 -0
- package/dist/mask.d.ts.map +1 -0
- package/dist/mask.js +98 -0
- package/dist/mask.js.map +1 -0
- package/dist/observe.d.ts +51 -0
- package/dist/observe.d.ts.map +1 -0
- package/dist/observe.js +233 -0
- package/dist/observe.js.map +1 -0
- package/dist/options.d.ts +249 -0
- package/dist/options.d.ts.map +1 -0
- package/dist/options.js +185 -0
- package/dist/options.js.map +1 -0
- package/dist/output.d.ts +113 -0
- package/dist/output.d.ts.map +1 -0
- package/dist/output.js +231 -0
- package/dist/output.js.map +1 -0
- package/dist/perf.d.ts +11 -0
- package/dist/perf.d.ts.map +1 -0
- package/dist/perf.js +150 -0
- package/dist/perf.js.map +1 -0
- package/dist/reading-level.d.ts +73 -0
- package/dist/reading-level.d.ts.map +1 -0
- package/dist/reading-level.js +189 -0
- package/dist/reading-level.js.map +1 -0
- package/dist/reporter.d.ts +94 -0
- package/dist/reporter.d.ts.map +1 -0
- package/dist/reporter.js +709 -0
- package/dist/reporter.js.map +1 -0
- package/dist/rules.d.ts +55 -0
- package/dist/rules.d.ts.map +1 -0
- package/dist/rules.js +77 -0
- package/dist/rules.js.map +1 -0
- package/dist/runtime.d.ts +32 -0
- package/dist/runtime.d.ts.map +1 -0
- package/dist/runtime.js +67 -0
- package/dist/runtime.js.map +1 -0
- package/dist/sanitise.d.ts +116 -0
- package/dist/sanitise.d.ts.map +1 -0
- package/dist/sanitise.js +247 -0
- package/dist/sanitise.js.map +1 -0
- package/dist/scan.d.ts +60 -0
- package/dist/scan.d.ts.map +1 -0
- package/dist/scan.js +246 -0
- package/dist/scan.js.map +1 -0
- package/dist/screens.d.ts +98 -0
- package/dist/screens.d.ts.map +1 -0
- package/dist/screens.js +301 -0
- package/dist/screens.js.map +1 -0
- package/dist/settle.d.ts +65 -0
- package/dist/settle.d.ts.map +1 -0
- package/dist/settle.js +162 -0
- package/dist/settle.js.map +1 -0
- package/dist/shots.d.ts +109 -0
- package/dist/shots.d.ts.map +1 -0
- package/dist/shots.js +113 -0
- package/dist/shots.js.map +1 -0
- package/dist/style.d.ts +47 -0
- package/dist/style.d.ts.map +1 -0
- package/dist/style.js +154 -0
- package/dist/style.js.map +1 -0
- package/dist/suite.d.ts +218 -0
- package/dist/suite.d.ts.map +1 -0
- package/dist/suite.js +219 -0
- package/dist/suite.js.map +1 -0
- package/dist/summary.d.ts +268 -0
- package/dist/summary.d.ts.map +1 -0
- package/dist/summary.js +1308 -0
- package/dist/summary.js.map +1 -0
- package/dist/unscannable.d.ts +75 -0
- package/dist/unscannable.d.ts.map +1 -0
- package/dist/unscannable.js +111 -0
- package/dist/unscannable.js.map +1 -0
- package/dist/versions.d.ts +13 -0
- package/dist/versions.d.ts.map +1 -0
- package/dist/versions.js +39 -0
- package/dist/versions.js.map +1 -0
- package/dist/wcag-map.d.ts +19 -0
- package/dist/wcag-map.d.ts.map +1 -0
- package/dist/wcag-map.js +52 -0
- package/dist/wcag-map.js.map +1 -0
- package/dist/with-setsquare.d.ts +26 -0
- package/dist/with-setsquare.d.ts.map +1 -0
- package/dist/with-setsquare.js +70 -0
- package/dist/with-setsquare.js.map +1 -0
- package/package.json +81 -0
|
@@ -0,0 +1,249 @@
|
|
|
1
|
+
import type { InferenceConfig } from './infer.js';
|
|
2
|
+
import type { MaskConfig } from './mask.js';
|
|
3
|
+
import { type RulePolicy } from './rules.js';
|
|
4
|
+
import { type SettleConfig } from './settle.js';
|
|
5
|
+
/**
|
|
6
|
+
* Configuration for `withSetsquare()`.
|
|
7
|
+
*
|
|
8
|
+
* Everything here is optional, and that is the product claim rather than a
|
|
9
|
+
* convenience: the promise is a single config line, so an empty options object
|
|
10
|
+
* has to produce a useful run. Options exist to correct inference, never to
|
|
11
|
+
* enable it.
|
|
12
|
+
*/
|
|
13
|
+
export interface SetsquareOptions {
|
|
14
|
+
/**
|
|
15
|
+
* Where the run envelope and its sidecar are written.
|
|
16
|
+
*
|
|
17
|
+
* Relative paths resolve against the Playwright config's directory, not the
|
|
18
|
+
* process working directory — a suite run from a monorepo root and the same
|
|
19
|
+
* suite run from its own package must put their output in the same place, or
|
|
20
|
+
* the artifact moves depending on where you were standing.
|
|
21
|
+
*/
|
|
22
|
+
outputDir?: string;
|
|
23
|
+
/**
|
|
24
|
+
* Print the closing block that explains what the platform adds.
|
|
25
|
+
*
|
|
26
|
+
* Once per run, at the end, five lines at most, derived from the run's own
|
|
27
|
+
* numbers. Off is honoured without complaint — a tool that nags is a tool
|
|
28
|
+
* people configure around, and then they have configured away the summary too.
|
|
29
|
+
*/
|
|
30
|
+
promo?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* The WCAG conformance level to assess against. Defaults to `AA`.
|
|
33
|
+
*
|
|
34
|
+
* AA is the floor because it is what conformance normally means in practice
|
|
35
|
+
* and what procurement, EN 301 549 and the EAA actually ask for. AAA is opt-in
|
|
36
|
+
* rather than default because it is a deliberate commitment — WCAG itself does
|
|
37
|
+
* not recommend AAA as a general policy, since some AAA criteria cannot be
|
|
38
|
+
* satisfied for all content, so defaulting to it would report every team as
|
|
39
|
+
* failing a bar they never set.
|
|
40
|
+
*/
|
|
41
|
+
wcag?: 'AA' | 'AAA';
|
|
42
|
+
/**
|
|
43
|
+
* Include axe's 30 advisory `best-practice` rules. Defaults to `false`.
|
|
44
|
+
*
|
|
45
|
+
* They catch real problems and are worth turning on. They are off by default
|
|
46
|
+
* because they are NOT WCAG failures, and a conformance grid that mixes advice
|
|
47
|
+
* with conformance cannot honestly answer "does this meet AA?". Findings from
|
|
48
|
+
* them are always distinguishable in the payload — a best-practice rule carries
|
|
49
|
+
* no `wcag` block.
|
|
50
|
+
*/
|
|
51
|
+
bestPractice?: boolean;
|
|
52
|
+
/** Scan automatically on settled navigation. On by default — it is the promise. */
|
|
53
|
+
autoScan?: boolean;
|
|
54
|
+
/** How long a page must be quiet before it counts as settled. Default 500ms. */
|
|
55
|
+
quietMs?: number;
|
|
56
|
+
/**
|
|
57
|
+
* Hard ceiling before scanning anyway. Default 5000ms.
|
|
58
|
+
*
|
|
59
|
+
* A page that never goes quiet is common — a spinner, a poller, a carousel —
|
|
60
|
+
* and declining to scan it would produce 'no findings', which reads as 'no
|
|
61
|
+
* problems'. On expiry the scan happens and the payload records that it did.
|
|
62
|
+
*/
|
|
63
|
+
settleTimeoutMs?: number;
|
|
64
|
+
/** Route pattern to surface name: `{ '/items/:id/edit': 'item-editor' }`. */
|
|
65
|
+
surfaces?: InferenceConfig['surfaces'];
|
|
66
|
+
/** Playwright project name to persona. */
|
|
67
|
+
personas?: InferenceConfig['personas'];
|
|
68
|
+
/** Playwright project name to theme. */
|
|
69
|
+
themes?: InferenceConfig['themes'];
|
|
70
|
+
/** The escape hatch for suites whose project names carry neither. */
|
|
71
|
+
persona?: InferenceConfig['persona'];
|
|
72
|
+
theme?: InferenceConfig['theme'];
|
|
73
|
+
/**
|
|
74
|
+
* Extra regions to mask, composed WITH the built-in defaults.
|
|
75
|
+
*
|
|
76
|
+
* Masking has no effect on the local path, which writes no images at all —
|
|
77
|
+
* it is configured here so the posture is set before any bytes are ever
|
|
78
|
+
* captured, rather than being bolted on when upload arrives.
|
|
79
|
+
*/
|
|
80
|
+
mask?: MaskConfig['mask'];
|
|
81
|
+
/** Drop the built-in mask defaults. A deliberate, documented act. */
|
|
82
|
+
maskDefaults?: MaskConfig['maskDefaults'];
|
|
83
|
+
/**
|
|
84
|
+
* How the run's summary is printed.
|
|
85
|
+
*
|
|
86
|
+
* `text` is for a human at a terminal. `markdown` survives being pasted into
|
|
87
|
+
* Slack, an issue, or an LLM prompt — which is the main thing that happens to
|
|
88
|
+
* this output. `json` is for a machine, and omits the closing block entirely.
|
|
89
|
+
*/
|
|
90
|
+
format?: 'text' | 'markdown' | 'json';
|
|
91
|
+
/**
|
|
92
|
+
* How the conformance grid renders in the terminal summary. Default `matrix`.
|
|
93
|
+
*
|
|
94
|
+
* `matrix` draws criteria × surfaces as aligned single-glyph columns — no
|
|
95
|
+
* box-drawing, so it survives being pasted — and falls back to per-criterion
|
|
96
|
+
* rows by itself when the run has more surfaces than the width budget fits.
|
|
97
|
+
* `rows` skips the matrix always, for people who find it noise.
|
|
98
|
+
*/
|
|
99
|
+
grid?: 'matrix' | 'rows';
|
|
100
|
+
/**
|
|
101
|
+
* Estimate reading level (WCAG 3.1.5, AAA) on scanned pages.
|
|
102
|
+
*
|
|
103
|
+
* Defaults to on when the run targets AAA — 3.1.5 is an AAA criterion — and
|
|
104
|
+
* off at AA unless opted in. Always a needs-review heuristic, never a
|
|
105
|
+
* violation: formulas approximate a grade, and the SC itself allows
|
|
106
|
+
* supplemental content and alternate versions no formula can see.
|
|
107
|
+
*/
|
|
108
|
+
readingLevel?: boolean;
|
|
109
|
+
/**
|
|
110
|
+
* The longest a single scan may hold a customer's test.
|
|
111
|
+
*
|
|
112
|
+
* Exists because it was missing and that turned out to matter. The SDK's first
|
|
113
|
+
* promise is that it never fails a build, and an unbounded axe run on a heavy
|
|
114
|
+
* page breaks it in the most confusing way available — the customer's test
|
|
115
|
+
* times out, blames itself, and nothing points at us.
|
|
116
|
+
*/
|
|
117
|
+
scanTimeoutMs?: number;
|
|
118
|
+
}
|
|
119
|
+
/** Options after defaulting, which is what the reporter actually holds. */
|
|
120
|
+
export interface ResolvedSetsquareOptions {
|
|
121
|
+
outputDir: string;
|
|
122
|
+
promo: boolean;
|
|
123
|
+
rules: RulePolicy;
|
|
124
|
+
autoScan: boolean;
|
|
125
|
+
settle: SettleConfig;
|
|
126
|
+
inference: InferenceConfig;
|
|
127
|
+
mask: MaskConfig;
|
|
128
|
+
format: 'text' | 'markdown' | 'json';
|
|
129
|
+
grid: 'matrix' | 'rows';
|
|
130
|
+
readingLevel: boolean;
|
|
131
|
+
scanTimeoutMs: number;
|
|
132
|
+
/** Off entirely. Set by `SETSQUARE_DISABLED`, and nothing else. */
|
|
133
|
+
disabled: boolean;
|
|
134
|
+
}
|
|
135
|
+
/**
|
|
136
|
+
* `.setsquare/` rather than something prettier: it sorts with the other tool
|
|
137
|
+
* directories, it is obviously ours, and `setsquare init` suggests exactly this line
|
|
138
|
+
* for the customer's `.gitignore`.
|
|
139
|
+
*/
|
|
140
|
+
export declare const DEFAULT_OUTPUT_DIR = ".setsquare";
|
|
141
|
+
/**
|
|
142
|
+
* Ten seconds, and the number is a compromise with a reason on each side.
|
|
143
|
+
*
|
|
144
|
+
* axe on a large real page legitimately takes seconds — a drag-and-drop builder
|
|
145
|
+
* with thousands of nodes is not being slow, it is being big — so a tight budget
|
|
146
|
+
* would throw away exactly the evidence hardest to get any other way. But a test
|
|
147
|
+
* that a customer wrote against a 30-second budget cannot afford to lend us most
|
|
148
|
+
* of it.
|
|
149
|
+
*
|
|
150
|
+
* Ten seconds fits every scan measured on the fixture site and on the reference
|
|
151
|
+
* implementation's ordinary pages, and cuts off the pathological case before it
|
|
152
|
+
* can take a test down with it.
|
|
153
|
+
*/
|
|
154
|
+
export declare const DEFAULT_SCAN_TIMEOUT_MS = 10000;
|
|
155
|
+
/**
|
|
156
|
+
* The kill switch, read from the environment rather than from config.
|
|
157
|
+
*
|
|
158
|
+
* A customer who suspects the SDK of breaking their suite needs to test that
|
|
159
|
+
* suspicion in one command, on a branch they have not touched, in CI they cannot
|
|
160
|
+
* edit. Making them change a config file first means the check is annoying enough
|
|
161
|
+
* to skip — and "is it you or is it me" is the question we most want them to be
|
|
162
|
+
* able to answer quickly, because the answer is sometimes yes.
|
|
163
|
+
*
|
|
164
|
+
* It is also how we get a baseline for our own measurements without asking anyone
|
|
165
|
+
* to revert anything.
|
|
166
|
+
*/
|
|
167
|
+
export declare function isDisabled(env?: NodeJS.ProcessEnv): boolean;
|
|
168
|
+
/**
|
|
169
|
+
* Per-invocation auto-scan override, from the environment.
|
|
170
|
+
*
|
|
171
|
+
* Exists for multi-invocation suites: axe is the bulk of the SDK's per-test
|
|
172
|
+
* cost, and a functional lane whose surfaces the a11y lane scans anyway is
|
|
173
|
+
* paying that cost twice for evidence the merge would deduplicate. The config
|
|
174
|
+
* file cannot carry this — it is the same file for every lane — so the lane
|
|
175
|
+
* that should not scan says so: `SETSQUARE_AUTOSCAN=0`.
|
|
176
|
+
*
|
|
177
|
+
* Deliberately narrower than the kill switch. `SETSQUARE_DISABLED` removes the SDK
|
|
178
|
+
* from the run entirely; this keeps observations, test outcomes and the run
|
|
179
|
+
* artifact — the lane still contributes to the merged run's e2e visibility and
|
|
180
|
+
* to the visited-but-never-scanned union — and skips only the scanning.
|
|
181
|
+
* Explicit `setsquare.scan()` calls still run: the customer asked for those by name.
|
|
182
|
+
*
|
|
183
|
+
* Returns undefined when unset, so config and defaults keep deciding.
|
|
184
|
+
*/
|
|
185
|
+
export declare function autoScanOverride(env?: NodeJS.ProcessEnv): boolean | undefined;
|
|
186
|
+
/**
|
|
187
|
+
* Per-invocation output directory, from the environment.
|
|
188
|
+
*
|
|
189
|
+
* Exists for `setsquare verify`, and the reason is a hazard rather than a
|
|
190
|
+
* convenience. Verify re-runs one surface to see whether a rule still fires — which
|
|
191
|
+
* means invoking the customer's own Playwright, which means the SDK writes a run.
|
|
192
|
+
* Writing it into `.setsquare/runs/` would make the re-scan **become the latest
|
|
193
|
+
* run**: `audit`, `report`, `findings` and `sarif` all read that, and `pruneRuns`
|
|
194
|
+
* would delete the real run it replaced. A command that silently overwrites the
|
|
195
|
+
* artefact every other command reads is worse than no command, so verify redirects
|
|
196
|
+
* the output instead.
|
|
197
|
+
*
|
|
198
|
+
* An env rather than a config option, for the same reason `SETSQUARE_RUN_ID` and
|
|
199
|
+
* `SETSQUARE_AUTOSCAN` are: it changes per invocation while the config file does
|
|
200
|
+
* not, and Playwright constructs reporters from JSON-safe config entries.
|
|
201
|
+
*
|
|
202
|
+
* Useful beyond verify — a CI lane that wants its evidence somewhere specific can
|
|
203
|
+
* set it — which is why it is a general option and not a `SETSQUARE_VERIFY=1` flag.
|
|
204
|
+
*
|
|
205
|
+
* Returns undefined when unset, so config and defaults keep deciding.
|
|
206
|
+
*/
|
|
207
|
+
export declare function outputDirOverride(env?: NodeJS.ProcessEnv): string | undefined;
|
|
208
|
+
/**
|
|
209
|
+
* Where to write the run summary as markdown.
|
|
210
|
+
*
|
|
211
|
+
* `SETSQUARE_SUMMARY_MD=<path>` makes the reporter write the summary it just
|
|
212
|
+
* printed, rendered through `renderMarkdown`, to that path as well. Nothing else
|
|
213
|
+
* changes: the terminal still gets whatever `format` asks for, and the file is a
|
|
214
|
+
* second rendering of the SAME input rather than a second summary.
|
|
215
|
+
*
|
|
216
|
+
* It exists for CI job summaries — GitHub's `$GITHUB_STEP_SUMMARY`, GitLab's
|
|
217
|
+
* report pages — and it is deliberately a path rather than a `github: true` flag,
|
|
218
|
+
* because the SDK has no business knowing which CI it is running under. The
|
|
219
|
+
* official Action points this at a file it owns and appends that file itself, so
|
|
220
|
+
* append-versus-replace stays the caller's decision.
|
|
221
|
+
*
|
|
222
|
+
* An env rather than a config option for the same reason as `SETSQUARE_OUTPUT_DIR`:
|
|
223
|
+
* it changes per invocation while the config file does not.
|
|
224
|
+
*
|
|
225
|
+
* The alternative was a CLI command that renders markdown from `run.json` — but
|
|
226
|
+
* `@setsquare/review-sdk` depends on `@setsquare/review-cli`, so the CLI cannot read the
|
|
227
|
+
* SDK's renderer, and rewriting it there is exactly the second renderer that
|
|
228
|
+
* `report.ts` forbids. One renderer, a second destination.
|
|
229
|
+
*/
|
|
230
|
+
export declare function summaryMarkdownPath(env?: NodeJS.ProcessEnv): string | undefined;
|
|
231
|
+
/**
|
|
232
|
+
* Changed-only mode: scan just the surfaces a change can reach.
|
|
233
|
+
*
|
|
234
|
+
* `SETSQUARE_CHANGED_ONLY=<path>` points at the file `setsquare changed` writes.
|
|
235
|
+
* The SDK does no route reasoning of its own — it compares patterns it already
|
|
236
|
+
* computes against a list, which is why this is a few lines rather than an adapter.
|
|
237
|
+
* The route knowledge lives in the CLI, where the adapters are, and
|
|
238
|
+
* `sdk/src/style.ts` records the standing decision that CLI code must not enter a
|
|
239
|
+
* test process's import graph.
|
|
240
|
+
*
|
|
241
|
+
* Two shapes in that file mean different things and must not be conflated:
|
|
242
|
+
* `routes: []` is "nothing changed that touches a route", and `routes: null` is
|
|
243
|
+
* "we could not work it out". Only the first licenses skipping anything; `null`
|
|
244
|
+
* means scan everything, because a set that might be missing surfaces is worse
|
|
245
|
+
* than no set at all.
|
|
246
|
+
*/
|
|
247
|
+
export declare function changedOnlyRoutes(env?: NodeJS.ProcessEnv, read?: (path: string) => string): Set<string> | undefined;
|
|
248
|
+
export declare function resolveOptions(options?: SetsquareOptions): ResolvedSetsquareOptions;
|
|
249
|
+
//# sourceMappingURL=options.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.d.ts","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"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"}
|
package/dist/options.js
ADDED
|
@@ -0,0 +1,185 @@
|
|
|
1
|
+
import { readFileSync } from 'node:fs';
|
|
2
|
+
import { DEFAULT_RULE_POLICY } from './rules.js';
|
|
3
|
+
import { DEFAULT_SETTLE } from './settle.js';
|
|
4
|
+
/**
|
|
5
|
+
* `.setsquare/` rather than something prettier: it sorts with the other tool
|
|
6
|
+
* directories, it is obviously ours, and `setsquare init` suggests exactly this line
|
|
7
|
+
* for the customer's `.gitignore`.
|
|
8
|
+
*/
|
|
9
|
+
export const DEFAULT_OUTPUT_DIR = '.setsquare';
|
|
10
|
+
/**
|
|
11
|
+
* Ten seconds, and the number is a compromise with a reason on each side.
|
|
12
|
+
*
|
|
13
|
+
* axe on a large real page legitimately takes seconds — a drag-and-drop builder
|
|
14
|
+
* with thousands of nodes is not being slow, it is being big — so a tight budget
|
|
15
|
+
* would throw away exactly the evidence hardest to get any other way. But a test
|
|
16
|
+
* that a customer wrote against a 30-second budget cannot afford to lend us most
|
|
17
|
+
* of it.
|
|
18
|
+
*
|
|
19
|
+
* Ten seconds fits every scan measured on the fixture site and on the reference
|
|
20
|
+
* implementation's ordinary pages, and cuts off the pathological case before it
|
|
21
|
+
* can take a test down with it.
|
|
22
|
+
*/
|
|
23
|
+
export const DEFAULT_SCAN_TIMEOUT_MS = 10_000;
|
|
24
|
+
/**
|
|
25
|
+
* The kill switch, read from the environment rather than from config.
|
|
26
|
+
*
|
|
27
|
+
* A customer who suspects the SDK of breaking their suite needs to test that
|
|
28
|
+
* suspicion in one command, on a branch they have not touched, in CI they cannot
|
|
29
|
+
* edit. Making them change a config file first means the check is annoying enough
|
|
30
|
+
* to skip — and "is it you or is it me" is the question we most want them to be
|
|
31
|
+
* able to answer quickly, because the answer is sometimes yes.
|
|
32
|
+
*
|
|
33
|
+
* It is also how we get a baseline for our own measurements without asking anyone
|
|
34
|
+
* to revert anything.
|
|
35
|
+
*/
|
|
36
|
+
export function isDisabled(env = process.env) {
|
|
37
|
+
const value = env['SETSQUARE_DISABLED'];
|
|
38
|
+
return value !== undefined && value !== '' && value !== '0' && value !== 'false';
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Per-invocation auto-scan override, from the environment.
|
|
42
|
+
*
|
|
43
|
+
* Exists for multi-invocation suites: axe is the bulk of the SDK's per-test
|
|
44
|
+
* cost, and a functional lane whose surfaces the a11y lane scans anyway is
|
|
45
|
+
* paying that cost twice for evidence the merge would deduplicate. The config
|
|
46
|
+
* file cannot carry this — it is the same file for every lane — so the lane
|
|
47
|
+
* that should not scan says so: `SETSQUARE_AUTOSCAN=0`.
|
|
48
|
+
*
|
|
49
|
+
* Deliberately narrower than the kill switch. `SETSQUARE_DISABLED` removes the SDK
|
|
50
|
+
* from the run entirely; this keeps observations, test outcomes and the run
|
|
51
|
+
* artifact — the lane still contributes to the merged run's e2e visibility and
|
|
52
|
+
* to the visited-but-never-scanned union — and skips only the scanning.
|
|
53
|
+
* Explicit `setsquare.scan()` calls still run: the customer asked for those by name.
|
|
54
|
+
*
|
|
55
|
+
* Returns undefined when unset, so config and defaults keep deciding.
|
|
56
|
+
*/
|
|
57
|
+
export function autoScanOverride(env = process.env) {
|
|
58
|
+
const value = env['SETSQUARE_AUTOSCAN'];
|
|
59
|
+
if (value === undefined || value === '')
|
|
60
|
+
return undefined;
|
|
61
|
+
return value !== '0' && value !== 'false';
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Per-invocation output directory, from the environment.
|
|
65
|
+
*
|
|
66
|
+
* Exists for `setsquare verify`, and the reason is a hazard rather than a
|
|
67
|
+
* convenience. Verify re-runs one surface to see whether a rule still fires — which
|
|
68
|
+
* means invoking the customer's own Playwright, which means the SDK writes a run.
|
|
69
|
+
* Writing it into `.setsquare/runs/` would make the re-scan **become the latest
|
|
70
|
+
* run**: `audit`, `report`, `findings` and `sarif` all read that, and `pruneRuns`
|
|
71
|
+
* would delete the real run it replaced. A command that silently overwrites the
|
|
72
|
+
* artefact every other command reads is worse than no command, so verify redirects
|
|
73
|
+
* the output instead.
|
|
74
|
+
*
|
|
75
|
+
* An env rather than a config option, for the same reason `SETSQUARE_RUN_ID` and
|
|
76
|
+
* `SETSQUARE_AUTOSCAN` are: it changes per invocation while the config file does
|
|
77
|
+
* not, and Playwright constructs reporters from JSON-safe config entries.
|
|
78
|
+
*
|
|
79
|
+
* Useful beyond verify — a CI lane that wants its evidence somewhere specific can
|
|
80
|
+
* set it — which is why it is a general option and not a `SETSQUARE_VERIFY=1` flag.
|
|
81
|
+
*
|
|
82
|
+
* Returns undefined when unset, so config and defaults keep deciding.
|
|
83
|
+
*/
|
|
84
|
+
export function outputDirOverride(env = process.env) {
|
|
85
|
+
const value = env['SETSQUARE_OUTPUT_DIR'];
|
|
86
|
+
if (value === undefined || value.trim() === '')
|
|
87
|
+
return undefined;
|
|
88
|
+
return value.trim();
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Where to write the run summary as markdown.
|
|
92
|
+
*
|
|
93
|
+
* `SETSQUARE_SUMMARY_MD=<path>` makes the reporter write the summary it just
|
|
94
|
+
* printed, rendered through `renderMarkdown`, to that path as well. Nothing else
|
|
95
|
+
* changes: the terminal still gets whatever `format` asks for, and the file is a
|
|
96
|
+
* second rendering of the SAME input rather than a second summary.
|
|
97
|
+
*
|
|
98
|
+
* It exists for CI job summaries — GitHub's `$GITHUB_STEP_SUMMARY`, GitLab's
|
|
99
|
+
* report pages — and it is deliberately a path rather than a `github: true` flag,
|
|
100
|
+
* because the SDK has no business knowing which CI it is running under. The
|
|
101
|
+
* official Action points this at a file it owns and appends that file itself, so
|
|
102
|
+
* append-versus-replace stays the caller's decision.
|
|
103
|
+
*
|
|
104
|
+
* An env rather than a config option for the same reason as `SETSQUARE_OUTPUT_DIR`:
|
|
105
|
+
* it changes per invocation while the config file does not.
|
|
106
|
+
*
|
|
107
|
+
* The alternative was a CLI command that renders markdown from `run.json` — but
|
|
108
|
+
* `@setsquare/review-sdk` depends on `@setsquare/review-cli`, so the CLI cannot read the
|
|
109
|
+
* SDK's renderer, and rewriting it there is exactly the second renderer that
|
|
110
|
+
* `report.ts` forbids. One renderer, a second destination.
|
|
111
|
+
*/
|
|
112
|
+
export function summaryMarkdownPath(env = process.env) {
|
|
113
|
+
const value = env['SETSQUARE_SUMMARY_MD'];
|
|
114
|
+
if (value === undefined || value.trim() === '')
|
|
115
|
+
return undefined;
|
|
116
|
+
return value.trim();
|
|
117
|
+
}
|
|
118
|
+
/**
|
|
119
|
+
* Changed-only mode: scan just the surfaces a change can reach.
|
|
120
|
+
*
|
|
121
|
+
* `SETSQUARE_CHANGED_ONLY=<path>` points at the file `setsquare changed` writes.
|
|
122
|
+
* The SDK does no route reasoning of its own — it compares patterns it already
|
|
123
|
+
* computes against a list, which is why this is a few lines rather than an adapter.
|
|
124
|
+
* The route knowledge lives in the CLI, where the adapters are, and
|
|
125
|
+
* `sdk/src/style.ts` records the standing decision that CLI code must not enter a
|
|
126
|
+
* test process's import graph.
|
|
127
|
+
*
|
|
128
|
+
* Two shapes in that file mean different things and must not be conflated:
|
|
129
|
+
* `routes: []` is "nothing changed that touches a route", and `routes: null` is
|
|
130
|
+
* "we could not work it out". Only the first licenses skipping anything; `null`
|
|
131
|
+
* means scan everything, because a set that might be missing surfaces is worse
|
|
132
|
+
* than no set at all.
|
|
133
|
+
*/
|
|
134
|
+
export function changedOnlyRoutes(env = process.env, read = (path) => readFileSync(path, 'utf8')) {
|
|
135
|
+
const path = env['SETSQUARE_CHANGED_ONLY'];
|
|
136
|
+
if (path === undefined || path.trim() === '')
|
|
137
|
+
return undefined;
|
|
138
|
+
try {
|
|
139
|
+
const parsed = JSON.parse(read(path.trim()));
|
|
140
|
+
// `null`, a missing key, or anything that is not an array: not a licence to skip.
|
|
141
|
+
if (!Array.isArray(parsed.routes))
|
|
142
|
+
return undefined;
|
|
143
|
+
return new Set(parsed.routes.filter((route) => typeof route === 'string'));
|
|
144
|
+
}
|
|
145
|
+
catch {
|
|
146
|
+
// Unreadable or malformed. Scanning everything is the safe failure.
|
|
147
|
+
return undefined;
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
export function resolveOptions(options = {}) {
|
|
151
|
+
return {
|
|
152
|
+
scanTimeoutMs: options.scanTimeoutMs ?? DEFAULT_SCAN_TIMEOUT_MS,
|
|
153
|
+
disabled: isDisabled(),
|
|
154
|
+
// The env wins over the config: it is the per-invocation statement, and the
|
|
155
|
+
// config file is the same file for every lane.
|
|
156
|
+
outputDir: outputDirOverride() ?? options.outputDir ?? DEFAULT_OUTPUT_DIR,
|
|
157
|
+
promo: options.promo ?? true,
|
|
158
|
+
rules: {
|
|
159
|
+
target: options.wcag ?? DEFAULT_RULE_POLICY.target,
|
|
160
|
+
bestPractice: options.bestPractice ?? DEFAULT_RULE_POLICY.bestPractice,
|
|
161
|
+
},
|
|
162
|
+
// Env outranks config here, because the config is shared across lanes and
|
|
163
|
+
// the whole point of the override is to differ per lane.
|
|
164
|
+
autoScan: autoScanOverride() ?? options.autoScan ?? true,
|
|
165
|
+
format: options.format ?? 'text',
|
|
166
|
+
grid: options.grid ?? 'matrix',
|
|
167
|
+
readingLevel: options.readingLevel ?? (options.wcag ?? DEFAULT_RULE_POLICY.target) === 'AAA',
|
|
168
|
+
settle: {
|
|
169
|
+
quietMs: options.quietMs ?? DEFAULT_SETTLE.quietMs,
|
|
170
|
+
settleTimeoutMs: options.settleTimeoutMs ?? DEFAULT_SETTLE.settleTimeoutMs,
|
|
171
|
+
},
|
|
172
|
+
mask: {
|
|
173
|
+
...(options.mask ? { mask: options.mask } : {}),
|
|
174
|
+
...(options.maskDefaults !== undefined ? { maskDefaults: options.maskDefaults } : {}),
|
|
175
|
+
},
|
|
176
|
+
inference: {
|
|
177
|
+
...(options.surfaces ? { surfaces: options.surfaces } : {}),
|
|
178
|
+
...(options.personas ? { personas: options.personas } : {}),
|
|
179
|
+
...(options.themes ? { themes: options.themes } : {}),
|
|
180
|
+
...(options.persona ? { persona: options.persona } : {}),
|
|
181
|
+
...(options.theme ? { theme: options.theme } : {}),
|
|
182
|
+
},
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
//# sourceMappingURL=options.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"options.js","sourceRoot":"","sources":["../src/options.ts"],"names":[],"mappings":"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"}
|
package/dist/output.d.ts
ADDED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import type { RunEnvelope, RunMeta } from './contract.js';
|
|
2
|
+
/**
|
|
3
|
+
* Write the run to disk: the envelope, and its sidecar.
|
|
4
|
+
*
|
|
5
|
+
* Two files, and the split is the whole design. `run.json` is the ingest request
|
|
6
|
+
* body byte-for-byte — nothing added, nothing removed — so the SDK's own test
|
|
7
|
+
* suite can validate it against the generated JSON Schema and the claim "the
|
|
8
|
+
* same artifact the platform would have received" is checkable. Every local fact
|
|
9
|
+
* that would otherwise have to be smuggled into the wire shape goes in
|
|
10
|
+
* `meta.json` instead.
|
|
11
|
+
*
|
|
12
|
+
* This is also why there is no `x-setsquare-local` extension field. The envelope is
|
|
13
|
+
* `.strict()`, and that strictness is exactly the mechanism that stopped `runId`
|
|
14
|
+
* creeping back after P1-17.7 removed it. Putting a licensed hole in it to carry
|
|
15
|
+
* a file path would trade a real guarantee for a small convenience.
|
|
16
|
+
*/
|
|
17
|
+
export interface WriteRunResult {
|
|
18
|
+
runDir: string;
|
|
19
|
+
envelopePath: string;
|
|
20
|
+
metaPath: string;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Sortable, collision-resistant, and readable at a glance in a directory listing.
|
|
24
|
+
*
|
|
25
|
+
* Derived from `generatedAt` rather than a fresh clock so the directory name and
|
|
26
|
+
* the envelope's own timestamp can never disagree. Colons are stripped because
|
|
27
|
+
* they are illegal in filenames on Windows, and a customer on Windows finding
|
|
28
|
+
* that we cannot write our own output would be an unforced error.
|
|
29
|
+
*
|
|
30
|
+
* The engine used to be part of this name and deliberately is not any more. A
|
|
31
|
+
* single Playwright run can span three engines — the compatibility matrix
|
|
32
|
+
* requires it — so a directory named after one of them would be wrong for every
|
|
33
|
+
* mixed run, and quietly right-looking. The engine belongs to each test result,
|
|
34
|
+
* which is the only place it is ever singular.
|
|
35
|
+
*/
|
|
36
|
+
export declare function runDirName(generatedAt: string): string;
|
|
37
|
+
/**
|
|
38
|
+
* Write a file so no reader can ever observe it half-written.
|
|
39
|
+
*
|
|
40
|
+
* A plain `writeFile` is atomic against other writers of *different* files, but
|
|
41
|
+
* not against a reader that lists the directory the instant the file appears —
|
|
42
|
+
* which is exactly what a concurrent invocation's merge does. Content goes to a
|
|
43
|
+
* uniquely-named sibling first, then renames into place; rename is atomic on
|
|
44
|
+
* every filesystem we run on, so a reader sees the old bytes or the new bytes
|
|
45
|
+
* and never a prefix.
|
|
46
|
+
*
|
|
47
|
+
* The rename is retried because Windows refuses to replace a file another
|
|
48
|
+
* process holds open without FILE_SHARE_DELETE — antivirus scanners and search
|
|
49
|
+
* indexers do this routinely, briefly. A short backoff outlasts almost all of
|
|
50
|
+
* them; persistent failure propagates, because falling back to a plain
|
|
51
|
+
* overwrite would reintroduce the torn read this function exists to prevent.
|
|
52
|
+
*/
|
|
53
|
+
export declare function writeFileAtomic(path: string, content: string): Promise<void>;
|
|
54
|
+
export declare function writeRun(outputDir: string, baseDir: string, envelope: RunEnvelope, meta: Omit<RunMeta, 'envelopePath' | 'outputDir'>): Promise<WriteRunResult>;
|
|
55
|
+
/**
|
|
56
|
+
* The write itself, with the destination chosen by the caller.
|
|
57
|
+
*
|
|
58
|
+
* Split from `writeRun` because a grouped run's directory is keyed by the
|
|
59
|
+
* orchestrator's id rather than by this invocation's clock — but what goes IN
|
|
60
|
+
* the directory, and how it gets there, must not differ between the two paths.
|
|
61
|
+
*
|
|
62
|
+
* `run.json` lands before `meta.json`, deliberately: the sidecar describes the
|
|
63
|
+
* envelope (down to a content hash, when grouped), so a reader must never find
|
|
64
|
+
* a sidecar whose envelope does not exist yet.
|
|
65
|
+
*/
|
|
66
|
+
export declare function writeRunInto(runDir: string, outputRoot: string, envelope: RunEnvelope, meta: Omit<RunMeta, 'envelopePath' | 'outputDir'>): Promise<WriteRunResult>;
|
|
67
|
+
/** A run-group directory, keyed by the orchestrator's id rather than a clock. */
|
|
68
|
+
export declare const GROUP_DIR_PATTERN: RegExp;
|
|
69
|
+
export interface PruneOptions {
|
|
70
|
+
/** A timestamp-named run dir to keep; timestamp dirs sorting before it go. */
|
|
71
|
+
currentName?: string;
|
|
72
|
+
/** A group dir name to keep unconditionally — the run being written now. */
|
|
73
|
+
currentGroupName?: string;
|
|
74
|
+
}
|
|
75
|
+
export declare function pruneRuns(runsRoot: string, options: PruneOptions): Promise<void>;
|
|
76
|
+
/**
|
|
77
|
+
* The HTML report, written beside `run.json` in the same run directory.
|
|
78
|
+
*
|
|
79
|
+
* Separate from `writeRun` rather than folded into it, because the two must be
|
|
80
|
+
* allowed to fail independently: a template bug must cost the customer the
|
|
81
|
+
* report and nothing else — never the envelope, and never the terminal
|
|
82
|
+
* summary. The reporter wraps this call in its own try.
|
|
83
|
+
*/
|
|
84
|
+
export declare function writeHtmlReport(runDir: string, html: string): Promise<string>;
|
|
85
|
+
/**
|
|
86
|
+
* The visual contact sheet, written beside `report.html` in the same run
|
|
87
|
+
* directory.
|
|
88
|
+
*
|
|
89
|
+
* Its own file and its own failure domain, for the same reason the HTML report
|
|
90
|
+
* has one: a template bug in the sheet must cost the customer the sheet and
|
|
91
|
+
* nothing else — not the envelope, not the accessibility report, not the
|
|
92
|
+
* terminal summary. The reporter wraps this call in its own try.
|
|
93
|
+
*
|
|
94
|
+
* The name is stable and boring on purpose. It is a path people put in a
|
|
95
|
+
* `.gitignore`, a CI artifact glob and a bookmark, and renaming it later would
|
|
96
|
+
* break all three.
|
|
97
|
+
*/
|
|
98
|
+
export declare function writeScreensReport(runDir: string, html: string): Promise<string>;
|
|
99
|
+
/**
|
|
100
|
+
* The summary as markdown, at a path the caller named.
|
|
101
|
+
*
|
|
102
|
+
* Directed by `SETSQUARE_SUMMARY_MD` and written nowhere by default, because this
|
|
103
|
+
* is not one of the run's artefacts — it is a second rendering of the terminal
|
|
104
|
+
* summary for a CI job-summary panel, and a file that appears in every
|
|
105
|
+
* `.setsquare/runs/` directory whether anyone asked for it or not would be one
|
|
106
|
+
* more thing to explain and one more thing to gitignore.
|
|
107
|
+
*
|
|
108
|
+
* `resolve` against the base directory rather than trusting the string, and its own
|
|
109
|
+
* failure domain like every other optional artefact here: a summary that could not
|
|
110
|
+
* be written must cost the summary and nothing else.
|
|
111
|
+
*/
|
|
112
|
+
export declare function writeSummaryMarkdown(baseDir: string, path: string, markdown: string): Promise<string>;
|
|
113
|
+
//# sourceMappingURL=output.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"output.d.ts","sourceRoot":"","sources":["../src/output.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,MAAM,eAAe,CAAC;AAE1D;;;;;;;;;;;;;;GAcG;AAEH,MAAM,WAAW,cAAc;IAC7B,MAAM,EAAE,MAAM,CAAC;IACf,YAAY,EAAE,MAAM,CAAC;IACrB,QAAQ,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,UAAU,CAAC,WAAW,EAAE,MAAM,GAAG,MAAM,CAEtD;AAED;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAiBlF;AAED,wBAAsB,QAAQ,CAC5B,SAAS,EAAE,MAAM,EACjB,OAAO,EAAE,MAAM,EACf,QAAQ,EAAE,WAAW,EACrB,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,WAAW,CAAC,GAChD,OAAO,CAAC,cAAc,CAAC,CAazB;AAED;;;;;;;;;;GAUG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,MAAM,EACd,UAAU,EAAE,MAAM,EAClB,QAAQ,EAAE,WAAW,EACrB,IAAI,EAAE,IAAI,CAAC,OAAO,EAAE,cAAc,GAAG,WAAW,CAAC,GAChD,OAAO,CAAC,cAAc,CAAC,CAezB;AAkBD,iFAAiF;AACjF,eAAO,MAAM,iBAAiB,QAA4C,CAAC;AAa3E,MAAM,WAAW,YAAY;IAC3B,8EAA8E;IAC9E,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,4EAA4E;IAC5E,gBAAgB,CAAC,EAAE,MAAM,CAAC;CAC3B;AAED,wBAAsB,SAAS,CAAC,QAAQ,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC,CAuCtF;AA8BD;;;;;;;GAOG;AACH,wBAAsB,eAAe,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAOnF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,kBAAkB,CAAC,MAAM,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAItF;AAED;;;;;;;;;;;;GAYG;AACH,wBAAsB,oBAAoB,CACxC,OAAO,EAAE,MAAM,EACf,IAAI,EAAE,MAAM,EACZ,QAAQ,EAAE,MAAM,GACf,OAAO,CAAC,MAAM,CAAC,CAKjB"}
|