azirid-react 0.11.1 → 0.11.2

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 CHANGED
@@ -60,10 +60,10 @@ Requests go directly to the Azirid API. Requires CORS to be configured on the AP
60
60
 
61
61
  ```ts
62
62
  // app/api/auth/[...path]/route.ts
63
- export { GET, POST, PUT, PATCH, DELETE } from 'azirid-react/next'
63
+ export { GET, POST, PUT, PATCH, DELETE } from 'azirid-react/next/handlers'
64
64
  ```
65
65
 
66
- That's it. The SDK handles proxy logic, cookie fixing, and header forwarding internally. Works with Next.js 14, 15, and 16+ automatically.
66
+ That's it. The SDK handles proxy logic, cookie fixing, and header forwarding internally. Works with Next.js 14, 15, and 16+ automatically — including `output: 'standalone'` builds.
67
67
 
68
68
  ### 2. Set the API URL (optional)
69
69
 
@@ -266,6 +266,23 @@ function Navbar() {
266
266
  }
267
267
  ```
268
268
 
269
+ > **`isLoading`** is `true` during session bootstrap (page load/refresh), login, and signup. Use it to show a loading state and prevent rendering authenticated UI before the session is ready. This ensures no API calls are made without a valid token.
270
+
271
+ #### Auth Guard pattern (Next.js)
272
+
273
+ ```tsx
274
+ import { useAzirid } from 'azirid-react'
275
+
276
+ function AuthGuard({ children }: { children: React.ReactNode }) {
277
+ const { isAuthenticated, isLoading } = useAzirid()
278
+
279
+ if (isLoading) return <LoadingSpinner />
280
+ if (!isAuthenticated) return <RedirectToLogin />
281
+
282
+ return <>{children}</>
283
+ }
284
+ ```
285
+
269
286
  ### `useLogin`
270
287
 
271
288
  ```tsx
@@ -376,7 +393,7 @@ import { useBootstrap } from 'azirid-react'
376
393
  const { bootstrap, isBootstrapping } = useBootstrap()
377
394
  ```
378
395
 
379
- > **Note:** The automatic bootstrap uses request deduplication — if React 18 Strict Mode (or any other scenario) triggers multiple bootstrap calls, only **one HTTP request** is made and all callers await the same promise. This prevents token rotation conflicts that would otherwise invalidate the session on page reload in development mode. Hooks like `usePayphoneCheckout` and `<PayphoneCallback>` wait for bootstrap to complete before making authenticated requests.
396
+ > **Note:** The automatic bootstrap uses request deduplication — if React 18 Strict Mode (or any other scenario) triggers multiple bootstrap calls, only **one HTTP request** is made and all callers await the same promise. This prevents token rotation conflicts that would otherwise invalidate the session on page reload in development mode. During bootstrap, `isLoading` from `useAzirid()` is `true`, so components using the Auth Guard pattern will show a loading state until the session is restored. Hooks like `usePayphoneCheckout`, `useSession`, and `<PayphoneCallback>` also wait for bootstrap to complete before making authenticated requests.
380
397
 
381
398
  ### `useRefresh`
382
399
 
@@ -1373,17 +1390,17 @@ Create the file `app/api/auth/[...path]/route.ts` — one line is all you need:
1373
1390
 
1374
1391
  ```ts
1375
1392
  // app/api/auth/[...path]/route.ts
1376
- export { GET, POST, PUT, PATCH, DELETE } from 'azirid-react/next'
1393
+ export { GET, POST, PUT, PATCH, DELETE } from 'azirid-react/next/handlers'
1377
1394
  ```
1378
1395
 
1379
1396
  That's it. The SDK handles all the proxy logic, cookie fixing, and header forwarding internally.
1380
- It works with Next.js 14, 15, and 16+ automatically.
1397
+ It works with Next.js 14, 15, and 16+ automatically — including `output: 'standalone'` builds.
1381
1398
 
1382
1399
  ### Custom API URL or debug logging
1383
1400
 
1384
1401
  ```ts
1385
1402
  // app/api/auth/[...path]/route.ts
1386
- import { createAziridRouteHandlers } from 'azirid-react/next'
1403
+ import { createAziridRouteHandlers } from 'azirid-react/next/handlers'
1387
1404
 
1388
1405
  export const { GET, POST, PUT, PATCH, DELETE } = createAziridRouteHandlers({
1389
1406
  apiUrl: 'https://my-custom-api.com',
@@ -1439,7 +1456,7 @@ module.exports = withAziridProxy()({
1439
1456
 
1440
1457
  ```ts
1441
1458
  // proxy.ts — only needed if you want route protection
1442
- import { createAziridProxy } from 'azirid-react/next'
1459
+ import { createAziridProxy } from 'azirid-react/next/proxy'
1443
1460
 
1444
1461
  export const proxy = createAziridProxy({
1445
1462
  protectedRoutes: ['/dashboard', '/settings'],
@@ -1456,7 +1473,7 @@ export const config = {
1456
1473
 
1457
1474
  ```ts
1458
1475
  // middleware.ts — only needed if you want route protection
1459
- import { createAziridMiddleware } from 'azirid-react/next'
1476
+ import { createAziridMiddleware } from 'azirid-react/next/proxy'
1460
1477
 
1461
1478
  export default createAziridMiddleware({
1462
1479
  protectedRoutes: ['/dashboard', '/settings'],
package/dist/index.cjs CHANGED
@@ -4746,7 +4746,7 @@ function usePasswordToggle() {
4746
4746
  }
4747
4747
 
4748
4748
  // src/index.ts
4749
- var SDK_VERSION = "0.11.1";
4749
+ var SDK_VERSION = "0.11.2";
4750
4750
 
4751
4751
  exports.AuthForm = AuthForm;
4752
4752
  exports.AziridProvider = AziridProvider;
package/dist/index.js CHANGED
@@ -4744,7 +4744,7 @@ function usePasswordToggle() {
4744
4744
  }
4745
4745
 
4746
4746
  // src/index.ts
4747
- var SDK_VERSION = "0.11.1";
4747
+ var SDK_VERSION = "0.11.2";
4748
4748
 
4749
4749
  export { AuthForm, AziridProvider, BASE_PATHS, CheckoutButton, ForgotPasswordForm, InvoiceList, LoginForm, PATHS, PayButton, PayphoneCallback, PayphoneWidgetRenderer, PricingTable, ReferralCard, ReferralStats, ResetPasswordForm, SDK_VERSION, SignupForm, SubscriptionBadge, buildPaths, changePasswordSchema, cn, createAccessClient, createForgotPasswordSchema, createLoginSchema, createMutationHook, createResetPasswordConfirmSchema, createSignupSchema, en, es, forgotPasswordSchema, isAuthError, loginSchema, magicLinkRequestSchema, magicLinkVerifySchema, passkeyRegisterStartSchema, removeStyles, resetPasswordConfirmSchema, resolveMessages, signupSchema, socialLoginSchema, useAccessClient, useAzirid, useBootstrap, useBranches, useBranding, useChangePassword, useCheckout, useFormState, useInvoices, useLogin, useLogout, useMagicLink, useMessages, usePasskeys, usePasswordReset, usePasswordToggle, usePayButton, usePaymentMethods, usePaymentProviders, usePayphoneCheckout, usePayphoneConfirm, usePlans, useReferral, useReferralStats, useRefresh, useSession, useSignup, useSocialLogin, useSubmitTransferProof, useSubscription, useSwitchTenant, useTenantMembers, useTenants, useTransferPayment, useTransferProofs, useUploadTransferProof };
4750
4750
  //# sourceMappingURL=index.js.map
@@ -0,0 +1,148 @@
1
+ 'use strict';
2
+
3
+ // src/server.ts
4
+ function createSessionSyncHandler(options) {
5
+ const name = options?.cookieName ?? "__session";
6
+ const secure = options?.secure ?? false;
7
+ const maxAge = options?.maxAge ?? 3600;
8
+ return {
9
+ async POST(req) {
10
+ const { token } = await req.json();
11
+ if (!token || typeof token !== "string") {
12
+ return new Response(JSON.stringify({ error: "Missing token" }), {
13
+ status: 400,
14
+ headers: { "Content-Type": "application/json" }
15
+ });
16
+ }
17
+ const parts = [`${name}=${token}`, "Path=/", "HttpOnly", "SameSite=Lax", `Max-Age=${maxAge}`];
18
+ if (secure) parts.push("Secure");
19
+ return new Response(JSON.stringify({ ok: true }), {
20
+ headers: {
21
+ "Content-Type": "application/json",
22
+ "Set-Cookie": parts.join("; ")
23
+ }
24
+ });
25
+ },
26
+ async DELETE() {
27
+ const parts = [`${name}=`, "Path=/", "HttpOnly", "SameSite=Lax", "Max-Age=0"];
28
+ if (secure) parts.push("Secure");
29
+ return new Response(JSON.stringify({ ok: true }), {
30
+ headers: {
31
+ "Content-Type": "application/json",
32
+ "Set-Cookie": parts.join("; ")
33
+ }
34
+ });
35
+ }
36
+ };
37
+ }
38
+
39
+ // src/next-handlers.ts
40
+ var AZIRID_API_URL = process.env.AZIRID_API_URL ?? "https://api.azirid.com";
41
+ function createHandler(options) {
42
+ const destination = (options?.apiUrl ?? AZIRID_API_URL).replace(/\/$/, "");
43
+ const debug = options?.debug ?? false;
44
+ return async function handler(request, context) {
45
+ const resolvedParams = context.params instanceof Promise ? await context.params : context.params;
46
+ const path = resolvedParams.path.join("/");
47
+ const targetUrl = `${destination}/v1/users/auth/${path}`;
48
+ if (debug) {
49
+ console.log(`[azirid-proxy] ${request.method} /api/auth/${path} \u2192 ${targetUrl}`);
50
+ console.log(`[azirid-proxy] Cookies:`, request.headers.get("cookie") ?? "(none)");
51
+ }
52
+ const forwardHeaders = new Headers();
53
+ request.headers.forEach((value, key) => {
54
+ const lower = key.toLowerCase();
55
+ if (lower !== "host" && lower !== "connection") {
56
+ forwardHeaders.set(key, value);
57
+ }
58
+ });
59
+ const body = request.method !== "GET" && request.method !== "HEAD" ? await request.text() : void 0;
60
+ const apiResponse = await fetch(targetUrl, {
61
+ method: request.method,
62
+ headers: forwardHeaders,
63
+ body
64
+ });
65
+ const responseHeaders = new Headers();
66
+ apiResponse.headers.forEach((value, key) => {
67
+ if (key.toLowerCase() !== "set-cookie") {
68
+ responseHeaders.set(key, value);
69
+ }
70
+ });
71
+ const isSecure = request.headers.get("x-forwarded-proto") === "https" || new URL(request.url).protocol === "https:";
72
+ const setCookies = typeof apiResponse.headers.getSetCookie === "function" ? apiResponse.headers.getSetCookie() : splitSetCookieHeader(apiResponse.headers.get("set-cookie") ?? "");
73
+ for (const cookie of setCookies) {
74
+ let fixed = cookie.replace(/;\s*[Dd]omain=[^;]*/g, "").replace(/;\s*[Pp]ath=[^;]*/g, "").replace(/[Ss]ame[Ss]ite=[Nn]one/g, "SameSite=Lax");
75
+ fixed += "; Path=/";
76
+ if (!isSecure) {
77
+ fixed = fixed.replace(/;\s*[Ss]ecure/g, "");
78
+ }
79
+ responseHeaders.append("set-cookie", fixed);
80
+ }
81
+ if (debug) {
82
+ console.log(`[azirid-proxy] API responded: ${apiResponse.status}`);
83
+ const responseCookies = [];
84
+ responseHeaders.forEach((value, key) => {
85
+ if (key.toLowerCase() === "set-cookie") responseCookies.push(value);
86
+ });
87
+ if (responseCookies.length > 0) {
88
+ console.log(`[azirid-proxy] Set-Cookie:`, responseCookies);
89
+ }
90
+ }
91
+ return new Response(apiResponse.body, {
92
+ status: apiResponse.status,
93
+ statusText: apiResponse.statusText,
94
+ headers: responseHeaders
95
+ });
96
+ };
97
+ }
98
+ function splitSetCookieHeader(header) {
99
+ if (!header) return [];
100
+ const cookies = [];
101
+ let current = "";
102
+ for (const part of header.split(", ")) {
103
+ if (current && /^[a-zA-Z0-9_\-.]+=/.test(part)) {
104
+ cookies.push(current);
105
+ current = part;
106
+ } else {
107
+ current = current ? `${current}, ${part}` : part;
108
+ }
109
+ }
110
+ if (current) cookies.push(current);
111
+ return cookies;
112
+ }
113
+ function createAziridRouteHandlers(options) {
114
+ const handler = createHandler(options);
115
+ return {
116
+ GET: handler,
117
+ POST: handler,
118
+ PUT: handler,
119
+ PATCH: handler,
120
+ DELETE: handler
121
+ };
122
+ }
123
+ var defaultHandlers = createAziridRouteHandlers();
124
+ var GET = defaultHandlers.GET;
125
+ var POST = defaultHandlers.POST;
126
+ var PUT = defaultHandlers.PUT;
127
+ var PATCH = defaultHandlers.PATCH;
128
+ var DELETE = defaultHandlers.DELETE;
129
+ function createAziridProxyHandler(apiUrl = AZIRID_API_URL) {
130
+ return createHandler({ apiUrl });
131
+ }
132
+ function withAziridProxy(apiUrl = AZIRID_API_URL) {
133
+ return (nextConfig = {}) => ({
134
+ ...nextConfig
135
+ });
136
+ }
137
+
138
+ exports.DELETE = DELETE;
139
+ exports.GET = GET;
140
+ exports.PATCH = PATCH;
141
+ exports.POST = POST;
142
+ exports.PUT = PUT;
143
+ exports.createAziridProxyHandler = createAziridProxyHandler;
144
+ exports.createAziridRouteHandlers = createAziridRouteHandlers;
145
+ exports.createSessionSyncHandler = createSessionSyncHandler;
146
+ exports.withAziridProxy = withAziridProxy;
147
+ //# sourceMappingURL=next-handlers.cjs.map
148
+ //# sourceMappingURL=next-handlers.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.ts","../src/next-handlers.ts"],"names":[],"mappings":"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","file":"next-handlers.cjs","sourcesContent":["/**\n * Server-side utilities for Next.js (App Router).\n *\n * Use this entry point in Server Components, Server Actions, and Route Handlers\n * to read the authenticated user's session token from the httpOnly `__session` cookie.\n *\n * @example\n * ```ts\n * // lib/access-server.ts\n * import { cookies } from \"next/headers\";\n * import { createServerAccess } from \"azirid-react/server\";\n * export const { getSessionToken } = createServerAccess({ cookies });\n * ```\n *\n * ```ts\n * // app/actions/profile.ts\n * \"use server\";\n * import { getSessionToken } from \"@/lib/access-server\";\n *\n * export async function getProfile() {\n * const token = await getSessionToken();\n * if (!token) throw new Error(\"Not authenticated\");\n *\n * const res = await fetch(\"https://api.myapp.com/v1/users/auth/me\", {\n * headers: { Authorization: `Bearer ${token}` },\n * });\n * return res.json();\n * }\n * ```\n *\n * @packageDocumentation\n */\n\n/** Minimal cookie store interface (subset of Next.js ReadonlyRequestCookies) */\ninterface CookieStore {\n get(name: string): { value: string } | undefined\n}\n\n/** The `cookies` function from `next/headers` */\ntype CookiesFn = () => CookieStore | Promise<CookieStore>\n\nexport interface ServerAccessOptions {\n /**\n * The `cookies` function imported from `next/headers`.\n * Required — pass it explicitly to avoid bundler issues with dynamic imports.\n *\n * @example\n * ```ts\n * import { cookies } from \"next/headers\";\n * createServerAccess({ cookies });\n * ```\n */\n cookies: CookiesFn\n\n /**\n * Name of the httpOnly cookie that carries the access token.\n * Must match the cookie set by the Azirid API.\n * @default \"__session\"\n */\n cookieName?: string\n}\n\nexport interface ServerAccess {\n /**\n * Read the raw JWT access token from the session cookie.\n * Returns `null` when no cookie is present or when called\n * outside a Next.js server context.\n */\n getSessionToken: () => Promise<string | null>\n\n /** Alias for {@link getSessionToken}. */\n getAccessToken: () => Promise<string | null>\n}\n\n/**\n * Create server-side helpers bound to the session cookie.\n *\n * Call once at module scope, then use the returned functions\n * in any Server Component, Server Action, or Route Handler.\n */\nexport function createServerAccess(options: ServerAccessOptions): ServerAccess {\n const { cookies, cookieName = '__session' } = options\n\n async function getSessionToken(): Promise<string | null> {\n try {\n const result = cookies()\n // Next.js 15+: cookies() returns a Promise\n const cookieStore = result instanceof Promise ? await result : result\n return cookieStore.get(cookieName)?.value ?? null\n } catch {\n return null\n }\n }\n\n return {\n getSessionToken,\n getAccessToken: getSessionToken,\n }\n}\n\n// ─── Session Sync Handler (cross-origin dev support) ─────────\n\nexport interface SessionSyncOptions {\n /** Cookie name (default: \"__session\") */\n cookieName?: string\n /** Set Secure flag on cookie (default: false) */\n secure?: boolean\n /** Cookie max age in seconds (default: 3600 = 1h) */\n maxAge?: number\n}\n\n/**\n * Create a route handler that syncs the access token to a local httpOnly cookie.\n *\n * Use this in a Next.js App Router route to bridge cross-origin sessions:\n *\n * @example\n * ```ts\n * // app/api/auth/session/route.ts\n * import { createSessionSyncHandler } from \"azirid-react/server\";\n * export const { POST, DELETE } = createSessionSyncHandler();\n * ```\n */\nexport function createSessionSyncHandler(options?: SessionSyncOptions) {\n const name = options?.cookieName ?? '__session'\n const secure = options?.secure ?? false\n const maxAge = options?.maxAge ?? 3600\n\n return {\n async POST(req: Request) {\n const { token } = await req.json()\n if (!token || typeof token !== 'string') {\n return new Response(JSON.stringify({ error: 'Missing token' }), {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n })\n }\n const parts = [`${name}=${token}`, 'Path=/', 'HttpOnly', 'SameSite=Lax', `Max-Age=${maxAge}`]\n if (secure) parts.push('Secure')\n return new Response(JSON.stringify({ ok: true }), {\n headers: {\n 'Content-Type': 'application/json',\n 'Set-Cookie': parts.join('; '),\n },\n })\n },\n async DELETE() {\n const parts = [`${name}=`, 'Path=/', 'HttpOnly', 'SameSite=Lax', 'Max-Age=0']\n if (secure) parts.push('Secure')\n return new Response(JSON.stringify({ ok: true }), {\n headers: {\n 'Content-Type': 'application/json',\n 'Set-Cookie': parts.join('; '),\n },\n })\n },\n }\n}\n","/**\n * Next.js route handlers for the Azirid auth proxy.\n *\n * This entry point uses **only standard Web APIs** (Request, Response, fetch)\n * and has **zero dependency on `next/server`**. This makes it safe to use in\n * Next.js standalone builds (`output: 'standalone'`) where external `next/server`\n * imports may fail at runtime.\n *\n * @example Route handler (simplest — one line)\n * ```ts\n * // app/api/auth/[...path]/route.ts\n * export { GET, POST, PUT, PATCH, DELETE } from \"azirid-react/next/handlers\";\n * ```\n *\n * @example Route handler (custom API URL)\n * ```ts\n * // app/api/auth/[...path]/route.ts\n * import { createAziridRouteHandlers } from \"azirid-react/next/handlers\";\n * export const { GET, POST, PUT, PATCH, DELETE } = createAziridRouteHandlers({\n * apiUrl: \"https://my-custom-api.com\",\n * debug: true,\n * });\n * ```\n *\n * @packageDocumentation\n */\n\n// ─── Constants ───────────────────────────────────────────────\n\n/**\n * Resolve the Azirid API URL.\n *\n * Priority:\n * 1. `AZIRID_API_URL` env var (server-only, recommended)\n * 2. `https://api.azirid.com` (production default)\n *\n * For local development, set `AZIRID_API_URL=http://localhost:3000` in your `.env`.\n */\nconst AZIRID_API_URL = process.env.AZIRID_API_URL ?? 'https://api.azirid.com'\n\n// ─── Types ───────────────────────────────────────────────────\n\ntype RouteHandler = (\n request: Request,\n context: { params: Promise<{ path: string[] }> | { path: string[] } },\n) => Promise<Response>\n\nexport interface AziridRouteHandlerOptions {\n /** Override the Azirid API URL (default: production API) */\n apiUrl?: string\n /** Enable debug logging of proxy requests (default: false) */\n debug?: boolean\n}\n\n// ─── Proxy Route Handler (core logic) ────────────────────────\n\nfunction createHandler(options?: AziridRouteHandlerOptions): RouteHandler {\n const destination = (options?.apiUrl ?? AZIRID_API_URL).replace(/\\/$/, '')\n const debug = options?.debug ?? false\n\n return async function handler(request, context) {\n // Handle Next.js 14 (sync params), 15 (async params), and 16+ (always async)\n const resolvedParams = context.params instanceof Promise ? await context.params : context.params\n const path = resolvedParams.path.join('/')\n const targetUrl = `${destination}/v1/users/auth/${path}`\n\n if (debug) {\n console.log(`[azirid-proxy] ${request.method} /api/auth/${path} → ${targetUrl}`)\n console.log(`[azirid-proxy] Cookies:`, request.headers.get('cookie') ?? '(none)')\n }\n\n // Forward request headers (strip host so the API sees its own host)\n const forwardHeaders = new Headers()\n request.headers.forEach((value, key) => {\n const lower = key.toLowerCase()\n if (lower !== 'host' && lower !== 'connection') {\n forwardHeaders.set(key, value)\n }\n })\n\n // Forward body for non-GET methods\n const body =\n request.method !== 'GET' && request.method !== 'HEAD' ? await request.text() : undefined\n\n // Proxy request to the Azirid API\n const apiResponse = await fetch(targetUrl, {\n method: request.method,\n headers: forwardHeaders,\n body,\n })\n\n // Build response headers, fixing Set-Cookie for first-party context\n const responseHeaders = new Headers()\n apiResponse.headers.forEach((value, key) => {\n if (key.toLowerCase() !== 'set-cookie') {\n responseHeaders.set(key, value)\n }\n })\n\n // Fix Set-Cookie headers: strip Domain, adjust SameSite/Secure for proxy\n const isSecure =\n request.headers.get('x-forwarded-proto') === 'https' ||\n new URL(request.url).protocol === 'https:'\n\n const setCookies: string[] =\n typeof apiResponse.headers.getSetCookie === 'function'\n ? apiResponse.headers.getSetCookie()\n : splitSetCookieHeader(apiResponse.headers.get('set-cookie') ?? '')\n\n for (const cookie of setCookies) {\n let fixed = cookie\n // Strip Domain — cookie will default to the proxy's domain (first-party)\n .replace(/;\\s*[Dd]omain=[^;]*/g, '')\n // Normalize Path to \"/\" — the API may set restrictive paths (e.g. /v1/users/auth/login)\n // which prevents cookies from being sent to other auth endpoints like /refresh or /bootstrap.\n // In proxy mode all auth cookies must be available on all routes.\n .replace(/;\\s*[Pp]ath=[^;]*/g, '')\n // Change SameSite=None to Lax (now same-origin, None is unnecessary)\n .replace(/[Ss]ame[Ss]ite=[Nn]one/g, 'SameSite=Lax')\n\n // Always set Path=/ for first-party proxy cookies\n fixed += '; Path=/'\n\n // In development (HTTP), remove Secure flag so cookies work on localhost\n if (!isSecure) {\n fixed = fixed.replace(/;\\s*[Ss]ecure/g, '')\n }\n\n responseHeaders.append('set-cookie', fixed)\n }\n\n if (debug) {\n console.log(`[azirid-proxy] API responded: ${apiResponse.status}`)\n const responseCookies: string[] = []\n responseHeaders.forEach((value, key) => {\n if (key.toLowerCase() === 'set-cookie') responseCookies.push(value)\n })\n if (responseCookies.length > 0) {\n console.log(`[azirid-proxy] Set-Cookie:`, responseCookies)\n }\n }\n\n return new Response(apiResponse.body, {\n status: apiResponse.status,\n statusText: apiResponse.statusText,\n headers: responseHeaders,\n })\n }\n}\n\n/** Split a raw Set-Cookie header string into individual cookies */\nfunction splitSetCookieHeader(header: string): string[] {\n if (!header) return []\n const cookies: string[] = []\n let current = ''\n for (const part of header.split(', ')) {\n if (current && /^[a-zA-Z0-9_\\-.]+=/.test(part)) {\n cookies.push(current)\n current = part\n } else {\n current = current ? `${current}, ${part}` : part\n }\n }\n if (current) cookies.push(current)\n return cookies\n}\n\n// ─── Route Handlers (ready to re-export) ─────────────────────\n\n/**\n * Create all route handlers for the Azirid auth proxy.\n *\n * Returns `{ GET, POST, PUT, PATCH, DELETE }` ready to be re-exported\n * from your `app/api/auth/[...path]/route.ts`.\n *\n * @example Default (zero config)\n * ```ts\n * // app/api/auth/[...path]/route.ts\n * import { createAziridRouteHandlers } from \"azirid-react/next/handlers\";\n * export const { GET, POST, PUT, PATCH, DELETE } = createAziridRouteHandlers();\n * ```\n *\n * @example Custom options\n * ```ts\n * // app/api/auth/[...path]/route.ts\n * import { createAziridRouteHandlers } from \"azirid-react/next/handlers\";\n * export const { GET, POST, PUT, PATCH, DELETE } = createAziridRouteHandlers({\n * apiUrl: \"https://my-custom-api.com\",\n * debug: true,\n * });\n * ```\n */\nexport function createAziridRouteHandlers(options?: AziridRouteHandlerOptions): {\n GET: RouteHandler\n POST: RouteHandler\n PUT: RouteHandler\n PATCH: RouteHandler\n DELETE: RouteHandler\n} {\n const handler = createHandler(options)\n return {\n GET: handler,\n POST: handler,\n PUT: handler,\n PATCH: handler,\n DELETE: handler,\n }\n}\n\n/**\n * Pre-built route handlers with default config.\n *\n * Just re-export these directly — no setup required:\n *\n * @example\n * ```ts\n * // app/api/auth/[...path]/route.ts\n * export { GET, POST, PUT, PATCH, DELETE } from \"azirid-react/next/handlers\";\n * ```\n */\nconst defaultHandlers = createAziridRouteHandlers()\nexport const GET = defaultHandlers.GET\nexport const POST = defaultHandlers.POST\nexport const PUT = defaultHandlers.PUT\nexport const PATCH = defaultHandlers.PATCH\nexport const DELETE = defaultHandlers.DELETE\n\n/**\n * Create a single Next.js route handler function.\n *\n * Use this if you need a single handler reference (advanced use).\n * For most cases, prefer `createAziridRouteHandlers()` or the pre-built exports.\n *\n * @deprecated Use `createAziridRouteHandlers()` instead.\n */\nexport function createAziridProxyHandler(apiUrl: string = AZIRID_API_URL): RouteHandler {\n return createHandler({ apiUrl })\n}\n\n// ─── Config Helper ───────────────────────────────────────────\n\n/**\n * Wrap your Next.js config with Azirid settings.\n *\n * In Next.js 16+ with Turbopack, `transpilePackages` is no longer needed.\n * This helper is kept for backward compatibility with Next.js 14/15.\n *\n * @param apiUrl - Override the Azirid API URL (default: production API)\n */\nexport function withAziridProxy(apiUrl: string = AZIRID_API_URL) {\n void apiUrl\n\n return (nextConfig: Record<string, unknown> = {}) => ({\n ...nextConfig,\n })\n}\n\n// ─── Re-export session sync for backward compat ──────────────\n\nexport { createSessionSyncHandler } from './server'\nexport type { SessionSyncOptions } from './server'\n"]}
@@ -0,0 +1,138 @@
1
+ // src/server.ts
2
+ function createSessionSyncHandler(options) {
3
+ const name = options?.cookieName ?? "__session";
4
+ const secure = options?.secure ?? false;
5
+ const maxAge = options?.maxAge ?? 3600;
6
+ return {
7
+ async POST(req) {
8
+ const { token } = await req.json();
9
+ if (!token || typeof token !== "string") {
10
+ return new Response(JSON.stringify({ error: "Missing token" }), {
11
+ status: 400,
12
+ headers: { "Content-Type": "application/json" }
13
+ });
14
+ }
15
+ const parts = [`${name}=${token}`, "Path=/", "HttpOnly", "SameSite=Lax", `Max-Age=${maxAge}`];
16
+ if (secure) parts.push("Secure");
17
+ return new Response(JSON.stringify({ ok: true }), {
18
+ headers: {
19
+ "Content-Type": "application/json",
20
+ "Set-Cookie": parts.join("; ")
21
+ }
22
+ });
23
+ },
24
+ async DELETE() {
25
+ const parts = [`${name}=`, "Path=/", "HttpOnly", "SameSite=Lax", "Max-Age=0"];
26
+ if (secure) parts.push("Secure");
27
+ return new Response(JSON.stringify({ ok: true }), {
28
+ headers: {
29
+ "Content-Type": "application/json",
30
+ "Set-Cookie": parts.join("; ")
31
+ }
32
+ });
33
+ }
34
+ };
35
+ }
36
+
37
+ // src/next-handlers.ts
38
+ var AZIRID_API_URL = process.env.AZIRID_API_URL ?? "https://api.azirid.com";
39
+ function createHandler(options) {
40
+ const destination = (options?.apiUrl ?? AZIRID_API_URL).replace(/\/$/, "");
41
+ const debug = options?.debug ?? false;
42
+ return async function handler(request, context) {
43
+ const resolvedParams = context.params instanceof Promise ? await context.params : context.params;
44
+ const path = resolvedParams.path.join("/");
45
+ const targetUrl = `${destination}/v1/users/auth/${path}`;
46
+ if (debug) {
47
+ console.log(`[azirid-proxy] ${request.method} /api/auth/${path} \u2192 ${targetUrl}`);
48
+ console.log(`[azirid-proxy] Cookies:`, request.headers.get("cookie") ?? "(none)");
49
+ }
50
+ const forwardHeaders = new Headers();
51
+ request.headers.forEach((value, key) => {
52
+ const lower = key.toLowerCase();
53
+ if (lower !== "host" && lower !== "connection") {
54
+ forwardHeaders.set(key, value);
55
+ }
56
+ });
57
+ const body = request.method !== "GET" && request.method !== "HEAD" ? await request.text() : void 0;
58
+ const apiResponse = await fetch(targetUrl, {
59
+ method: request.method,
60
+ headers: forwardHeaders,
61
+ body
62
+ });
63
+ const responseHeaders = new Headers();
64
+ apiResponse.headers.forEach((value, key) => {
65
+ if (key.toLowerCase() !== "set-cookie") {
66
+ responseHeaders.set(key, value);
67
+ }
68
+ });
69
+ const isSecure = request.headers.get("x-forwarded-proto") === "https" || new URL(request.url).protocol === "https:";
70
+ const setCookies = typeof apiResponse.headers.getSetCookie === "function" ? apiResponse.headers.getSetCookie() : splitSetCookieHeader(apiResponse.headers.get("set-cookie") ?? "");
71
+ for (const cookie of setCookies) {
72
+ let fixed = cookie.replace(/;\s*[Dd]omain=[^;]*/g, "").replace(/;\s*[Pp]ath=[^;]*/g, "").replace(/[Ss]ame[Ss]ite=[Nn]one/g, "SameSite=Lax");
73
+ fixed += "; Path=/";
74
+ if (!isSecure) {
75
+ fixed = fixed.replace(/;\s*[Ss]ecure/g, "");
76
+ }
77
+ responseHeaders.append("set-cookie", fixed);
78
+ }
79
+ if (debug) {
80
+ console.log(`[azirid-proxy] API responded: ${apiResponse.status}`);
81
+ const responseCookies = [];
82
+ responseHeaders.forEach((value, key) => {
83
+ if (key.toLowerCase() === "set-cookie") responseCookies.push(value);
84
+ });
85
+ if (responseCookies.length > 0) {
86
+ console.log(`[azirid-proxy] Set-Cookie:`, responseCookies);
87
+ }
88
+ }
89
+ return new Response(apiResponse.body, {
90
+ status: apiResponse.status,
91
+ statusText: apiResponse.statusText,
92
+ headers: responseHeaders
93
+ });
94
+ };
95
+ }
96
+ function splitSetCookieHeader(header) {
97
+ if (!header) return [];
98
+ const cookies = [];
99
+ let current = "";
100
+ for (const part of header.split(", ")) {
101
+ if (current && /^[a-zA-Z0-9_\-.]+=/.test(part)) {
102
+ cookies.push(current);
103
+ current = part;
104
+ } else {
105
+ current = current ? `${current}, ${part}` : part;
106
+ }
107
+ }
108
+ if (current) cookies.push(current);
109
+ return cookies;
110
+ }
111
+ function createAziridRouteHandlers(options) {
112
+ const handler = createHandler(options);
113
+ return {
114
+ GET: handler,
115
+ POST: handler,
116
+ PUT: handler,
117
+ PATCH: handler,
118
+ DELETE: handler
119
+ };
120
+ }
121
+ var defaultHandlers = createAziridRouteHandlers();
122
+ var GET = defaultHandlers.GET;
123
+ var POST = defaultHandlers.POST;
124
+ var PUT = defaultHandlers.PUT;
125
+ var PATCH = defaultHandlers.PATCH;
126
+ var DELETE = defaultHandlers.DELETE;
127
+ function createAziridProxyHandler(apiUrl = AZIRID_API_URL) {
128
+ return createHandler({ apiUrl });
129
+ }
130
+ function withAziridProxy(apiUrl = AZIRID_API_URL) {
131
+ return (nextConfig = {}) => ({
132
+ ...nextConfig
133
+ });
134
+ }
135
+
136
+ export { DELETE, GET, PATCH, POST, PUT, createAziridProxyHandler, createAziridRouteHandlers, createSessionSyncHandler, withAziridProxy };
137
+ //# sourceMappingURL=next-handlers.js.map
138
+ //# sourceMappingURL=next-handlers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.ts","../src/next-handlers.ts"],"names":[],"mappings":"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","file":"next-handlers.js","sourcesContent":["/**\n * Server-side utilities for Next.js (App Router).\n *\n * Use this entry point in Server Components, Server Actions, and Route Handlers\n * to read the authenticated user's session token from the httpOnly `__session` cookie.\n *\n * @example\n * ```ts\n * // lib/access-server.ts\n * import { cookies } from \"next/headers\";\n * import { createServerAccess } from \"azirid-react/server\";\n * export const { getSessionToken } = createServerAccess({ cookies });\n * ```\n *\n * ```ts\n * // app/actions/profile.ts\n * \"use server\";\n * import { getSessionToken } from \"@/lib/access-server\";\n *\n * export async function getProfile() {\n * const token = await getSessionToken();\n * if (!token) throw new Error(\"Not authenticated\");\n *\n * const res = await fetch(\"https://api.myapp.com/v1/users/auth/me\", {\n * headers: { Authorization: `Bearer ${token}` },\n * });\n * return res.json();\n * }\n * ```\n *\n * @packageDocumentation\n */\n\n/** Minimal cookie store interface (subset of Next.js ReadonlyRequestCookies) */\ninterface CookieStore {\n get(name: string): { value: string } | undefined\n}\n\n/** The `cookies` function from `next/headers` */\ntype CookiesFn = () => CookieStore | Promise<CookieStore>\n\nexport interface ServerAccessOptions {\n /**\n * The `cookies` function imported from `next/headers`.\n * Required — pass it explicitly to avoid bundler issues with dynamic imports.\n *\n * @example\n * ```ts\n * import { cookies } from \"next/headers\";\n * createServerAccess({ cookies });\n * ```\n */\n cookies: CookiesFn\n\n /**\n * Name of the httpOnly cookie that carries the access token.\n * Must match the cookie set by the Azirid API.\n * @default \"__session\"\n */\n cookieName?: string\n}\n\nexport interface ServerAccess {\n /**\n * Read the raw JWT access token from the session cookie.\n * Returns `null` when no cookie is present or when called\n * outside a Next.js server context.\n */\n getSessionToken: () => Promise<string | null>\n\n /** Alias for {@link getSessionToken}. */\n getAccessToken: () => Promise<string | null>\n}\n\n/**\n * Create server-side helpers bound to the session cookie.\n *\n * Call once at module scope, then use the returned functions\n * in any Server Component, Server Action, or Route Handler.\n */\nexport function createServerAccess(options: ServerAccessOptions): ServerAccess {\n const { cookies, cookieName = '__session' } = options\n\n async function getSessionToken(): Promise<string | null> {\n try {\n const result = cookies()\n // Next.js 15+: cookies() returns a Promise\n const cookieStore = result instanceof Promise ? await result : result\n return cookieStore.get(cookieName)?.value ?? null\n } catch {\n return null\n }\n }\n\n return {\n getSessionToken,\n getAccessToken: getSessionToken,\n }\n}\n\n// ─── Session Sync Handler (cross-origin dev support) ─────────\n\nexport interface SessionSyncOptions {\n /** Cookie name (default: \"__session\") */\n cookieName?: string\n /** Set Secure flag on cookie (default: false) */\n secure?: boolean\n /** Cookie max age in seconds (default: 3600 = 1h) */\n maxAge?: number\n}\n\n/**\n * Create a route handler that syncs the access token to a local httpOnly cookie.\n *\n * Use this in a Next.js App Router route to bridge cross-origin sessions:\n *\n * @example\n * ```ts\n * // app/api/auth/session/route.ts\n * import { createSessionSyncHandler } from \"azirid-react/server\";\n * export const { POST, DELETE } = createSessionSyncHandler();\n * ```\n */\nexport function createSessionSyncHandler(options?: SessionSyncOptions) {\n const name = options?.cookieName ?? '__session'\n const secure = options?.secure ?? false\n const maxAge = options?.maxAge ?? 3600\n\n return {\n async POST(req: Request) {\n const { token } = await req.json()\n if (!token || typeof token !== 'string') {\n return new Response(JSON.stringify({ error: 'Missing token' }), {\n status: 400,\n headers: { 'Content-Type': 'application/json' },\n })\n }\n const parts = [`${name}=${token}`, 'Path=/', 'HttpOnly', 'SameSite=Lax', `Max-Age=${maxAge}`]\n if (secure) parts.push('Secure')\n return new Response(JSON.stringify({ ok: true }), {\n headers: {\n 'Content-Type': 'application/json',\n 'Set-Cookie': parts.join('; '),\n },\n })\n },\n async DELETE() {\n const parts = [`${name}=`, 'Path=/', 'HttpOnly', 'SameSite=Lax', 'Max-Age=0']\n if (secure) parts.push('Secure')\n return new Response(JSON.stringify({ ok: true }), {\n headers: {\n 'Content-Type': 'application/json',\n 'Set-Cookie': parts.join('; '),\n },\n })\n },\n }\n}\n","/**\n * Next.js route handlers for the Azirid auth proxy.\n *\n * This entry point uses **only standard Web APIs** (Request, Response, fetch)\n * and has **zero dependency on `next/server`**. This makes it safe to use in\n * Next.js standalone builds (`output: 'standalone'`) where external `next/server`\n * imports may fail at runtime.\n *\n * @example Route handler (simplest — one line)\n * ```ts\n * // app/api/auth/[...path]/route.ts\n * export { GET, POST, PUT, PATCH, DELETE } from \"azirid-react/next/handlers\";\n * ```\n *\n * @example Route handler (custom API URL)\n * ```ts\n * // app/api/auth/[...path]/route.ts\n * import { createAziridRouteHandlers } from \"azirid-react/next/handlers\";\n * export const { GET, POST, PUT, PATCH, DELETE } = createAziridRouteHandlers({\n * apiUrl: \"https://my-custom-api.com\",\n * debug: true,\n * });\n * ```\n *\n * @packageDocumentation\n */\n\n// ─── Constants ───────────────────────────────────────────────\n\n/**\n * Resolve the Azirid API URL.\n *\n * Priority:\n * 1. `AZIRID_API_URL` env var (server-only, recommended)\n * 2. `https://api.azirid.com` (production default)\n *\n * For local development, set `AZIRID_API_URL=http://localhost:3000` in your `.env`.\n */\nconst AZIRID_API_URL = process.env.AZIRID_API_URL ?? 'https://api.azirid.com'\n\n// ─── Types ───────────────────────────────────────────────────\n\ntype RouteHandler = (\n request: Request,\n context: { params: Promise<{ path: string[] }> | { path: string[] } },\n) => Promise<Response>\n\nexport interface AziridRouteHandlerOptions {\n /** Override the Azirid API URL (default: production API) */\n apiUrl?: string\n /** Enable debug logging of proxy requests (default: false) */\n debug?: boolean\n}\n\n// ─── Proxy Route Handler (core logic) ────────────────────────\n\nfunction createHandler(options?: AziridRouteHandlerOptions): RouteHandler {\n const destination = (options?.apiUrl ?? AZIRID_API_URL).replace(/\\/$/, '')\n const debug = options?.debug ?? false\n\n return async function handler(request, context) {\n // Handle Next.js 14 (sync params), 15 (async params), and 16+ (always async)\n const resolvedParams = context.params instanceof Promise ? await context.params : context.params\n const path = resolvedParams.path.join('/')\n const targetUrl = `${destination}/v1/users/auth/${path}`\n\n if (debug) {\n console.log(`[azirid-proxy] ${request.method} /api/auth/${path} → ${targetUrl}`)\n console.log(`[azirid-proxy] Cookies:`, request.headers.get('cookie') ?? '(none)')\n }\n\n // Forward request headers (strip host so the API sees its own host)\n const forwardHeaders = new Headers()\n request.headers.forEach((value, key) => {\n const lower = key.toLowerCase()\n if (lower !== 'host' && lower !== 'connection') {\n forwardHeaders.set(key, value)\n }\n })\n\n // Forward body for non-GET methods\n const body =\n request.method !== 'GET' && request.method !== 'HEAD' ? await request.text() : undefined\n\n // Proxy request to the Azirid API\n const apiResponse = await fetch(targetUrl, {\n method: request.method,\n headers: forwardHeaders,\n body,\n })\n\n // Build response headers, fixing Set-Cookie for first-party context\n const responseHeaders = new Headers()\n apiResponse.headers.forEach((value, key) => {\n if (key.toLowerCase() !== 'set-cookie') {\n responseHeaders.set(key, value)\n }\n })\n\n // Fix Set-Cookie headers: strip Domain, adjust SameSite/Secure for proxy\n const isSecure =\n request.headers.get('x-forwarded-proto') === 'https' ||\n new URL(request.url).protocol === 'https:'\n\n const setCookies: string[] =\n typeof apiResponse.headers.getSetCookie === 'function'\n ? apiResponse.headers.getSetCookie()\n : splitSetCookieHeader(apiResponse.headers.get('set-cookie') ?? '')\n\n for (const cookie of setCookies) {\n let fixed = cookie\n // Strip Domain — cookie will default to the proxy's domain (first-party)\n .replace(/;\\s*[Dd]omain=[^;]*/g, '')\n // Normalize Path to \"/\" — the API may set restrictive paths (e.g. /v1/users/auth/login)\n // which prevents cookies from being sent to other auth endpoints like /refresh or /bootstrap.\n // In proxy mode all auth cookies must be available on all routes.\n .replace(/;\\s*[Pp]ath=[^;]*/g, '')\n // Change SameSite=None to Lax (now same-origin, None is unnecessary)\n .replace(/[Ss]ame[Ss]ite=[Nn]one/g, 'SameSite=Lax')\n\n // Always set Path=/ for first-party proxy cookies\n fixed += '; Path=/'\n\n // In development (HTTP), remove Secure flag so cookies work on localhost\n if (!isSecure) {\n fixed = fixed.replace(/;\\s*[Ss]ecure/g, '')\n }\n\n responseHeaders.append('set-cookie', fixed)\n }\n\n if (debug) {\n console.log(`[azirid-proxy] API responded: ${apiResponse.status}`)\n const responseCookies: string[] = []\n responseHeaders.forEach((value, key) => {\n if (key.toLowerCase() === 'set-cookie') responseCookies.push(value)\n })\n if (responseCookies.length > 0) {\n console.log(`[azirid-proxy] Set-Cookie:`, responseCookies)\n }\n }\n\n return new Response(apiResponse.body, {\n status: apiResponse.status,\n statusText: apiResponse.statusText,\n headers: responseHeaders,\n })\n }\n}\n\n/** Split a raw Set-Cookie header string into individual cookies */\nfunction splitSetCookieHeader(header: string): string[] {\n if (!header) return []\n const cookies: string[] = []\n let current = ''\n for (const part of header.split(', ')) {\n if (current && /^[a-zA-Z0-9_\\-.]+=/.test(part)) {\n cookies.push(current)\n current = part\n } else {\n current = current ? `${current}, ${part}` : part\n }\n }\n if (current) cookies.push(current)\n return cookies\n}\n\n// ─── Route Handlers (ready to re-export) ─────────────────────\n\n/**\n * Create all route handlers for the Azirid auth proxy.\n *\n * Returns `{ GET, POST, PUT, PATCH, DELETE }` ready to be re-exported\n * from your `app/api/auth/[...path]/route.ts`.\n *\n * @example Default (zero config)\n * ```ts\n * // app/api/auth/[...path]/route.ts\n * import { createAziridRouteHandlers } from \"azirid-react/next/handlers\";\n * export const { GET, POST, PUT, PATCH, DELETE } = createAziridRouteHandlers();\n * ```\n *\n * @example Custom options\n * ```ts\n * // app/api/auth/[...path]/route.ts\n * import { createAziridRouteHandlers } from \"azirid-react/next/handlers\";\n * export const { GET, POST, PUT, PATCH, DELETE } = createAziridRouteHandlers({\n * apiUrl: \"https://my-custom-api.com\",\n * debug: true,\n * });\n * ```\n */\nexport function createAziridRouteHandlers(options?: AziridRouteHandlerOptions): {\n GET: RouteHandler\n POST: RouteHandler\n PUT: RouteHandler\n PATCH: RouteHandler\n DELETE: RouteHandler\n} {\n const handler = createHandler(options)\n return {\n GET: handler,\n POST: handler,\n PUT: handler,\n PATCH: handler,\n DELETE: handler,\n }\n}\n\n/**\n * Pre-built route handlers with default config.\n *\n * Just re-export these directly — no setup required:\n *\n * @example\n * ```ts\n * // app/api/auth/[...path]/route.ts\n * export { GET, POST, PUT, PATCH, DELETE } from \"azirid-react/next/handlers\";\n * ```\n */\nconst defaultHandlers = createAziridRouteHandlers()\nexport const GET = defaultHandlers.GET\nexport const POST = defaultHandlers.POST\nexport const PUT = defaultHandlers.PUT\nexport const PATCH = defaultHandlers.PATCH\nexport const DELETE = defaultHandlers.DELETE\n\n/**\n * Create a single Next.js route handler function.\n *\n * Use this if you need a single handler reference (advanced use).\n * For most cases, prefer `createAziridRouteHandlers()` or the pre-built exports.\n *\n * @deprecated Use `createAziridRouteHandlers()` instead.\n */\nexport function createAziridProxyHandler(apiUrl: string = AZIRID_API_URL): RouteHandler {\n return createHandler({ apiUrl })\n}\n\n// ─── Config Helper ───────────────────────────────────────────\n\n/**\n * Wrap your Next.js config with Azirid settings.\n *\n * In Next.js 16+ with Turbopack, `transpilePackages` is no longer needed.\n * This helper is kept for backward compatibility with Next.js 14/15.\n *\n * @param apiUrl - Override the Azirid API URL (default: production API)\n */\nexport function withAziridProxy(apiUrl: string = AZIRID_API_URL) {\n void apiUrl\n\n return (nextConfig: Record<string, unknown> = {}) => ({\n ...nextConfig,\n })\n}\n\n// ─── Re-export session sync for backward compat ──────────────\n\nexport { createSessionSyncHandler } from './server'\nexport type { SessionSyncOptions } from './server'\n"]}
@@ -0,0 +1,45 @@
1
+ 'use strict';
2
+
3
+ var server = require('next/server');
4
+
5
+ // src/next-proxy.ts
6
+ function createRequestInterceptor(options) {
7
+ const cookieName = options?.cookieName ?? "__session";
8
+ const loginUrl = options?.loginUrl ?? "/login";
9
+ const publicRoutes = options?.publicRoutes ?? ["/login", "/signup"];
10
+ const protectedRoutes = options?.protectedRoutes;
11
+ return function handler(request) {
12
+ const { pathname } = request.nextUrl;
13
+ const token = request.cookies.get(cookieName)?.value;
14
+ const response = server.NextResponse.next();
15
+ if (token) {
16
+ response.headers.set("x-azirid-token", token);
17
+ }
18
+ if (protectedRoutes) {
19
+ const isPublic = publicRoutes.some((r) => pathname.startsWith(r));
20
+ const isProtected = protectedRoutes.some((r) => pathname.startsWith(r));
21
+ if (isProtected && !isPublic && !token) {
22
+ const url = request.nextUrl.clone();
23
+ url.pathname = loginUrl;
24
+ url.searchParams.set("redirect", pathname);
25
+ return server.NextResponse.redirect(url);
26
+ }
27
+ }
28
+ return response;
29
+ };
30
+ }
31
+ function createAziridProxy(options) {
32
+ return createRequestInterceptor(options);
33
+ }
34
+ var aziridProxy = createAziridProxy();
35
+ function createAziridMiddleware(options) {
36
+ return createRequestInterceptor(options);
37
+ }
38
+ var aziridMiddleware = createAziridMiddleware();
39
+
40
+ exports.aziridMiddleware = aziridMiddleware;
41
+ exports.aziridProxy = aziridProxy;
42
+ exports.createAziridMiddleware = createAziridMiddleware;
43
+ exports.createAziridProxy = createAziridProxy;
44
+ //# sourceMappingURL=next-proxy.cjs.map
45
+ //# sourceMappingURL=next-proxy.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/next-proxy.ts"],"names":["NextResponse"],"mappings":";;;;;AAmDA,SAAS,yBAAyB,OAAA,EAA8B;AAC9D,EAAA,MAAM,UAAA,GAAa,SAAS,UAAA,IAAc,WAAA;AAC1C,EAAA,MAAM,QAAA,GAAW,SAAS,QAAA,IAAY,QAAA;AACtC,EAAA,MAAM,YAAA,GAAe,OAAA,EAAS,YAAA,IAAgB,CAAC,UAAU,SAAS,CAAA;AAClE,EAAA,MAAM,kBAAkB,OAAA,EAAS,eAAA;AAEjC,EAAA,OAAO,SAAS,QAAQ,OAAA,EAAsB;AAC5C,IAAA,MAAM,EAAE,QAAA,EAAS,GAAI,OAAA,CAAQ,OAAA;AAC7B,IAAA,MAAM,KAAA,GAAQ,OAAA,CAAQ,OAAA,CAAQ,GAAA,CAAI,UAAU,CAAA,EAAG,KAAA;AAE/C,IAAA,MAAM,QAAA,GAAWA,oBAAa,IAAA,EAAK;AAGnC,IAAA,IAAI,KAAA,EAAO;AACT,MAAA,QAAA,CAAS,OAAA,CAAQ,GAAA,CAAI,gBAAA,EAAkB,KAAK,CAAA;AAAA,IAC9C;AAGA,IAAA,IAAI,eAAA,EAAiB;AACnB,MAAA,MAAM,QAAA,GAAW,aAAa,IAAA,CAAK,CAAC,MAAM,QAAA,CAAS,UAAA,CAAW,CAAC,CAAC,CAAA;AAChE,MAAA,MAAM,WAAA,GAAc,gBAAgB,IAAA,CAAK,CAAC,MAAM,QAAA,CAAS,UAAA,CAAW,CAAC,CAAC,CAAA;AAEtE,MAAA,IAAI,WAAA,IAAe,CAAC,QAAA,IAAY,CAAC,KAAA,EAAO;AACtC,QAAA,MAAM,GAAA,GAAM,OAAA,CAAQ,OAAA,CAAQ,KAAA,EAAM;AAClC,QAAA,GAAA,CAAI,QAAA,GAAW,QAAA;AACf,QAAA,GAAA,CAAI,YAAA,CAAa,GAAA,CAAI,UAAA,EAAY,QAAQ,CAAA;AACzC,QAAA,OAAOA,mBAAA,CAAa,SAAS,GAAG,CAAA;AAAA,MAClC;AAAA,IACF;AAEA,IAAA,OAAO,QAAA;AAAA,EACT,CAAA;AACF;AAyBO,SAAS,kBAAkB,OAAA,EAA8B;AAC9D,EAAA,OAAO,yBAAyB,OAAO,CAAA;AACzC;AAGO,IAAM,cAAc,iBAAA;AAOpB,SAAS,uBAAuB,OAAA,EAA8B;AACnE,EAAA,OAAO,yBAAyB,OAAO,CAAA;AACzC;AAKO,IAAM,mBAAmB,sBAAA","file":"next-proxy.cjs","sourcesContent":["/**\n * Next.js proxy and middleware utilities for Azirid Access.\n *\n * This entry point requires `next/server` and provides request interception\n * for route protection and token forwarding.\n *\n * @example Next.js 16+ (proxy.ts)\n * ```ts\n * // proxy.ts\n * export { aziridProxy as proxy } from \"azirid-react/next/proxy\";\n * export const config = { matcher: [\"/((?!_next|favicon.ico|api/).*)\"] };\n * ```\n *\n * @example Next.js 16+ with custom options\n * ```ts\n * // proxy.ts\n * import { createAziridProxy } from \"azirid-react/next/proxy\";\n * export const proxy = createAziridProxy({ protectedRoutes: [\"/dashboard\"] });\n * export const config = { matcher: [\"/((?!_next|favicon.ico|api/).*)\"] };\n * ```\n *\n * @example Next.js 14/15 (middleware.ts — deprecated in Next.js 16)\n * ```ts\n * // middleware.ts\n * export { aziridMiddleware as default } from \"azirid-react/next/proxy\";\n * export const config = { matcher: [\"/((?!_next|favicon.ico|api/).*)\"] };\n * ```\n *\n * @packageDocumentation\n */\n\nimport { NextResponse, type NextRequest } from 'next/server'\n\n// ─── Proxy / Middleware Options ──────────────────────────────\n\nexport interface AziridProxyOptions {\n /** Cookie name (default: \"__session\") */\n cookieName?: string\n /** Routes that require authentication (glob patterns via startsWith) */\n protectedRoutes?: string[]\n /** Route to redirect to when not authenticated (default: \"/login\") */\n loginUrl?: string\n /** Routes that are always public (default: [\"/login\", \"/signup\"]) */\n publicRoutes?: string[]\n}\n\n/** @deprecated Use `AziridProxyOptions` instead */\nexport type AziridMiddlewareOptions = AziridProxyOptions\n\n// ─── Shared proxy/middleware logic ───────────────────────────\n\nfunction createRequestInterceptor(options?: AziridProxyOptions) {\n const cookieName = options?.cookieName ?? '__session'\n const loginUrl = options?.loginUrl ?? '/login'\n const publicRoutes = options?.publicRoutes ?? ['/login', '/signup']\n const protectedRoutes = options?.protectedRoutes\n\n return function handler(request: NextRequest) {\n const { pathname } = request.nextUrl\n const token = request.cookies.get(cookieName)?.value\n\n const response = NextResponse.next()\n\n // Expose token as internal header for server components\n if (token) {\n response.headers.set('x-azirid-token', token)\n }\n\n // Route protection (only when protectedRoutes is configured)\n if (protectedRoutes) {\n const isPublic = publicRoutes.some((r) => pathname.startsWith(r))\n const isProtected = protectedRoutes.some((r) => pathname.startsWith(r))\n\n if (isProtected && !isPublic && !token) {\n const url = request.nextUrl.clone()\n url.pathname = loginUrl\n url.searchParams.set('redirect', pathname)\n return NextResponse.redirect(url)\n }\n }\n\n return response\n }\n}\n\n// ─── Proxy (Next.js 16+) ────────────────────────────────────\n\n/**\n * Create a customized Azirid proxy for Next.js 16+.\n *\n * In Next.js 16, `middleware.ts` is renamed to `proxy.ts` and the\n * exported function must be named `proxy`.\n *\n * @example Default (one line)\n * ```ts\n * // proxy.ts\n * export { aziridProxy as proxy } from \"azirid-react/next/proxy\";\n * export const config = { matcher: [\"/((?!_next|favicon.ico|api/).*)\"] };\n * ```\n *\n * @example Custom options\n * ```ts\n * // proxy.ts\n * import { createAziridProxy } from \"azirid-react/next/proxy\";\n * export const proxy = createAziridProxy({ protectedRoutes: [\"/dashboard\"] });\n * export const config = { matcher: [\"/((?!_next|favicon.ico|api/).*)\"] };\n * ```\n */\nexport function createAziridProxy(options?: AziridProxyOptions) {\n return createRequestInterceptor(options)\n}\n\n/** Default proxy export for Next.js 16+ (no route protection, only forwards token) */\nexport const aziridProxy = createAziridProxy()\n\n// ─── Middleware (Next.js 14/15 — deprecated in 16) ──────────\n\n/**\n * @deprecated In Next.js 16+, use `createAziridProxy` and `proxy.ts` instead.\n */\nexport function createAziridMiddleware(options?: AziridProxyOptions) {\n return createRequestInterceptor(options)\n}\n\n/**\n * @deprecated In Next.js 16+, use `aziridProxy` and `proxy.ts` instead.\n */\nexport const aziridMiddleware = createAziridMiddleware()\n"]}
@@ -0,0 +1,79 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+
3
+ /**
4
+ * Next.js proxy and middleware utilities for Azirid Access.
5
+ *
6
+ * This entry point requires `next/server` and provides request interception
7
+ * for route protection and token forwarding.
8
+ *
9
+ * @example Next.js 16+ (proxy.ts)
10
+ * ```ts
11
+ * // proxy.ts
12
+ * export { aziridProxy as proxy } from "azirid-react/next/proxy";
13
+ * export const config = { matcher: ["/((?!_next|favicon.ico|api/).*)"] };
14
+ * ```
15
+ *
16
+ * @example Next.js 16+ with custom options
17
+ * ```ts
18
+ * // proxy.ts
19
+ * import { createAziridProxy } from "azirid-react/next/proxy";
20
+ * export const proxy = createAziridProxy({ protectedRoutes: ["/dashboard"] });
21
+ * export const config = { matcher: ["/((?!_next|favicon.ico|api/).*)"] };
22
+ * ```
23
+ *
24
+ * @example Next.js 14/15 (middleware.ts — deprecated in Next.js 16)
25
+ * ```ts
26
+ * // middleware.ts
27
+ * export { aziridMiddleware as default } from "azirid-react/next/proxy";
28
+ * export const config = { matcher: ["/((?!_next|favicon.ico|api/).*)"] };
29
+ * ```
30
+ *
31
+ * @packageDocumentation
32
+ */
33
+
34
+ interface AziridProxyOptions {
35
+ /** Cookie name (default: "__session") */
36
+ cookieName?: string;
37
+ /** Routes that require authentication (glob patterns via startsWith) */
38
+ protectedRoutes?: string[];
39
+ /** Route to redirect to when not authenticated (default: "/login") */
40
+ loginUrl?: string;
41
+ /** Routes that are always public (default: ["/login", "/signup"]) */
42
+ publicRoutes?: string[];
43
+ }
44
+ /** @deprecated Use `AziridProxyOptions` instead */
45
+ type AziridMiddlewareOptions = AziridProxyOptions;
46
+ /**
47
+ * Create a customized Azirid proxy for Next.js 16+.
48
+ *
49
+ * In Next.js 16, `middleware.ts` is renamed to `proxy.ts` and the
50
+ * exported function must be named `proxy`.
51
+ *
52
+ * @example Default (one line)
53
+ * ```ts
54
+ * // proxy.ts
55
+ * export { aziridProxy as proxy } from "azirid-react/next/proxy";
56
+ * export const config = { matcher: ["/((?!_next|favicon.ico|api/).*)"] };
57
+ * ```
58
+ *
59
+ * @example Custom options
60
+ * ```ts
61
+ * // proxy.ts
62
+ * import { createAziridProxy } from "azirid-react/next/proxy";
63
+ * export const proxy = createAziridProxy({ protectedRoutes: ["/dashboard"] });
64
+ * export const config = { matcher: ["/((?!_next|favicon.ico|api/).*)"] };
65
+ * ```
66
+ */
67
+ declare function createAziridProxy(options?: AziridProxyOptions): (request: NextRequest) => NextResponse;
68
+ /** Default proxy export for Next.js 16+ (no route protection, only forwards token) */
69
+ declare const aziridProxy: (request: NextRequest) => NextResponse;
70
+ /**
71
+ * @deprecated In Next.js 16+, use `createAziridProxy` and `proxy.ts` instead.
72
+ */
73
+ declare function createAziridMiddleware(options?: AziridProxyOptions): (request: NextRequest) => NextResponse;
74
+ /**
75
+ * @deprecated In Next.js 16+, use `aziridProxy` and `proxy.ts` instead.
76
+ */
77
+ declare const aziridMiddleware: (request: NextRequest) => NextResponse;
78
+
79
+ export { type AziridMiddlewareOptions, type AziridProxyOptions, aziridMiddleware, aziridProxy, createAziridMiddleware, createAziridProxy };