A human-friendly DSL for ATProto Lexicons
27
fork

Configure Feed

Select the types of activity you want to include in your feed.

Add nullable documentation

authored by stavola.xyz and committed by

Tangled 198df48a 94d286d0

+89 -1
+38 -1
website/content/docs/language-guide/02-fields.md
··· 18 18 } 19 19 ``` 20 20 21 + ## Nullable Fields 22 + 23 + ATProto distinguishes three states for a field: 24 + 25 + - **Absent** — the field is omitted from the JSON object. 26 + - **Present with a value** — the field is set. 27 + - **Present but null** — the field is explicitly `null`, which is a distinct signal from absent. 28 + 29 + Use `T | null` to declare that a field may hold an explicit `null`: 30 + 31 + ```mlf 32 + record user { 33 + handle!: string, 34 + displayName: string | null, // optional; if present, may be null 35 + bio: string | null, 36 + } 37 + ``` 38 + 39 + When combined with constraints, the `| null` appears after the constraint block: 40 + 41 + ```mlf 42 + record profile { 43 + displayName: string constrained { 44 + maxLength: 64, 45 + } | null, 46 + } 47 + ``` 48 + 49 + Semantically: 50 + - `handle!: string` — required, must be a non-null string. 51 + - `displayName: string` — optional; if present, must be a non-null string. 52 + - `displayName: string | null` — optional; if present, may be a string or `null`. 53 + - `displayName!: string | null` — required to be present; value may be a string or `null`. 54 + 55 + In the generated ATProto Lexicon, nullable fields appear in a top-level `nullable` array alongside the object's `required` array. MLF's `T | null` syntax folds that sibling array into the field's type position for readability. 56 + 21 57 ## Primitive Types 22 58 23 59 MLF supports several primitive types: ··· 65 101 **Null:** 66 102 ```mlf 67 103 record example { 68 - nothing: null, // Always null (rarely used) 104 + nothing: null, // Always null — rare as a standalone type; see 105 + // "Nullable Fields" above for the common `T | null` form 69 106 } 70 107 ``` 71 108
+14
website/content/docs/language-guide/05-unions.md
··· 85 85 86 86 Though defining types separately is often cleaner. 87 87 88 + ## Special Case: `T | null` 89 + 90 + `null` as a union member has dedicated semantics — it marks the field as 91 + nullable, not as a discriminated union of `T` or the `null` primitive. 92 + See [Nullable Fields](/docs/language-guide/fields/#nullable-fields) for 93 + details. The `| null` clause is structural, not a regular ref member, and 94 + is always lowered to the ATProto spec's top-level `nullable` array. 95 + 96 + ```mlf 97 + record profile { 98 + displayName: string | null, // nullable field, not an open union 99 + } 100 + ``` 101 + 88 102 ## Unions in Arrays 89 103 90 104 Unions work in arrays:
+37
website/content/docs/language-guide/11-lexicon-mapping.md
··· 313 313 - External references → `"namespace#defName"` 314 314 - Imported types → Resolved to full namespace 315 315 316 + ## Nullable Fields 317 + 318 + `T | null` in MLF lowers to the object's top-level `nullable` array, 319 + alongside `required`. See [Fields → Nullable Fields](/docs/language-guide/fields/#nullable-fields) 320 + for the conceptual model. 321 + 322 + **MLF:** 323 + ```mlf 324 + record user { 325 + handle!: string, 326 + displayName: string | null, 327 + bio: string | null, 328 + } 329 + ``` 330 + 331 + **Generated JSON:** 332 + ```json 333 + { 334 + "defs": { 335 + "main": { 336 + "type": "record", 337 + "key": "tid", 338 + "record": { 339 + "type": "object", 340 + "required": ["handle"], 341 + "nullable": ["displayName", "bio"], 342 + "properties": { 343 + "handle": { "type": "string" }, 344 + "displayName": { "type": "string" }, 345 + "bio": { "type": "string" } 346 + } 347 + } 348 + } 349 + } 350 + } 351 + ``` 352 + 316 353 ## Unions 317 354 318 355 **MLF:**