← back

cerulea/lexicon

define atproto schemas in TypeScript

git clone https://git.t4t.associates/cerulea/lexicon

Charlotte Somschema: split union() into its three ways of naming variants62f5f17

main
2 folders3 files

files

lib/
tests/
README.md1.7 KiB
deno.json292 B
mod.ts134 B

@cerulea/lexicon

define AT Protocol lexicon schemas in TypeScript

usage

import * as l from "@cerulea/lexicon";

const facetRange = { start: l.integer, end: l.integer };
const Facet = l.union("example.myapp.facet", {
  "#mention": l.object({ ...facetRange, did: l.did }),
  "#link": l.object({ ...facetRange, uri: l.uri }),
});

const Post = l.record("example.myapp.post", { key: "tid" }, {
  text: l.stringWith({ maxGraphemes: 300 }),
  facets: l.optional(l.array(Facet)),
  createdAt: l.datetime,
});
type Post = l.Infer<typeof Post>;

const getPost = l.query("example.myapp.getPost", {
  parameters: l.params({ uri: l.atUri }),
  output: Post,
  errors: [{ name: "NotFound" }],
});

const post: Post = Post.build({
  text: "hi @alice",
  facets: [{ $type: "#mention", start: 3, end: 9, did: "did:example:alice" }],
  createdAt: new Date().toISOString(),
});

const untrusted: unknown = {
  $type: "example.myapp.post",
  text: "hello",
  createdAt: "my evil invalid date",
};
const result = Post.validate(untrusted);
if (!result.success) console.error(result.issues);

const lexicons = l.toLexicons(Post, getPost);
/* [
  { lexicon: 1, id: "example.myapp.facet", … },
  { lexicon: 1, id: "example.myapp.getPost", … },
  …
] */