···22 * GENERATED CODE - DO NOT MODIFY
33 */
44import { ValidationResult, BlobRef } from '@atproto/lexicon'
55-import { lexicons } from '../../../../lexicons'
66-import { isObj, hasProp } from '../../../../util'
75import { CID } from 'multiformats/cid'
88-import * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs'
99-import * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef'
66+import { validate as _validate } from '../../../../lexicons'
77+import { $Typed, is$typed as _is$typed, OmitKey } from '../../../../util'
88+import type * as ComAtprotoLabelDefs from '../../../com/atproto/label/defs.js'
99+import type * as ComAtprotoRepoStrongRef from '../../../com/atproto/repo/strongRef.js'
1010+1111+const is$typed = _is$typed,
1212+ validate = _validate
1313+const id = 'app.bsky.actor.profile'
10141115export interface Record {
1616+ $type: 'app.bsky.actor.profile'
1217 displayName?: string
1318 /** Free-form profile description text. */
1419 description?: string
···1621 avatar?: BlobRef
1722 /** Larger horizontal image to display behind profile view. */
1823 banner?: BlobRef
1919- labels?:
2020- | ComAtprotoLabelDefs.SelfLabels
2121- | { $type: string; [k: string]: unknown }
2424+ labels?: $Typed<ComAtprotoLabelDefs.SelfLabels> | { $type: string }
2225 joinedViaStarterPack?: ComAtprotoRepoStrongRef.Main
2326 createdAt?: string
2427 [k: string]: unknown
2528}
26292727-export function isRecord(v: unknown): v is Record {
2828- return (
2929- isObj(v) &&
3030- hasProp(v, '$type') &&
3131- (v.$type === 'app.bsky.actor.profile#main' ||
3232- v.$type === 'app.bsky.actor.profile')
3333- )
3030+const hashRecord = 'main'
3131+3232+export function isRecord<V>(v: V) {
3333+ return is$typed(v, id, hashRecord)
3434}
35353636-export function validateRecord(v: unknown): ValidationResult {
3737- return lexicons.validate('app.bsky.actor.profile#main', v)
3636+export function validateRecord<V>(v: V) {
3737+ return validate<Record & V>(v, id, hashRecord, true)
3838}
+43-52
src/lexicon/types/com/atproto/label/defs.ts
···22 * GENERATED CODE - DO NOT MODIFY
33 */
44import { ValidationResult, BlobRef } from '@atproto/lexicon'
55-import { lexicons } from '../../../../lexicons'
66-import { isObj, hasProp } from '../../../../util'
75import { CID } from 'multiformats/cid'
66+import { validate as _validate } from '../../../../lexicons'
77+import { $Typed, is$typed as _is$typed, OmitKey } from '../../../../util'
88+99+const is$typed = _is$typed,
1010+ validate = _validate
1111+const id = 'com.atproto.label.defs'
812913/** Metadata tag on an atproto resource (eg, repo or record). */
1014export interface Label {
1515+ $type?: 'com.atproto.label.defs#label'
1116 /** The AT Protocol version of the label object. */
1217 ver?: number
1318 /** DID of the actor who created this label. */
···2631 exp?: string
2732 /** Signature of dag-cbor encoded label. */
2833 sig?: Uint8Array
2929- [k: string]: unknown
3034}
31353232-export function isLabel(v: unknown): v is Label {
3333- return (
3434- isObj(v) &&
3535- hasProp(v, '$type') &&
3636- v.$type === 'com.atproto.label.defs#label'
3737- )
3636+const hashLabel = 'label'
3737+3838+export function isLabel<V>(v: V) {
3939+ return is$typed(v, id, hashLabel)
3840}
39414040-export function validateLabel(v: unknown): ValidationResult {
4141- return lexicons.validate('com.atproto.label.defs#label', v)
4242+export function validateLabel<V>(v: V) {
4343+ return validate<Label & V>(v, id, hashLabel)
4244}
43454446/** Metadata tags on an atproto record, published by the author within the record. */
4547export interface SelfLabels {
4848+ $type?: 'com.atproto.label.defs#selfLabels'
4649 values: SelfLabel[]
4747- [k: string]: unknown
4850}
49515050-export function isSelfLabels(v: unknown): v is SelfLabels {
5151- return (
5252- isObj(v) &&
5353- hasProp(v, '$type') &&
5454- v.$type === 'com.atproto.label.defs#selfLabels'
5555- )
5252+const hashSelfLabels = 'selfLabels'
5353+5454+export function isSelfLabels<V>(v: V) {
5555+ return is$typed(v, id, hashSelfLabels)
5656}
57575858-export function validateSelfLabels(v: unknown): ValidationResult {
5959- return lexicons.validate('com.atproto.label.defs#selfLabels', v)
5858+export function validateSelfLabels<V>(v: V) {
5959+ return validate<SelfLabels & V>(v, id, hashSelfLabels)
6060}
61616262/** Metadata tag on an atproto record, published by the author within the record. Note that schemas should use #selfLabels, not #selfLabel. */
6363export interface SelfLabel {
6464+ $type?: 'com.atproto.label.defs#selfLabel'
6465 /** The short string name of the value or type of this label. */
6566 val: string
6666- [k: string]: unknown
6767}
68686969-export function isSelfLabel(v: unknown): v is SelfLabel {
7070- return (
7171- isObj(v) &&
7272- hasProp(v, '$type') &&
7373- v.$type === 'com.atproto.label.defs#selfLabel'
7474- )
6969+const hashSelfLabel = 'selfLabel'
7070+7171+export function isSelfLabel<V>(v: V) {
7272+ return is$typed(v, id, hashSelfLabel)
7573}
76747777-export function validateSelfLabel(v: unknown): ValidationResult {
7878- return lexicons.validate('com.atproto.label.defs#selfLabel', v)
7575+export function validateSelfLabel<V>(v: V) {
7676+ return validate<SelfLabel & V>(v, id, hashSelfLabel)
7977}
80788179/** Declares a label value and its expected interpretations and behaviors. */
8280export interface LabelValueDefinition {
8181+ $type?: 'com.atproto.label.defs#labelValueDefinition'
8382 /** The value of the label being defined. Must only include lowercase ascii and the '-' character ([a-z-]+). */
8483 identifier: string
8584 /** How should a client visually convey this label? 'inform' means neutral and informational; 'alert' means negative and warning; 'none' means show nothing. */
···9190 /** Does the user need to have adult content enabled in order to configure this label? */
9291 adultOnly?: boolean
9392 locales: LabelValueDefinitionStrings[]
9494- [k: string]: unknown
9593}
96949797-export function isLabelValueDefinition(v: unknown): v is LabelValueDefinition {
9898- return (
9999- isObj(v) &&
100100- hasProp(v, '$type') &&
101101- v.$type === 'com.atproto.label.defs#labelValueDefinition'
102102- )
9595+const hashLabelValueDefinition = 'labelValueDefinition'
9696+9797+export function isLabelValueDefinition<V>(v: V) {
9898+ return is$typed(v, id, hashLabelValueDefinition)
10399}
104100105105-export function validateLabelValueDefinition(v: unknown): ValidationResult {
106106- return lexicons.validate('com.atproto.label.defs#labelValueDefinition', v)
101101+export function validateLabelValueDefinition<V>(v: V) {
102102+ return validate<LabelValueDefinition & V>(v, id, hashLabelValueDefinition)
107103}
108104109105/** Strings which describe the label in the UI, localized into a specific language. */
110106export interface LabelValueDefinitionStrings {
107107+ $type?: 'com.atproto.label.defs#labelValueDefinitionStrings'
111108 /** The code of the language these strings are written in. */
112109 lang: string
113110 /** A short human-readable name for the label. */
114111 name: string
115112 /** A longer description of what the label means and why it might be applied. */
116113 description: string
117117- [k: string]: unknown
118114}
119115120120-export function isLabelValueDefinitionStrings(
121121- v: unknown,
122122-): v is LabelValueDefinitionStrings {
123123- return (
124124- isObj(v) &&
125125- hasProp(v, '$type') &&
126126- v.$type === 'com.atproto.label.defs#labelValueDefinitionStrings'
127127- )
116116+const hashLabelValueDefinitionStrings = 'labelValueDefinitionStrings'
117117+118118+export function isLabelValueDefinitionStrings<V>(v: V) {
119119+ return is$typed(v, id, hashLabelValueDefinitionStrings)
128120}
129121130130-export function validateLabelValueDefinitionStrings(
131131- v: unknown,
132132-): ValidationResult {
133133- return lexicons.validate(
134134- 'com.atproto.label.defs#labelValueDefinitionStrings',
122122+export function validateLabelValueDefinitionStrings<V>(v: V) {
123123+ return validate<LabelValueDefinitionStrings & V>(
135124 v,
125125+ id,
126126+ hashLabelValueDefinitionStrings,
136127 )
137128}
138129
+13-12
src/lexicon/types/com/atproto/repo/strongRef.ts
···22 * GENERATED CODE - DO NOT MODIFY
33 */
44import { ValidationResult, BlobRef } from '@atproto/lexicon'
55-import { lexicons } from '../../../../lexicons'
66-import { isObj, hasProp } from '../../../../util'
75import { CID } from 'multiformats/cid'
66+import { validate as _validate } from '../../../../lexicons'
77+import { $Typed, is$typed as _is$typed, OmitKey } from '../../../../util'
88+99+const is$typed = _is$typed,
1010+ validate = _validate
1111+const id = 'com.atproto.repo.strongRef'
812913export interface Main {
1414+ $type?: 'com.atproto.repo.strongRef'
1015 uri: string
1116 cid: string
1212- [k: string]: unknown
1317}
14181515-export function isMain(v: unknown): v is Main {
1616- return (
1717- isObj(v) &&
1818- hasProp(v, '$type') &&
1919- (v.$type === 'com.atproto.repo.strongRef#main' ||
2020- v.$type === 'com.atproto.repo.strongRef')
2121- )
1919+const hashMain = 'main'
2020+2121+export function isMain<V>(v: V) {
2222+ return is$typed(v, id, hashMain)
2223}
23242424-export function validateMain(v: unknown): ValidationResult {
2525- return lexicons.validate('com.atproto.repo.strongRef#main', v)
2525+export function validateMain<V>(v: V) {
2626+ return validate<Main & V>(v, id, hashMain)
2627}
+13-11
src/lexicon/types/xyz/statusphere/status.ts
···22 * GENERATED CODE - DO NOT MODIFY
33 */
44import { ValidationResult, BlobRef } from '@atproto/lexicon'
55-import { lexicons } from '../../../lexicons'
66-import { isObj, hasProp } from '../../../util'
75import { CID } from 'multiformats/cid'
66+import { validate as _validate } from '../../../lexicons'
77+import { $Typed, is$typed as _is$typed, OmitKey } from '../../../util'
88+99+const is$typed = _is$typed,
1010+ validate = _validate
1111+const id = 'xyz.statusphere.status'
812913export interface Record {
1414+ $type: 'xyz.statusphere.status'
1015 status: string
1116 createdAt: string
1217 [k: string]: unknown
1318}
14191515-export function isRecord(v: unknown): v is Record {
1616- return (
1717- isObj(v) &&
1818- hasProp(v, '$type') &&
1919- (v.$type === 'xyz.statusphere.status#main' ||
2020- v.$type === 'xyz.statusphere.status')
2121- )
2020+const hashRecord = 'main'
2121+2222+export function isRecord<V>(v: V) {
2323+ return is$typed(v, id, hashRecord)
2224}
23252424-export function validateRecord(v: unknown): ValidationResult {
2525- return lexicons.validate('xyz.statusphere.status#main', v)
2626+export function validateRecord<V>(v: V) {
2727+ return validate<Record & V>(v, id, hashRecord, true)
2628}
+76-7
src/lexicon/util.ts
···11/**
22 * GENERATED CODE - DO NOT MODIFY
33 */
44-export function isObj(v: unknown): v is Record<string, unknown> {
55- return typeof v === 'object' && v !== null
44+55+import { ValidationResult } from '@atproto/lexicon'
66+77+export type OmitKey<T, K extends keyof T> = {
88+ [K2 in keyof T as K2 extends K ? never : K2]: T[K2]
99+}
1010+1111+export type $Typed<V, T extends string = string> = V & { $type: T }
1212+export type Un$Typed<V extends { $type?: string }> = OmitKey<V, '$type'>
1313+1414+export type $Type<Id extends string, Hash extends string> = Hash extends 'main'
1515+ ? Id
1616+ : `${Id}#${Hash}`
1717+1818+function isObject<V>(v: V): v is V & object {
1919+ return v != null && typeof v === 'object'
2020+}
2121+2222+function is$type<Id extends string, Hash extends string>(
2323+ $type: unknown,
2424+ id: Id,
2525+ hash: Hash,
2626+): $type is $Type<Id, Hash> {
2727+ return hash === 'main'
2828+ ? $type === id
2929+ : // $type === `${id}#${hash}`
3030+ typeof $type === 'string' &&
3131+ $type.length === id.length + 1 + hash.length &&
3232+ $type.charCodeAt(id.length) === 35 /* '#' */ &&
3333+ $type.startsWith(id) &&
3434+ $type.endsWith(hash)
3535+}
3636+3737+export type $TypedObject<
3838+ V,
3939+ Id extends string,
4040+ Hash extends string,
4141+> = V extends {
4242+ $type: $Type<Id, Hash>
4343+}
4444+ ? V
4545+ : V extends { $type?: string }
4646+ ? V extends { $type?: infer T extends $Type<Id, Hash> }
4747+ ? V & { $type: T }
4848+ : never
4949+ : V & { $type: $Type<Id, Hash> }
5050+5151+export function is$typed<V, Id extends string, Hash extends string>(
5252+ v: V,
5353+ id: Id,
5454+ hash: Hash,
5555+): v is $TypedObject<V, Id, Hash> {
5656+ return isObject(v) && '$type' in v && is$type(v.$type, id, hash)
5757+}
5858+5959+export function maybe$typed<V, Id extends string, Hash extends string>(
6060+ v: V,
6161+ id: Id,
6262+ hash: Hash,
6363+): v is V & object & { $type?: $Type<Id, Hash> } {
6464+ return (
6565+ isObject(v) &&
6666+ ('$type' in v ? v.$type === undefined || is$type(v.$type, id, hash) : true)
6767+ )
668}
76988-export function hasProp<K extends PropertyKey>(
99- data: object,
1010- prop: K,
1111-): data is Record<K, unknown> {
1212- return prop in data
7070+export type Validator<R = unknown> = (v: unknown) => ValidationResult<R>
7171+export type ValidatorParam<V extends Validator> =
7272+ V extends Validator<infer R> ? R : never
7373+7474+/**
7575+ * Utility function that allows to convert a "validate*" utility function into a
7676+ * type predicate.
7777+ */
7878+export function asPredicate<V extends Validator>(validate: V) {
7979+ return function <T>(v: T): v is T & ValidatorParam<V> {
8080+ return validate(v).success
8181+ }
1382}