this repo has no description
1import { LexiconDoc, LexUserType } from '@atproto/lexicon'
2import { NSID } from '@atproto/nsid'
3
4export interface DefTreeNodeUserType {
5 nsid: string
6 def: LexUserType
7}
8
9export interface DefTreeNode {
10 name: string
11 className: string
12 propName: string
13 children: DefTreeNode[]
14 userTypes: DefTreeNodeUserType[]
15}
16
17export function lexiconsToDefTree(lexicons: LexiconDoc[]): DefTreeNode[] {
18 const tree: DefTreeNode[] = []
19 for (const lexicon of lexicons) {
20 if (!lexicon.defs.main) {
21 continue
22 }
23 const node = getOrCreateNode(tree, lexicon.id.split('.').slice(0, -1))
24 node.userTypes.push({ nsid: lexicon.id, def: lexicon.defs.main })
25 }
26 return tree
27}
28
29function getOrCreateNode(tree: DefTreeNode[], path: string[]): DefTreeNode {
30 let node: DefTreeNode | undefined
31 for (const segment of path) {
32 node = tree.find((v) => v.name === segment)
33 if (!node) {
34 node = {
35 name: segment,
36 className: `${toTitleCase(segment)}NS`,
37 propName: toCamelCase(segment),
38 children: [],
39 userTypes: [],
40 } as DefTreeNode
41 tree.push(node)
42 }
43 tree = node.children
44 }
45 if (!node) throw new Error(`Invalid schema path: ${path.join('.')}`)
46 return node
47}
48
49export function schemasToNsidTokens(
50 lexiconDocs: LexiconDoc[],
51): Record<string, string[]> {
52 const nsidTokens: Record<string, string[]> = {}
53 for (const lexiconDoc of lexiconDocs) {
54 const nsidp = NSID.parse(lexiconDoc.id)
55 if (!nsidp.name) continue
56 for (const defId in lexiconDoc.defs) {
57 const def = lexiconDoc.defs[defId]
58 if (def.type !== 'token') continue
59 const authority = nsidp.segments.slice(0, -1).join('.')
60 nsidTokens[authority] ??= []
61 nsidTokens[authority].push(
62 nsidp.name + (defId === 'main' ? '' : `#${defId}`),
63 )
64 }
65 }
66 return nsidTokens
67}
68
69export function toTitleCase(v: string): string {
70 v = v.replace(/^([a-z])/gi, (_, g) => g.toUpperCase()) // upper-case first letter
71 v = v.replace(/[.#-]([a-z])/gi, (_, g) => g.toUpperCase()) // uppercase any dash, dot, or hash segments
72 return v.replace(/[.-]/g, '') // remove lefover dashes or dots
73}
74
75export function toCamelCase(v: string): string {
76 v = v.replace(/[.#-]([a-z])/gi, (_, g) => g.toUpperCase()) // uppercase any dash, dot, or hash segments
77 return v.replace(/[.-]/g, '') // remove lefover dashes or dots
78}
79
80export function toScreamingSnakeCase(v: string): string {
81 v = v.replace(/[.#-]+/gi, '_') // convert dashes, dots, and hashes into underscores
82 return v.toUpperCase() // and scream!
83}