chore: crush git history - reborn from consolidation on 2026-03-10

This commit is contained in:
John Dvorak
2026-03-10 00:00:00 -07:00
commit d278c4b105
313 changed files with 87549 additions and 0 deletions
+29
View File
@@ -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
}
+29
View File
@@ -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
}
}
}
+73
View File
@@ -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
})
}
+13
View File
@@ -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)
})
+16
View File
@@ -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()
}