@polishd/next 0.1.0 → 0.2.1-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 +161 -46
- package/CHANGELOG.md +163 -0
- package/README.md +275 -49
- package/bin/doctor.mjs +374 -0
- package/bin/init.mjs +215 -188
- package/bin/polishd.mjs +85 -0
- package/bin/shared.mjs +114 -0
- package/dist/ai/actions.d.ts +13 -2
- package/dist/ai/actions.d.ts.map +1 -1
- package/dist/ai/actions.js +19 -1
- package/dist/ai/actions.js.map +1 -1
- package/dist/ai/design.d.ts +28 -0
- package/dist/ai/design.d.ts.map +1 -0
- package/dist/ai/design.js +245 -0
- package/dist/ai/design.js.map +1 -0
- package/dist/ai/guard.d.ts +44 -3
- package/dist/ai/guard.d.ts.map +1 -1
- package/dist/ai/guard.js +13 -2
- package/dist/ai/guard.js.map +1 -1
- package/dist/ai/providers.d.ts +2 -0
- package/dist/ai/providers.d.ts.map +1 -1
- package/dist/ai/providers.js +70 -0
- package/dist/ai/providers.js.map +1 -1
- package/dist/ai/settings.d.ts +15 -1
- package/dist/ai/settings.d.ts.map +1 -1
- package/dist/ai/settings.js +38 -1
- package/dist/ai/settings.js.map +1 -1
- package/dist/ai/types.d.ts +57 -0
- package/dist/ai/types.d.ts.map +1 -1
- package/dist/client/design-scan.d.ts +37 -0
- package/dist/client/design-scan.d.ts.map +1 -0
- package/dist/client/design-scan.js +319 -0
- package/dist/client/design-scan.js.map +1 -0
- package/dist/client/init.d.ts.map +1 -1
- package/dist/client/init.js +67 -2
- package/dist/client/init.js.map +1 -1
- package/dist/config.d.ts +57 -3
- package/dist/config.d.ts.map +1 -1
- package/dist/config.js +62 -3
- package/dist/config.js.map +1 -1
- package/dist/dashboard/design-review-card.d.ts +15 -0
- package/dist/dashboard/design-review-card.d.ts.map +1 -0
- package/dist/dashboard/design-review-card.js +82 -0
- package/dist/dashboard/design-review-card.js.map +1 -0
- package/dist/dashboard/design.d.ts +10 -0
- package/dist/dashboard/design.d.ts.map +1 -0
- package/dist/dashboard/design.js +83 -0
- package/dist/dashboard/design.js.map +1 -0
- package/dist/dashboard/index.d.ts +35 -5
- package/dist/dashboard/index.d.ts.map +1 -1
- package/dist/dashboard/index.js +176 -18
- package/dist/dashboard/index.js.map +1 -1
- package/dist/dashboard/journeys.d.ts.map +1 -1
- package/dist/dashboard/journeys.js +1 -0
- package/dist/dashboard/journeys.js.map +1 -1
- package/dist/dashboard/summary.d.ts.map +1 -1
- package/dist/dashboard/summary.js +59 -5
- package/dist/dashboard/summary.js.map +1 -1
- package/dist/dashboard/token-auth.d.ts +56 -0
- package/dist/dashboard/token-auth.d.ts.map +1 -0
- package/dist/dashboard/token-auth.js +158 -0
- package/dist/dashboard/token-auth.js.map +1 -0
- package/dist/dashboard/unlock.d.ts +2 -0
- package/dist/dashboard/unlock.d.ts.map +1 -0
- package/dist/dashboard/unlock.js +54 -0
- package/dist/dashboard/unlock.js.map +1 -0
- package/dist/dashboard.css +2740 -0
- package/dist/proxy.d.ts +53 -5
- package/dist/proxy.d.ts.map +1 -1
- package/dist/proxy.js +73 -3
- package/dist/proxy.js.map +1 -1
- package/dist/route.d.ts.map +1 -1
- package/dist/route.js +11 -3
- package/dist/route.js.map +1 -1
- package/dist/server/design.d.ts +93 -0
- package/dist/server/design.d.ts.map +1 -0
- package/dist/server/design.js +430 -0
- package/dist/server/design.js.map +1 -0
- package/dist/server/ingest.d.ts +33 -2
- package/dist/server/ingest.d.ts.map +1 -1
- package/dist/server/ingest.js +70 -8
- package/dist/server/ingest.js.map +1 -1
- package/dist/server/queries.d.ts +16 -0
- package/dist/server/queries.d.ts.map +1 -1
- package/dist/server/queries.js +80 -16
- package/dist/server/queries.js.map +1 -1
- package/dist/session.d.ts.map +1 -1
- package/dist/session.js +4 -2
- package/dist/session.js.map +1 -1
- package/dist/shared/types.d.ts +31 -1
- package/dist/shared/types.d.ts.map +1 -1
- package/dist/shared/types.js +1 -0
- package/dist/shared/types.js.map +1 -1
- package/docs/SETUP.md +308 -51
- package/package.json +14 -7
package/dist/proxy.d.ts
CHANGED
|
@@ -9,7 +9,7 @@
|
|
|
9
9
|
* To compose with your own proxy logic, import `withPolishdSession` and
|
|
10
10
|
* `polishdMatcher` instead and thread the same NextResponse through.
|
|
11
11
|
*/
|
|
12
|
-
import type
|
|
12
|
+
import { NextResponse, type NextRequest } from "next/server";
|
|
13
13
|
import type { PolishdConfig } from "./config";
|
|
14
14
|
import { withPolishdSession } from "./session";
|
|
15
15
|
export { withPolishdSession };
|
|
@@ -21,7 +21,7 @@ export { withPolishdSession };
|
|
|
21
21
|
* routes don't need it. This is Next's officially recommended matcher shape.
|
|
22
22
|
*/
|
|
23
23
|
export declare const polishdMatcher: string[];
|
|
24
|
-
export declare function proxy(request: NextRequest):
|
|
24
|
+
export declare function proxy(request: NextRequest): NextResponse<unknown>;
|
|
25
25
|
export declare const config: {
|
|
26
26
|
matcher: string[];
|
|
27
27
|
};
|
|
@@ -29,12 +29,60 @@ export declare const config: {
|
|
|
29
29
|
* Build a configured proxy — use when you need a non-default cookie name (e.g.
|
|
30
30
|
* preserving a legacy `session` cookie across a migration):
|
|
31
31
|
*
|
|
32
|
-
* const { proxy
|
|
32
|
+
* const { proxy } = createPolishdProxy({ sessionCookie: "polish_session" });
|
|
33
33
|
* export { proxy };
|
|
34
|
-
* export const config = {
|
|
34
|
+
* export const config = {
|
|
35
|
+
* matcher: ["/((?!api|_next/static|_next/image|favicon|assets).*)"],
|
|
36
|
+
* };
|
|
35
37
|
*/
|
|
36
38
|
export declare function createPolishdProxy(config?: Partial<PolishdConfig>): {
|
|
37
|
-
proxy: (request: NextRequest) =>
|
|
39
|
+
proxy: (request: NextRequest) => NextResponse<unknown>;
|
|
38
40
|
matcher: string[];
|
|
39
41
|
};
|
|
42
|
+
/** A host's own proxy handler. May be sync or async, and may return nothing. */
|
|
43
|
+
export type PolishdComposableHandler = (request: NextRequest) => NextResponse | undefined | void | Promise<NextResponse | undefined | void>;
|
|
44
|
+
export interface ComposePolishdOptions {
|
|
45
|
+
/**
|
|
46
|
+
* The paths your own handler ran on *before* Polishd was added.
|
|
47
|
+
*
|
|
48
|
+
* This is the part of merging that goes wrong quietly. Next allows exactly
|
|
49
|
+
* one proxy module per app, so adding Polishd means widening
|
|
50
|
+
* `config.matcher` to the union of both — and Polishd's matcher is
|
|
51
|
+
* near-total. Your handler, which you deliberately scoped to two routes,
|
|
52
|
+
* silently starts running on every request in the app. Nothing errors; your
|
|
53
|
+
* redirects and rewrites just begin firing where they never did before.
|
|
54
|
+
*
|
|
55
|
+
* Declare the original scope here and it is re-applied as an internal guard,
|
|
56
|
+
* so the widened matcher feeds Polishd everything while your handler keeps
|
|
57
|
+
* seeing exactly what it saw before.
|
|
58
|
+
*
|
|
59
|
+
* Accepts Next's matcher strings (`"/admin/:path*"`, `"/((?!api).*)"`) or a
|
|
60
|
+
* `RegExp` when you want to be exact. Omit it only if your handler genuinely
|
|
61
|
+
* did run on everything.
|
|
62
|
+
*/
|
|
63
|
+
matcher?: string | RegExp | Array<string | RegExp>;
|
|
64
|
+
/** Non-default cookie name, matching your route and client config. */
|
|
65
|
+
config?: Partial<PolishdConfig>;
|
|
66
|
+
}
|
|
67
|
+
/**
|
|
68
|
+
* Wrap an existing proxy handler so Polishd's session cookie is minted
|
|
69
|
+
* alongside it:
|
|
70
|
+
*
|
|
71
|
+
* // proxy.ts (middleware.ts on Next 15)
|
|
72
|
+
* export const proxy = composePolishd(myProxy, { matcher: "/admin/:path*" });
|
|
73
|
+
* export const config = {
|
|
74
|
+
* // Still written by hand: Next statically parses this and it must be an
|
|
75
|
+
* // inline literal. The union of your paths and Polishd's.
|
|
76
|
+
* matcher: ["/((?!api|_next/static|_next/image|favicon|assets).*)"],
|
|
77
|
+
* };
|
|
78
|
+
*
|
|
79
|
+
* Your handler runs first and its response is threaded through, so a redirect
|
|
80
|
+
* or rewrite you return carries the analytics cookie rather than losing it.
|
|
81
|
+
* Returning nothing is fine — Polishd continues with a default response.
|
|
82
|
+
*
|
|
83
|
+
* Widening the matcher is safe from Polishd's side: `withPolishdSession`
|
|
84
|
+
* returns early once the cookie is present (see session.ts), so the extra
|
|
85
|
+
* paths cost a cookie lookup and nothing else.
|
|
86
|
+
*/
|
|
87
|
+
export declare function composePolishd(handler: PolishdComposableHandler, opts?: ComposePolishdOptions): (request: NextRequest) => Promise<NextResponse>;
|
|
40
88
|
//# sourceMappingURL=proxy.d.ts.map
|
package/dist/proxy.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,
|
|
1
|
+
{"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAE9B;;;;;;GAMG;AACH,eAAO,MAAM,cAAc,UAA2D,CAAC;AAEvF,wBAAgB,KAAK,CAAC,OAAO,EAAE,WAAW,yBAEzC;AAED,eAAO,MAAM,MAAM;;CAElB,CAAC;AAEF;;;;;;;;;GASG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM;qBAEjD,WAAW;;EAG/B;AAID,gFAAgF;AAChF,MAAM,MAAM,wBAAwB,GAAG,CACrC,OAAO,EAAE,WAAW,KACjB,YAAY,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAAC,YAAY,GAAG,SAAS,GAAG,IAAI,CAAC,CAAC;AAEhF,MAAM,WAAW,qBAAqB;IACpC;;;;;;;;;;;;;;;;;OAiBG;IACH,OAAO,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC,CAAC;IACnD,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;CACjC;AAyBD;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,cAAc,CAC5B,OAAO,EAAE,wBAAwB,EACjC,IAAI,GAAE,qBAA0B,IAKJ,SAAS,WAAW,KAAG,OAAO,CAAC,YAAY,CAAC,CAMzE"}
|
package/dist/proxy.js
CHANGED
|
@@ -1,3 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @polishd/next/proxy — anonymous session assignment.
|
|
3
|
+
*
|
|
4
|
+
* Consumers wire this up with a one-line re-export:
|
|
5
|
+
*
|
|
6
|
+
* // src/proxy.ts (Next 16; `middleware.ts` on Next 15)
|
|
7
|
+
* export { proxy, config } from "@polishd/next/proxy";
|
|
8
|
+
*
|
|
9
|
+
* To compose with your own proxy logic, import `withPolishdSession` and
|
|
10
|
+
* `polishdMatcher` instead and thread the same NextResponse through.
|
|
11
|
+
*/
|
|
12
|
+
import { NextResponse } from "next/server";
|
|
1
13
|
import { withPolishdSession } from "./session";
|
|
2
14
|
export { withPolishdSession };
|
|
3
15
|
/**
|
|
@@ -11,14 +23,18 @@ export const polishdMatcher = ["/((?!api|_next/static|_next/image|favicon|assets
|
|
|
11
23
|
export function proxy(request) {
|
|
12
24
|
return withPolishdSession(request);
|
|
13
25
|
}
|
|
14
|
-
export const config = {
|
|
26
|
+
export const config = {
|
|
27
|
+
matcher: ["/((?!api|_next/static|_next/image|favicon|assets).*)"],
|
|
28
|
+
};
|
|
15
29
|
/**
|
|
16
30
|
* Build a configured proxy — use when you need a non-default cookie name (e.g.
|
|
17
31
|
* preserving a legacy `session` cookie across a migration):
|
|
18
32
|
*
|
|
19
|
-
* const { proxy
|
|
33
|
+
* const { proxy } = createPolishdProxy({ sessionCookie: "polish_session" });
|
|
20
34
|
* export { proxy };
|
|
21
|
-
* export const config = {
|
|
35
|
+
* export const config = {
|
|
36
|
+
* matcher: ["/((?!api|_next/static|_next/image|favicon|assets).*)"],
|
|
37
|
+
* };
|
|
22
38
|
*/
|
|
23
39
|
export function createPolishdProxy(config = {}) {
|
|
24
40
|
return {
|
|
@@ -26,4 +42,58 @@ export function createPolishdProxy(config = {}) {
|
|
|
26
42
|
matcher: polishdMatcher,
|
|
27
43
|
};
|
|
28
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* Translate one Next matcher entry into a testable RegExp.
|
|
47
|
+
*
|
|
48
|
+
* Next's own matcher syntax is a subset of path-to-regexp: literal paths,
|
|
49
|
+
* `:param` and `:param*` segments, and raw regex bodies in parentheses. Those
|
|
50
|
+
* are handled here; anything more exotic can be passed as a `RegExp` directly.
|
|
51
|
+
*/
|
|
52
|
+
function toRegExp(pattern) {
|
|
53
|
+
if (pattern instanceof RegExp)
|
|
54
|
+
return pattern;
|
|
55
|
+
// Already regex-shaped, as in the near-total matcher Polishd itself uses.
|
|
56
|
+
if (pattern.includes("("))
|
|
57
|
+
return new RegExp(`^${pattern}$`);
|
|
58
|
+
let out = "";
|
|
59
|
+
for (const seg of pattern.split("/").slice(1)) {
|
|
60
|
+
if (seg.startsWith(":")) {
|
|
61
|
+
// `:path*` matches zero or more segments, so the slash goes with it.
|
|
62
|
+
out += seg.endsWith("*") ? "(?:/.*)?" : "/[^/]+";
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
out += `/${seg.replace(/[.*+?^${}()|[\]\\]/g, "\\$&")}`;
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
return new RegExp(`^${out || "/"}$`);
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* Wrap an existing proxy handler so Polishd's session cookie is minted
|
|
72
|
+
* alongside it:
|
|
73
|
+
*
|
|
74
|
+
* // proxy.ts (middleware.ts on Next 15)
|
|
75
|
+
* export const proxy = composePolishd(myProxy, { matcher: "/admin/:path*" });
|
|
76
|
+
* export const config = {
|
|
77
|
+
* // Still written by hand: Next statically parses this and it must be an
|
|
78
|
+
* // inline literal. The union of your paths and Polishd's.
|
|
79
|
+
* matcher: ["/((?!api|_next/static|_next/image|favicon|assets).*)"],
|
|
80
|
+
* };
|
|
81
|
+
*
|
|
82
|
+
* Your handler runs first and its response is threaded through, so a redirect
|
|
83
|
+
* or rewrite you return carries the analytics cookie rather than losing it.
|
|
84
|
+
* Returning nothing is fine — Polishd continues with a default response.
|
|
85
|
+
*
|
|
86
|
+
* Widening the matcher is safe from Polishd's side: `withPolishdSession`
|
|
87
|
+
* returns early once the cookie is present (see session.ts), so the extra
|
|
88
|
+
* paths cost a cookie lookup and nothing else.
|
|
89
|
+
*/
|
|
90
|
+
export function composePolishd(handler, opts = {}) {
|
|
91
|
+
const declared = opts.matcher === undefined ? [] : [opts.matcher].flat();
|
|
92
|
+
const guards = declared.map(toRegExp);
|
|
93
|
+
return async function proxy(request) {
|
|
94
|
+
const inScope = guards.length === 0 || guards.some((re) => re.test(request.nextUrl.pathname));
|
|
95
|
+
const response = inScope ? await handler(request) : undefined;
|
|
96
|
+
return withPolishdSession(request, response ?? NextResponse.next(), opts.config);
|
|
97
|
+
};
|
|
98
|
+
}
|
|
29
99
|
//# sourceMappingURL=proxy.js.map
|
package/dist/proxy.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"proxy.js","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,EAAE,YAAY,EAAoB,MAAM,aAAa,CAAC;AAG7D,OAAO,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAC;AAE/C,OAAO,EAAE,kBAAkB,EAAE,CAAC;AAE9B;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,cAAc,GAAG,CAAC,sDAAsD,CAAC,CAAC;AAEvF,MAAM,UAAU,KAAK,CAAC,OAAoB;IACxC,OAAO,kBAAkB,CAAC,OAAO,CAAC,CAAC;AACrC,CAAC;AAED,MAAM,CAAC,MAAM,MAAM,GAAG;IACpB,OAAO,EAAE,CAAC,sDAAsD,CAAC;CAClE,CAAC;AAEF;;;;;;;;;GASG;AACH,MAAM,UAAU,kBAAkB,CAAC,SAAiC,EAAE;IACpE,OAAO;QACL,KAAK,EAAE,CAAC,OAAoB,EAAE,EAAE,CAAC,kBAAkB,CAAC,OAAO,EAAE,SAAS,EAAE,MAAM,CAAC;QAC/E,OAAO,EAAE,cAAc;KACxB,CAAC;AACJ,CAAC;AAiCD;;;;;;GAMG;AACH,SAAS,QAAQ,CAAC,OAAwB;IACxC,IAAI,OAAO,YAAY,MAAM;QAAE,OAAO,OAAO,CAAC;IAC9C,0EAA0E;IAC1E,IAAI,OAAO,CAAC,QAAQ,CAAC,GAAG,CAAC;QAAE,OAAO,IAAI,MAAM,CAAC,IAAI,OAAO,GAAG,CAAC,CAAC;IAC7D,IAAI,GAAG,GAAG,EAAE,CAAC;IACb,KAAK,MAAM,GAAG,IAAI,OAAO,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,CAAC;QAC9C,IAAI,GAAG,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE,CAAC;YACxB,qEAAqE;YACrE,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,QAAQ,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,GAAG,IAAI,IAAI,GAAG,CAAC,OAAO,CAAC,qBAAqB,EAAE,MAAM,CAAC,EAAE,CAAC;QAC1D,CAAC;IACH,CAAC;IACD,OAAO,IAAI,MAAM,CAAC,IAAI,GAAG,IAAI,GAAG,GAAG,CAAC,CAAC;AACvC,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,cAAc,CAC5B,OAAiC,EACjC,OAA8B,EAAE;IAEhC,MAAM,QAAQ,GAAG,IAAI,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACzE,MAAM,MAAM,GAAG,QAAQ,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;IAEtC,OAAO,KAAK,UAAU,KAAK,CAAC,OAAoB;QAC9C,MAAM,OAAO,GACX,MAAM,CAAC,MAAM,KAAK,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,CAAC;QAChF,MAAM,QAAQ,GAAG,OAAO,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC;QAC9D,OAAO,kBAAkB,CAAC,OAAO,EAAE,QAAQ,IAAI,YAAY,CAAC,IAAI,EAAE,EAAE,IAAI,CAAC,MAAM,CAAC,CAAC;IACnF,CAAC,CAAC;AACJ,CAAC"}
|
package/dist/route.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../src/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,
|
|
1
|
+
{"version":3,"file":"route.d.ts","sourceRoot":"","sources":["../src/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,YAAY,EAAE,KAAK,WAAW,EAAE,MAAM,aAAa,CAAC;AAE7D,OAAO,EAA8C,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAI1F,eAAO,MAAM,OAAO,WAAW,CAAC;AAEhC,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAEvC,wBAAgB,kBAAkB,CAAC,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,IAWzC,KAAK,WAAW;;;oDAe5C;AAED,wDAAwD;AACxD,eAAO,MAAM,IAAI,QAlBiB,WAAW;;;mDAkBL,CAAC"}
|
package/dist/route.js
CHANGED
|
@@ -9,14 +9,22 @@
|
|
|
9
9
|
* Or build a configured handler with `createPolishdRoute({ sessionCookie })`.
|
|
10
10
|
*/
|
|
11
11
|
import { NextResponse } from "next/server";
|
|
12
|
-
import { defaultPolishdConfig } from "./config";
|
|
12
|
+
import { defaultPolishdConfig, resolveSessionCookie } from "./config";
|
|
13
13
|
import { ingest } from "./server/ingest";
|
|
14
14
|
// node:sqlite / pg need the Node runtime — never the Edge runtime.
|
|
15
15
|
export const runtime = "nodejs";
|
|
16
16
|
// This route mutates per-request; it must never be statically cached.
|
|
17
17
|
export const dynamic = "force-dynamic";
|
|
18
18
|
export function createPolishdRoute(config = {}) {
|
|
19
|
-
|
|
19
|
+
// The cookie name is resolved the way the proxy resolves it, so a
|
|
20
|
+
// `POLISHD_SESSION_COOKIE` set once reaches both sides rather than half of
|
|
21
|
+
// them — and it is folded into `cfg` so everything downstream, ingest
|
|
22
|
+
// included, sees the same name this handler reads.
|
|
23
|
+
const cfg = {
|
|
24
|
+
...defaultPolishdConfig,
|
|
25
|
+
...config,
|
|
26
|
+
sessionCookie: resolveSessionCookie(config.sessionCookie),
|
|
27
|
+
};
|
|
20
28
|
return async function POST(req) {
|
|
21
29
|
let body;
|
|
22
30
|
try {
|
|
@@ -26,7 +34,7 @@ export function createPolishdRoute(config = {}) {
|
|
|
26
34
|
return NextResponse.json({ ok: false, reason: "bad_json" }, { status: 400 });
|
|
27
35
|
}
|
|
28
36
|
const cookieValue = req.cookies.get(cfg.sessionCookie)?.value;
|
|
29
|
-
const result = await ingest(body, cookieValue);
|
|
37
|
+
const result = await ingest(body, cookieValue, cfg);
|
|
30
38
|
// Always succeed for valid requests so the beacon never retries on the
|
|
31
39
|
// client; real failures (bad payloads) return 4xx above.
|
|
32
40
|
return NextResponse.json(result, { status: result.ok ? 200 : 400 });
|
package/dist/route.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"route.js","sourceRoot":"","sources":["../src/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,YAAY,EAAoB,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAE,oBAAoB,EAAsB,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"route.js","sourceRoot":"","sources":["../src/route.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AACH,OAAO,EAAE,YAAY,EAAoB,MAAM,aAAa,CAAC;AAE7D,OAAO,EAAE,oBAAoB,EAAE,oBAAoB,EAAsB,MAAM,UAAU,CAAC;AAC1F,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAEzC,mEAAmE;AACnE,MAAM,CAAC,MAAM,OAAO,GAAG,QAAQ,CAAC;AAChC,sEAAsE;AACtE,MAAM,CAAC,MAAM,OAAO,GAAG,eAAe,CAAC;AAEvC,MAAM,UAAU,kBAAkB,CAAC,SAAiC,EAAE;IACpE,kEAAkE;IAClE,2EAA2E;IAC3E,sEAAsE;IACtE,mDAAmD;IACnD,MAAM,GAAG,GAAG;QACV,GAAG,oBAAoB;QACvB,GAAG,MAAM;QACT,aAAa,EAAE,oBAAoB,CAAC,MAAM,CAAC,aAAa,CAAC;KAC1D,CAAC;IAEF,OAAO,KAAK,UAAU,IAAI,CAAC,GAAgB;QACzC,IAAI,IAAa,CAAC;QAClB,IAAI,CAAC;YACH,IAAI,GAAG,MAAM,GAAG,CAAC,IAAI,EAAE,CAAC;QAC1B,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,YAAY,CAAC,IAAI,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,EAAE,EAAE,MAAM,EAAE,GAAG,EAAE,CAAC,CAAC;QAC/E,CAAC;QAED,MAAM,WAAW,GAAG,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,aAAa,CAAC,EAAE,KAAK,CAAC;QAC9D,MAAM,MAAM,GAAG,MAAM,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;QAEpD,uEAAuE;QACvE,yDAAyD;QACzD,OAAO,YAAY,CAAC,IAAI,CAAC,MAAM,EAAE,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IACtE,CAAC,CAAC;AACJ,CAAC;AAED,wDAAwD;AACxD,MAAM,CAAC,MAAM,IAAI,GAAG,kBAAkB,EAAE,CAAC"}
|
|
@@ -0,0 +1,93 @@
|
|
|
1
|
+
export interface DesignFontUsage {
|
|
2
|
+
family: string;
|
|
3
|
+
sizePx: number;
|
|
4
|
+
weight: number;
|
|
5
|
+
/** Elements across all pages rendering this exact combination. */
|
|
6
|
+
count: number;
|
|
7
|
+
/** Real text sampled from the site in this style. */
|
|
8
|
+
sample: string | null;
|
|
9
|
+
/** Tag names seen carrying it (h1, p, button…). */
|
|
10
|
+
tags: string[];
|
|
11
|
+
pages: string[];
|
|
12
|
+
/** True when this looks like a one-off rather than part of the type scale. */
|
|
13
|
+
outlier: boolean;
|
|
14
|
+
}
|
|
15
|
+
export type DesignColorRole = "text" | "background" | "border";
|
|
16
|
+
export interface DesignColorUsage {
|
|
17
|
+
hex: string;
|
|
18
|
+
/** Total tallies across roles. */
|
|
19
|
+
count: number;
|
|
20
|
+
roles: Record<DesignColorRole, number>;
|
|
21
|
+
pages: string[];
|
|
22
|
+
/** Share of all color tallies, 0–100. */
|
|
23
|
+
pct: number;
|
|
24
|
+
outlier: boolean;
|
|
25
|
+
}
|
|
26
|
+
export interface DesignContrastPair {
|
|
27
|
+
fg: string;
|
|
28
|
+
bg: string;
|
|
29
|
+
count: number;
|
|
30
|
+
/** Smallest font size this pair was seen at, px. */
|
|
31
|
+
minSizePx: number;
|
|
32
|
+
/** WCAG 2.x contrast ratio, e.g. 4.53. */
|
|
33
|
+
ratio: number;
|
|
34
|
+
/** The AA threshold that applies at `minSizePx` (3 for large text, else 4.5). */
|
|
35
|
+
required: number;
|
|
36
|
+
passes: boolean;
|
|
37
|
+
pages: string[];
|
|
38
|
+
}
|
|
39
|
+
export interface DesignRadiusUsage {
|
|
40
|
+
/** "8px", "9999px (full)" style label. */
|
|
41
|
+
value: string;
|
|
42
|
+
count: number;
|
|
43
|
+
pages: string[];
|
|
44
|
+
outlier: boolean;
|
|
45
|
+
}
|
|
46
|
+
export interface DesignSpacingUsage {
|
|
47
|
+
px: number;
|
|
48
|
+
count: number;
|
|
49
|
+
pages: string[];
|
|
50
|
+
/** True when the value sits off the site's dominant spacing grid. */
|
|
51
|
+
offGrid: boolean;
|
|
52
|
+
}
|
|
53
|
+
export type DesignFlagSection = "typography" | "color" | "contrast" | "radius" | "spacing";
|
|
54
|
+
export interface DesignFlag {
|
|
55
|
+
section: DesignFlagSection;
|
|
56
|
+
severity: "warn" | "info";
|
|
57
|
+
message: string;
|
|
58
|
+
}
|
|
59
|
+
export interface DesignPageScan {
|
|
60
|
+
path: string;
|
|
61
|
+
scannedAt: number;
|
|
62
|
+
elements: number;
|
|
63
|
+
}
|
|
64
|
+
export interface PolishdDesignData {
|
|
65
|
+
ready: boolean;
|
|
66
|
+
/** Pages with a scan, newest first. */
|
|
67
|
+
pages: DesignPageScan[];
|
|
68
|
+
fonts: DesignFontUsage[];
|
|
69
|
+
/** Distinct font families, most used first. */
|
|
70
|
+
families: {
|
|
71
|
+
family: string;
|
|
72
|
+
count: number;
|
|
73
|
+
}[];
|
|
74
|
+
colors: DesignColorUsage[];
|
|
75
|
+
contrast: DesignContrastPair[];
|
|
76
|
+
radii: DesignRadiusUsage[];
|
|
77
|
+
spacing: DesignSpacingUsage[];
|
|
78
|
+
flags: DesignFlag[];
|
|
79
|
+
}
|
|
80
|
+
export declare const EMPTY_DESIGN_DATA: PolishdDesignData;
|
|
81
|
+
/** WCAG 2.x contrast ratio between two hex colors, or null if unparseable. */
|
|
82
|
+
export declare function contrastRatio(a: string, b: string): number | null;
|
|
83
|
+
/**
|
|
84
|
+
* Build the full design dataset: merge per-page tallies site-wide, then run
|
|
85
|
+
* the deterministic checks. Read-only; degrades to `EMPTY_DESIGN_DATA`.
|
|
86
|
+
*/
|
|
87
|
+
export declare function getDesignData(): Promise<PolishdDesignData>;
|
|
88
|
+
/**
|
|
89
|
+
* Rule-based checks over the aggregated data. Pure function of its input so
|
|
90
|
+
* it's easy to test and the AI layer can quote the same findings verbatim.
|
|
91
|
+
*/
|
|
92
|
+
export declare function buildDesignFlags(data: PolishdDesignData): DesignFlag[];
|
|
93
|
+
//# sourceMappingURL=design.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"design.d.ts","sourceRoot":"","sources":["../../src/server/design.ts"],"names":[],"mappings":"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"}
|