/**
* Package routes — CRUD for service packages.
*/
import { json, readJson, notFound } from '../response.js'
import { requireAuth } from './auth-helpers.js'
export function registerPackageRoutes (router, server) {
// List packages for a provider (public)
router.get('/api/providers/:slug/packages', async (req, res) => {
const { slug } = req.params
const providerIdEntry = await server.db.get(`provider-by-slug:${slug}`)
if (!providerIdEntry) return notFound(res, 'Provider not found')
const providerId = providerIdEntry.value
const packages = []
for await (const entry of server.db.createReadStream({
gte: `package:${providerId}:`,
lte: `package:${providerId}:~`
})) {
if (entry.value.active !== false) {
packages.push(entry.value)
}
}
// Sort: discovery first, then by price
packages.sort((a, b) => {
if (a.type === 'discovery' && b.type !== 'discovery') return -1
if (b.type === 'discovery' && a.type !== 'discovery') return 1
return a.price - b.price
})
json(res, packages)
})
// Get single package (public)
router.get('/api/packages/:id', async (req, res) => {
const entry = await server.db.get(`package-detail:${req.params.id}`)
if (!entry) return notFound(res, 'Package not found')
json(res, entry.value)
})
// Create package (provider)
router.post('/api/packages', async (req, res) => {
const auth = await requireAuth(req, server, 'write')
const body = await readJson(req)
const {
providerId, name, type, description,
sessionDuration, sessionCount, price,
currency, discountFullPay, installments,
groupCapacity, intakeFormId, contractId
} = body
if (!providerId || !name || !type) {
json(res, { error: 'providerId, name, and type required' }, 400)
return
}
// Verify provider ownership
const providerEntry = await server.db.get(`provider:${providerId}`)
if (!providerEntry) return notFound(res, 'Provider not found')
if (providerEntry.value.userId !== auth.userId &&
!auth.permissions.admin) {
json(res, { error: 'Not your provider' }, 403)
return
}
const pkg = {
id: server.generateId('pkg'),
providerId,
name,
type, // single | bundle | subscription | discovery | group
description: description || '',
sessionDuration: sessionDuration || 60,
sessionCount: sessionCount || 1,
price: price || 0, // cents
currency: currency || 'USD',
discountFullPay: discountFullPay || 0,
installments: installments || 0,
groupCapacity: groupCapacity || null,
intakeFormId: intakeFormId || null,
contractId: contractId || null,
image: null,
active: true,
createdAt: Date.now()
}
const batch = server.db.batch()
await batch.put(`package:${providerId}:${pkg.id}`, pkg)
await batch.put(`package-detail:${pkg.id}`, pkg)
await batch.flush()
json(res, pkg, 201)
})
// Update package (provider)
router.put('/api/packages/:id', async (req, res) => {
const auth = await requireAuth(req, server, 'write')
const entry = await server.db.get(`package-detail:${req.params.id}`)
if (!entry) return notFound(res, 'Package not found')
const pkg = entry.value
// Verify ownership
const providerEntry = await server.db.get(`provider:${pkg.providerId}`)
if (providerEntry.value.userId !== auth.userId &&
!auth.permissions.admin) {
json(res, { error: 'Not your provider' }, 403)
return
}
const body = await readJson(req)
const updatable = [
'name', 'type', 'description', 'sessionDuration', 'sessionCount',
'price', 'currency', 'discountFullPay', 'installments',
'groupCapacity', 'intakeFormId', 'contractId', 'image', 'active'
]
for (const key of updatable) {
if (body[key] !== undefined) pkg[key] = body[key]
}
pkg.updatedAt = Date.now()
const batch = server.db.batch()
await batch.put(`package:${pkg.providerId}:${pkg.id}`, pkg)
await batch.put(`package-detail:${pkg.id}`, pkg)
await batch.flush()
json(res, pkg)
})
// Delete (archive) package (provider)
router.delete('/api/packages/:id', async (req, res) => {
const auth = await requireAuth(req, server, 'write')
const entry = await server.db.get(`package-detail:${req.params.id}`)
if (!entry) return notFound(res, 'Package not found')
const pkg = entry.value
pkg.active = false
pkg.archivedAt = Date.now()
const batch = server.db.batch()
await batch.put(`package:${pkg.providerId}:${pkg.id}`, pkg)
await batch.put(`package-detail:${pkg.id}`, pkg)
await batch.flush()
json(res, { ok: true })
})
}