@volcano.dev/sdk 1.2.0-nightly.22454064035.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,180 @@
1
+ /**
2
+ * Volcano SDK - Next.js Middleware Helpers
3
+ *
4
+ * Utilities for integrating Volcano authentication with Next.js middleware.
5
+ *
6
+ * @example
7
+ * ```javascript
8
+ * // middleware.js
9
+ * import { NextResponse } from 'next/server';
10
+ * import { withAuth, createServerClient } from '@volcano.dev/sdk/next/middleware';
11
+ *
12
+ * export async function middleware(request) {
13
+ * const client = createServerClient({
14
+ * anonKey: process.env.VOLCANO_ANON_KEY,
15
+ * apiUrl: process.env.VOLCANO_API_URL,
16
+ * });
17
+ *
18
+ * const user = await withAuth(request, client);
19
+ *
20
+ * if (!user && request.nextUrl.pathname.startsWith('/dashboard')) {
21
+ * return NextResponse.redirect(new URL('/login', request.url));
22
+ * }
23
+ *
24
+ * return NextResponse.next();
25
+ * }
26
+ * ```
27
+ */
28
+
29
+ /**
30
+ * Extract auth token from request headers or cookies
31
+ * @param {Request} request - Next.js request object
32
+ * @returns {string|null} The access token or null
33
+ */
34
+ function getTokenFromRequest(request) {
35
+ // Check Authorization header first
36
+ const authHeader = request.headers.get('authorization');
37
+ if (authHeader?.startsWith('Bearer ')) {
38
+ return authHeader.slice(7);
39
+ }
40
+
41
+ // Check cookies (for SSR/middleware)
42
+ const cookies = request.cookies;
43
+ if (cookies) {
44
+ const tokenCookie = cookies.get('volcano_access_token');
45
+ if (tokenCookie?.value) {
46
+ return tokenCookie.value;
47
+ }
48
+ }
49
+
50
+ return null;
51
+ }
52
+
53
+ /**
54
+ * Create a server-side Volcano client for middleware/API routes
55
+ * @param {Object} config - Client configuration
56
+ * @param {string} config.anonKey - Your project's anon key
57
+ * @param {string} [config.apiUrl] - API URL (defaults to https://api.volcano.dev)
58
+ * @param {string} [config.accessToken] - Optional pre-set access token
59
+ * @returns {Object} A minimal client for server-side auth validation
60
+ */
61
+ function createServerClient(config) {
62
+ const apiUrl = config.apiUrl || 'https://api.volcano.dev';
63
+ const anonKey = config.anonKey;
64
+
65
+ return {
66
+ /**
67
+ * Validate a token and get user info
68
+ * @param {string} accessToken - The access token to validate
69
+ * @returns {Promise<{user: Object|null, error: Error|null}>}
70
+ */
71
+ async getUser(accessToken) {
72
+ if (!accessToken) {
73
+ return { user: null, error: new Error('No access token provided') };
74
+ }
75
+
76
+ try {
77
+ const response = await fetch(`${apiUrl}/auth/user`, {
78
+ method: 'GET',
79
+ headers: {
80
+ 'Authorization': `Bearer ${accessToken}`,
81
+ 'X-Anon-Key': anonKey,
82
+ 'Content-Type': 'application/json',
83
+ },
84
+ });
85
+
86
+ if (!response.ok) {
87
+ const data = await response.json().catch(() => ({}));
88
+ return {
89
+ user: null,
90
+ error: new Error(data.error || `Auth failed: ${response.status}`)
91
+ };
92
+ }
93
+
94
+ const data = await response.json().catch(() => ({}));
95
+ return { user: data.user || null, error: null };
96
+ } catch (err) {
97
+ return { user: null, error: err };
98
+ }
99
+ },
100
+
101
+ /**
102
+ * Refresh an access token
103
+ * @param {string} refreshToken - The refresh token
104
+ * @returns {Promise<{accessToken: string|null, refreshToken: string|null, error: Error|null}>}
105
+ */
106
+ async refreshToken(refreshToken) {
107
+ if (!refreshToken) {
108
+ return { accessToken: null, refreshToken: null, error: new Error('No refresh token provided') };
109
+ }
110
+
111
+ try {
112
+ const response = await fetch(`${apiUrl}/auth/refresh`, {
113
+ method: 'POST',
114
+ headers: {
115
+ 'X-Anon-Key': anonKey,
116
+ 'Content-Type': 'application/json',
117
+ },
118
+ body: JSON.stringify({ refresh_token: refreshToken }),
119
+ });
120
+
121
+ if (!response.ok) {
122
+ const data = await response.json().catch(() => ({}));
123
+ return {
124
+ accessToken: null,
125
+ refreshToken: null,
126
+ error: new Error(data.error || `Refresh failed: ${response.status}`)
127
+ };
128
+ }
129
+
130
+ const data = await response.json();
131
+ return {
132
+ accessToken: data.access_token,
133
+ refreshToken: data.refresh_token,
134
+ error: null
135
+ };
136
+ } catch (err) {
137
+ return { accessToken: null, refreshToken: null, error: err };
138
+ }
139
+ },
140
+ };
141
+ }
142
+
143
+ /**
144
+ * Middleware helper to validate auth and get user
145
+ * @param {Request} request - Next.js request object
146
+ * @param {Object} client - Server client created with createServerClient
147
+ * @returns {Promise<Object|null>} The user object or null if not authenticated
148
+ */
149
+ async function withAuth(request, client) {
150
+ const token = getTokenFromRequest(request);
151
+ if (!token) {
152
+ return null;
153
+ }
154
+
155
+ const { user, error } = await client.getUser(token);
156
+ if (error) {
157
+ console.warn('Auth validation failed:', error.message);
158
+ return null;
159
+ }
160
+
161
+ return user;
162
+ }
163
+
164
+ /**
165
+ * Check if running in browser environment
166
+ * @returns {boolean}
167
+ */
168
+ function isBrowser() {
169
+ return typeof window !== 'undefined' && typeof window.document !== 'undefined';
170
+ }
171
+
172
+ /**
173
+ * Check if running in server environment (Node.js, Edge Runtime, etc.)
174
+ * @returns {boolean}
175
+ */
176
+ function isServer() {
177
+ return !isBrowser();
178
+ }
179
+
180
+ export { createServerClient, getTokenFromRequest, isBrowser, isServer, withAuth };
@@ -0,0 +1,186 @@
1
+ 'use strict';
2
+
3
+ /**
4
+ * Volcano SDK - Next.js Middleware Helpers
5
+ *
6
+ * Utilities for integrating Volcano authentication with Next.js middleware.
7
+ *
8
+ * @example
9
+ * ```javascript
10
+ * // middleware.js
11
+ * import { NextResponse } from 'next/server';
12
+ * import { withAuth, createServerClient } from '@volcano.dev/sdk/next/middleware';
13
+ *
14
+ * export async function middleware(request) {
15
+ * const client = createServerClient({
16
+ * anonKey: process.env.VOLCANO_ANON_KEY,
17
+ * apiUrl: process.env.VOLCANO_API_URL,
18
+ * });
19
+ *
20
+ * const user = await withAuth(request, client);
21
+ *
22
+ * if (!user && request.nextUrl.pathname.startsWith('/dashboard')) {
23
+ * return NextResponse.redirect(new URL('/login', request.url));
24
+ * }
25
+ *
26
+ * return NextResponse.next();
27
+ * }
28
+ * ```
29
+ */
30
+
31
+ /**
32
+ * Extract auth token from request headers or cookies
33
+ * @param {Request} request - Next.js request object
34
+ * @returns {string|null} The access token or null
35
+ */
36
+ function getTokenFromRequest(request) {
37
+ // Check Authorization header first
38
+ const authHeader = request.headers.get('authorization');
39
+ if (authHeader?.startsWith('Bearer ')) {
40
+ return authHeader.slice(7);
41
+ }
42
+
43
+ // Check cookies (for SSR/middleware)
44
+ const cookies = request.cookies;
45
+ if (cookies) {
46
+ const tokenCookie = cookies.get('volcano_access_token');
47
+ if (tokenCookie?.value) {
48
+ return tokenCookie.value;
49
+ }
50
+ }
51
+
52
+ return null;
53
+ }
54
+
55
+ /**
56
+ * Create a server-side Volcano client for middleware/API routes
57
+ * @param {Object} config - Client configuration
58
+ * @param {string} config.anonKey - Your project's anon key
59
+ * @param {string} [config.apiUrl] - API URL (defaults to https://api.volcano.dev)
60
+ * @param {string} [config.accessToken] - Optional pre-set access token
61
+ * @returns {Object} A minimal client for server-side auth validation
62
+ */
63
+ function createServerClient(config) {
64
+ const apiUrl = config.apiUrl || 'https://api.volcano.dev';
65
+ const anonKey = config.anonKey;
66
+
67
+ return {
68
+ /**
69
+ * Validate a token and get user info
70
+ * @param {string} accessToken - The access token to validate
71
+ * @returns {Promise<{user: Object|null, error: Error|null}>}
72
+ */
73
+ async getUser(accessToken) {
74
+ if (!accessToken) {
75
+ return { user: null, error: new Error('No access token provided') };
76
+ }
77
+
78
+ try {
79
+ const response = await fetch(`${apiUrl}/auth/user`, {
80
+ method: 'GET',
81
+ headers: {
82
+ 'Authorization': `Bearer ${accessToken}`,
83
+ 'X-Anon-Key': anonKey,
84
+ 'Content-Type': 'application/json',
85
+ },
86
+ });
87
+
88
+ if (!response.ok) {
89
+ const data = await response.json().catch(() => ({}));
90
+ return {
91
+ user: null,
92
+ error: new Error(data.error || `Auth failed: ${response.status}`)
93
+ };
94
+ }
95
+
96
+ const data = await response.json().catch(() => ({}));
97
+ return { user: data.user || null, error: null };
98
+ } catch (err) {
99
+ return { user: null, error: err };
100
+ }
101
+ },
102
+
103
+ /**
104
+ * Refresh an access token
105
+ * @param {string} refreshToken - The refresh token
106
+ * @returns {Promise<{accessToken: string|null, refreshToken: string|null, error: Error|null}>}
107
+ */
108
+ async refreshToken(refreshToken) {
109
+ if (!refreshToken) {
110
+ return { accessToken: null, refreshToken: null, error: new Error('No refresh token provided') };
111
+ }
112
+
113
+ try {
114
+ const response = await fetch(`${apiUrl}/auth/refresh`, {
115
+ method: 'POST',
116
+ headers: {
117
+ 'X-Anon-Key': anonKey,
118
+ 'Content-Type': 'application/json',
119
+ },
120
+ body: JSON.stringify({ refresh_token: refreshToken }),
121
+ });
122
+
123
+ if (!response.ok) {
124
+ const data = await response.json().catch(() => ({}));
125
+ return {
126
+ accessToken: null,
127
+ refreshToken: null,
128
+ error: new Error(data.error || `Refresh failed: ${response.status}`)
129
+ };
130
+ }
131
+
132
+ const data = await response.json();
133
+ return {
134
+ accessToken: data.access_token,
135
+ refreshToken: data.refresh_token,
136
+ error: null
137
+ };
138
+ } catch (err) {
139
+ return { accessToken: null, refreshToken: null, error: err };
140
+ }
141
+ },
142
+ };
143
+ }
144
+
145
+ /**
146
+ * Middleware helper to validate auth and get user
147
+ * @param {Request} request - Next.js request object
148
+ * @param {Object} client - Server client created with createServerClient
149
+ * @returns {Promise<Object|null>} The user object or null if not authenticated
150
+ */
151
+ async function withAuth(request, client) {
152
+ const token = getTokenFromRequest(request);
153
+ if (!token) {
154
+ return null;
155
+ }
156
+
157
+ const { user, error } = await client.getUser(token);
158
+ if (error) {
159
+ console.warn('Auth validation failed:', error.message);
160
+ return null;
161
+ }
162
+
163
+ return user;
164
+ }
165
+
166
+ /**
167
+ * Check if running in browser environment
168
+ * @returns {boolean}
169
+ */
170
+ function isBrowser() {
171
+ return typeof window !== 'undefined' && typeof window.document !== 'undefined';
172
+ }
173
+
174
+ /**
175
+ * Check if running in server environment (Node.js, Edge Runtime, etc.)
176
+ * @returns {boolean}
177
+ */
178
+ function isServer() {
179
+ return !isBrowser();
180
+ }
181
+
182
+ exports.createServerClient = createServerClient;
183
+ exports.getTokenFromRequest = getTokenFromRequest;
184
+ exports.isBrowser = isBrowser;
185
+ exports.isServer = isServer;
186
+ exports.withAuth = withAuth;