@checkmate-monitor/auth-frontend 0.1.0 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,22 @@
1
1
  # @checkmate-monitor/auth-frontend
2
2
 
3
+ ## 0.1.1
4
+
5
+ ### Patch Changes
6
+
7
+ - 0f8cc7d: Add runtime configuration API for Docker deployments
8
+
9
+ - Backend: Add `/api/config` endpoint serving `BASE_URL` at runtime
10
+ - Backend: Update CORS to use `BASE_URL` and auto-allow Vite dev server
11
+ - Backend: `INTERNAL_URL` now defaults to `localhost:3000` (no BASE_URL fallback)
12
+ - Frontend API: Add `RuntimeConfigProvider` context for runtime config
13
+ - Frontend: Use `RuntimeConfigProvider` from `frontend-api`
14
+ - Auth Frontend: Add `useAuthClient()` hook using runtime config
15
+
16
+ - Updated dependencies [0f8cc7d]
17
+ - @checkmate-monitor/frontend-api@0.0.3
18
+ - @checkmate-monitor/ui@0.1.1
19
+
3
20
  ## 0.1.0
4
21
 
5
22
  ### Minor Changes
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@checkmate-monitor/auth-frontend",
3
- "version": "0.1.0",
3
+ "version": "0.1.1",
4
4
  "type": "module",
5
5
  "main": "src/index.tsx",
6
6
  "exports": {
@@ -14,12 +14,13 @@ import {
14
14
  CardContent,
15
15
  CardFooter,
16
16
  } from "@checkmate-monitor/ui";
17
- import { authClient } from "../lib/auth-client";
17
+ import { useAuthClient } from "../lib/auth-client";
18
18
 
19
19
  export const ForgotPasswordPage = () => {
20
20
  const [email, setEmail] = useState("");
21
21
  const [loading, setLoading] = useState(false);
22
22
  const [submitted, setSubmitted] = useState(false);
23
+ const authClient = useAuthClient();
23
24
 
24
25
  const handleSubmit = async (e: React.FormEvent) => {
25
26
  e.preventDefault();
@@ -27,7 +27,7 @@ import {
27
27
  } from "@checkmate-monitor/ui";
28
28
  import { useEnabledStrategies } from "../hooks/useEnabledStrategies";
29
29
  import { SocialProviderButton } from "./SocialProviderButton";
30
- import { authClient } from "../lib/auth-client";
30
+ import { useAuthClient } from "../lib/auth-client";
31
31
 
32
32
  export const RegisterPage = () => {
33
33
  const [name, setName] = useState("");
@@ -42,6 +42,7 @@ export const RegisterPage = () => {
42
42
  const { strategies, loading: strategiesLoading } = useEnabledStrategies();
43
43
  const [registrationAllowed, setRegistrationAllowed] = useState<boolean>(true);
44
44
  const [checkingRegistration, setCheckingRegistration] = useState(true);
45
+ const authClient = useAuthClient();
45
46
 
46
47
  // Validate password on change
47
48
  useEffect(() => {
@@ -19,7 +19,7 @@ import {
19
19
  AlertTitle,
20
20
  AlertDescription,
21
21
  } from "@checkmate-monitor/ui";
22
- import { authClient } from "../lib/auth-client";
22
+ import { useAuthClient } from "../lib/auth-client";
23
23
 
24
24
  export const ResetPasswordPage = () => {
25
25
  const [searchParams] = useSearchParams();
@@ -32,6 +32,7 @@ export const ResetPasswordPage = () => {
32
32
  const [error, setError] = useState<string>();
33
33
  const [success, setSuccess] = useState(false);
34
34
  const [validationErrors, setValidationErrors] = useState<string[]>([]);
35
+ const authClient = useAuthClient();
35
36
 
36
37
  // Validate password on change
37
38
  useEffect(() => {
@@ -1,9 +1,10 @@
1
1
  import { useEffect, useState } from "react";
2
- import { authClient } from "../lib/auth-client";
2
+ import { useAuthClient } from "../lib/auth-client";
3
3
  import { rpcApiRef, useApi } from "@checkmate-monitor/frontend-api";
4
4
  import { AuthApi } from "@checkmate-monitor/auth-common";
5
5
 
6
6
  export const usePermissions = () => {
7
+ const authClient = useAuthClient();
7
8
  const { data: session } = authClient.useSession();
8
9
  const [permissions, setPermissions] = useState<string[]>([]);
9
10
  const [loading, setLoading] = useState(true);
package/src/index.tsx CHANGED
@@ -17,7 +17,7 @@ import { AuthErrorPage } from "./components/AuthErrorPage";
17
17
  import { ForgotPasswordPage } from "./components/ForgotPasswordPage";
18
18
  import { ResetPasswordPage } from "./components/ResetPasswordPage";
19
19
  import { authApiRef, AuthApi, AuthSession } from "./api";
20
- import { authClient } from "./lib/auth-client";
20
+ import { getAuthClientLazy } from "./lib/auth-client";
21
21
 
22
22
  import { usePermissions } from "./hooks/usePermissions";
23
23
 
@@ -93,7 +93,7 @@ class AuthPermissionApi implements PermissionApi {
93
93
  */
94
94
  class BetterAuthApi implements AuthApi {
95
95
  async signIn(email: string, password: string) {
96
- const res = await authClient.signIn.email({ email, password });
96
+ const res = await getAuthClientLazy().signIn.email({ email, password });
97
97
  if (res.error) {
98
98
  const error = new Error(res.error.message || res.error.statusText);
99
99
  error.name = res.error.code || "AuthError";
@@ -118,9 +118,9 @@ class BetterAuthApi implements AuthApi {
118
118
  }
119
119
 
120
120
  async signInWithSocial(provider: string) {
121
- const frontendUrl =
122
- import.meta.env.VITE_FRONTEND_URL || "http://localhost:5173";
123
- await authClient.signIn.social({
121
+ // Use current origin as callback URL (works in dev and production)
122
+ const frontendUrl = globalThis.location?.origin || "http://localhost:5173";
123
+ await getAuthClientLazy().signIn.social({
124
124
  provider,
125
125
  callbackURL: frontendUrl,
126
126
  errorCallbackURL: `${frontendUrl}${resolveRoute(
@@ -130,7 +130,7 @@ class BetterAuthApi implements AuthApi {
130
130
  }
131
131
 
132
132
  async signOut() {
133
- await authClient.signOut({
133
+ await getAuthClientLazy().signOut({
134
134
  fetchOptions: {
135
135
  onSuccess: () => {
136
136
  // Redirect to frontend root after successful logout
@@ -141,7 +141,7 @@ class BetterAuthApi implements AuthApi {
141
141
  }
142
142
 
143
143
  async getSession() {
144
- const res = await authClient.getSession();
144
+ const res = await getAuthClientLazy().getSession();
145
145
  if (res.error) {
146
146
  const error = new Error(res.error.message || res.error.statusText);
147
147
  error.name = res.error.code || "AuthError";
@@ -156,7 +156,7 @@ class BetterAuthApi implements AuthApi {
156
156
  }
157
157
 
158
158
  useSession() {
159
- const { data, isPending, error } = authClient.useSession();
159
+ const { data, isPending, error } = getAuthClientLazy().useSession();
160
160
  return {
161
161
  data: data as AuthSession | undefined,
162
162
  isPending,
@@ -1,6 +1,55 @@
1
+ import { useMemo } from "react";
1
2
  import { createAuthClient } from "better-auth/react";
3
+ import { useRuntimeConfig } from "@checkmate-monitor/frontend-api";
2
4
 
3
- export const authClient = createAuthClient({
4
- baseURL: import.meta.env.VITE_API_BASE_URL || "http://localhost:3000",
5
- basePath: "/api/auth",
6
- });
5
+ // Cache for lazy-initialized client
6
+ let cachedClient: ReturnType<typeof createAuthClient> | undefined;
7
+ let configPromise: Promise<string> | undefined;
8
+
9
+ /**
10
+ * React hook to get the auth client with proper runtime config.
11
+ * Uses RuntimeConfigProvider to get the base URL.
12
+ */
13
+ export function useAuthClient() {
14
+ const { baseUrl } = useRuntimeConfig();
15
+
16
+ return useMemo(
17
+ () =>
18
+ createAuthClient({
19
+ baseURL: baseUrl,
20
+ basePath: "/api/auth",
21
+ }),
22
+ [baseUrl]
23
+ );
24
+ }
25
+
26
+ /**
27
+ * Lazy-initialized auth client for class-based APIs.
28
+ * Fetches config from /api/config if not already cached.
29
+ * Use useAuthClient hook in React components instead.
30
+ */
31
+ export function getAuthClientLazy(): ReturnType<typeof createAuthClient> {
32
+ if (!cachedClient) {
33
+ // Create with default URL initially
34
+ cachedClient = createAuthClient({
35
+ baseURL: "http://localhost:3000",
36
+ basePath: "/api/auth",
37
+ });
38
+
39
+ // Fetch real config and update
40
+ if (!configPromise) {
41
+ configPromise = fetch("/api/config")
42
+ .then((res) => res.json())
43
+ .then((data: { baseUrl: string }) => data.baseUrl)
44
+ .catch(() => "http://localhost:3000");
45
+ }
46
+
47
+ configPromise.then((baseUrl) => {
48
+ cachedClient = createAuthClient({
49
+ baseURL: baseUrl,
50
+ basePath: "/api/auth",
51
+ });
52
+ });
53
+ }
54
+ return cachedClient;
55
+ }