a collection of lightweight TypeScript packages for AT Protocol, the protocol powering Bluesky
atproto bluesky typescript npm
101
fork

Configure Feed

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

refactor(xrpc-server)!: rename XRPCError.description to message

consolidate on the standard `Error.message` field rather than a separate
`description`. response bodies continue to serialize as `{ error, message }`;
the `InvalidHttpMethod` error code is replaced by the spec-standard
`InvalidRequest` to keep the vocabulary minimal.

Mary fa028bfd bd82378b

+38 -51
+7
.changeset/xrpc-server-error-message.md
··· 1 + --- 2 + '@atcute/xrpc-server': major 3 + --- 4 + 5 + rename `XRPCError.description` to `.message` (and the same on `XRPCSubscriptionError`). response 6 + bodies continue to serialize as `{ error, message }`. the custom `InvalidHttpMethod` error code is 7 + replaced by the spec-standard `InvalidRequest`.
+1 -1
packages/servers/xrpc-server-node/lib/index.test.ts
··· 191 191 const router = new XRPCRouter(); 192 192 router.addQuery(queryNoParams, { 193 193 async handler() { 194 - throw new InvalidRequestError({ description: 'something went wrong' }); 194 + throw new InvalidRequestError({ message: 'something went wrong' }); 195 195 }, 196 196 }); 197 197
+2 -2
packages/servers/xrpc-server/README.md
··· 135 135 136 136 const post = await db.getPost(params.uri); 137 137 if (!post) { 138 - throw new XRPCError({ status: 400, error: 'InvalidRequest', description: `post not found` }); 138 + throw new XRPCError({ status: 400, error: 'InvalidRequest', message: `post not found` }); 139 139 } 140 140 141 141 return json(post); ··· 201 201 if (params.cursor && isCursorTooOld(params.cursor)) { 202 202 throw new XRPCSubscriptionError({ 203 203 error: 'FutureCursor', 204 - description: `cursor is too old`, 204 + message: `cursor is too old`, 205 205 }); 206 206 } 207 207
+3 -3
packages/servers/xrpc-server/lib/main/router.test.ts
··· 274 274 { 275 275 router.addQuery(querySchema, { 276 276 async handler() { 277 - throw new InvalidRequestError({ description: 'invalid user' }); 277 + throw new InvalidRequestError({ message: 'invalid user' }); 278 278 }, 279 279 }); 280 280 ··· 883 883 { 884 884 router.addProcedure(procedureSchema, { 885 885 async handler() { 886 - throw new InvalidRequestError({ description: 'invalid user' }); 886 + throw new InvalidRequestError({ message: 'invalid user' }); 887 887 }, 888 888 }); 889 889 ··· 1136 1136 1137 1137 throw new XRPCSubscriptionError({ 1138 1138 error: 'FutureCursor', 1139 - description: 'Cursor is in the future', 1139 + message: 'Cursor is in the future', 1140 1140 }); 1141 1141 }, 1142 1142 });
+2 -2
packages/servers/xrpc-server/lib/main/router.ts
··· 114 114 115 115 if (request.method !== route.method) { 116 116 return Response.json( 117 - { error: 'InvalidHttpMethod', message: `invalid http method (expected ${route.method})` }, 117 + { error: 'InvalidRequest', message: `invalid http method (expected ${route.method})` }, 118 118 { status: 405, headers: { allow: `${route.method}` } }, 119 119 ); 120 120 } ··· 355 355 ws.close(1000); 356 356 } catch (err) { 357 357 if (err instanceof XRPCSubscriptionError) { 358 - const frame = encodeErrorFrame(err.error, err.description); 358 + const frame = encodeErrorFrame(err.error, err.message || undefined); 359 359 360 360 try { 361 361 await ws.send(frame);
+23 -43
packages/servers/xrpc-server/lib/main/xrpc-error.ts
··· 1 1 export interface XRPCErrorOptions { 2 2 status: number; 3 3 error: string; 4 - description?: string; 4 + message?: string; 5 5 headers?: HeadersInit; 6 6 } 7 7 ··· 11 11 12 12 /** error name */ 13 13 readonly error: string; 14 - /** error message */ 15 - readonly description?: string; 16 14 /** response headers */ 17 15 readonly headers?: HeadersInit; 18 16 19 - constructor({ status, error, description, headers }: XRPCErrorOptions) { 20 - super(`${error} > ${description ?? '(unspecified description)'}`); 17 + constructor({ status, error, message, headers }: XRPCErrorOptions) { 18 + super(message); 21 19 22 20 this.status = status; 23 21 24 22 this.error = error; 25 - this.description = description; 26 23 this.headers = headers; 27 24 } 28 25 29 26 toResponse(): Response { 30 27 return Response.json( 31 - { error: this.error, message: this.description }, 28 + { error: this.error, message: this.message || undefined }, 32 29 { status: this.status, headers: this.headers }, 33 30 ); 34 31 } 35 32 } 36 33 37 34 export class InvalidRequestError extends XRPCError { 38 - constructor({ 39 - status = 400, 40 - error = 'InvalidRequest', 41 - description, 42 - headers, 43 - }: Partial<XRPCErrorOptions> = {}) { 44 - super({ status, error, description, headers }); 35 + constructor({ status = 400, error = 'InvalidRequest', message, headers }: Partial<XRPCErrorOptions> = {}) { 36 + super({ status, error, message, headers }); 45 37 } 46 38 } 47 39 ··· 49 41 constructor({ 50 42 status = 401, 51 43 error = 'AuthenticationRequired', 52 - description, 44 + message, 53 45 headers, 54 46 }: Partial<XRPCErrorOptions> = {}) { 55 - super({ status, error, description, headers }); 47 + super({ status, error, message, headers }); 56 48 } 57 49 } 58 50 59 51 export class ForbiddenError extends XRPCError { 60 - constructor({ status = 403, error = 'Forbidden', description, headers }: Partial<XRPCErrorOptions> = {}) { 61 - super({ status, error, description, headers }); 52 + constructor({ status = 403, error = 'Forbidden', message, headers }: Partial<XRPCErrorOptions> = {}) { 53 + super({ status, error, message, headers }); 62 54 } 63 55 } 64 56 ··· 66 58 constructor({ 67 59 status = 429, 68 60 error = 'RateLimitExceeded', 69 - description, 61 + message, 70 62 headers, 71 63 }: Partial<XRPCErrorOptions> = {}) { 72 - super({ status, error, description, headers }); 64 + super({ status, error, message, headers }); 73 65 } 74 66 } 75 67 ··· 77 69 constructor({ 78 70 status = 500, 79 71 error = 'InternalServerError', 80 - description, 72 + message, 81 73 headers, 82 74 }: Partial<XRPCErrorOptions> = {}) { 83 - super({ status, error, description, headers }); 75 + super({ status, error, message, headers }); 84 76 } 85 77 } 86 78 87 79 export class UpstreamFailureError extends XRPCError { 88 - constructor({ 89 - status = 502, 90 - error = 'UpstreamFailure', 91 - description, 92 - headers, 93 - }: Partial<XRPCErrorOptions> = {}) { 94 - super({ status, error, description, headers }); 80 + constructor({ status = 502, error = 'UpstreamFailure', message, headers }: Partial<XRPCErrorOptions> = {}) { 81 + super({ status, error, message, headers }); 95 82 } 96 83 } 97 84 ··· 99 86 constructor({ 100 87 status = 503, 101 88 error = 'NotEnoughResources', 102 - description, 89 + message, 103 90 headers, 104 91 }: Partial<XRPCErrorOptions> = {}) { 105 - super({ status, error, description, headers }); 92 + super({ status, error, message, headers }); 106 93 } 107 94 } 108 95 109 96 export class UpstreamTimeoutError extends XRPCError { 110 - constructor({ 111 - status = 504, 112 - error = 'UpstreamTimeout', 113 - description, 114 - headers, 115 - }: Partial<XRPCErrorOptions> = {}) { 116 - super({ status, error, description, headers }); 97 + constructor({ status = 504, error = 'UpstreamTimeout', message, headers }: Partial<XRPCErrorOptions> = {}) { 98 + super({ status, error, message, headers }); 117 99 } 118 100 } 119 101 120 102 export interface XRPCSubscriptionErrorOptions { 121 103 closeCode?: number; 122 104 error: string; 123 - description?: string; 105 + message?: string; 124 106 } 125 107 126 108 export class XRPCSubscriptionError extends Error { 127 109 readonly closeCode: number; 128 110 readonly error: string; 129 - readonly description?: string; 130 111 131 - constructor({ closeCode = 1008, error, description }: XRPCSubscriptionErrorOptions) { 132 - super(`Subscription error: ${error}${description ? ` - ${description}` : ''}`); 112 + constructor({ closeCode = 1008, error, message }: XRPCSubscriptionErrorOptions) { 113 + super(message); 133 114 134 115 this.closeCode = closeCode; 135 116 this.error = error; 136 - this.description = description; 137 117 } 138 118 }