@pubflow/nextjs
Version:
Next.js adapter for Pubflow framework
254 lines (201 loc) • 5.8 kB
Markdown
# @pubflow/nextjs
Next.js adapter for the Pubflow framework.
## Overview
`@pubflow/nextjs` provides Next.js-specific implementations and utilities for the Pubflow framework, including:
- Server-side rendering (SSR) support
- API route handlers
- Next.js-specific storage adapter
- Integration with Next.js routing
## Installation
```bash
# Install the core package and Next.js adapter
npm install @pubflow/core @pubflow/nextjs
# Optional: Install Zod for schema validation
npm install zod
```
## Schema Validation
Pubflow recommends defining schemas at the application level, not in the adapter. This allows for better reusability and separation of concerns.
```tsx
// lib/schemas/user.ts
import { z } from 'zod';
// Schema for complete user entity
export const userSchema = z.object({
id: z.string().uuid().optional(),
name: z.string().min(2, 'Name must be at least 2 characters'),
email: z.string().email('Invalid email address'),
role: z.enum(['user', 'admin'], 'Role must be either user or admin')
});
// Schema for creating a user
export const createUserSchema = userSchema.omit({
id: true
});
// Schema for updating a user
export const updateUserSchema = userSchema
.partial()
.extend({
id: z.string().uuid()
});
// TypeScript types inferred from schemas
export type User = z.infer<typeof userSchema>;
export type CreateUser = z.infer<typeof createUserSchema>;
export type UpdateUser = z.infer<typeof updateUserSchema>;
```
These schemas can then be used with Pubflow's CRUD operations:
```tsx
import { useBridgeCrud } from '@pubflow/nextjs';
import { userSchema, createUserSchema, updateUserSchema } from '../lib/schemas/user';
function UsersPage() {
const {
items: users,
createItem,
updateItem,
deleteItem,
validationErrors
} = useBridgeCrud({
entityConfig: {
endpoint: 'users'
},
schemas: {
entity: userSchema,
create: createUserSchema,
update: updateUserSchema
}
});
// Component implementation...
}
```
## Persistent Cache
Pubflow Next.js adapter supports persistent caching to improve performance and offline experience:
```jsx
import { PubflowProvider, createPersistentCache } from '@pubflow/nextjs';
function MyApp({ Component, pageProps }) {
// Create a persistent cache provider
const persistentCacheProvider = createPersistentCache({
prefix: 'my_nextjs_app_cache',
ttl: 24 * 60 * 60 * 1000, // 24 hours
});
return (
<PubflowProvider
config={{
baseUrl: 'https://api.example.com',
bridgeBasePath: '/bridge',
authBasePath: '/auth'
}}
persistentCache={{
enabled: true,
provider: persistentCacheProvider
}}
>
<Component {...pageProps} />
</PubflowProvider>
);
}
export default MyApp;
```
For more information, see the persistent cache documentation.
## Usage
### Provider Setup
```tsx
// pages/_app.tsx
import { AppProps } from 'next/app';
import { PubflowProvider } from '@pubflow/nextjs';
function MyApp({ Component, pageProps }: AppProps) {
return (
<PubflowProvider
config={{
baseUrl: process.env.NEXT_PUBLIC_API_URL || 'http://localhost:8787',
bridgeBasePath: '/bridge',
authBasePath: '/auth'
}}
loginRedirectPath="/login"
publicPaths={['/login', '/register', '/forgot-password']}
>
<Component {...pageProps} />
</PubflowProvider>
);
}
export default MyApp;
```
### Server-Side Authentication
```tsx
// pages/profile.tsx
import { GetServerSideProps } from 'next';
import { withPubflowSSR, useAuth } from '@pubflow/nextjs';
export const getServerSideProps: GetServerSideProps = withPubflowSSR(
async (context, api, auth) => {
// Check if user is authenticated
const { isValid } = await auth.validateSession();
if (!isValid) {
return {
redirect: {
destination: '/login',
permanent: false,
},
};
}
// Get user data
const user = await auth.getCurrentUser();
return {
props: {
user,
},
};
}
);
function ProfilePage({ user }) {
const { logout } = useAuth();
return (
<div>
<h1>Profile</h1>
<p>Name: {user.name}</p>
<p>Email: {user.email}</p>
<button onClick={logout}>Logout</button>
</div>
);
}
export default ProfilePage;
```
### API Routes
```tsx
// pages/api/custom.ts
import { NextApiRequest, NextApiResponse } from 'next';
import { withPubflow } from '@pubflow/nextjs';
export default withPubflow(async (req, res, api) => {
// Check method
if (req.method !== 'GET') {
return res.status(405).json({ error: 'Method not allowed' });
}
try {
// Make API request
const response = await api.get('/some/endpoint');
// Return response
return res.status(200).json(response.data);
} catch (error) {
return res.status(500).json({ error: 'Internal server error' });
}
});
```
### Protected Routes with useServerAuth
```tsx
// pages/dashboard.tsx
import { useServerAuth } from '@pubflow/nextjs';
function DashboardPage() {
// This hook will automatically redirect to login if not authenticated
const { user, isAuthenticated, isLoading } = useServerAuth({
loginRedirectPath: '/login',
allowedTypes: ['admin', 'manager']
});
if (isLoading) {
return <div>Loading...</div>;
}
return (
<div>
<h1>Dashboard</h1>
<p>Welcome, {user.name}!</p>
</div>
);
}
export default DashboardPage;
```
## License
AGPL-3.0-or-later