@ainative/next-sdk 1.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 AINative Studio
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,395 @@
1
+ # @ainative/next-sdk
2
+
3
+ Official Next.js SDK for AINative Studio API. Provides server and client utilities for both App Router and Pages Router.
4
+
5
+ ## Features
6
+
7
+ - **Server Components**: Use `createServerClient()` in Server Components and Server Actions
8
+ - **Client Components**: Re-exports `@ainative/react-sdk` hooks for Client Components
9
+ - **API Routes**: Protect routes with `withAuth()` middleware
10
+ - **Session Management**: Extract JWT session from cookies
11
+ - **TypeScript**: Full type safety with TypeScript definitions
12
+ - **Zero Config**: Works out of the box with sensible defaults
13
+
14
+ ## Installation
15
+
16
+ ```bash
17
+ npm install @ainative/next-sdk
18
+ # or
19
+ yarn add @ainative/next-sdk
20
+ # or
21
+ pnpm add @ainative/next-sdk
22
+ ```
23
+
24
+ ## Quick Start
25
+
26
+ ### App Router (Next.js 13+)
27
+
28
+ #### Server Component
29
+
30
+ ```tsx
31
+ // app/dashboard/page.tsx
32
+ import { createServerClient, getApiKey } from '@ainative/next-sdk/server';
33
+ import { redirect } from 'next/navigation';
34
+
35
+ export default async function DashboardPage() {
36
+ const apiKey = await getApiKey();
37
+
38
+ if (!apiKey) {
39
+ redirect('/login');
40
+ }
41
+
42
+ const client = createServerClient({ apiKey });
43
+ const balance = await client.credits.balance();
44
+
45
+ return (
46
+ <div>
47
+ <h1>Dashboard</h1>
48
+ <p>Credits: {balance.remaining_credits}</p>
49
+ </div>
50
+ );
51
+ }
52
+ ```
53
+
54
+ #### Client Component
55
+
56
+ ```tsx
57
+ // app/chat/page.tsx
58
+ 'use client';
59
+
60
+ import { AINativeProvider, useChat } from '@ainative/next-sdk/client';
61
+
62
+ export default function ChatPage({ apiKey }: { apiKey: string }) {
63
+ return (
64
+ <AINativeProvider config={{ apiKey }}>
65
+ <ChatInterface />
66
+ </AINativeProvider>
67
+ );
68
+ }
69
+
70
+ function ChatInterface() {
71
+ const { messages, isLoading, sendMessage } = useChat();
72
+
73
+ return (
74
+ <div>
75
+ {messages.map((msg, idx) => (
76
+ <div key={idx}>{msg.content}</div>
77
+ ))}
78
+ <button onClick={() => sendMessage('Hello!')}>
79
+ Send
80
+ </button>
81
+ </div>
82
+ );
83
+ }
84
+ ```
85
+
86
+ #### API Route
87
+
88
+ ```tsx
89
+ // app/api/chat/route.ts
90
+ import { withAuth, createServerClient } from '@ainative/next-sdk/server';
91
+ import { NextRequest } from 'next/server';
92
+
93
+ export const POST = withAuth(async (req: NextRequest, { session, apiKey }) => {
94
+ const body = await req.json();
95
+ const client = createServerClient({ apiKey });
96
+
97
+ const response = await client.chat.completions.create({
98
+ messages: body.messages,
99
+ });
100
+
101
+ return Response.json(response);
102
+ });
103
+ ```
104
+
105
+ ### Pages Router (Next.js 12)
106
+
107
+ #### Page with Server-Side Rendering
108
+
109
+ ```tsx
110
+ // pages/dashboard.tsx
111
+ import { GetServerSideProps } from 'next';
112
+ import { getSessionFromCookie, createServerClient, getApiKeyFromCookie } from '@ainative/next-sdk/server';
113
+
114
+ export default function DashboardPage({ balance }) {
115
+ return <div>Credits: {balance.remaining_credits}</div>;
116
+ }
117
+
118
+ export const getServerSideProps: GetServerSideProps = async ({ req }) => {
119
+ const session = getSessionFromCookie(req.headers.cookie);
120
+
121
+ if (!session) {
122
+ return { redirect: { destination: '/login', permanent: false } };
123
+ }
124
+
125
+ const apiKey = getApiKeyFromCookie(req.headers.cookie);
126
+ const client = createServerClient({ apiKey });
127
+ const balance = await client.credits.balance();
128
+
129
+ return { props: { balance } };
130
+ };
131
+ ```
132
+
133
+ #### API Route
134
+
135
+ ```tsx
136
+ // pages/api/chat.ts
137
+ import { withAuthPages, createServerClient } from '@ainative/next-sdk/server';
138
+
139
+ export default withAuthPages(async (req, res, { session, apiKey }) => {
140
+ const client = createServerClient({ apiKey });
141
+
142
+ const response = await client.chat.completions.create({
143
+ messages: req.body.messages,
144
+ });
145
+
146
+ res.status(200).json(response);
147
+ });
148
+ ```
149
+
150
+ ## API Reference
151
+
152
+ ### Server Utilities
153
+
154
+ #### `createServerClient(config)`
155
+
156
+ Creates a server-side API client for use in Server Components, Server Actions, and API routes.
157
+
158
+ ```typescript
159
+ import { createServerClient } from '@ainative/next-sdk/server';
160
+
161
+ const client = createServerClient({
162
+ apiKey: 'your-jwt-token',
163
+ baseUrl: 'https://api.ainative.studio/api/v1', // optional
164
+ });
165
+
166
+ // Chat completions
167
+ const response = await client.chat.completions.create({
168
+ messages: [{ role: 'user', content: 'Hello!' }],
169
+ preferred_model: 'gpt-3.5-turbo',
170
+ temperature: 0.7,
171
+ });
172
+
173
+ // Credit balance
174
+ const balance = await client.credits.balance();
175
+ ```
176
+
177
+ #### `getSession()` (App Router)
178
+
179
+ Gets session from cookies in App Router. Returns `Session | null`.
180
+
181
+ ```typescript
182
+ import { getSession } from '@ainative/next-sdk/server';
183
+
184
+ const session = await getSession(); // default cookie: 'ainative_token'
185
+ const session = await getSession('custom_cookie'); // custom cookie name
186
+
187
+ if (session) {
188
+ console.log(session.userId, session.email);
189
+ }
190
+ ```
191
+
192
+ #### `getSessionFromCookie(cookieHeader)` (Pages Router)
193
+
194
+ Gets session from cookie header in Pages Router. Returns `Session | null`.
195
+
196
+ ```typescript
197
+ import { getSessionFromCookie } from '@ainative/next-sdk/server';
198
+
199
+ const session = getSessionFromCookie(req.headers.cookie);
200
+ ```
201
+
202
+ #### `getApiKey()` (App Router)
203
+
204
+ Gets JWT token from cookies. Returns `string | null`.
205
+
206
+ ```typescript
207
+ import { getApiKey } from '@ainative/next-sdk/server';
208
+
209
+ const apiKey = await getApiKey();
210
+ ```
211
+
212
+ #### `getApiKeyFromCookie(cookieHeader)` (Pages Router)
213
+
214
+ Gets JWT token from cookie header. Returns `string | null`.
215
+
216
+ ```typescript
217
+ import { getApiKeyFromCookie } from '@ainative/next-sdk/server';
218
+
219
+ const apiKey = getApiKeyFromCookie(req.headers.cookie);
220
+ ```
221
+
222
+ #### `withAuth(handler, options?)` (App Router)
223
+
224
+ Higher-order function to protect API routes in App Router.
225
+
226
+ ```typescript
227
+ import { withAuth } from '@ainative/next-sdk/server';
228
+
229
+ export const POST = withAuth(async (req, { session, apiKey, params }) => {
230
+ // session: Session object
231
+ // apiKey: JWT token string
232
+ // params: Route params (if any)
233
+
234
+ return Response.json({ userId: session.userId });
235
+ }, {
236
+ cookieName: 'ainative_token', // optional
237
+ });
238
+ ```
239
+
240
+ #### `withAuthPages(handler, options?)` (Pages Router)
241
+
242
+ Higher-order function to protect API routes in Pages Router.
243
+
244
+ ```typescript
245
+ import { withAuthPages } from '@ainative/next-sdk/server';
246
+
247
+ export default withAuthPages(async (req, res, { session, apiKey }) => {
248
+ res.status(200).json({ userId: session.userId });
249
+ });
250
+ ```
251
+
252
+ ### Client Utilities
253
+
254
+ All client utilities are re-exported from `@ainative/react-sdk`:
255
+
256
+ - `AINativeProvider` - Provider component for client-side context
257
+ - `useAINative()` - Access API client in client components
258
+ - `useChat()` - Chat completion hook with state management
259
+ - `useCredits()` - Credit balance hook with auto-refresh
260
+
261
+ See [@ainative/react-sdk](https://www.npmjs.com/package/@ainative/react-sdk) for full documentation.
262
+
263
+ ## Types
264
+
265
+ ```typescript
266
+ import type {
267
+ // Server types
268
+ Session,
269
+ ServerClient,
270
+ ServerClientConfig,
271
+ WithAuthOptions,
272
+
273
+ // Client types
274
+ AINativeConfig,
275
+ Message,
276
+ ChatCompletionRequest,
277
+ ChatCompletionResponse,
278
+ CreditBalance,
279
+ ChatState,
280
+ } from '@ainative/next-sdk';
281
+ ```
282
+
283
+ ## Authentication
284
+
285
+ The SDK expects JWT tokens stored in cookies. By default, it looks for a cookie named `ainative_token`.
286
+
287
+ ### Setting the Cookie
288
+
289
+ ```typescript
290
+ // After login, set the JWT token as a cookie
291
+ import { cookies } from 'next/headers';
292
+
293
+ async function loginHandler(email: string, password: string) {
294
+ // Authenticate with AINative API
295
+ const response = await fetch('https://api.ainative.studio/api/v1/public/auth/login', {
296
+ method: 'POST',
297
+ headers: { 'Content-Type': 'application/json' },
298
+ body: JSON.stringify({ email, password }),
299
+ });
300
+
301
+ const { access_token } = await response.json();
302
+
303
+ // Set cookie
304
+ const cookieStore = await cookies();
305
+ cookieStore.set('ainative_token', access_token, {
306
+ httpOnly: true,
307
+ secure: process.env.NODE_ENV === 'production',
308
+ sameSite: 'lax',
309
+ maxAge: 60 * 60 * 24 * 7, // 7 days
310
+ });
311
+ }
312
+ ```
313
+
314
+ ### Custom Cookie Name
315
+
316
+ ```typescript
317
+ // Use a custom cookie name
318
+ const session = await getSession('my_custom_token');
319
+ const apiKey = await getApiKey('my_custom_token');
320
+
321
+ export const POST = withAuth(handler, {
322
+ cookieName: 'my_custom_token',
323
+ });
324
+ ```
325
+
326
+ ## Middleware Example
327
+
328
+ ```typescript
329
+ // middleware.ts
330
+ import { NextResponse } from 'next/server';
331
+ import type { NextRequest } from 'next/server';
332
+
333
+ export function middleware(request: NextRequest) {
334
+ const token = request.cookies.get('ainative_token')?.value;
335
+ const isProtected = request.nextUrl.pathname.startsWith('/dashboard');
336
+
337
+ if (isProtected && !token) {
338
+ return NextResponse.redirect(new URL('/login', request.url));
339
+ }
340
+
341
+ return NextResponse.next();
342
+ }
343
+
344
+ export const config = {
345
+ matcher: ['/dashboard/:path*'],
346
+ };
347
+ ```
348
+
349
+ ## Error Handling
350
+
351
+ ```typescript
352
+ try {
353
+ const client = createServerClient({ apiKey });
354
+ const response = await client.chat.completions.create({
355
+ messages: [{ role: 'user', content: 'Hello!' }],
356
+ });
357
+ } catch (error) {
358
+ console.error('API error:', error.message);
359
+ // Handle error appropriately
360
+ }
361
+ ```
362
+
363
+ ## Environment Variables
364
+
365
+ ```bash
366
+ # Optional: Override default API URL
367
+ NEXT_PUBLIC_AINATIVE_API_URL=https://api.ainative.studio/api/v1
368
+ ```
369
+
370
+ ## Requirements
371
+
372
+ - Next.js 13.0+ or 14.0+
373
+ - React 18.0+
374
+ - Node.js 18.0+
375
+
376
+ ## Examples
377
+
378
+ See the [examples](./examples) directory for complete examples:
379
+
380
+ - [App Router examples](./examples/app-router)
381
+ - [Pages Router examples](./examples/pages-router)
382
+
383
+ ## Contributing
384
+
385
+ See the main [repository](https://github.com/AINative-Studio/core) for contribution guidelines.
386
+
387
+ ## License
388
+
389
+ MIT
390
+
391
+ ## Support
392
+
393
+ - Documentation: https://ainative.studio/docs
394
+ - API Reference: https://api.ainative.studio/docs-enhanced
395
+ - Issues: https://github.com/AINative-Studio/core/issues
@@ -0,0 +1 @@
1
+ export { AINativeConfig, AINativeError, AINativeProvider, ChatCompletionRequest, ChatCompletionResponse, ChatState, CreditBalance, Message, Usage, UseChatOptions, UseCreditsReturn, useAINative, useChat, useCredits } from '@ainative/react-sdk';
@@ -0,0 +1,2 @@
1
+ export{AINativeProvider,useAINative,useChat,useCredits}from"@ainative/react-sdk";
2
+ //# sourceMappingURL=client.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.esm.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
package/dist/client.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var e=require("@ainative/react-sdk");Object.defineProperty(exports,"AINativeProvider",{enumerable:!0,get:function(){return e.AINativeProvider}}),Object.defineProperty(exports,"useAINative",{enumerable:!0,get:function(){return e.useAINative}}),Object.defineProperty(exports,"useChat",{enumerable:!0,get:function(){return e.useChat}}),Object.defineProperty(exports,"useCredits",{enumerable:!0,get:function(){return e.useCredits}});
2
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sources":[],"sourcesContent":[],"names":[],"mappings":""}
@@ -0,0 +1,231 @@
1
+ import { ChatCompletionRequest, ChatCompletionResponse, CreditBalance } from '@ainative/react-sdk';
2
+ export { AINativeConfig, AINativeError, AINativeProvider, ChatCompletionRequest, ChatCompletionResponse, ChatState, CreditBalance, Message, Usage, UseChatOptions, UseCreditsReturn, useAINative, useChat, useCredits } from '@ainative/react-sdk';
3
+ import { NextRequest } from 'next/server';
4
+
5
+ /**
6
+ * AINative Next.js SDK Type Definitions
7
+ */
8
+
9
+ /**
10
+ * Session data extracted from JWT token
11
+ */
12
+ interface Session {
13
+ userId: string;
14
+ email: string;
15
+ exp: number;
16
+ iat: number;
17
+ }
18
+ /**
19
+ * Server-side API client configuration
20
+ */
21
+ interface ServerClientConfig {
22
+ apiKey: string;
23
+ baseUrl?: string;
24
+ }
25
+ /**
26
+ * Options for withAuth higher-order function
27
+ */
28
+ interface WithAuthOptions {
29
+ cookieName?: string;
30
+ redirectTo?: string;
31
+ }
32
+ /**
33
+ * Next.js API route request with authentication
34
+ */
35
+ interface AuthenticatedRequest {
36
+ session: Session;
37
+ apiKey: string;
38
+ }
39
+ /**
40
+ * Server-side API client for Next.js Server Components
41
+ */
42
+ interface ServerClient {
43
+ chat: {
44
+ completions: {
45
+ create: (request: ChatCompletionRequest) => Promise<ChatCompletionResponse>;
46
+ };
47
+ };
48
+ credits: {
49
+ balance: () => Promise<CreditBalance>;
50
+ };
51
+ }
52
+
53
+ /**
54
+ * Create server-side API client for Next.js Server Components
55
+ */
56
+
57
+ /**
58
+ * Create a server-side API client
59
+ *
60
+ * Use this in Server Components, Server Actions, and API routes.
61
+ *
62
+ * @param config - Client configuration with API key
63
+ * @returns Server-side API client
64
+ *
65
+ * @example
66
+ * ```tsx
67
+ * // app/chat/page.tsx
68
+ * import { createServerClient } from '@ainative/next-sdk/server';
69
+ * import { getApiKey } from '@ainative/next-sdk/server';
70
+ *
71
+ * export default async function ChatPage() {
72
+ * const apiKey = await getApiKey();
73
+ * if (!apiKey) return <div>Not authenticated</div>;
74
+ *
75
+ * const client = createServerClient({ apiKey });
76
+ * const balance = await client.credits.balance();
77
+ *
78
+ * return <div>Credits: {balance.remaining_credits}</div>;
79
+ * }
80
+ * ```
81
+ */
82
+ declare function createServerClient(config: ServerClientConfig): ServerClient;
83
+
84
+ /**
85
+ * Get session from JWT token stored in cookies
86
+ *
87
+ * Supports both App Router and Pages Router
88
+ */
89
+
90
+ /**
91
+ * Get session from cookies (App Router)
92
+ *
93
+ * Use this in Server Components and Server Actions.
94
+ *
95
+ * @param cookieName - Cookie name (default: 'ainative_token')
96
+ * @returns Session data or null if not authenticated
97
+ *
98
+ * @example
99
+ * ```tsx
100
+ * // app/dashboard/page.tsx
101
+ * import { getSession } from '@ainative/next-sdk/server';
102
+ *
103
+ * export default async function DashboardPage() {
104
+ * const session = await getSession();
105
+ *
106
+ * if (!session) {
107
+ * redirect('/login');
108
+ * }
109
+ *
110
+ * return <div>Welcome {session.email}</div>;
111
+ * }
112
+ * ```
113
+ */
114
+ declare function getSession(cookieName?: string): Promise<Session | null>;
115
+ /**
116
+ * Get session from cookies (Pages Router)
117
+ *
118
+ * Use this in getServerSideProps or API routes.
119
+ *
120
+ * @param cookieHeader - Cookie header string from request
121
+ * @param cookieName - Cookie name (default: 'ainative_token')
122
+ * @returns Session data or null if not authenticated
123
+ *
124
+ * @example
125
+ * ```tsx
126
+ * // pages/dashboard.tsx
127
+ * import { getSessionFromCookie } from '@ainative/next-sdk/server';
128
+ *
129
+ * export async function getServerSideProps({ req }) {
130
+ * const session = getSessionFromCookie(req.headers.cookie);
131
+ *
132
+ * if (!session) {
133
+ * return { redirect: { destination: '/login', permanent: false } };
134
+ * }
135
+ *
136
+ * return { props: { session } };
137
+ * }
138
+ * ```
139
+ */
140
+ declare function getSessionFromCookie(cookieHeader: string | undefined, cookieName?: string): Session | null;
141
+ /**
142
+ * Get API key from cookies (App Router)
143
+ *
144
+ * @param cookieName - Cookie name (default: 'ainative_token')
145
+ * @returns JWT token or null
146
+ */
147
+ declare function getApiKey(cookieName?: string): Promise<string | null>;
148
+ /**
149
+ * Get API key from cookie header (Pages Router)
150
+ *
151
+ * @param cookieHeader - Cookie header string from request
152
+ * @param cookieName - Cookie name (default: 'ainative_token')
153
+ * @returns JWT token or null
154
+ */
155
+ declare function getApiKeyFromCookie(cookieHeader: string | undefined, cookieName?: string): string | null;
156
+
157
+ /**
158
+ * Higher-order function for API route authentication
159
+ */
160
+
161
+ /**
162
+ * Request handler with authentication
163
+ */
164
+ type AuthHandler = (req: NextRequest, context: {
165
+ session: Session;
166
+ apiKey: string;
167
+ params?: any;
168
+ }) => Promise<Response> | Response;
169
+ /**
170
+ * Wrap API route handler with authentication
171
+ *
172
+ * Use this to protect API routes in both App Router and Pages Router.
173
+ *
174
+ * @param handler - Route handler function
175
+ * @param options - Authentication options
176
+ * @returns Protected route handler
177
+ *
178
+ * @example
179
+ * ```tsx
180
+ * // app/api/chat/route.ts
181
+ * import { withAuth } from '@ainative/next-sdk/server';
182
+ * import { createServerClient } from '@ainative/next-sdk/server';
183
+ *
184
+ * export const POST = withAuth(async (req, { session, apiKey }) => {
185
+ * const client = createServerClient({ apiKey });
186
+ * const body = await req.json();
187
+ *
188
+ * const response = await client.chat.completions.create({
189
+ * messages: body.messages,
190
+ * });
191
+ *
192
+ * return Response.json(response);
193
+ * });
194
+ * ```
195
+ */
196
+ declare function withAuth(handler: AuthHandler, options?: WithAuthOptions): (req: NextRequest, context?: {
197
+ params: any;
198
+ }) => Promise<Response>;
199
+ /**
200
+ * Wrap Pages Router API handler with authentication
201
+ *
202
+ * Use this for API routes in the pages directory.
203
+ *
204
+ * @param handler - Route handler function
205
+ * @param options - Authentication options
206
+ * @returns Protected route handler
207
+ *
208
+ * @example
209
+ * ```tsx
210
+ * // pages/api/chat.ts
211
+ * import { withAuthPages } from '@ainative/next-sdk/server';
212
+ * import { createServerClient } from '@ainative/next-sdk/server';
213
+ * import type { NextApiRequest, NextApiResponse } from 'next';
214
+ *
215
+ * export default withAuthPages(async (req, res, { session, apiKey }) => {
216
+ * const client = createServerClient({ apiKey });
217
+ *
218
+ * const response = await client.chat.completions.create({
219
+ * messages: req.body.messages,
220
+ * });
221
+ *
222
+ * res.status(200).json(response);
223
+ * });
224
+ * ```
225
+ */
226
+ declare function withAuthPages(handler: (req: any, res: any, context: {
227
+ session: Session;
228
+ apiKey: string;
229
+ }) => Promise<void> | void, options?: WithAuthOptions): (req: any, res: any) => Promise<any>;
230
+
231
+ export { AuthenticatedRequest, ServerClient, ServerClientConfig, Session, WithAuthOptions, createServerClient, getApiKey, getApiKeyFromCookie, getSession, getSessionFromCookie, withAuth, withAuthPages };
@@ -0,0 +1,2 @@
1
+ import{cookies as t}from"next/headers";import{NextResponse as e}from"next/server";export{AINativeProvider,useAINative,useChat,useCredits}from"@ainative/react-sdk";function r(t){const e=t.baseUrl||"https://api.ainative.studio/api/v1";async function r(r,n={}){const a=`${e}${r}`,s=await fetch(a,{...n,headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`,...n.headers}});if(!s.ok){const t=await s.json().catch(()=>({message:`HTTP ${s.status}: ${s.statusText}`}));throw new Error(t.message||`Request failed with status ${s.status}`)}return s.json()}return{chat:{completions:{create:async t=>r("/public/chat/completions",{method:"POST",body:JSON.stringify(t)})}},credits:{balance:async()=>r("/public/credits/balance")}}}function n(t){try{const e=t.split(".");if(3!==e.length)return null;const r=e[1],n=Buffer.from(r,"base64").toString("utf-8"),a=JSON.parse(n);if(!(a.userId&&a.email&&a.exp&&a.iat))return null;const s=Math.floor(Date.now()/1e3);return a.exp<s?null:{userId:a.userId,email:a.email,exp:a.exp,iat:a.iat}}catch(t){return null}}async function a(e="ainative_token"){try{const r=await t(),a=r.get(e)?.value;return a?n(a):null}catch(t){return null}}function s(t,e="ainative_token"){if(!t)return null;const r=t.split(";").map(t=>t.trim()).find(t=>t.startsWith(`${e}=`));if(!r)return null;return n(r.substring(e.length+1))}async function i(e="ainative_token"){try{const r=await t(),n=r.get(e)?.value;return n||null}catch(t){return null}}function o(t,e="ainative_token"){if(!t)return null;const r=t.split(";").map(t=>t.trim()).find(t=>t.startsWith(`${e}=`));return r?r.substring(e.length+1):null}function u(t,r={}){const n=r.cookieName||"ainative_token";return async(r,a)=>{try{const i=r.headers.get("cookie"),u=s(i||void 0,n);if(!u)return e.json({error:"Unauthorized",message:"Authentication required"},{status:401});const c=o(i||void 0,n);return c?await t(r,{session:u,apiKey:c,params:a?.params}):e.json({error:"Unauthorized",message:"API key not found"},{status:401})}catch(t){return console.error("Auth middleware error:",t),e.json({error:"Internal Server Error",message:"Authentication failed"},{status:500})}}}function c(t,e={}){const r=e.cookieName||"ainative_token";return async(e,n)=>{try{const a=e.headers.cookie,i=s(a,r);if(!i)return n.status(401).json({error:"Unauthorized",message:"Authentication required"});const u=o(a,r);return u?await t(e,n,{session:i,apiKey:u}):n.status(401).json({error:"Unauthorized",message:"API key not found"})}catch(t){return console.error("Auth middleware error:",t),n.status(500).json({error:"Internal Server Error",message:"Authentication failed"})}}}export{r as createServerClient,i as getApiKey,o as getApiKeyFromCookie,a as getSession,s as getSessionFromCookie,u as withAuth,c as withAuthPages};
2
+ //# sourceMappingURL=index.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.esm.js","sources":["../src/server/createServerClient.ts","../src/server/getSession.ts","../src/server/withAuth.ts"],"sourcesContent":["/**\n * Create server-side API client for Next.js Server Components\n */\n\nimport type {\n ServerClient,\n ServerClientConfig,\n ChatCompletionRequest,\n ChatCompletionResponse,\n CreditBalance,\n} from '../types';\n\n/**\n * Create a server-side API client\n *\n * Use this in Server Components, Server Actions, and API routes.\n *\n * @param config - Client configuration with API key\n * @returns Server-side API client\n *\n * @example\n * ```tsx\n * // app/chat/page.tsx\n * import { createServerClient } from '@ainative/next-sdk/server';\n * import { getApiKey } from '@ainative/next-sdk/server';\n *\n * export default async function ChatPage() {\n * const apiKey = await getApiKey();\n * if (!apiKey) return <div>Not authenticated</div>;\n *\n * const client = createServerClient({ apiKey });\n * const balance = await client.credits.balance();\n *\n * return <div>Credits: {balance.remaining_credits}</div>;\n * }\n * ```\n */\nexport function createServerClient(config: ServerClientConfig): ServerClient {\n const baseUrl = config.baseUrl || 'https://api.ainative.studio/api/v1';\n\n /**\n * Make authenticated API request\n */\n async function fetchAPI<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\n const url = `${baseUrl}${endpoint}`;\n\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${config.apiKey}`,\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({\n message: `HTTP ${response.status}: ${response.statusText}`,\n })) as { message?: string };\n\n throw new Error(error.message || `Request failed with status ${response.status}`);\n }\n\n return response.json() as Promise<T>;\n }\n\n return {\n chat: {\n completions: {\n /**\n * Create chat completion\n */\n create: async (request: ChatCompletionRequest): Promise<ChatCompletionResponse> => {\n return fetchAPI<ChatCompletionResponse>('/public/chat/completions', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n },\n },\n },\n credits: {\n /**\n * Get credit balance\n */\n balance: async (): Promise<CreditBalance> => {\n return fetchAPI<CreditBalance>('/public/credits/balance');\n },\n },\n };\n}\n","/**\n * Get session from JWT token stored in cookies\n *\n * Supports both App Router and Pages Router\n */\n\nimport { cookies } from 'next/headers';\nimport type { Session } from '../types';\n\n/**\n * Decode JWT token without verification (server-side only)\n *\n * @param token - JWT token string\n * @returns Decoded session data or null if invalid\n */\nfunction decodeJWT(token: string): Session | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return null;\n }\n\n const payload = parts[1];\n const decoded = Buffer.from(payload, 'base64').toString('utf-8');\n const parsed = JSON.parse(decoded);\n\n // Validate required fields\n if (!parsed.userId || !parsed.email || !parsed.exp || !parsed.iat) {\n return null;\n }\n\n // Check expiration\n const now = Math.floor(Date.now() / 1000);\n if (parsed.exp < now) {\n return null;\n }\n\n return {\n userId: parsed.userId,\n email: parsed.email,\n exp: parsed.exp,\n iat: parsed.iat,\n };\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Get session from cookies (App Router)\n *\n * Use this in Server Components and Server Actions.\n *\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns Session data or null if not authenticated\n *\n * @example\n * ```tsx\n * // app/dashboard/page.tsx\n * import { getSession } from '@ainative/next-sdk/server';\n *\n * export default async function DashboardPage() {\n * const session = await getSession();\n *\n * if (!session) {\n * redirect('/login');\n * }\n *\n * return <div>Welcome {session.email}</div>;\n * }\n * ```\n */\nexport async function getSession(cookieName = 'ainative_token'): Promise<Session | null> {\n try {\n const cookieStore = await cookies();\n const token = cookieStore.get(cookieName)?.value;\n\n if (!token) {\n return null;\n }\n\n return decodeJWT(token);\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Get session from cookies (Pages Router)\n *\n * Use this in getServerSideProps or API routes.\n *\n * @param cookieHeader - Cookie header string from request\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns Session data or null if not authenticated\n *\n * @example\n * ```tsx\n * // pages/dashboard.tsx\n * import { getSessionFromCookie } from '@ainative/next-sdk/server';\n *\n * export async function getServerSideProps({ req }) {\n * const session = getSessionFromCookie(req.headers.cookie);\n *\n * if (!session) {\n * return { redirect: { destination: '/login', permanent: false } };\n * }\n *\n * return { props: { session } };\n * }\n * ```\n */\nexport function getSessionFromCookie(\n cookieHeader: string | undefined,\n cookieName = 'ainative_token'\n): Session | null {\n if (!cookieHeader) {\n return null;\n }\n\n const cookies = cookieHeader.split(';').map((c) => c.trim());\n const tokenCookie = cookies.find((c) => c.startsWith(`${cookieName}=`));\n\n if (!tokenCookie) {\n return null;\n }\n\n const token = tokenCookie.substring(cookieName.length + 1);\n return decodeJWT(token);\n}\n\n/**\n * Get API key from cookies (App Router)\n *\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns JWT token or null\n */\nexport async function getApiKey(cookieName = 'ainative_token'): Promise<string | null> {\n try {\n const cookieStore = await cookies();\n const token = cookieStore.get(cookieName)?.value;\n return token || null;\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Get API key from cookie header (Pages Router)\n *\n * @param cookieHeader - Cookie header string from request\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns JWT token or null\n */\nexport function getApiKeyFromCookie(\n cookieHeader: string | undefined,\n cookieName = 'ainative_token'\n): string | null {\n if (!cookieHeader) {\n return null;\n }\n\n const cookies = cookieHeader.split(';').map((c) => c.trim());\n const tokenCookie = cookies.find((c) => c.startsWith(`${cookieName}=`));\n\n if (!tokenCookie) {\n return null;\n }\n\n return tokenCookie.substring(cookieName.length + 1);\n}\n","/**\n * Higher-order function for API route authentication\n */\n\nimport type { NextRequest } from 'next/server';\nimport { NextResponse } from 'next/server';\nimport type { WithAuthOptions, Session } from '../types';\nimport { getSessionFromCookie, getApiKeyFromCookie } from './getSession';\n\n/**\n * Request handler with authentication\n */\ntype AuthHandler = (\n req: NextRequest,\n context: { session: Session; apiKey: string; params?: any }\n) => Promise<Response> | Response;\n\n/**\n * Wrap API route handler with authentication\n *\n * Use this to protect API routes in both App Router and Pages Router.\n *\n * @param handler - Route handler function\n * @param options - Authentication options\n * @returns Protected route handler\n *\n * @example\n * ```tsx\n * // app/api/chat/route.ts\n * import { withAuth } from '@ainative/next-sdk/server';\n * import { createServerClient } from '@ainative/next-sdk/server';\n *\n * export const POST = withAuth(async (req, { session, apiKey }) => {\n * const client = createServerClient({ apiKey });\n * const body = await req.json();\n *\n * const response = await client.chat.completions.create({\n * messages: body.messages,\n * });\n *\n * return Response.json(response);\n * });\n * ```\n */\nexport function withAuth(handler: AuthHandler, options: WithAuthOptions = {}) {\n const cookieName = options.cookieName || 'ainative_token';\n\n return async (req: NextRequest, context?: { params: any }) => {\n try {\n // Get cookie from request\n const cookieHeader = req.headers.get('cookie');\n const session = getSessionFromCookie(cookieHeader || undefined, cookieName);\n\n if (!session) {\n return NextResponse.json(\n { error: 'Unauthorized', message: 'Authentication required' },\n { status: 401 }\n );\n }\n\n // Get API key\n const apiKey = getApiKeyFromCookie(cookieHeader || undefined, cookieName);\n\n if (!apiKey) {\n return NextResponse.json(\n { error: 'Unauthorized', message: 'API key not found' },\n { status: 401 }\n );\n }\n\n // Call handler with session and apiKey\n return await handler(req, {\n session,\n apiKey,\n params: context?.params,\n });\n } catch (error) {\n console.error('Auth middleware error:', error);\n return NextResponse.json(\n { error: 'Internal Server Error', message: 'Authentication failed' },\n { status: 500 }\n );\n }\n };\n}\n\n/**\n * Wrap Pages Router API handler with authentication\n *\n * Use this for API routes in the pages directory.\n *\n * @param handler - Route handler function\n * @param options - Authentication options\n * @returns Protected route handler\n *\n * @example\n * ```tsx\n * // pages/api/chat.ts\n * import { withAuthPages } from '@ainative/next-sdk/server';\n * import { createServerClient } from '@ainative/next-sdk/server';\n * import type { NextApiRequest, NextApiResponse } from 'next';\n *\n * export default withAuthPages(async (req, res, { session, apiKey }) => {\n * const client = createServerClient({ apiKey });\n *\n * const response = await client.chat.completions.create({\n * messages: req.body.messages,\n * });\n *\n * res.status(200).json(response);\n * });\n * ```\n */\nexport function withAuthPages(\n handler: (\n req: any,\n res: any,\n context: { session: Session; apiKey: string }\n ) => Promise<void> | void,\n options: WithAuthOptions = {}\n) {\n const cookieName = options.cookieName || 'ainative_token';\n\n return async (req: any, res: any) => {\n try {\n const cookieHeader = req.headers.cookie;\n const session = getSessionFromCookie(cookieHeader, cookieName);\n\n if (!session) {\n return res.status(401).json({\n error: 'Unauthorized',\n message: 'Authentication required',\n });\n }\n\n const apiKey = getApiKeyFromCookie(cookieHeader, cookieName);\n\n if (!apiKey) {\n return res.status(401).json({\n error: 'Unauthorized',\n message: 'API key not found',\n });\n }\n\n return await handler(req, res, { session, apiKey });\n } catch (error) {\n console.error('Auth middleware error:', error);\n return res.status(500).json({\n error: 'Internal Server Error',\n message: 'Authentication failed',\n });\n }\n };\n}\n"],"names":["createServerClient","config","baseUrl","async","fetchAPI","endpoint","options","url","response","fetch","headers","Authorization","apiKey","ok","error","json","catch","message","status","statusText","Error","chat","completions","create","request","method","body","JSON","stringify","credits","balance","decodeJWT","token","parts","split","length","payload","decoded","Buffer","from","toString","parsed","parse","userId","email","exp","iat","now","Math","floor","Date","getSession","cookieName","cookieStore","cookies","get","value","getSessionFromCookie","cookieHeader","tokenCookie","map","c","trim","find","startsWith","substring","getApiKey","getApiKeyFromCookie","withAuth","handler","req","context","session","undefined","NextResponse","params","console","withAuthPages","res","cookie"],"mappings":"mKAqCM,SAAUA,EAAmBC,GACjC,MAAMC,EAAUD,EAAOC,SAAW,qCAKlCC,eAAeC,EAAYC,EAAkBC,EAAuB,IAClE,MAAMC,EAAM,GAAGL,IAAUG,IAEnBG,QAAiBC,MAAMF,EAAK,IAC7BD,EACHI,QAAS,CACP,eAAgB,mBAChBC,cAAe,UAAUV,EAAOW,YAC7BN,EAAQI,WAIf,IAAKF,EAASK,GAAI,CAChB,MAAMC,QAAcN,EAASO,OAAOC,MAAM,KAAO,CAC/CC,QAAS,QAAQT,EAASU,WAAWV,EAASW,gBAGhD,MAAM,IAAIC,MAAMN,EAAMG,SAAW,8BAA8BT,EAASU,SACzE,CAED,OAAOV,EAASO,MACjB,CAED,MAAO,CACLM,KAAM,CACJC,YAAa,CAIXC,OAAQpB,MAAOqB,GACNpB,EAAiC,2BAA4B,CAClEqB,OAAQ,OACRC,KAAMC,KAAKC,UAAUJ,OAK7BK,QAAS,CAIPC,QAAS3B,SACAC,EAAwB,4BAIvC,CC1EA,SAAS2B,EAAUC,GACjB,IACE,MAAMC,EAAQD,EAAME,MAAM,KAC1B,GAAqB,IAAjBD,EAAME,OACR,OAAO,KAGT,MAAMC,EAAUH,EAAM,GAChBI,EAAUC,OAAOC,KAAKH,EAAS,UAAUI,SAAS,SAClDC,EAASd,KAAKe,MAAML,GAG1B,KAAKI,EAAOE,QAAWF,EAAOG,OAAUH,EAAOI,KAAQJ,EAAOK,KAC5D,OAAO,KAIT,MAAMC,EAAMC,KAAKC,MAAMC,KAAKH,MAAQ,KACpC,OAAIN,EAAOI,IAAME,EACR,KAGF,CACLJ,OAAQF,EAAOE,OACfC,MAAOH,EAAOG,MACdC,IAAKJ,EAAOI,IACZC,IAAKL,EAAOK,IAEf,CAAC,MAAOhC,GACP,OAAO,IACR,CACH,CA0BOX,eAAegD,EAAWC,EAAa,kBAC5C,IACE,MAAMC,QAAoBC,IACpBtB,EAAQqB,EAAYE,IAAIH,IAAaI,MAE3C,OAAKxB,EAIED,EAAUC,GAHR,IAIV,CAAC,MAAOlB,GACP,OAAO,IACR,CACH,UA2BgB2C,EACdC,EACAN,EAAa,kBAEb,IAAKM,EACH,OAAO,KAGT,MACMC,EADUD,EAAaxB,MAAM,KAAK0B,IAAKC,GAAMA,EAAEC,QACzBC,KAAMF,GAAMA,EAAEG,WAAW,GAAGZ,OAExD,IAAKO,EACH,OAAO,KAIT,OAAO5B,EADO4B,EAAYM,UAAUb,EAAWjB,OAAS,GAE1D,CAQOhC,eAAe+D,EAAUd,EAAa,kBAC3C,IACE,MAAMC,QAAoBC,IACpBtB,EAAQqB,EAAYE,IAAIH,IAAaI,MAC3C,OAAOxB,GAAS,IACjB,CAAC,MAAOlB,GACP,OAAO,IACR,CACH,UASgBqD,EACdT,EACAN,EAAa,kBAEb,IAAKM,EACH,OAAO,KAGT,MACMC,EADUD,EAAaxB,MAAM,KAAK0B,IAAKC,GAAMA,EAAEC,QACzBC,KAAMF,GAAMA,EAAEG,WAAW,GAAGZ,OAExD,OAAKO,EAIEA,EAAYM,UAAUb,EAAWjB,OAAS,GAHxC,IAIX,UC9HgBiC,EAASC,EAAsB/D,EAA2B,IACxE,MAAM8C,EAAa9C,EAAQ8C,YAAc,iBAEzC,OAAOjD,MAAOmE,EAAkBC,KAC9B,IAEE,MAAMb,EAAeY,EAAI5D,QAAQ6C,IAAI,UAC/BiB,EAAUf,EAAqBC,QAAgBe,EAAWrB,GAEhE,IAAKoB,EACH,OAAOE,EAAa3D,KAClB,CAAED,MAAO,eAAgBG,QAAS,2BAClC,CAAEC,OAAQ,MAKd,MAAMN,EAASuD,EAAoBT,QAAgBe,EAAWrB,GAE9D,OAAKxC,QAQQyD,EAAQC,EAAK,CACxBE,UACA5D,SACA+D,OAAQJ,GAASI,SAVVD,EAAa3D,KAClB,CAAED,MAAO,eAAgBG,QAAS,qBAClC,CAAEC,OAAQ,KAUf,CAAC,MAAOJ,GAEP,OADA8D,QAAQ9D,MAAM,yBAA0BA,GACjC4D,EAAa3D,KAClB,CAAED,MAAO,wBAAyBG,QAAS,yBAC3C,CAAEC,OAAQ,KAEb,EAEL,UA6BgB2D,EACdR,EAKA/D,EAA2B,IAE3B,MAAM8C,EAAa9C,EAAQ8C,YAAc,iBAEzC,OAAOjD,MAAOmE,EAAUQ,KACtB,IACE,MAAMpB,EAAeY,EAAI5D,QAAQqE,OAC3BP,EAAUf,EAAqBC,EAAcN,GAEnD,IAAKoB,EACH,OAAOM,EAAI5D,OAAO,KAAKH,KAAK,CAC1BD,MAAO,eACPG,QAAS,4BAIb,MAAML,EAASuD,EAAoBT,EAAcN,GAEjD,OAAKxC,QAOQyD,EAAQC,EAAKQ,EAAK,CAAEN,UAAS5D,WANjCkE,EAAI5D,OAAO,KAAKH,KAAK,CAC1BD,MAAO,eACPG,QAAS,qBAKd,CAAC,MAAOH,GAEP,OADA8D,QAAQ9D,MAAM,yBAA0BA,GACjCgE,EAAI5D,OAAO,KAAKH,KAAK,CAC1BD,MAAO,wBACPG,QAAS,yBAEZ,EAEL"}
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var e=require("next/headers"),t=require("next/server"),r=require("@ainative/react-sdk");function n(e){try{const t=e.split(".");if(3!==t.length)return null;const r=t[1],n=Buffer.from(r,"base64").toString("utf-8"),s=JSON.parse(n);if(!(s.userId&&s.email&&s.exp&&s.iat))return null;const o=Math.floor(Date.now()/1e3);return s.exp<o?null:{userId:s.userId,email:s.email,exp:s.exp,iat:s.iat}}catch(e){return null}}function s(e,t="ainative_token"){if(!e)return null;const r=e.split(";").map(e=>e.trim()).find(e=>e.startsWith(`${t}=`));if(!r)return null;return n(r.substring(t.length+1))}function o(e,t="ainative_token"){if(!e)return null;const r=e.split(";").map(e=>e.trim()).find(e=>e.startsWith(`${t}=`));return r?r.substring(t.length+1):null}Object.defineProperty(exports,"AINativeProvider",{enumerable:!0,get:function(){return r.AINativeProvider}}),Object.defineProperty(exports,"useAINative",{enumerable:!0,get:function(){return r.useAINative}}),Object.defineProperty(exports,"useChat",{enumerable:!0,get:function(){return r.useChat}}),Object.defineProperty(exports,"useCredits",{enumerable:!0,get:function(){return r.useCredits}}),exports.createServerClient=function(e){const t=e.baseUrl||"https://api.ainative.studio/api/v1";async function r(r,n={}){const s=`${t}${r}`,o=await fetch(s,{...n,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`,...n.headers}});if(!o.ok){const e=await o.json().catch(()=>({message:`HTTP ${o.status}: ${o.statusText}`}));throw new Error(e.message||`Request failed with status ${o.status}`)}return o.json()}return{chat:{completions:{create:async e=>r("/public/chat/completions",{method:"POST",body:JSON.stringify(e)})}},credits:{balance:async()=>r("/public/credits/balance")}}},exports.getApiKey=async function(t="ainative_token"){try{const r=await e.cookies(),n=r.get(t)?.value;return n||null}catch(e){return null}},exports.getApiKeyFromCookie=o,exports.getSession=async function(t="ainative_token"){try{const r=await e.cookies(),s=r.get(t)?.value;return s?n(s):null}catch(e){return null}},exports.getSessionFromCookie=s,exports.withAuth=function(e,r={}){const n=r.cookieName||"ainative_token";return async(r,i)=>{try{const a=r.headers.get("cookie"),u=s(a||void 0,n);if(!u)return t.NextResponse.json({error:"Unauthorized",message:"Authentication required"},{status:401});const c=o(a||void 0,n);return c?await e(r,{session:u,apiKey:c,params:i?.params}):t.NextResponse.json({error:"Unauthorized",message:"API key not found"},{status:401})}catch(e){return console.error("Auth middleware error:",e),t.NextResponse.json({error:"Internal Server Error",message:"Authentication failed"},{status:500})}}},exports.withAuthPages=function(e,t={}){const r=t.cookieName||"ainative_token";return async(t,n)=>{try{const i=t.headers.cookie,a=s(i,r);if(!a)return n.status(401).json({error:"Unauthorized",message:"Authentication required"});const u=o(i,r);return u?await e(t,n,{session:a,apiKey:u}):n.status(401).json({error:"Unauthorized",message:"API key not found"})}catch(e){return console.error("Auth middleware error:",e),n.status(500).json({error:"Internal Server Error",message:"Authentication failed"})}}};
2
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sources":["../src/server/getSession.ts","../src/server/createServerClient.ts","../src/server/withAuth.ts"],"sourcesContent":["/**\n * Get session from JWT token stored in cookies\n *\n * Supports both App Router and Pages Router\n */\n\nimport { cookies } from 'next/headers';\nimport type { Session } from '../types';\n\n/**\n * Decode JWT token without verification (server-side only)\n *\n * @param token - JWT token string\n * @returns Decoded session data or null if invalid\n */\nfunction decodeJWT(token: string): Session | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return null;\n }\n\n const payload = parts[1];\n const decoded = Buffer.from(payload, 'base64').toString('utf-8');\n const parsed = JSON.parse(decoded);\n\n // Validate required fields\n if (!parsed.userId || !parsed.email || !parsed.exp || !parsed.iat) {\n return null;\n }\n\n // Check expiration\n const now = Math.floor(Date.now() / 1000);\n if (parsed.exp < now) {\n return null;\n }\n\n return {\n userId: parsed.userId,\n email: parsed.email,\n exp: parsed.exp,\n iat: parsed.iat,\n };\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Get session from cookies (App Router)\n *\n * Use this in Server Components and Server Actions.\n *\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns Session data or null if not authenticated\n *\n * @example\n * ```tsx\n * // app/dashboard/page.tsx\n * import { getSession } from '@ainative/next-sdk/server';\n *\n * export default async function DashboardPage() {\n * const session = await getSession();\n *\n * if (!session) {\n * redirect('/login');\n * }\n *\n * return <div>Welcome {session.email}</div>;\n * }\n * ```\n */\nexport async function getSession(cookieName = 'ainative_token'): Promise<Session | null> {\n try {\n const cookieStore = await cookies();\n const token = cookieStore.get(cookieName)?.value;\n\n if (!token) {\n return null;\n }\n\n return decodeJWT(token);\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Get session from cookies (Pages Router)\n *\n * Use this in getServerSideProps or API routes.\n *\n * @param cookieHeader - Cookie header string from request\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns Session data or null if not authenticated\n *\n * @example\n * ```tsx\n * // pages/dashboard.tsx\n * import { getSessionFromCookie } from '@ainative/next-sdk/server';\n *\n * export async function getServerSideProps({ req }) {\n * const session = getSessionFromCookie(req.headers.cookie);\n *\n * if (!session) {\n * return { redirect: { destination: '/login', permanent: false } };\n * }\n *\n * return { props: { session } };\n * }\n * ```\n */\nexport function getSessionFromCookie(\n cookieHeader: string | undefined,\n cookieName = 'ainative_token'\n): Session | null {\n if (!cookieHeader) {\n return null;\n }\n\n const cookies = cookieHeader.split(';').map((c) => c.trim());\n const tokenCookie = cookies.find((c) => c.startsWith(`${cookieName}=`));\n\n if (!tokenCookie) {\n return null;\n }\n\n const token = tokenCookie.substring(cookieName.length + 1);\n return decodeJWT(token);\n}\n\n/**\n * Get API key from cookies (App Router)\n *\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns JWT token or null\n */\nexport async function getApiKey(cookieName = 'ainative_token'): Promise<string | null> {\n try {\n const cookieStore = await cookies();\n const token = cookieStore.get(cookieName)?.value;\n return token || null;\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Get API key from cookie header (Pages Router)\n *\n * @param cookieHeader - Cookie header string from request\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns JWT token or null\n */\nexport function getApiKeyFromCookie(\n cookieHeader: string | undefined,\n cookieName = 'ainative_token'\n): string | null {\n if (!cookieHeader) {\n return null;\n }\n\n const cookies = cookieHeader.split(';').map((c) => c.trim());\n const tokenCookie = cookies.find((c) => c.startsWith(`${cookieName}=`));\n\n if (!tokenCookie) {\n return null;\n }\n\n return tokenCookie.substring(cookieName.length + 1);\n}\n","/**\n * Create server-side API client for Next.js Server Components\n */\n\nimport type {\n ServerClient,\n ServerClientConfig,\n ChatCompletionRequest,\n ChatCompletionResponse,\n CreditBalance,\n} from '../types';\n\n/**\n * Create a server-side API client\n *\n * Use this in Server Components, Server Actions, and API routes.\n *\n * @param config - Client configuration with API key\n * @returns Server-side API client\n *\n * @example\n * ```tsx\n * // app/chat/page.tsx\n * import { createServerClient } from '@ainative/next-sdk/server';\n * import { getApiKey } from '@ainative/next-sdk/server';\n *\n * export default async function ChatPage() {\n * const apiKey = await getApiKey();\n * if (!apiKey) return <div>Not authenticated</div>;\n *\n * const client = createServerClient({ apiKey });\n * const balance = await client.credits.balance();\n *\n * return <div>Credits: {balance.remaining_credits}</div>;\n * }\n * ```\n */\nexport function createServerClient(config: ServerClientConfig): ServerClient {\n const baseUrl = config.baseUrl || 'https://api.ainative.studio/api/v1';\n\n /**\n * Make authenticated API request\n */\n async function fetchAPI<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\n const url = `${baseUrl}${endpoint}`;\n\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${config.apiKey}`,\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({\n message: `HTTP ${response.status}: ${response.statusText}`,\n })) as { message?: string };\n\n throw new Error(error.message || `Request failed with status ${response.status}`);\n }\n\n return response.json() as Promise<T>;\n }\n\n return {\n chat: {\n completions: {\n /**\n * Create chat completion\n */\n create: async (request: ChatCompletionRequest): Promise<ChatCompletionResponse> => {\n return fetchAPI<ChatCompletionResponse>('/public/chat/completions', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n },\n },\n },\n credits: {\n /**\n * Get credit balance\n */\n balance: async (): Promise<CreditBalance> => {\n return fetchAPI<CreditBalance>('/public/credits/balance');\n },\n },\n };\n}\n","/**\n * Higher-order function for API route authentication\n */\n\nimport type { NextRequest } from 'next/server';\nimport { NextResponse } from 'next/server';\nimport type { WithAuthOptions, Session } from '../types';\nimport { getSessionFromCookie, getApiKeyFromCookie } from './getSession';\n\n/**\n * Request handler with authentication\n */\ntype AuthHandler = (\n req: NextRequest,\n context: { session: Session; apiKey: string; params?: any }\n) => Promise<Response> | Response;\n\n/**\n * Wrap API route handler with authentication\n *\n * Use this to protect API routes in both App Router and Pages Router.\n *\n * @param handler - Route handler function\n * @param options - Authentication options\n * @returns Protected route handler\n *\n * @example\n * ```tsx\n * // app/api/chat/route.ts\n * import { withAuth } from '@ainative/next-sdk/server';\n * import { createServerClient } from '@ainative/next-sdk/server';\n *\n * export const POST = withAuth(async (req, { session, apiKey }) => {\n * const client = createServerClient({ apiKey });\n * const body = await req.json();\n *\n * const response = await client.chat.completions.create({\n * messages: body.messages,\n * });\n *\n * return Response.json(response);\n * });\n * ```\n */\nexport function withAuth(handler: AuthHandler, options: WithAuthOptions = {}) {\n const cookieName = options.cookieName || 'ainative_token';\n\n return async (req: NextRequest, context?: { params: any }) => {\n try {\n // Get cookie from request\n const cookieHeader = req.headers.get('cookie');\n const session = getSessionFromCookie(cookieHeader || undefined, cookieName);\n\n if (!session) {\n return NextResponse.json(\n { error: 'Unauthorized', message: 'Authentication required' },\n { status: 401 }\n );\n }\n\n // Get API key\n const apiKey = getApiKeyFromCookie(cookieHeader || undefined, cookieName);\n\n if (!apiKey) {\n return NextResponse.json(\n { error: 'Unauthorized', message: 'API key not found' },\n { status: 401 }\n );\n }\n\n // Call handler with session and apiKey\n return await handler(req, {\n session,\n apiKey,\n params: context?.params,\n });\n } catch (error) {\n console.error('Auth middleware error:', error);\n return NextResponse.json(\n { error: 'Internal Server Error', message: 'Authentication failed' },\n { status: 500 }\n );\n }\n };\n}\n\n/**\n * Wrap Pages Router API handler with authentication\n *\n * Use this for API routes in the pages directory.\n *\n * @param handler - Route handler function\n * @param options - Authentication options\n * @returns Protected route handler\n *\n * @example\n * ```tsx\n * // pages/api/chat.ts\n * import { withAuthPages } from '@ainative/next-sdk/server';\n * import { createServerClient } from '@ainative/next-sdk/server';\n * import type { NextApiRequest, NextApiResponse } from 'next';\n *\n * export default withAuthPages(async (req, res, { session, apiKey }) => {\n * const client = createServerClient({ apiKey });\n *\n * const response = await client.chat.completions.create({\n * messages: req.body.messages,\n * });\n *\n * res.status(200).json(response);\n * });\n * ```\n */\nexport function withAuthPages(\n handler: (\n req: any,\n res: any,\n context: { session: Session; apiKey: string }\n ) => Promise<void> | void,\n options: WithAuthOptions = {}\n) {\n const cookieName = options.cookieName || 'ainative_token';\n\n return async (req: any, res: any) => {\n try {\n const cookieHeader = req.headers.cookie;\n const session = getSessionFromCookie(cookieHeader, cookieName);\n\n if (!session) {\n return res.status(401).json({\n error: 'Unauthorized',\n message: 'Authentication required',\n });\n }\n\n const apiKey = getApiKeyFromCookie(cookieHeader, cookieName);\n\n if (!apiKey) {\n return res.status(401).json({\n error: 'Unauthorized',\n message: 'API key not found',\n });\n }\n\n return await handler(req, res, { session, apiKey });\n } catch (error) {\n console.error('Auth middleware error:', error);\n return res.status(500).json({\n error: 'Internal Server Error',\n message: 'Authentication failed',\n });\n }\n };\n}\n"],"names":["decodeJWT","token","parts","split","length","payload","decoded","Buffer","from","toString","parsed","JSON","parse","userId","email","exp","iat","now","Math","floor","Date","error","getSessionFromCookie","cookieHeader","cookieName","tokenCookie","map","c","trim","find","startsWith","substring","getApiKeyFromCookie","config","baseUrl","async","fetchAPI","endpoint","options","url","response","fetch","headers","Authorization","apiKey","ok","json","catch","message","status","statusText","Error","chat","completions","create","request","method","body","stringify","credits","balance","cookieStore","cookies","get","value","handler","req","context","session","undefined","NextResponse","params","console","res","cookie"],"mappings":"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"}
@@ -0,0 +1,230 @@
1
+ import { ChatCompletionRequest, ChatCompletionResponse, CreditBalance } from '@ainative/react-sdk';
2
+ import { NextRequest } from 'next/server';
3
+
4
+ /**
5
+ * AINative Next.js SDK Type Definitions
6
+ */
7
+
8
+ /**
9
+ * Session data extracted from JWT token
10
+ */
11
+ interface Session {
12
+ userId: string;
13
+ email: string;
14
+ exp: number;
15
+ iat: number;
16
+ }
17
+ /**
18
+ * Server-side API client configuration
19
+ */
20
+ interface ServerClientConfig {
21
+ apiKey: string;
22
+ baseUrl?: string;
23
+ }
24
+ /**
25
+ * Options for withAuth higher-order function
26
+ */
27
+ interface WithAuthOptions {
28
+ cookieName?: string;
29
+ redirectTo?: string;
30
+ }
31
+ /**
32
+ * Next.js API route request with authentication
33
+ */
34
+ interface AuthenticatedRequest {
35
+ session: Session;
36
+ apiKey: string;
37
+ }
38
+ /**
39
+ * Server-side API client for Next.js Server Components
40
+ */
41
+ interface ServerClient {
42
+ chat: {
43
+ completions: {
44
+ create: (request: ChatCompletionRequest) => Promise<ChatCompletionResponse>;
45
+ };
46
+ };
47
+ credits: {
48
+ balance: () => Promise<CreditBalance>;
49
+ };
50
+ }
51
+
52
+ /**
53
+ * Create server-side API client for Next.js Server Components
54
+ */
55
+
56
+ /**
57
+ * Create a server-side API client
58
+ *
59
+ * Use this in Server Components, Server Actions, and API routes.
60
+ *
61
+ * @param config - Client configuration with API key
62
+ * @returns Server-side API client
63
+ *
64
+ * @example
65
+ * ```tsx
66
+ * // app/chat/page.tsx
67
+ * import { createServerClient } from '@ainative/next-sdk/server';
68
+ * import { getApiKey } from '@ainative/next-sdk/server';
69
+ *
70
+ * export default async function ChatPage() {
71
+ * const apiKey = await getApiKey();
72
+ * if (!apiKey) return <div>Not authenticated</div>;
73
+ *
74
+ * const client = createServerClient({ apiKey });
75
+ * const balance = await client.credits.balance();
76
+ *
77
+ * return <div>Credits: {balance.remaining_credits}</div>;
78
+ * }
79
+ * ```
80
+ */
81
+ declare function createServerClient(config: ServerClientConfig): ServerClient;
82
+
83
+ /**
84
+ * Get session from JWT token stored in cookies
85
+ *
86
+ * Supports both App Router and Pages Router
87
+ */
88
+
89
+ /**
90
+ * Get session from cookies (App Router)
91
+ *
92
+ * Use this in Server Components and Server Actions.
93
+ *
94
+ * @param cookieName - Cookie name (default: 'ainative_token')
95
+ * @returns Session data or null if not authenticated
96
+ *
97
+ * @example
98
+ * ```tsx
99
+ * // app/dashboard/page.tsx
100
+ * import { getSession } from '@ainative/next-sdk/server';
101
+ *
102
+ * export default async function DashboardPage() {
103
+ * const session = await getSession();
104
+ *
105
+ * if (!session) {
106
+ * redirect('/login');
107
+ * }
108
+ *
109
+ * return <div>Welcome {session.email}</div>;
110
+ * }
111
+ * ```
112
+ */
113
+ declare function getSession(cookieName?: string): Promise<Session | null>;
114
+ /**
115
+ * Get session from cookies (Pages Router)
116
+ *
117
+ * Use this in getServerSideProps or API routes.
118
+ *
119
+ * @param cookieHeader - Cookie header string from request
120
+ * @param cookieName - Cookie name (default: 'ainative_token')
121
+ * @returns Session data or null if not authenticated
122
+ *
123
+ * @example
124
+ * ```tsx
125
+ * // pages/dashboard.tsx
126
+ * import { getSessionFromCookie } from '@ainative/next-sdk/server';
127
+ *
128
+ * export async function getServerSideProps({ req }) {
129
+ * const session = getSessionFromCookie(req.headers.cookie);
130
+ *
131
+ * if (!session) {
132
+ * return { redirect: { destination: '/login', permanent: false } };
133
+ * }
134
+ *
135
+ * return { props: { session } };
136
+ * }
137
+ * ```
138
+ */
139
+ declare function getSessionFromCookie(cookieHeader: string | undefined, cookieName?: string): Session | null;
140
+ /**
141
+ * Get API key from cookies (App Router)
142
+ *
143
+ * @param cookieName - Cookie name (default: 'ainative_token')
144
+ * @returns JWT token or null
145
+ */
146
+ declare function getApiKey(cookieName?: string): Promise<string | null>;
147
+ /**
148
+ * Get API key from cookie header (Pages Router)
149
+ *
150
+ * @param cookieHeader - Cookie header string from request
151
+ * @param cookieName - Cookie name (default: 'ainative_token')
152
+ * @returns JWT token or null
153
+ */
154
+ declare function getApiKeyFromCookie(cookieHeader: string | undefined, cookieName?: string): string | null;
155
+
156
+ /**
157
+ * Higher-order function for API route authentication
158
+ */
159
+
160
+ /**
161
+ * Request handler with authentication
162
+ */
163
+ type AuthHandler = (req: NextRequest, context: {
164
+ session: Session;
165
+ apiKey: string;
166
+ params?: any;
167
+ }) => Promise<Response> | Response;
168
+ /**
169
+ * Wrap API route handler with authentication
170
+ *
171
+ * Use this to protect API routes in both App Router and Pages Router.
172
+ *
173
+ * @param handler - Route handler function
174
+ * @param options - Authentication options
175
+ * @returns Protected route handler
176
+ *
177
+ * @example
178
+ * ```tsx
179
+ * // app/api/chat/route.ts
180
+ * import { withAuth } from '@ainative/next-sdk/server';
181
+ * import { createServerClient } from '@ainative/next-sdk/server';
182
+ *
183
+ * export const POST = withAuth(async (req, { session, apiKey }) => {
184
+ * const client = createServerClient({ apiKey });
185
+ * const body = await req.json();
186
+ *
187
+ * const response = await client.chat.completions.create({
188
+ * messages: body.messages,
189
+ * });
190
+ *
191
+ * return Response.json(response);
192
+ * });
193
+ * ```
194
+ */
195
+ declare function withAuth(handler: AuthHandler, options?: WithAuthOptions): (req: NextRequest, context?: {
196
+ params: any;
197
+ }) => Promise<Response>;
198
+ /**
199
+ * Wrap Pages Router API handler with authentication
200
+ *
201
+ * Use this for API routes in the pages directory.
202
+ *
203
+ * @param handler - Route handler function
204
+ * @param options - Authentication options
205
+ * @returns Protected route handler
206
+ *
207
+ * @example
208
+ * ```tsx
209
+ * // pages/api/chat.ts
210
+ * import { withAuthPages } from '@ainative/next-sdk/server';
211
+ * import { createServerClient } from '@ainative/next-sdk/server';
212
+ * import type { NextApiRequest, NextApiResponse } from 'next';
213
+ *
214
+ * export default withAuthPages(async (req, res, { session, apiKey }) => {
215
+ * const client = createServerClient({ apiKey });
216
+ *
217
+ * const response = await client.chat.completions.create({
218
+ * messages: req.body.messages,
219
+ * });
220
+ *
221
+ * res.status(200).json(response);
222
+ * });
223
+ * ```
224
+ */
225
+ declare function withAuthPages(handler: (req: any, res: any, context: {
226
+ session: Session;
227
+ apiKey: string;
228
+ }) => Promise<void> | void, options?: WithAuthOptions): (req: any, res: any) => Promise<any>;
229
+
230
+ export { AuthenticatedRequest, ServerClient, ServerClientConfig, Session, WithAuthOptions, createServerClient, getApiKey, getApiKeyFromCookie, getSession, getSessionFromCookie, withAuth, withAuthPages };
@@ -0,0 +1,2 @@
1
+ import{cookies as t}from"next/headers";import{NextResponse as e}from"next/server";function n(t){const e=t.baseUrl||"https://api.ainative.studio/api/v1";async function n(n,r={}){const a=`${e}${n}`,s=await fetch(a,{...r,headers:{"Content-Type":"application/json",Authorization:`Bearer ${t.apiKey}`,...r.headers}});if(!s.ok){const t=await s.json().catch(()=>({message:`HTTP ${s.status}: ${s.statusText}`}));throw new Error(t.message||`Request failed with status ${s.status}`)}return s.json()}return{chat:{completions:{create:async t=>n("/public/chat/completions",{method:"POST",body:JSON.stringify(t)})}},credits:{balance:async()=>n("/public/credits/balance")}}}function r(t){try{const e=t.split(".");if(3!==e.length)return null;const n=e[1],r=Buffer.from(n,"base64").toString("utf-8"),a=JSON.parse(r);if(!(a.userId&&a.email&&a.exp&&a.iat))return null;const s=Math.floor(Date.now()/1e3);return a.exp<s?null:{userId:a.userId,email:a.email,exp:a.exp,iat:a.iat}}catch(t){return null}}async function a(e="ainative_token"){try{const n=await t(),a=n.get(e)?.value;return a?r(a):null}catch(t){return null}}function s(t,e="ainative_token"){if(!t)return null;const n=t.split(";").map(t=>t.trim()).find(t=>t.startsWith(`${e}=`));if(!n)return null;return r(n.substring(e.length+1))}async function o(e="ainative_token"){try{const n=await t(),r=n.get(e)?.value;return r||null}catch(t){return null}}function i(t,e="ainative_token"){if(!t)return null;const n=t.split(";").map(t=>t.trim()).find(t=>t.startsWith(`${e}=`));return n?n.substring(e.length+1):null}function u(t,n={}){const r=n.cookieName||"ainative_token";return async(n,a)=>{try{const o=n.headers.get("cookie"),u=s(o||void 0,r);if(!u)return e.json({error:"Unauthorized",message:"Authentication required"},{status:401});const c=i(o||void 0,r);return c?await t(n,{session:u,apiKey:c,params:a?.params}):e.json({error:"Unauthorized",message:"API key not found"},{status:401})}catch(t){return console.error("Auth middleware error:",t),e.json({error:"Internal Server Error",message:"Authentication failed"},{status:500})}}}function c(t,e={}){const n=e.cookieName||"ainative_token";return async(e,r)=>{try{const a=e.headers.cookie,o=s(a,n);if(!o)return r.status(401).json({error:"Unauthorized",message:"Authentication required"});const u=i(a,n);return u?await t(e,r,{session:o,apiKey:u}):r.status(401).json({error:"Unauthorized",message:"API key not found"})}catch(t){return console.error("Auth middleware error:",t),r.status(500).json({error:"Internal Server Error",message:"Authentication failed"})}}}export{n as createServerClient,o as getApiKey,i as getApiKeyFromCookie,a as getSession,s as getSessionFromCookie,u as withAuth,c as withAuthPages};
2
+ //# sourceMappingURL=server.esm.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.esm.js","sources":["../src/server/createServerClient.ts","../src/server/getSession.ts","../src/server/withAuth.ts"],"sourcesContent":["/**\n * Create server-side API client for Next.js Server Components\n */\n\nimport type {\n ServerClient,\n ServerClientConfig,\n ChatCompletionRequest,\n ChatCompletionResponse,\n CreditBalance,\n} from '../types';\n\n/**\n * Create a server-side API client\n *\n * Use this in Server Components, Server Actions, and API routes.\n *\n * @param config - Client configuration with API key\n * @returns Server-side API client\n *\n * @example\n * ```tsx\n * // app/chat/page.tsx\n * import { createServerClient } from '@ainative/next-sdk/server';\n * import { getApiKey } from '@ainative/next-sdk/server';\n *\n * export default async function ChatPage() {\n * const apiKey = await getApiKey();\n * if (!apiKey) return <div>Not authenticated</div>;\n *\n * const client = createServerClient({ apiKey });\n * const balance = await client.credits.balance();\n *\n * return <div>Credits: {balance.remaining_credits}</div>;\n * }\n * ```\n */\nexport function createServerClient(config: ServerClientConfig): ServerClient {\n const baseUrl = config.baseUrl || 'https://api.ainative.studio/api/v1';\n\n /**\n * Make authenticated API request\n */\n async function fetchAPI<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\n const url = `${baseUrl}${endpoint}`;\n\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${config.apiKey}`,\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({\n message: `HTTP ${response.status}: ${response.statusText}`,\n })) as { message?: string };\n\n throw new Error(error.message || `Request failed with status ${response.status}`);\n }\n\n return response.json() as Promise<T>;\n }\n\n return {\n chat: {\n completions: {\n /**\n * Create chat completion\n */\n create: async (request: ChatCompletionRequest): Promise<ChatCompletionResponse> => {\n return fetchAPI<ChatCompletionResponse>('/public/chat/completions', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n },\n },\n },\n credits: {\n /**\n * Get credit balance\n */\n balance: async (): Promise<CreditBalance> => {\n return fetchAPI<CreditBalance>('/public/credits/balance');\n },\n },\n };\n}\n","/**\n * Get session from JWT token stored in cookies\n *\n * Supports both App Router and Pages Router\n */\n\nimport { cookies } from 'next/headers';\nimport type { Session } from '../types';\n\n/**\n * Decode JWT token without verification (server-side only)\n *\n * @param token - JWT token string\n * @returns Decoded session data or null if invalid\n */\nfunction decodeJWT(token: string): Session | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return null;\n }\n\n const payload = parts[1];\n const decoded = Buffer.from(payload, 'base64').toString('utf-8');\n const parsed = JSON.parse(decoded);\n\n // Validate required fields\n if (!parsed.userId || !parsed.email || !parsed.exp || !parsed.iat) {\n return null;\n }\n\n // Check expiration\n const now = Math.floor(Date.now() / 1000);\n if (parsed.exp < now) {\n return null;\n }\n\n return {\n userId: parsed.userId,\n email: parsed.email,\n exp: parsed.exp,\n iat: parsed.iat,\n };\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Get session from cookies (App Router)\n *\n * Use this in Server Components and Server Actions.\n *\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns Session data or null if not authenticated\n *\n * @example\n * ```tsx\n * // app/dashboard/page.tsx\n * import { getSession } from '@ainative/next-sdk/server';\n *\n * export default async function DashboardPage() {\n * const session = await getSession();\n *\n * if (!session) {\n * redirect('/login');\n * }\n *\n * return <div>Welcome {session.email}</div>;\n * }\n * ```\n */\nexport async function getSession(cookieName = 'ainative_token'): Promise<Session | null> {\n try {\n const cookieStore = await cookies();\n const token = cookieStore.get(cookieName)?.value;\n\n if (!token) {\n return null;\n }\n\n return decodeJWT(token);\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Get session from cookies (Pages Router)\n *\n * Use this in getServerSideProps or API routes.\n *\n * @param cookieHeader - Cookie header string from request\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns Session data or null if not authenticated\n *\n * @example\n * ```tsx\n * // pages/dashboard.tsx\n * import { getSessionFromCookie } from '@ainative/next-sdk/server';\n *\n * export async function getServerSideProps({ req }) {\n * const session = getSessionFromCookie(req.headers.cookie);\n *\n * if (!session) {\n * return { redirect: { destination: '/login', permanent: false } };\n * }\n *\n * return { props: { session } };\n * }\n * ```\n */\nexport function getSessionFromCookie(\n cookieHeader: string | undefined,\n cookieName = 'ainative_token'\n): Session | null {\n if (!cookieHeader) {\n return null;\n }\n\n const cookies = cookieHeader.split(';').map((c) => c.trim());\n const tokenCookie = cookies.find((c) => c.startsWith(`${cookieName}=`));\n\n if (!tokenCookie) {\n return null;\n }\n\n const token = tokenCookie.substring(cookieName.length + 1);\n return decodeJWT(token);\n}\n\n/**\n * Get API key from cookies (App Router)\n *\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns JWT token or null\n */\nexport async function getApiKey(cookieName = 'ainative_token'): Promise<string | null> {\n try {\n const cookieStore = await cookies();\n const token = cookieStore.get(cookieName)?.value;\n return token || null;\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Get API key from cookie header (Pages Router)\n *\n * @param cookieHeader - Cookie header string from request\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns JWT token or null\n */\nexport function getApiKeyFromCookie(\n cookieHeader: string | undefined,\n cookieName = 'ainative_token'\n): string | null {\n if (!cookieHeader) {\n return null;\n }\n\n const cookies = cookieHeader.split(';').map((c) => c.trim());\n const tokenCookie = cookies.find((c) => c.startsWith(`${cookieName}=`));\n\n if (!tokenCookie) {\n return null;\n }\n\n return tokenCookie.substring(cookieName.length + 1);\n}\n","/**\n * Higher-order function for API route authentication\n */\n\nimport type { NextRequest } from 'next/server';\nimport { NextResponse } from 'next/server';\nimport type { WithAuthOptions, Session } from '../types';\nimport { getSessionFromCookie, getApiKeyFromCookie } from './getSession';\n\n/**\n * Request handler with authentication\n */\ntype AuthHandler = (\n req: NextRequest,\n context: { session: Session; apiKey: string; params?: any }\n) => Promise<Response> | Response;\n\n/**\n * Wrap API route handler with authentication\n *\n * Use this to protect API routes in both App Router and Pages Router.\n *\n * @param handler - Route handler function\n * @param options - Authentication options\n * @returns Protected route handler\n *\n * @example\n * ```tsx\n * // app/api/chat/route.ts\n * import { withAuth } from '@ainative/next-sdk/server';\n * import { createServerClient } from '@ainative/next-sdk/server';\n *\n * export const POST = withAuth(async (req, { session, apiKey }) => {\n * const client = createServerClient({ apiKey });\n * const body = await req.json();\n *\n * const response = await client.chat.completions.create({\n * messages: body.messages,\n * });\n *\n * return Response.json(response);\n * });\n * ```\n */\nexport function withAuth(handler: AuthHandler, options: WithAuthOptions = {}) {\n const cookieName = options.cookieName || 'ainative_token';\n\n return async (req: NextRequest, context?: { params: any }) => {\n try {\n // Get cookie from request\n const cookieHeader = req.headers.get('cookie');\n const session = getSessionFromCookie(cookieHeader || undefined, cookieName);\n\n if (!session) {\n return NextResponse.json(\n { error: 'Unauthorized', message: 'Authentication required' },\n { status: 401 }\n );\n }\n\n // Get API key\n const apiKey = getApiKeyFromCookie(cookieHeader || undefined, cookieName);\n\n if (!apiKey) {\n return NextResponse.json(\n { error: 'Unauthorized', message: 'API key not found' },\n { status: 401 }\n );\n }\n\n // Call handler with session and apiKey\n return await handler(req, {\n session,\n apiKey,\n params: context?.params,\n });\n } catch (error) {\n console.error('Auth middleware error:', error);\n return NextResponse.json(\n { error: 'Internal Server Error', message: 'Authentication failed' },\n { status: 500 }\n );\n }\n };\n}\n\n/**\n * Wrap Pages Router API handler with authentication\n *\n * Use this for API routes in the pages directory.\n *\n * @param handler - Route handler function\n * @param options - Authentication options\n * @returns Protected route handler\n *\n * @example\n * ```tsx\n * // pages/api/chat.ts\n * import { withAuthPages } from '@ainative/next-sdk/server';\n * import { createServerClient } from '@ainative/next-sdk/server';\n * import type { NextApiRequest, NextApiResponse } from 'next';\n *\n * export default withAuthPages(async (req, res, { session, apiKey }) => {\n * const client = createServerClient({ apiKey });\n *\n * const response = await client.chat.completions.create({\n * messages: req.body.messages,\n * });\n *\n * res.status(200).json(response);\n * });\n * ```\n */\nexport function withAuthPages(\n handler: (\n req: any,\n res: any,\n context: { session: Session; apiKey: string }\n ) => Promise<void> | void,\n options: WithAuthOptions = {}\n) {\n const cookieName = options.cookieName || 'ainative_token';\n\n return async (req: any, res: any) => {\n try {\n const cookieHeader = req.headers.cookie;\n const session = getSessionFromCookie(cookieHeader, cookieName);\n\n if (!session) {\n return res.status(401).json({\n error: 'Unauthorized',\n message: 'Authentication required',\n });\n }\n\n const apiKey = getApiKeyFromCookie(cookieHeader, cookieName);\n\n if (!apiKey) {\n return res.status(401).json({\n error: 'Unauthorized',\n message: 'API key not found',\n });\n }\n\n return await handler(req, res, { session, apiKey });\n } catch (error) {\n console.error('Auth middleware error:', error);\n return res.status(500).json({\n error: 'Internal Server Error',\n message: 'Authentication failed',\n });\n }\n };\n}\n"],"names":["createServerClient","config","baseUrl","async","fetchAPI","endpoint","options","url","response","fetch","headers","Authorization","apiKey","ok","error","json","catch","message","status","statusText","Error","chat","completions","create","request","method","body","JSON","stringify","credits","balance","decodeJWT","token","parts","split","length","payload","decoded","Buffer","from","toString","parsed","parse","userId","email","exp","iat","now","Math","floor","Date","getSession","cookieName","cookieStore","cookies","get","value","getSessionFromCookie","cookieHeader","tokenCookie","map","c","trim","find","startsWith","substring","getApiKey","getApiKeyFromCookie","withAuth","handler","req","context","session","undefined","NextResponse","params","console","withAuthPages","res","cookie"],"mappings":"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"}
package/dist/server.js ADDED
@@ -0,0 +1,2 @@
1
+ "use strict";var e=require("next/headers"),t=require("next/server");function r(e){try{const t=e.split(".");if(3!==t.length)return null;const r=t[1],n=Buffer.from(r,"base64").toString("utf-8"),s=JSON.parse(n);if(!(s.userId&&s.email&&s.exp&&s.iat))return null;const o=Math.floor(Date.now()/1e3);return s.exp<o?null:{userId:s.userId,email:s.email,exp:s.exp,iat:s.iat}}catch(e){return null}}function n(e,t="ainative_token"){if(!e)return null;const n=e.split(";").map(e=>e.trim()).find(e=>e.startsWith(`${t}=`));if(!n)return null;return r(n.substring(t.length+1))}function s(e,t="ainative_token"){if(!e)return null;const r=e.split(";").map(e=>e.trim()).find(e=>e.startsWith(`${t}=`));return r?r.substring(t.length+1):null}exports.createServerClient=function(e){const t=e.baseUrl||"https://api.ainative.studio/api/v1";async function r(r,n={}){const s=`${t}${r}`,o=await fetch(s,{...n,headers:{"Content-Type":"application/json",Authorization:`Bearer ${e.apiKey}`,...n.headers}});if(!o.ok){const e=await o.json().catch(()=>({message:`HTTP ${o.status}: ${o.statusText}`}));throw new Error(e.message||`Request failed with status ${o.status}`)}return o.json()}return{chat:{completions:{create:async e=>r("/public/chat/completions",{method:"POST",body:JSON.stringify(e)})}},credits:{balance:async()=>r("/public/credits/balance")}}},exports.getApiKey=async function(t="ainative_token"){try{const r=await e.cookies(),n=r.get(t)?.value;return n||null}catch(e){return null}},exports.getApiKeyFromCookie=s,exports.getSession=async function(t="ainative_token"){try{const n=await e.cookies(),s=n.get(t)?.value;return s?r(s):null}catch(e){return null}},exports.getSessionFromCookie=n,exports.withAuth=function(e,r={}){const o=r.cookieName||"ainative_token";return async(r,a)=>{try{const i=r.headers.get("cookie"),u=n(i||void 0,o);if(!u)return t.NextResponse.json({error:"Unauthorized",message:"Authentication required"},{status:401});const c=s(i||void 0,o);return c?await e(r,{session:u,apiKey:c,params:a?.params}):t.NextResponse.json({error:"Unauthorized",message:"API key not found"},{status:401})}catch(e){return console.error("Auth middleware error:",e),t.NextResponse.json({error:"Internal Server Error",message:"Authentication failed"},{status:500})}}},exports.withAuthPages=function(e,t={}){const r=t.cookieName||"ainative_token";return async(t,o)=>{try{const a=t.headers.cookie,i=n(a,r);if(!i)return o.status(401).json({error:"Unauthorized",message:"Authentication required"});const u=s(a,r);return u?await e(t,o,{session:i,apiKey:u}):o.status(401).json({error:"Unauthorized",message:"API key not found"})}catch(e){return console.error("Auth middleware error:",e),o.status(500).json({error:"Internal Server Error",message:"Authentication failed"})}}};
2
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sources":["../src/server/getSession.ts","../src/server/createServerClient.ts","../src/server/withAuth.ts"],"sourcesContent":["/**\n * Get session from JWT token stored in cookies\n *\n * Supports both App Router and Pages Router\n */\n\nimport { cookies } from 'next/headers';\nimport type { Session } from '../types';\n\n/**\n * Decode JWT token without verification (server-side only)\n *\n * @param token - JWT token string\n * @returns Decoded session data or null if invalid\n */\nfunction decodeJWT(token: string): Session | null {\n try {\n const parts = token.split('.');\n if (parts.length !== 3) {\n return null;\n }\n\n const payload = parts[1];\n const decoded = Buffer.from(payload, 'base64').toString('utf-8');\n const parsed = JSON.parse(decoded);\n\n // Validate required fields\n if (!parsed.userId || !parsed.email || !parsed.exp || !parsed.iat) {\n return null;\n }\n\n // Check expiration\n const now = Math.floor(Date.now() / 1000);\n if (parsed.exp < now) {\n return null;\n }\n\n return {\n userId: parsed.userId,\n email: parsed.email,\n exp: parsed.exp,\n iat: parsed.iat,\n };\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Get session from cookies (App Router)\n *\n * Use this in Server Components and Server Actions.\n *\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns Session data or null if not authenticated\n *\n * @example\n * ```tsx\n * // app/dashboard/page.tsx\n * import { getSession } from '@ainative/next-sdk/server';\n *\n * export default async function DashboardPage() {\n * const session = await getSession();\n *\n * if (!session) {\n * redirect('/login');\n * }\n *\n * return <div>Welcome {session.email}</div>;\n * }\n * ```\n */\nexport async function getSession(cookieName = 'ainative_token'): Promise<Session | null> {\n try {\n const cookieStore = await cookies();\n const token = cookieStore.get(cookieName)?.value;\n\n if (!token) {\n return null;\n }\n\n return decodeJWT(token);\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Get session from cookies (Pages Router)\n *\n * Use this in getServerSideProps or API routes.\n *\n * @param cookieHeader - Cookie header string from request\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns Session data or null if not authenticated\n *\n * @example\n * ```tsx\n * // pages/dashboard.tsx\n * import { getSessionFromCookie } from '@ainative/next-sdk/server';\n *\n * export async function getServerSideProps({ req }) {\n * const session = getSessionFromCookie(req.headers.cookie);\n *\n * if (!session) {\n * return { redirect: { destination: '/login', permanent: false } };\n * }\n *\n * return { props: { session } };\n * }\n * ```\n */\nexport function getSessionFromCookie(\n cookieHeader: string | undefined,\n cookieName = 'ainative_token'\n): Session | null {\n if (!cookieHeader) {\n return null;\n }\n\n const cookies = cookieHeader.split(';').map((c) => c.trim());\n const tokenCookie = cookies.find((c) => c.startsWith(`${cookieName}=`));\n\n if (!tokenCookie) {\n return null;\n }\n\n const token = tokenCookie.substring(cookieName.length + 1);\n return decodeJWT(token);\n}\n\n/**\n * Get API key from cookies (App Router)\n *\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns JWT token or null\n */\nexport async function getApiKey(cookieName = 'ainative_token'): Promise<string | null> {\n try {\n const cookieStore = await cookies();\n const token = cookieStore.get(cookieName)?.value;\n return token || null;\n } catch (error) {\n return null;\n }\n}\n\n/**\n * Get API key from cookie header (Pages Router)\n *\n * @param cookieHeader - Cookie header string from request\n * @param cookieName - Cookie name (default: 'ainative_token')\n * @returns JWT token or null\n */\nexport function getApiKeyFromCookie(\n cookieHeader: string | undefined,\n cookieName = 'ainative_token'\n): string | null {\n if (!cookieHeader) {\n return null;\n }\n\n const cookies = cookieHeader.split(';').map((c) => c.trim());\n const tokenCookie = cookies.find((c) => c.startsWith(`${cookieName}=`));\n\n if (!tokenCookie) {\n return null;\n }\n\n return tokenCookie.substring(cookieName.length + 1);\n}\n","/**\n * Create server-side API client for Next.js Server Components\n */\n\nimport type {\n ServerClient,\n ServerClientConfig,\n ChatCompletionRequest,\n ChatCompletionResponse,\n CreditBalance,\n} from '../types';\n\n/**\n * Create a server-side API client\n *\n * Use this in Server Components, Server Actions, and API routes.\n *\n * @param config - Client configuration with API key\n * @returns Server-side API client\n *\n * @example\n * ```tsx\n * // app/chat/page.tsx\n * import { createServerClient } from '@ainative/next-sdk/server';\n * import { getApiKey } from '@ainative/next-sdk/server';\n *\n * export default async function ChatPage() {\n * const apiKey = await getApiKey();\n * if (!apiKey) return <div>Not authenticated</div>;\n *\n * const client = createServerClient({ apiKey });\n * const balance = await client.credits.balance();\n *\n * return <div>Credits: {balance.remaining_credits}</div>;\n * }\n * ```\n */\nexport function createServerClient(config: ServerClientConfig): ServerClient {\n const baseUrl = config.baseUrl || 'https://api.ainative.studio/api/v1';\n\n /**\n * Make authenticated API request\n */\n async function fetchAPI<T>(endpoint: string, options: RequestInit = {}): Promise<T> {\n const url = `${baseUrl}${endpoint}`;\n\n const response = await fetch(url, {\n ...options,\n headers: {\n 'Content-Type': 'application/json',\n Authorization: `Bearer ${config.apiKey}`,\n ...options.headers,\n },\n });\n\n if (!response.ok) {\n const error = await response.json().catch(() => ({\n message: `HTTP ${response.status}: ${response.statusText}`,\n })) as { message?: string };\n\n throw new Error(error.message || `Request failed with status ${response.status}`);\n }\n\n return response.json() as Promise<T>;\n }\n\n return {\n chat: {\n completions: {\n /**\n * Create chat completion\n */\n create: async (request: ChatCompletionRequest): Promise<ChatCompletionResponse> => {\n return fetchAPI<ChatCompletionResponse>('/public/chat/completions', {\n method: 'POST',\n body: JSON.stringify(request),\n });\n },\n },\n },\n credits: {\n /**\n * Get credit balance\n */\n balance: async (): Promise<CreditBalance> => {\n return fetchAPI<CreditBalance>('/public/credits/balance');\n },\n },\n };\n}\n","/**\n * Higher-order function for API route authentication\n */\n\nimport type { NextRequest } from 'next/server';\nimport { NextResponse } from 'next/server';\nimport type { WithAuthOptions, Session } from '../types';\nimport { getSessionFromCookie, getApiKeyFromCookie } from './getSession';\n\n/**\n * Request handler with authentication\n */\ntype AuthHandler = (\n req: NextRequest,\n context: { session: Session; apiKey: string; params?: any }\n) => Promise<Response> | Response;\n\n/**\n * Wrap API route handler with authentication\n *\n * Use this to protect API routes in both App Router and Pages Router.\n *\n * @param handler - Route handler function\n * @param options - Authentication options\n * @returns Protected route handler\n *\n * @example\n * ```tsx\n * // app/api/chat/route.ts\n * import { withAuth } from '@ainative/next-sdk/server';\n * import { createServerClient } from '@ainative/next-sdk/server';\n *\n * export const POST = withAuth(async (req, { session, apiKey }) => {\n * const client = createServerClient({ apiKey });\n * const body = await req.json();\n *\n * const response = await client.chat.completions.create({\n * messages: body.messages,\n * });\n *\n * return Response.json(response);\n * });\n * ```\n */\nexport function withAuth(handler: AuthHandler, options: WithAuthOptions = {}) {\n const cookieName = options.cookieName || 'ainative_token';\n\n return async (req: NextRequest, context?: { params: any }) => {\n try {\n // Get cookie from request\n const cookieHeader = req.headers.get('cookie');\n const session = getSessionFromCookie(cookieHeader || undefined, cookieName);\n\n if (!session) {\n return NextResponse.json(\n { error: 'Unauthorized', message: 'Authentication required' },\n { status: 401 }\n );\n }\n\n // Get API key\n const apiKey = getApiKeyFromCookie(cookieHeader || undefined, cookieName);\n\n if (!apiKey) {\n return NextResponse.json(\n { error: 'Unauthorized', message: 'API key not found' },\n { status: 401 }\n );\n }\n\n // Call handler with session and apiKey\n return await handler(req, {\n session,\n apiKey,\n params: context?.params,\n });\n } catch (error) {\n console.error('Auth middleware error:', error);\n return NextResponse.json(\n { error: 'Internal Server Error', message: 'Authentication failed' },\n { status: 500 }\n );\n }\n };\n}\n\n/**\n * Wrap Pages Router API handler with authentication\n *\n * Use this for API routes in the pages directory.\n *\n * @param handler - Route handler function\n * @param options - Authentication options\n * @returns Protected route handler\n *\n * @example\n * ```tsx\n * // pages/api/chat.ts\n * import { withAuthPages } from '@ainative/next-sdk/server';\n * import { createServerClient } from '@ainative/next-sdk/server';\n * import type { NextApiRequest, NextApiResponse } from 'next';\n *\n * export default withAuthPages(async (req, res, { session, apiKey }) => {\n * const client = createServerClient({ apiKey });\n *\n * const response = await client.chat.completions.create({\n * messages: req.body.messages,\n * });\n *\n * res.status(200).json(response);\n * });\n * ```\n */\nexport function withAuthPages(\n handler: (\n req: any,\n res: any,\n context: { session: Session; apiKey: string }\n ) => Promise<void> | void,\n options: WithAuthOptions = {}\n) {\n const cookieName = options.cookieName || 'ainative_token';\n\n return async (req: any, res: any) => {\n try {\n const cookieHeader = req.headers.cookie;\n const session = getSessionFromCookie(cookieHeader, cookieName);\n\n if (!session) {\n return res.status(401).json({\n error: 'Unauthorized',\n message: 'Authentication required',\n });\n }\n\n const apiKey = getApiKeyFromCookie(cookieHeader, cookieName);\n\n if (!apiKey) {\n return res.status(401).json({\n error: 'Unauthorized',\n message: 'API key not found',\n });\n }\n\n return await handler(req, res, { session, apiKey });\n } catch (error) {\n console.error('Auth middleware error:', error);\n return res.status(500).json({\n error: 'Internal Server Error',\n message: 'Authentication failed',\n });\n }\n };\n}\n"],"names":["decodeJWT","token","parts","split","length","payload","decoded","Buffer","from","toString","parsed","JSON","parse","userId","email","exp","iat","now","Math","floor","Date","error","getSessionFromCookie","cookieHeader","cookieName","tokenCookie","map","c","trim","find","startsWith","substring","getApiKeyFromCookie","config","baseUrl","async","fetchAPI","endpoint","options","url","response","fetch","headers","Authorization","apiKey","ok","json","catch","message","status","statusText","Error","chat","completions","create","request","method","body","stringify","credits","balance","cookieStore","cookies","get","value","handler","req","context","session","undefined","NextResponse","params","console","res","cookie"],"mappings":"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"}
package/package.json ADDED
@@ -0,0 +1,98 @@
1
+ {
2
+ "name": "@ainative/next-sdk",
3
+ "version": "1.0.1",
4
+ "description": "Official Next.js SDK for AINative Studio API - Server and client utilities for App Router and Pages Router",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.esm.js",
7
+ "types": "dist/index.d.ts",
8
+ "exports": {
9
+ ".": {
10
+ "types": "./dist/index.d.ts",
11
+ "import": "./dist/index.esm.js",
12
+ "require": "./dist/index.js"
13
+ },
14
+ "./server": {
15
+ "types": "./dist/server.d.ts",
16
+ "import": "./dist/server.esm.js",
17
+ "require": "./dist/server.js"
18
+ },
19
+ "./client": {
20
+ "types": "./dist/client.d.ts",
21
+ "import": "./dist/client.esm.js",
22
+ "require": "./dist/client.js"
23
+ }
24
+ },
25
+ "files": [
26
+ "dist",
27
+ "README.md",
28
+ "LICENSE"
29
+ ],
30
+ "scripts": {
31
+ "build": "rollup -c rollup.config.mjs",
32
+ "build:watch": "rollup -c -w",
33
+ "test": "jest",
34
+ "test:watch": "jest --watch",
35
+ "test:coverage": "jest --coverage",
36
+ "lint": "eslint . --ext .ts,.tsx",
37
+ "lint:fix": "eslint . --ext .ts,.tsx --fix",
38
+ "type-check": "tsc --noEmit",
39
+ "prepublishOnly": "npm run test && npm run build"
40
+ },
41
+ "keywords": [
42
+ "ainative",
43
+ "nextjs",
44
+ "next",
45
+ "react",
46
+ "server-components",
47
+ "app-router",
48
+ "pages-router",
49
+ "api",
50
+ "sdk",
51
+ "chat",
52
+ "ai",
53
+ "typescript"
54
+ ],
55
+ "author": "AINative Studio",
56
+ "license": "MIT",
57
+ "repository": {
58
+ "type": "git",
59
+ "url": "https://github.com/AINative-Studio/ainative-sdks"
60
+ },
61
+ "bugs": {
62
+ "url": "https://github.com/AINative-Studio/ainative-sdks/issues"
63
+ },
64
+ "homepage": "https://ainative.studio",
65
+ "peerDependencies": {
66
+ "next": "^13.0.0 || ^14.0.0",
67
+ "react": "^18.0.0"
68
+ },
69
+ "dependencies": {
70
+ "@ainative/react-sdk": "^1.0.0"
71
+ },
72
+ "devDependencies": {
73
+ "@rollup/plugin-commonjs": "^25.0.7",
74
+ "@rollup/plugin-node-resolve": "^15.2.3",
75
+ "@rollup/plugin-typescript": "^11.1.5",
76
+ "@rollup/plugin-terser": "^0.4.4",
77
+ "@types/jest": "^29.5.10",
78
+ "@types/node": "^20.10.0",
79
+ "@types/react": "^18.2.45",
80
+ "@typescript-eslint/eslint-plugin": "^6.13.0",
81
+ "@typescript-eslint/parser": "^6.13.0",
82
+ "eslint": "^8.54.0",
83
+ "eslint-plugin-react": "^7.33.2",
84
+ "eslint-plugin-react-hooks": "^4.6.0",
85
+ "jest": "^29.7.0",
86
+ "jest-environment-node": "^29.7.0",
87
+ "next": "^14.0.0",
88
+ "react": "^18.2.0",
89
+ "rollup": "^3.29.4",
90
+ "rollup-plugin-dts": "^5.3.1",
91
+ "ts-jest": "^29.1.1",
92
+ "tslib": "^2.6.2",
93
+ "typescript": "^5.3.2"
94
+ },
95
+ "engines": {
96
+ "node": ">=18.0.0"
97
+ }
98
+ }