@atproto/lex-schema 0.0.10 → 0.0.12

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (239) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/core/$type.d.ts +149 -0
  3. package/dist/core/$type.d.ts.map +1 -1
  4. package/dist/core/$type.js +44 -0
  5. package/dist/core/$type.js.map +1 -1
  6. package/dist/core/record-key.d.ts +44 -0
  7. package/dist/core/record-key.d.ts.map +1 -1
  8. package/dist/core/record-key.js +30 -0
  9. package/dist/core/record-key.js.map +1 -1
  10. package/dist/core/result.d.ts +85 -4
  11. package/dist/core/result.d.ts.map +1 -1
  12. package/dist/core/result.js +60 -4
  13. package/dist/core/result.js.map +1 -1
  14. package/dist/core/schema.d.ts +229 -2
  15. package/dist/core/schema.d.ts.map +1 -1
  16. package/dist/core/schema.js +197 -4
  17. package/dist/core/schema.js.map +1 -1
  18. package/dist/core/string-format.d.ts +244 -11
  19. package/dist/core/string-format.d.ts.map +1 -1
  20. package/dist/core/string-format.js +150 -0
  21. package/dist/core/string-format.js.map +1 -1
  22. package/dist/core/types.d.ts +90 -3
  23. package/dist/core/types.d.ts.map +1 -1
  24. package/dist/core/types.js.map +1 -1
  25. package/dist/core/validation-error.d.ts +61 -1
  26. package/dist/core/validation-error.d.ts.map +1 -1
  27. package/dist/core/validation-error.js +60 -0
  28. package/dist/core/validation-error.js.map +1 -1
  29. package/dist/core/validation-issue.d.ts +61 -0
  30. package/dist/core/validation-issue.d.ts.map +1 -1
  31. package/dist/core/validation-issue.js +51 -0
  32. package/dist/core/validation-issue.js.map +1 -1
  33. package/dist/core/validator.d.ts +347 -10
  34. package/dist/core/validator.d.ts.map +1 -1
  35. package/dist/core/validator.js +184 -3
  36. package/dist/core/validator.js.map +1 -1
  37. package/dist/helpers.d.ts +13 -25
  38. package/dist/helpers.d.ts.map +1 -1
  39. package/dist/helpers.js +2 -2
  40. package/dist/helpers.js.map +1 -1
  41. package/dist/schema/array.d.ts +45 -0
  42. package/dist/schema/array.d.ts.map +1 -1
  43. package/dist/schema/array.js +14 -0
  44. package/dist/schema/array.js.map +1 -1
  45. package/dist/schema/blob.d.ts +46 -0
  46. package/dist/schema/blob.d.ts.map +1 -1
  47. package/dist/schema/blob.js +39 -0
  48. package/dist/schema/blob.js.map +1 -1
  49. package/dist/schema/boolean.d.ts +28 -0
  50. package/dist/schema/boolean.d.ts.map +1 -1
  51. package/dist/schema/boolean.js +28 -0
  52. package/dist/schema/boolean.js.map +1 -1
  53. package/dist/schema/bytes.d.ts +38 -0
  54. package/dist/schema/bytes.d.ts.map +1 -1
  55. package/dist/schema/bytes.js +32 -0
  56. package/dist/schema/bytes.js.map +1 -1
  57. package/dist/schema/cid.d.ts +38 -0
  58. package/dist/schema/cid.d.ts.map +1 -1
  59. package/dist/schema/cid.js +33 -0
  60. package/dist/schema/cid.js.map +1 -1
  61. package/dist/schema/custom.d.ts +66 -1
  62. package/dist/schema/custom.d.ts.map +1 -1
  63. package/dist/schema/custom.js +54 -0
  64. package/dist/schema/custom.js.map +1 -1
  65. package/dist/schema/dict.d.ts +44 -0
  66. package/dist/schema/dict.d.ts.map +1 -1
  67. package/dist/schema/dict.js +44 -0
  68. package/dist/schema/dict.js.map +1 -1
  69. package/dist/schema/discriminated-union.d.ts +58 -0
  70. package/dist/schema/discriminated-union.d.ts.map +1 -1
  71. package/dist/schema/discriminated-union.js +45 -0
  72. package/dist/schema/discriminated-union.js.map +1 -1
  73. package/dist/schema/enum.d.ts +48 -0
  74. package/dist/schema/enum.d.ts.map +1 -1
  75. package/dist/schema/enum.js +48 -0
  76. package/dist/schema/enum.js.map +1 -1
  77. package/dist/schema/integer.d.ts +42 -0
  78. package/dist/schema/integer.d.ts.map +1 -1
  79. package/dist/schema/integer.js +36 -0
  80. package/dist/schema/integer.js.map +1 -1
  81. package/dist/schema/intersection.d.ts +54 -0
  82. package/dist/schema/intersection.d.ts.map +1 -1
  83. package/dist/schema/intersection.js +49 -0
  84. package/dist/schema/intersection.js.map +1 -1
  85. package/dist/schema/literal.d.ts +44 -0
  86. package/dist/schema/literal.d.ts.map +1 -1
  87. package/dist/schema/literal.js +44 -0
  88. package/dist/schema/literal.js.map +1 -1
  89. package/dist/schema/never.d.ts +42 -0
  90. package/dist/schema/never.d.ts.map +1 -1
  91. package/dist/schema/never.js +42 -0
  92. package/dist/schema/never.js.map +1 -1
  93. package/dist/schema/null.d.ts +29 -0
  94. package/dist/schema/null.d.ts.map +1 -1
  95. package/dist/schema/null.js +29 -0
  96. package/dist/schema/null.js.map +1 -1
  97. package/dist/schema/nullable.d.ts +41 -0
  98. package/dist/schema/nullable.d.ts.map +1 -1
  99. package/dist/schema/nullable.js +41 -0
  100. package/dist/schema/nullable.js.map +1 -1
  101. package/dist/schema/object.d.ts +56 -0
  102. package/dist/schema/object.d.ts.map +1 -1
  103. package/dist/schema/object.js +51 -0
  104. package/dist/schema/object.js.map +1 -1
  105. package/dist/schema/optional.d.ts +42 -0
  106. package/dist/schema/optional.d.ts.map +1 -1
  107. package/dist/schema/optional.js +42 -0
  108. package/dist/schema/optional.js.map +1 -1
  109. package/dist/schema/params.d.ts +89 -7
  110. package/dist/schema/params.d.ts.map +1 -1
  111. package/dist/schema/params.js +84 -10
  112. package/dist/schema/params.js.map +1 -1
  113. package/dist/schema/payload.d.ts +111 -15
  114. package/dist/schema/payload.d.ts.map +1 -1
  115. package/dist/schema/payload.js +70 -0
  116. package/dist/schema/payload.js.map +1 -1
  117. package/dist/schema/permission-set.d.ts +58 -0
  118. package/dist/schema/permission-set.d.ts.map +1 -1
  119. package/dist/schema/permission-set.js +50 -0
  120. package/dist/schema/permission-set.js.map +1 -1
  121. package/dist/schema/permission.d.ts +42 -0
  122. package/dist/schema/permission.d.ts.map +1 -1
  123. package/dist/schema/permission.js +39 -0
  124. package/dist/schema/permission.js.map +1 -1
  125. package/dist/schema/procedure.d.ts +64 -0
  126. package/dist/schema/procedure.d.ts.map +1 -1
  127. package/dist/schema/procedure.js +64 -0
  128. package/dist/schema/procedure.js.map +1 -1
  129. package/dist/schema/query.d.ts +55 -0
  130. package/dist/schema/query.d.ts.map +1 -1
  131. package/dist/schema/query.js +55 -0
  132. package/dist/schema/query.js.map +1 -1
  133. package/dist/schema/record.d.ts +63 -8
  134. package/dist/schema/record.d.ts.map +1 -1
  135. package/dist/schema/record.js +20 -0
  136. package/dist/schema/record.js.map +1 -1
  137. package/dist/schema/ref.d.ts +50 -0
  138. package/dist/schema/ref.d.ts.map +1 -1
  139. package/dist/schema/ref.js +17 -0
  140. package/dist/schema/ref.js.map +1 -1
  141. package/dist/schema/refine.d.ts +58 -9
  142. package/dist/schema/refine.d.ts.map +1 -1
  143. package/dist/schema/refine.js.map +1 -1
  144. package/dist/schema/regexp.d.ts +44 -0
  145. package/dist/schema/regexp.d.ts.map +1 -1
  146. package/dist/schema/regexp.js +44 -0
  147. package/dist/schema/regexp.js.map +1 -1
  148. package/dist/schema/string.d.ts +50 -0
  149. package/dist/schema/string.d.ts.map +1 -1
  150. package/dist/schema/string.js +41 -0
  151. package/dist/schema/string.js.map +1 -1
  152. package/dist/schema/subscription.d.ts +72 -2
  153. package/dist/schema/subscription.d.ts.map +1 -1
  154. package/dist/schema/subscription.js +59 -0
  155. package/dist/schema/subscription.js.map +1 -1
  156. package/dist/schema/token.d.ts +47 -0
  157. package/dist/schema/token.d.ts.map +1 -1
  158. package/dist/schema/token.js +47 -0
  159. package/dist/schema/token.js.map +1 -1
  160. package/dist/schema/typed-object.d.ts +62 -8
  161. package/dist/schema/typed-object.d.ts.map +1 -1
  162. package/dist/schema/typed-object.js +18 -0
  163. package/dist/schema/typed-object.js.map +1 -1
  164. package/dist/schema/typed-ref.d.ts +53 -0
  165. package/dist/schema/typed-ref.d.ts.map +1 -1
  166. package/dist/schema/typed-ref.js +15 -0
  167. package/dist/schema/typed-ref.js.map +1 -1
  168. package/dist/schema/typed-union.d.ts +50 -1
  169. package/dist/schema/typed-union.d.ts.map +1 -1
  170. package/dist/schema/typed-union.js +50 -1
  171. package/dist/schema/typed-union.js.map +1 -1
  172. package/dist/schema/union.d.ts +45 -0
  173. package/dist/schema/union.d.ts.map +1 -1
  174. package/dist/schema/union.js +40 -0
  175. package/dist/schema/union.js.map +1 -1
  176. package/dist/schema/unknown-object.d.ts +34 -0
  177. package/dist/schema/unknown-object.d.ts.map +1 -1
  178. package/dist/schema/unknown-object.js +31 -0
  179. package/dist/schema/unknown-object.js.map +1 -1
  180. package/dist/schema/unknown.d.ts +33 -0
  181. package/dist/schema/unknown.d.ts.map +1 -1
  182. package/dist/schema/unknown.js +33 -0
  183. package/dist/schema/unknown.js.map +1 -1
  184. package/dist/schema/with-default.d.ts +44 -0
  185. package/dist/schema/with-default.d.ts.map +1 -1
  186. package/dist/schema/with-default.js +44 -0
  187. package/dist/schema/with-default.js.map +1 -1
  188. package/package.json +4 -4
  189. package/src/core/$type.ts +150 -18
  190. package/src/core/record-key.ts +44 -0
  191. package/src/core/result.ts +86 -4
  192. package/src/core/schema.ts +236 -7
  193. package/src/core/string-format.ts +259 -13
  194. package/src/core/types.ts +91 -3
  195. package/src/core/validation-error.ts +60 -0
  196. package/src/core/validation-issue.ts +65 -0
  197. package/src/core/validator.ts +351 -10
  198. package/src/helpers.test.ts +110 -29
  199. package/src/helpers.ts +14 -14
  200. package/src/schema/array.test.ts +94 -79
  201. package/src/schema/array.ts +45 -0
  202. package/src/schema/blob.ts +46 -0
  203. package/src/schema/boolean.ts +28 -0
  204. package/src/schema/bytes.ts +38 -0
  205. package/src/schema/cid.ts +38 -0
  206. package/src/schema/custom.ts +66 -1
  207. package/src/schema/dict.ts +44 -0
  208. package/src/schema/discriminated-union.ts +58 -0
  209. package/src/schema/enum.ts +48 -0
  210. package/src/schema/integer.ts +42 -0
  211. package/src/schema/intersection.ts +54 -0
  212. package/src/schema/literal.ts +44 -0
  213. package/src/schema/never.ts +42 -0
  214. package/src/schema/null.ts +29 -0
  215. package/src/schema/nullable.ts +41 -0
  216. package/src/schema/object.ts +56 -0
  217. package/src/schema/optional.ts +42 -0
  218. package/src/schema/params.test.ts +58 -2
  219. package/src/schema/params.ts +124 -16
  220. package/src/schema/payload.test.ts +3 -3
  221. package/src/schema/payload.ts +142 -38
  222. package/src/schema/permission-set.ts +58 -0
  223. package/src/schema/permission.ts +42 -0
  224. package/src/schema/procedure.ts +64 -0
  225. package/src/schema/query.ts +55 -0
  226. package/src/schema/record.ts +63 -8
  227. package/src/schema/ref.ts +50 -0
  228. package/src/schema/refine.ts +58 -9
  229. package/src/schema/regexp.ts +44 -0
  230. package/src/schema/string.ts +50 -0
  231. package/src/schema/subscription.ts +72 -2
  232. package/src/schema/token.ts +47 -0
  233. package/src/schema/typed-object.ts +62 -8
  234. package/src/schema/typed-ref.ts +53 -0
  235. package/src/schema/typed-union.ts +55 -2
  236. package/src/schema/union.ts +45 -0
  237. package/src/schema/unknown-object.ts +34 -0
  238. package/src/schema/unknown.ts +33 -0
  239. package/src/schema/with-default.ts +44 -0
@@ -1,8 +1,42 @@
1
1
  import { LexMap } from '@atproto/lex-data';
2
2
  import { Schema, ValidationContext } from '../core.js';
3
+ /**
4
+ * Type alias for a plain object with unknown values.
5
+ */
3
6
  export type UnknownObject = LexMap;
7
+ /**
8
+ * Schema that accepts any plain object without validating its properties.
9
+ *
10
+ * Validates that the input is a plain object (not an array, Date, or other
11
+ * special object type), but does not validate the object's properties.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const schema = new UnknownObjectSchema()
16
+ * schema.validate({ any: 'props' }) // success
17
+ * schema.validate([1, 2, 3]) // fails - arrays not accepted
18
+ * ```
19
+ */
4
20
  export declare class UnknownObjectSchema extends Schema<UnknownObject> {
5
21
  validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<LexMap>;
6
22
  }
23
+ /**
24
+ * Creates a schema that accepts any plain object.
25
+ *
26
+ * Unlike `l.unknown()` which accepts any value, this validates that the input
27
+ * is specifically a plain object (not an array, null, or primitive).
28
+ *
29
+ * @returns A new {@link UnknownObjectSchema} instance
30
+ *
31
+ * @example
32
+ * ```ts
33
+ * // Accept any object shape
34
+ * const metadataSchema = l.unknownObject()
35
+ *
36
+ * metadataSchema.parse({ foo: 1, bar: 'baz' }) // success
37
+ * metadataSchema.parse([1, 2, 3]) // throws - not a plain object
38
+ * metadataSchema.parse(null) // throws
39
+ * ```
40
+ */
7
41
  export declare const unknownObject: () => UnknownObjectSchema;
8
42
  //# sourceMappingURL=unknown-object.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"unknown-object.d.ts","sourceRoot":"","sources":["../../src/schema/unknown-object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAY,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAGtD,MAAM,MAAM,aAAa,GAAG,MAAM,CAAA;AAElC,qBAAa,mBAAoB,SAAQ,MAAM,CAAC,aAAa,CAAC;IAC5D,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB;CAOzD;AAED,eAAO,MAAM,aAAa,2BAExB,CAAA"}
1
+ {"version":3,"file":"unknown-object.d.ts","sourceRoot":"","sources":["../../src/schema/unknown-object.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAY,MAAM,mBAAmB,CAAA;AACpD,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAGtD;;GAEG;AACH,MAAM,MAAM,aAAa,GAAG,MAAM,CAAA;AAElC;;;;;;;;;;;;GAYG;AACH,qBAAa,mBAAoB,SAAQ,MAAM,CAAC,aAAa,CAAC;IAC5D,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB;CAOzD;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,eAAO,MAAM,aAAa,2BAExB,CAAA"}
@@ -4,6 +4,19 @@ exports.unknownObject = exports.UnknownObjectSchema = void 0;
4
4
  const lex_data_1 = require("@atproto/lex-data");
5
5
  const core_js_1 = require("../core.js");
6
6
  const memoize_js_1 = require("../util/memoize.js");
7
+ /**
8
+ * Schema that accepts any plain object without validating its properties.
9
+ *
10
+ * Validates that the input is a plain object (not an array, Date, or other
11
+ * special object type), but does not validate the object's properties.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const schema = new UnknownObjectSchema()
16
+ * schema.validate({ any: 'props' }) // success
17
+ * schema.validate([1, 2, 3]) // fails - arrays not accepted
18
+ * ```
19
+ */
7
20
  class UnknownObjectSchema extends core_js_1.Schema {
8
21
  validateInContext(input, ctx) {
9
22
  if ((0, lex_data_1.isLexMap)(input)) {
@@ -13,6 +26,24 @@ class UnknownObjectSchema extends core_js_1.Schema {
13
26
  }
14
27
  }
15
28
  exports.UnknownObjectSchema = UnknownObjectSchema;
29
+ /**
30
+ * Creates a schema that accepts any plain object.
31
+ *
32
+ * Unlike `l.unknown()` which accepts any value, this validates that the input
33
+ * is specifically a plain object (not an array, null, or primitive).
34
+ *
35
+ * @returns A new {@link UnknownObjectSchema} instance
36
+ *
37
+ * @example
38
+ * ```ts
39
+ * // Accept any object shape
40
+ * const metadataSchema = l.unknownObject()
41
+ *
42
+ * metadataSchema.parse({ foo: 1, bar: 'baz' }) // success
43
+ * metadataSchema.parse([1, 2, 3]) // throws - not a plain object
44
+ * metadataSchema.parse(null) // throws
45
+ * ```
46
+ */
16
47
  exports.unknownObject = (0, memoize_js_1.memoizedOptions)(function () {
17
48
  return new UnknownObjectSchema();
18
49
  });
@@ -1 +1 @@
1
- {"version":3,"file":"unknown-object.js","sourceRoot":"","sources":["../../src/schema/unknown-object.ts"],"names":[],"mappings":";;;AAAA,gDAAoD;AACpD,wCAAsD;AACtD,mDAAoD;AAIpD,MAAa,mBAAoB,SAAQ,gBAAqB;IAC5D,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,IAAI,IAAA,mBAAQ,EAAC,KAAK,CAAC,EAAE,CAAC;YACpB,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAC3B,CAAC;QAED,OAAO,GAAG,CAAC,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IAC/C,CAAC;CACF;AARD,kDAQC;AAEY,QAAA,aAAa,GAAiB,IAAA,4BAAe,EAAC;IACzD,OAAO,IAAI,mBAAmB,EAAE,CAAA;AAClC,CAAC,CAAC,CAAA","sourcesContent":["import { LexMap, isLexMap } from '@atproto/lex-data'\nimport { Schema, ValidationContext } from '../core.js'\nimport { memoizedOptions } from '../util/memoize.js'\n\nexport type UnknownObject = LexMap\n\nexport class UnknownObjectSchema extends Schema<UnknownObject> {\n validateInContext(input: unknown, ctx: ValidationContext) {\n if (isLexMap(input)) {\n return ctx.success(input)\n }\n\n return ctx.issueInvalidType(input, 'unknown')\n }\n}\n\nexport const unknownObject = /*#__PURE__*/ memoizedOptions(function () {\n return new UnknownObjectSchema()\n})\n"]}
1
+ {"version":3,"file":"unknown-object.js","sourceRoot":"","sources":["../../src/schema/unknown-object.ts"],"names":[],"mappings":";;;AAAA,gDAAoD;AACpD,wCAAsD;AACtD,mDAAoD;AAOpD;;;;;;;;;;;;GAYG;AACH,MAAa,mBAAoB,SAAQ,gBAAqB;IAC5D,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,IAAI,IAAA,mBAAQ,EAAC,KAAK,CAAC,EAAE,CAAC;YACpB,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;QAC3B,CAAC;QAED,OAAO,GAAG,CAAC,gBAAgB,CAAC,KAAK,EAAE,SAAS,CAAC,CAAA;IAC/C,CAAC;CACF;AARD,kDAQC;AAED;;;;;;;;;;;;;;;;;GAiBG;AACU,QAAA,aAAa,GAAiB,IAAA,4BAAe,EAAC;IACzD,OAAO,IAAI,mBAAmB,EAAE,CAAA;AAClC,CAAC,CAAC,CAAA","sourcesContent":["import { LexMap, isLexMap } from '@atproto/lex-data'\nimport { Schema, ValidationContext } from '../core.js'\nimport { memoizedOptions } from '../util/memoize.js'\n\n/**\n * Type alias for a plain object with unknown values.\n */\nexport type UnknownObject = LexMap\n\n/**\n * Schema that accepts any plain object without validating its properties.\n *\n * Validates that the input is a plain object (not an array, Date, or other\n * special object type), but does not validate the object's properties.\n *\n * @example\n * ```ts\n * const schema = new UnknownObjectSchema()\n * schema.validate({ any: 'props' }) // success\n * schema.validate([1, 2, 3]) // fails - arrays not accepted\n * ```\n */\nexport class UnknownObjectSchema extends Schema<UnknownObject> {\n validateInContext(input: unknown, ctx: ValidationContext) {\n if (isLexMap(input)) {\n return ctx.success(input)\n }\n\n return ctx.issueInvalidType(input, 'unknown')\n }\n}\n\n/**\n * Creates a schema that accepts any plain object.\n *\n * Unlike `l.unknown()` which accepts any value, this validates that the input\n * is specifically a plain object (not an array, null, or primitive).\n *\n * @returns A new {@link UnknownObjectSchema} instance\n *\n * @example\n * ```ts\n * // Accept any object shape\n * const metadataSchema = l.unknownObject()\n *\n * metadataSchema.parse({ foo: 1, bar: 'baz' }) // success\n * metadataSchema.parse([1, 2, 3]) // throws - not a plain object\n * metadataSchema.parse(null) // throws\n * ```\n */\nexport const unknownObject = /*#__PURE__*/ memoizedOptions(function () {\n return new UnknownObjectSchema()\n})\n"]}
@@ -1,6 +1,39 @@
1
1
  import { Schema, ValidationContext } from '../core.js';
2
+ /**
3
+ * Schema that accepts any value without validation.
4
+ *
5
+ * Passes through any input unchanged. Use sparingly as it bypasses
6
+ * type safety. Useful for dynamic data or when the schema is not
7
+ * known at compile time.
8
+ *
9
+ * @example
10
+ * ```ts
11
+ * const schema = new UnknownSchema()
12
+ * schema.validate(anything) // always succeeds
13
+ * ```
14
+ */
2
15
  export declare class UnknownSchema extends Schema<unknown> {
3
16
  validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<unknown>;
4
17
  }
18
+ /**
19
+ * Creates an unknown schema that accepts any value.
20
+ *
21
+ * The value passes through without any validation or transformation.
22
+ * Use this when you need to accept arbitrary data.
23
+ *
24
+ * @returns A new {@link UnknownSchema} instance
25
+ *
26
+ * @example
27
+ * ```ts
28
+ * // Accept any value
29
+ * const anyDataSchema = l.unknown()
30
+ *
31
+ * // In an object with a dynamic field
32
+ * const flexibleSchema = l.object({
33
+ * type: l.string(),
34
+ * data: l.unknown(),
35
+ * })
36
+ * ```
37
+ */
5
38
  export declare const unknown: () => UnknownSchema;
6
39
  //# sourceMappingURL=unknown.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"unknown.d.ts","sourceRoot":"","sources":["../../src/schema/unknown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAGtD,qBAAa,aAAc,SAAQ,MAAM,CAAC,OAAO,CAAC;IAChD,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB;CAGzD;AAED,eAAO,MAAM,OAAO,qBAElB,CAAA"}
1
+ {"version":3,"file":"unknown.d.ts","sourceRoot":"","sources":["../../src/schema/unknown.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAA;AAGtD;;;;;;;;;;;;GAYG;AACH,qBAAa,aAAc,SAAQ,MAAM,CAAC,OAAO,CAAC;IAChD,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB;CAGzD;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,eAAO,MAAM,OAAO,qBAElB,CAAA"}
@@ -3,12 +3,45 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.unknown = exports.UnknownSchema = void 0;
4
4
  const core_js_1 = require("../core.js");
5
5
  const memoize_js_1 = require("../util/memoize.js");
6
+ /**
7
+ * Schema that accepts any value without validation.
8
+ *
9
+ * Passes through any input unchanged. Use sparingly as it bypasses
10
+ * type safety. Useful for dynamic data or when the schema is not
11
+ * known at compile time.
12
+ *
13
+ * @example
14
+ * ```ts
15
+ * const schema = new UnknownSchema()
16
+ * schema.validate(anything) // always succeeds
17
+ * ```
18
+ */
6
19
  class UnknownSchema extends core_js_1.Schema {
7
20
  validateInContext(input, ctx) {
8
21
  return ctx.success(input);
9
22
  }
10
23
  }
11
24
  exports.UnknownSchema = UnknownSchema;
25
+ /**
26
+ * Creates an unknown schema that accepts any value.
27
+ *
28
+ * The value passes through without any validation or transformation.
29
+ * Use this when you need to accept arbitrary data.
30
+ *
31
+ * @returns A new {@link UnknownSchema} instance
32
+ *
33
+ * @example
34
+ * ```ts
35
+ * // Accept any value
36
+ * const anyDataSchema = l.unknown()
37
+ *
38
+ * // In an object with a dynamic field
39
+ * const flexibleSchema = l.object({
40
+ * type: l.string(),
41
+ * data: l.unknown(),
42
+ * })
43
+ * ```
44
+ */
12
45
  exports.unknown = (0, memoize_js_1.memoizedOptions)(function () {
13
46
  return new UnknownSchema();
14
47
  });
@@ -1 +1 @@
1
- {"version":3,"file":"unknown.js","sourceRoot":"","sources":["../../src/schema/unknown.ts"],"names":[],"mappings":";;;AAAA,wCAAsD;AACtD,mDAAoD;AAEpD,MAAa,aAAc,SAAQ,gBAAe;IAChD,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC3B,CAAC;CACF;AAJD,sCAIC;AAEY,QAAA,OAAO,GAAiB,IAAA,4BAAe,EAAC;IACnD,OAAO,IAAI,aAAa,EAAE,CAAA;AAC5B,CAAC,CAAC,CAAA","sourcesContent":["import { Schema, ValidationContext } from '../core.js'\nimport { memoizedOptions } from '../util/memoize.js'\n\nexport class UnknownSchema extends Schema<unknown> {\n validateInContext(input: unknown, ctx: ValidationContext) {\n return ctx.success(input)\n }\n}\n\nexport const unknown = /*#__PURE__*/ memoizedOptions(function () {\n return new UnknownSchema()\n})\n"]}
1
+ {"version":3,"file":"unknown.js","sourceRoot":"","sources":["../../src/schema/unknown.ts"],"names":[],"mappings":";;;AAAA,wCAAsD;AACtD,mDAAoD;AAEpD;;;;;;;;;;;;GAYG;AACH,MAAa,aAAc,SAAQ,gBAAe;IAChD,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,OAAO,GAAG,CAAC,OAAO,CAAC,KAAK,CAAC,CAAA;IAC3B,CAAC;CACF;AAJD,sCAIC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACU,QAAA,OAAO,GAAiB,IAAA,4BAAe,EAAC;IACnD,OAAO,IAAI,aAAa,EAAE,CAAA;AAC5B,CAAC,CAAC,CAAA","sourcesContent":["import { Schema, ValidationContext } from '../core.js'\nimport { memoizedOptions } from '../util/memoize.js'\n\n/**\n * Schema that accepts any value without validation.\n *\n * Passes through any input unchanged. Use sparingly as it bypasses\n * type safety. Useful for dynamic data or when the schema is not\n * known at compile time.\n *\n * @example\n * ```ts\n * const schema = new UnknownSchema()\n * schema.validate(anything) // always succeeds\n * ```\n */\nexport class UnknownSchema extends Schema<unknown> {\n validateInContext(input: unknown, ctx: ValidationContext) {\n return ctx.success(input)\n }\n}\n\n/**\n * Creates an unknown schema that accepts any value.\n *\n * The value passes through without any validation or transformation.\n * Use this when you need to accept arbitrary data.\n *\n * @returns A new {@link UnknownSchema} instance\n *\n * @example\n * ```ts\n * // Accept any value\n * const anyDataSchema = l.unknown()\n *\n * // In an object with a dynamic field\n * const flexibleSchema = l.object({\n * type: l.string(),\n * data: l.unknown(),\n * })\n * ```\n */\nexport const unknown = /*#__PURE__*/ memoizedOptions(function () {\n return new UnknownSchema()\n})\n"]}
@@ -1,9 +1,53 @@
1
1
  import { InferInput, InferOutput, Schema, ValidationContext, Validator } from '../core.js';
2
+ /**
3
+ * Schema wrapper that provides a default value when the input is undefined.
4
+ *
5
+ * In parse mode, when the input is `undefined`, the default value is used
6
+ * instead. In validate mode, undefined values pass through unchanged (the
7
+ * default is not applied).
8
+ *
9
+ * @template TValidator - The wrapped validator type
10
+ *
11
+ * @example
12
+ * ```ts
13
+ * const schema = new WithDefaultSchema(l.integer(), 0)
14
+ * schema.parse(undefined) // 0
15
+ * schema.parse(42) // 42
16
+ * ```
17
+ */
2
18
  export declare class WithDefaultSchema<const TValidator extends Validator> extends Schema<InferInput<TValidator>, InferOutput<TValidator>> {
3
19
  readonly validator: TValidator;
4
20
  readonly defaultValue: InferInput<TValidator>;
5
21
  constructor(validator: TValidator, defaultValue: InferInput<TValidator>);
6
22
  validateInContext(input: unknown, ctx: ValidationContext): import("../core.js").ValidationResult<InferInput<TValidator>>;
7
23
  }
24
+ /**
25
+ * Creates a schema that applies a default value when the input is undefined.
26
+ *
27
+ * Commonly used with `optional()` to provide fallback values for missing
28
+ * properties. The default value is validated against the schema.
29
+ *
30
+ * @param validator - The validator for the value
31
+ * @param defaultValue - The default value to use when input is undefined
32
+ * @returns A new {@link WithDefaultSchema} instance
33
+ *
34
+ * @example
35
+ * ```ts
36
+ * // Integer with default
37
+ * const countSchema = l.withDefault(l.integer(), 0)
38
+ * countSchema.parse(undefined) // 0
39
+ * countSchema.parse(5) // 5
40
+ *
41
+ * // Commonly combined with optional in objects
42
+ * const settingsSchema = l.object({
43
+ * theme: l.optional(l.withDefault(l.string(), 'light')),
44
+ * pageSize: l.optional(l.withDefault(l.integer(), 25)),
45
+ * })
46
+ * settingsSchema.parse({}) // { theme: 'light', pageSize: 25 }
47
+ *
48
+ * // Boolean with default
49
+ * const enabledSchema = l.withDefault(l.boolean(), false)
50
+ * ```
51
+ */
8
52
  export declare function withDefault<const TValidator extends Validator>(validator: TValidator, defaultValue: InferInput<TValidator>): WithDefaultSchema<TValidator>;
9
53
  //# sourceMappingURL=with-default.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"with-default.d.ts","sourceRoot":"","sources":["../../src/schema/with-default.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,WAAW,EACX,MAAM,EACN,iBAAiB,EACjB,SAAS,EACV,MAAM,YAAY,CAAA;AAEnB,qBAAa,iBAAiB,CAC5B,KAAK,CAAC,UAAU,SAAS,SAAS,CAClC,SAAQ,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IAE7D,QAAQ,CAAC,SAAS,EAAE,UAAU;IAC9B,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC,UAAU,CAAC;gBADpC,SAAS,EAAE,UAAU,EACrB,YAAY,EAAE,UAAU,CAAC,UAAU,CAAC;IAK/C,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB;CASzD;AAED,wBAAgB,WAAW,CAAC,KAAK,CAAC,UAAU,SAAS,SAAS,EAC5D,SAAS,EAAE,UAAU,EACrB,YAAY,EAAE,UAAU,CAAC,UAAU,CAAC,iCAGrC"}
1
+ {"version":3,"file":"with-default.d.ts","sourceRoot":"","sources":["../../src/schema/with-default.ts"],"names":[],"mappings":"AAAA,OAAO,EACL,UAAU,EACV,WAAW,EACX,MAAM,EACN,iBAAiB,EACjB,SAAS,EACV,MAAM,YAAY,CAAA;AAEnB;;;;;;;;;;;;;;;GAeG;AACH,qBAAa,iBAAiB,CAC5B,KAAK,CAAC,UAAU,SAAS,SAAS,CAClC,SAAQ,MAAM,CAAC,UAAU,CAAC,UAAU,CAAC,EAAE,WAAW,CAAC,UAAU,CAAC,CAAC;IAE7D,QAAQ,CAAC,SAAS,EAAE,UAAU;IAC9B,QAAQ,CAAC,YAAY,EAAE,UAAU,CAAC,UAAU,CAAC;gBADpC,SAAS,EAAE,UAAU,EACrB,YAAY,EAAE,UAAU,CAAC,UAAU,CAAC;IAK/C,iBAAiB,CAAC,KAAK,EAAE,OAAO,EAAE,GAAG,EAAE,iBAAiB;CASzD;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,wBAAgB,WAAW,CAAC,KAAK,CAAC,UAAU,SAAS,SAAS,EAC5D,SAAS,EAAE,UAAU,EACrB,YAAY,EAAE,UAAU,CAAC,UAAU,CAAC,iCAGrC"}
@@ -3,6 +3,22 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.WithDefaultSchema = void 0;
4
4
  exports.withDefault = withDefault;
5
5
  const core_js_1 = require("../core.js");
6
+ /**
7
+ * Schema wrapper that provides a default value when the input is undefined.
8
+ *
9
+ * In parse mode, when the input is `undefined`, the default value is used
10
+ * instead. In validate mode, undefined values pass through unchanged (the
11
+ * default is not applied).
12
+ *
13
+ * @template TValidator - The wrapped validator type
14
+ *
15
+ * @example
16
+ * ```ts
17
+ * const schema = new WithDefaultSchema(l.integer(), 0)
18
+ * schema.parse(undefined) // 0
19
+ * schema.parse(42) // 42
20
+ * ```
21
+ */
6
22
  class WithDefaultSchema extends core_js_1.Schema {
7
23
  validator;
8
24
  defaultValue;
@@ -21,6 +37,34 @@ class WithDefaultSchema extends core_js_1.Schema {
21
37
  }
22
38
  }
23
39
  exports.WithDefaultSchema = WithDefaultSchema;
40
+ /**
41
+ * Creates a schema that applies a default value when the input is undefined.
42
+ *
43
+ * Commonly used with `optional()` to provide fallback values for missing
44
+ * properties. The default value is validated against the schema.
45
+ *
46
+ * @param validator - The validator for the value
47
+ * @param defaultValue - The default value to use when input is undefined
48
+ * @returns A new {@link WithDefaultSchema} instance
49
+ *
50
+ * @example
51
+ * ```ts
52
+ * // Integer with default
53
+ * const countSchema = l.withDefault(l.integer(), 0)
54
+ * countSchema.parse(undefined) // 0
55
+ * countSchema.parse(5) // 5
56
+ *
57
+ * // Commonly combined with optional in objects
58
+ * const settingsSchema = l.object({
59
+ * theme: l.optional(l.withDefault(l.string(), 'light')),
60
+ * pageSize: l.optional(l.withDefault(l.integer(), 25)),
61
+ * })
62
+ * settingsSchema.parse({}) // { theme: 'light', pageSize: 25 }
63
+ *
64
+ * // Boolean with default
65
+ * const enabledSchema = l.withDefault(l.boolean(), false)
66
+ * ```
67
+ */
24
68
  function withDefault(validator, defaultValue) {
25
69
  return new WithDefaultSchema(validator, defaultValue);
26
70
  }
@@ -1 +1 @@
1
- {"version":3,"file":"with-default.js","sourceRoot":"","sources":["../../src/schema/with-default.ts"],"names":[],"mappings":";;;AA6BA,kCAKC;AAlCD,wCAMmB;AAEnB,MAAa,iBAEX,SAAQ,gBAAuD;IAEpD;IACA;IAFX,YACW,SAAqB,EACrB,YAAoC;QAE7C,KAAK,EAAE,CAAA;QAHE,cAAS,GAAT,SAAS,CAAY;QACrB,iBAAY,GAAZ,YAAY,CAAwB;IAG/C,CAAC;IAED,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,kEAAkE;QAClE,iCAAiC;QACjC,IAAI,KAAK,KAAK,SAAS,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC3D,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;QACxD,CAAC;QAED,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;IAC5C,CAAC;CACF;AAnBD,8CAmBC;AAED,SAAgB,WAAW,CACzB,SAAqB,EACrB,YAAoC;IAEpC,OAAO,IAAI,iBAAiB,CAAa,SAAS,EAAE,YAAY,CAAC,CAAA;AACnE,CAAC","sourcesContent":["import {\n InferInput,\n InferOutput,\n Schema,\n ValidationContext,\n Validator,\n} from '../core.js'\n\nexport class WithDefaultSchema<\n const TValidator extends Validator,\n> extends Schema<InferInput<TValidator>, InferOutput<TValidator>> {\n constructor(\n readonly validator: TValidator,\n readonly defaultValue: InferInput<TValidator>,\n ) {\n super()\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n // When in a validation context, the output should not be altered,\n // so we don't apply the default.\n if (input === undefined && ctx.options.mode !== 'validate') {\n return ctx.validate(this.defaultValue, this.validator)\n }\n\n return ctx.validate(input, this.validator)\n }\n}\n\nexport function withDefault<const TValidator extends Validator>(\n validator: TValidator,\n defaultValue: InferInput<TValidator>,\n) {\n return new WithDefaultSchema<TValidator>(validator, defaultValue)\n}\n"]}
1
+ {"version":3,"file":"with-default.js","sourceRoot":"","sources":["../../src/schema/with-default.ts"],"names":[],"mappings":";;;AAyEA,kCAKC;AA9ED,wCAMmB;AAEnB;;;;;;;;;;;;;;;GAeG;AACH,MAAa,iBAEX,SAAQ,gBAAuD;IAEpD;IACA;IAFX,YACW,SAAqB,EACrB,YAAoC;QAE7C,KAAK,EAAE,CAAA;QAHE,cAAS,GAAT,SAAS,CAAY;QACrB,iBAAY,GAAZ,YAAY,CAAwB;IAG/C,CAAC;IAED,iBAAiB,CAAC,KAAc,EAAE,GAAsB;QACtD,kEAAkE;QAClE,iCAAiC;QACjC,IAAI,KAAK,KAAK,SAAS,IAAI,GAAG,CAAC,OAAO,CAAC,IAAI,KAAK,UAAU,EAAE,CAAC;YAC3D,OAAO,GAAG,CAAC,QAAQ,CAAC,IAAI,CAAC,YAAY,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;QACxD,CAAC;QAED,OAAO,GAAG,CAAC,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,SAAS,CAAC,CAAA;IAC5C,CAAC;CACF;AAnBD,8CAmBC;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,SAAgB,WAAW,CACzB,SAAqB,EACrB,YAAoC;IAEpC,OAAO,IAAI,iBAAiB,CAAa,SAAS,EAAE,YAAY,CAAC,CAAA;AACnE,CAAC","sourcesContent":["import {\n InferInput,\n InferOutput,\n Schema,\n ValidationContext,\n Validator,\n} from '../core.js'\n\n/**\n * Schema wrapper that provides a default value when the input is undefined.\n *\n * In parse mode, when the input is `undefined`, the default value is used\n * instead. In validate mode, undefined values pass through unchanged (the\n * default is not applied).\n *\n * @template TValidator - The wrapped validator type\n *\n * @example\n * ```ts\n * const schema = new WithDefaultSchema(l.integer(), 0)\n * schema.parse(undefined) // 0\n * schema.parse(42) // 42\n * ```\n */\nexport class WithDefaultSchema<\n const TValidator extends Validator,\n> extends Schema<InferInput<TValidator>, InferOutput<TValidator>> {\n constructor(\n readonly validator: TValidator,\n readonly defaultValue: InferInput<TValidator>,\n ) {\n super()\n }\n\n validateInContext(input: unknown, ctx: ValidationContext) {\n // When in a validation context, the output should not be altered,\n // so we don't apply the default.\n if (input === undefined && ctx.options.mode !== 'validate') {\n return ctx.validate(this.defaultValue, this.validator)\n }\n\n return ctx.validate(input, this.validator)\n }\n}\n\n/**\n * Creates a schema that applies a default value when the input is undefined.\n *\n * Commonly used with `optional()` to provide fallback values for missing\n * properties. The default value is validated against the schema.\n *\n * @param validator - The validator for the value\n * @param defaultValue - The default value to use when input is undefined\n * @returns A new {@link WithDefaultSchema} instance\n *\n * @example\n * ```ts\n * // Integer with default\n * const countSchema = l.withDefault(l.integer(), 0)\n * countSchema.parse(undefined) // 0\n * countSchema.parse(5) // 5\n *\n * // Commonly combined with optional in objects\n * const settingsSchema = l.object({\n * theme: l.optional(l.withDefault(l.string(), 'light')),\n * pageSize: l.optional(l.withDefault(l.integer(), 25)),\n * })\n * settingsSchema.parse({}) // { theme: 'light', pageSize: 25 }\n *\n * // Boolean with default\n * const enabledSchema = l.withDefault(l.boolean(), false)\n * ```\n */\nexport function withDefault<const TValidator extends Validator>(\n validator: TValidator,\n defaultValue: InferInput<TValidator>,\n) {\n return new WithDefaultSchema<TValidator>(validator, defaultValue)\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atproto/lex-schema",
3
- "version": "0.0.10",
3
+ "version": "0.0.12",
4
4
  "license": "MIT",
5
5
  "description": "Lexicon schema system for AT Lexicons",
6
6
  "keywords": [
@@ -31,13 +31,13 @@
31
31
  "types": "./dist/index.d.ts",
32
32
  "browser": "./dist/index.js",
33
33
  "import": "./dist/index.js",
34
- "require": "./dist/index.js"
34
+ "default": "./dist/index.js"
35
35
  }
36
36
  },
37
37
  "dependencies": {
38
38
  "tslib": "^2.8.1",
39
- "@atproto/syntax": "0.4.3",
40
- "@atproto/lex-data": "0.0.9"
39
+ "@atproto/syntax": "^0.4.3",
40
+ "@atproto/lex-data": "^0.0.11"
41
41
  },
42
42
  "devDependencies": {
43
43
  "vitest": "^4.0.16"
package/src/core/$type.ts CHANGED
@@ -1,6 +1,25 @@
1
1
  import { NsidString } from './string-format.js'
2
2
  import { OmitKey, Simplify } from './types.js'
3
3
 
4
+ /**
5
+ * Constructs the `$type` string type for a given NSID and hash.
6
+ *
7
+ * The `$type` value identifies a schema definition within a lexicon:
8
+ * - For "main" definitions: just the NSID (e.g., `'app.bsky.feed.post'`)
9
+ * - For named definitions: NSID + hash + name (e.g., `'app.bsky.feed.defs#postView'`)
10
+ *
11
+ * @typeParam N - The NSID string type
12
+ * @typeParam H - The hash/definition name (use `'main'` for the main definition)
13
+ *
14
+ * @example
15
+ * ```typescript
16
+ * type MainType = $Type<'app.bsky.feed.post', 'main'>
17
+ * // Result: 'app.bsky.feed.post'
18
+ *
19
+ * type DefType = $Type<'app.bsky.feed.defs', 'postView'>
20
+ * // Result: 'app.bsky.feed.defs#postView'
21
+ * ```
22
+ */
4
23
  export type $Type<
5
24
  N extends NsidString = NsidString,
6
25
  H extends string = string,
@@ -12,8 +31,41 @@ export type $Type<
12
31
  : `${N}#${H}`
13
32
  : never
14
33
 
34
+ /**
35
+ * Extracts the `$type` string type from an object type.
36
+ *
37
+ * @typeParam O - An object type with an optional `$type` property
38
+ *
39
+ * @example
40
+ * ```typescript
41
+ * type Post = { $type: 'app.bsky.feed.post'; text: string }
42
+ * type PostType = $TypeOf<Post>
43
+ * // Result: 'app.bsky.feed.post'
44
+ * ```
45
+ */
15
46
  export type $TypeOf<O extends { $type?: string }> = NonNullable<O['$type']>
16
47
 
48
+ /**
49
+ * Constructs a `$type` string value from an NSID and definition name.
50
+ *
51
+ * For the "main" definition, returns just the NSID. For named definitions,
52
+ * returns the NSID followed by `#` and the definition name.
53
+ *
54
+ * @typeParam N - The NSID string type
55
+ * @typeParam H - The definition name type
56
+ * @param nsid - The NSID of the lexicon
57
+ * @param hash - The definition name within the lexicon (use `'main'` for the main definition)
58
+ * @returns The constructed `$type` string
59
+ *
60
+ * @example
61
+ * ```typescript
62
+ * $type('app.bsky.feed.post', 'main')
63
+ * // Returns: 'app.bsky.feed.post'
64
+ *
65
+ * $type('app.bsky.feed.defs', 'postView')
66
+ * // Returns: 'app.bsky.feed.defs#postView'
67
+ * ```
68
+ */
17
69
  /*@__NO_SIDE_EFFECTS__*/
18
70
  export function $type<N extends NsidString, H extends string>(
19
71
  nsid: N,
@@ -22,12 +74,50 @@ export function $type<N extends NsidString, H extends string>(
22
74
  return (hash === 'main' ? nsid : `${nsid}#${hash}`) as $Type<N, H>
23
75
  }
24
76
 
77
+ /**
78
+ * Represents an object with a required `$type` property.
79
+ *
80
+ * This type adds a `$type` property to an existing object type, useful for
81
+ * representing typed AT Protocol objects.
82
+ *
83
+ * @typeParam V - The base object type
84
+ * @typeParam T - The `$type` string literal type
85
+ *
86
+ * @example
87
+ * ```typescript
88
+ * type Post = $Typed<{ text: string; createdAt: string }, 'app.bsky.feed.post'>
89
+ * // Result: { $type: 'app.bsky.feed.post'; text: string; createdAt: string }
90
+ * ```
91
+ */
25
92
  export type $Typed<V, T extends string = string> = Simplify<
26
93
  V & {
27
94
  $type: T
28
95
  }
29
96
  >
30
97
 
98
+ /**
99
+ * Ensures an object has the specified `$type` property.
100
+ *
101
+ * If the object already has the correct `$type`, returns it unchanged.
102
+ * Otherwise, creates a new object with the `$type` property added.
103
+ *
104
+ * @typeParam V - The object type (may already have `$type`)
105
+ * @typeParam T - The expected `$type` string
106
+ * @param value - The object to add `$type` to
107
+ * @param $type - The `$type` value to ensure
108
+ * @returns The object with the `$type` property
109
+ *
110
+ * @example
111
+ * ```typescript
112
+ * const post = $typed({ text: 'hello' }, 'app.bsky.feed.post')
113
+ * // Result: { $type: 'app.bsky.feed.post', text: 'hello' }
114
+ *
115
+ * // If already typed, returns same object
116
+ * const typed = { $type: 'app.bsky.feed.post', text: 'hello' }
117
+ * const same = $typed(typed, 'app.bsky.feed.post')
118
+ * console.log(typed === same) // true
119
+ * ```
120
+ */
31
121
  export function $typed<V extends { $type?: unknown }, T extends string>(
32
122
  value: V,
33
123
  $type: T,
@@ -35,33 +125,75 @@ export function $typed<V extends { $type?: unknown }, T extends string>(
35
125
  return value.$type === $type ? (value as $Typed<V, T>) : { ...value, $type }
36
126
  }
37
127
 
128
+ /**
129
+ * Represents an object with an optional `$type` property.
130
+ *
131
+ * This is used for objects that may or may not have type information,
132
+ * such as input parameters that accept both typed and untyped values.
133
+ *
134
+ * @typeParam V - The base object type
135
+ * @typeParam T - The optional `$type` string literal type
136
+ */
38
137
  export type $TypedMaybe<V, T extends string = string> = Simplify<
39
138
  V & {
40
139
  $type?: T
41
140
  }
42
141
  >
43
142
 
143
+ /**
144
+ * Removes the `$type` property from an object type.
145
+ *
146
+ * Useful for extracting the "content" of a typed object without the type marker.
147
+ *
148
+ * @typeParam V - An object type with an optional `$type` property
149
+ *
150
+ * @example
151
+ * ```typescript
152
+ * type Post = { $type: 'app.bsky.feed.post'; text: string }
153
+ * type PostContent = Un$Typed<Post>
154
+ * // Result: { text: string }
155
+ * ```
156
+ */
44
157
  export type Un$Typed<V extends { $type?: string }> = OmitKey<V, '$type'>
45
158
 
159
+ /**
160
+ * Unique symbol for branding unknown `$type` strings.
161
+ * @internal
162
+ */
46
163
  declare const unknown$TypeSymbol: unique symbol
164
+
165
+ /**
166
+ * Represents an unknown or unrecognized `$type` string.
167
+ *
168
+ * This branded type is used in union types to distinguish between
169
+ * known typed objects and unknown typed objects (from open unions).
170
+ * The branding prevents accidentally matching known `$type` values.
171
+ */
47
172
  export type Unknown$Type = string & { [unknown$TypeSymbol]: true }
48
173
 
49
- // In order to prevent places that expect a union of known and unknown $typed
50
- // objects (like lexicons schema open unions), from accepting an invalid version
51
- // of the known $typed objects, we need to prevent any other properties from
52
- // being present.
53
- //
54
- // For example, if we expect:
55
- // ```ts
56
- // type MyOpenUnion = { $type: 'A'; a: number } | Unknown$TypedObject
57
- // ```
58
- // we want to make that that the following is rejected:
59
- // ```ts
60
- // { $type: 'A' }
61
- // ```
62
- //
63
- // If we typed `Unknown$TypedObject` as `{ $type: string }`, `{ $type: 'A' }`
64
- // would be a valid `MyOpenUnion` as it would match the `Unknown$TypedObject`.
65
- // By using a $type property that uniquely describes unknown values, we ensure
66
- // that only valid known typed objects, or a type casted value, can be used.
174
+ /**
175
+ * Represents an object with an unknown `$type` value.
176
+ *
177
+ * This type is used in open union schemas to represent typed objects that
178
+ * don't match any of the known types. The {@link Unknown$Type} branding ensures
179
+ * that invalid instances of known types don't accidentally match this type.
180
+ *
181
+ * For example, in an open union like:
182
+ * ```typescript
183
+ * type MyOpenUnion = { $type: 'A'; a: number } | Unknown$TypedObject
184
+ * ```
185
+ *
186
+ * A value `{ $type: 'A' }` (missing the required `a` property) will NOT match
187
+ * `Unknown$TypedObject` because `'A'` is not assignable to `Unknown$Type`.
188
+ * This ensures that malformed instances of known types are properly rejected.
189
+ *
190
+ * @example
191
+ * ```typescript
192
+ * // This represents any typed object we don't recognize
193
+ * const unknownTyped: Unknown$TypedObject = {
194
+ * $type: 'some.unknown.type' as Unknown$Type,
195
+ * // ... arbitrary properties
196
+ * }
197
+ * ```
198
+ */
67
199
  export type Unknown$TypedObject = { $type: Unknown$Type }
@@ -1,7 +1,36 @@
1
1
  import { isValidRecordKey } from '@atproto/syntax'
2
2
 
3
+ /**
4
+ * The valid record key constraint types in a lexicon definition.
5
+ *
6
+ * - `'any'` - Accepts any valid record key
7
+ * - `'nsid'` - Record key must be a valid NSID
8
+ * - `'tid'` - Record key must be a valid TID
9
+ * - `'literal:...'` - Record key must be the exact specified value
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * const constraint: LexiconRecordKey = 'tid'
14
+ * const literalConstraint: LexiconRecordKey = 'literal:self'
15
+ * ```
16
+ */
3
17
  export type LexiconRecordKey = 'any' | 'nsid' | 'tid' | `literal:${string}`
4
18
 
19
+ /**
20
+ * Type guard that checks if a value is a valid lexicon record key constraint.
21
+ *
22
+ * @typeParam T - The input type
23
+ * @param key - The value to check
24
+ * @returns `true` if the value is a valid record key constraint
25
+ *
26
+ * @example
27
+ * ```typescript
28
+ * if (isLexiconRecordKey(value)) {
29
+ * // value is typed as LexiconRecordKey
30
+ * console.log('Valid constraint:', value)
31
+ * }
32
+ * ```
33
+ */
5
34
  /*@__NO_SIDE_EFFECTS__*/
6
35
  export function isLexiconRecordKey<T>(key: T): key is T & LexiconRecordKey {
7
36
  return (
@@ -15,6 +44,21 @@ export function isLexiconRecordKey<T>(key: T): key is T & LexiconRecordKey {
15
44
  )
16
45
  }
17
46
 
47
+ /**
48
+ * Validates and returns a value as a lexicon record key constraint, throwing if invalid.
49
+ *
50
+ * @param key - The value to validate
51
+ * @returns The value typed as {@link LexiconRecordKey}
52
+ * @throws {Error} If the value is not a valid record key constraint
53
+ *
54
+ * @example
55
+ * ```typescript
56
+ * const constraint = asLexiconRecordKey('tid')
57
+ * // constraint is typed as LexiconRecordKey
58
+ *
59
+ * asLexiconRecordKey('invalid') // throws Error
60
+ * ```
61
+ */
18
62
  /*@__NO_SIDE_EFFECTS__*/
19
63
  export function asLexiconRecordKey(key: unknown): LexiconRecordKey {
20
64
  if (isLexiconRecordKey(key)) return key