Suite of AT Protocol TypeScript libraries built on web standards
21
fork

Configure Feed

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

perms

+92 -28
+31
.github/workflows/check.yml
··· 1 + name: Check 2 + 3 + on: 4 + pull_request: 5 + branches: 6 + - main 7 + 8 + jobs: 9 + publish: 10 + runs-on: ubuntu-latest 11 + 12 + permissions: 13 + contents: read 14 + id-token: write 15 + 16 + steps: 17 + - name: Clone repository 18 + uses: actions/checkout@v5 19 + 20 + - name: Set up Deno 21 + uses: denoland/setup-deno@v2 22 + with: 23 + cache: true 24 + - name: Lint 25 + run: deno lint 26 + 27 + - name: Format 28 + run: deno fmt --check 29 + 30 + - name: Test 31 + run: deno test -P
+5 -2
.github/workflows/publish.yml
··· 1 - name: workspace publish 1 + name: Publish 2 2 3 3 on: 4 4 push: ··· 22 22 with: 23 23 cache: true 24 24 25 + - name: Lint 26 + run: deno lint 27 + 25 28 - name: Format 26 29 run: deno fmt --check 27 30 28 31 - name: Test 29 - run: deno test -A 32 + run: deno test -P 30 33 31 34 - name: Publish to JSR 32 35 run: deno publish
+5
common/deno.json
··· 16 16 "@std/streams": "jsr:@std/streams@^1.0.12", 17 17 "multiformats": "npm:multiformats@^13.4.1", 18 18 "zod": "jsr:@zod/zod@^4.1.11" 19 + }, 20 + "test": { 21 + "permissions": { 22 + "env": true 23 + } 19 24 } 20 25 }
+6
crypto/deno.json
··· 8 8 "@noble/hashes": "jsr:@noble/hashes@^2.0.1", 9 9 "@std/assert": "jsr:@std/assert@^1.0.14", 10 10 "multiformats": "npm:multiformats@^13.4.1" 11 + }, 12 + "test": { 13 + "permissions": { 14 + "env": true, 15 + "read": ["./tests/interop"] 16 + } 11 17 } 12 18 }
+5
lexicon/deno.json
··· 7 7 "@std/assert": "jsr:@std/assert@^1.0.14", 8 8 "multiformats": "npm:multiformats@^13.4.1", 9 9 "zod": "npm:zod@^4.1.11" 10 + }, 11 + "test": { 12 + "permissions": { 13 + "env": true 14 + } 10 15 } 11 16 }
+5
syntax/deno.json
··· 5 5 "license": "MIT", 6 6 "imports": { 7 7 "@std/assert": "jsr:@std/assert@^1.0.14" 8 + }, 9 + "test": { 10 + "permissions": { 11 + "read": ["./tests/interop"] 12 + } 8 13 } 9 14 }
+29 -26
xrpc-server/README.md
··· 1 1 # XRPC Server for Deno 2 2 3 - A native Deno implementation of an XRPC server that can be used with `deno.serve()`. 3 + A native Deno implementation of an XRPC server that can be used with 4 + `deno.serve()`. 4 5 5 6 ## Features 6 7 ··· 24 25 server.method("com.example.getProfile", { 25 26 handler: async (ctx: HandlerContext): Promise<HandlerSuccess> => { 26 27 const { params } = ctx; 27 - 28 + 28 29 return { 29 30 encoding: "application/json", 30 31 body: { ··· 40 41 server.method("com.example.createPost", { 41 42 handler: async (ctx: HandlerContext): Promise<HandlerSuccess> => { 42 43 const { input, auth } = ctx; 43 - 44 + 44 45 // Validate authentication 45 46 if (!auth) { 46 47 throw new Error("Authentication required"); 47 48 } 48 - 49 + 49 50 return { 50 51 encoding: "application/json", 51 52 body: { ··· 70 71 const server = createServer(lexicons, { 71 72 // Custom error parser 72 73 errorParser: (err) => { 73 - console.error('Server error:', err); 74 + console.error("Server error:", err); 74 75 return XRPCError.fromError(err); 75 76 }, 76 - 77 + 77 78 // Custom catchall handler for unregistered routes 78 79 catchall: async (req) => { 79 80 return new Response("Custom 404", { status: 404 }); 80 81 }, 81 - 82 + 82 83 // Rate limiting configuration 83 84 rateLimits: { 84 85 creator: (options) => new SomeRateLimiter(options), ··· 87 88 name: "global", 88 89 durationMs: 60000, // 1 minute 89 90 points: 100, // 100 requests per minute 90 - } 91 + }, 91 92 ], 92 93 shared: [ 93 94 { 94 95 name: "auth", 95 96 durationMs: 300000, // 5 minutes 96 97 points: 30, // 30 requests per 5 minutes 97 - } 98 + }, 98 99 ], 99 100 }, 100 101 }); ··· 108 109 server.method("com.example.searchPosts", { 109 110 handler: async ({ params }) => { 110 111 const { q, limit = 10 } = params; 111 - 112 + 112 113 // Search logic here 113 114 const results = await searchPosts(q, limit); 114 - 115 + 115 116 return { 116 117 encoding: "application/json", 117 118 body: { posts: results }, 118 119 }; 119 120 }, 120 - 121 + 121 122 // Optional authentication 122 123 auth: async ({ req, params, input }) => { 123 124 const token = req.headers.get("authorization"); 124 125 return await validateToken(token); 125 126 }, 126 - 127 + 127 128 // Optional rate limiting 128 129 rateLimit: { 129 130 durationMs: 60000, ··· 140 141 if (!auth?.user) { 141 142 throw new Error("Authentication required"); 142 143 } 143 - 144 + 144 145 const updatedProfile = await updateUserProfile(auth.user.id, input.body); 145 - 146 + 146 147 return { 147 148 encoding: "application/json", 148 149 body: updatedProfile, 149 150 }; 150 151 }, 151 - 152 + 152 153 auth: async ({ req }) => { 153 154 // Custom auth logic 154 155 return await authenticateUser(req); ··· 166 167 type: "update", 167 168 data: await getLiveData(), 168 169 }; 169 - 170 - await new Promise(resolve => setTimeout(resolve, 1000)); 170 + 171 + await new Promise((resolve) => setTimeout(resolve, 1000)); 171 172 } 172 173 }, 173 174 }); ··· 209 210 ## Error Handling 210 211 211 212 ```typescript 212 - import { 213 - InvalidRequestError, 213 + import { 214 + InvalidRequestError, 214 215 MethodNotImplementedError, 215 - XRPCError 216 + XRPCError, 216 217 } from "./errors.ts"; 217 218 218 219 server.method("com.example.riskyOperation", { ··· 220 221 if (!ctx.params.id) { 221 222 throw new InvalidRequestError("Missing required parameter: id"); 222 223 } 223 - 224 + 224 225 try { 225 226 const result = await performRiskyOperation(ctx.params.id); 226 227 return { ··· 250 251 ## Key Differences from Hono Version 251 252 252 253 1. **No external dependencies**: Uses native Deno server instead of Hono 253 - 2. **Direct handler**: The server's `handler` property is a function compatible with `deno.serve()` 254 + 2. **Direct handler**: The server's `handler` property is a function compatible 255 + with `deno.serve()` 254 256 3. **Simplified routing**: Routes are stored internally and matched directly 255 257 4. **Native Request/Response**: Uses standard Web API Request/Response objects 256 - 5. **Error handling**: Errors are converted to responses internally rather than thrown to middleware 258 + 5. **Error handling**: Errors are converted to responses internally rather than 259 + thrown to middleware 257 260 258 261 ## Migration from Hono 259 262 260 263 If you're migrating from a Hono-based XRPC server: 261 264 262 265 1. Remove Hono dependency from your imports 263 - 2. Replace `server.app` or `server.handler` with `server.handler` 266 + 2. Replace `server.app` or `server.handler` with `server.handler` 264 267 3. Use `deno.serve()` instead of Hono's serve method 265 - 4. Update any custom middleware to work with the native request handler 268 + 4. Update any custom middleware to work with the native request handler
+6
xrpc-server/deno.json
··· 15 15 "hono": "jsr:@hono/hono@^4.9.8", 16 16 "rate-limiter-flexible": "npm:rate-limiter-flexible@^2.4.2", 17 17 "ws": "npm:ws@^8.18.3" 18 + }, 19 + "test": { 20 + "permissions": { 21 + "env": true, 22 + "net": true 23 + } 18 24 } 19 25 }