@basictech/nextjs 0.6.0-beta.5 → 0.6.0-beta.7
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/.turbo/turbo-build.log +17 -11
- package/CHANGELOG.md +19 -0
- package/dist/client.d.mts +1 -0
- package/dist/client.d.ts +1 -0
- package/dist/client.js +46 -0
- package/dist/client.js.map +1 -0
- package/dist/client.mjs +24 -0
- package/dist/client.mjs.map +1 -0
- package/dist/index.d.mts +81 -8
- package/dist/index.d.ts +81 -8
- package/dist/index.js +69 -92
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +65 -81
- package/dist/index.mjs.map +1 -1
- package/package.json +24 -3
- package/readme.md +623 -53
- package/src/client.ts +33 -0
- package/src/{componets.tsx → components.tsx} +8 -8
- package/src/index.ts +35 -11
- package/src/middleware.ts +186 -0
- package/tsup.config.ts +1 -1
- package/src/sync.ts +0 -75
package/dist/index.mjs
CHANGED
|
@@ -1,85 +1,69 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
import { jsx, jsxs } from "react/jsx-runtime";
|
|
11
|
-
var LoginButton = () => {
|
|
12
|
-
return /* @__PURE__ */ jsxs(Popover.Root, { children: [
|
|
13
|
-
/* @__PURE__ */ jsx(Popover.Trigger, { asChild: true, children: /* @__PURE__ */ jsxs(Avatar.Root, { style: avatarContainerStyle, children: [
|
|
14
|
-
/* @__PURE__ */ jsx(
|
|
15
|
-
Avatar.Image,
|
|
16
|
-
{
|
|
17
|
-
src: "https://via.placeholder.com/150",
|
|
18
|
-
alt: "User Avatar",
|
|
19
|
-
style: avatarImageStyle
|
|
20
|
-
}
|
|
21
|
-
),
|
|
22
|
-
/* @__PURE__ */ jsx(Avatar.Fallback, { delayMs: 600, style: avatarFallbackStyle, children: "U" })
|
|
23
|
-
] }) }),
|
|
24
|
-
/* @__PURE__ */ jsx(Popover.Portal, { children: /* @__PURE__ */ jsxs(Popover.Content, { style: popoverContentStyle, sideOffset: 10, children: [
|
|
25
|
-
/* @__PURE__ */ jsx("p", { style: { marginBottom: "10px" }, children: "Hello, User!" }),
|
|
26
|
-
/* @__PURE__ */ jsx("button", { style: buttonStyle, children: "Logout" }),
|
|
27
|
-
/* @__PURE__ */ jsx(Popover.Arrow, { style: popoverArrowStyle })
|
|
28
|
-
] }) })
|
|
29
|
-
] });
|
|
1
|
+
// src/middleware.ts
|
|
2
|
+
import { NextResponse } from "next/server";
|
|
3
|
+
var DEFAULT_CONFIG = {
|
|
4
|
+
protectedRoutes: [],
|
|
5
|
+
publicRoutes: ["/login", "/signup", "/auth/*"],
|
|
6
|
+
signInUrl: "/login",
|
|
7
|
+
afterSignInUrl: "/",
|
|
8
|
+
tokenCookieName: "basic_access_token",
|
|
9
|
+
fullTokenCookieName: "basic_token"
|
|
30
10
|
};
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
};
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
};
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
11
|
+
function matchesPattern(path, patterns) {
|
|
12
|
+
return patterns.some((pattern) => {
|
|
13
|
+
const regexPattern = pattern.replace(/\*/g, ".*").replace(/\//g, "\\/");
|
|
14
|
+
const regex = new RegExp(`^${regexPattern}$`);
|
|
15
|
+
return regex.test(path);
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function hasValidToken(request, config) {
|
|
19
|
+
const token = request.cookies.get(config.tokenCookieName)?.value;
|
|
20
|
+
if (!token) {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return token.length > 0;
|
|
24
|
+
}
|
|
25
|
+
function getAuthFromRequest(request, config) {
|
|
26
|
+
const mergedConfig = { ...DEFAULT_CONFIG, ...config };
|
|
27
|
+
const token = request.cookies.get(mergedConfig.tokenCookieName)?.value || null;
|
|
28
|
+
return {
|
|
29
|
+
isAuthenticated: !!token && token.length > 0,
|
|
30
|
+
token
|
|
31
|
+
};
|
|
32
|
+
}
|
|
33
|
+
function createBasicMiddleware(config) {
|
|
34
|
+
const mergedConfig = { ...DEFAULT_CONFIG, ...config };
|
|
35
|
+
return function middleware(request) {
|
|
36
|
+
const { pathname } = request.nextUrl;
|
|
37
|
+
if (pathname.startsWith("/_next") || pathname.startsWith("/api/_next") || pathname.includes(".")) {
|
|
38
|
+
return NextResponse.next();
|
|
39
|
+
}
|
|
40
|
+
if (matchesPattern(pathname, mergedConfig.publicRoutes)) {
|
|
41
|
+
return NextResponse.next();
|
|
42
|
+
}
|
|
43
|
+
const isProtectedRoute = mergedConfig.protectedRoutes.length === 0 ? true : matchesPattern(pathname, mergedConfig.protectedRoutes);
|
|
44
|
+
if (!isProtectedRoute) {
|
|
45
|
+
return NextResponse.next();
|
|
46
|
+
}
|
|
47
|
+
const isAuthenticated = hasValidToken(request, mergedConfig);
|
|
48
|
+
if (!isAuthenticated) {
|
|
49
|
+
const signInUrl = new URL(mergedConfig.signInUrl, request.url);
|
|
50
|
+
signInUrl.searchParams.set("returnUrl", pathname);
|
|
51
|
+
return NextResponse.redirect(signInUrl);
|
|
52
|
+
}
|
|
53
|
+
return NextResponse.next();
|
|
54
|
+
};
|
|
55
|
+
}
|
|
56
|
+
function withBasicAuth(request) {
|
|
57
|
+
return createBasicMiddleware()(request);
|
|
58
|
+
}
|
|
59
|
+
function getReturnUrl(request, defaultUrl = "/") {
|
|
60
|
+
const returnUrl = request.nextUrl.searchParams.get("returnUrl");
|
|
61
|
+
return returnUrl || defaultUrl;
|
|
62
|
+
}
|
|
79
63
|
export {
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
64
|
+
createBasicMiddleware,
|
|
65
|
+
getAuthFromRequest,
|
|
66
|
+
getReturnUrl,
|
|
67
|
+
withBasicAuth
|
|
84
68
|
};
|
|
85
69
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/
|
|
1
|
+
{"version":3,"sources":["../src/middleware.ts"],"sourcesContent":["import { NextRequest, NextResponse } from 'next/server'\n\n/**\n * Configuration options for the Basic auth middleware\n */\nexport interface BasicMiddlewareConfig {\n /**\n * Routes that require authentication\n * Supports glob patterns like '/dashboard/*', '/api/protected/*'\n */\n protectedRoutes?: string[]\n \n /**\n * Routes that are always public (bypass auth check)\n * Useful for login pages, public APIs, etc.\n */\n publicRoutes?: string[]\n \n /**\n * Where to redirect unauthenticated users\n * @default '/login'\n */\n signInUrl?: string\n \n /**\n * Where to redirect after successful sign-in\n * @default '/'\n */\n afterSignInUrl?: string\n \n /**\n * Cookie name for the access token\n * @default 'basic_access_token'\n */\n tokenCookieName?: string\n \n /**\n * Cookie name for the full token object\n * @default 'basic_token'\n */\n fullTokenCookieName?: string\n}\n\nconst DEFAULT_CONFIG: Required<BasicMiddlewareConfig> = {\n protectedRoutes: [],\n publicRoutes: ['/login', '/signup', '/auth/*'],\n signInUrl: '/login',\n afterSignInUrl: '/',\n tokenCookieName: 'basic_access_token',\n fullTokenCookieName: 'basic_token'\n}\n\n/**\n * Check if a path matches any of the patterns\n * Supports simple glob patterns with * wildcard\n */\nfunction matchesPattern(path: string, patterns: string[]): boolean {\n return patterns.some(pattern => {\n // Convert glob pattern to regex\n const regexPattern = pattern\n .replace(/\\*/g, '.*') // Replace * with .*\n .replace(/\\//g, '\\\\/') // Escape slashes\n const regex = new RegExp(`^${regexPattern}$`)\n return regex.test(path)\n })\n}\n\n/**\n * Check if the user has a valid token\n */\nfunction hasValidToken(request: NextRequest, config: Required<BasicMiddlewareConfig>): boolean {\n const token = request.cookies.get(config.tokenCookieName)?.value\n \n if (!token) {\n return false\n }\n \n // Basic validation - token exists and is not empty\n // For more thorough validation, you'd decode the JWT and check expiry\n // But that adds latency to every request\n return token.length > 0\n}\n\n/**\n * Get auth info from cookies\n */\nexport function getAuthFromRequest(request: NextRequest, config?: Partial<BasicMiddlewareConfig>): {\n isAuthenticated: boolean\n token: string | null\n} {\n const mergedConfig = { ...DEFAULT_CONFIG, ...config }\n const token = request.cookies.get(mergedConfig.tokenCookieName)?.value || null\n \n return {\n isAuthenticated: !!token && token.length > 0,\n token\n }\n}\n\n/**\n * Create a Basic auth middleware for NextJS\n * \n * @example\n * // In middleware.ts at the root of your NextJS app:\n * import { createBasicMiddleware } from '@basictech/nextjs'\n * \n * export const middleware = createBasicMiddleware({\n * protectedRoutes: ['/dashboard/*', '/settings/*'],\n * publicRoutes: ['/login', '/signup', '/'],\n * signInUrl: '/login'\n * })\n * \n * export const config = {\n * matcher: ['/((?!_next/static|_next/image|favicon.ico).*)']\n * }\n */\nexport function createBasicMiddleware(config?: BasicMiddlewareConfig) {\n const mergedConfig = { ...DEFAULT_CONFIG, ...config }\n \n return function middleware(request: NextRequest): NextResponse {\n const { pathname } = request.nextUrl\n \n // Skip middleware for static files and Next.js internals\n if (\n pathname.startsWith('/_next') ||\n pathname.startsWith('/api/_next') ||\n pathname.includes('.') // Static files like .css, .js, .ico\n ) {\n return NextResponse.next()\n }\n \n // Check if route is explicitly public\n if (matchesPattern(pathname, mergedConfig.publicRoutes)) {\n return NextResponse.next()\n }\n \n // Check if route is protected\n const isProtectedRoute = mergedConfig.protectedRoutes.length === 0 \n ? true // If no protected routes specified, protect everything except public\n : matchesPattern(pathname, mergedConfig.protectedRoutes)\n \n if (!isProtectedRoute) {\n return NextResponse.next()\n }\n \n // Check authentication\n const isAuthenticated = hasValidToken(request, mergedConfig)\n \n if (!isAuthenticated) {\n // Redirect to sign-in page with return URL\n const signInUrl = new URL(mergedConfig.signInUrl, request.url)\n signInUrl.searchParams.set('returnUrl', pathname)\n \n return NextResponse.redirect(signInUrl)\n }\n \n // User is authenticated, allow the request\n return NextResponse.next()\n }\n}\n\n/**\n * Simple auth check middleware - redirects unauthenticated users\n * \n * @example\n * // In middleware.ts\n * import { withBasicAuth } from '@basictech/nextjs'\n * \n * export const middleware = withBasicAuth\n * \n * export const config = {\n * matcher: ['/dashboard/:path*', '/settings/:path*']\n * }\n */\nexport function withBasicAuth(request: NextRequest): NextResponse {\n return createBasicMiddleware()(request)\n}\n\n/**\n * Helper to get the return URL from search params\n */\nexport function getReturnUrl(request: NextRequest, defaultUrl: string = '/'): string {\n const returnUrl = request.nextUrl.searchParams.get('returnUrl')\n return returnUrl || defaultUrl\n}\n\n"],"mappings":";AAAA,SAAsB,oBAAoB;AA2C1C,IAAM,iBAAkD;AAAA,EACtD,iBAAiB,CAAC;AAAA,EAClB,cAAc,CAAC,UAAU,WAAW,SAAS;AAAA,EAC7C,WAAW;AAAA,EACX,gBAAgB;AAAA,EAChB,iBAAiB;AAAA,EACjB,qBAAqB;AACvB;AAMA,SAAS,eAAe,MAAc,UAA6B;AACjE,SAAO,SAAS,KAAK,aAAW;AAE9B,UAAM,eAAe,QAClB,QAAQ,OAAO,IAAI,EACnB,QAAQ,OAAO,KAAK;AACvB,UAAM,QAAQ,IAAI,OAAO,IAAI,YAAY,GAAG;AAC5C,WAAO,MAAM,KAAK,IAAI;AAAA,EACxB,CAAC;AACH;AAKA,SAAS,cAAc,SAAsB,QAAkD;AAC7F,QAAM,QAAQ,QAAQ,QAAQ,IAAI,OAAO,eAAe,GAAG;AAE3D,MAAI,CAAC,OAAO;AACV,WAAO;AAAA,EACT;AAKA,SAAO,MAAM,SAAS;AACxB;AAKO,SAAS,mBAAmB,SAAsB,QAGvD;AACA,QAAM,eAAe,EAAE,GAAG,gBAAgB,GAAG,OAAO;AACpD,QAAM,QAAQ,QAAQ,QAAQ,IAAI,aAAa,eAAe,GAAG,SAAS;AAE1E,SAAO;AAAA,IACL,iBAAiB,CAAC,CAAC,SAAS,MAAM,SAAS;AAAA,IAC3C;AAAA,EACF;AACF;AAmBO,SAAS,sBAAsB,QAAgC;AACpE,QAAM,eAAe,EAAE,GAAG,gBAAgB,GAAG,OAAO;AAEpD,SAAO,SAAS,WAAW,SAAoC;AAC7D,UAAM,EAAE,SAAS,IAAI,QAAQ;AAG7B,QACE,SAAS,WAAW,QAAQ,KAC5B,SAAS,WAAW,YAAY,KAChC,SAAS,SAAS,GAAG,GACrB;AACA,aAAO,aAAa,KAAK;AAAA,IAC3B;AAGA,QAAI,eAAe,UAAU,aAAa,YAAY,GAAG;AACvD,aAAO,aAAa,KAAK;AAAA,IAC3B;AAGA,UAAM,mBAAmB,aAAa,gBAAgB,WAAW,IAC7D,OACA,eAAe,UAAU,aAAa,eAAe;AAEzD,QAAI,CAAC,kBAAkB;AACrB,aAAO,aAAa,KAAK;AAAA,IAC3B;AAGA,UAAM,kBAAkB,cAAc,SAAS,YAAY;AAE3D,QAAI,CAAC,iBAAiB;AAEpB,YAAM,YAAY,IAAI,IAAI,aAAa,WAAW,QAAQ,GAAG;AAC7D,gBAAU,aAAa,IAAI,aAAa,QAAQ;AAEhD,aAAO,aAAa,SAAS,SAAS;AAAA,IACxC;AAGA,WAAO,aAAa,KAAK;AAAA,EAC3B;AACF;AAeO,SAAS,cAAc,SAAoC;AAChE,SAAO,sBAAsB,EAAE,OAAO;AACxC;AAKO,SAAS,aAAa,SAAsB,aAAqB,KAAa;AACnF,QAAM,YAAY,QAAQ,QAAQ,aAAa,IAAI,WAAW;AAC9D,SAAO,aAAa;AACtB;","names":[]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@basictech/nextjs",
|
|
3
|
-
"version": "0.6.0-beta.
|
|
3
|
+
"version": "0.6.0-beta.7",
|
|
4
4
|
"description": "",
|
|
5
5
|
"private": false,
|
|
6
6
|
"publishConfig": {
|
|
@@ -9,6 +9,27 @@
|
|
|
9
9
|
"main": "dist/index.js",
|
|
10
10
|
"module": "dist/index.mjs",
|
|
11
11
|
"types": "dist/index.d.ts",
|
|
12
|
+
"exports": {
|
|
13
|
+
".": {
|
|
14
|
+
"types": "./dist/index.d.ts",
|
|
15
|
+
"import": "./dist/index.mjs",
|
|
16
|
+
"require": "./dist/index.js",
|
|
17
|
+
"default": "./src/index.ts"
|
|
18
|
+
},
|
|
19
|
+
"./client": {
|
|
20
|
+
"types": "./dist/client.d.ts",
|
|
21
|
+
"import": "./dist/client.mjs",
|
|
22
|
+
"require": "./dist/client.js",
|
|
23
|
+
"default": "./src/client.ts"
|
|
24
|
+
}
|
|
25
|
+
},
|
|
26
|
+
"typesVersions": {
|
|
27
|
+
"*": {
|
|
28
|
+
"client": [
|
|
29
|
+
"./dist/client.d.ts"
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
},
|
|
12
33
|
"scripts": {
|
|
13
34
|
"build": "tsup",
|
|
14
35
|
"dev": "tsup --watch",
|
|
@@ -17,7 +38,7 @@
|
|
|
17
38
|
"author": "",
|
|
18
39
|
"license": "ISC",
|
|
19
40
|
"dependencies": {
|
|
20
|
-
"@basictech/react": "0.7.0-beta.
|
|
41
|
+
"@basictech/react": "0.7.0-beta.7",
|
|
21
42
|
"@radix-ui/react-avatar": "^1.1.1",
|
|
22
43
|
"@radix-ui/react-popover": "^1.1.2"
|
|
23
44
|
},
|
|
@@ -29,6 +50,6 @@
|
|
|
29
50
|
},
|
|
30
51
|
"peerDependencies": {
|
|
31
52
|
"react": "^17.0.0 || ^18.0.0 || ^19.0.0",
|
|
32
|
-
"next": "^14.0.0"
|
|
53
|
+
"next": "^14.0.0 || ^15.0.0 || ^16.0.0"
|
|
33
54
|
}
|
|
34
55
|
}
|