@archlast/client 0.1.2 → 0.1.3

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/LICENSE CHANGED
@@ -1,21 +1,21 @@
1
- MIT License
2
-
3
- Copyright (c) 2025 Archlast Team
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
1
+ MIT License
2
+
3
+ Copyright (c) 2025 Archlast Team
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md CHANGED
@@ -1,174 +1,174 @@
1
- # @archlast/client
2
-
3
- The Archlast client SDK provides WebSocket-based queries and mutations, React
4
- hooks with cache integration, authentication helpers, storage utilities, admin
5
- APIs, and optional tRPC access.
6
-
7
- ## Installation
8
-
9
- ```bash
10
- npm install @archlast/client
11
-
12
- # Other package managers
13
- pnpm add @archlast/client
14
- yarn add @archlast/client
15
- bun add @archlast/client
16
- ```
17
-
18
- Peer dependencies:
19
-
20
- ```bash
21
- npm install react react-dom @tanstack/react-query
22
- ```
23
-
24
- ## Quick start
25
-
26
- ```ts
27
- import { ArchlastClient } from "@archlast/client";
28
- import { ArchlastProvider, useQuery, useMutation } from "@archlast/client/react";
29
- import { api } from "./_generated/api";
30
-
31
- const client = new ArchlastClient(
32
- "ws://localhost:4000/ws",
33
- "http://localhost:4000",
34
- "web"
35
- );
36
-
37
- function App() {
38
- return (
39
- <ArchlastProvider client={client}>
40
- <TodoList />
41
- </ArchlastProvider>
42
- );
43
- }
44
-
45
- function TodoList() {
46
- const tasks = useQuery(api.tasks.list, {});
47
- const createTask = useMutation(api.tasks.create);
48
-
49
- return (
50
- <div>
51
- <pre>{JSON.stringify(tasks, null, 2)}</pre>
52
- <button onClick={() => createTask({ text: "New task" })}>
53
- Add
54
- </button>
55
- </div>
56
- );
57
- }
58
- ```
59
-
60
- The `api` object is generated by the CLI in `_generated/api.ts`.
61
-
62
- ## Client configuration
63
-
64
- Constructor signature:
65
-
66
- ```ts
67
- new ArchlastClient(wsUrl, httpUrl?, appId?, authUrl?, options?)
68
- ```
69
-
70
- Options:
71
- - `autoConnect` (default true)
72
- - `apiKey` Better Auth API key (`arch_` prefix)
73
- - `isAdmin` subscribe to admin streams
74
- - `betterAuthCookies` for session cookies
75
-
76
- ```ts
77
- const client = new ArchlastClient(
78
- "ws://localhost:4000/ws",
79
- "http://localhost:4000",
80
- "web",
81
- undefined,
82
- { apiKey: "arch_example" }
83
- );
84
-
85
- client.setApiKey("arch_new_key");
86
- client.setBetterAuthCookies({ "better-auth.session": "..." });
87
- ```
88
-
89
- ## React hooks
90
-
91
- Available from `@archlast/client/react`:
92
-
93
- - `useQuery` / `useMutation` for live queries and mutations
94
- - `usePagination` for cursor based queries
95
- - `useAuth` for Better Auth session state
96
- - `useUpload`, `useDownload` for storage
97
- - `useStorageList`, `useStorageMetadata`, `useStorageDeleteFile`
98
-
99
- Example:
100
-
101
- ```ts
102
- const items = useQuery(api.items.list, { limit: 10 });
103
- const createItem = useMutation(api.items.create);
104
- ```
105
-
106
- ## Direct client usage
107
-
108
- ```ts
109
- const data = await client.fetch("tasks.get", { id: "123" });
110
- const updated = await client.mutate("tasks.update", { id: "123", text: "Hi" });
111
- ```
112
-
113
- ## Authentication
114
-
115
- Auth uses Better Auth endpoints under `/api/auth/*`.
116
-
117
- ```ts
118
- import { useAuth } from "@archlast/client/react";
119
-
120
- const { signIn, signOut, isAuthenticated } = useAuth();
121
- ```
122
-
123
- Or use the auth client directly:
124
-
125
- ```ts
126
- import { ArchlastAuthClient } from "@archlast/client/auth";
127
-
128
- const auth = new ArchlastAuthClient({ baseUrl: "http://localhost:4000" });
129
- ```
130
-
131
- ## Storage
132
-
133
- ```ts
134
- const file = new File(["hello"], "hello.txt", { type: "text/plain" });
135
- const uploaded = await client.storage.upload(file);
136
- const list = await client.storage.list();
137
- const { url } = await client.storage.presign(uploaded.id);
138
- ```
139
-
140
- ## Admin APIs
141
-
142
- ```ts
143
- const profile = await client.admin.auth.getProfile();
144
- ```
145
-
146
- ## tRPC integration
147
-
148
- ```ts
149
- import { createArchlastTRPCClient } from "@archlast/client/trpc";
150
- import type { AppRouter } from "./_generated/rpc";
151
-
152
- const trpc = createArchlastTRPCClient<AppRouter>({
153
- baseUrl: "http://localhost:4000",
154
- apiKey: "arch_example"
155
- });
156
- ```
157
-
158
- ## Subpath exports
159
-
160
- - `@archlast/client/react`
161
- - `@archlast/client/trpc`
162
- - `@archlast/client/auth`
163
- - `@archlast/client/storage`
164
- - `@archlast/client/admin`
165
-
166
- ## Troubleshooting
167
-
168
- - WebSocket errors: use `ws://<host>/ws` and confirm CORS settings.
169
- - Auth errors: ensure cookies or API key are configured.
170
- - Storage uploads: use `File` or `Blob` for browser uploads.
171
-
172
- ## Publishing (maintainers)
173
-
1
+ # @archlast/client
2
+
3
+ The Archlast client SDK provides WebSocket-based queries and mutations, React
4
+ hooks with cache integration, authentication helpers, storage utilities, admin
5
+ APIs, and optional tRPC access.
6
+
7
+ ## Installation
8
+
9
+ ```bash
10
+ npm install @archlast/client
11
+
12
+ # Other package managers
13
+ pnpm add @archlast/client
14
+ yarn add @archlast/client
15
+ bun add @archlast/client
16
+ ```
17
+
18
+ Peer dependencies:
19
+
20
+ ```bash
21
+ npm install react react-dom @tanstack/react-query
22
+ ```
23
+
24
+ ## Quick start
25
+
26
+ ```ts
27
+ import { ArchlastClient } from "@archlast/client";
28
+ import { ArchlastProvider, useQuery, useMutation } from "@archlast/client/react";
29
+ import { api } from "./_generated/api";
30
+
31
+ const client = new ArchlastClient(
32
+ "ws://localhost:4000/ws",
33
+ "http://localhost:4000",
34
+ "web"
35
+ );
36
+
37
+ function App() {
38
+ return (
39
+ <ArchlastProvider client={client}>
40
+ <TodoList />
41
+ </ArchlastProvider>
42
+ );
43
+ }
44
+
45
+ function TodoList() {
46
+ const tasks = useQuery(api.tasks.list, {});
47
+ const createTask = useMutation(api.tasks.create);
48
+
49
+ return (
50
+ <div>
51
+ <pre>{JSON.stringify(tasks, null, 2)}</pre>
52
+ <button onClick={() => createTask({ text: "New task" })}>
53
+ Add
54
+ </button>
55
+ </div>
56
+ );
57
+ }
58
+ ```
59
+
60
+ The `api` object is generated by the CLI in `_generated/api.ts`.
61
+
62
+ ## Client configuration
63
+
64
+ Constructor signature:
65
+
66
+ ```ts
67
+ new ArchlastClient(wsUrl, httpUrl?, appId?, authUrl?, options?)
68
+ ```
69
+
70
+ Options:
71
+ - `autoConnect` (default true)
72
+ - `apiKey` Better Auth API key (`arch_` prefix)
73
+ - `isAdmin` subscribe to admin streams
74
+ - `betterAuthCookies` for session cookies
75
+
76
+ ```ts
77
+ const client = new ArchlastClient(
78
+ "ws://localhost:4000/ws",
79
+ "http://localhost:4000",
80
+ "web",
81
+ undefined,
82
+ { apiKey: "arch_example" }
83
+ );
84
+
85
+ client.setApiKey("arch_new_key");
86
+ client.setBetterAuthCookies({ "better-auth.session": "..." });
87
+ ```
88
+
89
+ ## React hooks
90
+
91
+ Available from `@archlast/client/react`:
92
+
93
+ - `useQuery` / `useMutation` for live queries and mutations
94
+ - `usePagination` for cursor based queries
95
+ - `useAuth` for Better Auth session state
96
+ - `useUpload`, `useDownload` for storage
97
+ - `useStorageList`, `useStorageMetadata`, `useStorageDeleteFile`
98
+
99
+ Example:
100
+
101
+ ```ts
102
+ const items = useQuery(api.items.list, { limit: 10 });
103
+ const createItem = useMutation(api.items.create);
104
+ ```
105
+
106
+ ## Direct client usage
107
+
108
+ ```ts
109
+ const data = await client.fetch("tasks.get", { id: "123" });
110
+ const updated = await client.mutate("tasks.update", { id: "123", text: "Hi" });
111
+ ```
112
+
113
+ ## Authentication
114
+
115
+ Auth uses Better Auth endpoints under `/api/auth/*`.
116
+
117
+ ```ts
118
+ import { useAuth } from "@archlast/client/react";
119
+
120
+ const { signIn, signOut, isAuthenticated } = useAuth();
121
+ ```
122
+
123
+ Or use the auth client directly:
124
+
125
+ ```ts
126
+ import { ArchlastAuthClient } from "@archlast/client/auth";
127
+
128
+ const auth = new ArchlastAuthClient({ baseUrl: "http://localhost:4000" });
129
+ ```
130
+
131
+ ## Storage
132
+
133
+ ```ts
134
+ const file = new File(["hello"], "hello.txt", { type: "text/plain" });
135
+ const uploaded = await client.storage.upload(file);
136
+ const list = await client.storage.list();
137
+ const { url } = await client.storage.presign(uploaded.id);
138
+ ```
139
+
140
+ ## Admin APIs
141
+
142
+ ```ts
143
+ const profile = await client.admin.auth.getProfile();
144
+ ```
145
+
146
+ ## tRPC integration
147
+
148
+ ```ts
149
+ import { createArchlastTRPCClient } from "@archlast/client/trpc";
150
+ import type { AppRouter } from "./_generated/rpc";
151
+
152
+ const trpc = createArchlastTRPCClient<AppRouter>({
153
+ baseUrl: "http://localhost:4000",
154
+ apiKey: "arch_example"
155
+ });
156
+ ```
157
+
158
+ ## Subpath exports
159
+
160
+ - `@archlast/client/react`
161
+ - `@archlast/client/trpc`
162
+ - `@archlast/client/auth`
163
+ - `@archlast/client/storage`
164
+ - `@archlast/client/admin`
165
+
166
+ ## Troubleshooting
167
+
168
+ - WebSocket errors: use `ws://<host>/ws` and confirm CORS settings.
169
+ - Auth errors: ensure cookies or API key are configured.
170
+ - Storage uploads: use `File` or `Blob` for browser uploads.
171
+
172
+ ## Publishing (maintainers)
173
+
174
174
  See `docs/npm-publishing.md` for release and publish steps.
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/admin/index.ts"],"sourcesContent":["import axios, { AxiosInstance } from \"axios\";\n\nexport type AdminSession = {\n id: string;\n userId: string;\n createdAt: number;\n lastAccess: number;\n userAgent: string | null;\n ipAddress: string | null;\n current: boolean;\n};\n\nexport type AdminProfile = {\n id: string;\n email: string;\n is_super_admin: boolean;\n created_at: number;\n};\n\nexport type AdminClientOptions = {\n /**\n * Better-Auth API key for authentication\n * When provided, uses x-api-key header instead of cookies\n */\n apiKey?: string;\n};\n\nexport class AdminAuthClient {\n private readonly axios: AxiosInstance;\n\n constructor(baseUrl: string, options?: AdminClientOptions) {\n this.axios = axios.create({\n baseURL: baseUrl,\n withCredentials: !options?.apiKey,\n headers: {\n ...(options?.apiKey ? { \"x-api-key\": options.apiKey } : {}),\n },\n });\n }\n\n async signIn(\n email: string,\n password: string\n ): Promise<{ success: boolean; user: AdminProfile }> {\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-in\", {\n email,\n password,\n });\n return response.data;\n }\n\n async signOut(): Promise<{ success: boolean }> {\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-out\");\n return response.data;\n }\n\n async getProfile(): Promise<{ user: AdminProfile }> {\n const response = await this.axios.get(\"/_archlast/admin/auth/me\");\n return response.data;\n }\n\n async getSessions(): Promise<{ sessions: AdminSession[] }> {\n const response = await this.axios.get(\"/_archlast/admin/auth/sessions\");\n return response.data;\n }\n\n async revokeSession(sessionId: string): Promise<{ success: boolean }> {\n const response = await this.axios.post(\"/_archlast/admin/auth/revoke-session\", {\n sessionId,\n });\n return response.data;\n }\n\n async signOutAll(): Promise<{ success: boolean }> {\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-out-all\");\n return response.data;\n }\n}\n\nexport class AdminClient {\n public auth: AdminAuthClient;\n // Add other admin clients here (users, tenants, etc.)\n\n constructor(baseUrl: string, options?: AdminClientOptions) {\n this.auth = new AdminAuthClient(baseUrl, options);\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAqC;AA2B9B,IAAM,kBAAN,MAAsB;AAAA,EAGzB,YAAY,SAAiB,SAA8B;AAF3D,wBAAiB;AAGb,SAAK,QAAQ,aAAAA,QAAM,OAAO;AAAA,MACtB,SAAS;AAAA,MACT,iBAAiB,CAAC,SAAS;AAAA,MAC3B,SAAS;AAAA,QACL,GAAI,SAAS,SAAS,EAAE,aAAa,QAAQ,OAAO,IAAI,CAAC;AAAA,MAC7D;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EAEA,MAAM,OACF,OACA,UACiD;AACjD,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,iCAAiC;AAAA,MACpE;AAAA,MACA;AAAA,IACJ,CAAC;AACD,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,UAAyC;AAC3C,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,gCAAgC;AACvE,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,aAA8C;AAChD,UAAM,WAAW,MAAM,KAAK,MAAM,IAAI,0BAA0B;AAChE,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,cAAqD;AACvD,UAAM,WAAW,MAAM,KAAK,MAAM,IAAI,gCAAgC;AACtE,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,cAAc,WAAkD;AAClE,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,wCAAwC;AAAA,MAC3E;AAAA,IACJ,CAAC;AACD,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,aAA4C;AAC9C,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,oCAAoC;AAC3E,WAAO,SAAS;AAAA,EACpB;AACJ;AAEO,IAAM,cAAN,MAAkB;AAAA;AAAA,EAIrB,YAAY,SAAiB,SAA8B;AAH3D,wBAAO;AAIH,SAAK,OAAO,IAAI,gBAAgB,SAAS,OAAO;AAAA,EACpD;AACJ;","names":["axios"]}
1
+ {"version":3,"sources":["../../src/admin/index.ts"],"sourcesContent":["import axios, { AxiosInstance } from \"axios\";\r\n\r\nexport type AdminSession = {\r\n id: string;\r\n userId: string;\r\n createdAt: number;\r\n lastAccess: number;\r\n userAgent: string | null;\r\n ipAddress: string | null;\r\n current: boolean;\r\n};\r\n\r\nexport type AdminProfile = {\r\n id: string;\r\n email: string;\r\n is_super_admin: boolean;\r\n created_at: number;\r\n};\r\n\r\nexport type AdminClientOptions = {\r\n /**\r\n * Better-Auth API key for authentication\r\n * When provided, uses x-api-key header instead of cookies\r\n */\r\n apiKey?: string;\r\n};\r\n\r\nexport class AdminAuthClient {\r\n private readonly axios: AxiosInstance;\r\n\r\n constructor(baseUrl: string, options?: AdminClientOptions) {\r\n this.axios = axios.create({\r\n baseURL: baseUrl,\r\n withCredentials: !options?.apiKey,\r\n headers: {\r\n ...(options?.apiKey ? { \"x-api-key\": options.apiKey } : {}),\r\n },\r\n });\r\n }\r\n\r\n async signIn(\r\n email: string,\r\n password: string\r\n ): Promise<{ success: boolean; user: AdminProfile }> {\r\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-in\", {\r\n email,\r\n password,\r\n });\r\n return response.data;\r\n }\r\n\r\n async signOut(): Promise<{ success: boolean }> {\r\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-out\");\r\n return response.data;\r\n }\r\n\r\n async getProfile(): Promise<{ user: AdminProfile }> {\r\n const response = await this.axios.get(\"/_archlast/admin/auth/me\");\r\n return response.data;\r\n }\r\n\r\n async getSessions(): Promise<{ sessions: AdminSession[] }> {\r\n const response = await this.axios.get(\"/_archlast/admin/auth/sessions\");\r\n return response.data;\r\n }\r\n\r\n async revokeSession(sessionId: string): Promise<{ success: boolean }> {\r\n const response = await this.axios.post(\"/_archlast/admin/auth/revoke-session\", {\r\n sessionId,\r\n });\r\n return response.data;\r\n }\r\n\r\n async signOutAll(): Promise<{ success: boolean }> {\r\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-out-all\");\r\n return response.data;\r\n }\r\n}\r\n\r\nexport class AdminClient {\r\n public auth: AdminAuthClient;\r\n // Add other admin clients here (users, tenants, etc.)\r\n\r\n constructor(baseUrl: string, options?: AdminClientOptions) {\r\n this.auth = new AdminAuthClient(baseUrl, options);\r\n }\r\n}\r\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,mBAAqC;AA2B9B,IAAM,kBAAN,MAAsB;AAAA,EAGzB,YAAY,SAAiB,SAA8B;AAF3D,wBAAiB;AAGb,SAAK,QAAQ,aAAAA,QAAM,OAAO;AAAA,MACtB,SAAS;AAAA,MACT,iBAAiB,CAAC,SAAS;AAAA,MAC3B,SAAS;AAAA,QACL,GAAI,SAAS,SAAS,EAAE,aAAa,QAAQ,OAAO,IAAI,CAAC;AAAA,MAC7D;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EAEA,MAAM,OACF,OACA,UACiD;AACjD,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,iCAAiC;AAAA,MACpE;AAAA,MACA;AAAA,IACJ,CAAC;AACD,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,UAAyC;AAC3C,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,gCAAgC;AACvE,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,aAA8C;AAChD,UAAM,WAAW,MAAM,KAAK,MAAM,IAAI,0BAA0B;AAChE,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,cAAqD;AACvD,UAAM,WAAW,MAAM,KAAK,MAAM,IAAI,gCAAgC;AACtE,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,cAAc,WAAkD;AAClE,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,wCAAwC;AAAA,MAC3E;AAAA,IACJ,CAAC;AACD,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,aAA4C;AAC9C,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,oCAAoC;AAC3E,WAAO,SAAS;AAAA,EACpB;AACJ;AAEO,IAAM,cAAN,MAAkB;AAAA;AAAA,EAIrB,YAAY,SAAiB,SAA8B;AAH3D,wBAAO;AAIH,SAAK,OAAO,IAAI,gBAAgB,SAAS,OAAO;AAAA,EACpD;AACJ;","names":["axios"]}
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/admin/index.ts"],"sourcesContent":["import axios, { AxiosInstance } from \"axios\";\n\nexport type AdminSession = {\n id: string;\n userId: string;\n createdAt: number;\n lastAccess: number;\n userAgent: string | null;\n ipAddress: string | null;\n current: boolean;\n};\n\nexport type AdminProfile = {\n id: string;\n email: string;\n is_super_admin: boolean;\n created_at: number;\n};\n\nexport type AdminClientOptions = {\n /**\n * Better-Auth API key for authentication\n * When provided, uses x-api-key header instead of cookies\n */\n apiKey?: string;\n};\n\nexport class AdminAuthClient {\n private readonly axios: AxiosInstance;\n\n constructor(baseUrl: string, options?: AdminClientOptions) {\n this.axios = axios.create({\n baseURL: baseUrl,\n withCredentials: !options?.apiKey,\n headers: {\n ...(options?.apiKey ? { \"x-api-key\": options.apiKey } : {}),\n },\n });\n }\n\n async signIn(\n email: string,\n password: string\n ): Promise<{ success: boolean; user: AdminProfile }> {\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-in\", {\n email,\n password,\n });\n return response.data;\n }\n\n async signOut(): Promise<{ success: boolean }> {\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-out\");\n return response.data;\n }\n\n async getProfile(): Promise<{ user: AdminProfile }> {\n const response = await this.axios.get(\"/_archlast/admin/auth/me\");\n return response.data;\n }\n\n async getSessions(): Promise<{ sessions: AdminSession[] }> {\n const response = await this.axios.get(\"/_archlast/admin/auth/sessions\");\n return response.data;\n }\n\n async revokeSession(sessionId: string): Promise<{ success: boolean }> {\n const response = await this.axios.post(\"/_archlast/admin/auth/revoke-session\", {\n sessionId,\n });\n return response.data;\n }\n\n async signOutAll(): Promise<{ success: boolean }> {\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-out-all\");\n return response.data;\n }\n}\n\nexport class AdminClient {\n public auth: AdminAuthClient;\n // Add other admin clients here (users, tenants, etc.)\n\n constructor(baseUrl: string, options?: AdminClientOptions) {\n this.auth = new AdminAuthClient(baseUrl, options);\n }\n}\n"],"mappings":";;;;;AAAA,OAAO,WAA8B;AA2B9B,IAAM,kBAAN,MAAsB;AAAA,EAGzB,YAAY,SAAiB,SAA8B;AAF3D,wBAAiB;AAGb,SAAK,QAAQ,MAAM,OAAO;AAAA,MACtB,SAAS;AAAA,MACT,iBAAiB,CAAC,SAAS;AAAA,MAC3B,SAAS;AAAA,QACL,GAAI,SAAS,SAAS,EAAE,aAAa,QAAQ,OAAO,IAAI,CAAC;AAAA,MAC7D;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EAEA,MAAM,OACF,OACA,UACiD;AACjD,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,iCAAiC;AAAA,MACpE;AAAA,MACA;AAAA,IACJ,CAAC;AACD,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,UAAyC;AAC3C,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,gCAAgC;AACvE,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,aAA8C;AAChD,UAAM,WAAW,MAAM,KAAK,MAAM,IAAI,0BAA0B;AAChE,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,cAAqD;AACvD,UAAM,WAAW,MAAM,KAAK,MAAM,IAAI,gCAAgC;AACtE,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,cAAc,WAAkD;AAClE,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,wCAAwC;AAAA,MAC3E;AAAA,IACJ,CAAC;AACD,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,aAA4C;AAC9C,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,oCAAoC;AAC3E,WAAO,SAAS;AAAA,EACpB;AACJ;AAEO,IAAM,cAAN,MAAkB;AAAA;AAAA,EAIrB,YAAY,SAAiB,SAA8B;AAH3D,wBAAO;AAIH,SAAK,OAAO,IAAI,gBAAgB,SAAS,OAAO;AAAA,EACpD;AACJ;","names":[]}
1
+ {"version":3,"sources":["../../src/admin/index.ts"],"sourcesContent":["import axios, { AxiosInstance } from \"axios\";\r\n\r\nexport type AdminSession = {\r\n id: string;\r\n userId: string;\r\n createdAt: number;\r\n lastAccess: number;\r\n userAgent: string | null;\r\n ipAddress: string | null;\r\n current: boolean;\r\n};\r\n\r\nexport type AdminProfile = {\r\n id: string;\r\n email: string;\r\n is_super_admin: boolean;\r\n created_at: number;\r\n};\r\n\r\nexport type AdminClientOptions = {\r\n /**\r\n * Better-Auth API key for authentication\r\n * When provided, uses x-api-key header instead of cookies\r\n */\r\n apiKey?: string;\r\n};\r\n\r\nexport class AdminAuthClient {\r\n private readonly axios: AxiosInstance;\r\n\r\n constructor(baseUrl: string, options?: AdminClientOptions) {\r\n this.axios = axios.create({\r\n baseURL: baseUrl,\r\n withCredentials: !options?.apiKey,\r\n headers: {\r\n ...(options?.apiKey ? { \"x-api-key\": options.apiKey } : {}),\r\n },\r\n });\r\n }\r\n\r\n async signIn(\r\n email: string,\r\n password: string\r\n ): Promise<{ success: boolean; user: AdminProfile }> {\r\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-in\", {\r\n email,\r\n password,\r\n });\r\n return response.data;\r\n }\r\n\r\n async signOut(): Promise<{ success: boolean }> {\r\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-out\");\r\n return response.data;\r\n }\r\n\r\n async getProfile(): Promise<{ user: AdminProfile }> {\r\n const response = await this.axios.get(\"/_archlast/admin/auth/me\");\r\n return response.data;\r\n }\r\n\r\n async getSessions(): Promise<{ sessions: AdminSession[] }> {\r\n const response = await this.axios.get(\"/_archlast/admin/auth/sessions\");\r\n return response.data;\r\n }\r\n\r\n async revokeSession(sessionId: string): Promise<{ success: boolean }> {\r\n const response = await this.axios.post(\"/_archlast/admin/auth/revoke-session\", {\r\n sessionId,\r\n });\r\n return response.data;\r\n }\r\n\r\n async signOutAll(): Promise<{ success: boolean }> {\r\n const response = await this.axios.post(\"/_archlast/admin/auth/sign-out-all\");\r\n return response.data;\r\n }\r\n}\r\n\r\nexport class AdminClient {\r\n public auth: AdminAuthClient;\r\n // Add other admin clients here (users, tenants, etc.)\r\n\r\n constructor(baseUrl: string, options?: AdminClientOptions) {\r\n this.auth = new AdminAuthClient(baseUrl, options);\r\n }\r\n}\r\n"],"mappings":";;;;;AAAA,OAAO,WAA8B;AA2B9B,IAAM,kBAAN,MAAsB;AAAA,EAGzB,YAAY,SAAiB,SAA8B;AAF3D,wBAAiB;AAGb,SAAK,QAAQ,MAAM,OAAO;AAAA,MACtB,SAAS;AAAA,MACT,iBAAiB,CAAC,SAAS;AAAA,MAC3B,SAAS;AAAA,QACL,GAAI,SAAS,SAAS,EAAE,aAAa,QAAQ,OAAO,IAAI,CAAC;AAAA,MAC7D;AAAA,IACJ,CAAC;AAAA,EACL;AAAA,EAEA,MAAM,OACF,OACA,UACiD;AACjD,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,iCAAiC;AAAA,MACpE;AAAA,MACA;AAAA,IACJ,CAAC;AACD,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,UAAyC;AAC3C,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,gCAAgC;AACvE,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,aAA8C;AAChD,UAAM,WAAW,MAAM,KAAK,MAAM,IAAI,0BAA0B;AAChE,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,cAAqD;AACvD,UAAM,WAAW,MAAM,KAAK,MAAM,IAAI,gCAAgC;AACtE,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,cAAc,WAAkD;AAClE,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,wCAAwC;AAAA,MAC3E;AAAA,IACJ,CAAC;AACD,WAAO,SAAS;AAAA,EACpB;AAAA,EAEA,MAAM,aAA4C;AAC9C,UAAM,WAAW,MAAM,KAAK,MAAM,KAAK,oCAAoC;AAC3E,WAAO,SAAS;AAAA,EACpB;AACJ;AAEO,IAAM,cAAN,MAAkB;AAAA;AAAA,EAIrB,YAAY,SAAiB,SAA8B;AAH3D,wBAAO;AAIH,SAAK,OAAO,IAAI,gBAAgB,SAAS,OAAO;AAAA,EACpD;AACJ;","names":[]}
@@ -33,10 +33,58 @@ var __publicField = (obj, key, value) => __defNormalProp(obj, typeof key !== "sy
33
33
  var auth_exports = {};
34
34
  __export(auth_exports, {
35
35
  ArchlastAuthClient: () => ArchlastAuthClient,
36
- default: () => auth_default
36
+ betterAuthClient: () => authClient,
37
+ createArchlastAuthClient: () => createArchlastAuthClient,
38
+ default: () => auth_default,
39
+ useBetterAuthSession: () => useSession
37
40
  });
38
41
  module.exports = __toCommonJS(auth_exports);
39
42
  var import_axios = __toESM(require("axios"), 1);
43
+
44
+ // src/auth/better-auth.ts
45
+ var import_react = require("better-auth/react");
46
+ var import_plugins = require("better-auth/client/plugins");
47
+ function getBetterAuthBaseURL() {
48
+ const envURL = process.env.NEXT_PUBLIC_BETTER_AUTH_URL || process.env.NEXT_PUBLIC_ARCHLAST_HTTP_URL || process.env.ARCHLAST_HTTP_URL;
49
+ if (envURL) {
50
+ return `${envURL}/api/auth`;
51
+ }
52
+ return "http://localhost:4000/api/auth";
53
+ }
54
+ var authClient = (0, import_react.createAuthClient)({
55
+ baseURL: getBetterAuthBaseURL(),
56
+ fetchOptions: {
57
+ credentials: "include"
58
+ // Required for cookies
59
+ },
60
+ plugins: [
61
+ // Admin plugin - user management, roles, bans
62
+ (0, import_plugins.adminClient)(),
63
+ // Organization plugin - multi-tenancy
64
+ (0, import_plugins.organizationClient)(),
65
+ // Username plugin - username-based sign-in
66
+ (0, import_plugins.usernameClient)()
67
+ ]
68
+ });
69
+ function useSession() {
70
+ return authClient.useSession();
71
+ }
72
+ function createArchlastAuthClient(options) {
73
+ return (0, import_react.createAuthClient)({
74
+ baseURL: options.baseURL || getBetterAuthBaseURL(),
75
+ fetchOptions: {
76
+ credentials: "include",
77
+ ...options.fetchOptions
78
+ },
79
+ plugins: [
80
+ (0, import_plugins.adminClient)(),
81
+ (0, import_plugins.organizationClient)(),
82
+ (0, import_plugins.usernameClient)()
83
+ ]
84
+ });
85
+ }
86
+
87
+ // src/auth/index.ts
40
88
  function resolveBaseUrl(explicit) {
41
89
  if (explicit && explicit.trim()) return explicit.replace(/\/+$/, "");
42
90
  if (typeof window !== "undefined" && window.location?.origin) return window.location.origin;
@@ -169,6 +217,9 @@ var ArchlastAuthClient = class {
169
217
  var auth_default = ArchlastAuthClient;
170
218
  // Annotate the CommonJS export names for ESM import in node:
171
219
  0 && (module.exports = {
172
- ArchlastAuthClient
220
+ ArchlastAuthClient,
221
+ betterAuthClient,
222
+ createArchlastAuthClient,
223
+ useBetterAuthSession
173
224
  });
174
225
  //# sourceMappingURL=index.cjs.map
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/auth/index.ts"],"sourcesContent":["/**\n * Client-side auth API wrapper for Archlast.\n *\n * This now uses Better-Auth endpoints via the proxy:\n * - GET /api/auth/get-session\n * - POST /api/auth/sign-up\n * - POST /api/auth/sign-in\n * - POST /api/auth/sign-out\n *\n * Migration from legacy /_auth/* endpoints:\n * - /_auth/state → /api/auth/get-session\n * - /_auth/sign-up → /api/auth/sign-up (email)\n * - /_auth/sign-in → /api/auth/sign-in (email)\n * - /_auth/sign-out → /api/auth/sign-out\n *\n * Notes:\n * - Uses cookie-based sessions by default (credentials: \"include\").\n * - For programmatic access, use Better-Auth API keys (arch_* prefix) via x-api-key header.\n * - Better-Auth supports username, OAuth, magic link, and more.\n */\n\nimport axios, { type AxiosInstance } from \"axios\";\n\nexport type AuthUser = {\n id: string;\n email: string;\n emailVerified: boolean;\n name?: string;\n image?: string;\n createdAt?: Date;\n updatedAt?: Date;\n role?: string;\n banned?: boolean;\n};\n\nexport type AuthSession = {\n token: string;\n expiresAt: Date;\n userId: string;\n ipAddress?: string;\n userAgent?: string;\n};\n\nexport type AuthState = {\n user: AuthUser | null;\n session: AuthSession | null;\n isAuthenticated: boolean;\n};\n\nexport type SignUpInput = {\n email: string;\n password: string;\n name?: string;\n username?: string;\n};\n\nexport type SignInInput = {\n email?: string;\n username?: string;\n password: string;\n};\n\nexport type ArchlastAuthClientOptions = {\n /**\n * Base URL for the Archlast server.\n * Example: \"http://localhost:4000\"\n *\n * If omitted, it will default to:\n * - window.location.origin in the browser\n * - \"\" in non-browser contexts\n */\n baseUrl?: string;\n\n /**\n * App ID for session isolation (e.g. \"web\", \"admin\").\n * When set, adds x-archlast-app-id header.\n */\n appId?: string;\n\n /**\n * Better-Auth API key for authentication.\n * When provided, uses x-api-key header instead of cookies.\n */\n apiKey?: string;\n};\n\nfunction resolveBaseUrl(explicit?: string): string {\n if (explicit && explicit.trim()) return explicit.replace(/\\/+$/, \"\");\n if (typeof window !== \"undefined\" && window.location?.origin) return window.location.origin;\n return \"\";\n}\n\nexport class ArchlastAuthClient {\n private readonly baseUrl: string;\n private readonly axios: AxiosInstance;\n private readonly appId?: string;\n private readonly apiKey?: string;\n\n constructor(options: ArchlastAuthClientOptions = {}) {\n this.baseUrl = resolveBaseUrl(options.baseUrl);\n this.appId = options.appId;\n this.apiKey = options.apiKey;\n this.axios = axios.create({\n baseURL: this.baseUrl,\n withCredentials: !options.apiKey, // Only use cookies if no API key\n headers: {\n \"content-type\": \"application/json\",\n ...(this.appId ? { \"x-archlast-app-id\": this.appId } : {}),\n ...(options.apiKey ? { \"x-api-key\": options.apiKey } : {}),\n },\n });\n }\n\n /**\n * Get current authentication state\n * Uses Better-Auth's getSession endpoint\n */\n async getState(): Promise<AuthState> {\n try {\n const response = await this.axios.get<{\n user: AuthUser | null;\n session: AuthSession | null;\n }>(\"/api/auth/get-session\");\n\n const { user, session } = response.data;\n\n return {\n user,\n session,\n isAuthenticated: !!user,\n };\n } catch (error) {\n // Return unauthenticated state on error\n return {\n user: null,\n session: null,\n isAuthenticated: false,\n };\n }\n }\n\n /**\n * Sign up new user\n * Uses Better-Auth's email signUp endpoint\n */\n async signUp(input: SignUpInput): Promise<AuthState> {\n const response = await this.axios.post<{ user: AuthUser }>(\"/api/auth/sign-up/email\", {\n email: input.email,\n password: input.password,\n name: input.name,\n username: input.username,\n });\n\n return {\n user: response.data.user,\n session: null, // Session is managed via cookies\n isAuthenticated: !!response.data.user,\n };\n }\n\n /**\n * Sign in with email/username and password\n * Uses Better-Auth's credential sign-in endpoint\n */\n async signIn(input: SignInInput): Promise<AuthState> {\n // Support email or username sign-in\n if (!input.email && !input.username) {\n throw new Error(\"Either email or username is required\");\n }\n\n const response = await this.axios.post<{ user: AuthUser }>(\"/api/auth/sign-in/email\", {\n email: input.email,\n username: input.username,\n password: input.password,\n });\n\n return {\n user: response.data.user,\n session: null, // Session is managed via cookies\n isAuthenticated: !!response.data.user,\n };\n }\n\n /**\n * Sign out and revoke session\n * Uses Better-Auth's sign-out endpoint\n */\n async signOut(): Promise<{ success: boolean }> {\n const response = await this.axios.post<{ success: boolean }>(\n \"/api/auth/sign-out\",\n {},\n { withCredentials: true }\n );\n\n return response.data;\n }\n\n /**\n * Request password reset email\n * Uses Better-Auth's password reset flow\n */\n async requestPasswordReset(email: string, callbackURL?: string): Promise<{ success: boolean }> {\n const response = await this.axios.post<{ success: boolean }>(\"/api/auth/forgot-password\", {\n email,\n redirectTo: callbackURL,\n });\n\n return response.data;\n }\n\n /**\n * Reset password with token\n * Uses Better-Auth's reset password endpoint\n */\n async resetPassword(token: string, password: string): Promise<{ success: boolean }> {\n const response = await this.axios.post<{ success: boolean }>(\"/api/auth/reset-password\", {\n token,\n password,\n });\n\n return response.data;\n }\n\n /**\n * Verify email with token\n * Uses Better-Auth's email verification endpoint\n */\n async verifyEmail(token: string): Promise<{ success: boolean; user?: AuthUser }> {\n const response = await this.axios.post<{ success: boolean; user?: AuthUser }>(\"/api/auth/verify-email\", {\n token,\n });\n\n return response.data;\n }\n}\n\n/**\n * Default export for backward compatibility\n */\nexport default ArchlastAuthClient;\n"],"mappings":"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","names":["axios"]}
1
+ {"version":3,"sources":["../../src/auth/index.ts","../../src/auth/better-auth.ts"],"sourcesContent":["/**\r\n * Client-side auth API wrapper for Archlast.\r\n *\r\n * This now uses Better-Auth endpoints via the proxy:\r\n * - GET /api/auth/get-session\r\n * - POST /api/auth/sign-up\r\n * - POST /api/auth/sign-in\r\n * - POST /api/auth/sign-out\r\n *\r\n * Migration from legacy /_auth/* endpoints:\r\n * - /_auth/state → /api/auth/get-session\r\n * - /_auth/sign-up → /api/auth/sign-up (email)\r\n * - /_auth/sign-in → /api/auth/sign-in (email)\r\n * - /_auth/sign-out → /api/auth/sign-out\r\n *\r\n * Notes:\r\n * - Uses cookie-based sessions by default (credentials: \"include\").\r\n * - For programmatic access, use Better-Auth API keys (arch_* prefix) via x-api-key header.\r\n * - Better-Auth supports username, OAuth, magic link, and more.\r\n */\r\n\r\nimport axios, { type AxiosInstance } from \"axios\";\r\n\r\nexport type AuthUser = {\r\n id: string;\r\n email: string;\r\n emailVerified: boolean;\r\n name?: string;\r\n image?: string;\r\n createdAt?: Date;\r\n updatedAt?: Date;\r\n role?: string;\r\n banned?: boolean;\r\n};\r\n\r\nexport type AuthSession = {\r\n token: string;\r\n expiresAt: Date;\r\n userId: string;\r\n ipAddress?: string;\r\n userAgent?: string;\r\n};\r\n\r\nexport type AuthState = {\r\n user: AuthUser | null;\r\n session: AuthSession | null;\r\n isAuthenticated: boolean;\r\n};\r\n\r\nexport type SignUpInput = {\r\n email: string;\r\n password: string;\r\n name?: string;\r\n username?: string;\r\n};\r\n\r\nexport type SignInInput = {\r\n email?: string;\r\n username?: string;\r\n password: string;\r\n};\r\n\r\nexport type ArchlastAuthClientOptions = {\r\n /**\r\n * Base URL for the Archlast server.\r\n * Example: \"http://localhost:4000\"\r\n *\r\n * If omitted, it will default to:\r\n * - window.location.origin in the browser\r\n * - \"\" in non-browser contexts\r\n */\r\n baseUrl?: string;\r\n\r\n /**\r\n * App ID for session isolation (e.g. \"web\", \"admin\").\r\n * When set, adds x-archlast-app-id header.\r\n */\r\n appId?: string;\r\n\r\n /**\r\n * Better-Auth API key for authentication.\r\n * When provided, uses x-api-key header instead of cookies.\r\n */\r\n apiKey?: string;\r\n};\r\n\r\nfunction resolveBaseUrl(explicit?: string): string {\r\n if (explicit && explicit.trim()) return explicit.replace(/\\/+$/, \"\");\r\n if (typeof window !== \"undefined\" && window.location?.origin) return window.location.origin;\r\n return \"\";\r\n}\r\n\r\nexport class ArchlastAuthClient {\r\n private readonly baseUrl: string;\r\n private readonly axios: AxiosInstance;\r\n private readonly appId?: string;\r\n private readonly apiKey?: string;\r\n\r\n constructor(options: ArchlastAuthClientOptions = {}) {\r\n this.baseUrl = resolveBaseUrl(options.baseUrl);\r\n this.appId = options.appId;\r\n this.apiKey = options.apiKey;\r\n this.axios = axios.create({\r\n baseURL: this.baseUrl,\r\n withCredentials: !options.apiKey, // Only use cookies if no API key\r\n headers: {\r\n \"content-type\": \"application/json\",\r\n ...(this.appId ? { \"x-archlast-app-id\": this.appId } : {}),\r\n ...(options.apiKey ? { \"x-api-key\": options.apiKey } : {}),\r\n },\r\n });\r\n }\r\n\r\n /**\r\n * Get current authentication state\r\n * Uses Better-Auth's getSession endpoint\r\n */\r\n async getState(): Promise<AuthState> {\r\n try {\r\n const response = await this.axios.get<{\r\n user: AuthUser | null;\r\n session: AuthSession | null;\r\n }>(\"/api/auth/get-session\");\r\n\r\n const { user, session } = response.data;\r\n\r\n return {\r\n user,\r\n session,\r\n isAuthenticated: !!user,\r\n };\r\n } catch (error) {\r\n // Return unauthenticated state on error\r\n return {\r\n user: null,\r\n session: null,\r\n isAuthenticated: false,\r\n };\r\n }\r\n }\r\n\r\n /**\r\n * Sign up new user\r\n * Uses Better-Auth's email signUp endpoint\r\n */\r\n async signUp(input: SignUpInput): Promise<AuthState> {\r\n const response = await this.axios.post<{ user: AuthUser }>(\"/api/auth/sign-up/email\", {\r\n email: input.email,\r\n password: input.password,\r\n name: input.name,\r\n username: input.username,\r\n });\r\n\r\n return {\r\n user: response.data.user,\r\n session: null, // Session is managed via cookies\r\n isAuthenticated: !!response.data.user,\r\n };\r\n }\r\n\r\n /**\r\n * Sign in with email/username and password\r\n * Uses Better-Auth's credential sign-in endpoint\r\n */\r\n async signIn(input: SignInInput): Promise<AuthState> {\r\n // Support email or username sign-in\r\n if (!input.email && !input.username) {\r\n throw new Error(\"Either email or username is required\");\r\n }\r\n\r\n const response = await this.axios.post<{ user: AuthUser }>(\"/api/auth/sign-in/email\", {\r\n email: input.email,\r\n username: input.username,\r\n password: input.password,\r\n });\r\n\r\n return {\r\n user: response.data.user,\r\n session: null, // Session is managed via cookies\r\n isAuthenticated: !!response.data.user,\r\n };\r\n }\r\n\r\n /**\r\n * Sign out and revoke session\r\n * Uses Better-Auth's sign-out endpoint\r\n */\r\n async signOut(): Promise<{ success: boolean }> {\r\n const response = await this.axios.post<{ success: boolean }>(\r\n \"/api/auth/sign-out\",\r\n {},\r\n { withCredentials: true }\r\n );\r\n\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Request password reset email\r\n * Uses Better-Auth's password reset flow\r\n */\r\n async requestPasswordReset(email: string, callbackURL?: string): Promise<{ success: boolean }> {\r\n const response = await this.axios.post<{ success: boolean }>(\"/api/auth/forgot-password\", {\r\n email,\r\n redirectTo: callbackURL,\r\n });\r\n\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Reset password with token\r\n * Uses Better-Auth's reset password endpoint\r\n */\r\n async resetPassword(token: string, password: string): Promise<{ success: boolean }> {\r\n const response = await this.axios.post<{ success: boolean }>(\"/api/auth/reset-password\", {\r\n token,\r\n password,\r\n });\r\n\r\n return response.data;\r\n }\r\n\r\n /**\r\n * Verify email with token\r\n * Uses Better-Auth's email verification endpoint\r\n */\r\n async verifyEmail(token: string): Promise<{ success: boolean; user?: AuthUser }> {\r\n const response = await this.axios.post<{ success: boolean; user?: AuthUser }>(\"/api/auth/verify-email\", {\r\n token,\r\n });\r\n\r\n return response.data;\r\n }\r\n}\r\n\r\n/**\r\n * Default export for backward compatibility\r\n */\r\nexport default ArchlastAuthClient;\r\n\r\n/**\r\n * Better-Auth wrapper exports\r\n *\r\n * These provide direct access to Better-Auth client for advanced usage.\r\n * Most users should use the hooks from @archlast/client/react instead.\r\n *\r\n * @example\r\n * ```ts\r\n * import { betterAuthClient, useBetterAuthSession } from \"@archlast/client/auth\";\r\n *\r\n * // In React component\r\n * const { data: session } = useBetterAuthSession();\r\n *\r\n * // Anywhere\r\n * await betterAuthClient.signIn.email({ email, password });\r\n * ```\r\n */\r\nexport {\r\n authClient as betterAuthClient,\r\n useSession as useBetterAuthSession,\r\n createArchlastAuthClient,\r\n} from \"./better-auth.js\";\r\n\r\n","/**\n * Better-Auth wrapper for Archlast React client\n *\n * This module wraps Better-Auth and re-exports it under the @archlast/client namespace.\n * End-users should NOT need to install better-auth directly.\n */\n\nimport { createAuthClient } from \"better-auth/react\";\nimport { adminClient, organizationClient, usernameClient } from \"better-auth/client/plugins\";\n\n/**\n * Get the Better-Auth base URL from environment or construct from server URL\n */\nfunction getBetterAuthBaseURL(): string {\n // Try environment variable first\n const envURL = process.env.NEXT_PUBLIC_BETTER_AUTH_URL ||\n process.env.NEXT_PUBLIC_ARCHLAST_HTTP_URL ||\n process.env.ARCHLAST_HTTP_URL;\n\n if (envURL) {\n return `${envURL}/api/auth`;\n }\n\n // Fallback to localhost\n return \"http://localhost:4000/api/auth\";\n}\n\n/**\n * Create a Better-Auth client configured for Archlast\n *\n * This is the main export - users import this from @archlast/client/auth\n *\n * @example\n * ```ts\n * import { authClient, useSession } from \"@archlast/client/auth\";\n *\n * // In component\n * export default function Profile() {\n * const { data: session } = useSession();\n * return <div>Welcome {session?.user?.name}</div>;\n * }\n *\n * // Anywhere\n * await authClient.signIn.email({ email, password });\n * ```\n */\nexport const authClient = createAuthClient({\n baseURL: getBetterAuthBaseURL(),\n fetchOptions: {\n credentials: \"include\", // Required for cookies\n },\n plugins: [\n // Admin plugin - user management, roles, bans\n adminClient(),\n\n // Organization plugin - multi-tenancy\n organizationClient(),\n\n // Username plugin - username-based sign-in\n usernameClient(),\n ],\n});\n\n/**\n * Type-safe session hook\n *\n * @example\n * ```tsx\n * import { useSession } from \"@archlast/client/auth\";\n *\n * function MyComponent() {\n * const { data: session, isPending } = useSession();\n * if (isPending) return <div>Loading...</div>;\n * if (!session) return <div>Not authenticated</div>;\n * return <div>Hello {session.user.name}</div>;\n * }\n * ```\n */\nexport function useSession() {\n return authClient.useSession();\n}\n\n/**\n * Re-export Better-Auth types for convenience\n */\nexport type { Session, User } from \"better-auth\";\n\n/**\n * Re-export createAuthClient for advanced use cases\n *\n * Most users should use the default `authClient` export, but if you need\n * a custom configuration (e.g., different base URL), you can create a new client:\n *\n * @example\n * ```ts\n * import { createArchlastAuthClient } from \"@archlast/client/auth\";\n *\n * const customAuth = createArchlastAuthClient({\n * baseURL: \"https://api.example.com/api/auth\",\n * });\n * ```\n */\nexport function createArchlastAuthClient(options: {\n baseURL?: string;\n fetchOptions?: RequestInit;\n}) {\n return createAuthClient({\n baseURL: options.baseURL || getBetterAuthBaseURL(),\n fetchOptions: {\n credentials: \"include\",\n ...options.fetchOptions,\n },\n plugins: [\n adminClient(),\n organizationClient(),\n usernameClient(),\n ],\n });\n}\n\n/**\n * Default export for backward compatibility\n */\nexport default authClient;\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAqBA,mBAA0C;;;ACd1C,mBAAiC;AACjC,qBAAgE;AAKhE,SAAS,uBAA+B;AAEpC,QAAM,SAAS,QAAQ,IAAI,+BACZ,QAAQ,IAAI,iCACZ,QAAQ,IAAI;AAE3B,MAAI,QAAQ;AACR,WAAO,GAAG,MAAM;AAAA,EACpB;AAGA,SAAO;AACX;AAqBO,IAAM,iBAAa,+BAAiB;AAAA,EACvC,SAAS,qBAAqB;AAAA,EAC9B,cAAc;AAAA,IACV,aAAa;AAAA;AAAA,EACjB;AAAA,EACA,SAAS;AAAA;AAAA,QAEL,4BAAY;AAAA;AAAA,QAGZ,mCAAmB;AAAA;AAAA,QAGnB,+BAAe;AAAA,EACnB;AACJ,CAAC;AAiBM,SAAS,aAAa;AACzB,SAAO,WAAW,WAAW;AACjC;AAsBO,SAAS,yBAAyB,SAGtC;AACC,aAAO,+BAAiB;AAAA,IACpB,SAAS,QAAQ,WAAW,qBAAqB;AAAA,IACjD,cAAc;AAAA,MACV,aAAa;AAAA,MACb,GAAG,QAAQ;AAAA,IACf;AAAA,IACA,SAAS;AAAA,UACL,4BAAY;AAAA,UACZ,mCAAmB;AAAA,UACnB,+BAAe;AAAA,IACnB;AAAA,EACJ,CAAC;AACL;;;ADhCA,SAAS,eAAe,UAA2B;AAC/C,MAAI,YAAY,SAAS,KAAK,EAAG,QAAO,SAAS,QAAQ,QAAQ,EAAE;AACnE,MAAI,OAAO,WAAW,eAAe,OAAO,UAAU,OAAQ,QAAO,OAAO,SAAS;AACrF,SAAO;AACX;AAEO,IAAM,qBAAN,MAAyB;AAAA,EAM5B,YAAY,UAAqC,CAAC,GAAG;AALrD,wBAAiB;AACjB,wBAAiB;AACjB,wBAAiB;AACjB,wBAAiB;AAGb,SAAK,UAAU,eAAe,QAAQ,OAAO;AAC7C,SAAK,QAAQ,QAAQ;AACrB,SAAK,SAAS,QAAQ;AACtB,SAAK,QAAQ,aAAAA,QAAM,OAAO;AAAA,MACtB,SAAS,KAAK;AAAA,MACd,iBAAiB,CAAC,QAAQ;AAAA;AAAA,MAC1B,SAAS;AAAA,QACL,gBAAgB;AAAA,QAChB,GAAI,KAAK,QAAQ,EAAE,qBAAqB,KAAK,MAAM,IAAI,CAAC;AAAA,QACxD,GAAI,QAAQ,SAAS,EAAE,aAAa,QAAQ,OAAO,IAAI,CAAC;AAAA,MAC5D;AAAA,IACJ,CAAC;AAAA,EACL;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,WAA+B;AACjC,QAAI;AACA,YAAM,WAAW,MAAM,KAAK,MAAM,IAG/B,uBAAuB;AAE1B,YAAM,EAAE,MAAM,QAAQ,IAAI,SAAS;AAEnC,aAAO;AAAA,QACH;AAAA,QACA;AAAA,QACA,iBAAiB,CAAC,CAAC;AAAA,MACvB;AAAA,IACJ,SAAS,OAAO;AAEZ,aAAO;AAAA,QACH,MAAM;AAAA,QACN,SAAS;AAAA,QACT,iBAAiB;AAAA,MACrB;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAO,OAAwC;AACjD,UAAM,WAAW,MAAM,KAAK,MAAM,KAAyB,2BAA2B;AAAA,MAClF,OAAO,MAAM;AAAA,MACb,UAAU,MAAM;AAAA,MAChB,MAAM,MAAM;AAAA,MACZ,UAAU,MAAM;AAAA,IACpB,CAAC;AAED,WAAO;AAAA,MACH,MAAM,SAAS,KAAK;AAAA,MACpB,SAAS;AAAA;AAAA,MACT,iBAAiB,CAAC,CAAC,SAAS,KAAK;AAAA,IACrC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,OAAO,OAAwC;AAEjD,QAAI,CAAC,MAAM,SAAS,CAAC,MAAM,UAAU;AACjC,YAAM,IAAI,MAAM,sCAAsC;AAAA,IAC1D;AAEA,UAAM,WAAW,MAAM,KAAK,MAAM,KAAyB,2BAA2B;AAAA,MAClF,OAAO,MAAM;AAAA,MACb,UAAU,MAAM;AAAA,MAChB,UAAU,MAAM;AAAA,IACpB,CAAC;AAED,WAAO;AAAA,MACH,MAAM,SAAS,KAAK;AAAA,MACpB,SAAS;AAAA;AAAA,MACT,iBAAiB,CAAC,CAAC,SAAS,KAAK;AAAA,IACrC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,UAAyC;AAC3C,UAAM,WAAW,MAAM,KAAK,MAAM;AAAA,MAC9B;AAAA,MACA,CAAC;AAAA,MACD,EAAE,iBAAiB,KAAK;AAAA,IAC5B;AAEA,WAAO,SAAS;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,qBAAqB,OAAe,aAAqD;AAC3F,UAAM,WAAW,MAAM,KAAK,MAAM,KAA2B,6BAA6B;AAAA,MACtF;AAAA,MACA,YAAY;AAAA,IAChB,CAAC;AAED,WAAO,SAAS;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,cAAc,OAAe,UAAiD;AAChF,UAAM,WAAW,MAAM,KAAK,MAAM,KAA2B,4BAA4B;AAAA,MACrF;AAAA,MACA;AAAA,IACJ,CAAC;AAED,WAAO,SAAS;AAAA,EACpB;AAAA;AAAA;AAAA;AAAA;AAAA,EAMA,MAAM,YAAY,OAA+D;AAC7E,UAAM,WAAW,MAAM,KAAK,MAAM,KAA4C,0BAA0B;AAAA,MACpG;AAAA,IACJ,CAAC;AAED,WAAO,SAAS;AAAA,EACpB;AACJ;AAKA,IAAO,eAAQ;","names":["axios"]}