polen 0.11.0-next.17 → 0.11.0-next.19

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 (307) hide show
  1. package/build/api/builder/ssg/generate.d.ts.map +1 -1
  2. package/build/api/builder/ssg/generate.js +5 -5
  3. package/build/api/builder/ssg/generate.js.map +1 -1
  4. package/build/api/builder/ssg/page-generator.worker.js +13 -3
  5. package/build/api/builder/ssg/page-generator.worker.js.map +1 -1
  6. package/build/api/config/input.d.ts +88 -3
  7. package/build/api/config/input.d.ts.map +1 -1
  8. package/build/api/config/normalized.d.ts +92 -7
  9. package/build/api/config/normalized.d.ts.map +1 -1
  10. package/build/api/config/normalized.js +11 -3
  11. package/build/api/config/normalized.js.map +1 -1
  12. package/build/api/config-template/template.js +2 -2
  13. package/build/api/config-template/template.js.map +1 -1
  14. package/build/api/content/sidebar.d.ts.map +1 -1
  15. package/build/api/content/sidebar.js +2 -1
  16. package/build/api/content/sidebar.js.map +1 -1
  17. package/build/api/errors.d.ts +278 -0
  18. package/build/api/errors.d.ts.map +1 -0
  19. package/build/api/errors.js +153 -0
  20. package/build/api/errors.js.map +1 -0
  21. package/build/api/examples/config.d.ts +366 -3
  22. package/build/api/examples/config.d.ts.map +1 -1
  23. package/build/api/examples/config.js +25 -3
  24. package/build/api/examples/config.js.map +1 -1
  25. package/build/api/examples/diagnostic/diagnostic.d.ts +1 -1
  26. package/build/api/examples/diagnostic/validation-error.d.ts +3 -2
  27. package/build/api/examples/diagnostic/validation-error.d.ts.map +1 -1
  28. package/build/api/examples/diagnostic/validation-error.js +9 -3
  29. package/build/api/examples/diagnostic/validation-error.js.map +1 -1
  30. package/build/api/examples/diagnostic/validator.d.ts.map +1 -1
  31. package/build/api/examples/diagnostic/validator.js +115 -68
  32. package/build/api/examples/diagnostic/validator.js.map +1 -1
  33. package/build/api/examples/filter.d.ts.map +1 -1
  34. package/build/api/examples/filter.js +9 -6
  35. package/build/api/examples/filter.js.map +1 -1
  36. package/build/api/examples/scanner.d.ts.map +1 -1
  37. package/build/api/examples/scanner.js +89 -103
  38. package/build/api/examples/scanner.js.map +1 -1
  39. package/build/api/examples/type-usage-indexer.d.ts.map +1 -1
  40. package/build/api/examples/type-usage-indexer.js +17 -30
  41. package/build/api/examples/type-usage-indexer.js.map +1 -1
  42. package/build/api/iso/schema/routing.d.ts.map +1 -1
  43. package/build/api/iso/schema/routing.js +8 -8
  44. package/build/api/iso/schema/routing.js.map +1 -1
  45. package/build/api/iso/schema/validation.d.ts.map +1 -1
  46. package/build/api/iso/schema/validation.js +3 -2
  47. package/build/api/iso/schema/validation.js.map +1 -1
  48. package/build/api/schema/input-source/$$.d.ts +1 -0
  49. package/build/api/schema/input-source/$$.d.ts.map +1 -1
  50. package/build/api/schema/input-source/$$.js +1 -0
  51. package/build/api/schema/input-source/$$.js.map +1 -1
  52. package/build/api/schema/input-source/errors.d.ts +36 -0
  53. package/build/api/schema/input-source/errors.d.ts.map +1 -0
  54. package/build/api/schema/input-source/errors.js +17 -0
  55. package/build/api/schema/input-source/errors.js.map +1 -0
  56. package/build/api/schema/input-source/input-source.d.ts +1 -7
  57. package/build/api/schema/input-source/input-source.d.ts.map +1 -1
  58. package/build/api/schema/input-source/input-source.js +0 -6
  59. package/build/api/schema/input-source/input-source.js.map +1 -1
  60. package/build/api/schema/input-sources/directory.d.ts.map +1 -1
  61. package/build/api/schema/input-sources/directory.js +19 -6
  62. package/build/api/schema/input-sources/directory.js.map +1 -1
  63. package/build/api/schema/input-sources/file.d.ts.map +1 -1
  64. package/build/api/schema/input-sources/file.js +15 -4
  65. package/build/api/schema/input-sources/file.js.map +1 -1
  66. package/build/api/schema/input-sources/introspection-file.d.ts.map +1 -1
  67. package/build/api/schema/input-sources/introspection-file.js +28 -6
  68. package/build/api/schema/input-sources/introspection-file.js.map +1 -1
  69. package/build/api/schema/input-sources/introspection.d.ts.map +1 -1
  70. package/build/api/schema/input-sources/introspection.js +35 -7
  71. package/build/api/schema/input-sources/introspection.js.map +1 -1
  72. package/build/api/schema/input-sources/memory.d.ts.map +1 -1
  73. package/build/api/schema/input-sources/memory.js +15 -3
  74. package/build/api/schema/input-sources/memory.js.map +1 -1
  75. package/build/api/schema/input-sources/versioned-directory.d.ts.map +1 -1
  76. package/build/api/schema/input-sources/versioned-directory.js +23 -7
  77. package/build/api/schema/input-sources/versioned-directory.js.map +1 -1
  78. package/build/api/schema/load.d.ts +1 -1
  79. package/build/api/schema/load.d.ts.map +1 -1
  80. package/build/api/schema/load.js.map +1 -1
  81. package/build/cli/commands/hero-image.d.ts +1 -2
  82. package/build/cli/commands/hero-image.d.ts.map +1 -1
  83. package/build/cli/index.d.ts +1 -1
  84. package/build/lib/catalog/catalog.d.ts +43 -3
  85. package/build/lib/catalog/catalog.d.ts.map +1 -1
  86. package/build/lib/catalog/catalog.js +67 -5
  87. package/build/lib/catalog/catalog.js.map +1 -1
  88. package/build/lib/catalog/versioned.d.ts +11 -1
  89. package/build/lib/catalog/versioned.d.ts.map +1 -1
  90. package/build/lib/catalog/versioned.js +23 -5
  91. package/build/lib/catalog/versioned.js.map +1 -1
  92. package/build/lib/document/document.d.ts +55 -5
  93. package/build/lib/document/document.d.ts.map +1 -1
  94. package/build/lib/document/document.js +96 -2
  95. package/build/lib/document/document.js.map +1 -1
  96. package/build/lib/document/versioned.d.ts +2 -2
  97. package/build/lib/document/versioned.d.ts.map +1 -1
  98. package/build/lib/document/versioned.js +7 -7
  99. package/build/lib/document/versioned.js.map +1 -1
  100. package/build/lib/lifecycles/lifecycles.d.ts +5 -4
  101. package/build/lib/lifecycles/lifecycles.d.ts.map +1 -1
  102. package/build/lib/lifecycles/lifecycles.js +14 -12
  103. package/build/lib/lifecycles/lifecycles.js.map +1 -1
  104. package/build/lib/version-coverage/$$.d.ts +2 -0
  105. package/build/lib/version-coverage/$$.d.ts.map +1 -0
  106. package/build/lib/version-coverage/$$.js +2 -0
  107. package/build/lib/version-coverage/$$.js.map +1 -0
  108. package/build/lib/version-coverage/$.d.ts.map +1 -0
  109. package/build/lib/version-coverage/$.js.map +1 -0
  110. package/build/lib/{version-selection/version-selection.d.ts → version-coverage/version-coverage.d.ts} +1 -1
  111. package/build/lib/version-coverage/version-coverage.d.ts.map +1 -0
  112. package/build/lib/{version-selection/version-selection.js → version-coverage/version-coverage.js} +2 -2
  113. package/build/lib/version-coverage/version-coverage.js.map +1 -0
  114. package/build/template/components/GraphQLDocument.d.ts +1 -1
  115. package/build/template/components/GraphQLDocument.d.ts.map +1 -1
  116. package/build/template/components/GraphQLDocument.js +10 -39
  117. package/build/template/components/GraphQLDocument.js.map +1 -1
  118. package/build/template/components/GraphQLInteractive/lib/parser.d.ts +28 -0
  119. package/build/template/components/GraphQLInteractive/lib/parser.d.ts.map +1 -1
  120. package/build/template/components/GraphQLInteractive/lib/parser.js +60 -27
  121. package/build/template/components/GraphQLInteractive/lib/parser.js.map +1 -1
  122. package/build/template/components/ReferenceVersionPicker.d.ts +9 -0
  123. package/build/template/components/ReferenceVersionPicker.d.ts.map +1 -0
  124. package/build/template/components/ReferenceVersionPicker.js +79 -0
  125. package/build/template/components/ReferenceVersionPicker.js.map +1 -0
  126. package/build/template/components/VersionCoveragePicker.d.ts +1 -1
  127. package/build/template/components/VersionCoveragePicker.d.ts.map +1 -1
  128. package/build/template/components/VersionCoveragePicker.js +4 -6
  129. package/build/template/components/VersionCoveragePicker.js.map +1 -1
  130. package/build/template/components/VersionPicker.d.ts +8 -3
  131. package/build/template/components/VersionPicker.d.ts.map +1 -1
  132. package/build/template/components/VersionPicker.js +12 -77
  133. package/build/template/components/VersionPicker.js.map +1 -1
  134. package/build/template/components/home/QuickStart.d.ts.map +1 -1
  135. package/build/template/components/home/QuickStart.js +8 -4
  136. package/build/template/components/home/QuickStart.js.map +1 -1
  137. package/build/template/hooks/use-highlighted.d.ts.map +1 -1
  138. package/build/template/hooks/use-highlighted.js +19 -13
  139. package/build/template/hooks/use-highlighted.js.map +1 -1
  140. package/build/template/lib/fetch-text.d.ts +18 -0
  141. package/build/template/lib/fetch-text.d.ts.map +1 -1
  142. package/build/template/lib/fetch-text.js +32 -4
  143. package/build/template/lib/fetch-text.js.map +1 -1
  144. package/build/template/routes/changelog/ChangelogBody.d.ts +6 -0
  145. package/build/template/routes/changelog/ChangelogBody.d.ts.map +1 -0
  146. package/build/template/{components/Changelog/Changelog.js → routes/changelog/ChangelogBody.js} +8 -58
  147. package/build/template/routes/changelog/ChangelogBody.js.map +1 -0
  148. package/build/template/routes/changelog/ChangelogSidebar.d.ts +7 -0
  149. package/build/template/routes/changelog/ChangelogSidebar.d.ts.map +1 -0
  150. package/build/template/routes/changelog/ChangelogSidebar.js +46 -0
  151. package/build/template/routes/changelog/ChangelogSidebar.js.map +1 -0
  152. package/build/template/routes/changelog/ChangelogSidebarItem.d.ts +11 -0
  153. package/build/template/routes/changelog/ChangelogSidebarItem.d.ts.map +1 -0
  154. package/build/template/routes/changelog/ChangelogSidebarItem.js +35 -0
  155. package/build/template/routes/changelog/ChangelogSidebarItem.js.map +1 -0
  156. package/build/template/routes/changelog/_.d.ts +3264 -0
  157. package/build/template/routes/changelog/_.d.ts.map +1 -0
  158. package/build/template/routes/changelog/_.js +111 -0
  159. package/build/template/routes/changelog/_.js.map +1 -0
  160. package/build/template/routes/changelog/utils.d.ts +3 -0
  161. package/build/template/routes/changelog/utils.d.ts.map +1 -0
  162. package/build/template/routes/changelog/utils.js +11 -0
  163. package/build/template/routes/changelog/utils.js.map +1 -0
  164. package/build/template/routes/examples/name.d.ts.map +1 -1
  165. package/build/template/routes/examples/name.js +4 -2
  166. package/build/template/routes/examples/name.js.map +1 -1
  167. package/build/template/routes/reference.js +2 -2
  168. package/build/template/routes/reference.js.map +1 -1
  169. package/build/template/routes/root.js +1 -1
  170. package/build/template/routes/root.js.map +1 -1
  171. package/build/template/stores/toast.d.ts.map +1 -1
  172. package/build/template/stores/toast.js +5 -3
  173. package/build/template/stores/toast.js.map +1 -1
  174. package/build/template/theme/swiss-sharp.css +14 -14
  175. package/build/vite/plugins/schemas.d.ts +1 -2
  176. package/build/vite/plugins/schemas.d.ts.map +1 -1
  177. package/build/vite/plugins/schemas.js +0 -1
  178. package/build/vite/plugins/schemas.js.map +1 -1
  179. package/package.json +7 -7
  180. package/src/api/builder/ssg/generate.ts +10 -5
  181. package/src/api/builder/ssg/page-generator.worker.ts +18 -3
  182. package/src/api/config/normalized.ts +12 -3
  183. package/src/api/config-template/template.ts +2 -2
  184. package/src/api/content/sidebar.ts +3 -3
  185. package/src/api/errors.ts +227 -0
  186. package/src/api/examples/config.test.ts +10 -0
  187. package/src/api/examples/config.ts +33 -4
  188. package/src/api/examples/diagnostic/validation-error.ts +9 -3
  189. package/src/api/examples/diagnostic/validator.test.ts +30 -0
  190. package/src/api/examples/diagnostic/validator.ts +148 -103
  191. package/src/api/examples/filter.ts +9 -6
  192. package/src/api/examples/scanner.ts +136 -117
  193. package/src/api/examples/type-usage-indexer.ts +24 -36
  194. package/src/api/iso/schema/routing.ts +10 -10
  195. package/src/api/iso/schema/validation.ts +3 -2
  196. package/src/api/schema/input-source/$$.ts +1 -0
  197. package/src/api/schema/input-source/errors.ts +26 -0
  198. package/src/api/schema/input-source/input-source.ts +1 -22
  199. package/src/api/schema/input-sources/directory.ts +20 -15
  200. package/src/api/schema/input-sources/file.ts +17 -4
  201. package/src/api/schema/input-sources/introspection-file.ts +30 -15
  202. package/src/api/schema/input-sources/introspection.ts +38 -7
  203. package/src/api/schema/input-sources/memory.ts +19 -3
  204. package/src/api/schema/input-sources/versioned-directory.ts +25 -27
  205. package/src/api/schema/load.ts +2 -1
  206. package/src/lib/catalog/catalog.ts +89 -6
  207. package/src/lib/catalog/versioned.ts +26 -5
  208. package/src/lib/document/document.ts +135 -2
  209. package/src/lib/document/versioned.ts +8 -8
  210. package/src/lib/lifecycles/lifecycles.ts +32 -27
  211. package/src/lib/version-coverage/$$.ts +1 -0
  212. package/src/lib/{version-selection/version-selection.ts → version-coverage/version-coverage.ts} +1 -1
  213. package/src/template/components/GraphQLDocument.tsx +11 -69
  214. package/src/template/components/GraphQLInteractive/lib/parser.ts +81 -29
  215. package/src/template/components/ReferenceVersionPicker.tsx +107 -0
  216. package/src/template/components/VersionCoveragePicker.tsx +4 -5
  217. package/src/template/components/VersionPicker.tsx +32 -98
  218. package/src/template/components/home/QuickStart.tsx +16 -7
  219. package/src/template/hooks/use-highlighted.ts +31 -19
  220. package/src/template/lib/fetch-text.ts +45 -4
  221. package/src/template/{components/Changelog/Changelog.tsx → routes/changelog/ChangelogBody.tsx} +7 -64
  222. package/src/template/routes/changelog/ChangelogSidebar.tsx +80 -0
  223. package/src/template/routes/changelog/ChangelogSidebarItem.tsx +68 -0
  224. package/src/template/routes/changelog/_.tsx +129 -0
  225. package/src/template/routes/changelog/utils.ts +13 -0
  226. package/src/template/routes/examples/name.tsx +4 -2
  227. package/src/template/routes/reference.tsx +2 -2
  228. package/src/template/routes/root.tsx +1 -1
  229. package/src/template/stores/toast.ts +6 -3
  230. package/src/template/theme/swiss-sharp.css +14 -14
  231. package/src/vite/plugins/schemas.ts +0 -1
  232. package/build/lib/graph/$$.d.ts +0 -2
  233. package/build/lib/graph/$$.d.ts.map +0 -1
  234. package/build/lib/graph/$$.js +0 -2
  235. package/build/lib/graph/$$.js.map +0 -1
  236. package/build/lib/graph/$.d.ts +0 -2
  237. package/build/lib/graph/$.d.ts.map +0 -1
  238. package/build/lib/graph/$.js +0 -2
  239. package/build/lib/graph/$.js.map +0 -1
  240. package/build/lib/graph/graph.d.ts +0 -127
  241. package/build/lib/graph/graph.d.ts.map +0 -1
  242. package/build/lib/graph/graph.js +0 -152
  243. package/build/lib/graph/graph.js.map +0 -1
  244. package/build/lib/mask/$$.d.ts +0 -3
  245. package/build/lib/mask/$$.d.ts.map +0 -1
  246. package/build/lib/mask/$$.js +0 -3
  247. package/build/lib/mask/$$.js.map +0 -1
  248. package/build/lib/mask/$.d.ts +0 -2
  249. package/build/lib/mask/$.d.ts.map +0 -1
  250. package/build/lib/mask/$.js +0 -2
  251. package/build/lib/mask/$.js.map +0 -1
  252. package/build/lib/mask/apply.d.ts +0 -86
  253. package/build/lib/mask/apply.d.ts.map +0 -1
  254. package/build/lib/mask/apply.js +0 -86
  255. package/build/lib/mask/apply.js.map +0 -1
  256. package/build/lib/mask/mask.d.ts +0 -124
  257. package/build/lib/mask/mask.d.ts.map +0 -1
  258. package/build/lib/mask/mask.js +0 -137
  259. package/build/lib/mask/mask.js.map +0 -1
  260. package/build/lib/mask/mask.test-d.d.ts +0 -2
  261. package/build/lib/mask/mask.test-d.d.ts.map +0 -1
  262. package/build/lib/mask/mask.test-d.js +0 -102
  263. package/build/lib/mask/mask.test-d.js.map +0 -1
  264. package/build/lib/version-selection/$$.d.ts +0 -2
  265. package/build/lib/version-selection/$$.d.ts.map +0 -1
  266. package/build/lib/version-selection/$$.js +0 -2
  267. package/build/lib/version-selection/$$.js.map +0 -1
  268. package/build/lib/version-selection/$.d.ts.map +0 -1
  269. package/build/lib/version-selection/$.js.map +0 -1
  270. package/build/lib/version-selection/version-selection.d.ts.map +0 -1
  271. package/build/lib/version-selection/version-selection.js.map +0 -1
  272. package/build/sandbox.d.ts +0 -2
  273. package/build/sandbox.d.ts.map +0 -1
  274. package/build/sandbox.js +0 -17
  275. package/build/sandbox.js.map +0 -1
  276. package/build/template/components/Changelog/Changelog.d.ts +0 -8
  277. package/build/template/components/Changelog/Changelog.d.ts.map +0 -1
  278. package/build/template/components/Changelog/Changelog.js.map +0 -1
  279. package/build/template/components/Changelog/ChangelogVersionPicker.d.ts +0 -8
  280. package/build/template/components/Changelog/ChangelogVersionPicker.d.ts.map +0 -1
  281. package/build/template/components/Changelog/ChangelogVersionPicker.js +0 -16
  282. package/build/template/components/Changelog/ChangelogVersionPicker.js.map +0 -1
  283. package/build/template/components/SimpleVersionPicker.d.ts +0 -15
  284. package/build/template/components/SimpleVersionPicker.d.ts.map +0 -1
  285. package/build/template/components/SimpleVersionPicker.js +0 -15
  286. package/build/template/components/SimpleVersionPicker.js.map +0 -1
  287. package/build/template/routes/changelog.d.ts +0 -1635
  288. package/build/template/routes/changelog.d.ts.map +0 -1
  289. package/build/template/routes/changelog.js +0 -168
  290. package/build/template/routes/changelog.js.map +0 -1
  291. package/src/lib/graph/$$.ts +0 -1
  292. package/src/lib/graph/$.ts +0 -1
  293. package/src/lib/graph/graph.ts +0 -197
  294. package/src/lib/mask/$$.ts +0 -2
  295. package/src/lib/mask/$.test.ts +0 -226
  296. package/src/lib/mask/$.ts +0 -1
  297. package/src/lib/mask/apply.ts +0 -134
  298. package/src/lib/mask/mask.test-d.ts +0 -156
  299. package/src/lib/mask/mask.ts +0 -244
  300. package/src/lib/version-selection/$$.ts +0 -1
  301. package/src/sandbox.ts +0 -15
  302. package/src/template/components/Changelog/ChangelogVersionPicker.tsx +0 -36
  303. package/src/template/components/SimpleVersionPicker.tsx +0 -48
  304. package/src/template/routes/changelog.tsx +0 -267
  305. /package/build/lib/{version-selection → version-coverage}/$.d.ts +0 -0
  306. /package/build/lib/{version-selection → version-coverage}/$.js +0 -0
  307. /package/src/lib/{version-selection → version-coverage}/$.ts +0 -0
@@ -1,6 +1,30 @@
1
+ import { Catalog } from '#lib/catalog/$'
1
2
  import { S } from '#lib/kit-temp/effect'
3
+ import { Schema } from '#lib/schema/$'
4
+ import { VersionCoverage } from '#lib/version-coverage'
5
+ import { Version } from '#lib/version/$'
6
+ import { Data, Either, Option } from 'effect'
2
7
  import { DocumentUnversioned } from './unversioned.js'
3
- import { DocumentVersioned } from './versioned.js'
8
+ import * as DocumentVersioned from './versioned.js'
9
+
10
+ // ============================================================================
11
+ // Error Types
12
+ // ============================================================================
13
+
14
+ /**
15
+ * Error thrown when trying to use version coverage with an unversioned catalog
16
+ */
17
+ export class VersionCoverageMismatchError extends Data.TaggedError('VersionCoverageMismatchError')<{
18
+ readonly reason: string
19
+ }> {}
20
+
21
+ /**
22
+ * Error thrown when a version is not found in the document
23
+ */
24
+ export class VersionNotFoundInDocumentError extends Data.TaggedError('VersionNotFoundInDocumentError')<{
25
+ readonly version: string
26
+ readonly reason: string
27
+ }> {}
4
28
 
5
29
  // ============================================================================
6
30
  // Schema
@@ -13,7 +37,7 @@ import { DocumentVersioned } from './versioned.js'
13
37
  */
14
38
  export const Document = S.Union(
15
39
  DocumentUnversioned,
16
- DocumentVersioned,
40
+ DocumentVersioned.DocumentVersioned,
17
41
  )
18
42
 
19
43
  // ============================================================================
@@ -35,3 +59,112 @@ export const is = S.is(Document)
35
59
  export const decode = S.decode(Document)
36
60
  export const decodeSync = S.decodeSync(Document)
37
61
  export const encode = S.encode(Document)
62
+
63
+ // ============================================================================
64
+ // Domain Logic - Resolution Functions
65
+ // ============================================================================
66
+
67
+ /**
68
+ * Resolve document content for a given version coverage.
69
+ *
70
+ * @param document - The document to resolve content from
71
+ * @param versionCoverage - The version coverage to use (optional, defaults to latest)
72
+ * @returns The resolved document content
73
+ * @throws {Error} If version is not found in document
74
+ */
75
+ export const resolveDocumentContent = (
76
+ document: Document,
77
+ versionCoverage?: VersionCoverage.VersionCoverage | null,
78
+ ): string => {
79
+ if (document._tag === 'DocumentUnversioned') {
80
+ return document.document
81
+ }
82
+
83
+ // If no version coverage specified, use latest
84
+ if (!versionCoverage) {
85
+ return DocumentVersioned.getContentForLatestVersionOrThrow(document)
86
+ }
87
+
88
+ // Get the latest version from the coverage
89
+ const version = VersionCoverage.getLatest(versionCoverage)
90
+ const contentOption = DocumentVersioned.getContentForVersion(document, version)
91
+
92
+ if (Option.isNone(contentOption)) {
93
+ throw new VersionNotFoundInDocumentError({
94
+ version: Version.encodeSync(version),
95
+ reason: `Version ${Version.encodeSync(version)} not covered by document`,
96
+ })
97
+ }
98
+
99
+ return contentOption.value
100
+ }
101
+
102
+ /**
103
+ * Resolve both document content and schema for a given version coverage.
104
+ * This is the primary resolution function that handles all combinations
105
+ * of versioned/unversioned documents and catalogs.
106
+ *
107
+ * @param document - The document to resolve content from
108
+ * @param catalog - The schema catalog (optional)
109
+ * @param versionCoverage - The version coverage to use (optional, defaults to latest)
110
+ * @returns Either with resolved content and optional schema, or error
111
+ */
112
+ export const resolveDocumentAndSchema = (
113
+ document: Document,
114
+ catalog?: Catalog.Catalog,
115
+ versionCoverage?: VersionCoverage.VersionCoverage | null,
116
+ ): Either.Either<
117
+ { content: string; schema?: Schema.Schema },
118
+ | VersionCoverageMismatchError
119
+ | VersionNotFoundInDocumentError
120
+ | Catalog.VersionNotFoundInCatalogError
121
+ | Catalog.EmptyCatalogError
122
+ > => {
123
+ // Handle unversioned document
124
+ if (document._tag === 'DocumentUnversioned') {
125
+ const content = document.document
126
+
127
+ if (!catalog) {
128
+ return Either.right({ content })
129
+ }
130
+
131
+ return Catalog.resolveCatalogSchemaEither(catalog, null).pipe(
132
+ Either.map(schema => ({ content, schema })),
133
+ )
134
+ }
135
+
136
+ // Handle versioned document
137
+ let content: string
138
+ try {
139
+ content = resolveDocumentContent(document, versionCoverage)
140
+ } catch (error) {
141
+ // resolveDocumentContent throws our tagged error
142
+ if (error instanceof VersionNotFoundInDocumentError) {
143
+ return Either.left(error)
144
+ }
145
+ // This shouldn't happen but handle gracefully
146
+ return Either.left(
147
+ new VersionNotFoundInDocumentError({
148
+ version: String(versionCoverage),
149
+ reason: error instanceof Error ? error.message : String(error),
150
+ }),
151
+ )
152
+ }
153
+
154
+ if (!catalog) {
155
+ return Either.right({ content })
156
+ }
157
+
158
+ // Cannot use version coverage with unversioned catalog
159
+ if (versionCoverage && Catalog.Unversioned.is(catalog)) {
160
+ return Either.left(
161
+ new VersionCoverageMismatchError({
162
+ reason: 'Cannot use a version coverage with an unversioned catalog',
163
+ }),
164
+ )
165
+ }
166
+
167
+ return Catalog.resolveCatalogSchemaEither(catalog, versionCoverage).pipe(
168
+ Either.map(schema => ({ content, schema })),
169
+ )
170
+ }
@@ -1,5 +1,5 @@
1
1
  import { S } from '#lib/kit-temp/effect'
2
- import { VersionCoverage } from '#lib/version-selection/$'
2
+ import { VersionCoverage } from '#lib/version-coverage'
3
3
  import { Version } from '#lib/version/$'
4
4
  import { HashMap, Option } from 'effect'
5
5
 
@@ -56,21 +56,21 @@ export const encode = S.encode(DocumentVersioned)
56
56
  export const getContentForVersion = (
57
57
  doc: DocumentVersioned,
58
58
  version: Version.Version,
59
- ): string | null => {
59
+ ): Option.Option<string> => {
60
60
  // Try exact match first (single version key)
61
61
  const exactMatch = HashMap.get(doc.versionDocuments, version)
62
62
  if (Option.isSome(exactMatch)) {
63
- return exactMatch.value
63
+ return Option.some(exactMatch.value)
64
64
  }
65
65
 
66
66
  // Check version sets
67
67
  for (const [selection, content] of HashMap.entries(doc.versionDocuments)) {
68
68
  if (VersionCoverage.isSet(selection) && VersionCoverage.contains(selection, version)) {
69
- return content
69
+ return Option.some(content)
70
70
  }
71
71
  }
72
72
 
73
- return null
73
+ return Option.none()
74
74
  }
75
75
 
76
76
  /**
@@ -98,9 +98,9 @@ export const getContentForLatestVersionOrThrow = (doc: DocumentVersioned): strin
98
98
  // Use Version.max with reduce to find the latest version
99
99
  const latestVersion = versions.reduce(Version.max)
100
100
 
101
- const content = getContentForVersion(doc, latestVersion)
102
- if (!content) {
101
+ const contentOption = getContentForVersion(doc, latestVersion)
102
+ if (Option.isNone(contentOption)) {
103
103
  throw new Error('Latest version not found in document')
104
104
  }
105
- return content
105
+ return contentOption.value
106
106
  }
@@ -3,7 +3,7 @@ import { Change } from '#lib/change/$'
3
3
  import { Revision } from '#lib/revision/$'
4
4
  import { Schema } from '#lib/schema/$'
5
5
  import { Version } from '#lib/version/$'
6
- import { Match } from 'effect'
6
+ import { Match, Option } from 'effect'
7
7
 
8
8
  // ============================================================================
9
9
  // Lifecycles Type - Simple Index
@@ -44,21 +44,21 @@ export type Since =
44
44
  /**
45
45
  * Extract the type name from a change
46
46
  */
47
- const extractTypeNameFromChange = (change: Change.Change): string | null => {
47
+ const extractTypeNameFromChange = (change: Change.Change): Option.Option<string> => {
48
48
  return Match.value(change).pipe(
49
- Match.tag('TYPE_ADDED', (c) => c.name),
50
- Match.tag('TYPE_REMOVED', (c) => c.name),
51
- Match.tag('FIELD_ADDED', (c) => c.typeName),
52
- Match.tag('FIELD_REMOVED', (c) => c.typeName),
53
- Match.tag('INPUT_FIELD_ADDED', (c) => c.inputName),
54
- Match.tag('INPUT_FIELD_REMOVED', (c) => c.inputName),
55
- Match.tag('ENUM_VALUE_ADDED', (c) => c.enumName),
56
- Match.tag('ENUM_VALUE_REMOVED', (c) => c.enumName),
57
- Match.tag('UNION_MEMBER_ADDED', (c) => c.unionName),
58
- Match.tag('UNION_MEMBER_REMOVED', (c) => c.unionName),
59
- Match.tag('OBJECT_TYPE_INTERFACE_ADDED', (c) => c.objectName),
60
- Match.tag('OBJECT_TYPE_INTERFACE_REMOVED', (c) => c.objectName),
61
- Match.orElse(() => null),
49
+ Match.tag('TYPE_ADDED', (c) => Option.some(c.name)),
50
+ Match.tag('TYPE_REMOVED', (c) => Option.some(c.name)),
51
+ Match.tag('FIELD_ADDED', (c) => Option.some(c.typeName)),
52
+ Match.tag('FIELD_REMOVED', (c) => Option.some(c.typeName)),
53
+ Match.tag('INPUT_FIELD_ADDED', (c) => Option.some(c.inputName)),
54
+ Match.tag('INPUT_FIELD_REMOVED', (c) => Option.some(c.inputName)),
55
+ Match.tag('ENUM_VALUE_ADDED', (c) => Option.some(c.enumName)),
56
+ Match.tag('ENUM_VALUE_REMOVED', (c) => Option.some(c.enumName)),
57
+ Match.tag('UNION_MEMBER_ADDED', (c) => Option.some(c.unionName)),
58
+ Match.tag('UNION_MEMBER_REMOVED', (c) => Option.some(c.unionName)),
59
+ Match.tag('OBJECT_TYPE_INTERFACE_ADDED', (c) => Option.some(c.objectName)),
60
+ Match.tag('OBJECT_TYPE_INTERFACE_REMOVED', (c) => Option.some(c.objectName)),
61
+ Match.orElse(() => Option.none()),
62
62
  )
63
63
  }
64
64
 
@@ -72,8 +72,9 @@ export const createFromSchema = (schema: Schema.Schema): Lifecycles => {
72
72
  for (const revision of schema.revisions) {
73
73
  // Process all changes in this revision
74
74
  for (const change of revision.changes) {
75
- const typeName = extractTypeNameFromChange(change)
76
- if (typeName) {
75
+ const typeNameOption = extractTypeNameFromChange(change)
76
+ if (Option.isSome(typeNameOption)) {
77
+ const typeName = typeNameOption.value
77
78
  if (!lifecycles[typeName]) {
78
79
  lifecycles[typeName] = []
79
80
  }
@@ -100,8 +101,9 @@ export const create = (catalog: Catalog.Catalog): Lifecycles => {
100
101
  for (const revision of schema.revisions) {
101
102
  // Process all changes in this revision
102
103
  for (const change of revision.changes) {
103
- const typeName = extractTypeNameFromChange(change)
104
- if (typeName) {
104
+ const typeNameOption = extractTypeNameFromChange(change)
105
+ if (Option.isSome(typeNameOption)) {
106
+ const typeName = typeNameOption.value
105
107
  if (!lifecycles[typeName]) {
106
108
  lifecycles[typeName] = []
107
109
  }
@@ -477,9 +479,9 @@ export const getFieldLifecycle = (
477
479
  lifecycles: Lifecycles,
478
480
  typeName: string,
479
481
  fieldName: string,
480
- ): { events: ChangeEntry[] } | undefined => {
482
+ ): Option.Option<{ events: ChangeEntry[] }> => {
481
483
  const entries = lifecycles[typeName]
482
- if (!entries) return undefined
484
+ if (!entries) return Option.none()
483
485
 
484
486
  // Filter entries related to this specific field
485
487
  const fieldEntries = entries.filter(entry => {
@@ -497,25 +499,28 @@ export const getFieldLifecycle = (
497
499
  && entry.change.fieldName === fieldName)
498
500
  })
499
501
 
500
- if (fieldEntries.length === 0) return undefined
502
+ if (fieldEntries.length === 0) return Option.none()
501
503
 
502
504
  // Return in a format compatible with existing code that expects an object with events
503
- return { events: fieldEntries }
505
+ return Option.some({ events: fieldEntries })
504
506
  }
505
507
 
506
508
  /**
507
509
  * Get type lifecycle info (for compatibility with existing UI code)
508
510
  */
509
- export const getTypeLifecycle = (lifecycles: Lifecycles, typeName: string): { events: ChangeEntry[] } | undefined => {
511
+ export const getTypeLifecycle = (
512
+ lifecycles: Lifecycles,
513
+ typeName: string,
514
+ ): Option.Option<{ events: ChangeEntry[] }> => {
510
515
  const entries = lifecycles[typeName]
511
- if (!entries) return undefined
516
+ if (!entries) return Option.none()
512
517
 
513
518
  // Filter entries related to type-level changes
514
519
  const typeEntries = entries.filter(entry => {
515
520
  return entry.change._tag === 'TYPE_ADDED' || entry.change._tag === 'TYPE_REMOVED'
516
521
  })
517
522
 
518
- if (typeEntries.length === 0) return undefined
523
+ if (typeEntries.length === 0) return Option.none()
519
524
 
520
- return { events: typeEntries }
525
+ return Option.some({ events: typeEntries })
521
526
  }
@@ -0,0 +1 @@
1
+ export * from './version-coverage.js'
@@ -58,7 +58,7 @@ export const encodeSync = S.encodeSync(VersionCoverage)
58
58
  export const equivalence = S.equivalence(VersionCoverage)
59
59
 
60
60
  // ============================================================================
61
- // Domain Logic
61
+ // Domain Logic - Basic Operations
62
62
  // ============================================================================
63
63
 
64
64
  /**
@@ -1,12 +1,7 @@
1
1
  import { Catalog } from '#lib/catalog/$'
2
2
  import { Document } from '#lib/document/$'
3
- import { S } from '#lib/kit-temp/$'
4
- import type { Schema } from '#lib/schema/$'
5
- import { VersionCoverage } from '#lib/version-selection/$'
6
- import { VersionCoverageSet } from '#lib/version-selection/version-selection'
7
- import { Version } from '#lib/version/$'
8
- import { Array, HashMap, Match, Option } from 'effect'
9
- import type { GraphQLSchema } from 'graphql'
3
+ import { VersionCoverage } from '#lib/version-coverage'
4
+ import { Either, Option } from 'effect'
10
5
  import * as React from 'react'
11
6
  import { useHighlighted } from '../hooks/use-highlighted.js'
12
7
  import { GraphQLInteractive } from './GraphQLInteractive/GraphQLInteractive.js'
@@ -47,7 +42,7 @@ export const GraphQLDocument: React.FC<GraphQLDocumentProps> = ({
47
42
  /// ━ VERSION MANAGEMENT
48
43
  const isControlled = controlledVersionCoverage !== undefined
49
44
  const [internalVersionCoverage, setInternalVersionCoverage] = React.useState<VersionCoverage.VersionCoverage | null>(
50
- Catalog.getLatestVersion(schemaCatalog),
45
+ Option.getOrNull(Catalog.getLatestVersion(schemaCatalog)),
51
46
  )
52
47
  const selectedVersionCoverage = isControlled ? controlledVersionCoverage : internalVersionCoverage
53
48
  const internalOnVersionChange = (version: VersionCoverage.VersionCoverage) => {
@@ -58,11 +53,15 @@ export const GraphQLDocument: React.FC<GraphQLDocumentProps> = ({
58
53
  }
59
54
 
60
55
  /// ━ DATA RESOLUTION
61
- const {
62
- schema,
63
- content,
64
- } = resolveSelectedVerCov(document, selectedVersionCoverage, schemaCatalog)
56
+ const result = Document.resolveDocumentAndSchema(document, schemaCatalog, selectedVersionCoverage)
65
57
 
58
+ // Handle resolution errors gracefully
59
+ if (Either.isLeft(result)) {
60
+ console.error('Failed to resolve document and schema:', result.left.message)
61
+ return null
62
+ }
63
+
64
+ const { schema, content } = result.right
66
65
  const highlightedCode = useHighlighted(content, { interactive: true })
67
66
 
68
67
  if (!highlightedCode) {
@@ -87,60 +86,3 @@ export const GraphQLDocument: React.FC<GraphQLDocumentProps> = ({
87
86
  />
88
87
  )
89
88
  }
90
-
91
- /**
92
- * Matches a document with an optional schema catalog, returning the document content,
93
- * corresponding schema, and available versions for the selected version.
94
- *
95
- * @param document - The document to retrieve content from (required)
96
- * @param selectedVersionCoverage - The version to select (optional, defaults to latest)
97
- * @param schemaCatalog - The schema catalog to match against (optional)
98
- * @returns Object with document content, optional schema, and available versions
99
- * @throws {Error} If versions in catalog don't match versions in document
100
- */
101
- type Result = { content: string; schema?: Schema.Schema }
102
- const resolveSelectedVerCov = (
103
- document: Document.Document,
104
- selectedVersionCoverage?: VersionCoverage.VersionCoverage | null,
105
- schemaCatalog?: Catalog.Catalog,
106
- ): Result => {
107
- if (Document.Unversioned.is(document)) {
108
- return {
109
- content: document.document,
110
- schema: Match.value(schemaCatalog).pipe(
111
- Match.tagsExhaustive({
112
- CatalogUnversioned: (catalog) => catalog.schema,
113
- CatalogVersioned: (catalog) => Catalog.Versioned.getLatestOrThrow(catalog),
114
- }),
115
- ),
116
- }
117
- }
118
-
119
- return Match.value(selectedVersionCoverage).pipe(
120
- Match.whenOr(null, undefined, _ => {
121
- const content = Document.Versioned.getContentForLatestVersionOrThrow(document)
122
- return { content }
123
- }),
124
- Match.orElse(_ => {
125
- const version = VersionCoverage.getLatest(_)
126
-
127
- const content = Document.Versioned.getContentForVersion(document, version)
128
- if (!content) {
129
- throw new Error(`Version ${Version.encodeSync(version)} not covered by document`)
130
- }
131
-
132
- if (!schemaCatalog) return { version, content }
133
-
134
- if (Catalog.Unversioned.is(schemaCatalog)) {
135
- throw new Error('Cannot use a set of versions with an unversioned catalog')
136
- }
137
- const schemaOption = HashMap.get(schemaCatalog.entries, version)
138
- if (Option.isNone(schemaOption)) {
139
- throw new Error(`Version ${Version.encodeSync(version)} not found in catalog`)
140
- }
141
- const schema = Option.getOrThrow(schemaOption)
142
-
143
- return { content, schema: schema }
144
- }),
145
- )
146
- }
@@ -7,6 +7,7 @@
7
7
 
8
8
  import { Api } from '#api/iso'
9
9
  import type { CodeAnnotation } from 'codehike/code'
10
+ import { Either } from 'effect'
10
11
  import {
11
12
  getNamedType,
12
13
  type GraphQLArgument,
@@ -504,41 +505,65 @@ class SemanticContext {
504
505
  }
505
506
 
506
507
  /**
507
- * Parse GraphQL code into interactive tokens with semantic information
508
+ * Error types for GraphQL parsing
509
+ */
510
+ export type ParseError =
511
+ | { readonly _tag: 'InvalidInput'; readonly message: string }
512
+ | { readonly _tag: 'DocumentTooLarge'; readonly maxSize: number; readonly actualSize: number }
513
+ | { readonly _tag: 'TreeSitterError'; readonly message: string }
514
+ | { readonly _tag: 'ParserInitError'; readonly message: string }
515
+
516
+ const makeParseError = {
517
+ invalidInput: (message: string): ParseError => ({ _tag: 'InvalidInput', message }),
518
+ documentTooLarge: (maxSize: number, actualSize: number): ParseError => ({
519
+ _tag: 'DocumentTooLarge',
520
+ maxSize,
521
+ actualSize,
522
+ }),
523
+ treeSitterError: (message: string): ParseError => ({ _tag: 'TreeSitterError', message }),
524
+ parserInitError: (message: string): ParseError => ({ _tag: 'ParserInitError', message }),
525
+ }
526
+
527
+ /**
528
+ * Parse GraphQL code into interactive tokens with semantic information (Either version)
508
529
  *
509
530
  * @param code - The raw GraphQL code to parse
510
531
  * @param annotations - CodeHike annotations that might affect rendering
511
532
  * @param schema - Optional GraphQL schema for semantic analysis
512
- * @returns Array of tokens representing the parsed code
533
+ * @returns Either with array of tokens on right or ParseError on left
513
534
  */
514
- export async function parseGraphQLWithTreeSitter(
535
+ export async function parseGraphQLWithTreeSitterEither(
515
536
  code: string,
516
537
  annotations: CodeAnnotation[] = [],
517
538
  schema?: GraphQLSchema,
518
- ): Promise<GraphQLToken[]> {
539
+ ): Promise<Either.Either<GraphQLToken[], ParseError>> {
519
540
  // Validate input
520
541
  if (!code || typeof code !== 'string') {
521
- throw new Error('Invalid GraphQL code: code must be a non-empty string')
542
+ return Either.left(makeParseError.invalidInput('Invalid GraphQL code: code must be a non-empty string'))
522
543
  }
523
544
 
524
545
  // Prevent parsing extremely large documents that could cause performance issues
525
- if (code.length > 100_000) {
526
- throw new Error('GraphQL document too large: maximum 100,000 characters allowed')
546
+ const maxSize = 100_000
547
+ if (code.length > maxSize) {
548
+ return Either.left(makeParseError.documentTooLarge(maxSize, code.length))
527
549
  }
528
550
 
529
551
  // Step 1: Parse with tree-sitter
530
- const parser = await getParser()
552
+ let parser: WebTreeSitter.Parser
553
+ try {
554
+ parser = await getParser()
555
+ } catch (error) {
556
+ return Either.left(makeParseError.parserInitError(
557
+ error instanceof Error ? error.message : 'Failed to initialize parser',
558
+ ))
559
+ }
560
+
531
561
  const tree = parser.parse(code)
532
562
 
533
563
  if (!tree) {
534
- throw new Error('Tree-sitter failed to parse GraphQL code')
564
+ return Either.left(makeParseError.treeSitterError('Tree-sitter failed to parse GraphQL code'))
535
565
  }
536
566
 
537
- // Check if tree-sitter found syntax errors (disabled for now as it may be too strict)
538
- // if (tree.rootNode.hasError) {
539
- // throw new Error('GraphQL syntax error detected by tree-sitter parser')
540
- // }
541
-
542
567
  try {
543
568
  // Step 2: Walk tree and attach semantics
544
569
  const tokens = collectTokensWithSemantics(tree, code, schema, annotations)
@@ -546,26 +571,53 @@ export async function parseGraphQLWithTreeSitter(
546
571
  // Step 3: Add error hint tokens after invalid fields
547
572
  const tokensWithHints = addErrorHintTokens(tokens, code, annotations)
548
573
 
549
- return tokensWithHints
574
+ return Either.right(tokensWithHints)
575
+ } catch (error) {
576
+ return Either.left(makeParseError.treeSitterError(
577
+ error instanceof Error ? error.message : 'Failed to process tokens',
578
+ ))
550
579
  } finally {
551
- // ## Tree-sitter Resource Lifecycle Management
552
- //
553
- // Tree-sitter creates native WASM objects that must be explicitly freed to prevent memory leaks.
554
- // The tree object holds references to parsed nodes and internal parser state that won't be
555
- // garbage collected automatically by JavaScript.
556
- //
557
- // Critical cleanup points:
558
- // 1. Always call tree.delete() in a finally block to ensure cleanup even on errors
559
- // 2. Do not access tree or any of its nodes after calling delete()
560
- // 3. The parser instance is cached globally and reused across multiple parsing calls
561
- //
562
- // Memory safety: Once tree.delete() is called, all WebTreeSitter.Node references become invalid.
563
- // Our tokens hold references to these nodes, but only use their text and position properties
564
- // which are copied during token creation, so the nodes can be safely deleted.
580
+ // Tree-sitter Resource Lifecycle Management
565
581
  tree.delete()
566
582
  }
567
583
  }
568
584
 
585
+ /**
586
+ * Parse GraphQL code into interactive tokens with semantic information
587
+ *
588
+ * @param code - The raw GraphQL code to parse
589
+ * @param annotations - CodeHike annotations that might affect rendering
590
+ * @param schema - Optional GraphQL schema for semantic analysis
591
+ * @returns Array of tokens representing the parsed code
592
+ * @deprecated Use parseGraphQLWithTreeSitterEither for better error handling
593
+ */
594
+ export async function parseGraphQLWithTreeSitter(
595
+ code: string,
596
+ annotations: CodeAnnotation[] = [],
597
+ schema?: GraphQLSchema,
598
+ ): Promise<GraphQLToken[]> {
599
+ const result = await parseGraphQLWithTreeSitterEither(code, annotations, schema)
600
+
601
+ if (Either.isLeft(result)) {
602
+ const error = result.left
603
+ switch (error._tag) {
604
+ case 'InvalidInput':
605
+ throw new Error(error.message)
606
+ case 'DocumentTooLarge':
607
+ throw new Error(`GraphQL document too large: maximum ${error.maxSize} characters allowed`)
608
+ case 'TreeSitterError':
609
+ case 'ParserInitError':
610
+ throw new Error(error.message)
611
+ default: {
612
+ const exhaustiveCheck: never = error
613
+ throw new Error(`Unhandled parse error: ${JSON.stringify(exhaustiveCheck)}`)
614
+ }
615
+ }
616
+ }
617
+
618
+ return result.right
619
+ }
620
+
569
621
  /**
570
622
  * Get or create the tree-sitter parser instance
571
623
  */