chadtmiller.com/pds.js
An atproto PDS in JavaScript, for Cloudflare Workers and Node
0
0
import { describe, expect, it } from 'vitest';
import {
parseDictionary,
SfToken,
serializeBare,
serializeDictionary,
serializeInnerList,
} from '../src/structured-fields.js';
describe('parseDictionary', () => {
it('parses items, inner lists and parameters', () => {
const dict = parseDictionary(
'a="x\\"y", b=12, c=:AQI=:, d=?1, e, f=tok/en;p=1, g=("h" "i";q);tag="t"',
);
expect(dict.get('a')).toMatchObject({ kind: 'item', value: 'x"y' });
expect(dict.get('b')).toMatchObject({ kind: 'item', value: 12 });
const c = dict.get('c');
expect(c?.kind === 'item' && c.value).toEqual(new Uint8Array([1, 2]));
expect(dict.get('d')).toMatchObject({ value: true });
expect(dict.get('e')).toMatchObject({ value: true });
const f = dict.get('f');
expect(f?.kind === 'item' && f.value).toBeInstanceOf(SfToken);
expect(f?.params.get('p')).toBe(1);
const g = dict.get('g');
if (g?.kind !== 'innerList') throw new Error('expected an inner list');
expect(g.items.map((i) => i.value)).toEqual(['h', 'i']);
expect(g.items[1].params.get('q')).toBe(true);
expect(g.params.get('tag')).toBe('t');
});
it('parses an empty field', () => {
expect(parseDictionary('').size).toBe(0);
});
it('refuses malformed input', () => {
for (const bad of [
'A=1',
'a=1,',
'a=1 b=2',
'a="unterminated',
'a="bad\\escape"',
'a=:AQI',
'a=:!!:',
'a=?2',
'a=("x"y)',
'a=@',
'a="é"',
]) {
expect(() => parseDictionary(bad), bad).toThrow();
}
});
});
describe('serialize', () => {
it('writes canonical members', () => {
expect(
serializeDictionary([
['type', 'atproto-space-repo'],
['ver', 1],
['mac', new Uint8Array([1, 2])],
['flag', true],
['off', false],
]),
).toBe('type="atproto-space-repo", ver=1, mac=:AQI=:, flag, off=?0');
expect(serializeBare('a"b\\c')).toBe('"a\\"b\\\\c"');
expect(serializeBare(new SfToken('tok'))).toBe('tok');
});
it('round-trips an inner list', () => {
const input = '("authorization" "atproto-space-audience";x);tag="t";flag';
const g = parseDictionary(`s=${input}`).get('s');
if (g?.kind !== 'innerList') throw new Error('expected an inner list');
expect(serializeInnerList(g.items, g.params)).toBe(input);
});
});