@drawnagency/primitives 0.1.35 → 0.1.37

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.
@@ -49,6 +49,14 @@ export interface AuthProvider {
49
49
  getPasswordEnabled(): Promise<boolean>;
50
50
  setPasswordEnabled?(enabled: boolean): Promise<void>;
51
51
  handleCallback?(request: Request, ctx: AuthContext): Promise<Response>;
52
+ handleTokenExchange?(tokens: {
53
+ accessToken: string;
54
+ refreshToken: string;
55
+ }, type: string, ctx: AuthContext): Promise<{
56
+ redirectTo: string;
57
+ } | {
58
+ error: string;
59
+ }>;
52
60
  updatePassword?(password: string, ctx: AuthContext): Promise<void>;
53
61
  resetPassword?(email: string): Promise<void>;
54
62
  }
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/auth/types.ts"],"names":[],"mappings":"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"}
@@ -1 +1 @@
1
- {"version":3,"file":"EditorLoginForm.d.ts","sourceRoot":"","sources":["../../../src/components/shell/EditorLoginForm.tsx"],"names":[],"mappings":"AAKA,UAAU,KAAK;IACb,YAAY,EAAE;QACZ,KAAK,EAAE,OAAO,CAAC;QACf,aAAa,EAAE,OAAO,CAAC;QACvB,YAAY,EAAE,OAAO,CAAC;QACtB,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,cAAc,CAAC,EAAE,CAAC,QAAQ,GAAG,QAAQ,CAAC,EAAE,CAAC;IACzC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,wBAAgB,eAAe,CAAC,EAAE,YAAY,EAAE,cAAmB,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,KAAK,2CA0O9F"}
1
+ {"version":3,"file":"EditorLoginForm.d.ts","sourceRoot":"","sources":["../../../src/components/shell/EditorLoginForm.tsx"],"names":[],"mappings":"AA6CA,UAAU,KAAK;IACb,YAAY,EAAE;QACZ,KAAK,EAAE,OAAO,CAAC;QACf,aAAa,EAAE,OAAO,CAAC;QACvB,YAAY,EAAE,OAAO,CAAC;QACtB,cAAc,EAAE,OAAO,CAAC;KACzB,CAAC;IACF,cAAc,CAAC,EAAE,CAAC,QAAQ,GAAG,QAAQ,CAAC,EAAE,CAAC;IACzC,IAAI,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,wBAAgB,eAAe,CAAC,EAAE,YAAY,EAAE,cAAmB,EAAE,IAAI,EAAE,WAAW,EAAE,EAAE,KAAK,2CAuR9F"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@drawnagency/primitives",
3
- "version": "0.1.35",
3
+ "version": "0.1.37",
4
4
  "type": "module",
5
5
  "exports": {
6
6
  "./package.json": "./package.json",
package/src/auth/types.ts CHANGED
@@ -47,6 +47,7 @@ export interface AuthProvider {
47
47
  setPasswordEnabled?(enabled: boolean): Promise<void>;
48
48
 
49
49
  handleCallback?(request: Request, ctx: AuthContext): Promise<Response>;
50
+ handleTokenExchange?(tokens: { accessToken: string; refreshToken: string }, type: string, ctx: AuthContext): Promise<{ redirectTo: string } | { error: string }>;
50
51
  updatePassword?(password: string, ctx: AuthContext): Promise<void>;
51
52
  resetPassword?(email: string): Promise<void>;
52
53
  }
@@ -1,8 +1,48 @@
1
- import { useState, type FormEvent } from "react";
1
+ import { useState, useEffect, type FormEvent } from "react";
2
2
  import { PasswordInput } from "../shared/PasswordInput";
3
3
  import { Button } from "../shared/Button";
4
4
  import { safeRedirect } from "../../lib/safeRedirect";
5
5
 
6
+ const HASH_ERROR_MESSAGES: Record<string, string> = {
7
+ otp_expired: "This link has expired. Please request a new one.",
8
+ access_denied: "Access denied. Please request a new link or contact your site admin.",
9
+ };
10
+
11
+ type HashData = {
12
+ type: "error";
13
+ message: string;
14
+ } | {
15
+ type: "tokens";
16
+ accessToken: string;
17
+ refreshToken: string;
18
+ authType: string;
19
+ };
20
+
21
+ function parseHash(): HashData | null {
22
+ if (typeof window === "undefined" || !window.location?.hash) return null;
23
+ const hash = window.location.hash.substring(1);
24
+ if (!hash) return null;
25
+ const params = new URLSearchParams(hash);
26
+ window.history.replaceState(null, "", window.location.pathname + window.location.search);
27
+
28
+ const errorCode = params.get("error_code");
29
+ if (errorCode) {
30
+ return {
31
+ type: "error",
32
+ message: HASH_ERROR_MESSAGES[errorCode] ?? "Authentication failed. Please try again.",
33
+ };
34
+ }
35
+
36
+ const accessToken = params.get("access_token");
37
+ const refreshToken = params.get("refresh_token");
38
+ const authType = params.get("type");
39
+ if (accessToken && refreshToken && authType) {
40
+ return { type: "tokens", accessToken, refreshToken, authType };
41
+ }
42
+
43
+ return null;
44
+ }
45
+
6
46
  interface Props {
7
47
  capabilities: {
8
48
  oauth: boolean;
@@ -22,6 +62,43 @@ export function EditorLoginForm({ capabilities, oauthProviders = [], next, serve
22
62
  const [loading, setLoading] = useState(false);
23
63
  const [mode, setMode] = useState<"sign-in" | "forgot">("sign-in");
24
64
  const [resetSent, setResetSent] = useState(false);
65
+ const [exchangingTokens, setExchangingTokens] = useState(false);
66
+
67
+ useEffect(() => {
68
+ const hashData = parseHash();
69
+ if (!hashData) return;
70
+ if (hashData.type === "error") {
71
+ setError(hashData.message);
72
+ return;
73
+ }
74
+ setExchangingTokens(true);
75
+ fetch("/api/auth/token-exchange", {
76
+ method: "POST",
77
+ headers: { "Content-Type": "application/json" },
78
+ body: JSON.stringify({
79
+ accessToken: hashData.accessToken,
80
+ refreshToken: hashData.refreshToken,
81
+ type: hashData.authType,
82
+ }),
83
+ })
84
+ .then((res) => res.json())
85
+ .then((data) => {
86
+ if (data.redirectTo) {
87
+ window.location.assign(data.redirectTo);
88
+ } else {
89
+ setExchangingTokens(false);
90
+ setError(
91
+ data.error === "no_access"
92
+ ? "You don't have access to this site."
93
+ : "Authentication failed. Please try again.",
94
+ );
95
+ }
96
+ })
97
+ .catch(() => {
98
+ setExchangingTokens(false);
99
+ setError("Authentication failed. Please try again.");
100
+ });
101
+ }, []);
25
102
 
26
103
  async function handlePasswordSubmit(e: FormEvent) {
27
104
  e.preventDefault();
@@ -99,6 +176,14 @@ export function EditorLoginForm({ capabilities, oauthProviders = [], next, serve
99
176
  setResetSent(false);
100
177
  }
101
178
 
179
+ if (exchangingTokens) {
180
+ return (
181
+ <div className="mx-auto max-w-sm py-8 text-center">
182
+ <p className="text-sm text-base-contrast-light">Signing in...</p>
183
+ </div>
184
+ );
185
+ }
186
+
102
187
  if (mode === "forgot") {
103
188
  return (
104
189
  <div className="mx-auto max-w-sm space-y-6">