@yusufstar07/sdk-client 1.0.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/README.md +262 -0
- package/dist/client.d.ts +76 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +339 -0
- package/dist/index.d.ts +9 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +7 -0
- package/dist/types.d.ts +69 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +4 -0
- package/dist/utils.d.ts +37 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +96 -0
- package/package.json +38 -0
package/README.md
ADDED
|
@@ -0,0 +1,262 @@
|
|
|
1
|
+
# Multi-Auth Platform SDK Client
|
|
2
|
+
|
|
3
|
+
A fetch-based authentication client for Next.js and React applications. Supports both client-side and server-side rendering (SSR).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @yusufstar07/sdk-client
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Usage
|
|
12
|
+
|
|
13
|
+
### Basic Setup
|
|
14
|
+
|
|
15
|
+
```typescript
|
|
16
|
+
import { createSDKClient } from "@yusufstar07/sdk-client";
|
|
17
|
+
|
|
18
|
+
const sdk = createSDKClient({
|
|
19
|
+
apiKey: process.env.NEXT_PUBLIC_API_KEY!, // Your API key
|
|
20
|
+
baseUrl: process.env.NEXT_PUBLIC_API_URL!, // Your API base URL (e.g., http://localhost:3001)
|
|
21
|
+
});
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
### Client-Side Usage (React)
|
|
25
|
+
|
|
26
|
+
```typescript
|
|
27
|
+
"use client";
|
|
28
|
+
|
|
29
|
+
import { createSDKClient } from "@yusufstar07/sdk-client";
|
|
30
|
+
import { useState } from "react";
|
|
31
|
+
|
|
32
|
+
const sdk = createSDKClient({
|
|
33
|
+
apiKey: process.env.NEXT_PUBLIC_API_KEY!,
|
|
34
|
+
baseUrl: process.env.NEXT_PUBLIC_API_URL!,
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
export default function LoginPage() {
|
|
38
|
+
const [email, setEmail] = useState("");
|
|
39
|
+
const [password, setPassword] = useState("");
|
|
40
|
+
|
|
41
|
+
const handleLogin = async () => {
|
|
42
|
+
try {
|
|
43
|
+
const response = await sdk.login({ email, password });
|
|
44
|
+
console.log("Logged in:", response.user);
|
|
45
|
+
} catch (error) {
|
|
46
|
+
console.error("Login failed:", error);
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
return (
|
|
51
|
+
<form onSubmit={(e) => { e.preventDefault(); handleLogin(); }}>
|
|
52
|
+
<input
|
|
53
|
+
type="email"
|
|
54
|
+
value={email}
|
|
55
|
+
onChange={(e) => setEmail(e.target.value)}
|
|
56
|
+
placeholder="Email"
|
|
57
|
+
/>
|
|
58
|
+
<input
|
|
59
|
+
type="password"
|
|
60
|
+
value={password}
|
|
61
|
+
onChange={(e) => setPassword(e.target.value)}
|
|
62
|
+
placeholder="Password"
|
|
63
|
+
/>
|
|
64
|
+
<button type="submit">Login</button>
|
|
65
|
+
</form>
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
```
|
|
69
|
+
|
|
70
|
+
### Server-Side Usage (Next.js App Router)
|
|
71
|
+
|
|
72
|
+
```typescript
|
|
73
|
+
// app/api/user/route.ts
|
|
74
|
+
import { createSDKClient, getAccessTokenFromCookieString } from "@yusufstar07/sdk-client";
|
|
75
|
+
import { cookies } from "next/headers";
|
|
76
|
+
import { NextResponse } from "next/server";
|
|
77
|
+
|
|
78
|
+
const sdk = createSDKClient({
|
|
79
|
+
apiKey: process.env.API_KEY!,
|
|
80
|
+
baseUrl: process.env.API_URL!,
|
|
81
|
+
fetch: fetch, // Use native fetch for SSR
|
|
82
|
+
});
|
|
83
|
+
|
|
84
|
+
export async function GET() {
|
|
85
|
+
try {
|
|
86
|
+
const cookieStore = await cookies();
|
|
87
|
+
const cookieString = cookieStore.toString();
|
|
88
|
+
const accessToken = getAccessTokenFromCookieString(cookieString);
|
|
89
|
+
|
|
90
|
+
if (!accessToken) {
|
|
91
|
+
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
const response = await sdk.me(accessToken);
|
|
95
|
+
return NextResponse.json(response);
|
|
96
|
+
} catch (error: any) {
|
|
97
|
+
return NextResponse.json(
|
|
98
|
+
{ error: error.error || "Failed to get user" },
|
|
99
|
+
{ status: error.status || 500 }
|
|
100
|
+
);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
```
|
|
104
|
+
|
|
105
|
+
### Server Component Usage
|
|
106
|
+
|
|
107
|
+
```typescript
|
|
108
|
+
// app/profile/page.tsx
|
|
109
|
+
import { createSDKClient, getAccessTokenFromCookieString } from "@yusufstar07/sdk-client";
|
|
110
|
+
import { cookies } from "next/headers";
|
|
111
|
+
import { redirect } from "next/navigation";
|
|
112
|
+
|
|
113
|
+
const sdk = createSDKClient({
|
|
114
|
+
apiKey: process.env.API_KEY!,
|
|
115
|
+
baseUrl: process.env.API_URL!,
|
|
116
|
+
fetch: fetch,
|
|
117
|
+
});
|
|
118
|
+
|
|
119
|
+
export default async function ProfilePage() {
|
|
120
|
+
const cookieStore = await cookies();
|
|
121
|
+
const cookieString = cookieStore.toString();
|
|
122
|
+
const accessToken = getAccessTokenFromCookieString(cookieString);
|
|
123
|
+
|
|
124
|
+
if (!accessToken) {
|
|
125
|
+
redirect("/login");
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
try {
|
|
129
|
+
const { user } = await sdk.me(accessToken);
|
|
130
|
+
return (
|
|
131
|
+
<div>
|
|
132
|
+
<h1>Profile</h1>
|
|
133
|
+
<p>Email: {user.email}</p>
|
|
134
|
+
<p>Name: {user.name}</p>
|
|
135
|
+
</div>
|
|
136
|
+
);
|
|
137
|
+
} catch (error) {
|
|
138
|
+
redirect("/login");
|
|
139
|
+
}
|
|
140
|
+
}
|
|
141
|
+
```
|
|
142
|
+
|
|
143
|
+
## API Methods
|
|
144
|
+
|
|
145
|
+
### `register(data: RegisterRequest): Promise<RegisterResponse>`
|
|
146
|
+
|
|
147
|
+
Register a new user.
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
const response = await sdk.register({
|
|
151
|
+
email: "user@example.com",
|
|
152
|
+
password: "password123",
|
|
153
|
+
name: "John Doe", // Optional
|
|
154
|
+
});
|
|
155
|
+
```
|
|
156
|
+
|
|
157
|
+
### `login(data: LoginRequest): Promise<LoginResponse>`
|
|
158
|
+
|
|
159
|
+
Login user and store tokens in cookies.
|
|
160
|
+
|
|
161
|
+
```typescript
|
|
162
|
+
const response = await sdk.login({
|
|
163
|
+
email: "user@example.com",
|
|
164
|
+
password: "password123",
|
|
165
|
+
});
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
### `refresh(refreshToken?: string): Promise<RefreshResponse>`
|
|
169
|
+
|
|
170
|
+
Refresh access token using refresh token.
|
|
171
|
+
|
|
172
|
+
```typescript
|
|
173
|
+
const response = await sdk.refresh(); // Uses cookie if available
|
|
174
|
+
// or
|
|
175
|
+
const response = await sdk.refresh(customRefreshToken);
|
|
176
|
+
```
|
|
177
|
+
|
|
178
|
+
### `logout(accessToken?: string): Promise<LogoutResponse>`
|
|
179
|
+
|
|
180
|
+
Logout user and clear tokens.
|
|
181
|
+
|
|
182
|
+
```typescript
|
|
183
|
+
await sdk.logout(); // Uses cookie if available
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
### `me(accessToken?: string): Promise<MeResponse>`
|
|
187
|
+
|
|
188
|
+
Get current authenticated user.
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
const response = await sdk.me(); // Uses cookie if available
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
### `isAuthenticated(): boolean`
|
|
195
|
+
|
|
196
|
+
Check if user is authenticated (has access token in cookie).
|
|
197
|
+
|
|
198
|
+
```typescript
|
|
199
|
+
if (sdk.isAuthenticated()) {
|
|
200
|
+
// User is logged in
|
|
201
|
+
}
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
### `getToken(): string | null`
|
|
205
|
+
|
|
206
|
+
Get current access token from cookie.
|
|
207
|
+
|
|
208
|
+
```typescript
|
|
209
|
+
const token = sdk.getToken();
|
|
210
|
+
```
|
|
211
|
+
|
|
212
|
+
## Configuration Options
|
|
213
|
+
|
|
214
|
+
```typescript
|
|
215
|
+
interface SDKClientConfig {
|
|
216
|
+
apiKey: string; // Required: Your API key
|
|
217
|
+
baseUrl: string; // Required: API base URL
|
|
218
|
+
cookieDomain?: string; // Optional: Cookie domain
|
|
219
|
+
useCookies?: boolean; // Optional: Use cookies for token storage (default: true)
|
|
220
|
+
fetch?: typeof fetch; // Optional: Custom fetch implementation (required for SSR)
|
|
221
|
+
}
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
## Error Handling
|
|
225
|
+
|
|
226
|
+
All methods throw `SDKError` objects:
|
|
227
|
+
|
|
228
|
+
```typescript
|
|
229
|
+
try {
|
|
230
|
+
await sdk.login({ email, password });
|
|
231
|
+
} catch (error: SDKError) {
|
|
232
|
+
console.error(error.error); // Error message
|
|
233
|
+
console.error(error.status); // HTTP status code
|
|
234
|
+
}
|
|
235
|
+
```
|
|
236
|
+
|
|
237
|
+
## SSR Compatibility
|
|
238
|
+
|
|
239
|
+
The SDK is fully compatible with Next.js App Router and Server Components:
|
|
240
|
+
|
|
241
|
+
1. **Server Components**: Use `getAccessTokenFromCookieString()` to get tokens from cookies
|
|
242
|
+
2. **API Routes**: Use `cookies()` from `next/headers` to get cookie string
|
|
243
|
+
3. **Custom Fetch**: Always provide `fetch` implementation for SSR
|
|
244
|
+
|
|
245
|
+
## TypeScript Support
|
|
246
|
+
|
|
247
|
+
Full TypeScript support with exported types:
|
|
248
|
+
|
|
249
|
+
```typescript
|
|
250
|
+
import type {
|
|
251
|
+
SDKUser,
|
|
252
|
+
RegisterRequest,
|
|
253
|
+
LoginRequest,
|
|
254
|
+
SDKError,
|
|
255
|
+
SDKClientConfig,
|
|
256
|
+
} from "@yusufstar07/sdk-client";
|
|
257
|
+
```
|
|
258
|
+
|
|
259
|
+
## License
|
|
260
|
+
|
|
261
|
+
UNLICENSED - Private package
|
|
262
|
+
|
package/dist/client.d.ts
ADDED
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
import type { SDKClientConfig, RegisterRequest, RegisterResponse, LoginRequest, LoginResponse, RefreshResponse, LogoutResponse, MeResponse } from "./types";
|
|
2
|
+
export declare class SDKClient {
|
|
3
|
+
private config;
|
|
4
|
+
private fetchImpl;
|
|
5
|
+
private refreshPromise;
|
|
6
|
+
constructor(config: SDKClientConfig);
|
|
7
|
+
/**
|
|
8
|
+
* Make authenticated request with automatic token refresh and retry
|
|
9
|
+
*/
|
|
10
|
+
private request;
|
|
11
|
+
/**
|
|
12
|
+
* Internal refresh token method (prevents concurrent refresh requests)
|
|
13
|
+
*/
|
|
14
|
+
private refreshTokenInternal;
|
|
15
|
+
/**
|
|
16
|
+
* Perform actual refresh token request
|
|
17
|
+
*/
|
|
18
|
+
private performRefresh;
|
|
19
|
+
/**
|
|
20
|
+
* Get access token from cookie or return null
|
|
21
|
+
*/
|
|
22
|
+
private getAccessToken;
|
|
23
|
+
/**
|
|
24
|
+
* Get refresh token from cookie or return null
|
|
25
|
+
*/
|
|
26
|
+
private getRefreshToken;
|
|
27
|
+
/**
|
|
28
|
+
* Store tokens in cookies
|
|
29
|
+
*/
|
|
30
|
+
private storeTokens;
|
|
31
|
+
/**
|
|
32
|
+
* Clear tokens from cookies
|
|
33
|
+
*/
|
|
34
|
+
private clearTokens;
|
|
35
|
+
/**
|
|
36
|
+
* Register a new user
|
|
37
|
+
*/
|
|
38
|
+
register(data: RegisterRequest): Promise<RegisterResponse>;
|
|
39
|
+
/**
|
|
40
|
+
* Login user
|
|
41
|
+
*/
|
|
42
|
+
login(data: LoginRequest): Promise<LoginResponse>;
|
|
43
|
+
/**
|
|
44
|
+
* Refresh access token (manual refresh)
|
|
45
|
+
*/
|
|
46
|
+
refresh(refreshToken?: string): Promise<RefreshResponse>;
|
|
47
|
+
/**
|
|
48
|
+
* Logout user
|
|
49
|
+
*/
|
|
50
|
+
logout(accessToken?: string): Promise<LogoutResponse>;
|
|
51
|
+
/**
|
|
52
|
+
* Get current user
|
|
53
|
+
*/
|
|
54
|
+
me(accessToken?: string): Promise<MeResponse>;
|
|
55
|
+
/**
|
|
56
|
+
* Get access token (for manual token management)
|
|
57
|
+
*/
|
|
58
|
+
getToken(): string | null;
|
|
59
|
+
/**
|
|
60
|
+
* Check if user is authenticated
|
|
61
|
+
*/
|
|
62
|
+
isAuthenticated(): boolean;
|
|
63
|
+
}
|
|
64
|
+
/**
|
|
65
|
+
* Create SDK client instance
|
|
66
|
+
*/
|
|
67
|
+
export declare function createSDKClient(config: SDKClientConfig): SDKClient;
|
|
68
|
+
/**
|
|
69
|
+
* Get access token from cookie string (for SSR)
|
|
70
|
+
*/
|
|
71
|
+
export declare function getAccessTokenFromCookieString(cookieString?: string): string | null;
|
|
72
|
+
/**
|
|
73
|
+
* Get refresh token from cookie string (for SSR)
|
|
74
|
+
*/
|
|
75
|
+
export declare function getRefreshTokenFromCookieString(cookieString?: string): string | null;
|
|
76
|
+
//# sourceMappingURL=client.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACR,eAAe,EACf,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,eAAe,EACf,cAAc,EACd,UAAU,EAEb,MAAM,SAAS,CAAC;AAGjB,qBAAa,SAAS;IAClB,OAAO,CAAC,MAAM,CAKZ;IACF,OAAO,CAAC,SAAS,CAAe;IAChC,OAAO,CAAC,cAAc,CAAyC;gBAEnD,MAAM,EAAE,eAAe;IAyBnC;;OAEG;YACW,OAAO;IA4DrB;;OAEG;YACW,oBAAoB;IAkBlC;;OAEG;YACW,cAAc;IAmD5B;;OAEG;IACH,OAAO,CAAC,cAAc;IAOtB;;OAEG;IACH,OAAO,CAAC,eAAe;IAOvB;;OAEG;IACH,OAAO,CAAC,WAAW;IAwBnB;;OAEG;IACH,OAAO,CAAC,WAAW;IAgBnB;;OAEG;IACG,QAAQ,CAAC,IAAI,EAAE,eAAe,GAAG,OAAO,CAAC,gBAAgB,CAAC;IAOhE;;OAEG;IACG,KAAK,CAAC,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,aAAa,CAAC;IAcvD;;OAEG;IACG,OAAO,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAmD9D;;OAEG;IACG,MAAM,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,cAAc,CAAC;IAmC3D;;OAEG;IACG,EAAE,CAAC,WAAW,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,CAAC;IAsBnD;;OAEG;IACH,QAAQ,IAAI,MAAM,GAAG,IAAI;IAIzB;;OAEG;IACH,eAAe,IAAI,OAAO;CAG7B;AAED;;GAEG;AACH,wBAAgB,eAAe,CAAC,MAAM,EAAE,eAAe,GAAG,SAAS,CAElE;AAED;;GAEG;AACH,wBAAgB,8BAA8B,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEnF;AAED;;GAEG;AACH,wBAAgB,+BAA+B,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAEpF"}
|
package/dist/client.js
ADDED
|
@@ -0,0 +1,339 @@
|
|
|
1
|
+
import { getCookie, setCookie, deleteCookie, getAccessTokenFromCookies, getRefreshTokenFromCookies } from "./utils";
|
|
2
|
+
export class SDKClient {
|
|
3
|
+
constructor(config) {
|
|
4
|
+
this.refreshPromise = null; // Prevent concurrent refresh requests
|
|
5
|
+
if (!config.apiKey) {
|
|
6
|
+
throw new Error("API key is required");
|
|
7
|
+
}
|
|
8
|
+
if (!config.baseUrl) {
|
|
9
|
+
throw new Error("Base URL is required");
|
|
10
|
+
}
|
|
11
|
+
const fetchImpl = config.fetch ?? (typeof fetch !== "undefined" ? fetch : undefined);
|
|
12
|
+
if (!fetchImpl) {
|
|
13
|
+
throw new Error("Fetch is not available. Provide a custom fetch implementation for SSR.");
|
|
14
|
+
}
|
|
15
|
+
this.config = {
|
|
16
|
+
apiKey: config.apiKey,
|
|
17
|
+
baseUrl: config.baseUrl.replace(/\/$/, ""), // Remove trailing slash
|
|
18
|
+
cookieDomain: config.cookieDomain,
|
|
19
|
+
useCookies: config.useCookies ?? true,
|
|
20
|
+
};
|
|
21
|
+
this.fetchImpl = fetchImpl;
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* Make authenticated request with automatic token refresh and retry
|
|
25
|
+
*/
|
|
26
|
+
async request(endpoint, options = {}, useAuth = false, retryCount = 0) {
|
|
27
|
+
const url = `${this.config.baseUrl}${endpoint}`;
|
|
28
|
+
const headers = {
|
|
29
|
+
"Content-Type": "application/json",
|
|
30
|
+
"x-api-key": this.config.apiKey,
|
|
31
|
+
...options.headers,
|
|
32
|
+
};
|
|
33
|
+
// Add access token if needed
|
|
34
|
+
if (useAuth) {
|
|
35
|
+
const accessToken = this.getAccessToken();
|
|
36
|
+
if (accessToken) {
|
|
37
|
+
headers["Authorization"] = `Bearer ${accessToken}`;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
const response = await this.fetchImpl(url, {
|
|
41
|
+
...options,
|
|
42
|
+
headers,
|
|
43
|
+
credentials: "include", // Include cookies for SSR
|
|
44
|
+
});
|
|
45
|
+
const data = await response.json();
|
|
46
|
+
// Handle 401 Unauthorized - try to refresh token and retry
|
|
47
|
+
if (response.status === 401 && useAuth && retryCount === 0) {
|
|
48
|
+
try {
|
|
49
|
+
// Attempt to refresh token
|
|
50
|
+
await this.refreshTokenInternal();
|
|
51
|
+
// Retry the original request with new token
|
|
52
|
+
return this.request(endpoint, options, useAuth, retryCount + 1);
|
|
53
|
+
}
|
|
54
|
+
catch (refreshError) {
|
|
55
|
+
// Refresh failed - clear tokens and throw original 401 error
|
|
56
|
+
this.clearTokens();
|
|
57
|
+
const error = {
|
|
58
|
+
error: data.error || "Unauthorized",
|
|
59
|
+
status: 401,
|
|
60
|
+
};
|
|
61
|
+
throw error;
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
if (!response.ok) {
|
|
65
|
+
const error = {
|
|
66
|
+
error: data.error || "Request failed",
|
|
67
|
+
status: response.status,
|
|
68
|
+
};
|
|
69
|
+
throw error;
|
|
70
|
+
}
|
|
71
|
+
return data;
|
|
72
|
+
}
|
|
73
|
+
/**
|
|
74
|
+
* Internal refresh token method (prevents concurrent refresh requests)
|
|
75
|
+
*/
|
|
76
|
+
async refreshTokenInternal() {
|
|
77
|
+
// If there's already a refresh in progress, wait for it
|
|
78
|
+
if (this.refreshPromise) {
|
|
79
|
+
return this.refreshPromise;
|
|
80
|
+
}
|
|
81
|
+
// Start new refresh
|
|
82
|
+
this.refreshPromise = this.performRefresh();
|
|
83
|
+
try {
|
|
84
|
+
const result = await this.refreshPromise;
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
finally {
|
|
88
|
+
// Clear the promise after completion
|
|
89
|
+
this.refreshPromise = null;
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Perform actual refresh token request
|
|
94
|
+
*/
|
|
95
|
+
async performRefresh() {
|
|
96
|
+
const refreshToken = this.getRefreshToken();
|
|
97
|
+
if (!refreshToken) {
|
|
98
|
+
throw {
|
|
99
|
+
error: "Refresh token is required",
|
|
100
|
+
status: 401,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
const url = `${this.config.baseUrl}/api/sdk/refresh`;
|
|
104
|
+
const response = await this.fetchImpl(url, {
|
|
105
|
+
method: "POST",
|
|
106
|
+
headers: {
|
|
107
|
+
"Content-Type": "application/json",
|
|
108
|
+
"x-api-key": this.config.apiKey,
|
|
109
|
+
Authorization: `Bearer ${refreshToken}`,
|
|
110
|
+
},
|
|
111
|
+
credentials: "include",
|
|
112
|
+
});
|
|
113
|
+
const data = await response.json();
|
|
114
|
+
if (!response.ok) {
|
|
115
|
+
// Refresh failed - clear tokens on backend
|
|
116
|
+
this.clearTokens();
|
|
117
|
+
const error = {
|
|
118
|
+
error: data.error || "Failed to refresh token",
|
|
119
|
+
status: response.status,
|
|
120
|
+
};
|
|
121
|
+
throw error;
|
|
122
|
+
}
|
|
123
|
+
const refreshResponse = data;
|
|
124
|
+
// Update access token in cookies
|
|
125
|
+
if (this.config.useCookies && refreshResponse.accessToken) {
|
|
126
|
+
setCookie("sdk_access_token", refreshResponse.accessToken, {
|
|
127
|
+
domain: this.config.cookieDomain,
|
|
128
|
+
maxAge: refreshResponse.expiresIn || 15 * 60, // Use expiresIn from response or default 15 minutes
|
|
129
|
+
path: "/",
|
|
130
|
+
secure: true,
|
|
131
|
+
sameSite: "lax",
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
return refreshResponse;
|
|
135
|
+
}
|
|
136
|
+
/**
|
|
137
|
+
* Get access token from cookie or return null
|
|
138
|
+
*/
|
|
139
|
+
getAccessToken() {
|
|
140
|
+
if (this.config.useCookies && typeof document !== "undefined") {
|
|
141
|
+
return getCookie("sdk_access_token");
|
|
142
|
+
}
|
|
143
|
+
return null;
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* Get refresh token from cookie or return null
|
|
147
|
+
*/
|
|
148
|
+
getRefreshToken() {
|
|
149
|
+
if (this.config.useCookies && typeof document !== "undefined") {
|
|
150
|
+
return getCookie("sdk_refresh_token");
|
|
151
|
+
}
|
|
152
|
+
return null;
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* Store tokens in cookies
|
|
156
|
+
*/
|
|
157
|
+
storeTokens(accessToken, refreshToken) {
|
|
158
|
+
if (!this.config.useCookies || typeof document === "undefined") {
|
|
159
|
+
return;
|
|
160
|
+
}
|
|
161
|
+
// Access token expires in 15 minutes
|
|
162
|
+
setCookie("sdk_access_token", accessToken, {
|
|
163
|
+
domain: this.config.cookieDomain,
|
|
164
|
+
maxAge: 15 * 60, // 15 minutes
|
|
165
|
+
path: "/",
|
|
166
|
+
secure: true,
|
|
167
|
+
sameSite: "lax",
|
|
168
|
+
});
|
|
169
|
+
// Refresh token expires in 7 days
|
|
170
|
+
setCookie("sdk_refresh_token", refreshToken, {
|
|
171
|
+
domain: this.config.cookieDomain,
|
|
172
|
+
maxAge: 7 * 24 * 60 * 60, // 7 days
|
|
173
|
+
path: "/",
|
|
174
|
+
secure: true,
|
|
175
|
+
sameSite: "lax",
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Clear tokens from cookies
|
|
180
|
+
*/
|
|
181
|
+
clearTokens() {
|
|
182
|
+
if (typeof document === "undefined") {
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
deleteCookie("sdk_access_token", {
|
|
186
|
+
domain: this.config.cookieDomain,
|
|
187
|
+
path: "/",
|
|
188
|
+
});
|
|
189
|
+
deleteCookie("sdk_refresh_token", {
|
|
190
|
+
domain: this.config.cookieDomain,
|
|
191
|
+
path: "/",
|
|
192
|
+
});
|
|
193
|
+
}
|
|
194
|
+
/**
|
|
195
|
+
* Register a new user
|
|
196
|
+
*/
|
|
197
|
+
async register(data) {
|
|
198
|
+
return this.request("/api/sdk/register", {
|
|
199
|
+
method: "POST",
|
|
200
|
+
body: JSON.stringify(data),
|
|
201
|
+
});
|
|
202
|
+
}
|
|
203
|
+
/**
|
|
204
|
+
* Login user
|
|
205
|
+
*/
|
|
206
|
+
async login(data) {
|
|
207
|
+
const response = await this.request("/api/sdk/login", {
|
|
208
|
+
method: "POST",
|
|
209
|
+
body: JSON.stringify(data),
|
|
210
|
+
});
|
|
211
|
+
// Store tokens in cookies if cookies are enabled
|
|
212
|
+
if (this.config.useCookies && response.accessToken && response.refreshToken) {
|
|
213
|
+
this.storeTokens(response.accessToken, response.refreshToken);
|
|
214
|
+
}
|
|
215
|
+
return response;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Refresh access token (manual refresh)
|
|
219
|
+
*/
|
|
220
|
+
async refresh(refreshToken) {
|
|
221
|
+
const token = refreshToken || this.getRefreshToken();
|
|
222
|
+
if (!token) {
|
|
223
|
+
throw {
|
|
224
|
+
error: "Refresh token is required",
|
|
225
|
+
status: 401,
|
|
226
|
+
};
|
|
227
|
+
}
|
|
228
|
+
const url = `${this.config.baseUrl}/api/sdk/refresh`;
|
|
229
|
+
const response = await this.fetchImpl(url, {
|
|
230
|
+
method: "POST",
|
|
231
|
+
headers: {
|
|
232
|
+
"Content-Type": "application/json",
|
|
233
|
+
"x-api-key": this.config.apiKey,
|
|
234
|
+
Authorization: `Bearer ${token}`,
|
|
235
|
+
},
|
|
236
|
+
credentials: "include",
|
|
237
|
+
});
|
|
238
|
+
const data = await response.json();
|
|
239
|
+
if (!response.ok) {
|
|
240
|
+
// Refresh failed - clear tokens
|
|
241
|
+
this.clearTokens();
|
|
242
|
+
const error = {
|
|
243
|
+
error: data.error || "Failed to refresh token",
|
|
244
|
+
status: response.status,
|
|
245
|
+
};
|
|
246
|
+
throw error;
|
|
247
|
+
}
|
|
248
|
+
const refreshResponse = data;
|
|
249
|
+
// Update access token in cookies
|
|
250
|
+
if (this.config.useCookies && refreshResponse.accessToken) {
|
|
251
|
+
setCookie("sdk_access_token", refreshResponse.accessToken, {
|
|
252
|
+
domain: this.config.cookieDomain,
|
|
253
|
+
maxAge: refreshResponse.expiresIn || 15 * 60,
|
|
254
|
+
path: "/",
|
|
255
|
+
secure: true,
|
|
256
|
+
sameSite: "lax",
|
|
257
|
+
});
|
|
258
|
+
}
|
|
259
|
+
return refreshResponse;
|
|
260
|
+
}
|
|
261
|
+
/**
|
|
262
|
+
* Logout user
|
|
263
|
+
*/
|
|
264
|
+
async logout(accessToken) {
|
|
265
|
+
const token = accessToken || this.getAccessToken();
|
|
266
|
+
if (!token) {
|
|
267
|
+
// Clear cookies anyway
|
|
268
|
+
this.clearTokens();
|
|
269
|
+
return {
|
|
270
|
+
success: true,
|
|
271
|
+
message: "Logged out successfully",
|
|
272
|
+
};
|
|
273
|
+
}
|
|
274
|
+
try {
|
|
275
|
+
const response = await this.request("/api/sdk/logout", {
|
|
276
|
+
method: "POST",
|
|
277
|
+
headers: {
|
|
278
|
+
Authorization: `Bearer ${token}`,
|
|
279
|
+
},
|
|
280
|
+
}, true);
|
|
281
|
+
// Clear tokens from cookies
|
|
282
|
+
this.clearTokens();
|
|
283
|
+
return response;
|
|
284
|
+
}
|
|
285
|
+
catch (error) {
|
|
286
|
+
// Clear cookies even if request fails
|
|
287
|
+
this.clearTokens();
|
|
288
|
+
throw error;
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/**
|
|
292
|
+
* Get current user
|
|
293
|
+
*/
|
|
294
|
+
async me(accessToken) {
|
|
295
|
+
const token = accessToken || this.getAccessToken();
|
|
296
|
+
if (!token) {
|
|
297
|
+
throw {
|
|
298
|
+
error: "Access token is required",
|
|
299
|
+
status: 401,
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
return this.request("/api/sdk/me", {
|
|
303
|
+
method: "GET",
|
|
304
|
+
headers: {
|
|
305
|
+
Authorization: `Bearer ${token}`,
|
|
306
|
+
},
|
|
307
|
+
}, true);
|
|
308
|
+
}
|
|
309
|
+
/**
|
|
310
|
+
* Get access token (for manual token management)
|
|
311
|
+
*/
|
|
312
|
+
getToken() {
|
|
313
|
+
return this.getAccessToken();
|
|
314
|
+
}
|
|
315
|
+
/**
|
|
316
|
+
* Check if user is authenticated
|
|
317
|
+
*/
|
|
318
|
+
isAuthenticated() {
|
|
319
|
+
return this.getAccessToken() !== null;
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
/**
|
|
323
|
+
* Create SDK client instance
|
|
324
|
+
*/
|
|
325
|
+
export function createSDKClient(config) {
|
|
326
|
+
return new SDKClient(config);
|
|
327
|
+
}
|
|
328
|
+
/**
|
|
329
|
+
* Get access token from cookie string (for SSR)
|
|
330
|
+
*/
|
|
331
|
+
export function getAccessTokenFromCookieString(cookieString) {
|
|
332
|
+
return getAccessTokenFromCookies(cookieString);
|
|
333
|
+
}
|
|
334
|
+
/**
|
|
335
|
+
* Get refresh token from cookie string (for SSR)
|
|
336
|
+
*/
|
|
337
|
+
export function getRefreshTokenFromCookieString(cookieString) {
|
|
338
|
+
return getRefreshTokenFromCookies(cookieString);
|
|
339
|
+
}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Auth Platform SDK Client
|
|
3
|
+
*
|
|
4
|
+
* A fetch-based authentication client for Next.js and React applications.
|
|
5
|
+
* Supports both client-side and server-side rendering (SSR).
|
|
6
|
+
*/
|
|
7
|
+
export { SDKClient, createSDKClient, getAccessTokenFromCookieString, getRefreshTokenFromCookieString } from "./client";
|
|
8
|
+
export type { SDKUser, RegisterRequest, RegisterResponse, LoginRequest, LoginResponse, RefreshResponse, LogoutResponse, MeResponse, SDKError, SDKClientConfig, } from "./types";
|
|
9
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,OAAO,EAAE,SAAS,EAAE,eAAe,EAAE,8BAA8B,EAAE,+BAA+B,EAAE,MAAM,UAAU,CAAC;AACvH,YAAY,EACR,OAAO,EACP,eAAe,EACf,gBAAgB,EAChB,YAAY,EACZ,aAAa,EACb,eAAe,EACf,cAAc,EACd,UAAU,EACV,QAAQ,EACR,eAAe,GAClB,MAAM,SAAS,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-Auth Platform SDK Client
|
|
3
|
+
*
|
|
4
|
+
* A fetch-based authentication client for Next.js and React applications.
|
|
5
|
+
* Supports both client-side and server-side rendering (SSR).
|
|
6
|
+
*/
|
|
7
|
+
export { SDKClient, createSDKClient, getAccessTokenFromCookieString, getRefreshTokenFromCookieString } from "./client";
|
package/dist/types.d.ts
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* SDK Client Types
|
|
3
|
+
*/
|
|
4
|
+
export interface SDKUser {
|
|
5
|
+
id: string;
|
|
6
|
+
email: string;
|
|
7
|
+
name?: string;
|
|
8
|
+
organizationId: string;
|
|
9
|
+
projectId: string;
|
|
10
|
+
isEmailVerified: boolean;
|
|
11
|
+
lastLoginAt?: string;
|
|
12
|
+
createdAt: string;
|
|
13
|
+
}
|
|
14
|
+
export interface RegisterRequest {
|
|
15
|
+
email: string;
|
|
16
|
+
password: string;
|
|
17
|
+
name?: string;
|
|
18
|
+
}
|
|
19
|
+
export interface RegisterResponse {
|
|
20
|
+
success: boolean;
|
|
21
|
+
user: SDKUser;
|
|
22
|
+
}
|
|
23
|
+
export interface LoginRequest {
|
|
24
|
+
email: string;
|
|
25
|
+
password: string;
|
|
26
|
+
}
|
|
27
|
+
export interface LoginResponse {
|
|
28
|
+
success: boolean;
|
|
29
|
+
user: SDKUser;
|
|
30
|
+
accessToken: string;
|
|
31
|
+
refreshToken: string;
|
|
32
|
+
expiresIn: number;
|
|
33
|
+
}
|
|
34
|
+
export interface RefreshResponse {
|
|
35
|
+
success: boolean;
|
|
36
|
+
accessToken: string;
|
|
37
|
+
refreshToken: string;
|
|
38
|
+
expiresIn: number;
|
|
39
|
+
}
|
|
40
|
+
export interface LogoutResponse {
|
|
41
|
+
success: boolean;
|
|
42
|
+
message: string;
|
|
43
|
+
}
|
|
44
|
+
export interface MeResponse {
|
|
45
|
+
user: SDKUser;
|
|
46
|
+
}
|
|
47
|
+
export interface SDKError {
|
|
48
|
+
error: string;
|
|
49
|
+
status?: number;
|
|
50
|
+
}
|
|
51
|
+
export interface SDKClientConfig {
|
|
52
|
+
apiKey: string;
|
|
53
|
+
baseUrl: string;
|
|
54
|
+
/**
|
|
55
|
+
* Cookie domain for storing tokens (for SSR)
|
|
56
|
+
* Default: undefined (current domain)
|
|
57
|
+
*/
|
|
58
|
+
cookieDomain?: string;
|
|
59
|
+
/**
|
|
60
|
+
* Whether to use cookies for token storage (SSR mode)
|
|
61
|
+
* Default: true
|
|
62
|
+
*/
|
|
63
|
+
useCookies?: boolean;
|
|
64
|
+
/**
|
|
65
|
+
* Custom fetch implementation (for SSR compatibility)
|
|
66
|
+
*/
|
|
67
|
+
fetch?: typeof fetch;
|
|
68
|
+
}
|
|
69
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH,MAAM,WAAW,OAAO;IACpB,EAAE,EAAE,MAAM,CAAC;IACX,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,cAAc,EAAE,MAAM,CAAC;IACvB,SAAS,EAAE,MAAM,CAAC;IAClB,eAAe,EAAE,OAAO,CAAC;IACzB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,IAAI,CAAC,EAAE,MAAM,CAAC;CACjB;AAED,MAAM,WAAW,gBAAgB;IAC7B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,YAAY;IACzB,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,aAAa;IAC1B,OAAO,EAAE,OAAO,CAAC;IACjB,IAAI,EAAE,OAAO,CAAC;IACd,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,eAAe;IAC5B,OAAO,EAAE,OAAO,CAAC;IACjB,WAAW,EAAE,MAAM,CAAC;IACpB,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,cAAc;IAC3B,OAAO,EAAE,OAAO,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,UAAU;IACvB,IAAI,EAAE,OAAO,CAAC;CACjB;AAED,MAAM,WAAW,QAAQ;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,MAAM,WAAW,eAAe;IAC5B,MAAM,EAAE,MAAM,CAAC;IACf,OAAO,EAAE,MAAM,CAAC;IAChB;;;OAGG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB;;;OAGG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB;;OAEG;IACH,KAAK,CAAC,EAAE,OAAO,KAAK,CAAC;CACxB"}
|
package/dist/types.js
ADDED
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for SDK Client
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Get cookie value by name
|
|
6
|
+
*/
|
|
7
|
+
export declare function getCookie(name: string): string | null;
|
|
8
|
+
/**
|
|
9
|
+
* Set cookie
|
|
10
|
+
*/
|
|
11
|
+
export declare function setCookie(name: string, value: string, options?: {
|
|
12
|
+
domain?: string;
|
|
13
|
+
maxAge?: number;
|
|
14
|
+
path?: string;
|
|
15
|
+
secure?: boolean;
|
|
16
|
+
sameSite?: "strict" | "lax" | "none";
|
|
17
|
+
}): void;
|
|
18
|
+
/**
|
|
19
|
+
* Delete cookie
|
|
20
|
+
*/
|
|
21
|
+
export declare function deleteCookie(name: string, options?: {
|
|
22
|
+
domain?: string;
|
|
23
|
+
path?: string;
|
|
24
|
+
}): void;
|
|
25
|
+
/**
|
|
26
|
+
* Get cookies from cookie string (for SSR)
|
|
27
|
+
*/
|
|
28
|
+
export declare function parseCookies(cookieString?: string): Record<string, string>;
|
|
29
|
+
/**
|
|
30
|
+
* Get access token from cookies (for SSR)
|
|
31
|
+
*/
|
|
32
|
+
export declare function getAccessTokenFromCookies(cookieString?: string): string | null;
|
|
33
|
+
/**
|
|
34
|
+
* Get refresh token from cookies (for SSR)
|
|
35
|
+
*/
|
|
36
|
+
export declare function getRefreshTokenFromCookies(cookieString?: string): string | null;
|
|
37
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAAA;;GAEG;AAEH;;GAEG;AACH,wBAAgB,SAAS,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAarD;AAED;;GAEG;AACH,wBAAgB,SAAS,CACrB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,EACb,OAAO,GAAE;IACL,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,MAAM,CAAC,EAAE,OAAO,CAAC;IACjB,QAAQ,CAAC,EAAE,QAAQ,GAAG,KAAK,GAAG,MAAM,CAAC;CACnC,GACP,IAAI,CAgCN;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAA;CAAO,GAAG,IAAI,CAkBjG;AAED;;GAEG;AACH,wBAAgB,YAAY,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAY1E;AAED;;GAEG;AACH,wBAAgB,yBAAyB,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG9E;AAED;;GAEG;AACH,wBAAgB,0BAA0B,CAAC,YAAY,CAAC,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAG/E"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,96 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Utility functions for SDK Client
|
|
3
|
+
*/
|
|
4
|
+
/**
|
|
5
|
+
* Get cookie value by name
|
|
6
|
+
*/
|
|
7
|
+
export function getCookie(name) {
|
|
8
|
+
if (typeof document === "undefined") {
|
|
9
|
+
return null;
|
|
10
|
+
}
|
|
11
|
+
const value = `; ${document.cookie}`;
|
|
12
|
+
const parts = value.split(`; ${name}=`);
|
|
13
|
+
if (parts.length === 2) {
|
|
14
|
+
return parts.pop()?.split(";").shift() || null;
|
|
15
|
+
}
|
|
16
|
+
return null;
|
|
17
|
+
}
|
|
18
|
+
/**
|
|
19
|
+
* Set cookie
|
|
20
|
+
*/
|
|
21
|
+
export function setCookie(name, value, options = {}) {
|
|
22
|
+
if (typeof document === "undefined") {
|
|
23
|
+
return;
|
|
24
|
+
}
|
|
25
|
+
let cookieString = `${name}=${encodeURIComponent(value)}`;
|
|
26
|
+
if (options.maxAge) {
|
|
27
|
+
cookieString += `; max-age=${options.maxAge}`;
|
|
28
|
+
}
|
|
29
|
+
if (options.path) {
|
|
30
|
+
cookieString += `; path=${options.path}`;
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
cookieString += `; path=/`;
|
|
34
|
+
}
|
|
35
|
+
if (options.domain) {
|
|
36
|
+
cookieString += `; domain=${options.domain}`;
|
|
37
|
+
}
|
|
38
|
+
if (options.secure) {
|
|
39
|
+
cookieString += `; secure`;
|
|
40
|
+
}
|
|
41
|
+
if (options.sameSite) {
|
|
42
|
+
cookieString += `; samesite=${options.sameSite}`;
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
cookieString += `; samesite=lax`;
|
|
46
|
+
}
|
|
47
|
+
document.cookie = cookieString;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Delete cookie
|
|
51
|
+
*/
|
|
52
|
+
export function deleteCookie(name, options = {}) {
|
|
53
|
+
if (typeof document === "undefined") {
|
|
54
|
+
return;
|
|
55
|
+
}
|
|
56
|
+
let cookieString = `${name}=; expires=Thu, 01 Jan 1970 00:00:00 UTC`;
|
|
57
|
+
if (options.path) {
|
|
58
|
+
cookieString += `; path=${options.path}`;
|
|
59
|
+
}
|
|
60
|
+
else {
|
|
61
|
+
cookieString += `; path=/`;
|
|
62
|
+
}
|
|
63
|
+
if (options.domain) {
|
|
64
|
+
cookieString += `; domain=${options.domain}`;
|
|
65
|
+
}
|
|
66
|
+
document.cookie = cookieString;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Get cookies from cookie string (for SSR)
|
|
70
|
+
*/
|
|
71
|
+
export function parseCookies(cookieString) {
|
|
72
|
+
if (!cookieString) {
|
|
73
|
+
return {};
|
|
74
|
+
}
|
|
75
|
+
return cookieString.split(";").reduce((acc, cookie) => {
|
|
76
|
+
const [key, value] = cookie.trim().split("=");
|
|
77
|
+
if (key && value) {
|
|
78
|
+
acc[key] = decodeURIComponent(value);
|
|
79
|
+
}
|
|
80
|
+
return acc;
|
|
81
|
+
}, {});
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Get access token from cookies (for SSR)
|
|
85
|
+
*/
|
|
86
|
+
export function getAccessTokenFromCookies(cookieString) {
|
|
87
|
+
const cookies = parseCookies(cookieString);
|
|
88
|
+
return cookies["sdk_access_token"] || null;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Get refresh token from cookies (for SSR)
|
|
92
|
+
*/
|
|
93
|
+
export function getRefreshTokenFromCookies(cookieString) {
|
|
94
|
+
const cookies = parseCookies(cookieString);
|
|
95
|
+
return cookies["sdk_refresh_token"] || null;
|
|
96
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@yusufstar07/sdk-client",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "SDK client for Multi-Auth Platform authentication",
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
7
|
+
"scripts": {
|
|
8
|
+
"build": "tsc",
|
|
9
|
+
"prepublishOnly": "npm run build"
|
|
10
|
+
},
|
|
11
|
+
"keywords": [
|
|
12
|
+
"authentication",
|
|
13
|
+
"sdk",
|
|
14
|
+
"auth",
|
|
15
|
+
"multi-auth"
|
|
16
|
+
],
|
|
17
|
+
"author": "",
|
|
18
|
+
"license": "UNLICENSED",
|
|
19
|
+
"publishConfig": {
|
|
20
|
+
"access": "public"
|
|
21
|
+
},
|
|
22
|
+
"files": [
|
|
23
|
+
"dist",
|
|
24
|
+
"README.md"
|
|
25
|
+
],
|
|
26
|
+
"devDependencies": {
|
|
27
|
+
"@types/node": "^20.0.0",
|
|
28
|
+
"typescript": "^5.0.0"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"react": ">=18.0.0"
|
|
32
|
+
},
|
|
33
|
+
"peerDependenciesMeta": {
|
|
34
|
+
"react": {
|
|
35
|
+
"optional": true
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|