Matthieu Sieben 8ef976d385
xrpc-server & lex-cli rework (#3999)
* xrpc-server & lex-cli rework

* codegen

* tidy

* tidy

* tidy

* Update .changeset/nasty-icons-peel.md

Co-authored-by: devin ivy <devinivy@gmail.com>

* excludeErrorResult util

* Restore export of `SkeletonHandler` from `pds`

* Make `calcKey` RateLimiter option required

* Process request input after auth

* fix tests

* changeset

---------

Co-authored-by: devin ivy <devinivy@gmail.com>
2025-07-08 13:04:11 +02:00

124 lines
3.1 KiB
TypeScript

import * as http from 'node:http'
import { AddressInfo } from 'node:net'
import { LexiconDoc } from '@atproto/lexicon'
import { XrpcClient } from '@atproto/xrpc'
import * as xrpcServer from '../src'
import { closeServer, createServer } from './_util'
const LEXICONS: LexiconDoc[] = [
{
lexicon: 1,
id: 'io.example.pingOne',
defs: {
main: {
type: 'query',
parameters: {
type: 'params',
properties: {
message: { type: 'string' },
},
},
output: {
encoding: 'text/plain',
},
},
},
},
{
lexicon: 1,
id: 'io.example.pingTwo',
defs: {
main: {
type: 'query',
parameters: {
type: 'params',
properties: {
message: { type: 'string' },
},
},
output: {
encoding: 'application/octet-stream',
},
},
},
},
{
lexicon: 1,
id: 'io.example.pingThree',
defs: {
main: {
type: 'query',
parameters: {
type: 'params',
properties: {
message: { type: 'string' },
},
},
output: {
encoding: 'application/json',
schema: {
type: 'object',
required: ['message'],
properties: { message: { type: 'string' } },
},
},
},
},
},
]
describe('Queries', () => {
let s: http.Server
const server = xrpcServer.createServer(LEXICONS)
server.method('io.example.pingOne', (ctx) => {
return { encoding: 'text/plain', body: ctx.params.message }
})
server.method('io.example.pingTwo', (ctx) => {
return {
encoding: 'application/octet-stream',
body: new TextEncoder().encode(String(ctx.params.message)),
}
})
server.method('io.example.pingThree', (ctx) => {
return {
encoding: 'application/json',
body: { message: ctx.params.message },
headers: { 'x-test-header-name': 'test-value' },
}
})
let client: XrpcClient
beforeAll(async () => {
s = await createServer(server)
const { port } = s.address() as AddressInfo
client = new XrpcClient(`http://localhost:${port}`, LEXICONS)
})
afterAll(async () => {
await closeServer(s)
})
it('serves requests', async () => {
const res1 = await client.call('io.example.pingOne', {
message: 'hello world',
})
expect(res1.success).toBeTruthy()
expect(res1.headers['content-type']).toBe('text/plain; charset=utf-8')
expect(res1.data).toBe('hello world')
const res2 = await client.call('io.example.pingTwo', {
message: 'hello world',
})
expect(res2.success).toBeTruthy()
expect(res2.headers['content-type']).toBe('application/octet-stream')
expect(new TextDecoder().decode(res2.data)).toBe('hello world')
const res3 = await client.call('io.example.pingThree', {
message: 'hello world',
})
expect(res3.success).toBeTruthy()
expect(res3.headers['content-type']).toBe('application/json; charset=utf-8')
expect(res3.data?.message).toBe('hello world')
expect(res3.headers['x-test-header-name']).toEqual('test-value')
})
})