polen 0.10.0 → 0.11.0-next.10

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 (357) hide show
  1. package/build/api/api.d.ts +1 -0
  2. package/build/api/api.d.ts.map +1 -1
  3. package/build/api/api.js +1 -0
  4. package/build/api/api.js.map +1 -1
  5. package/build/api/config/configurator.d.ts +55 -26
  6. package/build/api/config/configurator.d.ts.map +1 -1
  7. package/build/api/config/configurator.js +27 -9
  8. package/build/api/config/configurator.js.map +1 -1
  9. package/build/api/config/merge.d.ts.map +1 -1
  10. package/build/api/config/merge.js +0 -11
  11. package/build/api/config/merge.js.map +1 -1
  12. package/build/api/content/metadata.d.ts +8 -2
  13. package/build/api/content/metadata.d.ts.map +1 -1
  14. package/build/api/content/metadata.js +1 -1
  15. package/build/api/content/metadata.js.map +1 -1
  16. package/build/api/schema/data-sources/data-sources.d.ts +1 -0
  17. package/build/api/schema/data-sources/data-sources.d.ts.map +1 -1
  18. package/build/api/schema/data-sources/data-sources.js +1 -0
  19. package/build/api/schema/data-sources/data-sources.js.map +1 -1
  20. package/build/api/schema/data-sources/introspection/introspection.d.ts +83 -0
  21. package/build/api/schema/data-sources/introspection/introspection.d.ts.map +1 -0
  22. package/build/api/schema/data-sources/introspection/introspection.js +110 -0
  23. package/build/api/schema/data-sources/introspection/introspection.js.map +1 -0
  24. package/build/api/schema/data-sources/memory/memory.d.ts +2 -2
  25. package/build/api/schema/data-sources/memory/memory.d.ts.map +1 -1
  26. package/build/api/schema/data-sources/memory/memory.js +1 -3
  27. package/build/api/schema/data-sources/memory/memory.js.map +1 -1
  28. package/build/api/schema/data-sources/schema-directory/file-name-expression/file-name-expression.d.ts +7 -3
  29. package/build/api/schema/data-sources/schema-directory/file-name-expression/file-name-expression.d.ts.map +1 -1
  30. package/build/api/schema/data-sources/schema-directory/file-name-expression/file-name-expression.js +15 -11
  31. package/build/api/schema/data-sources/schema-directory/file-name-expression/file-name-expression.js.map +1 -1
  32. package/build/api/schema/data-sources/schema-directory/schema-directory.d.ts +16 -7
  33. package/build/api/schema/data-sources/schema-directory/schema-directory.d.ts.map +1 -1
  34. package/build/api/schema/data-sources/schema-directory/schema-directory.js +26 -7
  35. package/build/api/schema/data-sources/schema-directory/schema-directory.js.map +1 -1
  36. package/build/api/schema/data-sources/schema-file/schema-file.d.ts +7 -2
  37. package/build/api/schema/data-sources/schema-file/schema-file.d.ts.map +1 -1
  38. package/build/api/schema/data-sources/schema-file/schema-file.js +13 -5
  39. package/build/api/schema/data-sources/schema-file/schema-file.js.map +1 -1
  40. package/build/api/schema/metadata.d.ts +16 -0
  41. package/build/api/schema/metadata.d.ts.map +1 -0
  42. package/build/api/schema/metadata.js +19 -0
  43. package/build/api/schema/metadata.js.map +1 -0
  44. package/build/api/schema/read.d.ts +85 -11
  45. package/build/api/schema/read.d.ts.map +1 -1
  46. package/build/api/schema/read.js +15 -6
  47. package/build/api/schema/read.js.map +1 -1
  48. package/build/api/schema/schema.d.ts +33 -2
  49. package/build/api/schema/schema.d.ts.map +1 -1
  50. package/build/api/schema/schema.js +42 -0
  51. package/build/api/schema/schema.js.map +1 -1
  52. package/build/api/schema-source/index.d.ts +2 -0
  53. package/build/api/schema-source/index.d.ts.map +1 -0
  54. package/build/api/schema-source/index.js +2 -0
  55. package/build/api/schema-source/index.js.map +1 -0
  56. package/build/api/schema-source/schema-source.d.ts +33 -0
  57. package/build/api/schema-source/schema-source.d.ts.map +1 -0
  58. package/build/api/schema-source/schema-source.js +137 -0
  59. package/build/api/schema-source/schema-source.js.map +1 -0
  60. package/build/api/static/manifest.d.ts +1 -2
  61. package/build/api/static/manifest.d.ts.map +1 -1
  62. package/build/api/static/manifest.js +1 -1
  63. package/build/api/static/manifest.js.map +1 -1
  64. package/build/api/vite/plugins/build.d.ts.map +1 -1
  65. package/build/api/vite/plugins/build.js +3 -0
  66. package/build/api/vite/plugins/build.js.map +1 -1
  67. package/build/api/vite/plugins/core.d.ts +1 -0
  68. package/build/api/vite/plugins/core.d.ts.map +1 -1
  69. package/build/api/vite/plugins/core.js +25 -22
  70. package/build/api/vite/plugins/core.js.map +1 -1
  71. package/build/api/vite/plugins/main.d.ts.map +1 -1
  72. package/build/api/vite/plugins/main.js +1 -8
  73. package/build/api/vite/plugins/main.js.map +1 -1
  74. package/build/api/vite/plugins/schema-assets.d.ts +22 -0
  75. package/build/api/vite/plugins/schema-assets.d.ts.map +1 -0
  76. package/build/api/vite/plugins/schema-assets.js +310 -0
  77. package/build/api/vite/plugins/schema-assets.js.map +1 -0
  78. package/build/api/vite/plugins/serve.d.ts.map +1 -1
  79. package/build/api/vite/plugins/serve.js +11 -0
  80. package/build/api/vite/plugins/serve.js.map +1 -1
  81. package/build/cli/commands/open.js +1 -1
  82. package/build/cli/commands/open.js.map +1 -1
  83. package/build/lib/grafaid/schema/schema.d.ts +1 -1
  84. package/build/lib/grafaid/schema/schema.d.ts.map +1 -1
  85. package/build/lib/grafaid/schema/schema.js +1 -1
  86. package/build/lib/grafaid/schema/schema.js.map +1 -1
  87. package/build/lib/graphql-change/change-groups.d.ts +2 -0
  88. package/build/lib/graphql-change/change-groups.d.ts.map +1 -1
  89. package/build/lib/graphql-change/change-groups.js +54 -0
  90. package/build/lib/graphql-change/change-groups.js.map +1 -1
  91. package/build/lib/kit-temp.d.ts +9 -0
  92. package/build/lib/kit-temp.d.ts.map +1 -1
  93. package/build/lib/kit-temp.js +14 -2
  94. package/build/lib/kit-temp.js.map +1 -1
  95. package/build/lib/path-map/path-map.d.ts.map +1 -1
  96. package/build/lib/path-map/path-map.js +3 -1
  97. package/build/lib/path-map/path-map.js.map +1 -1
  98. package/build/lib/react-router-aid/react-router-aid.d.ts +5 -3
  99. package/build/lib/react-router-aid/react-router-aid.d.ts.map +1 -1
  100. package/build/lib/react-router-aid/react-router-aid.js +7 -4
  101. package/build/lib/react-router-aid/react-router-aid.js.map +1 -1
  102. package/build/project-data.d.ts +3 -11
  103. package/build/project-data.d.ts.map +1 -1
  104. package/build/template/components/Changelog.d.ts +3 -3
  105. package/build/template/components/Changelog.d.ts.map +1 -1
  106. package/build/template/components/Changelog.js +8 -84
  107. package/build/template/components/Changelog.js.map +1 -1
  108. package/build/template/components/CodeBlock.d.ts +2 -0
  109. package/build/template/components/CodeBlock.d.ts.map +1 -1
  110. package/build/template/components/CodeBlock.js +1 -4
  111. package/build/template/components/CodeBlock.js.map +1 -1
  112. package/build/template/components/ComponentDispatch.d.ts +34 -0
  113. package/build/template/components/ComponentDispatch.d.ts.map +1 -0
  114. package/build/template/components/ComponentDispatch.js +33 -0
  115. package/build/template/components/ComponentDispatch.js.map +1 -0
  116. package/build/template/components/ReferenceLink.d.ts +19 -0
  117. package/build/template/components/ReferenceLink.d.ts.map +1 -0
  118. package/build/template/components/ReferenceLink.js +19 -0
  119. package/build/template/components/ReferenceLink.js.map +1 -0
  120. package/build/template/components/TypeAnnotation.d.ts.map +1 -1
  121. package/build/template/components/TypeAnnotation.js +3 -3
  122. package/build/template/components/TypeAnnotation.js.map +1 -1
  123. package/build/template/components/TypeFieldsLinkList.d.ts.map +1 -1
  124. package/build/template/components/TypeFieldsLinkList.js +4 -4
  125. package/build/template/components/TypeFieldsLinkList.js.map +1 -1
  126. package/build/template/components/TypeIndex.js +2 -2
  127. package/build/template/components/TypeIndex.js.map +1 -1
  128. package/build/template/components/VersionSelector.d.ts +7 -0
  129. package/build/template/components/VersionSelector.d.ts.map +1 -0
  130. package/build/template/components/VersionSelector.js +30 -0
  131. package/build/template/components/VersionSelector.js.map +1 -0
  132. package/build/template/components/graphql/type-link.d.ts.map +1 -1
  133. package/build/template/components/graphql/type-link.js +2 -2
  134. package/build/template/components/graphql/type-link.js.map +1 -1
  135. package/build/template/hooks/useVersionPath.d.ts +6 -0
  136. package/build/template/hooks/useVersionPath.d.ts.map +1 -0
  137. package/build/template/hooks/useVersionPath.js +10 -0
  138. package/build/template/hooks/useVersionPath.js.map +1 -0
  139. package/build/template/layouts/ChangelogLayout.d.ts.map +1 -0
  140. package/build/template/{components → layouts}/ChangelogLayout.js +1 -1
  141. package/build/template/layouts/ChangelogLayout.js.map +1 -0
  142. package/build/template/layouts/index.d.ts +1 -0
  143. package/build/template/layouts/index.d.ts.map +1 -1
  144. package/build/template/layouts/index.js +1 -0
  145. package/build/template/layouts/index.js.map +1 -1
  146. package/build/template/lib/fetch-text.d.ts +8 -0
  147. package/build/template/lib/fetch-text.d.ts.map +1 -0
  148. package/build/template/lib/fetch-text.js +14 -0
  149. package/build/template/lib/fetch-text.js.map +1 -0
  150. package/build/template/lib/polen-url.d.ts +14 -0
  151. package/build/template/lib/polen-url.d.ts.map +1 -1
  152. package/build/template/lib/polen-url.js +16 -0
  153. package/build/template/lib/polen-url.js.map +1 -1
  154. package/build/template/lib/schema-utils/constants.d.ts +5 -0
  155. package/build/template/lib/schema-utils/constants.d.ts.map +1 -0
  156. package/build/template/lib/schema-utils/constants.js +5 -0
  157. package/build/template/lib/schema-utils/constants.js.map +1 -0
  158. package/build/template/lib/schema-utils/schema-utils.d.ts +15 -0
  159. package/build/template/lib/schema-utils/schema-utils.d.ts.map +1 -0
  160. package/build/template/lib/schema-utils/schema-utils.js +37 -0
  161. package/build/template/lib/schema-utils/schema-utils.js.map +1 -0
  162. package/build/template/routes/changelog.d.ts +4 -3
  163. package/build/template/routes/changelog.d.ts.map +1 -1
  164. package/build/template/routes/changelog.js +15 -9
  165. package/build/template/routes/changelog.js.map +1 -1
  166. package/build/template/routes/index.js +2 -2
  167. package/build/template/routes/index.js.map +1 -1
  168. package/build/template/routes/pages.d.ts +10 -0
  169. package/build/template/routes/pages.d.ts.map +1 -0
  170. package/build/template/routes/pages.js +76 -0
  171. package/build/template/routes/pages.js.map +1 -0
  172. package/build/template/routes/reference.d.ts +35 -6
  173. package/build/template/routes/reference.d.ts.map +1 -1
  174. package/build/template/routes/reference.js +97 -14
  175. package/build/template/routes/reference.js.map +1 -1
  176. package/build/template/routes/root.d.ts.map +1 -1
  177. package/build/template/routes/root.js +11 -75
  178. package/build/template/routes/root.js.map +1 -1
  179. package/build/template/server/app.d.ts +22 -1
  180. package/build/template/server/app.d.ts.map +1 -1
  181. package/build/template/server/app.js +19 -9
  182. package/build/template/server/app.js.map +1 -1
  183. package/build/template/server/main.js +9 -1
  184. package/build/template/server/main.js.map +1 -1
  185. package/build/template/server/ssg/generate.js +2 -2
  186. package/build/template/server/ssg/generate.js.map +1 -1
  187. package/build/template/server/ssg/get-route-paths.d.ts +1 -1
  188. package/build/template/server/ssg/get-route-paths.d.ts.map +1 -1
  189. package/build/template/server/ssg/get-route-paths.js +90 -27
  190. package/build/template/server/ssg/get-route-paths.js.map +1 -1
  191. package/build/template/sources/schema-source.d.ts +15 -0
  192. package/build/template/sources/schema-source.d.ts.map +1 -0
  193. package/build/template/sources/schema-source.js +64 -0
  194. package/build/template/sources/schema-source.js.map +1 -0
  195. package/package.json +16 -17
  196. package/src/api/api.ts +1 -0
  197. package/src/api/config/configurator.ts +86 -36
  198. package/src/api/config/merge.ts +0 -16
  199. package/src/api/content/metadata.ts +1 -1
  200. package/src/api/schema/data-sources/data-sources.ts +1 -0
  201. package/src/api/schema/data-sources/introspection/introspection.ts +213 -0
  202. package/src/api/schema/data-sources/memory/memory.ts +3 -5
  203. package/src/api/schema/data-sources/schema-directory/file-name-expression/file-name-expression.ts +29 -13
  204. package/src/api/schema/data-sources/schema-directory/schema-directory.ts +56 -16
  205. package/src/api/schema/data-sources/schema-file/schema-file.ts +16 -7
  206. package/src/api/schema/metadata.ts +23 -0
  207. package/src/api/schema/read.ts +109 -18
  208. package/src/api/schema/schema.ts +62 -2
  209. package/src/api/schema-source/index.ts +1 -0
  210. package/src/api/schema-source/schema-source.ts +189 -0
  211. package/src/api/static/manifest.ts +1 -1
  212. package/src/api/vite/plugins/build.ts +3 -0
  213. package/src/api/vite/plugins/core.ts +27 -22
  214. package/src/api/vite/plugins/main.ts +1 -9
  215. package/src/api/vite/plugins/schema-assets.ts +364 -0
  216. package/src/api/vite/plugins/serve.ts +15 -8
  217. package/src/cli/commands/open.ts +1 -1
  218. package/src/lib/grafaid/schema/schema.ts +1 -0
  219. package/src/lib/graphql-change/change-groups.ts +57 -0
  220. package/src/lib/kit-temp.ts +15 -2
  221. package/src/lib/mask/$.test.ts +3 -3
  222. package/src/lib/path-map/$.test.ts +22 -19
  223. package/src/lib/path-map/path-map.ts +3 -1
  224. package/src/lib/react-router-aid/react-router-aid.ts +12 -6
  225. package/src/project-data.ts +3 -11
  226. package/src/template/components/Changelog.tsx +16 -67
  227. package/src/template/components/CodeBlock.tsx +3 -5
  228. package/src/template/components/ComponentDispatch.tsx +42 -0
  229. package/src/template/components/ReferenceLink.tsx +34 -0
  230. package/src/template/components/TypeAnnotation.tsx +5 -7
  231. package/src/template/components/TypeFieldsLinkList.tsx +20 -23
  232. package/src/template/components/TypeIndex.tsx +10 -12
  233. package/src/template/components/VersionSelector.tsx +50 -0
  234. package/src/template/components/graphql/type-link.tsx +4 -3
  235. package/src/template/hooks/useVersionPath.ts +10 -0
  236. package/src/template/{components → layouts}/ChangelogLayout.tsx +1 -1
  237. package/src/template/layouts/index.ts +1 -0
  238. package/src/template/lib/fetch-text.ts +13 -0
  239. package/src/template/lib/polen-url.ts +20 -0
  240. package/src/template/lib/schema-utils/constants.ts +4 -0
  241. package/src/template/lib/schema-utils/schema-utils.ts +42 -0
  242. package/src/template/routes/changelog.tsx +19 -10
  243. package/src/template/routes/index.tsx +2 -2
  244. package/src/template/routes/pages.tsx +109 -0
  245. package/src/template/routes/reference.tsx +112 -12
  246. package/src/template/routes/root.tsx +11 -112
  247. package/src/template/server/app.ts +47 -14
  248. package/src/template/server/main.ts +9 -1
  249. package/src/template/server/ssg/generate.ts +2 -2
  250. package/src/template/server/ssg/get-route-paths.test.ts +132 -0
  251. package/src/template/server/ssg/get-route-paths.ts +91 -27
  252. package/src/template/sources/schema-source.ts +69 -0
  253. package/build/lib/graphql-document/$$.d.ts +0 -5
  254. package/build/lib/graphql-document/$$.d.ts.map +0 -1
  255. package/build/lib/graphql-document/$$.js +0 -5
  256. package/build/lib/graphql-document/$$.js.map +0 -1
  257. package/build/lib/graphql-document/$.d.ts +0 -2
  258. package/build/lib/graphql-document/$.d.ts.map +0 -1
  259. package/build/lib/graphql-document/$.js +0 -2
  260. package/build/lib/graphql-document/$.js.map +0 -1
  261. package/build/lib/graphql-document/analysis.d.ts +0 -44
  262. package/build/lib/graphql-document/analysis.d.ts.map +0 -1
  263. package/build/lib/graphql-document/analysis.js +0 -361
  264. package/build/lib/graphql-document/analysis.js.map +0 -1
  265. package/build/lib/graphql-document/components/GraphQLDocument.d.ts +0 -38
  266. package/build/lib/graphql-document/components/GraphQLDocument.d.ts.map +0 -1
  267. package/build/lib/graphql-document/components/GraphQLDocument.js +0 -151
  268. package/build/lib/graphql-document/components/GraphQLDocument.js.map +0 -1
  269. package/build/lib/graphql-document/components/GraphQLDocumentWithSchema.d.ts +0 -7
  270. package/build/lib/graphql-document/components/GraphQLDocumentWithSchema.d.ts.map +0 -1
  271. package/build/lib/graphql-document/components/GraphQLDocumentWithSchema.js +0 -27
  272. package/build/lib/graphql-document/components/GraphQLDocumentWithSchema.js.map +0 -1
  273. package/build/lib/graphql-document/components/GraphQLIdentifierPopover.d.ts +0 -33
  274. package/build/lib/graphql-document/components/GraphQLIdentifierPopover.d.ts.map +0 -1
  275. package/build/lib/graphql-document/components/GraphQLIdentifierPopover.js +0 -50
  276. package/build/lib/graphql-document/components/GraphQLIdentifierPopover.js.map +0 -1
  277. package/build/lib/graphql-document/components/IdentifierLink.d.ts +0 -39
  278. package/build/lib/graphql-document/components/IdentifierLink.d.ts.map +0 -1
  279. package/build/lib/graphql-document/components/IdentifierLink.js +0 -75
  280. package/build/lib/graphql-document/components/IdentifierLink.js.map +0 -1
  281. package/build/lib/graphql-document/components/graphql-document-styles.d.ts +0 -5
  282. package/build/lib/graphql-document/components/graphql-document-styles.d.ts.map +0 -1
  283. package/build/lib/graphql-document/components/graphql-document-styles.js +0 -144
  284. package/build/lib/graphql-document/components/graphql-document-styles.js.map +0 -1
  285. package/build/lib/graphql-document/components/index.d.ts +0 -5
  286. package/build/lib/graphql-document/components/index.d.ts.map +0 -1
  287. package/build/lib/graphql-document/components/index.js +0 -5
  288. package/build/lib/graphql-document/components/index.js.map +0 -1
  289. package/build/lib/graphql-document/example.d.ts +0 -25
  290. package/build/lib/graphql-document/example.d.ts.map +0 -1
  291. package/build/lib/graphql-document/example.js +0 -140
  292. package/build/lib/graphql-document/example.js.map +0 -1
  293. package/build/lib/graphql-document/graphql-document.d.ts +0 -35
  294. package/build/lib/graphql-document/graphql-document.d.ts.map +0 -1
  295. package/build/lib/graphql-document/graphql-document.js +0 -36
  296. package/build/lib/graphql-document/graphql-document.js.map +0 -1
  297. package/build/lib/graphql-document/hooks/use-tooltip-state.d.ts +0 -43
  298. package/build/lib/graphql-document/hooks/use-tooltip-state.d.ts.map +0 -1
  299. package/build/lib/graphql-document/hooks/use-tooltip-state.js +0 -132
  300. package/build/lib/graphql-document/hooks/use-tooltip-state.js.map +0 -1
  301. package/build/lib/graphql-document/positioning-simple.d.ts +0 -63
  302. package/build/lib/graphql-document/positioning-simple.d.ts.map +0 -1
  303. package/build/lib/graphql-document/positioning-simple.js +0 -185
  304. package/build/lib/graphql-document/positioning-simple.js.map +0 -1
  305. package/build/lib/graphql-document/schema-context.d.ts +0 -8
  306. package/build/lib/graphql-document/schema-context.d.ts.map +0 -1
  307. package/build/lib/graphql-document/schema-context.js +0 -11
  308. package/build/lib/graphql-document/schema-context.js.map +0 -1
  309. package/build/lib/graphql-document/schema-integration.d.ts +0 -135
  310. package/build/lib/graphql-document/schema-integration.d.ts.map +0 -1
  311. package/build/lib/graphql-document/schema-integration.js +0 -328
  312. package/build/lib/graphql-document/schema-integration.js.map +0 -1
  313. package/build/lib/graphql-document/types.d.ts +0 -117
  314. package/build/lib/graphql-document/types.d.ts.map +0 -1
  315. package/build/lib/graphql-document/types.js +0 -2
  316. package/build/lib/graphql-document/types.js.map +0 -1
  317. package/build/template/components/ChangelogLayout.d.ts.map +0 -1
  318. package/build/template/components/ChangelogLayout.js.map +0 -1
  319. package/build/template/components/CodeHikePre.d.ts +0 -16
  320. package/build/template/components/CodeHikePre.d.ts.map +0 -1
  321. package/build/template/components/CodeHikePre.js +0 -37
  322. package/build/template/components/CodeHikePre.js.map +0 -1
  323. package/build/template/routes/reference.$type.$field.d.ts +0 -5
  324. package/build/template/routes/reference.$type.$field.d.ts.map +0 -1
  325. package/build/template/routes/reference.$type.$field.js +0 -31
  326. package/build/template/routes/reference.$type.$field.js.map +0 -1
  327. package/build/template/routes/reference.$type.d.ts +0 -5
  328. package/build/template/routes/reference.$type.d.ts.map +0 -1
  329. package/build/template/routes/reference.$type.js +0 -23
  330. package/build/template/routes/reference.$type.js.map +0 -1
  331. package/src/lib/graphql-document/$$.ts +0 -4
  332. package/src/lib/graphql-document/$.test.ts +0 -132
  333. package/src/lib/graphql-document/$.ts +0 -1
  334. package/src/lib/graphql-document/README.md +0 -102
  335. package/src/lib/graphql-document/analysis.ts +0 -415
  336. package/src/lib/graphql-document/components/GraphQLDocument.tsx +0 -265
  337. package/src/lib/graphql-document/components/GraphQLDocument.unit.test.ts +0 -188
  338. package/src/lib/graphql-document/components/GraphQLDocumentWithSchema.tsx +0 -46
  339. package/src/lib/graphql-document/components/GraphQLIdentifierPopover.tsx +0 -199
  340. package/src/lib/graphql-document/components/IdentifierLink.tsx +0 -160
  341. package/src/lib/graphql-document/components/graphql-document-styles.ts +0 -144
  342. package/src/lib/graphql-document/components/index.ts +0 -4
  343. package/src/lib/graphql-document/demo.md +0 -155
  344. package/src/lib/graphql-document/example.ts +0 -163
  345. package/src/lib/graphql-document/graphql-document.ts +0 -37
  346. package/src/lib/graphql-document/hooks/use-tooltip-state.test.ts +0 -76
  347. package/src/lib/graphql-document/hooks/use-tooltip-state.ts +0 -191
  348. package/src/lib/graphql-document/positioning-simple.test.ts +0 -248
  349. package/src/lib/graphql-document/positioning-simple.ts +0 -260
  350. package/src/lib/graphql-document/schema-context.tsx +0 -20
  351. package/src/lib/graphql-document/schema-integration.test.ts +0 -365
  352. package/src/lib/graphql-document/schema-integration.ts +0 -488
  353. package/src/lib/graphql-document/types.ts +0 -129
  354. package/src/template/components/CodeHikePre.tsx +0 -51
  355. package/src/template/routes/reference.$type.$field.tsx +0 -34
  356. package/src/template/routes/reference.$type.tsx +0 -27
  357. /package/build/template/{components → layouts}/ChangelogLayout.d.ts +0 -0
@@ -0,0 +1,364 @@
1
+ import type { Config } from '#api/config/index'
2
+ import { SchemaAugmentation } from '#api/schema-augmentation/index'
3
+ import { createSchemaSource } from '#api/schema-source/index'
4
+ import { Schema } from '#api/schema/index'
5
+ import type { Vite } from '#dep/vite/index'
6
+ import { Grafaid } from '#lib/grafaid/index'
7
+ import { ViteVirtual } from '#lib/vite-virtual/index'
8
+ import { debugPolen } from '#singletons/debug'
9
+ import { Cache } from '@wollybeard/kit'
10
+ import * as NodeFs from 'node:fs/promises'
11
+ import * as NodePath from 'node:path'
12
+ import type { NonEmptyChangeSets } from '../../schema/schema.js'
13
+ import { polenVirtual } from '../vi.js'
14
+
15
+ export const viProjectSchemaMetadata = polenVirtual([`project`, `schema-metadata`])
16
+
17
+ /**
18
+ * Vite plugin that generates JSON assets for GraphQL schemas at build time.
19
+ *
20
+ * This plugin:
21
+ * - Reads GraphQL schema files from the project
22
+ * - Applies schema augmentations
23
+ * - Converts schemas to AST format and emits as JSON assets
24
+ * - Creates a metadata file with available versions
25
+ * - Provides a virtual module for accessing schema metadata
26
+ *
27
+ * The generated assets enable client-side loading of different schema versions
28
+ * without requiring all schemas to be bundled into the main JavaScript bundle.
29
+ *
30
+ * @param config - Polen configuration object
31
+ * @returns Vite plugin instance
32
+ */
33
+ export const SchemaAssets = (config: Config.Config): Vite.Plugin => {
34
+ const debug = debugPolen.sub(`vite-plugin:schema-assets`)
35
+ let viteServer: Vite.ViteDevServer | null = null
36
+
37
+ // Helper to load and process schema data
38
+ const loadAndProcessSchemaData = Cache.memoize(async () => {
39
+ const schemaResult = await Schema.readOrThrow({
40
+ ...config.schema,
41
+ projectRoot: config.paths.project.rootDir,
42
+ })
43
+
44
+ if (!schemaResult.data) {
45
+ const metadata: Schema.SchemaMetadata = { hasSchema: false, versions: [] }
46
+ return {
47
+ schemaData: null,
48
+ metadata,
49
+ source: schemaResult.source,
50
+ }
51
+ }
52
+
53
+ // Apply augmentations
54
+ schemaResult.data.forEach(version => {
55
+ SchemaAugmentation.apply(version.after, config.schemaAugmentations)
56
+ })
57
+
58
+ // Build metadata
59
+ const versionStrings: string[] = []
60
+ for (const [index, version] of schemaResult.data.entries()) {
61
+ const versionName = index === 0 ? Schema.VERSION_LATEST : Schema.dateToVersionString(version.date)
62
+ versionStrings.push(versionName)
63
+ }
64
+
65
+ const metadata = {
66
+ hasSchema: true,
67
+ versions: versionStrings,
68
+ }
69
+
70
+ debug(`schemaDataLoaded`, { versionCount: schemaResult.data.length })
71
+
72
+ return {
73
+ schemaData: schemaResult.data,
74
+ metadata,
75
+ source: schemaResult.source,
76
+ }
77
+ })
78
+
79
+ // Helper to create schema source with filesystem IO
80
+ const createDevSchemaSource = (metadata: Schema.SchemaMetadata) => {
81
+ return createSchemaSource({
82
+ io: {
83
+ read: async () => {
84
+ throw new Error('Read not supported in dev asset writer')
85
+ },
86
+ write: async (path: string, content: string) => {
87
+ await NodeFs.writeFile(path, content, 'utf-8')
88
+ },
89
+ clearDirectory: async (path: string) => {
90
+ try {
91
+ const files = await NodeFs.readdir(path)
92
+ await Promise.all(files.map(file => NodeFs.rm(NodePath.join(path, file), { force: true })))
93
+ } catch (error) {
94
+ // Directory might not exist, which is fine
95
+ }
96
+ },
97
+ removeFile: async (path: string) => {
98
+ await NodeFs.rm(path, { force: true })
99
+ },
100
+ },
101
+ versions: metadata.versions,
102
+ assetsPath: config.paths.framework.devAssets.absolute,
103
+ })
104
+ }
105
+
106
+ // Helper to write assets using schema-source API
107
+ const writeDevAssets = async (
108
+ schemaData: NonEmptyChangeSets,
109
+ metadata: Schema.SchemaMetadata,
110
+ ) => {
111
+ // schemaData is now guaranteed to be non-null NonEmptyChangeSets
112
+
113
+ const devAssetsDir = config.paths.framework.devAssets.schemas
114
+ await NodeFs.mkdir(devAssetsDir, { recursive: true })
115
+
116
+ const schemaSource = createDevSchemaSource(metadata)
117
+ await schemaSource.writeAllAssets(schemaData, metadata)
118
+ debug(`devAssetsWritten`, { versionCount: schemaData.length })
119
+ }
120
+
121
+ return {
122
+ name: `polen:schema-assets`,
123
+
124
+ configureServer(server) {
125
+ viteServer = server
126
+
127
+ // Clear all assets when dev server starts
128
+ const clearAssets = async () => {
129
+ try {
130
+ // Create a basic schema source just for clearing
131
+ const schemaSource = createDevSchemaSource({ hasSchema: false, versions: [] })
132
+ await schemaSource.clearAllAssets()
133
+ debug(`devAssetsCleared`, {})
134
+ } catch (error) {
135
+ // Ignore errors during clearing
136
+ }
137
+ }
138
+
139
+ // Clear assets immediately
140
+ void clearAssets()
141
+
142
+ // Set up file watching for schema source files
143
+ if (config.schema?.dataSources?.directory?.path) {
144
+ // Watch the entire directory for directory mode
145
+ server.watcher.add(config.schema.dataSources.directory.path)
146
+ debug(`watchingSchemaDirectory`, { path: config.schema.dataSources.directory.path })
147
+ }
148
+
149
+ if (config.schema?.dataSources?.file?.path) {
150
+ // Watch the specific file for file mode
151
+ server.watcher.add(config.schema.dataSources.file.path)
152
+ debug(`watchingSchemaFile`, { path: config.schema.dataSources.file.path })
153
+ }
154
+
155
+ if (config.schema?.dataSources?.introspection?.url) {
156
+ // Watch the introspection file if introspection is configured
157
+ const introspectionFilePath = NodePath.join(config.paths.project.rootDir, `schema.introspection.json`)
158
+ server.watcher.add(introspectionFilePath)
159
+ debug(`watchingIntrospectionFile`, { path: introspectionFilePath })
160
+ }
161
+
162
+ // Handle file removal
163
+ server.watcher.on('unlink', async (file) => {
164
+ const isSchemaFile = config.schema && (() => {
165
+ const absoluteFile = NodePath.resolve(file)
166
+
167
+ // Check if file path matches the configured schema file
168
+ if (config.schema.dataSources?.file?.path) {
169
+ const absoluteSchemaFile = NodePath.resolve(
170
+ config.paths.project.rootDir,
171
+ config.schema.dataSources.file.path,
172
+ )
173
+ if (absoluteFile === absoluteSchemaFile) return true
174
+ }
175
+
176
+ // Check if file path is within the configured schema directory
177
+ if (config.schema.dataSources?.directory?.path) {
178
+ const absoluteSchemaDir = NodePath.resolve(
179
+ config.paths.project.rootDir,
180
+ config.schema.dataSources.directory.path,
181
+ )
182
+ if (absoluteFile.startsWith(absoluteSchemaDir + NodePath.sep)) return true
183
+ }
184
+
185
+ // Check if file is the introspection file
186
+ if (config.schema.dataSources?.introspection?.url) {
187
+ const absoluteIntrospectionFile = NodePath.resolve(
188
+ config.paths.project.rootDir,
189
+ `schema.introspection.json`,
190
+ )
191
+ if (absoluteFile === absoluteIntrospectionFile) return true
192
+ }
193
+
194
+ return false
195
+ })()
196
+
197
+ if (isSchemaFile) {
198
+ debug(`schemaFileRemoved`, { file })
199
+
200
+ try {
201
+ // Clear cache and regenerate
202
+ loadAndProcessSchemaData.clear()
203
+ const { schemaData, metadata, source } = await loadAndProcessSchemaData()
204
+
205
+ // If file was deleted but can be recreated, attempt recreation
206
+ if (!schemaData && source.reCreate) {
207
+ debug(`attemptingSchemaRecreation`, { sourceType: source.type })
208
+ try {
209
+ const recreatedData = await source.reCreate()
210
+ if (recreatedData) {
211
+ // Clear cache again and reload after recreation
212
+ loadAndProcessSchemaData.clear()
213
+ const reloadResult = await loadAndProcessSchemaData()
214
+ if (reloadResult.schemaData) {
215
+ await writeDevAssets(reloadResult.schemaData, reloadResult.metadata)
216
+ debug(`hmr:schemaRecreatedAndWritten`, { versionCount: reloadResult.schemaData.length })
217
+ }
218
+ } else {
219
+ debug(`hmr:schemaRecreationFailed`, { reason: 'reCreate returned null' })
220
+ }
221
+ } catch (recreationError) {
222
+ debug(`hmr:schemaRecreationFailed`, { error: recreationError })
223
+ }
224
+ } else if (schemaData) {
225
+ // Write new assets without the removed file
226
+ await writeDevAssets(schemaData, metadata)
227
+ debug(`hmr:schemaAssetsUpdatedAfterRemoval`, { versionCount: schemaData.length })
228
+ } else {
229
+ // No schema data and cannot recreate - clear all assets
230
+ const schemaSource = createDevSchemaSource({ hasSchema: false, versions: [] })
231
+ await schemaSource.clearAllAssets()
232
+ debug(`hmr:allAssetsCleared`, {})
233
+ }
234
+ } catch (error) {
235
+ debug(`hmr:schemaRemovalFailed`, { error })
236
+ }
237
+
238
+ // Send HMR invalidation signal
239
+ server.ws.send({
240
+ type: 'custom',
241
+ event: 'polen:schema-invalidate',
242
+ data: { timestamp: Date.now() },
243
+ })
244
+
245
+ debug(`hmr:schemaInvalidationSent`, {})
246
+ }
247
+ })
248
+ },
249
+
250
+ async buildStart() {
251
+ debug(`buildStart`, {})
252
+
253
+ // Load and process schema data
254
+ const { schemaData, metadata } = await loadAndProcessSchemaData()
255
+
256
+ if (!schemaData) {
257
+ debug(`noSchemaFound`, {})
258
+ return
259
+ }
260
+
261
+ // Handle asset generation differently for dev vs build
262
+ if (viteServer) {
263
+ // Dev mode: Write assets directly to filesystem
264
+ await writeDevAssets(schemaData, metadata)
265
+ debug(`devMode:schemaAssetsWritten`, {})
266
+ return
267
+ }
268
+
269
+ // Build mode: Create schema source for emitting files
270
+ const schemaSource = createSchemaSource({
271
+ io: {
272
+ read: async () => {
273
+ throw new Error('Read not supported in build asset emitter')
274
+ },
275
+ write: async (path: string, content: string) => {
276
+ // Convert absolute path to relative filename for Vite
277
+ const relativePath = NodePath.relative(config.paths.framework.devAssets.absolute, path)
278
+ const fileName = `${config.paths.project.relative.build.relative.assets.root}/${relativePath}`
279
+
280
+ this.emitFile({
281
+ type: `asset`,
282
+ fileName,
283
+ source: content,
284
+ })
285
+ },
286
+ },
287
+ versions: metadata.versions,
288
+ assetsPath: config.paths.framework.devAssets.absolute,
289
+ })
290
+
291
+ // Emit all assets using the high-level API
292
+ await schemaSource.writeAllAssets(schemaData, metadata)
293
+ debug(`buildMode:allAssetsEmitted`, { versionCount: schemaData.length })
294
+ },
295
+
296
+ async handleHotUpdate({ file, server }) {
297
+ const isSchemaFile = config.schema && (() => {
298
+ const absoluteFile = NodePath.resolve(file)
299
+
300
+ // Check if file path matches the configured schema file
301
+ if (config.schema.dataSources?.file?.path) {
302
+ const absoluteSchemaFile = NodePath.resolve(config.paths.project.rootDir, config.schema.dataSources.file.path)
303
+ if (absoluteFile === absoluteSchemaFile) return true
304
+ }
305
+
306
+ // Check if file path is within the configured schema directory
307
+ if (config.schema.dataSources?.directory?.path) {
308
+ const absoluteSchemaDir = NodePath.resolve(
309
+ config.paths.project.rootDir,
310
+ config.schema.dataSources.directory.path,
311
+ )
312
+ if (absoluteFile.startsWith(absoluteSchemaDir + NodePath.sep)) return true
313
+ }
314
+
315
+ // Check if file is the introspection file
316
+ if (config.schema.dataSources?.introspection?.url) {
317
+ const absoluteIntrospectionFile = NodePath.resolve(
318
+ config.paths.project.rootDir,
319
+ `schema.introspection.json`,
320
+ )
321
+ if (absoluteFile === absoluteIntrospectionFile) return true
322
+ }
323
+
324
+ return false
325
+ })()
326
+ if (isSchemaFile) {
327
+ debug(`schemaFileChanged`, { file })
328
+
329
+ // Regenerate schema assets
330
+ try {
331
+ loadAndProcessSchemaData.clear()
332
+ const { schemaData, metadata } = await loadAndProcessSchemaData()
333
+
334
+ if (schemaData) {
335
+ debug(`hmr:schemaRegenerated`, { versionCount: schemaData.length })
336
+
337
+ // Write new assets to filesystem
338
+ await writeDevAssets(schemaData, metadata)
339
+ }
340
+ } catch (error) {
341
+ debug(`hmr:schemaRegenerationFailed`, { error })
342
+ }
343
+
344
+ // Send HMR invalidation signal
345
+ server.ws.send({
346
+ type: 'custom',
347
+ event: 'polen:schema-invalidate',
348
+ data: { timestamp: Date.now() },
349
+ })
350
+
351
+ debug(`hmr:schemaInvalidationSent`, {})
352
+ }
353
+ },
354
+
355
+ ...ViteVirtual.IdentifiedLoader.toHooks({
356
+ identifier: viProjectSchemaMetadata,
357
+ async loader() {
358
+ debug(`virtualModuleLoad`, { id: viProjectSchemaMetadata.id })
359
+ const { metadata } = await loadAndProcessSchemaData()
360
+ return `export default ${JSON.stringify(metadata)}`
361
+ },
362
+ }),
363
+ }
364
+ }
@@ -5,16 +5,10 @@ import type { Vite } from '#dep/vite/index'
5
5
  import { createHtmlTransformer } from '#lib/html-utils/html-transformer'
6
6
  import { ResponseInternalServerError } from '#lib/kit-temp'
7
7
  import { debugPolen } from '#singletons/debug'
8
+ import type { App, AppOptions } from '#template/server/app'
8
9
  import * as HonoNodeServer from '@hono/node-server'
9
10
  import { Err } from '@wollybeard/kit'
10
-
11
- type App = Hono.Hono
12
-
13
- interface AppOptions {
14
- hooks?: {
15
- transformHtml?: ((html: string, ctx: Hono.Context) => Promise<string> | string)[]
16
- }
17
- }
11
+ import * as NodePath from 'node:path'
18
12
 
19
13
  interface AppServerModule {
20
14
  createApp: (options: AppOptions) => App
@@ -80,6 +74,19 @@ export const Serve = (
80
74
  }),
81
75
  ],
82
76
  },
77
+ paths: {
78
+ base: config.build.base,
79
+ assets: {
80
+ // Calculate relative path from CWD to Polen's assets
81
+ // CWD is user's project directory where they run 'pnpm dev'
82
+ // Assets are in Polen's dev assets directory
83
+ directory: NodePath.relative(
84
+ process.cwd(),
85
+ config.paths.framework.devAssets.absolute,
86
+ ),
87
+ route: config.server.routes.assets,
88
+ },
89
+ },
83
90
  })
84
91
  })
85
92
  .catch(async (error) => {
@@ -132,7 +132,7 @@ const wrapCache = <fn extends Fn.AnyAnyAsync>(fn: fn): fn => {
132
132
 
133
133
  // todo: use a proper validation, e.g. zod, better yet: allow to specify the validation in molt itself
134
134
  const parseHeaders = (headersJsonEncoded: string): Record<string, string> => {
135
- const headersJson = Json.codec.deserialize(headersJsonEncoded)
135
+ const headersJson = Json.codec.decode(headersJsonEncoded)
136
136
  if (!Rec.is(headersJson)) {
137
137
  console.log(`--introspection-headers must be a JSON object.`)
138
138
  process.exit(1)
@@ -4,6 +4,7 @@ export {
4
4
  buildASTSchema as fromAST,
5
5
  buildClientSchema as fromIntrospectionQuery,
6
6
  GraphQLSchema as Schema,
7
+ introspectionFromSchema as toIntrospectionQuery,
7
8
  printSchema as print,
8
9
  } from 'graphql'
9
10
 
@@ -1,3 +1,4 @@
1
+ import { neverCase } from '@wollybeard/kit/language'
1
2
  import type {
2
3
  Change,
3
4
  DirectiveAddedChange,
@@ -248,3 +249,59 @@ export type DirectiveUsage =
248
249
  | DirectiveUsageInputFieldDefinitionRemovedChange
249
250
 
250
251
  export const isDirectiveUsage = (change: Change): change is DirectiveUsage => change.type.startsWith(`DIRECTIVE_USAGE_`)
252
+
253
+ export type Type =
254
+ | 'TypeOperation'
255
+ | 'TypeDescription'
256
+ | 'FieldOperation'
257
+ | 'FieldDescription'
258
+ | 'FieldDeprecation'
259
+ | 'FieldDeprecationReason'
260
+ | 'FieldArgumentOperation'
261
+ | 'FieldArgument'
262
+ | 'FieldArgumentDescription'
263
+ | 'EnumValueOperation'
264
+ | 'EnumValueDescription'
265
+ | 'EnumValueDeprecationReason'
266
+ | 'InputFieldOperation'
267
+ | 'InputFieldDescription'
268
+ | 'InputFieldDefaultValue'
269
+ | 'UnionMemberOperation'
270
+ | 'ObjectTypeInterfaceOperation'
271
+ | 'DirectiveOperation'
272
+ | 'DirectiveDescription'
273
+ | 'DirectiveLocationOperation'
274
+ | 'DirectiveArgumentOperation'
275
+ | 'DirectiveArgument'
276
+ | 'DirectiveArgumentDescription'
277
+ | 'SchemaRootType'
278
+ | 'DirectiveUsage'
279
+
280
+ export const getType = (change: Change): Type => {
281
+ if (isTypeOperation(change)) return 'TypeOperation'
282
+ if (isTypeDescription(change)) return 'TypeDescription'
283
+ if (isFieldOperation(change)) return 'FieldOperation'
284
+ if (isFieldDescription(change)) return 'FieldDescription'
285
+ if (isFieldDeprecation(change)) return 'FieldDeprecation'
286
+ if (isFieldDeprecationReason(change)) return 'FieldDeprecationReason'
287
+ if (isFieldArgumentOperation(change)) return 'FieldArgumentOperation'
288
+ if (isFieldArgument(change)) return 'FieldArgument'
289
+ if (isFieldArgumentDescription(change)) return 'FieldArgumentDescription'
290
+ if (isEnumValueOperation(change)) return 'EnumValueOperation'
291
+ if (isEnumValueDescription(change)) return 'EnumValueDescription'
292
+ if (isEnumValueDeprecationReason(change)) return 'EnumValueDeprecationReason'
293
+ if (isInputFieldOperation(change)) return 'InputFieldOperation'
294
+ if (isInputFieldDescription(change)) return 'InputFieldDescription'
295
+ if (isInputFieldDefaultValue(change)) return 'InputFieldDefaultValue'
296
+ if (isUnionMemberOperation(change)) return 'UnionMemberOperation'
297
+ if (isObjectTypeInterfaceOperation(change)) return 'ObjectTypeInterfaceOperation'
298
+ if (isDirectiveOperation(change)) return 'DirectiveOperation'
299
+ if (isDirectiveDescription(change)) return 'DirectiveDescription'
300
+ if (isDirectiveLocationOperation(change)) return 'DirectiveLocationOperation'
301
+ if (isDirectiveArgumentOperation(change)) return 'DirectiveArgumentOperation'
302
+ if (isDirectiveArgument(change)) return 'DirectiveArgument'
303
+ if (isDirectiveArgumentDescription(change)) return 'DirectiveArgumentDescription'
304
+ if (isSchemaRootType(change)) return 'SchemaRootType'
305
+ if (isDirectiveUsage(change)) return 'DirectiveUsage'
306
+ neverCase(change)
307
+ }
@@ -105,9 +105,9 @@ export const objPolicyFilter = <
105
105
  const result: any = mode === `deny` ? { ...obj } : {}
106
106
 
107
107
  if (mode === `allow`) {
108
- // For allow mode, only add specified keys
108
+ // For allow mode, only add specified keys that are own properties
109
109
  for (const key of keys) {
110
- if (key in obj) {
110
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
111
111
  // @ts-expect-error
112
112
  result[key] = obj[key]
113
113
  }
@@ -181,6 +181,19 @@ export const ensureEnd = (string: string, ending: string) => {
181
181
  return string + ending
182
182
  }
183
183
 
184
+ /**
185
+ * Create a generic cache with clear interface
186
+ */
187
+ export const createCache = <T>() => {
188
+ const cache = new Map<string, T>()
189
+ return {
190
+ has: (key: string) => cache.has(key),
191
+ get: (key: string) => cache.get(key),
192
+ set: (key: string, value: T) => cache.set(key, value),
193
+ clear: () => cache.clear(),
194
+ }
195
+ }
196
+
184
197
  export const ResponseInternalServerError = () =>
185
198
  new Response(null, {
186
199
  status: Http.Status.InternalServerError.code,
@@ -113,9 +113,9 @@ describe('property-based tests', () => {
113
113
  // Result contains only keys that were in both mask and object
114
114
  expect(resultKeys.every(key => keys.includes(key))).toBe(true)
115
115
 
116
- // All requested keys that exist in obj are in result
116
+ // All requested keys that are own properties of obj are in result
117
117
  keys.forEach(key => {
118
- if (key in obj) {
118
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
119
119
  expect(result).toHaveProperty(key, (obj as any)[key])
120
120
  }
121
121
  })
@@ -169,7 +169,7 @@ describe('property-based tests', () => {
169
169
  const result = Mask.apply(obj as any, Mask.create(keys))
170
170
 
171
171
  keys.forEach(key => {
172
- if (key in obj) {
172
+ if (Object.prototype.hasOwnProperty.call(obj, key)) {
173
173
  expect(result).toHaveProperty(key)
174
174
  expect((result as any)[key]).toBe((obj as any)[key])
175
175
  }
@@ -197,6 +197,22 @@ describe('PathMap', () => {
197
197
  })
198
198
 
199
199
  describe('property tests', () => {
200
+ // Helper to normalize base paths the same way PathMap.create does
201
+ const normalizeBasePath = (base: string): string => {
202
+ const trimmedBase = base.trim()
203
+ const collapsedBase = trimmedBase.replace(/\/+/g, '/')
204
+ const cleanedBase = collapsedBase === '/.' ? '/' : collapsedBase
205
+ return cleanedBase === '/' ? '/' : cleanedBase.replace(/\/$/, '')
206
+ }
207
+
208
+ // Helper to build absolute paths with proper handling of root base
209
+ const buildAbsolutePath = (normalizedBase: string, segments: string[]): string => {
210
+ if (segments.length === 0) return normalizedBase
211
+ return normalizedBase === '/'
212
+ ? `/${segments.join('/')}`
213
+ : `${normalizedBase}/${segments.join('/')}`
214
+ }
215
+
200
216
  // Arbitrary for valid path segments
201
217
  const pathSegment = fc.stringMatching(/^[a-zA-Z0-9_-]+$/)
202
218
 
@@ -243,10 +259,7 @@ describe('PathMap', () => {
243
259
  fc.assert(
244
260
  fc.property(pathInput, fc.string({ minLength: 1 }).filter(s => s.startsWith('/')), (input, base) => {
245
261
  const paths = PathMap.create(input, base)
246
-
247
- // Base is normalized (trimmed, multiple slashes collapsed, trailing removed)
248
- const collapsedBase = base.trim().replace(/\/+/g, '/')
249
- const normalizedBase = collapsedBase === '/' ? '/' : collapsedBase.replace(/\/$/, '')
262
+ const normalizedBase = normalizeBasePath(base)
250
263
 
251
264
  function checkAbsolute(obj: any) {
252
265
  for (const [key, value] of Object.entries(obj)) {
@@ -278,14 +291,11 @@ describe('PathMap', () => {
278
291
  expect(JSON.stringify(p1.rooted)).toBe(JSON.stringify(p2.rooted))
279
292
 
280
293
  // Only absolute paths and base should change
281
- const collapsedBase2 = base2.trim().replace(/\/+/g, '/')
282
- const normalizedBase2 = collapsedBase2 === '/' ? '/' : collapsedBase2.replace(/\/$/, '')
283
- expect(p2.base).toBe(normalizedBase2)
284
-
294
+ // Use the normalized base from the PathMap itself
285
295
  function checkBase(obj: any) {
286
296
  for (const [key, value] of Object.entries(obj)) {
287
297
  if (typeof value === 'string') {
288
- expect(value.startsWith(normalizedBase2)).toBe(true)
298
+ expect(value.startsWith(p2.base)).toBe(true)
289
299
  } else if (typeof value === 'object') {
290
300
  checkBase(value)
291
301
  }
@@ -309,20 +319,13 @@ describe('PathMap', () => {
309
319
  if (currentPath.length === 0) {
310
320
  expect(rel.$).toBe('.')
311
321
  expect(rooted.$).toBe('.')
312
- // Base is normalized in create() (trimmed, collapsed, trailing removed)
313
- const collapsedBase = base.trim().replace(/\/+/g, '/')
314
- const normalizedBase = collapsedBase === '/' ? '/' : collapsedBase.replace(/\/$/, '')
322
+ const normalizedBase = normalizeBasePath(base)
315
323
  expect(abs.$).toBe(normalizedBase)
316
324
  } else {
317
325
  expect(rel.$).toBe(currentPath[currentPath.length - 1])
318
326
  expect(rooted.$).toBe(currentPath.join('/'))
319
- // Handle base that might be '/' or have trailing slash
320
- // Note: create() normalizes the base (trim + collapse + remove trailing)
321
- const collapsedBase = base.trim().replace(/\/+/g, '/')
322
- const normalizedBase = collapsedBase === '/' ? '/' : collapsedBase.replace(/\/$/, '')
323
- const expectedAbs = normalizedBase === '/'
324
- ? `/${currentPath.join('/')}`
325
- : `${normalizedBase}/${currentPath.join('/')}`
327
+ const normalizedBase = normalizeBasePath(base)
328
+ const expectedAbs = buildAbsolutePath(normalizedBase, currentPath)
326
329
  expect(abs.$).toBe(expectedAbs)
327
330
  }
328
331
  }
@@ -113,7 +113,9 @@ export function create<T extends PathInput>(paths: T, base?: string): RelativePa
113
113
  const trimmedBase = base.trim()
114
114
  // Collapse multiple slashes to single, then remove trailing (unless it's just "/")
115
115
  const collapsedBase = trimmedBase.replace(/\/+/g, `/`)
116
- const normalizedBase = collapsedBase === `/` ? `/` : collapsedBase.replace(/\/$/, ``)
116
+ // Handle edge case where base is "/." - this should become "/"
117
+ const cleanedBase = collapsedBase === `/.` ? `/` : collapsedBase
118
+ const normalizedBase = cleanedBase === `/` ? `/` : cleanedBase.replace(/\/$/, ``)
117
119
 
118
120
  const rooted = processRootedPaths(paths, [])
119
121
  const absolute = processAbsolutePaths(paths, normalizedBase, [])
@@ -1,4 +1,5 @@
1
1
  import type { ReactRouter } from '#dep/react-router/index'
2
+ import type { React } from '#dep/react/index'
2
3
  import type { Http } from '@wollybeard/kit'
3
4
 
4
5
  export * from './get-paths-patterns.js'
@@ -18,23 +19,28 @@ export interface RouteHandle {
18
19
  statusCode?: Http.Status.Code.All
19
20
  }
20
21
 
21
- export const createRoute = <routeObject extends RouteObject>(
22
+ export const route = <routeObject extends RouteObject>(
22
23
  routeObject: routeObject,
23
24
  ): routeObject => {
24
25
  return {
25
- id: routeObject.path,
26
26
  ...routeObject,
27
27
  }
28
28
  }
29
29
 
30
- export type RouteObjectIndexInput = Omit<RouteObjectIndex, `index` | `children`>
30
+ export type RouteObjectIndexInput = RouteObjectIndexInputConfig | React.ComponentType
31
+ export type RouteObjectIndexInputConfig = Omit<RouteObjectIndex, `index` | `children`>
31
32
 
32
- export const createRouteIndex = (
33
- indexRouteObjectInput: RouteObjectIndexInput,
33
+ export const routeIndex = (
34
+ input: RouteObjectIndexInput,
34
35
  ): RouteObjectIndex => {
36
+ const routeConfig: RouteObjectIndexInputConfig = isComponentType(input) ? { Component: input } : input
35
37
  return {
36
- ...indexRouteObjectInput,
38
+ ...routeConfig,
37
39
  index: true,
38
40
  children: undefined,
39
41
  }
40
42
  }
43
+
44
+ const isComponentType = (value: unknown): value is React.ComponentType => {
45
+ return typeof value === 'function'
46
+ }