Fork of github.com/did-method-plc/did-method-plc
1import express from 'express' 2import * as plc from '@did-plc/lib' 3import { ServerError } from './error' 4import { AppContext } from './context' 5import { validateIncomingOp } from './constraints' 6 7export const createRouter = (ctx: AppContext): express.Router => { 8 const router = express.Router() 9 10 router.get('/', async function (req, res) { 11 // HTTP temporary redirect to project homepage 12 res.redirect(302, 'https://web.plc.directory') 13 }) 14 15 router.get('/_health', async function (req, res) { 16 const { db, version } = ctx 17 try { 18 await db.healthCheck() 19 } catch (err) { 20 req.log.error(err, 'failed health check') 21 return res.status(503).send({ version, error: 'Service Unavailable' }) 22 } 23 res.send({ version }) 24 }) 25 26 // Export ops in the form of paginated json lines 27 router.get('/export', async function (req, res) { 28 const parsedCount = req.query.count ? parseInt(req.query.count, 10) : 1000 29 if (isNaN(parsedCount) || parsedCount < 1) { 30 throw new ServerError(400, 'Invalid count parameter') 31 } 32 const count = Math.min(parsedCount, 1000) 33 const after = req.query.after ? new Date(req.query.after) : undefined 34 const ops = await ctx.db.exportOps(count, after) 35 res.setHeader('content-type', 'application/jsonlines') 36 res.status(200) 37 for (let i = 0; i < ops.length; i++) { 38 if (i > 0) { 39 res.write('\n') 40 } 41 const line = JSON.stringify(ops[i]) 42 res.write(line) 43 } 44 res.end() 45 }) 46 47 // Get data for a DID document 48 router.get('/:did', async function (req, res) { 49 const { did } = req.params 50 const last = await ctx.db.lastOpForDid(did) 51 if (!last) { 52 throw new ServerError(404, `DID not registered: ${did}`) 53 } 54 const data = plc.opToData(did, last) 55 if (data === null) { 56 throw new ServerError(404, `DID not available: ${did}`) 57 } 58 const doc = await plc.formatDidDoc(data) 59 res.type('application/did+ld+json') 60 res.send(JSON.stringify(doc)) 61 }) 62 63 // Get data for a DID document 64 router.get('/:did/data', async function (req, res) { 65 const { did } = req.params 66 const last = await ctx.db.lastOpForDid(did) 67 if (!last) { 68 throw new ServerError(404, `DID not registered: ${did}`) 69 } 70 const data = plc.opToData(did, last) 71 if (data === null) { 72 throw new ServerError(404, `DID not available: ${did}`) 73 } 74 res.json(data) 75 }) 76 77 // Get operation log for a DID 78 router.get('/:did/log', async function (req, res) { 79 const { did } = req.params 80 const log = await ctx.db.opsForDid(did) 81 if (log.length === 0) { 82 throw new ServerError(404, `DID not registered: ${did}`) 83 } 84 res.json(log) 85 }) 86 87 // Get operation log for a DID 88 router.get('/:did/log/audit', async function (req, res) { 89 const { did } = req.params 90 const ops = await ctx.db.indexedOpsForDid(did, true) 91 if (ops.length === 0) { 92 throw new ServerError(404, `DID not registered: ${did}`) 93 } 94 const log = ops.map((op) => ({ 95 ...op, 96 cid: op.cid.toString(), 97 createdAt: op.createdAt.toISOString(), 98 })) 99 100 res.json(log) 101 }) 102 103 // Get the most recent operation in the log for a DID 104 router.get('/:did/log/last', async function (req, res) { 105 const { did } = req.params 106 const last = await ctx.db.lastOpForDid(did) 107 if (!last) { 108 throw new ServerError(404, `DID not registered: ${did}`) 109 } 110 res.json(last) 111 }) 112 113 // Update or create a DID doc 114 router.post('/:did', async function (req, res) { 115 const { did } = req.params 116 const op = validateIncomingOp(req.body) 117 await ctx.db.validateAndAddOp(did, op) 118 res.sendStatus(200) 119 }) 120 121 return router 122} 123 124export default createRouter