chore: crush git history - reborn from consolidation on 2026-03-10
This commit is contained in:
@@ -0,0 +1,29 @@
|
||||
import Fastify from 'fastify'
|
||||
import swagger from '@fastify/swagger'
|
||||
import { apophisPlugin } from 'apophis-fastify'
|
||||
import { databasePlugin } from './plugins/database.js'
|
||||
import { userRoutes } from './routes/users.js'
|
||||
|
||||
export interface BuildAppOptions {
|
||||
databaseUrl?: string
|
||||
}
|
||||
|
||||
export async function buildApp(opts: BuildAppOptions = {}) {
|
||||
const app = Fastify({ logger: true })
|
||||
|
||||
// Register APOPHIS first (required before routes)
|
||||
await app.register(swagger, {})
|
||||
await app.register(apophisPlugin, {
|
||||
runtime: 'warn',
|
||||
})
|
||||
|
||||
// Register domain plugins
|
||||
await app.register(databasePlugin, {
|
||||
url: opts.databaseUrl || process.env.DATABASE_URL || 'sqlite::memory:',
|
||||
})
|
||||
|
||||
// Register routes
|
||||
await app.register(userRoutes)
|
||||
|
||||
return app
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
import fp from 'fastify-plugin'
|
||||
|
||||
export interface DatabasePluginOptions {
|
||||
url: string
|
||||
}
|
||||
|
||||
export const databasePlugin = fp(async (fastify, opts: DatabasePluginOptions) => {
|
||||
// In a real app, this would connect to PostgreSQL, MongoDB, etc.
|
||||
const db = {
|
||||
users: new Map<string, { id: string; name: string; email: string }>(),
|
||||
url: opts.url,
|
||||
}
|
||||
|
||||
fastify.decorate('db', db)
|
||||
|
||||
fastify.addHook('onClose', async () => {
|
||||
// Cleanup connections
|
||||
})
|
||||
})
|
||||
|
||||
// Type augmentation for Fastify
|
||||
declare module 'fastify' {
|
||||
interface FastifyInstance {
|
||||
db: {
|
||||
users: Map<string, { id: string; name: string; email: string }>
|
||||
url: string
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
import type { FastifyInstance } from 'fastify'
|
||||
|
||||
export async function userRoutes(fastify: FastifyInstance) {
|
||||
fastify.post('/users', {
|
||||
schema: {
|
||||
body: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
name: { type: 'string' },
|
||||
email: { type: 'string', format: 'email' },
|
||||
},
|
||||
required: ['name', 'email'],
|
||||
},
|
||||
response: {
|
||||
201: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string' },
|
||||
name: { type: 'string' },
|
||||
email: { type: 'string' },
|
||||
},
|
||||
},
|
||||
},
|
||||
'x-category': 'constructor',
|
||||
'x-ensures': [
|
||||
'status:201',
|
||||
'response_body(this).id != null',
|
||||
'response_body(this).name == request_body(this).name',
|
||||
],
|
||||
},
|
||||
}, async (req, reply) => {
|
||||
const { name, email } = req.body as { name: string; email: string }
|
||||
const id = `user-${Date.now()}`
|
||||
const user = { id, name, email }
|
||||
fastify.db.users.set(id, user)
|
||||
reply.status(201)
|
||||
return user
|
||||
})
|
||||
|
||||
fastify.get('/users/:id', {
|
||||
schema: {
|
||||
params: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string' },
|
||||
},
|
||||
required: ['id'],
|
||||
},
|
||||
response: {
|
||||
200: {
|
||||
type: 'object',
|
||||
properties: {
|
||||
id: { type: 'string' },
|
||||
name: { type: 'string' },
|
||||
email: { type: 'string' },
|
||||
},
|
||||
},
|
||||
},
|
||||
'x-category': 'observer',
|
||||
'x-ensures': [
|
||||
'status:200',
|
||||
'response_body(this).id == request_params(this).id',
|
||||
],
|
||||
},
|
||||
}, async (req) => {
|
||||
const { id } = req.params as { id: string }
|
||||
const user = fastify.db.users.get(id)
|
||||
if (!user) {
|
||||
throw new Error('User not found')
|
||||
}
|
||||
return user
|
||||
})
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
import { buildApp } from './app.js'
|
||||
|
||||
async function start() {
|
||||
const app = await buildApp()
|
||||
await app.ready()
|
||||
await app.listen({ port: Number(process.env.PORT) || 3000 })
|
||||
app.log.info(`Server listening on port ${process.env.PORT || 3000}`)
|
||||
}
|
||||
|
||||
start().catch((err) => {
|
||||
console.error(err)
|
||||
process.exit(1)
|
||||
})
|
||||
@@ -0,0 +1,16 @@
|
||||
import { buildApp } from '../app.js'
|
||||
import type { FastifyInstance } from 'fastify'
|
||||
|
||||
export interface TestContext {
|
||||
app: FastifyInstance
|
||||
}
|
||||
|
||||
export async function setupTestApp(): Promise<TestContext> {
|
||||
const app = await buildApp({ databaseUrl: 'sqlite::memory:' })
|
||||
await app.ready()
|
||||
return { app }
|
||||
}
|
||||
|
||||
export async function teardownTestApp(ctx: TestContext): Promise<void> {
|
||||
await ctx.app.close()
|
||||
}
|
||||
Reference in New Issue
Block a user