@authaz/next 0.0.1 → 1.0.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/dist/index.js CHANGED
@@ -1,30 +1,442 @@
1
- import { authaz, validateToken } from "@authaz/sdk";
2
- import { cookies } from "next/headers";
1
+ import { AuthazError, COOKIE_NAMES, createAuthazClient, fetchUserinfo, getSecureCookieOptions, isOk, mapUserinfoToUser, timingSafeCompare } from "@authaz/sdk";
2
+ import { NextResponse } from "next/server";
3
3
 
4
4
  //#region src/index.tsx
5
- const authazNext = (config, args) => {
6
- const sdk = authaz(config);
7
- const isDebug = args?.debug || false;
8
- const getUserSession = (args$1) => {
9
- const accessTokenCookie = args$1?.cookies?.accessToken || "accessToken";
10
- return async () => {
11
- try {
12
- const accessToken = (await cookies()).get(accessTokenCookie)?.value;
13
- if (!accessToken || !validateToken(accessToken)) return null;
14
- const response = await sdk.getMe(accessToken);
15
- if (response.status !== "success") return null;
16
- return response.user;
17
- } catch (error) {
18
- if (isDebug) console.error("[authaz-sdk] Error on get user session", error);
19
- return null;
20
- }
21
- };
5
+ /**
6
+ * Lazy load next/headers at runtime to avoid MODULE_NOT_FOUND on Vercel/serverless
7
+ * when the package is resolved from a different node_modules context (e.g. pnpm).
8
+ */
9
+ const getCookieStore = async () => {
10
+ const { cookies } = await import("next/headers");
11
+ return cookies();
12
+ };
13
+ const isRequestHttps = (request) => {
14
+ if (request.headers.get("x-forwarded-proto") === "https") return true;
15
+ return new URL(request.url).protocol === "https:";
16
+ };
17
+ const toNextCookieOptions = (options) => {
18
+ return {
19
+ httpOnly: options.httpOnly,
20
+ secure: options.secure,
21
+ sameSite: options.sameSite,
22
+ path: options.path,
23
+ maxAge: options.maxAge
24
+ };
25
+ };
26
+ /**
27
+ * Creates the Authaz Next.js authentication handler.
28
+ *
29
+ * This creates a route handler that manages the complete OAuth flow:
30
+ * - GET /api/auth/login - Redirects to Universal Login
31
+ * - POST /api/auth/callback - Handles OAuth callback (receives code via form POST)
32
+ * - POST /api/auth/logout - Clears session and redirects to logout (POST-only for CSRF protection)
33
+ * - GET /api/auth/me - Returns current user info (requires valid session)
34
+ * - POST /api/auth/refresh - Refreshes the access token
35
+ *
36
+ * IMPORTANT: The OAuth callback from the identity provider arrives as GET.
37
+ * You need a callback page that POSTs to /api/auth/callback:
38
+ *
39
+ * ```tsx
40
+ * // app/auth/callback/page.tsx
41
+ * 'use client';
42
+ * import { useEffect } from 'react';
43
+ * import { useSearchParams } from 'next/navigation';
44
+ *
45
+ * export default function CallbackPage() {
46
+ * const searchParams = useSearchParams();
47
+ *
48
+ * useEffect(() => {
49
+ * const form = document.createElement('form');
50
+ * form.method = 'POST';
51
+ * form.action = '/api/auth/callback';
52
+ *
53
+ * const code = searchParams.get('code');
54
+ * const state = searchParams.get('state');
55
+ * const error = searchParams.get('error');
56
+ *
57
+ * ['code', 'state', 'error', 'error_description'].forEach(param => {
58
+ * const value = searchParams.get(param);
59
+ * if (value) {
60
+ * const input = document.createElement('input');
61
+ * input.type = 'hidden';
62
+ * input.name = param;
63
+ * input.value = value;
64
+ * form.appendChild(input);
65
+ * }
66
+ * });
67
+ *
68
+ * document.body.appendChild(form);
69
+ * form.submit();
70
+ * }, [searchParams]);
71
+ *
72
+ * return <div>Completing login...</div>;
73
+ * }
74
+ * ```
75
+ *
76
+ * @example
77
+ * ```typescript
78
+ * // app/api/auth/[...authaz]/route.ts
79
+ * import { createAuthazHandler } from '@authaz/next';
80
+ *
81
+ * export const { GET, POST } = createAuthazHandler({
82
+ * clientId: process.env.AUTHAZ_CLIENT_ID!,
83
+ * clientSecret: process.env.AUTHAZ_CLIENT_SECRET!,
84
+ * tenantId: process.env.AUTHAZ_TENANT_ID!,
85
+ * organizationId: process.env.AUTHAZ_ORGANIZATION_ID!,
86
+ * });
87
+ * ```
88
+ */
89
+ const createAuthazHandler = (config) => {
90
+ let _client = null;
91
+ const getClient = () => {
92
+ if (!_client) _client = createAuthazClient(config);
93
+ return _client;
94
+ };
95
+ const afterLoginUrl = config.afterLoginUrl || "/";
96
+ const afterLogoutUrl = config.afterLogoutUrl || "/";
97
+ const authazDomain = config.authazDomain || "https://authaz.com";
98
+ const fixedRedirectUri = config.redirectUri;
99
+ const isDebug = config.debug || false;
100
+ const apiKey = config.apiKey || config.clientSecret;
101
+ const log = (message, data) => {
102
+ if (isDebug) console.log(`[authaz-next] ${message}`, data || "");
103
+ };
104
+ const logError = (message, error) => {
105
+ if (isDebug) console.error(`[authaz-next] ${message}`, error || "");
106
+ };
107
+ const getAction = (request) => {
108
+ const url = new URL(request.url);
109
+ const pathParts = url.pathname.split("/");
110
+ const action = pathParts[pathParts.length - 1];
111
+ log(`getAction: pathname=${url.pathname}, action=${action}`);
112
+ return action;
113
+ };
114
+ const getBaseUrl = (request) => {
115
+ const url = new URL(request.url);
116
+ return `${url.protocol}//${url.host}`;
117
+ };
118
+ const handleLogin = async (request) => {
119
+ log("Starting login flow");
120
+ let redirectUri;
121
+ if (fixedRedirectUri) {
122
+ redirectUri = fixedRedirectUri;
123
+ log("Using fixed redirectUri from config", { redirectUri });
124
+ } else {
125
+ const baseUrl = getBaseUrl(request);
126
+ const callbackPage = new URL(request.url).searchParams.get("callbackUrl") || "/auth/callback";
127
+ redirectUri = callbackPage.startsWith("http") ? callbackPage : `${baseUrl}${callbackPage}`;
128
+ log("Using dynamic redirectUri", { redirectUri });
129
+ }
130
+ const result = await getClient().auth.getLoginUrl(redirectUri);
131
+ if (!isOk(result)) {
132
+ logError("Failed to generate login URL", result.error);
133
+ return NextResponse.json({ error: "Failed to generate login URL" }, { status: 500 });
134
+ }
135
+ const loginResult = result.data;
136
+ const response = NextResponse.redirect(loginResult.url);
137
+ const oauthCookieOptions = toNextCookieOptions(getSecureCookieOptions(600, isRequestHttps(request)));
138
+ response.cookies.set(COOKIE_NAMES.CODE_VERIFIER, loginResult.codeVerifier, oauthCookieOptions);
139
+ response.cookies.set(COOKIE_NAMES.STATE, loginResult.state, oauthCookieOptions);
140
+ response.cookies.set(COOKIE_NAMES.NONCE, loginResult.nonce, oauthCookieOptions);
141
+ log("Redirecting to Universal Login", { url: loginResult.url });
142
+ return response;
143
+ };
144
+ const handleCallback = async (request) => {
145
+ log("Handling OAuth callback");
146
+ const formData = await request.formData();
147
+ const code = formData.get("code");
148
+ const state = formData.get("state");
149
+ const error = formData.get("error");
150
+ const errorDescription = formData.get("error_description");
151
+ log("Callback params", {
152
+ code: code?.substring(0, 10),
153
+ state: state?.substring(0, 10),
154
+ error
155
+ });
156
+ const baseUrl = getBaseUrl(request);
157
+ if (error) {
158
+ logError("OAuth error", {
159
+ error,
160
+ errorDescription
161
+ });
162
+ return NextResponse.redirect(`${baseUrl}${afterLoginUrl}?error=${encodeURIComponent(error)}`);
163
+ }
164
+ if (!code) {
165
+ logError("Missing authorization code");
166
+ return NextResponse.redirect(`${baseUrl}${afterLoginUrl}?error=missing_code`);
167
+ }
168
+ const cookieStore = await getCookieStore();
169
+ const codeVerifier = cookieStore.get(COOKIE_NAMES.CODE_VERIFIER)?.value;
170
+ const storedState = cookieStore.get(COOKIE_NAMES.STATE)?.value;
171
+ log("All cookies", cookieStore.getAll().map((c) => c.name));
172
+ if (!codeVerifier) {
173
+ logError("Missing code verifier cookie");
174
+ return NextResponse.redirect(`${baseUrl}${afterLoginUrl}?error=missing_verifier`);
175
+ }
176
+ if (!storedState || !state || !timingSafeCompare(state, storedState)) {
177
+ logError("State mismatch", {
178
+ received: state,
179
+ stored: storedState
180
+ });
181
+ return NextResponse.redirect(`${baseUrl}${afterLoginUrl}?error=state_mismatch`);
182
+ }
183
+ const redirectUri = fixedRedirectUri || `${baseUrl}/auth/redirect`;
184
+ log("Using redirectUri for token exchange", { redirectUri });
185
+ const result = await getClient().auth.exchangeCode(code, codeVerifier, redirectUri);
186
+ if (!isOk(result)) {
187
+ logError("Token exchange failed", result.error);
188
+ return NextResponse.redirect(`${baseUrl}${afterLoginUrl}?error=token_exchange_failed`);
189
+ }
190
+ const tokens = result.data;
191
+ log("Token exchange successful");
192
+ const redirectUrl = `${baseUrl}${afterLoginUrl}`;
193
+ const response = NextResponse.redirect(redirectUrl, { status: 303 });
194
+ const isHttps = isRequestHttps(request);
195
+ const accessTokenOptions = toNextCookieOptions(getSecureCookieOptions(tokens.expiresIn || 3600, isHttps));
196
+ const refreshTokenOptions = toNextCookieOptions(getSecureCookieOptions(3600 * 24 * 30, isHttps));
197
+ log("Setting cookies", {
198
+ isHttps,
199
+ secure: accessTokenOptions.secure,
200
+ sameSite: accessTokenOptions.sameSite,
201
+ accessTokenLength: tokens.accessToken?.length,
202
+ redirectUrl: `${baseUrl}${afterLoginUrl}`
203
+ });
204
+ response.cookies.set(COOKIE_NAMES.ACCESS_TOKEN, tokens.accessToken, accessTokenOptions);
205
+ if (tokens.refreshToken) response.cookies.set(COOKIE_NAMES.REFRESH_TOKEN, tokens.refreshToken, refreshTokenOptions);
206
+ response.cookies.delete(COOKIE_NAMES.CODE_VERIFIER);
207
+ response.cookies.delete(COOKIE_NAMES.STATE);
208
+ response.cookies.delete(COOKIE_NAMES.NONCE);
209
+ return response;
210
+ };
211
+ const handleLogout = async (request) => {
212
+ log("Handling logout");
213
+ const baseUrl = getBaseUrl(request);
214
+ const postLogoutRedirectUri = `${baseUrl}${afterLogoutUrl}`;
215
+ const result = getClient().auth.getLogoutUrl(postLogoutRedirectUri);
216
+ if (!isOk(result)) {
217
+ logError("Failed to generate logout URL", result.error);
218
+ const response$1 = NextResponse.redirect(`${baseUrl}${afterLogoutUrl}`);
219
+ response$1.cookies.delete(COOKIE_NAMES.ACCESS_TOKEN);
220
+ response$1.cookies.delete(COOKIE_NAMES.REFRESH_TOKEN);
221
+ return response$1;
222
+ }
223
+ const response = NextResponse.redirect(result.data);
224
+ response.cookies.delete(COOKIE_NAMES.ACCESS_TOKEN);
225
+ response.cookies.delete(COOKIE_NAMES.REFRESH_TOKEN);
226
+ response.cookies.delete(COOKIE_NAMES.CODE_VERIFIER);
227
+ response.cookies.delete(COOKIE_NAMES.STATE);
228
+ response.cookies.delete(COOKIE_NAMES.NONCE);
229
+ return response;
230
+ };
231
+ const handleMe = async () => {
232
+ log("Getting current user");
233
+ const accessToken = (await getCookieStore()).get(COOKIE_NAMES.ACCESS_TOKEN)?.value;
234
+ if (!accessToken) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
235
+ const userinfo = await fetchUserinfo(authazDomain, accessToken, apiKey);
236
+ if (!userinfo) {
237
+ logError("Failed to fetch userinfo");
238
+ return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
239
+ }
240
+ const user = mapUserinfoToUser(userinfo);
241
+ return NextResponse.json({
242
+ authenticated: true,
243
+ user
244
+ });
245
+ };
246
+ const handleRefresh = async (request) => {
247
+ log("Handling token refresh");
248
+ const refreshToken = (await getCookieStore()).get(COOKIE_NAMES.REFRESH_TOKEN)?.value;
249
+ if (!refreshToken) return NextResponse.json({ error: "No refresh token" }, { status: 401 });
250
+ const result = await getClient().auth.refreshTokens(refreshToken);
251
+ if (!isOk(result)) {
252
+ logError("Token refresh failed", result.error);
253
+ const response$1 = NextResponse.json({ error: "Refresh failed" }, { status: 401 });
254
+ response$1.cookies.delete(COOKIE_NAMES.ACCESS_TOKEN);
255
+ response$1.cookies.delete(COOKIE_NAMES.REFRESH_TOKEN);
256
+ return response$1;
257
+ }
258
+ const tokens = result.data;
259
+ log("Token refresh successful");
260
+ const response = NextResponse.json({ success: true });
261
+ const isHttps = isRequestHttps(request);
262
+ const accessTokenOptions = toNextCookieOptions(getSecureCookieOptions(tokens.expiresIn || 3600, isHttps));
263
+ const refreshTokenOptions = toNextCookieOptions(getSecureCookieOptions(3600 * 24 * 30, isHttps));
264
+ response.cookies.set(COOKIE_NAMES.ACCESS_TOKEN, tokens.accessToken, accessTokenOptions);
265
+ if (tokens.refreshToken) response.cookies.set(COOKIE_NAMES.REFRESH_TOKEN, tokens.refreshToken, refreshTokenOptions);
266
+ return response;
267
+ };
268
+ const GET = async (request) => {
269
+ const action = getAction(request);
270
+ switch (action) {
271
+ case "login": return handleLogin(request);
272
+ case "me": return handleMe();
273
+ case "callback":
274
+ case "logout":
275
+ case "refresh": return NextResponse.json({ error: "Method not allowed. Use POST." }, { status: 405 });
276
+ default: return NextResponse.json({ error: `Unknown action: ${action}` }, { status: 404 });
277
+ }
278
+ };
279
+ const POST = async (request) => {
280
+ const action = getAction(request);
281
+ switch (action) {
282
+ case "callback": return handleCallback(request);
283
+ case "logout": return handleLogout(request);
284
+ case "refresh": return handleRefresh(request);
285
+ case "login":
286
+ case "me": return NextResponse.json({ error: "Method not allowed. Use GET." }, { status: 405 });
287
+ default: return NextResponse.json({ error: `Unknown action: ${action}` }, { status: 404 });
288
+ }
22
289
  };
23
290
  return {
24
- getUserSession: getUserSession(args),
25
- sdk
291
+ GET,
292
+ POST
293
+ };
294
+ };
295
+ /**
296
+ * Gets the current access token from cookies.
297
+ */
298
+ const getAccessToken = async () => {
299
+ return (await getCookieStore()).get(COOKIE_NAMES.ACCESS_TOKEN)?.value || null;
300
+ };
301
+ /**
302
+ * Gets the current refresh token from cookies.
303
+ */
304
+ const getRefreshToken = async () => {
305
+ return (await getCookieStore()).get(COOKIE_NAMES.REFRESH_TOKEN)?.value || null;
306
+ };
307
+ /**
308
+ * Checks if the user is authenticated (has an access token).
309
+ */
310
+ const isAuthenticated = async () => {
311
+ return await getAccessToken() !== null;
312
+ };
313
+ /**
314
+ * Creates helper functions that require the authazDomain for API calls.
315
+ */
316
+ const createAuthazHelpers = (config) => {
317
+ const authazDomain = config.authazDomain || "https://authaz.com";
318
+ const apiKey = config.apiKey || config.clientSecret;
319
+ const getUser = async () => {
320
+ const accessToken = (await getCookieStore()).get(COOKIE_NAMES.ACCESS_TOKEN)?.value;
321
+ if (!accessToken) return null;
322
+ const userinfo = await fetchUserinfo(authazDomain, accessToken, apiKey);
323
+ if (!userinfo) return null;
324
+ return mapUserinfoToUser(userinfo);
325
+ };
326
+ return { getUser };
327
+ };
328
+ /**
329
+ * Creates middleware config for protecting routes in Next.js middleware.ts
330
+ *
331
+ * @example
332
+ * ```typescript
333
+ * // middleware.ts
334
+ * import { createAuthMiddleware } from '@authaz/next';
335
+ *
336
+ * export const middleware = createAuthMiddleware({
337
+ * publicPaths: ['/', '/login', '/api/auth'],
338
+ * loginPath: '/api/auth/login',
339
+ * });
340
+ *
341
+ * export const config = {
342
+ * matcher: ['/((?!_next/static|_next/image|favicon.ico).*)'],
343
+ * };
344
+ * ```
345
+ */
346
+ const createAuthMiddleware = (options) => {
347
+ const publicPaths = options.publicPaths || [];
348
+ const loginPath = options.loginPath || "/api/auth/login";
349
+ const isPublicPath = (pathname) => {
350
+ return publicPaths.some((pattern) => {
351
+ if (pattern.endsWith("*")) return pathname.startsWith(pattern.slice(0, -1));
352
+ return pathname === pattern;
353
+ });
354
+ };
355
+ return async (request) => {
356
+ const pathname = request.nextUrl.pathname;
357
+ if (isPublicPath(pathname)) return NextResponse.next();
358
+ if (!request.cookies.get(COOKIE_NAMES.ACCESS_TOKEN)?.value) {
359
+ const loginUrl = new URL(loginPath, request.url);
360
+ loginUrl.searchParams.set("returnTo", pathname);
361
+ return NextResponse.redirect(loginUrl);
362
+ }
363
+ return NextResponse.next();
364
+ };
365
+ };
366
+ /**
367
+ * Wrapper for API route handlers that require authentication.
368
+ * Returns 401 if not authenticated.
369
+ *
370
+ * @example
371
+ * ```typescript
372
+ * // app/api/protected/route.ts
373
+ * import { withAuth } from '@authaz/next';
374
+ *
375
+ * export const GET = withAuth(async (request) => {
376
+ * // User is authenticated
377
+ * return Response.json({ message: 'Protected data' });
378
+ * });
379
+ * ```
380
+ */
381
+ const withAuth = (handler) => {
382
+ return async (request) => {
383
+ if (!request.cookies.get(COOKIE_NAMES.ACCESS_TOKEN)?.value) return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
384
+ return handler(request);
385
+ };
386
+ };
387
+ /**
388
+ * Server Component helper that throws redirect if not authenticated.
389
+ * Use in Server Components to protect pages.
390
+ *
391
+ * @example
392
+ * ```typescript
393
+ * // app/dashboard/page.tsx
394
+ * import { requireAuth } from '@authaz/next';
395
+ *
396
+ * export default async function DashboardPage() {
397
+ * await requireAuth(); // Redirects to login if not authenticated
398
+ *
399
+ * return <div>Dashboard</div>;
400
+ * }
401
+ * ```
402
+ */
403
+ const requireAuth = async (loginPath = "/api/auth/login") => {
404
+ const navigation = await import("next/navigation");
405
+ if (!await getAccessToken()) navigation.redirect(loginPath);
406
+ };
407
+ /**
408
+ * Server Component helper that returns user or redirects if not authenticated.
409
+ *
410
+ * @example
411
+ * ```typescript
412
+ * // app/profile/page.tsx
413
+ * import { requireUser } from '@authaz/next';
414
+ *
415
+ * const helpers = requireUser({
416
+ * authazDomain: 'https://authaz.com',
417
+ * apiKey: process.env.AUTHAZ_API_KEY!,
418
+ * });
419
+ *
420
+ * export default async function ProfilePage() {
421
+ * const user = await helpers.getOrRedirect();
422
+ * return <div>Hello {user.name}</div>;
423
+ * }
424
+ * ```
425
+ */
426
+ const requireUser = (config) => {
427
+ const authazDomain = config.authazDomain || "https://authaz.com";
428
+ const apiKey = config.apiKey || config.clientSecret;
429
+ const loginPath = config.loginPath || "/api/auth/login";
430
+ const getOrRedirect = async () => {
431
+ const navigation = await import("next/navigation");
432
+ const accessToken = (await getCookieStore()).get(COOKIE_NAMES.ACCESS_TOKEN)?.value;
433
+ if (!accessToken) navigation.redirect(loginPath);
434
+ const userinfo = await fetchUserinfo(authazDomain, accessToken, apiKey);
435
+ if (!userinfo) navigation.redirect(loginPath);
436
+ return mapUserinfoToUser(userinfo);
26
437
  };
438
+ return { getOrRedirect };
27
439
  };
28
440
 
29
441
  //#endregion
30
- export { authazNext };
442
+ export { AuthazError, createAuthMiddleware, createAuthazHandler, createAuthazHelpers, getAccessToken, getRefreshToken, isAuthenticated, requireAuth, requireUser, withAuth };
package/package.json CHANGED
@@ -1,52 +1,68 @@
1
1
  {
2
- "author": "@authaz",
3
- "name": "@authaz/next",
4
- "version": "0.0.1",
5
- "type": "module",
6
- "description": "NextJS authaz SDK",
7
- "license": "MIT",
8
- "main": "dist/index.js",
9
- "module": "dist/index.js",
10
- "types": "dist/index.d.ts",
11
- "exports": {
12
- "./*": "./dist/*",
13
- "./src/*": "./src/*",
14
- ".": {
15
- "import": "./dist/index.js",
16
- "require": "./dist/index.js",
17
- "types": "./dist/index.d.ts",
18
- "development": "./src/index.ts"
19
- }
2
+ "author": "@authaz",
3
+ "name": "@authaz/next",
4
+ "version": "1.0.1",
5
+ "type": "module",
6
+ "description": "NextJS authaz SDK",
7
+ "license": "MIT",
8
+ "main": "dist/index.js",
9
+ "module": "dist/index.js",
10
+ "types": "dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "import": "./dist/index.js",
14
+ "require": "./dist/index.js",
15
+ "types": "./dist/index.d.ts"
20
16
  },
21
- "repository": {
22
- "type": "git",
23
- "url": "git+https://github.com/Authaz/authaz-sdk-js.git"
24
- },
25
- "scripts": {
26
- "build": "tsdown",
27
- "prepare": "npm run build",
28
- "release:patch": "pnpm version patch && git push origin main --follow-tags",
29
- "release:minor": "pnpm version minor && git push origin main --follow-tags",
30
- "release:major": "pnpm version major && git push origin main --follow-tags",
31
- "release": "pnpm build && pnpm run release:patch"
32
- },
33
- "keywords": [
34
- "auth",
35
- "authentication",
36
- "authaz",
37
- "sdk",
38
- "react",
39
- "nextjs",
40
- "next"
41
- ],
42
- "peerDependencies": {
43
- "react": ">=17",
44
- "next": ">=15",
45
- "@authaz/sdk": "workspace:*"
46
- },
47
- "devDependencies": {
48
- "@types/node": "24.10.0",
49
- "tsdown": "0.15.12",
50
- "typescript": "5.9.3"
51
- }
52
- }
17
+ "./*": "./dist/*"
18
+ },
19
+ "files": [
20
+ "dist",
21
+ "README.md"
22
+ ],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "repository": {
27
+ "type": "git",
28
+ "url": "git+https://github.com/Authaz/authaz-sdk-js.git"
29
+ },
30
+ "keywords": [
31
+ "auth",
32
+ "authentication",
33
+ "authaz",
34
+ "sdk",
35
+ "react",
36
+ "nextjs",
37
+ "next"
38
+ ],
39
+ "peerDependencies": {
40
+ "next": ">=15",
41
+ "react": ">=17",
42
+ "@authaz/sdk": "^1.2.1"
43
+ },
44
+ "devDependencies": {
45
+ "@jest/globals": "30.2.0",
46
+ "@types/jest": "30.0.0",
47
+ "@types/node": "24.10.0",
48
+ "@types/react": "19.2.10",
49
+ "@types/react-dom": "19.2.3",
50
+ "jest": "30.2.0",
51
+ "next": "^15.5.11",
52
+ "react": "19.2.4",
53
+ "react-dom": "19.2.4",
54
+ "ts-jest": "29.4.5",
55
+ "tsdown": "0.15.12",
56
+ "typescript": "5.9.3"
57
+ },
58
+ "scripts": {
59
+ "build": "tsdown",
60
+ "test": "jest --config jest.config.cjs",
61
+ "test:watch": "jest --config jest.config.cjs --watch",
62
+ "test:coverage": "jest --config jest.config.cjs --coverage",
63
+ "release:patch": "pnpm version patch && git push origin main --follow-tags",
64
+ "release:minor": "pnpm version minor && git push origin main --follow-tags",
65
+ "release:major": "pnpm version major && git push origin main --follow-tags",
66
+ "release": "pnpm build && pnpm run release:patch"
67
+ }
68
+ }
package/CHANGELOG.md DELETED
@@ -1,64 +0,0 @@
1
- # Changelog
2
-
3
- Todas as mudanças notáveis deste projeto serão documentadas neste arquivo.
4
-
5
- ## [1.1.0] - 2024-01-XX
6
-
7
- ### ✨ Adicionado
8
- - **Nova API de Configuração**: Introduzida configuração baseada em objeto para melhor organização
9
- - **Validação de Configuração**: Validação automática de campos obrigatórios
10
- - **Status Específicos**: Cada fluxo agora tem status específicos para diferentes cenários
11
- - **Arquivo de Configuração**: Novo módulo `config.ts` para centralizar configurações
12
-
13
- ### 🔧 Melhorado
14
- - **Nomenclatura Padronizada**:
15
- - `SignupConfigureMfa` → `signupConfigureMfa`
16
- - `SignupVerifyMfa` → `signupVerifyMfa`
17
- - `acessTokenMfa` → `accessTokenMfa`
18
- - **Estrutura de Respostas**: Status específicos para cada tipo de operação com cenários detalhados
19
- - **Tipos de Usuário**: Unificação dos tipos de usuário com interface base `User`
20
- - **URLs Dinâmicas**: Remoção de URLs hardcoded, agora configuráveis
21
-
22
- ### 🏗️ Refatorado
23
- - **Construtor da ApiService**: Suporte para objeto de configuração + compatibilidade legacy
24
- - **Tipos de Token**: Melhor organização e reutilização de tipos de token
25
- - **Tipos de Erro**: Padronização de tipos de erro comuns
26
-
27
- ### 📚 Documentação
28
- - **README Atualizado**: Exemplos de configuração moderna e legacy
29
- - **Tipos Documentados**: Melhor documentação dos tipos disponíveis
30
- - **Exemplos de Uso**: Adicionados exemplos com nova API de configuração
31
-
32
- ### ⚡ Compatibilidade
33
- - **Backward Compatible**: Mantida compatibilidade com API legacy
34
- - **Migração Suave**: Possibilidade de migrar gradualmente para nova API
35
-
36
- ## Exemplo de Migração
37
-
38
- ### Antes (Legacy)
39
- ```typescript
40
- const client = new ApiService(
41
- 'https://api.authaz.com',
42
- 'client-id',
43
- 'client-secret',
44
- 'auth-pool-id',
45
- 'org-id',
46
- 'redirect-uri'
47
- )
48
- ```
49
-
50
- ### Depois (Moderno)
51
- ```typescript
52
- const client = new ApiService({
53
- baseUrl: 'https://api.authaz.com',
54
- clientId: 'client-id',
55
- clientSecret: 'client-secret',
56
- authPoolId: 'auth-pool-id',
57
- organizationId: 'org-id',
58
- redirectUri: 'redirect-uri'
59
- })
60
- ```
61
-
62
- ## Breaking Changes
63
-
64
- Nenhuma breaking change nesta versão. Todas as mudanças mantêm compatibilidade com versões anteriores.