@polishd/next 0.2.2-dev.4 → 0.2.3-dev.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/AGENTS.md +1 -1
- package/CHANGELOG.md +102 -12
- package/README.md +29 -0
- package/bin/doctor.mjs +8 -1
- package/dist/client/init.d.ts.map +1 -1
- package/dist/client/init.js +39 -8
- package/dist/client/init.js.map +1 -1
- package/dist/client/script-provenance.d.ts +21 -0
- package/dist/client/script-provenance.d.ts.map +1 -0
- package/dist/client/script-provenance.js +127 -0
- package/dist/client/script-provenance.js.map +1 -0
- package/dist/config.d.ts +10 -0
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +1 -0
- package/dist/config.js.map +1 -1
- package/dist/dashboard/design.d.ts +3 -1
- package/dist/dashboard/design.d.ts.map +1 -1
- package/dist/dashboard/design.js +3 -2
- package/dist/dashboard/design.js.map +1 -1
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +23 -18
- package/dist/dashboard/index.js.map +1 -1
- package/dist/dashboard/snapshot-actions.d.ts +16 -0
- package/dist/dashboard/snapshot-actions.d.ts.map +1 -0
- package/dist/dashboard/snapshot-actions.js +79 -0
- package/dist/dashboard/snapshot-actions.js.map +1 -0
- package/dist/dashboard/snapshots.d.ts +6 -0
- package/dist/dashboard/snapshots.d.ts.map +1 -0
- package/dist/dashboard/snapshots.js +86 -0
- package/dist/dashboard/snapshots.js.map +1 -0
- package/dist/dashboard/telemetry.d.ts.map +1 -1
- package/dist/dashboard/telemetry.js +20 -3
- package/dist/dashboard/telemetry.js.map +1 -1
- package/dist/dashboard.css +77 -0
- package/dist/server/ingest.d.ts +2 -5
- package/dist/server/ingest.d.ts.map +1 -1
- package/dist/server/ingest.js +40 -10
- package/dist/server/ingest.js.map +1 -1
- package/dist/server/queries.d.ts +18 -11
- package/dist/server/queries.d.ts.map +1 -1
- package/dist/server/queries.js +64 -24
- package/dist/server/queries.js.map +1 -1
- package/dist/server/snapshots.d.ts +65 -0
- package/dist/server/snapshots.d.ts.map +1 -0
- package/dist/server/snapshots.js +194 -0
- package/dist/server/snapshots.js.map +1 -0
- package/dist/shared/capture-status.d.ts +99 -0
- package/dist/shared/capture-status.d.ts.map +1 -0
- package/dist/shared/capture-status.js +133 -0
- package/dist/shared/capture-status.js.map +1 -0
- package/dist/shared/error-noise.d.ts +39 -0
- package/dist/shared/error-noise.d.ts.map +1 -0
- package/dist/shared/error-noise.js +101 -0
- package/dist/shared/error-noise.js.map +1 -0
- package/docs/SETUP.md +25 -0
- package/package.json +6 -1
package/AGENTS.md
CHANGED
|
@@ -348,7 +348,7 @@ Run `npx @polishd/next doctor` first — it names most of these directly.
|
|
|
348
348
|
| Every `/api/*` route 404s | Proxy matcher matches `/api` | Restore the `api` exclusion in the matcher |
|
|
349
349
|
| Dashboard renders unstyled | `@polishd/next/dashboard.css` not imported in the page | Phase 4 |
|
|
350
350
|
| Dashboard is empty, warning about the store | No writable backend | Set `POLISHD_DATABASE_URL`, or check Node ≥ 22.5 in dev |
|
|
351
|
-
| Dashboard shows *"no session cookie — your proxy isn't running"* | Proxy missing, misnamed for the Next major, matcher not covering the path, or a botched merge | Phase 3c and `doctor --url` |
|
|
351
|
+
| Dashboard shows *"no session cookie — your proxy isn't running"* | Proxy missing, misnamed for the Next major, matcher not covering the path, or a botched merge. Red means *nothing is being stored* — with events landing you get a neutral note instead | Phase 3c and `doctor --url <origin>`; plain `doctor` only reads the source tree, so it can pass while a deployed build still mints no cookie |
|
|
352
352
|
| Beacons return 200 but nothing is stored | Same as above — ingest answers `{ok:true,stored:0,reason:"no_session"}` so the client cannot see a failure | `doctor --url http://localhost:3000` |
|
|
353
353
|
| Proxy and ingest disagree on the cookie name | `sessionCookie` threaded into one layer but not another | Set `POLISHD_SESSION_COOKIE`; both read it |
|
|
354
354
|
| `ERR_UNKNOWN_BUILTIN_MODULE: node:sqlite` | Node < 22.5 | Upgrade Node, or configure Postgres |
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,108 @@
|
|
|
2
2
|
|
|
3
3
|
## Unreleased
|
|
4
4
|
|
|
5
|
+
### The "your proxy isn't running" banner stops crying wolf
|
|
6
|
+
|
|
7
|
+
A correctly installed, verifiably healthy site could show the red banner
|
|
8
|
+
indefinitely. The 0.2.2 rule compared an *all-time* drop total against an
|
|
9
|
+
all-time event total behind a one-hour recency gate, so the two halves covered
|
|
10
|
+
different time ranges: one fresh cookie-less batch — a crawler POSTing at the
|
|
11
|
+
public endpoint — re-armed every drop the install had ever recorded, including
|
|
12
|
+
the ones from before the proxy was first deployed. At the 1-in-400 ratio, 7
|
|
13
|
+
drops only needed fewer than 2,800 lifetime events to trip, which is most
|
|
14
|
+
personal sites for months.
|
|
15
|
+
|
|
16
|
+
- Drops are now bucketed by the hour, so the alert can compare drops and
|
|
17
|
+
stored events over **the same 24-hour window**. Records written before this
|
|
18
|
+
release carry no buckets, which means their history counts toward no window
|
|
19
|
+
and cannot re-arm anything.
|
|
20
|
+
- The strongest signal is now the cheapest one: an event stored *after* the
|
|
21
|
+
most recent drop proves the proxy is minting cookies right now, because
|
|
22
|
+
every event is attributed to that cookie and a broken proxy drops every
|
|
23
|
+
batch. No threshold to tune.
|
|
24
|
+
- Severity is split. Red — "your proxy isn't running" — is reserved for
|
|
25
|
+
nothing stored at all, or nothing stored in the window while drops keep
|
|
26
|
+
arriving. Otherwise the dashboard shows a neutral note: *N batches arrived
|
|
27
|
+
without a session cookie (bots, or visitors with cookies blocked) — X% of
|
|
28
|
+
traffic*, which is useful and true.
|
|
29
|
+
- "so nothing is being stored" only renders when nothing has been stored. It
|
|
30
|
+
used to sit directly above stat tiles counting stored sessions and events.
|
|
31
|
+
- The banner now points at `doctor --url <origin>` and says why: plain
|
|
32
|
+
`doctor` reads the source tree, so it can pass every check while a deployed
|
|
33
|
+
build still doesn't mint a cookie. Sending someone to a command that
|
|
34
|
+
answers "12 checks passed" was most of what made this alert expensive.
|
|
35
|
+
- The 60-second write collapse in `recordNoSession()` survives cold starts.
|
|
36
|
+
Its counters were module-level, so serverless reset them on every
|
|
37
|
+
invocation and the sparse traffic the throttle exists to absorb persisted
|
|
38
|
+
roughly 1:1; the durable `lastAt` now gates the write too.
|
|
39
|
+
- The rule lives in `src/shared/capture-status.ts` — pure, no database, no
|
|
40
|
+
React — with tests (`npm test`).
|
|
41
|
+
|
|
42
|
+
### Site snapshots on the Design tab
|
|
43
|
+
|
|
44
|
+
The Design tab grows a **Site snapshots** card: one click screenshots every
|
|
45
|
+
scanned route of the site — phone and desktop, light and dark — and renders
|
|
46
|
+
the shots as a filterable gallery with a full-page lightbox. Capture runs
|
|
47
|
+
through the new `allpages` dependency (Playwright underneath), launching the
|
|
48
|
+
developer's own Chrome/Edge before falling back to Playwright's Chromium, and
|
|
49
|
+
never auto-downloads a browser. The origin is learned from the request that
|
|
50
|
+
rendered the dashboard (`POLISHD_SITE_ORIGIN` overrides); shots land under
|
|
51
|
+
`.polishd/snapshots/` (`POLISHD_SNAPSHOT_DIR` overrides, last 6 runs kept)
|
|
52
|
+
with only an index in the store, and every image travels to the browser
|
|
53
|
+
through an auth-guarded server action rather than a new public route. Each
|
|
54
|
+
snapshot is stamped with the design-metrics fingerprint at capture time — the
|
|
55
|
+
hook for before/after visual diffing as design suggestions get applied. This
|
|
56
|
+
is the package's first runtime dependency beyond the optional `pg`.
|
|
57
|
+
|
|
58
|
+
### Errors are attributed to the code that threw them
|
|
59
|
+
|
|
60
|
+
`window` hears every throw in the tab, so an extension's failures — "Failed to
|
|
61
|
+
connect to MetaMask" being the canonical one — arrived as `js_error` events
|
|
62
|
+
indistinguishable from real bugs, often as the loudest error on the dashboard.
|
|
63
|
+
|
|
64
|
+
Rather than match error text, the client now works out *whose script threw*.
|
|
65
|
+
Resource Timing records every script the document actually fetched; extension
|
|
66
|
+
code is absent from it, because the browser injects content scripts and the
|
|
67
|
+
page never requested them. Comparing an error's stack against that live set
|
|
68
|
+
identifies injected code without knowing what it's called, so a new extension
|
|
69
|
+
needs no new pattern. Four verdicts come out: `site` (every frame is code you
|
|
70
|
+
shipped), `extension` (a frame names an extension URL scheme, including blobs
|
|
71
|
+
an extension minted at runtime), `foreign` (a frame names a script this
|
|
72
|
+
document never loaded), and `unknown` (nothing attributable — an opaque
|
|
73
|
+
cross-origin `Script error.`, an empty stack).
|
|
74
|
+
|
|
75
|
+
Only `extension` is dropped. `foreign` and `unknown` are kept, tagged with
|
|
76
|
+
`meta.origin`, and shown dimmed in Recent errors as "not your code" /
|
|
77
|
+
"unattributable" — a filter that silently eats what it can't identify is how a
|
|
78
|
+
real bug goes missing. A short list of message patterns remains as a last
|
|
79
|
+
resort for extension plumbing that throws with no attributable frame at all.
|
|
80
|
+
|
|
81
|
+
The drop also runs at ingest (a cached bundle can predate the filter, and the
|
|
82
|
+
endpoint is a public POST) and on the way out of `getRecentErrors`, so rows
|
|
83
|
+
written before this stop showing up too. New `ignoreErrors` config option —
|
|
84
|
+
strings matched case-insensitively, or regexes — drops anything else you've
|
|
85
|
+
decided not to chase.
|
|
86
|
+
|
|
87
|
+
### Telemetry answers the product questions clicks can't
|
|
88
|
+
|
|
89
|
+
The dashboard telemetry emitter now sends one `install_state` event per
|
|
90
|
+
session — whether a model is connected and which provider/model, resolved
|
|
91
|
+
server-side, never the key — and the consent prompt discloses it. On the
|
|
92
|
+
collecting side, the Installs tab grew a "With a model" stat and a per-domain
|
|
93
|
+
Model column built from each install's latest report, so connecting,
|
|
94
|
+
switching, or disconnecting a model reads correctly.
|
|
95
|
+
|
|
96
|
+
The dashboard's own controls also carry `data-component` names now
|
|
97
|
+
(`ai-summary-refresh`, `ai-summary-generate`, `ai-connect-model`,
|
|
98
|
+
`journey-open`, `loss-file-bug`, `loss-ignore`, `design-review-refresh`,
|
|
99
|
+
`settings-scan-codebase`, `show-more`, coarse `settings`/`ai-summary`
|
|
100
|
+
containers, …), so with `POLISHD_ANALYTICS_SOURCE=telemetry` the collector's
|
|
101
|
+
Most-used-features table groups dashboard clicks by feature instead of raw
|
|
102
|
+
selectors — the same component-level story polishd tells its hosts, told
|
|
103
|
+
about itself. The attributes are inert for host apps.
|
|
104
|
+
|
|
105
|
+
## 0.2.2
|
|
106
|
+
|
|
5
107
|
### Cross-install telemetry ingest
|
|
6
108
|
|
|
7
109
|
A new `@polishd/next/telemetry` entry point exports a CORS-enabled ingest
|
|
@@ -54,18 +156,6 @@ summary, all through the same single source function the separation uses.
|
|
|
54
156
|
First-party events keep being captured and stored, just not shown, so the
|
|
55
157
|
switch is losslessly reversible.
|
|
56
158
|
|
|
57
|
-
Telemetry also answers the product questions clicks can't: the emitter sends
|
|
58
|
-
one `install_state` event per session — whether a model is connected and
|
|
59
|
-
which provider/model, resolved server-side, never the key — and the Installs
|
|
60
|
-
tab grew a "With a model" stat and a per-domain Model column from the latest
|
|
61
|
-
report. And the dashboard's own controls now carry `data-component` names
|
|
62
|
-
(`ai-summary-refresh`, `ai-summary-generate`, `ai-connect-model`,
|
|
63
|
-
`journey-open`, `loss-file-bug`, `loss-ignore`, `design-review-refresh`,
|
|
64
|
-
`settings-scan-codebase`, `show-more`, coarse `settings`/`ai-summary`
|
|
65
|
-
containers, …), so on the collecting side the Most-used-features table groups
|
|
66
|
-
dashboard clicks by feature instead of raw selectors — the same
|
|
67
|
-
component-level story polishd tells its hosts, told about itself.
|
|
68
|
-
|
|
69
159
|
To make that experience complete, the telemetry emitter now also captures
|
|
70
160
|
scroll depth (of the dashboard's own scroll container — the document never
|
|
71
161
|
scrolls under the shell), JS errors raised while the dashboard is up, and one
|
package/README.md
CHANGED
|
@@ -424,6 +424,23 @@ Nothing extra to install or wire: the scan ships with the existing client,
|
|
|
424
424
|
flows through the existing ingest route, and the dashboard itself is never
|
|
425
425
|
scanned.
|
|
426
426
|
|
|
427
|
+
### Site snapshots
|
|
428
|
+
|
|
429
|
+
The Design tab can also **screenshot the site itself** — every scanned route,
|
|
430
|
+
phone and desktop, light and dark — and render the shots as a gallery, so the
|
|
431
|
+
measured tokens sit next to what the pages actually look like. Capture uses
|
|
432
|
+
[allpages](https://www.npmjs.com/package/allpages) (Playwright underneath): it
|
|
433
|
+
launches your installed Chrome or Edge, falling back to Playwright's Chromium
|
|
434
|
+
(`npx playwright install chromium` once, if you have neither). The origin to
|
|
435
|
+
shoot is taken from the request that rendered the dashboard, or set
|
|
436
|
+
`POLISHD_SITE_ORIGIN` to override it. Images live on disk under
|
|
437
|
+
`.polishd/snapshots/` (override with `POLISHD_SNAPSHOT_DIR`; the last 6
|
|
438
|
+
snapshots are kept), and each snapshot is stamped with the design-metrics
|
|
439
|
+
fingerprint at capture time — so a snapshot taken before a round of design
|
|
440
|
+
fixes can be held against one taken after. Capture is a dev-machine feature:
|
|
441
|
+
serverless filesystems are read-only, and the button will say so rather than
|
|
442
|
+
fail silently.
|
|
443
|
+
|
|
427
444
|
## Component-level tracking
|
|
428
445
|
|
|
429
446
|
Wrap any element to track it explicitly. Interactive controls get hover + click
|
|
@@ -491,9 +508,21 @@ import { definePolishdConfig } from "@polishd/next";
|
|
|
491
508
|
export default definePolishdConfig({
|
|
492
509
|
sampleRate: 1,
|
|
493
510
|
rageClick: { count: 3, windowMs: 500 },
|
|
511
|
+
ignoreErrors: [],
|
|
494
512
|
});
|
|
495
513
|
```
|
|
496
514
|
|
|
515
|
+
Browser-extension errors are never recorded. `window` hears every throw in the
|
|
516
|
+
tab, so an extension's failures — "Failed to connect to MetaMask" and its kin —
|
|
517
|
+
would otherwise show up as your site's noisiest bugs. Rather than match error
|
|
518
|
+
text, polishd asks whose script threw: the browser records every script your
|
|
519
|
+
document actually fetched, extension code is never among them, so an error
|
|
520
|
+
whose stack points outside that set is identifiable as injected without knowing
|
|
521
|
+
what it's called. Confident extension errors are dropped at capture and again
|
|
522
|
+
at ingest; errors that merely *can't* be attributed to your code are kept and
|
|
523
|
+
labelled, not hidden. `ignoreErrors` (strings, matched case-insensitively, or
|
|
524
|
+
regexes) drops anything else you'd rather not see.
|
|
525
|
+
|
|
497
526
|
The dashboard never measures itself: nothing on `/polishd` (or below it) is
|
|
498
527
|
captured, so reading your analytics can't show up as your site's most-used
|
|
499
528
|
feature. **Moved the dashboard elsewhere?** Set `dashboardRoute` in your
|
package/bin/doctor.mjs
CHANGED
|
@@ -349,8 +349,15 @@ function report(results, origin) {
|
|
|
349
349
|
c.dim(`, ${results.filter((r) => r.status === PASS).length} checks passed`),
|
|
350
350
|
);
|
|
351
351
|
if (!origin) {
|
|
352
|
+
// "no problems" means the source tree is right, which is not the same as
|
|
353
|
+
// the deployed site minting cookies — a build that ships without the proxy
|
|
354
|
+
// passes every check here. Say so, so a green run isn't read as proof.
|
|
352
355
|
console.log(
|
|
353
|
-
c.dim(
|
|
356
|
+
c.dim(
|
|
357
|
+
"\nThese are static checks on your source tree. Run with" +
|
|
358
|
+
" --url http://localhost:3000 (or your deployed origin) to verify the" +
|
|
359
|
+
" cookie and ingest on the running site.",
|
|
360
|
+
),
|
|
354
361
|
);
|
|
355
362
|
}
|
|
356
363
|
return fails > 0 ? 1 : 0;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/client/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAyC,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;
|
|
1
|
+
{"version":3,"file":"init.d.ts","sourceRoot":"","sources":["../../src/client/init.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,EAAyC,KAAK,aAAa,EAAE,MAAM,WAAW,CAAC;AActF,KAAK,WAAW,GAAG,OAAO,CAAC,aAAa,CAAC,CAAC;AAS1C,wBAAgB,WAAW,CAAC,OAAO,GAAE,WAAgB,GAAG,IAAI,CAiT3D"}
|
package/dist/client/init.js
CHANGED
|
@@ -8,7 +8,9 @@
|
|
|
8
8
|
* events, and flushes on an interval, on soft navigation, and on pagehide.
|
|
9
9
|
*/
|
|
10
10
|
import { defaultPolishdConfig, isDashboardPath } from "../config";
|
|
11
|
+
import { isIgnorableError } from "../shared/error-noise";
|
|
11
12
|
import { scheduleDesignScan } from "./design-scan";
|
|
13
|
+
import { errorOrigin, startScriptProvenance } from "./script-provenance";
|
|
12
14
|
import { componentOf, deviceCategory, hasTextSelection, isInteractive, labelOf, selectorOf, } from "./dom";
|
|
13
15
|
let started = false;
|
|
14
16
|
// Next inlines this at build time. Guarded for any bundler that doesn't define
|
|
@@ -27,6 +29,9 @@ export function initPolishd(options = {}) {
|
|
|
27
29
|
if (cfg.sampleRate < 1 && Math.random() > cfg.sampleRate)
|
|
28
30
|
return;
|
|
29
31
|
started = true;
|
|
32
|
+
// Start before anything else can throw: this is what lets an error name the
|
|
33
|
+
// script it came from, and it has to be listening first.
|
|
34
|
+
startScriptProvenance();
|
|
30
35
|
const queue = [];
|
|
31
36
|
let currentPath = location.pathname;
|
|
32
37
|
let maxScrollPct = 0;
|
|
@@ -197,22 +202,48 @@ export function initPolishd(options = {}) {
|
|
|
197
202
|
maxScrollPct = Math.min(100, pct);
|
|
198
203
|
};
|
|
199
204
|
// ---- errors --------------------------------------------------------------
|
|
200
|
-
|
|
205
|
+
// `window` hears every throw in the tab, including the ones from extensions
|
|
206
|
+
// injected into the page. Those are not the site's bugs and nothing here can
|
|
207
|
+
// fix them, so they never become events.
|
|
208
|
+
//
|
|
209
|
+
// Provenance decides first and decides most: the scripts this document
|
|
210
|
+
// fetched are known (see `script-provenance.ts`), so code from anywhere else
|
|
211
|
+
// is identifiable without knowing what it's called. The message rules in
|
|
212
|
+
// `shared/error-noise.ts` only mop up what has no attributable frame at all —
|
|
213
|
+
// extension plumbing that throws with the page as its only stack entry.
|
|
214
|
+
//
|
|
215
|
+
// Errors that aren't the site's but aren't confidently an extension's are
|
|
216
|
+
// kept and labeled with `meta.origin`, never silently dropped.
|
|
217
|
+
const captureError = (message, origin, extra) => {
|
|
218
|
+
if (origin === "extension")
|
|
219
|
+
return;
|
|
220
|
+
if (isIgnorableError({ message, source: String(extra.meta.source ?? ""), ignore: cfg.ignoreErrors })) {
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
201
223
|
push({
|
|
202
224
|
type: "js_error",
|
|
203
|
-
|
|
225
|
+
...extra,
|
|
204
226
|
meta: {
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
227
|
+
...extra.meta,
|
|
228
|
+
message: message.slice(0, 300),
|
|
229
|
+
// Absent means "site" — the common case shouldn't pay for the label.
|
|
230
|
+
...(origin === "site" ? {} : { origin }),
|
|
208
231
|
},
|
|
209
232
|
});
|
|
210
233
|
};
|
|
234
|
+
const onError = (ev) => {
|
|
235
|
+
const source = ev.filename || "";
|
|
236
|
+
captureError(String(ev.message), errorOrigin(source, ev.error?.stack), {
|
|
237
|
+
component: componentOf(ev.target),
|
|
238
|
+
meta: { source, line: ev.lineno || 0 },
|
|
239
|
+
});
|
|
240
|
+
};
|
|
211
241
|
const onRejection = (ev) => {
|
|
212
242
|
const reason = ev.reason;
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
243
|
+
// A rejection carries no filename, so the stack is the only thing that can
|
|
244
|
+
// place the code that threw it.
|
|
245
|
+
captureError(String(reason?.message ?? reason), errorOrigin(undefined, reason?.stack), {
|
|
246
|
+
meta: { kind: "unhandledrejection" },
|
|
216
247
|
});
|
|
217
248
|
};
|
|
218
249
|
// ---- web vitals (LCP, CLS) ----------------------------------------------
|
package/dist/client/init.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/client/init.ts"],"names":[],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"init.js","sourceRoot":"","sources":["../../src/client/init.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type ErrorOrigin = "site" | "extension" | "foreign" | "unknown";
|
|
2
|
+
/**
|
|
3
|
+
* Begin recording which scripts this document loads.
|
|
4
|
+
*
|
|
5
|
+
* Called at init, which on Next runs before hydration — but `buffered: true`
|
|
6
|
+
* means even the entries from before this point are replayed, so a script that
|
|
7
|
+
* loaded during parse is still counted.
|
|
8
|
+
*/
|
|
9
|
+
export declare function startScriptProvenance(): void;
|
|
10
|
+
/**
|
|
11
|
+
* Decide who owns an error, from the script URLs it can be attributed to.
|
|
12
|
+
*
|
|
13
|
+
* `source` is the browser's own blame (`ErrorEvent.filename`); `stack` is
|
|
14
|
+
* searched too because injected code frequently presents with the page as its
|
|
15
|
+
* top frame and the extension only further down — which is exactly how a
|
|
16
|
+
* wallet's "failed to connect" surfaces.
|
|
17
|
+
*/
|
|
18
|
+
export declare function errorOrigin(source: string | undefined, stack: string | undefined): ErrorOrigin;
|
|
19
|
+
/** Test seam: forget everything recorded so far. */
|
|
20
|
+
export declare function resetScriptProvenance(): void;
|
|
21
|
+
//# sourceMappingURL=script-provenance.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script-provenance.d.ts","sourceRoot":"","sources":["../../src/client/script-provenance.ts"],"names":[],"mappings":"AA4BA,MAAM,MAAM,WAAW,GAAG,MAAM,GAAG,WAAW,GAAG,SAAS,GAAG,SAAS,CAAC;AAoBvE;;;;;;GAMG;AACH,wBAAgB,qBAAqB,IAAI,IAAI,CAe5C;AA2BD;;;;;;;GAOG;AACH,wBAAgB,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,EAAE,KAAK,EAAE,MAAM,GAAG,SAAS,GAAG,WAAW,CAY9F;AAED,oDAAoD;AACpD,wBAAgB,qBAAqB,IAAI,IAAI,CAG5C"}
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Polishd — script provenance: whose code actually threw.
|
|
3
|
+
*
|
|
4
|
+
* Pattern-matching error messages is guesswork that ages badly: every new
|
|
5
|
+
* extension brings a new string, and the list only ever grows. There is a
|
|
6
|
+
* better question the browser can answer directly — *did this document ever
|
|
7
|
+
* fetch that script?*
|
|
8
|
+
*
|
|
9
|
+
* Resource Timing records every resource the page loaded, including the
|
|
10
|
+
* lazily-imported chunks and CDN scripts added long after parse. Extension
|
|
11
|
+
* code is not in it: the browser injects content scripts, the document never
|
|
12
|
+
* requested them. So a stack frame pointing at a URL absent from that set is
|
|
13
|
+
* code the site did not ship — whatever it happens to be called this month.
|
|
14
|
+
*
|
|
15
|
+
* That gives four verdicts instead of a yes/no, which matters because the
|
|
16
|
+
* honest answer is sometimes "can't tell":
|
|
17
|
+
*
|
|
18
|
+
* site every frame is code this document loaded — a real bug
|
|
19
|
+
* extension a frame names an extension URL scheme — never the site's
|
|
20
|
+
* foreign a frame names a script the document never fetched — injected
|
|
21
|
+
* unknown nothing attributable (opaque cross-origin, empty stack)
|
|
22
|
+
*
|
|
23
|
+
* Only `extension` is confident enough to drop. `foreign` and `unknown` are
|
|
24
|
+
* kept and labeled, because a filter that silently eats what it can't identify
|
|
25
|
+
* is how a real bug goes missing.
|
|
26
|
+
*/
|
|
27
|
+
import { isExtensionUrl } from "../shared/error-noise";
|
|
28
|
+
/** Every script URL this document is known to have fetched itself. */
|
|
29
|
+
const loadedScripts = new Set();
|
|
30
|
+
let observing = false;
|
|
31
|
+
/** Drop the `:line:col` suffix and any trailing bracket a stack frame carries. */
|
|
32
|
+
function bareUrl(raw) {
|
|
33
|
+
return raw.replace(/[)\]]+$/, "").replace(/:\d+(?::\d+)?$/, "");
|
|
34
|
+
}
|
|
35
|
+
function record(entry) {
|
|
36
|
+
const e = entry;
|
|
37
|
+
// `script` covers <script src> and dynamic import(); `link` covers modulepreload.
|
|
38
|
+
// Anything else on the page can't be the thing that threw.
|
|
39
|
+
if (e.initiatorType !== "script" && e.initiatorType !== "link")
|
|
40
|
+
return;
|
|
41
|
+
loadedScripts.add(bareUrl(e.name));
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Begin recording which scripts this document loads.
|
|
45
|
+
*
|
|
46
|
+
* Called at init, which on Next runs before hydration — but `buffered: true`
|
|
47
|
+
* means even the entries from before this point are replayed, so a script that
|
|
48
|
+
* loaded during parse is still counted.
|
|
49
|
+
*/
|
|
50
|
+
export function startScriptProvenance() {
|
|
51
|
+
if (observing || typeof PerformanceObserver === "undefined")
|
|
52
|
+
return;
|
|
53
|
+
observing = true;
|
|
54
|
+
try {
|
|
55
|
+
for (const entry of performance.getEntriesByType("resource"))
|
|
56
|
+
record(entry);
|
|
57
|
+
// The resource buffer is finite (250 entries by default) and a busy page
|
|
58
|
+
// can overflow it, so we keep our own set rather than re-reading it later.
|
|
59
|
+
new PerformanceObserver((list) => {
|
|
60
|
+
for (const entry of list.getEntries())
|
|
61
|
+
record(entry);
|
|
62
|
+
}).observe({ type: "resource", buffered: true });
|
|
63
|
+
}
|
|
64
|
+
catch {
|
|
65
|
+
// No Resource Timing: every verdict below degrades to same-origin checks,
|
|
66
|
+
// which still separates injected code from the site's own.
|
|
67
|
+
observing = false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* True when `url` is code this page is responsible for.
|
|
72
|
+
*
|
|
73
|
+
* Three ways to qualify, in descending confidence: the document fetched it,
|
|
74
|
+
* it shares the page's origin (covers inline scripts, which blame the document
|
|
75
|
+
* URL), or it's a blob the page itself minted — `blob:` inherits its creator's
|
|
76
|
+
* origin, so an extension's blob reads as `blob:chrome-extension://…` and
|
|
77
|
+
* correctly fails this test.
|
|
78
|
+
*/
|
|
79
|
+
function isOurScript(url) {
|
|
80
|
+
if (loadedScripts.has(url))
|
|
81
|
+
return true;
|
|
82
|
+
if (isExtensionUrl(url))
|
|
83
|
+
return false;
|
|
84
|
+
try {
|
|
85
|
+
const origin = location.origin;
|
|
86
|
+
if (url.startsWith(`blob:${origin}`))
|
|
87
|
+
return true;
|
|
88
|
+
return new URL(url, location.href).origin === origin;
|
|
89
|
+
}
|
|
90
|
+
catch {
|
|
91
|
+
return false;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// Stack formats differ per engine, so rather than parse frames, pull out
|
|
95
|
+
// anything shaped like an absolute URL and classify each one.
|
|
96
|
+
const URL_IN_STACK = /[a-zA-Z][a-zA-Z0-9+.-]*:\/\/[^\s)'"]+/g;
|
|
97
|
+
/**
|
|
98
|
+
* Decide who owns an error, from the script URLs it can be attributed to.
|
|
99
|
+
*
|
|
100
|
+
* `source` is the browser's own blame (`ErrorEvent.filename`); `stack` is
|
|
101
|
+
* searched too because injected code frequently presents with the page as its
|
|
102
|
+
* top frame and the extension only further down — which is exactly how a
|
|
103
|
+
* wallet's "failed to connect" surfaces.
|
|
104
|
+
*/
|
|
105
|
+
export function errorOrigin(source, stack) {
|
|
106
|
+
const urls = [];
|
|
107
|
+
if (source)
|
|
108
|
+
urls.push(bareUrl(source));
|
|
109
|
+
if (stack)
|
|
110
|
+
for (const match of stack.match(URL_IN_STACK) ?? [])
|
|
111
|
+
urls.push(bareUrl(match));
|
|
112
|
+
if (urls.length === 0)
|
|
113
|
+
return "unknown";
|
|
114
|
+
if (urls.some(isExtensionUrl))
|
|
115
|
+
return "extension";
|
|
116
|
+
// Every frame has to be ours for this to be the site's bug. One frame the
|
|
117
|
+
// document never loaded means something else is on the stack — a third-party
|
|
118
|
+
// script that qualifies (the page fetched it) still reads as "site", which is
|
|
119
|
+
// right: you shipped it.
|
|
120
|
+
return urls.every(isOurScript) ? "site" : "foreign";
|
|
121
|
+
}
|
|
122
|
+
/** Test seam: forget everything recorded so far. */
|
|
123
|
+
export function resetScriptProvenance() {
|
|
124
|
+
loadedScripts.clear();
|
|
125
|
+
observing = false;
|
|
126
|
+
}
|
|
127
|
+
//# sourceMappingURL=script-provenance.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"script-provenance.js","sourceRoot":"","sources":["../../src/client/script-provenance.ts"],"names":[],"mappings":"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"}
|
package/dist/config.d.ts
CHANGED
|
@@ -27,6 +27,16 @@ export interface PolishdConfig {
|
|
|
27
27
|
count: number;
|
|
28
28
|
windowMs: number;
|
|
29
29
|
};
|
|
30
|
+
/**
|
|
31
|
+
* Extra error messages to drop, on top of the built-in filtering.
|
|
32
|
+
*
|
|
33
|
+
* Errors thrown by browser extensions are always dropped — see
|
|
34
|
+
* `shared/error-noise.ts` for what that covers and why. This is the escape
|
|
35
|
+
* hatch for the rest: a noisy third-party embed, a known-benign warning, an
|
|
36
|
+
* error you've decided not to chase. Strings match case-insensitively
|
|
37
|
+
* anywhere in the message; regexes are tested against it as-is.
|
|
38
|
+
*/
|
|
39
|
+
ignoreErrors: (string | RegExp)[];
|
|
30
40
|
/** Local SQLite file used in dev. Ignored when POLISHD_DATABASE_URL is set. */
|
|
31
41
|
databasePath: string;
|
|
32
42
|
/** Name of the anonymous session cookie set by the middleware. */
|
package/dist/config.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,aAAa;IAC5B,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAC;IACjB,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,eAAe,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,YAAY,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,oBAAoB,EAAE,
|
|
1
|
+
{"version":3,"file":"config.d.ts","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,MAAM,WAAW,aAAa;IAC5B,2EAA2E;IAC3E,OAAO,EAAE,OAAO,CAAC;IACjB,6EAA6E;IAC7E,QAAQ,EAAE,MAAM,CAAC;IACjB,gEAAgE;IAChE,eAAe,EAAE,MAAM,CAAC;IACxB,6EAA6E;IAC7E,YAAY,EAAE,MAAM,CAAC;IACrB,0DAA0D;IAC1D,UAAU,EAAE,MAAM,CAAC;IACnB,uEAAuE;IACvE,SAAS,EAAE;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,QAAQ,EAAE,MAAM,CAAA;KAAE,CAAC;IAC/C;;;;;;;;OAQG;IACH,YAAY,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,CAAC;IAClC,+EAA+E;IAC/E,YAAY,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,aAAa,EAAE,MAAM,CAAC;IACtB;;;;;;OAMG;IACH,cAAc,EAAE,MAAM,CAAC;CACxB;AAED,eAAO,MAAM,oBAAoB,EAAE,aAWlC,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,wBAAgB,mBAAmB,CAAC,SAAS,EAAE,OAAO,CAAC,aAAa,CAAC,GAAG,aAAa,CAEpF;AAED;;;;;;;;;;;;;GAaG;AACH,wBAAgB,oBAAoB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAK9D;AAeD;;;;GAIG;AACH,wBAAgB,6BAA6B,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAEjE;AAED;;;;GAIG;AACH,wBAAgB,qBAAqB,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,MAAM,CAO/D;AAED;;;;;;GAMG;AACH,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAIpE"}
|
package/dist/config.js
CHANGED
package/dist/config.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;
|
|
1
|
+
{"version":3,"file":"config.js","sourceRoot":"","sources":["../src/config.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAuCH,MAAM,CAAC,MAAM,oBAAoB,GAAkB;IACjD,OAAO,EAAE,IAAI;IACb,QAAQ,EAAE,cAAc;IACxB,eAAe,EAAE,MAAM;IACvB,YAAY,EAAE,EAAE;IAChB,UAAU,EAAE,CAAC;IACb,SAAS,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,QAAQ,EAAE,GAAG,EAAE;IACtC,YAAY,EAAE,EAAE;IAChB,YAAY,EAAE,uBAAuB;IACrC,aAAa,EAAE,iBAAiB;IAChC,cAAc,EAAE,UAAU;CAC3B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,MAAM,UAAU,mBAAmB,CAAC,SAAiC;IACnE,OAAO,EAAE,GAAG,oBAAoB,EAAE,GAAG,SAAS,EAAE,CAAC;AACnD,CAAC;AAED;;;;;;;;;;;;;GAaG;AACH,MAAM,UAAU,oBAAoB,CAAC,QAAiB;IACpD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,MAAM,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,sBAAsB,CAAC;IACnD,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IAClD,OAAO,oBAAoB,CAAC,aAAa,CAAC;AAC5C,CAAC;AAED,+EAA+E;AAC/E,4EAA4E;AAC5E,6EAA6E;AAC7E,6EAA6E;AAC7E,0EAA0E;AAC1E,0EAA0E;AAC1E,0EAA0E;AAC1E,6EAA6E;AAC7E,8EAA8E;AAC9E,gEAAgE;AAEhE,IAAI,wBAAwB,GAAkB,IAAI,CAAC;AAEnD;;;;GAIG;AACH,MAAM,UAAU,6BAA6B,CAAC,KAAa;IACzD,wBAAwB,GAAG,KAAK,CAAC;AACnC,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,qBAAqB,CAAC,QAAiB;IACrD,IAAI,QAAQ;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,wBAAwB;QAAE,OAAO,wBAAwB,CAAC;IAC9D,MAAM,OAAO,GACX,OAAO,OAAO,KAAK,WAAW,CAAC,CAAC,CAAC,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC,CAAC,SAAS,CAAC;IACnF,IAAI,OAAO,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC;QAAE,OAAO,OAAO,CAAC;IAClD,OAAO,oBAAoB,CAAC,cAAc,CAAC;AAC7C,CAAC;AAED;;;;;;GAMG;AACH,MAAM,UAAU,eAAe,CAAC,IAAY,EAAE,KAAa;IACzD,MAAM,CAAC,GAAG,KAAK,CAAC,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;IACpC,IAAI,CAAC,CAAC;QAAE,OAAO,KAAK,CAAC;IACrB,OAAO,IAAI,KAAK,CAAC,IAAI,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;AAChD,CAAC"}
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
import type { PolishdDesignData } from "../server/design";
|
|
2
2
|
import type { PolishdAISettingsPublic, PolishdDesignReview } from "../ai/types";
|
|
3
|
+
import type { PolishdSnapshot } from "../server/snapshots";
|
|
3
4
|
export interface DesignPanelProps {
|
|
4
5
|
data: PolishdDesignData;
|
|
5
6
|
review: PolishdDesignReview | null;
|
|
6
7
|
reviewStale: boolean;
|
|
7
8
|
settings: PolishdAISettingsPublic;
|
|
9
|
+
snapshots: PolishdSnapshot[];
|
|
8
10
|
}
|
|
9
|
-
export declare function DesignPanel({ data, review, reviewStale, settings }: DesignPanelProps): import("react").JSX.Element;
|
|
11
|
+
export declare function DesignPanel({ data, review, reviewStale, settings, snapshots }: DesignPanelProps): import("react").JSX.Element;
|
|
10
12
|
//# sourceMappingURL=design.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"design.d.ts","sourceRoot":"","sources":["../../src/dashboard/design.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAGV,iBAAiB,EAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"design.d.ts","sourceRoot":"","sources":["../../src/dashboard/design.tsx"],"names":[],"mappings":"AAaA,OAAO,KAAK,EAGV,iBAAiB,EAClB,MAAM,kBAAkB,CAAC;AAC1B,OAAO,KAAK,EAAE,uBAAuB,EAAE,mBAAmB,EAAE,MAAM,aAAa,CAAC;AAChF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,qBAAqB,CAAC;AAsZ3D,MAAM,WAAW,gBAAgB;IAC/B,IAAI,EAAE,iBAAiB,CAAC;IACxB,MAAM,EAAE,mBAAmB,GAAG,IAAI,CAAC;IACnC,WAAW,EAAE,OAAO,CAAC;IACrB,QAAQ,EAAE,uBAAuB,CAAC;IAClC,SAAS,EAAE,eAAe,EAAE,CAAC;CAC9B;AAED,wBAAgB,WAAW,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,EAAE,gBAAgB,+BAuE/F"}
|
package/dist/dashboard/design.js
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
2
|
import DesignReviewCard, { RefreshMetricsButton } from "./design-review-card";
|
|
3
|
+
import SnapshotsCard from "./snapshots";
|
|
3
4
|
import { Annotated, ColorToken, ContrastMeter, contrastPercent } from "./design-tokens";
|
|
4
5
|
import OverflowRow from "./overflow-row";
|
|
5
6
|
import ShowMore from "./show-more";
|
|
@@ -106,10 +107,10 @@ function ScannedPages({ data }) {
|
|
|
106
107
|
const overflow = data.pages.slice(VISIBLE_ROWS);
|
|
107
108
|
return (_jsx(Section, { title: "Scanned pages", tip: "\u2014 latest design scan per route; the dashboard itself is never scanned.", children: _jsxs("div", { className: `${card} overflow-hidden`, children: [visible.map((p, i) => (_jsx(PageRow, { p: p, first: i === 0 }, p.path))), _jsx(ShowMore, { count: overflow.length, label: "pages", children: overflow.map((p) => (_jsx(PageRow, { p: p, first: false }, p.path))) })] }) }));
|
|
108
109
|
}
|
|
109
|
-
export function DesignPanel({ data, review, reviewStale, settings }) {
|
|
110
|
+
export function DesignPanel({ data, review, reviewStale, settings, snapshots }) {
|
|
110
111
|
const hasScans = data.pages.length > 0;
|
|
111
112
|
return (_jsxs("main", { className: "text-white", children: [_jsxs("div", { className: `mb-8 flex items-start justify-between gap-3 border-b ${border} pb-6`, children: [_jsxs("div", { children: [_jsx("h1", { className: "text-[22px] font-semibold tracking-tight text-white", children: "Design review" }), _jsx("p", { className: "mt-1 max-w-xl text-[13px] leading-relaxed text-[#666]", children: "Your site's brand guideline, reverse-engineered from the rendered pages \u2014 the typography, palette, radii and spacing it actually ships, with anything that breaks the system flagged." })] }), _jsxs("div", { className: "flex shrink-0 items-center gap-2", children: [_jsx(RefreshMetricsButton, {}), _jsx("div", { className: `whitespace-nowrap rounded-full px-3 py-1 text-[11px] font-medium ${hasScans ? "bg-emerald-950 text-emerald-400" : "bg-[#1a1a1a] text-[#666]"}`, children: hasScans
|
|
112
113
|
? `● ${data.pages.length} ${data.pages.length === 1 ? "page" : "pages"} scanned`
|
|
113
|
-
: "○ no scans yet" })] })] }), !data.ready && (_jsxs("div", { className: "mb-8 rounded-lg border border-amber-900/50 bg-amber-950/30 px-4 py-3 text-[13px] text-amber-400", children: ["The analytics store isn't writable in this environment. Run locally or configure a database \u2014 see the ", _jsx("span", { className: "font-mono text-amber-300", children: "@polishd/next" }), " ", "DATABASE.md guide."] })), data.ready && !hasScans && (_jsx("div", { className: `mb-8 ${card} px-5 py-8 text-center`, children: _jsx("p", { className: "text-[13px] text-[#888]", children: "No design scans captured yet. Each page measures its own rendered design (fonts, colors, radii, spacing) once per visitor session \u2014 browse a few pages of the site, then refresh the metrics." }) })), _jsx(DesignReviewCard, { initialReview: review, initialStale: reviewStale, hasApiKey: settings.hasApiKey, provider: settings.provider, model: settings.model, scannedPages: data.pages.length }), hasScans && (_jsxs(_Fragment, { children: [_jsx(TypographySection, { data: data }), _jsx(PaletteSection, { data: data }), _jsx(ContrastSection, { data: data }), _jsx(RadiusSection, { data: data }), _jsx(SpacingSection, { data: data }), _jsx(ScannedPages, { data: data })] }))] }));
|
|
114
|
+
: "○ no scans yet" })] })] }), !data.ready && (_jsxs("div", { className: "mb-8 rounded-lg border border-amber-900/50 bg-amber-950/30 px-4 py-3 text-[13px] text-amber-400", children: ["The analytics store isn't writable in this environment. Run locally or configure a database \u2014 see the ", _jsx("span", { className: "font-mono text-amber-300", children: "@polishd/next" }), " ", "DATABASE.md guide."] })), data.ready && !hasScans && (_jsx("div", { className: `mb-8 ${card} px-5 py-8 text-center`, children: _jsx("p", { className: "text-[13px] text-[#888]", children: "No design scans captured yet. Each page measures its own rendered design (fonts, colors, radii, spacing) once per visitor session \u2014 browse a few pages of the site, then refresh the metrics." }) })), _jsx(SnapshotsCard, { initial: snapshots }), _jsx(DesignReviewCard, { initialReview: review, initialStale: reviewStale, hasApiKey: settings.hasApiKey, provider: settings.provider, model: settings.model, scannedPages: data.pages.length }), hasScans && (_jsxs(_Fragment, { children: [_jsx(TypographySection, { data: data }), _jsx(PaletteSection, { data: data }), _jsx(ContrastSection, { data: data }), _jsx(RadiusSection, { data: data }), _jsx(SpacingSection, { data: data }), _jsx(ScannedPages, { data: data })] }))] }));
|
|
114
115
|
}
|
|
115
116
|
//# sourceMappingURL=design.js.map
|