spfn
Version:
Superfunction CLI - Add SPFN to your Next.js project
113 lines (96 loc) • 2.91 kB
text/typescript
/**
* Example Routes: CRUD Operations
*
* SPFN uses contract-based routing with absolute paths:
* - Contracts are defined in src/lib/contracts/ (shared with frontend)
* - Handlers import contracts and implement business logic
* - URL paths are defined by contract.path (e.g., '/examples/:id')
* - File structure is flexible - organize routes however you want
*/
import { createApp } from '@spfn/core/route';
import {
getExamplesContract,
getExampleContract,
createExampleContract,
updateExampleContract,
deleteExampleContract
} from '@/lib/contracts/examples'; // ← Import from @/lib/contracts
const app = createApp();
// GET /examples - List examples with pagination
app.bind(getExamplesContract, async (c) =>
{
const { limit = 10, offset = 0 } = c.query;
// Mock data - replace with actual database queries
const examples = [
{
id: '1',
name: 'File-based Routing',
description: 'Next.js style automatic route registration'
},
{
id: '2',
name: 'Contract-based Validation',
description: 'TypeBox schemas for end-to-end type safety'
},
{
id: '3',
name: 'Auto-generated Types',
description: 'Client code generation from contracts'
}
];
return c.success({
examples: examples.slice(offset, offset + limit),
total: examples.length,
limit,
offset
});
});
// GET /examples/:id - Get single example
app.bind(getExampleContract, async (c) =>
{
const { id } = c.params;
// Mock data - replace with actual database query
const example = {
id,
name: 'Example ' + id,
description: 'This is an example',
createdAt: Date.now(),
updatedAt: Date.now()
};
return c.success(example);
});
// POST /examples - Create example
app.bind(createExampleContract, async (c) =>
{
const body = await c.data();
// Mock data - replace with actual database insert
const example = {
id: Math.random().toString(36).substring(7),
name: body.name,
description: body.description,
createdAt: Date.now()
};
return c.success(example);
});
// PUT /examples/:id - Update example
app.bind(updateExampleContract, async (c) =>
{
const { id } = c.params;
const body = await c.data();
// Mock data - replace with actual database update
const example = {
id,
name: body.name || 'Updated Example',
description: body.description || 'Updated description',
updatedAt: Date.now()
};
return c.success(example);
});
// DELETE /examples/:id - Delete example
app.bind(deleteExampleContract, async (c) =>
{
const { id } = c.params;
// Mock data - replace with actual database delete
return c.success({ id });
});
export default app;