@carlonicora/nextjs-jsonapi 1.109.0 → 1.111.0

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 (268) hide show
  1. package/dist/{AssistantMessageInterface-Cs1yb-gF.d.ts → AssistantMessageInterface-BNzf1etU.d.ts} +14 -1
  2. package/dist/{AssistantMessageInterface-DQ3mH5L8.d.mts → AssistantMessageInterface-DrgHDjZ5.d.mts} +14 -1
  3. package/dist/{BlockNoteEditor-3XYBZLWO.js → BlockNoteEditor-7OKW6HHN.js} +19 -20
  4. package/dist/BlockNoteEditor-7OKW6HHN.js.map +1 -0
  5. package/dist/{BlockNoteEditor-EBFZG7AL.mjs → BlockNoteEditor-K7IIWM3S.mjs} +4 -5
  6. package/dist/{BlockNoteEditor-EBFZG7AL.mjs.map → BlockNoteEditor-K7IIWM3S.mjs.map} +1 -1
  7. package/dist/BlockNoteViewer-OPSCTHKJ.mjs +31 -0
  8. package/dist/BlockNoteViewer-OPSCTHKJ.mjs.map +1 -0
  9. package/dist/BlockNoteViewer-UW5VZ5UF.js +31 -0
  10. package/dist/BlockNoteViewer-UW5VZ5UF.js.map +1 -0
  11. package/dist/billing/index.d.mts +41 -41
  12. package/dist/billing/index.d.ts +41 -41
  13. package/dist/billing/index.js +346 -347
  14. package/dist/billing/index.js.map +1 -1
  15. package/dist/billing/index.mjs +3 -4
  16. package/dist/billing/index.mjs.map +1 -1
  17. package/dist/{chunk-7E3O52U5.js → chunk-6XWW67F2.js} +25 -12
  18. package/dist/chunk-6XWW67F2.js.map +1 -0
  19. package/dist/{chunk-UHO3KUUH.js → chunk-AKXUNE3A.js} +977 -850
  20. package/dist/chunk-AKXUNE3A.js.map +1 -0
  21. package/dist/{chunk-UOYIWJEJ.mjs → chunk-CWVYU4YZ.mjs} +18 -5
  22. package/dist/{chunk-UOYIWJEJ.mjs.map → chunk-CWVYU4YZ.mjs.map} +1 -1
  23. package/dist/{chunk-CRTVAQEK.mjs → chunk-TXVVZLUQ.mjs} +1388 -1261
  24. package/dist/chunk-TXVVZLUQ.mjs.map +1 -0
  25. package/dist/{chunk-CFI4WZ5R.js → chunk-U2HR57MY.js} +111 -5
  26. package/dist/chunk-U2HR57MY.js.map +1 -0
  27. package/dist/chunk-WPAQRB5Q.mjs +7 -0
  28. package/dist/chunk-WPAQRB5Q.mjs.map +1 -0
  29. package/dist/chunk-YBZVWLPH.js +7 -0
  30. package/dist/chunk-YBZVWLPH.js.map +1 -0
  31. package/dist/{chunk-MSNNAHDB.mjs → chunk-ZYPNVEHB.mjs} +112 -6
  32. package/dist/{chunk-MSNNAHDB.mjs.map → chunk-ZYPNVEHB.mjs.map} +1 -1
  33. package/dist/client/index.d.mts +3 -4
  34. package/dist/client/index.d.ts +3 -4
  35. package/dist/client/index.js +4 -5
  36. package/dist/client/index.js.map +1 -1
  37. package/dist/client/index.mjs +3 -4
  38. package/dist/components/index.d.mts +418 -415
  39. package/dist/components/index.d.ts +418 -415
  40. package/dist/components/index.js +6 -5
  41. package/dist/components/index.js.map +1 -1
  42. package/dist/components/index.mjs +5 -4
  43. package/dist/{config-CN23v3eJ.d.ts → config-BrkU_Ynz.d.ts} +2 -2
  44. package/dist/{config-gh88Qn4h.d.mts → config-snd2ToEB.d.mts} +2 -2
  45. package/dist/contexts/index.d.mts +15 -15
  46. package/dist/contexts/index.d.ts +15 -15
  47. package/dist/contexts/index.js +4 -5
  48. package/dist/contexts/index.js.map +1 -1
  49. package/dist/contexts/index.mjs +3 -4
  50. package/dist/core/index.d.mts +35 -4
  51. package/dist/core/index.d.ts +35 -4
  52. package/dist/core/index.js +2 -2
  53. package/dist/core/index.mjs +1 -1
  54. package/dist/features/help/index.d.mts +25 -66
  55. package/dist/features/help/index.d.ts +25 -66
  56. package/dist/features/help/index.js +114 -124
  57. package/dist/features/help/index.js.map +1 -1
  58. package/dist/features/help/index.mjs +95 -105
  59. package/dist/features/help/index.mjs.map +1 -1
  60. package/dist/features/help/server.d.mts +27 -65
  61. package/dist/features/help/server.d.ts +27 -65
  62. package/dist/features/help/server.js +4 -119
  63. package/dist/features/help/server.js.map +1 -1
  64. package/dist/features/help/server.mjs +4 -119
  65. package/dist/features/help/server.mjs.map +1 -1
  66. package/dist/help-content-config.interface-C5ESIod9.d.mts +13 -0
  67. package/dist/help-content-config.interface-C5ESIod9.d.ts +13 -0
  68. package/dist/index.d.mts +3 -3
  69. package/dist/index.d.ts +3 -3
  70. package/dist/index.js +3 -4
  71. package/dist/index.js.map +1 -1
  72. package/dist/index.mjs +2 -3
  73. package/dist/scripts/generate-web-module/__tests__/container.spec.d.ts +2 -0
  74. package/dist/scripts/generate-web-module/__tests__/container.spec.d.ts.map +1 -0
  75. package/dist/scripts/generate-web-module/__tests__/container.spec.js +54 -0
  76. package/dist/scripts/generate-web-module/__tests__/container.spec.js.map +1 -0
  77. package/dist/scripts/generate-web-module/__tests__/data-service.spec.d.ts +2 -0
  78. package/dist/scripts/generate-web-module/__tests__/data-service.spec.d.ts.map +1 -0
  79. package/dist/scripts/generate-web-module/__tests__/data-service.spec.js +19 -0
  80. package/dist/scripts/generate-web-module/__tests__/data-service.spec.js.map +1 -0
  81. package/dist/scripts/generate-web-module/__tests__/editor.spec.d.ts +2 -0
  82. package/dist/scripts/generate-web-module/__tests__/editor.spec.d.ts.map +1 -0
  83. package/dist/scripts/generate-web-module/__tests__/editor.spec.js +35 -0
  84. package/dist/scripts/generate-web-module/__tests__/editor.spec.js.map +1 -0
  85. package/dist/scripts/generate-web-module/__tests__/fixtures.d.ts +4 -0
  86. package/dist/scripts/generate-web-module/__tests__/fixtures.d.ts.map +1 -0
  87. package/dist/scripts/generate-web-module/__tests__/fixtures.js +45 -0
  88. package/dist/scripts/generate-web-module/__tests__/fixtures.js.map +1 -0
  89. package/dist/scripts/generate-web-module/__tests__/model-interface.spec.d.ts +2 -0
  90. package/dist/scripts/generate-web-module/__tests__/model-interface.spec.d.ts.map +1 -0
  91. package/dist/scripts/generate-web-module/__tests__/model-interface.spec.js +74 -0
  92. package/dist/scripts/generate-web-module/__tests__/model-interface.spec.js.map +1 -0
  93. package/dist/scripts/generate-web-module/__tests__/plumbing.spec.d.ts +2 -0
  94. package/dist/scripts/generate-web-module/__tests__/plumbing.spec.d.ts.map +1 -0
  95. package/dist/scripts/generate-web-module/__tests__/plumbing.spec.js +21 -0
  96. package/dist/scripts/generate-web-module/__tests__/plumbing.spec.js.map +1 -0
  97. package/dist/scripts/generate-web-module/__tests__/selector.spec.d.ts +2 -0
  98. package/dist/scripts/generate-web-module/__tests__/selector.spec.d.ts.map +1 -0
  99. package/dist/scripts/generate-web-module/__tests__/selector.spec.js +25 -0
  100. package/dist/scripts/generate-web-module/__tests__/selector.spec.js.map +1 -0
  101. package/dist/scripts/generate-web-module/__tests__/table-module-list.spec.d.ts +2 -0
  102. package/dist/scripts/generate-web-module/__tests__/table-module-list.spec.d.ts.map +1 -0
  103. package/dist/scripts/generate-web-module/__tests__/table-module-list.spec.js +55 -0
  104. package/dist/scripts/generate-web-module/__tests__/table-module-list.spec.js.map +1 -0
  105. package/dist/scripts/generate-web-module/generator.d.ts.map +1 -1
  106. package/dist/scripts/generate-web-module/generator.js +14 -11
  107. package/dist/scripts/generate-web-module/generator.js.map +1 -1
  108. package/dist/scripts/generate-web-module/templates/components/container.template.d.ts +5 -1
  109. package/dist/scripts/generate-web-module/templates/components/container.template.d.ts.map +1 -1
  110. package/dist/scripts/generate-web-module/templates/components/container.template.js +43 -63
  111. package/dist/scripts/generate-web-module/templates/components/container.template.js.map +1 -1
  112. package/dist/scripts/generate-web-module/templates/components/content.template.d.ts +7 -4
  113. package/dist/scripts/generate-web-module/templates/components/content.template.d.ts.map +1 -1
  114. package/dist/scripts/generate-web-module/templates/components/content.template.js +103 -14
  115. package/dist/scripts/generate-web-module/templates/components/content.template.js.map +1 -1
  116. package/dist/scripts/generate-web-module/templates/components/editor.template.d.ts +1 -1
  117. package/dist/scripts/generate-web-module/templates/components/editor.template.js +139 -150
  118. package/dist/scripts/generate-web-module/templates/components/editor.template.js.map +1 -1
  119. package/dist/scripts/generate-web-module/templates/components/index.d.ts +0 -1
  120. package/dist/scripts/generate-web-module/templates/components/index.d.ts.map +1 -1
  121. package/dist/scripts/generate-web-module/templates/components/index.js +1 -3
  122. package/dist/scripts/generate-web-module/templates/components/index.js.map +1 -1
  123. package/dist/scripts/generate-web-module/templates/components/list-container.template.js +2 -2
  124. package/dist/scripts/generate-web-module/templates/components/list.template.d.ts.map +1 -1
  125. package/dist/scripts/generate-web-module/templates/components/list.template.js +6 -1
  126. package/dist/scripts/generate-web-module/templates/components/list.template.js.map +1 -1
  127. package/dist/scripts/generate-web-module/templates/components/selector.template.d.ts.map +1 -1
  128. package/dist/scripts/generate-web-module/templates/components/selector.template.js +48 -52
  129. package/dist/scripts/generate-web-module/templates/components/selector.template.js.map +1 -1
  130. package/dist/scripts/generate-web-module/templates/data/interface.template.d.ts.map +1 -1
  131. package/dist/scripts/generate-web-module/templates/data/interface.template.js +38 -11
  132. package/dist/scripts/generate-web-module/templates/data/interface.template.js.map +1 -1
  133. package/dist/scripts/generate-web-module/templates/data/model.template.d.ts.map +1 -1
  134. package/dist/scripts/generate-web-module/templates/data/model.template.js +83 -26
  135. package/dist/scripts/generate-web-module/templates/data/model.template.js.map +1 -1
  136. package/dist/scripts/generate-web-module/templates/data/service.template.d.ts.map +1 -1
  137. package/dist/scripts/generate-web-module/templates/data/service.template.js +21 -1
  138. package/dist/scripts/generate-web-module/templates/data/service.template.js.map +1 -1
  139. package/dist/scripts/generate-web-module/templates/index.d.ts +1 -1
  140. package/dist/scripts/generate-web-module/templates/index.d.ts.map +1 -1
  141. package/dist/scripts/generate-web-module/templates/index.js +1 -2
  142. package/dist/scripts/generate-web-module/templates/index.js.map +1 -1
  143. package/dist/scripts/generate-web-module/templates/module.template.d.ts.map +1 -1
  144. package/dist/scripts/generate-web-module/templates/module.template.js +11 -3
  145. package/dist/scripts/generate-web-module/templates/module.template.js.map +1 -1
  146. package/dist/scripts/generate-web-module/templates/table-hook.template.js +31 -1
  147. package/dist/scripts/generate-web-module/templates/table-hook.template.js.map +1 -1
  148. package/dist/scripts/generate-web-module/transformers/import-resolver.d.ts +0 -1
  149. package/dist/scripts/generate-web-module/transformers/import-resolver.d.ts.map +1 -1
  150. package/dist/scripts/generate-web-module/transformers/import-resolver.js +0 -1
  151. package/dist/scripts/generate-web-module/transformers/import-resolver.js.map +1 -1
  152. package/dist/scripts/generate-web-module/transformers/relationship-key.d.ts +5 -0
  153. package/dist/scripts/generate-web-module/transformers/relationship-key.d.ts.map +1 -0
  154. package/dist/scripts/generate-web-module/transformers/relationship-key.js +21 -0
  155. package/dist/scripts/generate-web-module/transformers/relationship-key.js.map +1 -0
  156. package/dist/scripts/generate-web-module/transformers/relationship-resolver.d.ts.map +1 -1
  157. package/dist/scripts/generate-web-module/transformers/relationship-resolver.js +2 -0
  158. package/dist/scripts/generate-web-module/transformers/relationship-resolver.js.map +1 -1
  159. package/dist/scripts/generate-web-module/types/json-schema.interface.d.ts +21 -0
  160. package/dist/scripts/generate-web-module/types/json-schema.interface.d.ts.map +1 -1
  161. package/dist/scripts/generate-web-module/types/template-data.interface.d.ts +17 -0
  162. package/dist/scripts/generate-web-module/types/template-data.interface.d.ts.map +1 -1
  163. package/dist/server/index.js +3 -3
  164. package/dist/server/index.mjs +1 -1
  165. package/dist/testing/index.d.mts +1 -2
  166. package/dist/testing/index.d.ts +1 -2
  167. package/package.json +1 -6
  168. package/scripts/generate-web-module/__tests__/container.spec.ts +58 -0
  169. package/scripts/generate-web-module/__tests__/data-service.spec.ts +18 -0
  170. package/scripts/generate-web-module/__tests__/editor.spec.ts +36 -0
  171. package/scripts/generate-web-module/__tests__/fixtures.ts +43 -0
  172. package/scripts/generate-web-module/__tests__/model-interface.spec.ts +77 -0
  173. package/scripts/generate-web-module/__tests__/plumbing.spec.ts +21 -0
  174. package/scripts/generate-web-module/__tests__/selector.spec.ts +24 -0
  175. package/scripts/generate-web-module/__tests__/table-module-list.spec.ts +59 -0
  176. package/scripts/generate-web-module/generator.ts +14 -13
  177. package/scripts/generate-web-module/templates/components/container.template.ts +51 -66
  178. package/scripts/generate-web-module/templates/components/content.template.ts +107 -15
  179. package/scripts/generate-web-module/templates/components/editor.template.ts +140 -152
  180. package/scripts/generate-web-module/templates/components/index.ts +0 -1
  181. package/scripts/generate-web-module/templates/components/list-container.template.ts +2 -2
  182. package/scripts/generate-web-module/templates/components/list.template.ts +6 -1
  183. package/scripts/generate-web-module/templates/components/selector.template.ts +48 -52
  184. package/scripts/generate-web-module/templates/data/interface.template.ts +44 -12
  185. package/scripts/generate-web-module/templates/data/model.template.ts +88 -28
  186. package/scripts/generate-web-module/templates/data/service.template.ts +23 -1
  187. package/scripts/generate-web-module/templates/index.ts +0 -1
  188. package/scripts/generate-web-module/templates/module.template.ts +13 -3
  189. package/scripts/generate-web-module/templates/table-hook.template.ts +31 -2
  190. package/scripts/generate-web-module/transformers/import-resolver.ts +0 -2
  191. package/scripts/generate-web-module/transformers/relationship-key.ts +18 -0
  192. package/scripts/generate-web-module/transformers/relationship-resolver.ts +2 -0
  193. package/scripts/generate-web-module/types/json-schema.interface.ts +9 -0
  194. package/scripts/generate-web-module/types/template-data.interface.ts +7 -0
  195. package/src/client/config.ts +1 -1
  196. package/src/components/index.ts +1 -0
  197. package/src/components/viewers/BlockNoteViewer.tsx +27 -0
  198. package/src/components/viewers/BlockNoteViewerContainer.tsx +10 -0
  199. package/src/core/registry/helpStore.ts +2 -19
  200. package/src/features/assistant-message/components/parts/MessageSourcesContainer.tsx +4 -0
  201. package/src/features/assistant-message/components/parts/tabs/ContentsTab.tsx +5 -5
  202. package/src/features/assistant-message/components/parts/tabs/ReferencesTab.tsx +3 -2
  203. package/src/features/help/components/HelpArticleBody.tsx +27 -19
  204. package/src/features/help/components/HelpHint.tsx +20 -11
  205. package/src/features/help/components/HelpSearchResultRow.tsx +16 -6
  206. package/src/features/help/components/HelpSideNav.tsx +54 -19
  207. package/src/features/help/components/__tests__/HelpAskAi.spec.tsx +1 -1
  208. package/src/features/help/components/__tests__/HelpHint.spec.tsx +17 -17
  209. package/src/features/help/components/__tests__/HelpSearchResultRow.spec.tsx +18 -19
  210. package/src/features/help/components/__tests__/HelpSideNav.spec.tsx +20 -22
  211. package/src/features/help/contexts/HelpContext.spec.tsx +1 -3
  212. package/src/features/help/index.ts +3 -6
  213. package/src/features/help/interfaces/help-content-config.interface.ts +0 -5
  214. package/src/features/help/server-entry.ts +6 -15
  215. package/src/features/help/types/help-article.types.ts +2 -4
  216. package/src/features/how-to/HowToModule.ts +14 -1
  217. package/src/features/how-to/components/forms/HowToEditor.tsx +108 -4
  218. package/src/features/how-to/data/HowTo.spec.ts +43 -0
  219. package/src/features/how-to/data/HowTo.ts +47 -4
  220. package/src/features/how-to/data/HowToInterface.ts +14 -1
  221. package/src/features/how-to/data/HowToService.ts +61 -0
  222. package/dist/BlockNoteEditor-3XYBZLWO.js.map +0 -1
  223. package/dist/chunk-3J7RQBF3.js +0 -123
  224. package/dist/chunk-3J7RQBF3.js.map +0 -1
  225. package/dist/chunk-7E3O52U5.js.map +0 -1
  226. package/dist/chunk-CFI4WZ5R.js.map +0 -1
  227. package/dist/chunk-CQID6RCF.mjs +0 -38
  228. package/dist/chunk-CQID6RCF.mjs.map +0 -1
  229. package/dist/chunk-CRTVAQEK.mjs.map +0 -1
  230. package/dist/chunk-MZTKPPET.mjs +0 -123
  231. package/dist/chunk-MZTKPPET.mjs.map +0 -1
  232. package/dist/chunk-UHO3KUUH.js.map +0 -1
  233. package/dist/chunk-YQQHAFBS.js +0 -38
  234. package/dist/chunk-YQQHAFBS.js.map +0 -1
  235. package/dist/features/help/server/createHelpAssetRouteHandler.d.mts +0 -11
  236. package/dist/features/help/server/createHelpAssetRouteHandler.d.ts +0 -11
  237. package/dist/features/help/server/createHelpAssetRouteHandler.js +0 -43
  238. package/dist/features/help/server/createHelpAssetRouteHandler.js.map +0 -1
  239. package/dist/features/help/server/createHelpAssetRouteHandler.mjs +0 -43
  240. package/dist/features/help/server/createHelpAssetRouteHandler.mjs.map +0 -1
  241. package/dist/help-content-config.interface-B9L02u9i.d.mts +0 -50
  242. package/dist/help-content-config.interface-B9L02u9i.d.ts +0 -50
  243. package/dist/scripts/generate-web-module/templates/components/details.template.d.ts +0 -14
  244. package/dist/scripts/generate-web-module/templates/components/details.template.d.ts.map +0 -1
  245. package/dist/scripts/generate-web-module/templates/components/details.template.js +0 -112
  246. package/dist/scripts/generate-web-module/templates/components/details.template.js.map +0 -1
  247. package/scripts/generate-web-module/templates/components/details.template.ts +0 -116
  248. package/src/features/help/components/mdx/Callout.tsx +0 -21
  249. package/src/features/help/components/mdx/EntityRef.tsx +0 -18
  250. package/src/features/help/components/mdx/KeyBinding.tsx +0 -6
  251. package/src/features/help/components/mdx/Related.tsx +0 -33
  252. package/src/features/help/components/mdx/Screenshot.tsx +0 -9
  253. package/src/features/help/components/mdx/Steps.tsx +0 -21
  254. package/src/features/help/components/mdx/Video.tsx +0 -8
  255. package/src/features/help/components/mdx/mdx-server-components.ts +0 -23
  256. package/src/features/help/components/mdx/mdxComponents.ts +0 -9
  257. package/src/features/help/hooks/useHelpArticle.ts +0 -7
  258. package/src/features/help/hooks/useHelpManifest.ts +0 -5
  259. package/src/features/help/server/__tests__/createHelpAssetRouteHandler.spec.ts +0 -43
  260. package/src/features/help/server/createHelpAssetRouteHandler.ts +0 -35
  261. package/src/features/help/server/generateHelpArticleMetadata.ts +0 -18
  262. package/src/features/help/server/generateHelpArticleStaticParams.ts +0 -7
  263. package/src/features/help/server/generateHelpModeStaticParams.ts +0 -5
  264. package/src/features/help/server/getHelpContent.ts +0 -17
  265. package/src/features/help/server/index.ts +0 -8
  266. package/src/features/help/server/serializeHelpArticle.tsx +0 -46
  267. package/src/features/help/utils/__tests__/helpNavigation.spec.ts +0 -70
  268. package/src/features/help/utils/helpNavigation.ts +0 -29
@@ -1,8 +0,0 @@
1
- export function Video({ src, poster }: { src: string; poster?: string }) {
2
- const url = src.startsWith("/") ? src : `/help-assets/${src}`;
3
- return (
4
- <video controls preload="metadata" poster={poster} className="my-4 w-full rounded-md ring-1 ring-border">
5
- <source src={url} />
6
- </video>
7
- );
8
- }
@@ -1,23 +0,0 @@
1
- // Server-safe subset of MDX_COMPONENTS used by `renderHelpArticle`.
2
- // Mirrors `mdxComponents.ts` but EXCLUDES `Related` (which is a client
3
- // component that uses `useHelp` + `usePageUrlGenerator`). Server-side rendering
4
- // of `<Related>` would require passing the manifest by prop, which the standard
5
- // MDX components map cannot do — articles that need related links should be
6
- // extended via a server-side render hook rather than the MDX shortcode.
7
-
8
- import { Callout } from "./Callout";
9
- import { Steps, Step } from "./Steps";
10
- import { Screenshot } from "./Screenshot";
11
- import { EntityRef } from "./EntityRef";
12
- import { KeyBinding } from "./KeyBinding";
13
- import { Video } from "./Video";
14
-
15
- export const MDX_SERVER_COMPONENTS = {
16
- Callout,
17
- Steps,
18
- Step,
19
- Screenshot,
20
- EntityRef,
21
- KeyBinding,
22
- Video,
23
- } as const;
@@ -1,9 +0,0 @@
1
- import { Callout } from "./Callout";
2
- import { Steps, Step } from "./Steps";
3
- import { Screenshot } from "./Screenshot";
4
- import { EntityRef } from "./EntityRef";
5
- import { KeyBinding } from "./KeyBinding";
6
- import { Video } from "./Video";
7
- import { Related } from "./Related";
8
-
9
- export const MDX_COMPONENTS = { Callout, Steps, Step, Screenshot, EntityRef, KeyBinding, Video, Related };
@@ -1,7 +0,0 @@
1
- "use client";
2
- import { useHelp } from "../contexts/HelpContext";
3
- import { findHelpArticle } from "../utils/helpNavigation";
4
-
5
- export function useHelpArticle(mode: string, slug: string) {
6
- return findHelpArticle(useHelp().manifest, mode, slug);
7
- }
@@ -1,5 +0,0 @@
1
- "use client";
2
- import { useHelp } from "../contexts/HelpContext";
3
- export function useHelpManifest() {
4
- return useHelp().manifest;
5
- }
@@ -1,43 +0,0 @@
1
- import { describe, it, expect, beforeAll, afterAll } from "vitest";
2
- import { mkdtemp, writeFile, mkdir, rm } from "node:fs/promises";
3
- import { tmpdir } from "node:os";
4
- import { join } from "node:path";
5
- import { createHelpAssetRouteHandler } from "../createHelpAssetRouteHandler";
6
-
7
- describe("createHelpAssetRouteHandler", () => {
8
- let srcRoot: string;
9
-
10
- beforeAll(async () => {
11
- srcRoot = await mkdtemp(join(tmpdir(), "help-assets-"));
12
- await mkdir(srcRoot, { recursive: true });
13
- await writeFile(join(srcRoot, "ok.png"), Buffer.from([0x89, 0x50, 0x4e, 0x47]));
14
- });
15
- afterAll(async () => {
16
- await rm(srcRoot, { recursive: true, force: true });
17
- });
18
-
19
- it("returns 200 with correct MIME for an existing PNG", async () => {
20
- const GET = createHelpAssetRouteHandler({ srcRoot });
21
- const res = await GET(new Request("http://localhost/help-assets/ok.png"), {
22
- params: Promise.resolve({ path: ["ok.png"] }),
23
- });
24
- expect(res.status).toBe(200);
25
- expect(res.headers.get("Content-Type")).toBe("image/png");
26
- });
27
-
28
- it("returns 404 for missing files", async () => {
29
- const GET = createHelpAssetRouteHandler({ srcRoot });
30
- const res = await GET(new Request("http://localhost/help-assets/missing.png"), {
31
- params: Promise.resolve({ path: ["missing.png"] }),
32
- });
33
- expect(res.status).toBe(404);
34
- });
35
-
36
- it("sanitizes path traversal attempts", async () => {
37
- const GET = createHelpAssetRouteHandler({ srcRoot });
38
- const res = await GET(new Request("http://localhost/help-assets/etc/passwd"), {
39
- params: Promise.resolve({ path: ["..", "..", "etc", "passwd"] }),
40
- });
41
- expect(res.status).toBe(404);
42
- });
43
- });
@@ -1,35 +0,0 @@
1
- import { NextResponse } from "next/server";
2
- import { readFile, stat } from "node:fs/promises";
3
- import { join } from "node:path";
4
-
5
- const MIME: Record<string, string> = {
6
- ".png": "image/png",
7
- ".jpg": "image/jpeg",
8
- ".jpeg": "image/jpeg",
9
- ".webp": "image/webp",
10
- ".gif": "image/gif",
11
- ".svg": "image/svg+xml",
12
- ".mp4": "video/mp4",
13
- ".webm": "video/webm",
14
- };
15
-
16
- export function createHelpAssetRouteHandler({ srcRoot }: { srcRoot: string }) {
17
- return async function GET(_req: Request, { params }: { params: Promise<{ path: string[] }> }) {
18
- const { path } = await params;
19
- const safe = path.filter((p) => p !== ".." && !p.includes("/")).join("/");
20
- const filePath = join(srcRoot, safe);
21
- try {
22
- const s = await stat(filePath);
23
- if (!s.isFile()) return new NextResponse("Not found", { status: 404 });
24
- const ext = filePath.toLowerCase().slice(filePath.lastIndexOf("."));
25
- const mime = MIME[ext] ?? "application/octet-stream";
26
- const data = await readFile(filePath);
27
- return new NextResponse(data, {
28
- status: 200,
29
- headers: { "Content-Type": mime, "Cache-Control": "public, max-age=3600" },
30
- });
31
- } catch {
32
- return new NextResponse("Not found", { status: 404 });
33
- }
34
- };
35
- }
@@ -1,18 +0,0 @@
1
- import type { Metadata } from "next";
2
- import { findHelpArticle } from "../utils/helpNavigation";
3
- import { getHelpContent } from "./getHelpContent";
4
-
5
- export async function generateHelpArticleMetadata({
6
- params,
7
- }: {
8
- params: Promise<{ mode: string; slug: string }>;
9
- }): Promise<Metadata> {
10
- const { mode, slug } = await params;
11
- const article = findHelpArticle(getHelpContent().manifest, mode, slug);
12
- if (!article) return {};
13
- return {
14
- title: article.title,
15
- description: article.summary,
16
- openGraph: { title: article.title, description: article.summary },
17
- };
18
- }
@@ -1,7 +0,0 @@
1
- import { getHelpContent } from "./getHelpContent";
2
-
3
- export function generateHelpArticleStaticParams(): { mode: string; slug: string }[] {
4
- return getHelpContent()
5
- .manifest.filter((a) => !a.draft)
6
- .map((a) => ({ mode: a.mode, slug: a.slug }));
7
- }
@@ -1,5 +0,0 @@
1
- import { HELP_MODES } from "../types/help-article.types";
2
-
3
- export function generateHelpModeStaticParams(): { mode: string }[] {
4
- return HELP_MODES.map((mode) => ({ mode }));
5
- }
@@ -1,17 +0,0 @@
1
- import { _getStaticHelpContent } from "../../../core/registry/helpStore";
2
- import type { HelpContentConfig } from "../interfaces/help-content-config.interface";
3
-
4
- /**
5
- * Server-side accessor for the help-content config set via configureJsonApi().
6
- * Returns the same value <HelpProvider> exposes via React Context to client components.
7
- * Throws with a setup error if helpContent was never configured.
8
- */
9
- export function getHelpContent(): HelpContentConfig {
10
- const cfg = _getStaticHelpContent<HelpContentConfig>();
11
- if (!cfg) {
12
- throw new Error(
13
- "Help content not configured — call configureJsonApi({ helpContent: {...} }) before importing help pages.",
14
- );
15
- }
16
- return cfg;
17
- }
@@ -1,8 +0,0 @@
1
- export { getHelpContent } from "./getHelpContent";
2
- export { renderHelpArticle, serializeHelpArticle } from "./serializeHelpArticle";
3
- export { generateHelpArticleStaticParams } from "./generateHelpArticleStaticParams";
4
- export { generateHelpArticleMetadata } from "./generateHelpArticleMetadata";
5
- export { generateHelpModeStaticParams } from "./generateHelpModeStaticParams";
6
- // NOTE: `createHelpAssetRouteHandler` is intentionally NOT re-exported here.
7
- // It uses `node:fs/promises` and must only be reachable via the dedicated
8
- // `@carlonicora/nextjs-jsonapi/help-asset-route` subpath, never the main bundle.
@@ -1,46 +0,0 @@
1
- import { MDXRemote } from "next-mdx-remote/rsc";
2
- import remarkGfm from "remark-gfm";
3
- import rehypeSlug from "rehype-slug";
4
- import rehypeAutolinkHeadings from "rehype-autolink-headings";
5
- import type { ReactElement } from "react";
6
- import type { HelpArticle } from "../types/help-article.types";
7
- import { _getStaticHelpReader } from "../../../core/registry/helpStore";
8
- import { MDX_SERVER_COMPONENTS } from "../components/mdx/mdx-server-components";
9
-
10
- /**
11
- * Server-side: read the article's raw markdown via the registered help reader
12
- * and render it through `next-mdx-remote/rsc`'s server-side MDXRemote, using
13
- * the server-safe MDX components (Callout, Steps, Screenshot, EntityRef,
14
- * KeyBinding, Video). The returned React element can be embedded inside a
15
- * server component (e.g. as `children` of `<HelpArticleBody>`).
16
- *
17
- * Note: `<Related>` is intentionally not part of the server map — it's a client
18
- * component that reads HelpContext. Articles that reference `<Related>` would
19
- * need a separate render path that injects the manifest by prop.
20
- */
21
- export async function renderHelpArticle(article: HelpArticle): Promise<ReactElement> {
22
- const readRawMarkdown = _getStaticHelpReader();
23
- if (!readRawMarkdown) {
24
- throw new Error(
25
- "Help reader not configured. Call setHelpReader(fn) from a server-only entrypoint (e.g. Next.js instrumentation register()) before rendering help articles.",
26
- );
27
- }
28
- const source = await readRawMarkdown(article);
29
- return (
30
- <MDXRemote
31
- source={source}
32
- components={MDX_SERVER_COMPONENTS}
33
- options={{
34
- parseFrontmatter: true,
35
- mdxOptions: {
36
- remarkPlugins: [remarkGfm],
37
- rehypePlugins: [rehypeSlug, [rehypeAutolinkHeadings, { behavior: "wrap" }]],
38
- },
39
- }}
40
- />
41
- );
42
- }
43
-
44
- /** @deprecated Use `renderHelpArticle` instead — the legacy serialize + client
45
- * MDXRemote pattern is incompatible with App Router RSC. */
46
- export const serializeHelpArticle = renderHelpArticle;
@@ -1,70 +0,0 @@
1
- import { describe, it, expect } from "vitest";
2
- import { buildHelpNav, findHelpArticle, prevNextWithinMode } from "../helpNavigation";
3
-
4
- const base = {
5
- tags: [],
6
- contextualKeys: [],
7
- aiIndexed: true,
8
- draft: false,
9
- contentHash: "h",
10
- headings: [],
11
- relatedSlugs: [],
12
- lastUpdated: "",
13
- };
14
- const manifest = [
15
- {
16
- ...base,
17
- id: "a",
18
- slug: "a",
19
- mode: "how-to" as const,
20
- title: "Alpha",
21
- summary: "s",
22
- order: 1,
23
- path: "how-to/a.mdx",
24
- },
25
- { ...base, id: "b", slug: "b", mode: "how-to" as const, title: "Beta", summary: "s", order: 2, path: "how-to/b.mdx" },
26
- {
27
- ...base,
28
- id: "c",
29
- slug: "c",
30
- mode: "tutorial" as const,
31
- title: "Gamma",
32
- summary: "s",
33
- order: 1,
34
- path: "tutorial/c.mdx",
35
- },
36
- ];
37
-
38
- describe("helpNavigation", () => {
39
- it("buildHelpNav groups articles by mode, sorted by order", () => {
40
- const groups = buildHelpNav(manifest);
41
- const howTo = groups.find((g) => g.mode === "how-to")!;
42
- expect(howTo.articles.map((a) => a.slug)).toEqual(["a", "b"]);
43
- });
44
-
45
- it("findHelpArticle locates by mode + slug", () => {
46
- expect(findHelpArticle(manifest, "how-to", "b")?.title).toBe("Beta");
47
- expect(findHelpArticle(manifest, "how-to", "missing")).toBeUndefined();
48
- });
49
-
50
- it("prevNextWithinMode returns siblings within the same mode", () => {
51
- const current = manifest[0]; // Alpha (how-to, order 1)
52
- const { prev, next } = prevNextWithinMode(manifest, current);
53
- expect(prev).toBeNull();
54
- expect(next?.slug).toBe("b");
55
- });
56
-
57
- it("prevNextWithinMode returns null at the boundaries", () => {
58
- const current = manifest[1]; // Beta (how-to, order 2)
59
- const { prev, next } = prevNextWithinMode(manifest, current);
60
- expect(prev?.slug).toBe("a");
61
- expect(next).toBeNull();
62
- });
63
-
64
- it("prevNextWithinMode does not cross modes", () => {
65
- const current = manifest[2]; // Gamma (tutorial)
66
- const { prev, next } = prevNextWithinMode(manifest, current);
67
- expect(prev).toBeNull();
68
- expect(next).toBeNull();
69
- });
70
- });
@@ -1,29 +0,0 @@
1
- import { HELP_MODES, type HelpArticle, type HelpMode } from "../types/help-article.types";
2
-
3
- export interface HelpNavGroup {
4
- mode: HelpMode;
5
- articles: HelpArticle[];
6
- }
7
-
8
- export function buildHelpNav(manifest: readonly HelpArticle[]): HelpNavGroup[] {
9
- return HELP_MODES.map((mode) => ({
10
- mode,
11
- articles: manifest.filter((a) => a.mode === mode && !a.draft).sort((a, b) => a.order - b.order),
12
- }));
13
- }
14
-
15
- export function findHelpArticle(manifest: readonly HelpArticle[], mode: string, slug: string): HelpArticle | undefined {
16
- return manifest.find((a) => a.mode === mode && a.slug === slug);
17
- }
18
-
19
- export function prevNextWithinMode(
20
- manifest: readonly HelpArticle[],
21
- current: HelpArticle,
22
- ): { prev: HelpArticle | null; next: HelpArticle | null } {
23
- const siblings = manifest.filter((a) => a.mode === current.mode && !a.draft).sort((a, b) => a.order - b.order);
24
- const idx = siblings.findIndex((a) => a.slug === current.slug);
25
- return {
26
- prev: idx > 0 ? siblings[idx - 1] : null,
27
- next: idx >= 0 && idx < siblings.length - 1 ? siblings[idx + 1] : null,
28
- };
29
- }