Fork of github.com/did-method-plc/did-method-plc
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

upgrade axios + better error handling

dholms 254f179d f0599f71

+73 -43
+1 -1
packages/lib/package.json
··· 1 1 { 2 2 "name": "@did-plc/lib", 3 3 "version": "0.0.1", 4 - "main": "dist/index.js", 4 + "main": "src/index.ts", 5 5 "license": "MIT", 6 6 "scripts": { 7 7 "test": "jest",
+45 -13
packages/lib/src/client.ts
··· 1 1 import { check, cidForCbor } from '@atproto/common' 2 2 import { Keypair } from '@atproto/crypto' 3 - import axios from 'axios' 3 + import axios, { AxiosError } from 'axios' 4 4 import { 5 5 atprotoOp, 6 6 createUpdateOp, ··· 16 16 export class Client { 17 17 constructor(public url: string) {} 18 18 19 + private async makeGetReq(url: string) { 20 + try { 21 + const res = await axios.get(url) 22 + return res.data 23 + } catch (err) { 24 + if (!axios.isAxiosError(err)) { 25 + throw err 26 + } 27 + throw PlcClientError.fromAxiosError(err) 28 + } 29 + } 30 + 19 31 async getDocument(did: string): Promise<t.DidDocument> { 20 - const res = await axios.get(`${this.url}/${encodeURIComponent(did)}`) 21 - return res.data 32 + return await this.makeGetReq(`${this.url}/${encodeURIComponent(did)}`) 22 33 } 23 34 24 35 async getDocumentData(did: string): Promise<t.DocumentData> { 25 - const res = await axios.get(`${this.url}/${encodeURIComponent(did)}/data`) 26 - return res.data 36 + return await this.makeGetReq(`${this.url}/${encodeURIComponent(did)}/data`) 27 37 } 28 38 29 39 async getOperationLog(did: string): Promise<t.CompatibleOpOrTombstone[]> { 30 - const res = await axios.get(`${this.url}/${encodeURIComponent(did)}/log`) 31 - return res.data 40 + return await this.makeGetReq(`${this.url}/${encodeURIComponent(did)}/log`) 32 41 } 33 42 34 43 async getAuditableLog(did: string): Promise<t.ExportedOp[]> { 35 - const res = await axios.get( 44 + return await this.makeGetReq( 36 45 `${this.url}/${encodeURIComponent(did)}/log/audit`, 37 46 ) 38 - return res.data 39 47 } 40 48 41 49 postOpUrl(did: string): string { ··· 43 51 } 44 52 45 53 async getLastOp(did: string): Promise<t.CompatibleOpOrTombstone> { 46 - const res = await axios.get( 54 + return await this.makeGetReq( 47 55 `${this.url}/${encodeURIComponent(did)}/log/last`, 48 56 ) 49 - return res.data 50 57 } 51 58 52 59 async sendOperation(did: string, op: t.OpOrTombstone) { 53 - await axios.post(this.postOpUrl(did), op) 60 + try { 61 + await axios.post(this.postOpUrl(did), op) 62 + } catch (err) { 63 + if (!axios.isAxiosError(err)) { 64 + throw err 65 + } 66 + throw PlcClientError.fromAxiosError(err) 67 + } 54 68 } 55 69 56 70 async export(after?: string, count?: number): Promise<t.ExportedOp[]> { ··· 129 143 } 130 144 131 145 async health() { 132 - return await axios.get(`${this.url}/_health`) 146 + return await this.makeGetReq(`${this.url}/_health`) 147 + } 148 + } 149 + 150 + export class PlcClientError extends Error { 151 + constructor( 152 + public status: number, 153 + public data: unknown, 154 + public message: string, 155 + ) { 156 + super(message) 157 + } 158 + 159 + static fromAxiosError(err: AxiosError) { 160 + return new PlcClientError( 161 + err.response?.status || 500, 162 + err.response?.data, 163 + err.message, 164 + ) 133 165 } 134 166 } 135 167
+3 -2
packages/lib/tsconfig.json
··· 2 2 "extends": "../../tsconfig.json", 3 3 "compilerOptions": { 4 4 "rootDir": "./src", 5 - "outDir": "./dist", // Your outDir, 5 + "outDir": "./dist", 6 + "declarationDir": "./dist", 6 7 "emitDeclarationOnly": true, 7 8 }, 8 - "include": ["./src", "__tests__/**/**.ts"] 9 + "include": ["./src"] 9 10 }
+1 -1
packages/server/package.json
··· 26 26 "@atproto/common": "0.1.0", 27 27 "@atproto/crypto": "0.1.0", 28 28 "@did-plc/lib": "*", 29 - "axios": "^0.27.2", 29 + "axios": "^1.3.4", 30 30 "cors": "^2.8.5", 31 31 "express": "^4.18.2", 32 32 "express-async-errors": "^3.1.1",
+15 -16
packages/server/tests/server.test.ts
··· 2 2 import * as plc from '@did-plc/lib' 3 3 import { CloseFn, runTestServer } from './_util' 4 4 import { check } from '@atproto/common' 5 - import { AxiosError } from 'axios' 6 5 import { Database } from '../src' 6 + import { PlcClientError } from '@did-plc/lib' 7 7 8 8 describe('PLC server', () => { 9 9 let handle = 'at://alice.example.com' ··· 95 95 'did:key:z6MkjwbBXZnFqL8su24wGL2Fdjti6GSLv9SWdYGswfazUPm9' 96 96 97 97 const promise = client.updateAtprotoKey(did, rotationKey1, newSigningKey) 98 - await expect(promise).rejects.toThrow(AxiosError) 98 + await expect(promise).rejects.toThrow(PlcClientError) 99 99 100 100 const promise2 = client.updateRotationKeys(did, rotationKey1, [ 101 101 newSigningKey, 102 102 ]) 103 - await expect(promise2).rejects.toThrow(AxiosError) 103 + await expect(promise2).rejects.toThrow(PlcClientError) 104 104 }) 105 105 106 106 it('retrieves the operation log', async () => { ··· 157 157 }) 158 158 159 159 it('handles concurrent requests to many docs', async () => { 160 - const COUNT = 50 160 + const COUNT = 20 161 161 const keys: EcdsaKeypair[] = [] 162 162 for (let i = 0; i < COUNT; i++) { 163 163 keys.push(await EcdsaKeypair.create()) ··· 176 176 }) 177 177 178 178 it('resolves races into a coherent history with no forks', async () => { 179 - const COUNT = 50 179 + const COUNT = 20 180 180 const keys: EcdsaKeypair[] = [] 181 181 for (let i = 0; i < COUNT; i++) { 182 182 keys.push(await EcdsaKeypair.create()) ··· 196 196 }), 197 197 ) 198 198 expect(successes).toBe(1) 199 - expect(failures).toBe(49) 199 + expect(failures).toBe(19) 200 200 201 201 const ops = await client.getOperationLog(did) 202 202 await plc.validateOperationLog(did, ops) ··· 206 206 await client.tombstone(did, rotationKey1) 207 207 208 208 const promise = client.getDocument(did) 209 - await expect(promise).rejects.toThrow(AxiosError) 209 + await expect(promise).rejects.toThrow(PlcClientError) 210 210 const promise2 = client.getDocumentData(did) 211 - await expect(promise2).rejects.toThrow(AxiosError) 211 + await expect(promise2).rejects.toThrow(PlcClientError) 212 212 }) 213 213 214 214 it('exports the data set', async () => { 215 215 const data = await client.export() 216 216 expect(data.every((row) => check.is(row, plc.def.exportedOp))).toBeTruthy() 217 - expect(data.length).toBe(59) 217 + expect(data.length).toBe(29) 218 218 for (let i = 1; i < data.length; i++) { 219 219 expect(data[i].createdAt >= data[i - 1].createdAt).toBeTruthy() 220 220 } 221 221 }) 222 222 223 223 it('healthcheck succeeds when database is available.', async () => { 224 - const { data, status } = await client.health() 225 - expect(status).toEqual(200) 226 - expect(data).toEqual({ version: '0.0.0' }) 224 + const res = await client.health() 225 + expect(res).toEqual({ version: '0.0.0' }) 227 226 }) 228 227 229 228 it('healthcheck fails when database is unavailable.', async () => { 230 229 await db.db.destroy() 231 - let error: AxiosError 230 + let error: PlcClientError 232 231 try { 233 232 await client.health() 234 233 throw new Error('Healthcheck should have failed') 235 234 } catch (err) { 236 - if (err instanceof AxiosError) { 235 + if (err instanceof PlcClientError) { 237 236 error = err 238 237 } else { 239 238 throw err 240 239 } 241 240 } 242 - expect(error.response?.status).toEqual(503) 243 - expect(error.response?.data).toEqual({ 241 + expect(error.status).toEqual(503) 242 + expect(error.data).toEqual({ 244 243 version: '0.0.0', 245 244 error: 'Service Unavailable', 246 245 })
+7 -1
packages/server/tsconfig.build.json
··· 1 1 { 2 2 "extends": "./tsconfig.json", 3 - "exclude": ["**/*.spec.ts", "**/*.test.ts"] 3 + "compilerOptions": { 4 + "rootDir": "./src", 5 + "outDir": "./dist", 6 + "declarationDir": "./dist", 7 + "emitDeclarationOnly": true, 8 + }, 9 + "include": ["./src"] 4 10 }
+1 -9
yarn.lock
··· 2647 2647 resolved "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz" 2648 2648 integrity sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA== 2649 2649 2650 - axios@^0.27.2: 2651 - version "0.27.2" 2652 - resolved "https://registry.npmjs.org/axios/-/axios-0.27.2.tgz" 2653 - integrity sha512-t+yRIyySRTp/wua5xEr+z1q60QmLq8ABsS5O9Me1AsE5dfKqgnCFzwiCZZ/cGNd1lq4/7akDWMxdhVlucjmnOQ== 2654 - dependencies: 2655 - follow-redirects "^1.14.9" 2656 - form-data "^4.0.0" 2657 - 2658 2650 axios@^1.3.4: 2659 2651 version "1.3.4" 2660 2652 resolved "https://registry.yarnpkg.com/axios/-/axios-1.3.4.tgz#f5760cefd9cfb51fd2481acf88c05f67c4523024" ··· 4252 4244 resolved "https://registry.npmjs.org/flatted/-/flatted-3.2.7.tgz" 4253 4245 integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== 4254 4246 4255 - follow-redirects@^1.14.9, follow-redirects@^1.15.0: 4247 + follow-redirects@^1.15.0: 4256 4248 version "1.15.2" 4257 4249 resolved "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.2.tgz" 4258 4250 integrity sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==