@inai-dev/nextjs 0.1.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 ADDED
@@ -0,0 +1,80 @@
1
+ # @inai-dev/nextjs
2
+
3
+ Full Next.js integration for InAI Auth. Includes middleware, server-side helpers, API route handlers, and re-exports all React hooks/components.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @inai-dev/nextjs
9
+ ```
10
+
11
+ ## Setup
12
+
13
+ ### 1. Environment Variables
14
+
15
+ ```env
16
+ NEXT_PUBLIC_INAI_PUBLISHABLE_KEY=pk_live_...
17
+ INAI_SECRET_KEY=sk_live_...
18
+ ```
19
+
20
+ ### 2. Middleware
21
+
22
+ ```ts
23
+ // middleware.ts
24
+ import { authMiddleware } from "@inai-dev/nextjs/middleware";
25
+
26
+ export default authMiddleware({
27
+ publishableKey: process.env.NEXT_PUBLIC_INAI_PUBLISHABLE_KEY!,
28
+ publicRoutes: ["/", "/about", "/sign-in"],
29
+ });
30
+
31
+ export const config = { matcher: ["/((?!_next|static|favicon.ico).*)"] };
32
+ ```
33
+
34
+ ### 3. Provider
35
+
36
+ ```tsx
37
+ // app/layout.tsx
38
+ import { InAIProvider } from "@inai-dev/nextjs";
39
+
40
+ export default function RootLayout({ children }) {
41
+ return <InAIProvider>{children}</InAIProvider>;
42
+ }
43
+ ```
44
+
45
+ ### 4. Server-Side Auth
46
+
47
+ ```ts
48
+ // app/dashboard/page.tsx
49
+ import { auth } from "@inai-dev/nextjs/server";
50
+
51
+ export default async function Dashboard() {
52
+ const session = await auth();
53
+ if (!session) redirect("/sign-in");
54
+ return <p>Welcome {session.user.email}</p>;
55
+ }
56
+ ```
57
+
58
+ ### 5. API Route Handlers
59
+
60
+ ```ts
61
+ // app/api/auth/[...inai]/route.ts
62
+ import { handleAuthRoutes } from "@inai-dev/nextjs";
63
+ export const { GET, POST } = handleAuthRoutes();
64
+ ```
65
+
66
+ ## Exports
67
+
68
+ - `@inai-dev/nextjs` — Provider, React hooks, API route handler
69
+ - `@inai-dev/nextjs/server` — `auth()`, `currentUser()`, server-side helpers
70
+ - `@inai-dev/nextjs/middleware` — `authMiddleware()`
71
+
72
+ ## Documentation
73
+
74
+ - [Getting Started](https://github.com/inai-dev/sdk/blob/main/docs/getting-started.md)
75
+ - [Next.js Integration](https://github.com/inai-dev/sdk/blob/main/docs/nextjs-integration.md)
76
+ - [API Reference](https://github.com/inai-dev/sdk/blob/main/docs/api-reference.md)
77
+
78
+ ## License
79
+
80
+ [MIT](../../LICENSE)
package/dist/index.cjs ADDED
@@ -0,0 +1,65 @@
1
+ "use client";
2
+ "use strict";
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __export = (target, all) => {
8
+ for (var name in all)
9
+ __defProp(target, name, { get: all[name], enumerable: true });
10
+ };
11
+ var __copyProps = (to, from, except, desc) => {
12
+ if (from && typeof from === "object" || typeof from === "function") {
13
+ for (let key of __getOwnPropNames(from))
14
+ if (!__hasOwnProp.call(to, key) && key !== except)
15
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
16
+ }
17
+ return to;
18
+ };
19
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
20
+
21
+ // src/index.ts
22
+ var src_exports = {};
23
+ __export(src_exports, {
24
+ COOKIE_AUTH_SESSION: () => import_shared.COOKIE_AUTH_SESSION,
25
+ COOKIE_AUTH_TOKEN: () => import_shared.COOKIE_AUTH_TOKEN,
26
+ COOKIE_REFRESH_TOKEN: () => import_shared.COOKIE_REFRESH_TOKEN,
27
+ InAIAuthProvider: () => import_react.InAIAuthProvider,
28
+ OrganizationSwitcher: () => import_react.OrganizationSwitcher,
29
+ PermissionGate: () => import_react.PermissionGate,
30
+ Protect: () => import_react.Protect,
31
+ SignIn: () => import_react.SignIn,
32
+ SignedIn: () => import_react.SignedIn,
33
+ SignedOut: () => import_react.SignedOut,
34
+ UserButton: () => import_react.UserButton,
35
+ useAuth: () => import_react.useAuth,
36
+ useOrganization: () => import_react.useOrganization,
37
+ useSession: () => import_react.useSession,
38
+ useSignIn: () => import_react.useSignIn,
39
+ useSignUp: () => import_react.useSignUp,
40
+ useUser: () => import_react.useUser
41
+ });
42
+ module.exports = __toCommonJS(src_exports);
43
+ var import_react = require("@inai-dev/react");
44
+ var import_shared = require("@inai-dev/shared");
45
+ // Annotate the CommonJS export names for ESM import in node:
46
+ 0 && (module.exports = {
47
+ COOKIE_AUTH_SESSION,
48
+ COOKIE_AUTH_TOKEN,
49
+ COOKIE_REFRESH_TOKEN,
50
+ InAIAuthProvider,
51
+ OrganizationSwitcher,
52
+ PermissionGate,
53
+ Protect,
54
+ SignIn,
55
+ SignedIn,
56
+ SignedOut,
57
+ UserButton,
58
+ useAuth,
59
+ useOrganization,
60
+ useSession,
61
+ useSignIn,
62
+ useSignUp,
63
+ useUser
64
+ });
65
+ //# sourceMappingURL=index.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Re-export all React hooks, components, and providers\nexport {\n InAIAuthProvider,\n useAuth,\n useUser,\n useSession,\n useOrganization,\n useSignIn,\n useSignUp,\n Protect,\n SignedIn,\n SignedOut,\n PermissionGate,\n UserButton,\n SignIn,\n OrganizationSwitcher,\n} from \"@inai-dev/react\";\n\n// Cookie constants\nexport {\n COOKIE_AUTH_TOKEN,\n COOKIE_REFRESH_TOKEN,\n COOKIE_AUTH_SESSION,\n} from \"@inai-dev/shared\";\n\n// Re-export types\nexport type {\n AuthObject,\n ServerAuthObject,\n ProtectedAuthObject,\n UserResource,\n SessionResource,\n OrganizationResource,\n InAIAuthConfig,\n InAIAuthErrorBody,\n SignInResult,\n SignUpResult,\n} from \"@inai-dev/types\";\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AACA,mBAeO;AAGP,oBAIO;","names":[]}
@@ -0,0 +1,3 @@
1
+ export { InAIAuthProvider, OrganizationSwitcher, PermissionGate, Protect, SignIn, SignedIn, SignedOut, UserButton, useAuth, useOrganization, useSession, useSignIn, useSignUp, useUser } from '@inai-dev/react';
2
+ export { COOKIE_AUTH_SESSION, COOKIE_AUTH_TOKEN, COOKIE_REFRESH_TOKEN } from '@inai-dev/shared';
3
+ export { AuthObject, InAIAuthConfig, InAIAuthErrorBody, OrganizationResource, ProtectedAuthObject, ServerAuthObject, SessionResource, SignInResult, SignUpResult, UserResource } from '@inai-dev/types';
@@ -0,0 +1,3 @@
1
+ export { InAIAuthProvider, OrganizationSwitcher, PermissionGate, Protect, SignIn, SignedIn, SignedOut, UserButton, useAuth, useOrganization, useSession, useSignIn, useSignUp, useUser } from '@inai-dev/react';
2
+ export { COOKIE_AUTH_SESSION, COOKIE_AUTH_TOKEN, COOKIE_REFRESH_TOKEN } from '@inai-dev/shared';
3
+ export { AuthObject, InAIAuthConfig, InAIAuthErrorBody, OrganizationResource, ProtectedAuthObject, ServerAuthObject, SessionResource, SignInResult, SignUpResult, UserResource } from '@inai-dev/types';
package/dist/index.js ADDED
@@ -0,0 +1,44 @@
1
+ "use client";
2
+
3
+ // src/index.ts
4
+ import {
5
+ InAIAuthProvider,
6
+ useAuth,
7
+ useUser,
8
+ useSession,
9
+ useOrganization,
10
+ useSignIn,
11
+ useSignUp,
12
+ Protect,
13
+ SignedIn,
14
+ SignedOut,
15
+ PermissionGate,
16
+ UserButton,
17
+ SignIn,
18
+ OrganizationSwitcher
19
+ } from "@inai-dev/react";
20
+ import {
21
+ COOKIE_AUTH_TOKEN,
22
+ COOKIE_REFRESH_TOKEN,
23
+ COOKIE_AUTH_SESSION
24
+ } from "@inai-dev/shared";
25
+ export {
26
+ COOKIE_AUTH_SESSION,
27
+ COOKIE_AUTH_TOKEN,
28
+ COOKIE_REFRESH_TOKEN,
29
+ InAIAuthProvider,
30
+ OrganizationSwitcher,
31
+ PermissionGate,
32
+ Protect,
33
+ SignIn,
34
+ SignedIn,
35
+ SignedOut,
36
+ UserButton,
37
+ useAuth,
38
+ useOrganization,
39
+ useSession,
40
+ useSignIn,
41
+ useSignUp,
42
+ useUser
43
+ };
44
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/index.ts"],"sourcesContent":["// Re-export all React hooks, components, and providers\nexport {\n InAIAuthProvider,\n useAuth,\n useUser,\n useSession,\n useOrganization,\n useSignIn,\n useSignUp,\n Protect,\n SignedIn,\n SignedOut,\n PermissionGate,\n UserButton,\n SignIn,\n OrganizationSwitcher,\n} from \"@inai-dev/react\";\n\n// Cookie constants\nexport {\n COOKIE_AUTH_TOKEN,\n COOKIE_REFRESH_TOKEN,\n COOKIE_AUTH_SESSION,\n} from \"@inai-dev/shared\";\n\n// Re-export types\nexport type {\n AuthObject,\n ServerAuthObject,\n ProtectedAuthObject,\n UserResource,\n SessionResource,\n OrganizationResource,\n InAIAuthConfig,\n InAIAuthErrorBody,\n SignInResult,\n SignUpResult,\n} from \"@inai-dev/types\";\n"],"mappings":";;;AACA;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;AAGP;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,OACK;","names":[]}
@@ -0,0 +1,198 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/middleware.ts
21
+ var middleware_exports = {};
22
+ __export(middleware_exports, {
23
+ createRouteMatcher: () => createRouteMatcher,
24
+ inaiAuthMiddleware: () => inaiAuthMiddleware,
25
+ withInAIAuth: () => withInAIAuth
26
+ });
27
+ module.exports = __toCommonJS(middleware_exports);
28
+ var import_server = require("next/server");
29
+ var import_shared = require("@inai-dev/shared");
30
+ function createRouteMatcher(patterns) {
31
+ const matchers = patterns.map((pattern) => {
32
+ if (pattern instanceof RegExp) return pattern;
33
+ let regexStr = pattern;
34
+ if (regexStr.endsWith("*") && !regexStr.includes("(")) {
35
+ regexStr = regexStr.slice(0, -1) + ".*";
36
+ }
37
+ return new RegExp(`^${regexStr}$`);
38
+ });
39
+ return (req) => {
40
+ const pathname = req.nextUrl.pathname;
41
+ return matchers.some((m) => m.test(pathname));
42
+ };
43
+ }
44
+ function matchesRoute(pathname, patterns) {
45
+ return patterns.some((pattern) => {
46
+ if (pattern.endsWith("*")) {
47
+ return pathname.startsWith(pattern.slice(0, -1));
48
+ }
49
+ return pathname === pattern;
50
+ });
51
+ }
52
+ function isPublicRoute(req, publicRoutes, builtinPublic) {
53
+ const pathname = req.nextUrl.pathname;
54
+ if (matchesRoute(pathname, builtinPublic)) return true;
55
+ if (typeof publicRoutes === "function") return publicRoutes(req);
56
+ return matchesRoute(pathname, publicRoutes);
57
+ }
58
+ function buildAuthObject(token, claims) {
59
+ const roles = claims.roles ?? [];
60
+ const permissions = claims.permissions ?? [];
61
+ return {
62
+ userId: claims.sub,
63
+ tenantId: claims.tenant_id,
64
+ appId: claims.app_id ?? null,
65
+ envId: claims.env_id ?? null,
66
+ orgId: claims.org_id ?? null,
67
+ orgRole: claims.org_role ?? null,
68
+ sessionId: null,
69
+ getToken: async () => token,
70
+ has: (params) => {
71
+ if (params.role && roles.includes(params.role)) return true;
72
+ if (params.permission && permissions.includes(params.permission))
73
+ return true;
74
+ return false;
75
+ }
76
+ };
77
+ }
78
+ async function runAuthCheck(req, signInUrl) {
79
+ const { pathname } = req.nextUrl;
80
+ const token = req.cookies.get(import_shared.COOKIE_AUTH_TOKEN)?.value;
81
+ if (!token || (0, import_shared.isTokenExpired)(token)) {
82
+ const refreshToken = req.cookies.get(import_shared.COOKIE_REFRESH_TOKEN)?.value;
83
+ if (refreshToken) {
84
+ try {
85
+ const refreshUrl = new URL("/api/auth/refresh", req.url);
86
+ const refreshRes = await fetch(refreshUrl.toString(), {
87
+ method: "POST",
88
+ headers: {
89
+ "Content-Type": "application/json",
90
+ Cookie: req.headers.get("cookie") ?? ""
91
+ }
92
+ });
93
+ if (refreshRes.ok) {
94
+ const response2 = import_server.NextResponse.next();
95
+ const setCookies = refreshRes.headers.getSetCookie?.() ?? [];
96
+ for (const cookie of setCookies) {
97
+ response2.headers.append("Set-Cookie", cookie);
98
+ }
99
+ return { authObj: null, response: response2 };
100
+ }
101
+ } catch {
102
+ }
103
+ }
104
+ const response = import_server.NextResponse.redirect(
105
+ new URL(
106
+ `${signInUrl}?returnTo=${encodeURIComponent(pathname)}`,
107
+ req.url
108
+ )
109
+ );
110
+ response.cookies.set(import_shared.COOKIE_AUTH_TOKEN, "", { path: "/", maxAge: 0 });
111
+ response.cookies.set(import_shared.COOKIE_REFRESH_TOKEN, "", {
112
+ path: "/api/auth",
113
+ maxAge: 0
114
+ });
115
+ response.cookies.set(import_shared.COOKIE_AUTH_SESSION, "", { path: "/", maxAge: 0 });
116
+ return { authObj: null, response };
117
+ }
118
+ const claims = (0, import_shared.getClaimsFromToken)(token);
119
+ if (!claims) {
120
+ return {
121
+ authObj: null,
122
+ response: import_server.NextResponse.redirect(new URL(signInUrl, req.url))
123
+ };
124
+ }
125
+ return { authObj: buildAuthObject(token, claims) };
126
+ }
127
+ function inaiAuthMiddleware(config = {}) {
128
+ const {
129
+ publicRoutes = [],
130
+ signInUrl = "/login",
131
+ beforeAuth,
132
+ afterAuth
133
+ } = config;
134
+ const builtinPublic = ["/_next/*", "/favicon.ico", "/api/*", signInUrl];
135
+ return async function middleware(req) {
136
+ if (beforeAuth) {
137
+ const result = beforeAuth(req);
138
+ if (result) return result;
139
+ }
140
+ if (isPublicRoute(req, publicRoutes, builtinPublic)) {
141
+ return import_server.NextResponse.next();
142
+ }
143
+ const { authObj, response } = await runAuthCheck(req, signInUrl);
144
+ if (response) return response;
145
+ if (!authObj)
146
+ return import_server.NextResponse.redirect(new URL(signInUrl, req.url));
147
+ if (afterAuth) {
148
+ const result = afterAuth(authObj, req);
149
+ if (result) return result;
150
+ }
151
+ return import_server.NextResponse.next();
152
+ };
153
+ }
154
+ function withInAIAuth(wrappedMiddleware, config = {}) {
155
+ const {
156
+ publicRoutes = [],
157
+ signInUrl = "/login",
158
+ beforeAuth,
159
+ afterAuth
160
+ } = config;
161
+ const builtinPublic = ["/_next/*", "/favicon.ico", "/api/*", signInUrl];
162
+ return async function middleware(req) {
163
+ if (beforeAuth) {
164
+ const result = beforeAuth(req);
165
+ if (result) return result;
166
+ }
167
+ const isPublic = isPublicRoute(req, publicRoutes, builtinPublic);
168
+ if (!isPublic) {
169
+ const { authObj, response } = await runAuthCheck(req, signInUrl);
170
+ if (response) return response;
171
+ if (!authObj)
172
+ return import_server.NextResponse.redirect(new URL(signInUrl, req.url));
173
+ if (afterAuth) {
174
+ const result = afterAuth(authObj, req);
175
+ if (result) return result;
176
+ }
177
+ const authHeader = JSON.stringify({
178
+ userId: authObj.userId,
179
+ tenantId: authObj.tenantId,
180
+ appId: authObj.appId,
181
+ envId: authObj.envId,
182
+ orgId: authObj.orgId,
183
+ orgRole: authObj.orgRole
184
+ });
185
+ req.headers.set("x-inai-auth", authHeader);
186
+ }
187
+ const wrappedResponse = await wrappedMiddleware(req);
188
+ if (wrappedResponse instanceof import_server.NextResponse) return wrappedResponse;
189
+ return new import_server.NextResponse(wrappedResponse.body, wrappedResponse);
190
+ };
191
+ }
192
+ // Annotate the CommonJS export names for ESM import in node:
193
+ 0 && (module.exports = {
194
+ createRouteMatcher,
195
+ inaiAuthMiddleware,
196
+ withInAIAuth
197
+ });
198
+ //# sourceMappingURL=middleware.cjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middleware.ts"],"sourcesContent":["import { NextResponse } from \"next/server\";\nimport type { NextRequest } from \"next/server\";\nimport type { AuthObject } from \"@inai-dev/types\";\nimport {\n COOKIE_AUTH_TOKEN,\n COOKIE_AUTH_SESSION,\n COOKIE_REFRESH_TOKEN,\n getClaimsFromToken,\n isTokenExpired,\n} from \"@inai-dev/shared\";\n\nexport interface InAIMiddlewareConfig {\n publicRoutes?: string[] | ((req: NextRequest) => boolean);\n signInUrl?: string;\n beforeAuth?: (req: NextRequest) => NextResponse | void;\n afterAuth?: (auth: AuthObject, req: NextRequest) => NextResponse | void;\n}\n\nexport function createRouteMatcher(\n patterns: (string | RegExp)[],\n): (req: NextRequest) => boolean {\n const matchers = patterns.map((pattern) => {\n if (pattern instanceof RegExp) return pattern;\n let regexStr = pattern;\n if (regexStr.endsWith(\"*\") && !regexStr.includes(\"(\")) {\n regexStr = regexStr.slice(0, -1) + \".*\";\n }\n return new RegExp(`^${regexStr}$`);\n });\n\n return (req: NextRequest) => {\n const pathname = req.nextUrl.pathname;\n return matchers.some((m) => m.test(pathname));\n };\n}\n\nfunction matchesRoute(pathname: string, patterns: string[]): boolean {\n return patterns.some((pattern) => {\n if (pattern.endsWith(\"*\")) {\n return pathname.startsWith(pattern.slice(0, -1));\n }\n return pathname === pattern;\n });\n}\n\nfunction isPublicRoute(\n req: NextRequest,\n publicRoutes: string[] | ((req: NextRequest) => boolean),\n builtinPublic: string[],\n): boolean {\n const pathname = req.nextUrl.pathname;\n if (matchesRoute(pathname, builtinPublic)) return true;\n if (typeof publicRoutes === \"function\") return publicRoutes(req);\n return matchesRoute(pathname, publicRoutes);\n}\n\nfunction buildAuthObject(\n token: string,\n claims: NonNullable<ReturnType<typeof getClaimsFromToken>>,\n): AuthObject {\n const roles = claims.roles ?? [];\n const permissions = claims.permissions ?? [];\n return {\n userId: claims.sub,\n tenantId: claims.tenant_id,\n appId: claims.app_id ?? null,\n envId: claims.env_id ?? null,\n orgId: claims.org_id ?? null,\n orgRole: claims.org_role ?? null,\n sessionId: null,\n getToken: async () => token,\n has: (params: { role?: string; permission?: string }) => {\n if (params.role && roles.includes(params.role)) return true;\n if (params.permission && permissions.includes(params.permission))\n return true;\n return false;\n },\n };\n}\n\nasync function runAuthCheck(\n req: NextRequest,\n signInUrl: string,\n): Promise<{ authObj: AuthObject | null; response?: NextResponse }> {\n const { pathname } = req.nextUrl;\n const token = req.cookies.get(COOKIE_AUTH_TOKEN)?.value;\n\n if (!token || isTokenExpired(token)) {\n const refreshToken = req.cookies.get(COOKIE_REFRESH_TOKEN)?.value;\n if (refreshToken) {\n try {\n const refreshUrl = new URL(\"/api/auth/refresh\", req.url);\n const refreshRes = await fetch(refreshUrl.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Cookie: req.headers.get(\"cookie\") ?? \"\",\n },\n });\n if (refreshRes.ok) {\n const response = NextResponse.next();\n const setCookies = refreshRes.headers.getSetCookie?.() ?? [];\n for (const cookie of setCookies) {\n response.headers.append(\"Set-Cookie\", cookie);\n }\n return { authObj: null, response };\n }\n } catch {\n // Refresh failed, fall through to redirect\n }\n }\n\n const response = NextResponse.redirect(\n new URL(\n `${signInUrl}?returnTo=${encodeURIComponent(pathname)}`,\n req.url,\n ),\n );\n response.cookies.set(COOKIE_AUTH_TOKEN, \"\", { path: \"/\", maxAge: 0 });\n response.cookies.set(COOKIE_REFRESH_TOKEN, \"\", {\n path: \"/api/auth\",\n maxAge: 0,\n });\n response.cookies.set(COOKIE_AUTH_SESSION, \"\", { path: \"/\", maxAge: 0 });\n return { authObj: null, response };\n }\n\n const claims = getClaimsFromToken(token);\n if (!claims) {\n return {\n authObj: null,\n response: NextResponse.redirect(new URL(signInUrl, req.url)),\n };\n }\n\n return { authObj: buildAuthObject(token, claims) };\n}\n\nexport function inaiAuthMiddleware(config: InAIMiddlewareConfig = {}) {\n const {\n publicRoutes = [],\n signInUrl = \"/login\",\n beforeAuth,\n afterAuth,\n } = config;\n\n const builtinPublic = [\"/_next/*\", \"/favicon.ico\", \"/api/*\", signInUrl];\n\n return async function middleware(\n req: NextRequest,\n ): Promise<NextResponse> {\n if (beforeAuth) {\n const result = beforeAuth(req);\n if (result) return result;\n }\n\n if (isPublicRoute(req, publicRoutes, builtinPublic)) {\n return NextResponse.next();\n }\n\n const { authObj, response } = await runAuthCheck(req, signInUrl);\n if (response) return response;\n if (!authObj)\n return NextResponse.redirect(new URL(signInUrl, req.url));\n\n if (afterAuth) {\n const result = afterAuth(authObj, req);\n if (result) return result;\n }\n\n return NextResponse.next();\n };\n}\n\nexport function withInAIAuth(\n wrappedMiddleware: (\n req: NextRequest,\n ) => NextResponse | Response | Promise<NextResponse | Response>,\n config: InAIMiddlewareConfig = {},\n): (req: NextRequest) => Promise<NextResponse> {\n const {\n publicRoutes = [],\n signInUrl = \"/login\",\n beforeAuth,\n afterAuth,\n } = config;\n\n const builtinPublic = [\"/_next/*\", \"/favicon.ico\", \"/api/*\", signInUrl];\n\n return async function middleware(\n req: NextRequest,\n ): Promise<NextResponse> {\n if (beforeAuth) {\n const result = beforeAuth(req);\n if (result) return result;\n }\n\n const isPublic = isPublicRoute(req, publicRoutes, builtinPublic);\n\n if (!isPublic) {\n const { authObj, response } = await runAuthCheck(req, signInUrl);\n if (response) return response;\n if (!authObj)\n return NextResponse.redirect(new URL(signInUrl, req.url));\n\n if (afterAuth) {\n const result = afterAuth(authObj, req);\n if (result) return result;\n }\n\n const authHeader = JSON.stringify({\n userId: authObj.userId,\n tenantId: authObj.tenantId,\n appId: authObj.appId,\n envId: authObj.envId,\n orgId: authObj.orgId,\n orgRole: authObj.orgRole,\n });\n req.headers.set(\"x-inai-auth\", authHeader);\n }\n\n const wrappedResponse = await wrappedMiddleware(req);\n if (wrappedResponse instanceof NextResponse) return wrappedResponse;\n return new NextResponse(wrappedResponse.body, wrappedResponse);\n };\n}\n"],"mappings":"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","names":["response"]}
@@ -0,0 +1,14 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { AuthObject } from '@inai-dev/types';
3
+
4
+ interface InAIMiddlewareConfig {
5
+ publicRoutes?: string[] | ((req: NextRequest) => boolean);
6
+ signInUrl?: string;
7
+ beforeAuth?: (req: NextRequest) => NextResponse | void;
8
+ afterAuth?: (auth: AuthObject, req: NextRequest) => NextResponse | void;
9
+ }
10
+ declare function createRouteMatcher(patterns: (string | RegExp)[]): (req: NextRequest) => boolean;
11
+ declare function inaiAuthMiddleware(config?: InAIMiddlewareConfig): (req: NextRequest) => Promise<NextResponse>;
12
+ declare function withInAIAuth(wrappedMiddleware: (req: NextRequest) => NextResponse | Response | Promise<NextResponse | Response>, config?: InAIMiddlewareConfig): (req: NextRequest) => Promise<NextResponse>;
13
+
14
+ export { type InAIMiddlewareConfig, createRouteMatcher, inaiAuthMiddleware, withInAIAuth };
@@ -0,0 +1,14 @@
1
+ import { NextRequest, NextResponse } from 'next/server';
2
+ import { AuthObject } from '@inai-dev/types';
3
+
4
+ interface InAIMiddlewareConfig {
5
+ publicRoutes?: string[] | ((req: NextRequest) => boolean);
6
+ signInUrl?: string;
7
+ beforeAuth?: (req: NextRequest) => NextResponse | void;
8
+ afterAuth?: (auth: AuthObject, req: NextRequest) => NextResponse | void;
9
+ }
10
+ declare function createRouteMatcher(patterns: (string | RegExp)[]): (req: NextRequest) => boolean;
11
+ declare function inaiAuthMiddleware(config?: InAIMiddlewareConfig): (req: NextRequest) => Promise<NextResponse>;
12
+ declare function withInAIAuth(wrappedMiddleware: (req: NextRequest) => NextResponse | Response | Promise<NextResponse | Response>, config?: InAIMiddlewareConfig): (req: NextRequest) => Promise<NextResponse>;
13
+
14
+ export { type InAIMiddlewareConfig, createRouteMatcher, inaiAuthMiddleware, withInAIAuth };
@@ -0,0 +1,177 @@
1
+ // src/middleware.ts
2
+ import { NextResponse } from "next/server";
3
+ import {
4
+ COOKIE_AUTH_TOKEN,
5
+ COOKIE_AUTH_SESSION,
6
+ COOKIE_REFRESH_TOKEN,
7
+ getClaimsFromToken,
8
+ isTokenExpired
9
+ } from "@inai-dev/shared";
10
+ function createRouteMatcher(patterns) {
11
+ const matchers = patterns.map((pattern) => {
12
+ if (pattern instanceof RegExp) return pattern;
13
+ let regexStr = pattern;
14
+ if (regexStr.endsWith("*") && !regexStr.includes("(")) {
15
+ regexStr = regexStr.slice(0, -1) + ".*";
16
+ }
17
+ return new RegExp(`^${regexStr}$`);
18
+ });
19
+ return (req) => {
20
+ const pathname = req.nextUrl.pathname;
21
+ return matchers.some((m) => m.test(pathname));
22
+ };
23
+ }
24
+ function matchesRoute(pathname, patterns) {
25
+ return patterns.some((pattern) => {
26
+ if (pattern.endsWith("*")) {
27
+ return pathname.startsWith(pattern.slice(0, -1));
28
+ }
29
+ return pathname === pattern;
30
+ });
31
+ }
32
+ function isPublicRoute(req, publicRoutes, builtinPublic) {
33
+ const pathname = req.nextUrl.pathname;
34
+ if (matchesRoute(pathname, builtinPublic)) return true;
35
+ if (typeof publicRoutes === "function") return publicRoutes(req);
36
+ return matchesRoute(pathname, publicRoutes);
37
+ }
38
+ function buildAuthObject(token, claims) {
39
+ const roles = claims.roles ?? [];
40
+ const permissions = claims.permissions ?? [];
41
+ return {
42
+ userId: claims.sub,
43
+ tenantId: claims.tenant_id,
44
+ appId: claims.app_id ?? null,
45
+ envId: claims.env_id ?? null,
46
+ orgId: claims.org_id ?? null,
47
+ orgRole: claims.org_role ?? null,
48
+ sessionId: null,
49
+ getToken: async () => token,
50
+ has: (params) => {
51
+ if (params.role && roles.includes(params.role)) return true;
52
+ if (params.permission && permissions.includes(params.permission))
53
+ return true;
54
+ return false;
55
+ }
56
+ };
57
+ }
58
+ async function runAuthCheck(req, signInUrl) {
59
+ const { pathname } = req.nextUrl;
60
+ const token = req.cookies.get(COOKIE_AUTH_TOKEN)?.value;
61
+ if (!token || isTokenExpired(token)) {
62
+ const refreshToken = req.cookies.get(COOKIE_REFRESH_TOKEN)?.value;
63
+ if (refreshToken) {
64
+ try {
65
+ const refreshUrl = new URL("/api/auth/refresh", req.url);
66
+ const refreshRes = await fetch(refreshUrl.toString(), {
67
+ method: "POST",
68
+ headers: {
69
+ "Content-Type": "application/json",
70
+ Cookie: req.headers.get("cookie") ?? ""
71
+ }
72
+ });
73
+ if (refreshRes.ok) {
74
+ const response2 = NextResponse.next();
75
+ const setCookies = refreshRes.headers.getSetCookie?.() ?? [];
76
+ for (const cookie of setCookies) {
77
+ response2.headers.append("Set-Cookie", cookie);
78
+ }
79
+ return { authObj: null, response: response2 };
80
+ }
81
+ } catch {
82
+ }
83
+ }
84
+ const response = NextResponse.redirect(
85
+ new URL(
86
+ `${signInUrl}?returnTo=${encodeURIComponent(pathname)}`,
87
+ req.url
88
+ )
89
+ );
90
+ response.cookies.set(COOKIE_AUTH_TOKEN, "", { path: "/", maxAge: 0 });
91
+ response.cookies.set(COOKIE_REFRESH_TOKEN, "", {
92
+ path: "/api/auth",
93
+ maxAge: 0
94
+ });
95
+ response.cookies.set(COOKIE_AUTH_SESSION, "", { path: "/", maxAge: 0 });
96
+ return { authObj: null, response };
97
+ }
98
+ const claims = getClaimsFromToken(token);
99
+ if (!claims) {
100
+ return {
101
+ authObj: null,
102
+ response: NextResponse.redirect(new URL(signInUrl, req.url))
103
+ };
104
+ }
105
+ return { authObj: buildAuthObject(token, claims) };
106
+ }
107
+ function inaiAuthMiddleware(config = {}) {
108
+ const {
109
+ publicRoutes = [],
110
+ signInUrl = "/login",
111
+ beforeAuth,
112
+ afterAuth
113
+ } = config;
114
+ const builtinPublic = ["/_next/*", "/favicon.ico", "/api/*", signInUrl];
115
+ return async function middleware(req) {
116
+ if (beforeAuth) {
117
+ const result = beforeAuth(req);
118
+ if (result) return result;
119
+ }
120
+ if (isPublicRoute(req, publicRoutes, builtinPublic)) {
121
+ return NextResponse.next();
122
+ }
123
+ const { authObj, response } = await runAuthCheck(req, signInUrl);
124
+ if (response) return response;
125
+ if (!authObj)
126
+ return NextResponse.redirect(new URL(signInUrl, req.url));
127
+ if (afterAuth) {
128
+ const result = afterAuth(authObj, req);
129
+ if (result) return result;
130
+ }
131
+ return NextResponse.next();
132
+ };
133
+ }
134
+ function withInAIAuth(wrappedMiddleware, config = {}) {
135
+ const {
136
+ publicRoutes = [],
137
+ signInUrl = "/login",
138
+ beforeAuth,
139
+ afterAuth
140
+ } = config;
141
+ const builtinPublic = ["/_next/*", "/favicon.ico", "/api/*", signInUrl];
142
+ return async function middleware(req) {
143
+ if (beforeAuth) {
144
+ const result = beforeAuth(req);
145
+ if (result) return result;
146
+ }
147
+ const isPublic = isPublicRoute(req, publicRoutes, builtinPublic);
148
+ if (!isPublic) {
149
+ const { authObj, response } = await runAuthCheck(req, signInUrl);
150
+ if (response) return response;
151
+ if (!authObj)
152
+ return NextResponse.redirect(new URL(signInUrl, req.url));
153
+ if (afterAuth) {
154
+ const result = afterAuth(authObj, req);
155
+ if (result) return result;
156
+ }
157
+ const authHeader = JSON.stringify({
158
+ userId: authObj.userId,
159
+ tenantId: authObj.tenantId,
160
+ appId: authObj.appId,
161
+ envId: authObj.envId,
162
+ orgId: authObj.orgId,
163
+ orgRole: authObj.orgRole
164
+ });
165
+ req.headers.set("x-inai-auth", authHeader);
166
+ }
167
+ const wrappedResponse = await wrappedMiddleware(req);
168
+ if (wrappedResponse instanceof NextResponse) return wrappedResponse;
169
+ return new NextResponse(wrappedResponse.body, wrappedResponse);
170
+ };
171
+ }
172
+ export {
173
+ createRouteMatcher,
174
+ inaiAuthMiddleware,
175
+ withInAIAuth
176
+ };
177
+ //# sourceMappingURL=middleware.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/middleware.ts"],"sourcesContent":["import { NextResponse } from \"next/server\";\nimport type { NextRequest } from \"next/server\";\nimport type { AuthObject } from \"@inai-dev/types\";\nimport {\n COOKIE_AUTH_TOKEN,\n COOKIE_AUTH_SESSION,\n COOKIE_REFRESH_TOKEN,\n getClaimsFromToken,\n isTokenExpired,\n} from \"@inai-dev/shared\";\n\nexport interface InAIMiddlewareConfig {\n publicRoutes?: string[] | ((req: NextRequest) => boolean);\n signInUrl?: string;\n beforeAuth?: (req: NextRequest) => NextResponse | void;\n afterAuth?: (auth: AuthObject, req: NextRequest) => NextResponse | void;\n}\n\nexport function createRouteMatcher(\n patterns: (string | RegExp)[],\n): (req: NextRequest) => boolean {\n const matchers = patterns.map((pattern) => {\n if (pattern instanceof RegExp) return pattern;\n let regexStr = pattern;\n if (regexStr.endsWith(\"*\") && !regexStr.includes(\"(\")) {\n regexStr = regexStr.slice(0, -1) + \".*\";\n }\n return new RegExp(`^${regexStr}$`);\n });\n\n return (req: NextRequest) => {\n const pathname = req.nextUrl.pathname;\n return matchers.some((m) => m.test(pathname));\n };\n}\n\nfunction matchesRoute(pathname: string, patterns: string[]): boolean {\n return patterns.some((pattern) => {\n if (pattern.endsWith(\"*\")) {\n return pathname.startsWith(pattern.slice(0, -1));\n }\n return pathname === pattern;\n });\n}\n\nfunction isPublicRoute(\n req: NextRequest,\n publicRoutes: string[] | ((req: NextRequest) => boolean),\n builtinPublic: string[],\n): boolean {\n const pathname = req.nextUrl.pathname;\n if (matchesRoute(pathname, builtinPublic)) return true;\n if (typeof publicRoutes === \"function\") return publicRoutes(req);\n return matchesRoute(pathname, publicRoutes);\n}\n\nfunction buildAuthObject(\n token: string,\n claims: NonNullable<ReturnType<typeof getClaimsFromToken>>,\n): AuthObject {\n const roles = claims.roles ?? [];\n const permissions = claims.permissions ?? [];\n return {\n userId: claims.sub,\n tenantId: claims.tenant_id,\n appId: claims.app_id ?? null,\n envId: claims.env_id ?? null,\n orgId: claims.org_id ?? null,\n orgRole: claims.org_role ?? null,\n sessionId: null,\n getToken: async () => token,\n has: (params: { role?: string; permission?: string }) => {\n if (params.role && roles.includes(params.role)) return true;\n if (params.permission && permissions.includes(params.permission))\n return true;\n return false;\n },\n };\n}\n\nasync function runAuthCheck(\n req: NextRequest,\n signInUrl: string,\n): Promise<{ authObj: AuthObject | null; response?: NextResponse }> {\n const { pathname } = req.nextUrl;\n const token = req.cookies.get(COOKIE_AUTH_TOKEN)?.value;\n\n if (!token || isTokenExpired(token)) {\n const refreshToken = req.cookies.get(COOKIE_REFRESH_TOKEN)?.value;\n if (refreshToken) {\n try {\n const refreshUrl = new URL(\"/api/auth/refresh\", req.url);\n const refreshRes = await fetch(refreshUrl.toString(), {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n Cookie: req.headers.get(\"cookie\") ?? \"\",\n },\n });\n if (refreshRes.ok) {\n const response = NextResponse.next();\n const setCookies = refreshRes.headers.getSetCookie?.() ?? [];\n for (const cookie of setCookies) {\n response.headers.append(\"Set-Cookie\", cookie);\n }\n return { authObj: null, response };\n }\n } catch {\n // Refresh failed, fall through to redirect\n }\n }\n\n const response = NextResponse.redirect(\n new URL(\n `${signInUrl}?returnTo=${encodeURIComponent(pathname)}`,\n req.url,\n ),\n );\n response.cookies.set(COOKIE_AUTH_TOKEN, \"\", { path: \"/\", maxAge: 0 });\n response.cookies.set(COOKIE_REFRESH_TOKEN, \"\", {\n path: \"/api/auth\",\n maxAge: 0,\n });\n response.cookies.set(COOKIE_AUTH_SESSION, \"\", { path: \"/\", maxAge: 0 });\n return { authObj: null, response };\n }\n\n const claims = getClaimsFromToken(token);\n if (!claims) {\n return {\n authObj: null,\n response: NextResponse.redirect(new URL(signInUrl, req.url)),\n };\n }\n\n return { authObj: buildAuthObject(token, claims) };\n}\n\nexport function inaiAuthMiddleware(config: InAIMiddlewareConfig = {}) {\n const {\n publicRoutes = [],\n signInUrl = \"/login\",\n beforeAuth,\n afterAuth,\n } = config;\n\n const builtinPublic = [\"/_next/*\", \"/favicon.ico\", \"/api/*\", signInUrl];\n\n return async function middleware(\n req: NextRequest,\n ): Promise<NextResponse> {\n if (beforeAuth) {\n const result = beforeAuth(req);\n if (result) return result;\n }\n\n if (isPublicRoute(req, publicRoutes, builtinPublic)) {\n return NextResponse.next();\n }\n\n const { authObj, response } = await runAuthCheck(req, signInUrl);\n if (response) return response;\n if (!authObj)\n return NextResponse.redirect(new URL(signInUrl, req.url));\n\n if (afterAuth) {\n const result = afterAuth(authObj, req);\n if (result) return result;\n }\n\n return NextResponse.next();\n };\n}\n\nexport function withInAIAuth(\n wrappedMiddleware: (\n req: NextRequest,\n ) => NextResponse | Response | Promise<NextResponse | Response>,\n config: InAIMiddlewareConfig = {},\n): (req: NextRequest) => Promise<NextResponse> {\n const {\n publicRoutes = [],\n signInUrl = \"/login\",\n beforeAuth,\n afterAuth,\n } = config;\n\n const builtinPublic = [\"/_next/*\", \"/favicon.ico\", \"/api/*\", signInUrl];\n\n return async function middleware(\n req: NextRequest,\n ): Promise<NextResponse> {\n if (beforeAuth) {\n const result = beforeAuth(req);\n if (result) return result;\n }\n\n const isPublic = isPublicRoute(req, publicRoutes, builtinPublic);\n\n if (!isPublic) {\n const { authObj, response } = await runAuthCheck(req, signInUrl);\n if (response) return response;\n if (!authObj)\n return NextResponse.redirect(new URL(signInUrl, req.url));\n\n if (afterAuth) {\n const result = afterAuth(authObj, req);\n if (result) return result;\n }\n\n const authHeader = JSON.stringify({\n userId: authObj.userId,\n tenantId: authObj.tenantId,\n appId: authObj.appId,\n envId: authObj.envId,\n orgId: authObj.orgId,\n orgRole: authObj.orgRole,\n });\n req.headers.set(\"x-inai-auth\", authHeader);\n }\n\n const wrappedResponse = await wrappedMiddleware(req);\n if (wrappedResponse instanceof NextResponse) return wrappedResponse;\n return new NextResponse(wrappedResponse.body, wrappedResponse);\n };\n}\n"],"mappings":"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","names":["response"]}