@atproto/lex-schema 0.0.1 → 0.0.3

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 (289) hide show
  1. package/CHANGELOG.md +68 -0
  2. package/dist/core/$type.d.ts +6 -3
  3. package/dist/core/$type.d.ts.map +1 -1
  4. package/dist/core/$type.js +1 -0
  5. package/dist/core/$type.js.map +1 -1
  6. package/dist/core/record-key.d.ts +3 -3
  7. package/dist/core/record-key.d.ts.map +1 -1
  8. package/dist/core/record-key.js +12 -6
  9. package/dist/core/record-key.js.map +1 -1
  10. package/dist/core/result.d.ts.map +1 -1
  11. package/dist/core/result.js +6 -0
  12. package/dist/core/result.js.map +1 -1
  13. package/dist/core/string-format.d.ts +30 -27
  14. package/dist/core/string-format.d.ts.map +1 -1
  15. package/dist/core/string-format.js +56 -42
  16. package/dist/core/string-format.js.map +1 -1
  17. package/dist/core/types.d.ts +9 -1
  18. package/dist/core/types.d.ts.map +1 -1
  19. package/dist/core/types.js.map +1 -1
  20. package/dist/external.d.ts +31 -28
  21. package/dist/external.d.ts.map +1 -1
  22. package/dist/external.js +33 -17
  23. package/dist/external.js.map +1 -1
  24. package/dist/schema/_parameters.d.ts +2 -2
  25. package/dist/schema/_parameters.d.ts.map +1 -1
  26. package/dist/schema/array.d.ts +5 -6
  27. package/dist/schema/array.d.ts.map +1 -1
  28. package/dist/schema/array.js +5 -6
  29. package/dist/schema/array.js.map +1 -1
  30. package/dist/schema/blob.d.ts +2 -3
  31. package/dist/schema/blob.d.ts.map +1 -1
  32. package/dist/schema/blob.js +1 -2
  33. package/dist/schema/blob.js.map +1 -1
  34. package/dist/schema/boolean.d.ts +4 -5
  35. package/dist/schema/boolean.d.ts.map +1 -1
  36. package/dist/schema/boolean.js +2 -3
  37. package/dist/schema/boolean.js.map +1 -1
  38. package/dist/schema/bytes.d.ts +3 -4
  39. package/dist/schema/bytes.d.ts.map +1 -1
  40. package/dist/schema/bytes.js +2 -3
  41. package/dist/schema/bytes.js.map +1 -1
  42. package/dist/schema/cid.d.ts +13 -6
  43. package/dist/schema/cid.d.ts.map +1 -1
  44. package/dist/schema/cid.js +2 -4
  45. package/dist/schema/cid.js.map +1 -1
  46. package/dist/schema/custom.d.ts +3 -4
  47. package/dist/schema/custom.d.ts.map +1 -1
  48. package/dist/schema/custom.js +4 -3
  49. package/dist/schema/custom.js.map +1 -1
  50. package/dist/schema/dict.d.ts +3 -3
  51. package/dist/schema/dict.d.ts.map +1 -1
  52. package/dist/schema/dict.js +1 -1
  53. package/dist/schema/dict.js.map +1 -1
  54. package/dist/schema/discriminated-union.d.ts +15 -24
  55. package/dist/schema/discriminated-union.d.ts.map +1 -1
  56. package/dist/schema/discriminated-union.js +40 -64
  57. package/dist/schema/discriminated-union.js.map +1 -1
  58. package/dist/schema/enum.d.ts +8 -4
  59. package/dist/schema/enum.d.ts.map +1 -1
  60. package/dist/schema/enum.js +5 -3
  61. package/dist/schema/enum.js.map +1 -1
  62. package/dist/schema/integer.d.ts +3 -4
  63. package/dist/schema/integer.d.ts.map +1 -1
  64. package/dist/schema/integer.js +3 -4
  65. package/dist/schema/integer.js.map +1 -1
  66. package/dist/schema/intersection.d.ts +22 -14
  67. package/dist/schema/intersection.d.ts.map +1 -1
  68. package/dist/schema/intersection.js +12 -22
  69. package/dist/schema/intersection.js.map +1 -1
  70. package/dist/schema/literal.d.ts +8 -4
  71. package/dist/schema/literal.d.ts.map +1 -1
  72. package/dist/schema/literal.js +5 -3
  73. package/dist/schema/literal.js.map +1 -1
  74. package/dist/schema/never.d.ts +2 -2
  75. package/dist/schema/never.d.ts.map +1 -1
  76. package/dist/schema/never.js +1 -1
  77. package/dist/schema/never.js.map +1 -1
  78. package/dist/schema/null.d.ts +2 -3
  79. package/dist/schema/null.d.ts.map +1 -1
  80. package/dist/schema/null.js +1 -2
  81. package/dist/schema/null.js.map +1 -1
  82. package/dist/schema/nullable.d.ts +7 -0
  83. package/dist/schema/nullable.d.ts.map +1 -0
  84. package/dist/schema/nullable.js +19 -0
  85. package/dist/schema/nullable.js.map +1 -0
  86. package/dist/schema/object.d.ts +10 -44
  87. package/dist/schema/object.d.ts.map +1 -1
  88. package/dist/schema/object.js +13 -56
  89. package/dist/schema/object.js.map +1 -1
  90. package/dist/schema/optional.d.ts +7 -0
  91. package/dist/schema/optional.d.ts.map +1 -0
  92. package/dist/schema/optional.js +25 -0
  93. package/dist/schema/optional.js.map +1 -0
  94. package/dist/schema/params.d.ts +14 -19
  95. package/dist/schema/params.d.ts.map +1 -1
  96. package/dist/schema/params.js +10 -24
  97. package/dist/schema/params.js.map +1 -1
  98. package/dist/schema/payload.d.ts +4 -4
  99. package/dist/schema/payload.d.ts.map +1 -1
  100. package/dist/schema/payload.js.map +1 -1
  101. package/dist/schema/permission-set.d.ts +6 -6
  102. package/dist/schema/permission-set.d.ts.map +1 -1
  103. package/dist/schema/permission-set.js +1 -2
  104. package/dist/schema/permission-set.js.map +1 -1
  105. package/dist/schema/permission.d.ts +0 -1
  106. package/dist/schema/permission.d.ts.map +1 -1
  107. package/dist/schema/permission.js +0 -1
  108. package/dist/schema/permission.js.map +1 -1
  109. package/dist/schema/procedure.d.ts +8 -9
  110. package/dist/schema/procedure.d.ts.map +1 -1
  111. package/dist/schema/procedure.js +0 -1
  112. package/dist/schema/procedure.js.map +1 -1
  113. package/dist/schema/query.d.ts +7 -8
  114. package/dist/schema/query.d.ts.map +1 -1
  115. package/dist/schema/query.js +0 -1
  116. package/dist/schema/query.js.map +1 -1
  117. package/dist/schema/record.d.ts +34 -28
  118. package/dist/schema/record.d.ts.map +1 -1
  119. package/dist/schema/record.js +1 -2
  120. package/dist/schema/record.js.map +1 -1
  121. package/dist/schema/ref.d.ts +2 -3
  122. package/dist/schema/ref.d.ts.map +1 -1
  123. package/dist/schema/ref.js +1 -2
  124. package/dist/schema/ref.js.map +1 -1
  125. package/dist/schema/refine.d.ts +18 -0
  126. package/dist/schema/refine.d.ts.map +1 -0
  127. package/dist/schema/refine.js +33 -0
  128. package/dist/schema/refine.js.map +1 -0
  129. package/dist/schema/regexp.d.ts +7 -0
  130. package/dist/schema/regexp.d.ts.map +1 -0
  131. package/dist/schema/regexp.js +22 -0
  132. package/dist/schema/regexp.js.map +1 -0
  133. package/dist/schema/string.d.ts +4 -8
  134. package/dist/schema/string.d.ts.map +1 -1
  135. package/dist/schema/string.js +6 -3
  136. package/dist/schema/string.js.map +1 -1
  137. package/dist/schema/subscription.d.ts +7 -6
  138. package/dist/schema/subscription.d.ts.map +1 -1
  139. package/dist/schema/subscription.js.map +1 -1
  140. package/dist/schema/token.d.ts +2 -3
  141. package/dist/schema/token.d.ts.map +1 -1
  142. package/dist/schema/token.js +1 -2
  143. package/dist/schema/token.js.map +1 -1
  144. package/dist/schema/typed-object.d.ts +29 -27
  145. package/dist/schema/typed-object.d.ts.map +1 -1
  146. package/dist/schema/typed-object.js +1 -2
  147. package/dist/schema/typed-object.js.map +1 -1
  148. package/dist/schema/typed-ref.d.ts +2 -2
  149. package/dist/schema/typed-ref.d.ts.map +1 -1
  150. package/dist/schema/typed-ref.js +1 -1
  151. package/dist/schema/typed-ref.js.map +1 -1
  152. package/dist/schema/typed-union.d.ts +3 -4
  153. package/dist/schema/typed-union.d.ts.map +1 -1
  154. package/dist/schema/typed-union.js +3 -10
  155. package/dist/schema/typed-union.js.map +1 -1
  156. package/dist/schema/union.d.ts +2 -2
  157. package/dist/schema/union.d.ts.map +1 -1
  158. package/dist/schema/union.js +1 -1
  159. package/dist/schema/union.js.map +1 -1
  160. package/dist/schema/unknown-object.d.ts +2 -3
  161. package/dist/schema/unknown-object.d.ts.map +1 -1
  162. package/dist/schema/unknown-object.js +1 -2
  163. package/dist/schema/unknown-object.js.map +1 -1
  164. package/dist/schema/unknown.d.ts +2 -2
  165. package/dist/schema/unknown.d.ts.map +1 -1
  166. package/dist/schema/unknown.js +1 -1
  167. package/dist/schema/unknown.js.map +1 -1
  168. package/dist/schema.d.ts +4 -0
  169. package/dist/schema.d.ts.map +1 -1
  170. package/dist/schema.js +6 -1
  171. package/dist/schema.js.map +1 -1
  172. package/dist/util/array-agg.d.ts.map +1 -1
  173. package/dist/util/array-agg.js +1 -0
  174. package/dist/util/array-agg.js.map +1 -1
  175. package/dist/util/lazy-property.d.ts +2 -0
  176. package/dist/util/lazy-property.d.ts.map +1 -0
  177. package/dist/util/lazy-property.js +14 -0
  178. package/dist/util/lazy-property.js.map +1 -0
  179. package/dist/validation/schema.d.ts +24 -0
  180. package/dist/validation/schema.d.ts.map +1 -0
  181. package/dist/validation/schema.js +57 -0
  182. package/dist/validation/schema.js.map +1 -0
  183. package/dist/validation/validation-error.d.ts +3 -3
  184. package/dist/validation/validation-error.d.ts.map +1 -1
  185. package/dist/validation/validation-error.js +32 -4
  186. package/dist/validation/validation-error.js.map +1 -1
  187. package/dist/validation/validation-issue.d.ts +32 -24
  188. package/dist/validation/validation-issue.d.ts.map +1 -1
  189. package/dist/validation/validation-issue.js +136 -92
  190. package/dist/validation/validation-issue.js.map +1 -1
  191. package/dist/validation/validator.d.ts +20 -50
  192. package/dist/validation/validator.d.ts.map +1 -1
  193. package/dist/validation/validator.js +40 -134
  194. package/dist/validation/validator.js.map +1 -1
  195. package/dist/validation.d.ts +1 -0
  196. package/dist/validation.d.ts.map +1 -1
  197. package/dist/validation.js +1 -0
  198. package/dist/validation.js.map +1 -1
  199. package/package.json +8 -4
  200. package/src/core/$type.ts +7 -4
  201. package/src/core/record-key.ts +12 -5
  202. package/src/core/result.ts +6 -0
  203. package/src/core/string-format.ts +97 -61
  204. package/src/core/types.ts +12 -6
  205. package/src/external.ts +92 -70
  206. package/src/schema/_parameters.test.ts +416 -0
  207. package/src/schema/array.test.ts +237 -0
  208. package/src/schema/array.ts +17 -11
  209. package/src/schema/blob.test.ts +506 -0
  210. package/src/schema/blob.ts +3 -5
  211. package/src/schema/boolean.test.ts +116 -0
  212. package/src/schema/boolean.ts +5 -7
  213. package/src/schema/bytes.test.ts +226 -0
  214. package/src/schema/bytes.ts +4 -6
  215. package/src/schema/cid.test.ts +155 -0
  216. package/src/schema/cid.ts +14 -8
  217. package/src/schema/custom.test.ts +413 -0
  218. package/src/schema/custom.ts +10 -8
  219. package/src/schema/dict.test.ts +198 -0
  220. package/src/schema/dict.ts +6 -8
  221. package/src/schema/discriminated-union.test.ts +675 -0
  222. package/src/schema/discriminated-union.ts +68 -95
  223. package/src/schema/enum.test.ts +396 -0
  224. package/src/schema/enum.ts +12 -5
  225. package/src/schema/integer.test.ts +312 -0
  226. package/src/schema/integer.ts +5 -7
  227. package/src/schema/intersection.test.ts +32 -0
  228. package/src/schema/intersection.ts +37 -40
  229. package/src/schema/literal.test.ts +531 -0
  230. package/src/schema/literal.ts +12 -5
  231. package/src/schema/never.test.ts +174 -0
  232. package/src/schema/never.ts +3 -10
  233. package/src/schema/null.test.ts +79 -0
  234. package/src/schema/null.ts +3 -5
  235. package/src/schema/nullable.test.ts +480 -0
  236. package/src/schema/nullable.ts +23 -0
  237. package/src/schema/object.test.ts +47 -115
  238. package/src/schema/object.ts +23 -134
  239. package/src/schema/optional.test.ts +485 -0
  240. package/src/schema/optional.ts +31 -0
  241. package/src/schema/params.test.ts +582 -0
  242. package/src/schema/params.ts +37 -55
  243. package/src/schema/payload.test.ts +345 -0
  244. package/src/schema/payload.ts +5 -5
  245. package/src/schema/permission-set.test.ts +679 -0
  246. package/src/schema/permission-set.ts +6 -8
  247. package/src/schema/permission.test.ts +536 -0
  248. package/src/schema/permission.ts +0 -2
  249. package/src/schema/procedure.test.ts +443 -0
  250. package/src/schema/procedure.ts +11 -13
  251. package/src/schema/query.test.ts +408 -0
  252. package/src/schema/query.ts +9 -11
  253. package/src/schema/record.test.ts +694 -0
  254. package/src/schema/record.ts +38 -36
  255. package/src/schema/ref.test.ts +365 -0
  256. package/src/schema/ref.ts +8 -5
  257. package/src/schema/refine.test.ts +578 -0
  258. package/src/schema/refine.ts +85 -0
  259. package/src/schema/regexp.test.ts +580 -0
  260. package/src/schema/regexp.ts +22 -0
  261. package/src/schema/string.test.ts +612 -0
  262. package/src/schema/string.ts +11 -17
  263. package/src/schema/subscription.test.ts +689 -0
  264. package/src/schema/subscription.ts +13 -8
  265. package/src/schema/token.test.ts +428 -0
  266. package/src/schema/token.ts +3 -5
  267. package/src/schema/typed-object.test.ts +612 -0
  268. package/src/schema/typed-object.ts +23 -20
  269. package/src/schema/typed-ref.test.ts +823 -0
  270. package/src/schema/typed-ref.ts +10 -5
  271. package/src/schema/typed-union.test.ts +378 -0
  272. package/src/schema/typed-union.ts +6 -15
  273. package/src/schema/union.test.ts +200 -0
  274. package/src/schema/union.ts +5 -4
  275. package/src/schema/unknown-object.test.ts +592 -0
  276. package/src/schema/unknown-object.ts +3 -5
  277. package/src/schema/unknown.test.ts +312 -0
  278. package/src/schema/unknown.ts +3 -3
  279. package/src/schema.ts +7 -1
  280. package/src/util/array-agg.ts +1 -0
  281. package/src/util/lazy-property.ts +14 -0
  282. package/src/validation/schema.ts +92 -0
  283. package/src/validation/validation-error.ts +60 -9
  284. package/src/validation/validation-issue.ts +141 -144
  285. package/src/validation/validator.ts +67 -206
  286. package/src/validation.ts +1 -0
  287. package/tsconfig.build.json +12 -0
  288. package/tsconfig.json +7 -0
  289. package/tsconfig.tests.json +9 -0
@@ -1,83 +1,143 @@
1
- import { CID, isPlainObject } from '@atproto/lex-data'
2
- import { arrayAgg } from '../util/array-agg.js'
1
+ import { asCid, isPlainObject } from '@atproto/lex-data'
3
2
  import { PropertyKey } from './property-key.js'
4
3
 
5
- export interface Issue<I = unknown> {
6
- readonly input: I
7
- readonly code: string
8
- readonly message?: string
9
- readonly path: readonly PropertyKey[]
10
- }
4
+ export abstract class Issue {
5
+ constructor(
6
+ readonly code: string,
7
+ readonly path: readonly PropertyKey[],
8
+ readonly input: unknown,
9
+ ) {}
11
10
 
12
- export interface IssueCustom extends Issue {
13
- readonly code: 'custom'
14
- readonly message: string
11
+ abstract toString(): string
15
12
  }
16
13
 
17
- export interface IssueInvalidFormat extends Issue {
18
- readonly code: 'invalid_format'
19
- readonly format: string
20
- }
14
+ export class IssueCustom extends Issue {
15
+ constructor(
16
+ readonly path: readonly PropertyKey[],
17
+ readonly input: unknown,
18
+ readonly message: string,
19
+ ) {
20
+ super('custom', path, input)
21
+ }
21
22
 
22
- export interface IssueInvalidType extends Issue {
23
- readonly code: 'invalid_type'
24
- readonly expected: readonly string[]
23
+ toString() {
24
+ return `${this.message}${stringifyPath(this.path)}`
25
+ }
25
26
  }
26
27
 
27
- export interface IssueInvalidValue extends Issue {
28
- readonly code: 'invalid_value'
29
- readonly values: readonly unknown[]
28
+ export class IssueInvalidFormat extends Issue {
29
+ constructor(
30
+ path: readonly PropertyKey[],
31
+ input: unknown,
32
+ readonly format: string,
33
+ readonly message?: string,
34
+ ) {
35
+ super('invalid_format', path, input)
36
+ }
37
+
38
+ toString() {
39
+ return `Invalid ${this.formatDescription} format${this.message ? ` (${this.message})` : ''}${stringifyPath(this.path)} (got ${stringifyValue(this.input)})`
40
+ }
41
+
42
+ get formatDescription(): string {
43
+ switch (this.format) {
44
+ case 'at-identifier':
45
+ return `AT identifier`
46
+ case 'did':
47
+ return `DID`
48
+ case 'nsid':
49
+ return `NSID`
50
+ case 'cid':
51
+ return `CID string`
52
+ case 'tid':
53
+ return `TID string`
54
+ case 'record-key':
55
+ return `record key`
56
+ default:
57
+ return this.format
58
+ }
59
+ }
30
60
  }
31
61
 
32
- export interface IssueRequiredKey extends Issue {
33
- readonly code: 'required_key'
34
- readonly key: PropertyKey
62
+ export class IssueInvalidType extends Issue {
63
+ constructor(
64
+ path: readonly PropertyKey[],
65
+ input: unknown,
66
+ readonly expected: readonly string[],
67
+ ) {
68
+ super('invalid_type', path, input)
69
+ }
70
+
71
+ toString() {
72
+ return `Expected ${oneOf(this.expected.map(stringifyExpectedType))} value type${stringifyPath(this.path)} (got ${stringifyType(this.input)})`
73
+ }
35
74
  }
36
75
 
37
- export interface IssueTooBig extends Issue {
38
- readonly code: 'too_big'
39
- readonly maximum: number
40
- readonly type: 'array' | 'string' | 'integer' | 'grapheme' | 'bytes' | 'blob'
41
- readonly actual: number
76
+ export class IssueInvalidValue extends Issue {
77
+ constructor(
78
+ path: readonly PropertyKey[],
79
+ input: unknown,
80
+ readonly values: readonly unknown[],
81
+ ) {
82
+ super('invalid_value', path, input)
83
+ }
84
+
85
+ toString() {
86
+ return `Expected ${oneOf(this.values.map(stringifyValue))}${stringifyPath(this.path)} (got ${stringifyValue(this.input)})`
87
+ }
42
88
  }
43
89
 
44
- export interface IssueTooSmall extends Issue {
45
- readonly code: 'too_small'
46
- readonly minimum: number
47
- readonly type: 'array' | 'string' | 'integer' | 'grapheme' | 'bytes'
48
- readonly actual: number
90
+ export class IssueRequiredKey extends Issue {
91
+ constructor(
92
+ path: readonly PropertyKey[],
93
+ input: unknown,
94
+ readonly key: PropertyKey,
95
+ ) {
96
+ super('required_key', path, input)
97
+ }
98
+
99
+ toString() {
100
+ return `Missing required key "${String(this.key)}"${stringifyPath(this.path)}`
101
+ }
49
102
  }
50
103
 
51
- export type ValidationIssue =
52
- | IssueCustom
53
- | IssueInvalidFormat
54
- | IssueInvalidType
55
- | IssueInvalidValue
56
- | IssueRequiredKey
57
- | IssueTooBig
58
- | IssueTooSmall
104
+ export type MeasurableType =
105
+ | 'array'
106
+ | 'string'
107
+ | 'integer'
108
+ | 'grapheme'
109
+ | 'bytes'
110
+ | 'blob'
111
+
112
+ export class IssueTooBig extends Issue {
113
+ constructor(
114
+ path: readonly PropertyKey[],
115
+ input: unknown,
116
+ readonly maximum: number,
117
+ readonly type: MeasurableType,
118
+ readonly actual: number,
119
+ ) {
120
+ super('too_big', path, input)
121
+ }
59
122
 
60
- export function stringifyIssue(issue: ValidationIssue): string {
61
- const pathStr = issue.path.length ? ` at ${buildJsonPath(issue.path)}` : ''
123
+ toString() {
124
+ return `${this.type} too big (maximum ${this.maximum})${stringifyPath(this.path)} (got ${this.actual})`
125
+ }
126
+ }
62
127
 
63
- switch (issue.code) {
64
- case 'invalid_format':
65
- return `Invalid ${stringifyStringFormat(issue.format)} format${issue.message ? ` (${issue.message})` : ''}${pathStr} (got ${stringifyValue(issue.input)})`
66
- case 'invalid_type':
67
- return `Expected ${oneOf(issue.expected.map(stringifyExpectedType))} value type${pathStr} (got ${stringifyType(issue.input)})`
68
- case 'invalid_value':
69
- return `Expected ${oneOf(issue.values.map(stringifyValue))}${pathStr} (got ${stringifyValue(issue.input)})`
70
- case 'required_key':
71
- return `Missing required key "${String(issue.key)}"${pathStr}`
72
- case 'too_big':
73
- return `${issue.type} too big (maximum ${issue.maximum})${pathStr} (got ${issue.actual})`
74
- case 'too_small':
75
- return `${issue.type} too small (minimum ${issue.minimum})${pathStr} (got ${issue.actual})`
76
- case 'custom':
77
- return `${issue.message}${pathStr}`
78
- default:
79
- // @ts-expect-error fool-proofing
80
- return `${issue.code} validation error${pathStr}`
128
+ export class IssueTooSmall extends Issue {
129
+ constructor(
130
+ path: readonly PropertyKey[],
131
+ input: unknown,
132
+ readonly minimum: number,
133
+ readonly type: MeasurableType,
134
+ readonly actual: number,
135
+ ) {
136
+ super('too_small', path, input)
137
+ }
138
+
139
+ toString() {
140
+ return `${this.type} too small (minimum ${this.minimum})${stringifyPath(this.path)} (got ${this.actual})`
81
141
  }
82
142
  }
83
143
 
@@ -85,22 +145,25 @@ function stringifyExpectedType(expected: string): string {
85
145
  if (expected === '$typed') {
86
146
  return 'an object or record which includes a "$type" property'
87
147
  }
88
-
89
148
  return expected
90
149
  }
91
150
 
151
+ function stringifyPath(path: readonly PropertyKey[]) {
152
+ return ` at ${buildJsonPath(path)}`
153
+ }
154
+
92
155
  function buildJsonPath(path: readonly PropertyKey[]): string {
93
- let jsonPath = '$'
94
- for (const segment of path) {
95
- if (typeof segment === 'number') {
96
- jsonPath += `[${segment}]`
97
- } else if (/^[a-zA-Z_$][a-zA-Z0-9_]*$/.test(segment as string)) {
98
- jsonPath += `.${segment}`
99
- } else {
100
- jsonPath += `[${JSON.stringify(segment)}]`
101
- }
156
+ return `$${path.map(toJsonPathSegment).join('')}`
157
+ }
158
+
159
+ function toJsonPathSegment(segment: PropertyKey): string {
160
+ if (typeof segment === 'number') {
161
+ return `[${segment}]`
162
+ } else if (/^[a-zA-Z_$][a-zA-Z0-9_]*$/.test(segment as string)) {
163
+ return `.${segment}`
164
+ } else {
165
+ return `[${JSON.stringify(segment)}]`
102
166
  }
103
- return jsonPath
104
167
  }
105
168
 
106
169
  function oneOf(arr: readonly string[]): string {
@@ -109,37 +172,12 @@ function oneOf(arr: readonly string[]): string {
109
172
  return `one of ${arr.slice(0, -1).join(', ')} or ${arr.at(-1)}`
110
173
  }
111
174
 
112
- function stringifyStringFormat(format: string): string {
113
- switch (format) {
114
- case 'datetime':
115
- return 'datetime'
116
- case 'language':
117
- return 'language'
118
- case 'at-identifier':
119
- return `AT identifier`
120
- case 'did':
121
- return `DID`
122
- case 'handle':
123
- return `handle`
124
- case 'nsid':
125
- return `NSID`
126
- case 'cid':
127
- return `CID string`
128
- case 'tid':
129
- return `TID string`
130
- case 'record-key':
131
- return `record key`
132
- default:
133
- return format
134
- }
135
- }
136
-
137
- export function stringifyType(value: unknown): string {
175
+ function stringifyType(value: unknown): string {
138
176
  switch (typeof value) {
139
177
  case 'object':
140
178
  if (value === null) return 'null'
141
179
  if (Array.isArray(value)) return 'array'
142
- if (CID.asCID(value)) return 'cid'
180
+ if (asCid(value)) return 'cid'
143
181
  if (value instanceof Date) return 'date'
144
182
  if (value instanceof RegExp) return 'regexp'
145
183
  if (value instanceof Map) return 'map'
@@ -154,7 +192,7 @@ export function stringifyType(value: unknown): string {
154
192
  }
155
193
  }
156
194
 
157
- export function stringifyValue(value: unknown): string {
195
+ function stringifyValue(value: unknown): string {
158
196
  switch (typeof value) {
159
197
  case 'bigint':
160
198
  return `${value}n`
@@ -175,10 +213,12 @@ export function stringifyValue(value: unknown): string {
175
213
  }
176
214
  }
177
215
 
216
+ /*@__NO_SIDE_EFFECTS__*/
178
217
  function stringifyObjectEntry([key, _value]: [PropertyKey, unknown]): string {
179
218
  return `${JSON.stringify(key)}: ...`
180
219
  }
181
220
 
221
+ /*@__NO_SIDE_EFFECTS__*/
182
222
  function stringifyArray<T>(
183
223
  arr: readonly T[],
184
224
  fn: (item: T) => string,
@@ -186,46 +226,3 @@ function stringifyArray<T>(
186
226
  ): string {
187
227
  return arr.slice(0, n).map(fn).join(', ') + (arr.length > n ? ', ...' : '')
188
228
  }
189
-
190
- export function aggregateIssues(issues: ValidationIssue[]): ValidationIssue[] {
191
- // Quick path for common cases
192
- if (issues.length <= 1) return issues
193
- if (issues.length === 2 && issues[0].code !== issues[1].code) return issues
194
-
195
- return [
196
- // Aggregate invalid_type with identical paths
197
- ...arrayAgg(
198
- issues.filter((issue) => issue.code === 'invalid_type'),
199
- (a, b) => comparePropertyPaths(a.path, b.path),
200
- (issues) => ({
201
- ...issues[0],
202
- expected: Array.from(new Set(issues.flatMap((iss) => iss.expected))),
203
- }),
204
- ),
205
- // Aggregate invalid_value with identical paths
206
- ...arrayAgg(
207
- issues.filter((issue) => issue.code === 'invalid_value'),
208
- (a, b) => comparePropertyPaths(a.path, b.path),
209
- (issues) => ({
210
- ...issues[0],
211
- values: Array.from(new Set(issues.flatMap((iss) => iss.values))),
212
- }),
213
- ),
214
- // Pass through other issues
215
- ...issues.filter(
216
- (issue) =>
217
- issue.code !== 'invalid_type' && issue.code !== 'invalid_value',
218
- ),
219
- ]
220
- }
221
-
222
- function comparePropertyPaths(
223
- a: readonly PropertyKey[],
224
- b: readonly PropertyKey[],
225
- ) {
226
- if (a.length !== b.length) return false
227
- for (let i = 0; i < a.length; i++) {
228
- if (a[i] !== b[i]) return false
229
- }
230
- return true
231
- }