@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.
Files changed (95) hide show
  1. package/AGENTS.md +161 -46
  2. package/CHANGELOG.md +163 -0
  3. package/README.md +275 -49
  4. package/bin/doctor.mjs +374 -0
  5. package/bin/init.mjs +215 -188
  6. package/bin/polishd.mjs +85 -0
  7. package/bin/shared.mjs +114 -0
  8. package/dist/ai/actions.d.ts +13 -2
  9. package/dist/ai/actions.d.ts.map +1 -1
  10. package/dist/ai/actions.js +19 -1
  11. package/dist/ai/actions.js.map +1 -1
  12. package/dist/ai/design.d.ts +28 -0
  13. package/dist/ai/design.d.ts.map +1 -0
  14. package/dist/ai/design.js +245 -0
  15. package/dist/ai/design.js.map +1 -0
  16. package/dist/ai/guard.d.ts +44 -3
  17. package/dist/ai/guard.d.ts.map +1 -1
  18. package/dist/ai/guard.js +13 -2
  19. package/dist/ai/guard.js.map +1 -1
  20. package/dist/ai/providers.d.ts +2 -0
  21. package/dist/ai/providers.d.ts.map +1 -1
  22. package/dist/ai/providers.js +70 -0
  23. package/dist/ai/providers.js.map +1 -1
  24. package/dist/ai/settings.d.ts +15 -1
  25. package/dist/ai/settings.d.ts.map +1 -1
  26. package/dist/ai/settings.js +38 -1
  27. package/dist/ai/settings.js.map +1 -1
  28. package/dist/ai/types.d.ts +57 -0
  29. package/dist/ai/types.d.ts.map +1 -1
  30. package/dist/client/design-scan.d.ts +37 -0
  31. package/dist/client/design-scan.d.ts.map +1 -0
  32. package/dist/client/design-scan.js +319 -0
  33. package/dist/client/design-scan.js.map +1 -0
  34. package/dist/client/init.d.ts.map +1 -1
  35. package/dist/client/init.js +67 -2
  36. package/dist/client/init.js.map +1 -1
  37. package/dist/config.d.ts +57 -3
  38. package/dist/config.d.ts.map +1 -1
  39. package/dist/config.js +62 -3
  40. package/dist/config.js.map +1 -1
  41. package/dist/dashboard/design-review-card.d.ts +15 -0
  42. package/dist/dashboard/design-review-card.d.ts.map +1 -0
  43. package/dist/dashboard/design-review-card.js +82 -0
  44. package/dist/dashboard/design-review-card.js.map +1 -0
  45. package/dist/dashboard/design.d.ts +10 -0
  46. package/dist/dashboard/design.d.ts.map +1 -0
  47. package/dist/dashboard/design.js +83 -0
  48. package/dist/dashboard/design.js.map +1 -0
  49. package/dist/dashboard/index.d.ts +35 -5
  50. package/dist/dashboard/index.d.ts.map +1 -1
  51. package/dist/dashboard/index.js +176 -18
  52. package/dist/dashboard/index.js.map +1 -1
  53. package/dist/dashboard/journeys.d.ts.map +1 -1
  54. package/dist/dashboard/journeys.js +1 -0
  55. package/dist/dashboard/journeys.js.map +1 -1
  56. package/dist/dashboard/summary.d.ts.map +1 -1
  57. package/dist/dashboard/summary.js +59 -5
  58. package/dist/dashboard/summary.js.map +1 -1
  59. package/dist/dashboard/token-auth.d.ts +56 -0
  60. package/dist/dashboard/token-auth.d.ts.map +1 -0
  61. package/dist/dashboard/token-auth.js +158 -0
  62. package/dist/dashboard/token-auth.js.map +1 -0
  63. package/dist/dashboard/unlock.d.ts +2 -0
  64. package/dist/dashboard/unlock.d.ts.map +1 -0
  65. package/dist/dashboard/unlock.js +54 -0
  66. package/dist/dashboard/unlock.js.map +1 -0
  67. package/dist/dashboard.css +2740 -0
  68. package/dist/proxy.d.ts +53 -5
  69. package/dist/proxy.d.ts.map +1 -1
  70. package/dist/proxy.js +73 -3
  71. package/dist/proxy.js.map +1 -1
  72. package/dist/route.d.ts.map +1 -1
  73. package/dist/route.js +11 -3
  74. package/dist/route.js.map +1 -1
  75. package/dist/server/design.d.ts +93 -0
  76. package/dist/server/design.d.ts.map +1 -0
  77. package/dist/server/design.js +430 -0
  78. package/dist/server/design.js.map +1 -0
  79. package/dist/server/ingest.d.ts +33 -2
  80. package/dist/server/ingest.d.ts.map +1 -1
  81. package/dist/server/ingest.js +70 -8
  82. package/dist/server/ingest.js.map +1 -1
  83. package/dist/server/queries.d.ts +16 -0
  84. package/dist/server/queries.d.ts.map +1 -1
  85. package/dist/server/queries.js +80 -16
  86. package/dist/server/queries.js.map +1 -1
  87. package/dist/session.d.ts.map +1 -1
  88. package/dist/session.js +4 -2
  89. package/dist/session.js.map +1 -1
  90. package/dist/shared/types.d.ts +31 -1
  91. package/dist/shared/types.d.ts.map +1 -1
  92. package/dist/shared/types.js +1 -0
  93. package/dist/shared/types.js.map +1 -1
  94. package/docs/SETUP.md +308 -51
  95. 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 { NextRequest } from "next/server";
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): import("next/server").NextResponse<unknown>;
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, matcher } = createPolishdProxy({ sessionCookie: "polish_session" });
32
+ * const { proxy } = createPolishdProxy({ sessionCookie: "polish_session" });
33
33
  * export { proxy };
34
- * export const config = { matcher };
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) => import("next/server").NextResponse<unknown>;
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
@@ -1 +1 @@
1
- {"version":3,"file":"proxy.d.ts","sourceRoot":"","sources":["../src/proxy.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAC;AAE/C,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,+CAEzC;AAED,eAAO,MAAM,MAAM;;CAA8B,CAAC;AAElD;;;;;;;GAOG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM;qBAEjD,WAAW;;EAG/B"}
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 = { matcher: polishdMatcher };
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, matcher } = createPolishdProxy({ sessionCookie: "polish_session" });
33
+ * const { proxy } = createPolishdProxy({ sessionCookie: "polish_session" });
20
34
  * export { proxy };
21
- * export const config = { matcher };
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":"AAcA,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,EAAE,OAAO,EAAE,cAAc,EAAE,CAAC;AAElD;;;;;;;GAOG;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"}
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"}
@@ -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,EAAwB,KAAK,aAAa,EAAE,MAAM,UAAU,CAAC;AAIpE,eAAO,MAAM,OAAO,WAAW,CAAC;AAEhC,eAAO,MAAM,OAAO,kBAAkB,CAAC;AAEvC,wBAAgB,kBAAkB,CAAC,MAAM,GAAE,OAAO,CAAC,aAAa,CAAM,IAGzC,KAAK,WAAW;;;oDAe5C;AAED,wDAAwD;AACxD,eAAO,MAAM,IAAI,QAlBiB,WAAW;;;mDAkBL,CAAC"}
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
- const cfg = { ...defaultPolishdConfig, ...config };
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;AACpE,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,MAAM,GAAG,GAAG,EAAE,GAAG,oBAAoB,EAAE,GAAG,MAAM,EAAE,CAAC;IAEnD,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,CAAC,CAAC;QAE/C,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"}
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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"}