zudoku 0.3.0-dev.31 → 0.3.0-dev.33

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 (206) hide show
  1. package/dist/app/App.d.ts +1 -0
  2. package/dist/app/App.js +2 -0
  3. package/dist/app/App.js.map +1 -0
  4. package/dist/app/entry.client.d.ts +3 -0
  5. package/dist/app/entry.client.js +38 -0
  6. package/dist/app/entry.client.js.map +1 -0
  7. package/dist/app/entry.server.d.ts +10 -0
  8. package/dist/app/entry.server.js +107 -0
  9. package/dist/app/entry.server.js.map +1 -0
  10. package/dist/app/main.d.ts +26 -2
  11. package/dist/app/main.js +39 -17
  12. package/dist/app/main.js.map +1 -1
  13. package/dist/app/tailwind.js +5 -0
  14. package/dist/app/tailwind.js.map +1 -1
  15. package/dist/app/zudoku-manifest.d.ts +1 -0
  16. package/dist/app/zudoku-manifest.js +20 -0
  17. package/dist/app/zudoku-manifest.js.map +1 -0
  18. package/dist/cli/cmds/dev.js +5 -0
  19. package/dist/cli/cmds/dev.js.map +1 -1
  20. package/dist/cli/dev/handler.d.ts +1 -0
  21. package/dist/cli/dev/handler.js +3 -1
  22. package/dist/cli/dev/handler.js.map +1 -1
  23. package/dist/config/config.d.ts +5 -0
  24. package/dist/lib/authentication/providers/clerk.js +2 -0
  25. package/dist/lib/authentication/providers/clerk.js.map +1 -1
  26. package/dist/lib/components/DevPortal.d.ts +1 -1
  27. package/dist/lib/components/DevPortal.js +6 -10
  28. package/dist/lib/components/DevPortal.js.map +1 -1
  29. package/dist/lib/components/ErrorPage.d.ts +6 -0
  30. package/dist/lib/components/ErrorPage.js +9 -0
  31. package/dist/lib/components/ErrorPage.js.map +1 -0
  32. package/dist/lib/components/InlineCode.d.ts +5 -0
  33. package/dist/lib/components/InlineCode.js +4 -0
  34. package/dist/lib/components/InlineCode.js.map +1 -0
  35. package/dist/lib/components/Layout.js +2 -1
  36. package/dist/lib/components/Layout.js.map +1 -1
  37. package/dist/lib/components/NotFoundPage.d.ts +1 -0
  38. package/dist/lib/components/NotFoundPage.js +12 -0
  39. package/dist/lib/components/NotFoundPage.js.map +1 -0
  40. package/dist/lib/components/SyntaxHighlight.d.ts +3 -2
  41. package/dist/lib/components/SyntaxHighlight.js +20 -22
  42. package/dist/lib/components/SyntaxHighlight.js.map +1 -1
  43. package/dist/lib/errors/RouterError.js +6 -3
  44. package/dist/lib/errors/RouterError.js.map +1 -1
  45. package/dist/lib/errors/ServerError.d.ts +3 -0
  46. package/dist/lib/errors/ServerError.js +6 -0
  47. package/dist/lib/errors/ServerError.js.map +1 -0
  48. package/dist/lib/oas/parser/index.d.ts +1 -1
  49. package/dist/lib/oas/parser/index.js +38 -14
  50. package/dist/lib/oas/parser/index.js.map +1 -1
  51. package/dist/lib/plugins/api-keys/index.js +3 -8
  52. package/dist/lib/plugins/api-keys/index.js.map +1 -1
  53. package/dist/lib/plugins/markdown/generateRoutes.js.map +1 -1
  54. package/dist/lib/plugins/markdown/index.js +3 -7
  55. package/dist/lib/plugins/markdown/index.js.map +1 -1
  56. package/dist/lib/plugins/openapi/OperationList.js +11 -1
  57. package/dist/lib/plugins/openapi/OperationList.js.map +1 -1
  58. package/dist/lib/plugins/openapi/OperationListItem.js +2 -1
  59. package/dist/lib/plugins/openapi/OperationListItem.js.map +1 -1
  60. package/dist/lib/plugins/openapi/SchemaListView.js +2 -1
  61. package/dist/lib/plugins/openapi/SchemaListView.js.map +1 -1
  62. package/dist/lib/plugins/openapi/client/createMemoryClient.js +1 -1
  63. package/dist/lib/plugins/openapi/client/createMemoryClient.js.map +1 -1
  64. package/dist/lib/plugins/openapi/index.js +9 -1
  65. package/dist/lib/plugins/openapi/index.js.map +1 -1
  66. package/dist/lib/plugins/openapi/playground/QueryParams.js +2 -1
  67. package/dist/lib/plugins/openapi/playground/QueryParams.js.map +1 -1
  68. package/dist/lib/plugins/redirect/index.js +2 -3
  69. package/dist/lib/plugins/redirect/index.js.map +1 -1
  70. package/dist/lib/ui/Callout.js +1 -1
  71. package/dist/lib/ui/Callout.js.map +1 -1
  72. package/dist/lib/ui/button-variants.d.ts +1 -1
  73. package/dist/lib/util/MdxComponents.js +2 -2
  74. package/dist/lib/util/MdxComponents.js.map +1 -1
  75. package/dist/lib/util/groupBy.d.ts +1 -6
  76. package/dist/lib/util/groupBy.js +10 -8
  77. package/dist/lib/util/groupBy.js.map +1 -1
  78. package/dist/vite/build.js +30 -11
  79. package/dist/vite/build.js.map +1 -1
  80. package/dist/vite/config.d.ts +2 -1
  81. package/dist/vite/config.js +34 -7
  82. package/dist/vite/config.js.map +1 -1
  83. package/dist/vite/dev-server.d.ts +1 -1
  84. package/dist/vite/dev-server.js +15 -9
  85. package/dist/vite/dev-server.js.map +1 -1
  86. package/dist/vite/html.js +5 -4
  87. package/dist/vite/html.js.map +1 -1
  88. package/dist/vite/plugin-custom-css.d.ts +6 -0
  89. package/dist/vite/plugin-custom-css.js +55 -0
  90. package/dist/vite/plugin-custom-css.js.map +1 -0
  91. package/dist/vite/plugin-docs.js +14 -5
  92. package/dist/vite/plugin-docs.js.map +1 -1
  93. package/dist/vite/plugin-openapi-worker.js +4 -1
  94. package/dist/vite/plugin-openapi-worker.js.map +1 -1
  95. package/dist/vite/plugin.js +2 -0
  96. package/dist/vite/plugin.js.map +1 -1
  97. package/dist/vite/prerender.d.ts +1 -0
  98. package/dist/vite/prerender.js +57 -0
  99. package/dist/vite/prerender.js.map +1 -0
  100. package/lib/{DevPortalProvider-BMk-RCE0.js → DevPortalProvider-BlxLX6GG.js} +230 -250
  101. package/lib/DevPortalProvider-BlxLX6GG.js.map +1 -0
  102. package/lib/{Markdown-DDmW47R9.js → Markdown-CL8KPvJN.js} +8 -9
  103. package/lib/{Markdown-DDmW47R9.js.map → Markdown-CL8KPvJN.js.map} +1 -1
  104. package/lib/MdxComponents-Ev_hBHb2.js +5885 -0
  105. package/lib/MdxComponents-Ev_hBHb2.js.map +1 -0
  106. package/lib/{MdxPage-DyJAHF9y.js → MdxPage-Z3HKNTrj.js} +92 -89
  107. package/lib/MdxPage-Z3HKNTrj.js.map +1 -0
  108. package/lib/{OperationList-Dz9rHM9r.js → OperationList-DfkWNe8Y.js} +1972 -1786
  109. package/lib/OperationList-DfkWNe8Y.js.map +1 -0
  110. package/lib/Route-Bf1_D_vC.js +13 -0
  111. package/lib/{Route-CN_7-e5r.js.map → Route-Bf1_D_vC.js.map} +1 -1
  112. package/lib/Select-DSa3bN4t.js +4770 -0
  113. package/lib/Select-DSa3bN4t.js.map +1 -0
  114. package/lib/assets/{worker-BXS8hiSM.js → worker-BjPv-hjP.js} +3100 -2720
  115. package/lib/assets/worker-BjPv-hjP.js.map +1 -0
  116. package/lib/hook-CTmJ6CWq.js +35 -0
  117. package/lib/hook-CTmJ6CWq.js.map +1 -0
  118. package/lib/index-BdWBDosx.js +74 -0
  119. package/lib/index-BdWBDosx.js.map +1 -0
  120. package/lib/{index-Cpdpun6t.js → index-BjSy8IQO.js} +57 -41
  121. package/lib/index-BjSy8IQO.js.map +1 -0
  122. package/lib/{AnchorLink-ptdQk87q.js → index.esm-CPEExBJE.js} +156 -168
  123. package/lib/index.esm-CPEExBJE.js.map +1 -0
  124. package/lib/jsx-runtime-CM0TzjGp.js +866 -0
  125. package/lib/jsx-runtime-CM0TzjGp.js.map +1 -0
  126. package/lib/mutation-91kw0lHb.js +208 -0
  127. package/lib/mutation-91kw0lHb.js.map +1 -0
  128. package/lib/router-CcYTwKjf.js +183 -0
  129. package/lib/router-CcYTwKjf.js.map +1 -0
  130. package/lib/zudoku.auth-clerk.js.map +1 -1
  131. package/lib/zudoku.auth-openid.js +588 -441
  132. package/lib/zudoku.auth-openid.js.map +1 -1
  133. package/lib/zudoku.components.js +284 -595
  134. package/lib/zudoku.components.js.map +1 -1
  135. package/lib/zudoku.openapi-worker.js +18 -18
  136. package/lib/zudoku.plugin-api-keys.js +143 -98
  137. package/lib/zudoku.plugin-api-keys.js.map +1 -1
  138. package/lib/zudoku.plugin-markdown.js +2 -49
  139. package/lib/zudoku.plugin-markdown.js.map +1 -1
  140. package/lib/zudoku.plugin-openapi.js +5 -3
  141. package/lib/zudoku.plugin-openapi.js.map +1 -1
  142. package/lib/zudoku.plugin-redirect.js +6 -7
  143. package/lib/zudoku.plugin-redirect.js.map +1 -1
  144. package/package.json +9 -8
  145. package/src/app/App.tsx +0 -0
  146. package/src/app/entry.client.tsx +64 -0
  147. package/src/app/entry.server.tsx +158 -0
  148. package/src/app/main.tsx +65 -43
  149. package/src/app/tailwind.ts +6 -0
  150. package/src/app/zudoku-manifest.ts +22 -0
  151. package/src/lib/authentication/providers/clerk.tsx +1 -0
  152. package/src/lib/components/DevPortal.tsx +25 -33
  153. package/src/lib/components/ErrorPage.tsx +28 -0
  154. package/src/lib/components/InlineCode.tsx +19 -0
  155. package/src/lib/components/Layout.tsx +7 -4
  156. package/src/lib/components/NotFoundPage.tsx +39 -0
  157. package/src/lib/components/SyntaxHighlight.tsx +26 -22
  158. package/src/lib/errors/RouterError.tsx +8 -7
  159. package/src/lib/errors/ServerError.tsx +5 -0
  160. package/src/lib/oas/parser/index.ts +41 -22
  161. package/src/lib/plugins/api-keys/index.tsx +4 -16
  162. package/src/lib/plugins/markdown/generateRoutes.tsx +1 -1
  163. package/src/lib/plugins/markdown/index.tsx +3 -7
  164. package/src/lib/plugins/openapi/OperationList.tsx +30 -0
  165. package/src/lib/plugins/openapi/OperationListItem.tsx +3 -1
  166. package/src/lib/plugins/openapi/SchemaListView.tsx +8 -10
  167. package/src/lib/plugins/openapi/client/createMemoryClient.ts +1 -1
  168. package/src/lib/plugins/openapi/index.tsx +18 -1
  169. package/src/lib/plugins/openapi/playground/QueryParams.tsx +6 -1
  170. package/src/lib/plugins/redirect/index.tsx +2 -2
  171. package/src/lib/ui/Callout.tsx +2 -2
  172. package/src/lib/util/MdxComponents.tsx +2 -11
  173. package/src/lib/util/groupBy.ts +7 -12
  174. package/dist/lib/components/Router.d.ts +0 -4
  175. package/dist/lib/components/Router.js +0 -21
  176. package/dist/lib/components/Router.js.map +0 -1
  177. package/lib/AnchorLink-ptdQk87q.js.map +0 -1
  178. package/lib/DevPortalProvider-BMk-RCE0.js.map +0 -1
  179. package/lib/MdxComponents-C0R6zobS.js +0 -3019
  180. package/lib/MdxComponents-C0R6zobS.js.map +0 -1
  181. package/lib/MdxPage-DyJAHF9y.js.map +0 -1
  182. package/lib/OperationList-Dz9rHM9r.js.map +0 -1
  183. package/lib/Route-CN_7-e5r.js +0 -14
  184. package/lib/Select-D-Jtx53Q.js +0 -4572
  185. package/lib/Select-D-Jtx53Q.js.map +0 -1
  186. package/lib/Spinner-BG1JnYy0.js +0 -182
  187. package/lib/Spinner-BG1JnYy0.js.map +0 -1
  188. package/lib/assets/worker-BXS8hiSM.js.map +0 -1
  189. package/lib/cn-DpqTslo9.js +0 -2342
  190. package/lib/cn-DpqTslo9.js.map +0 -1
  191. package/lib/hook-BzBeIPL4.js +0 -25
  192. package/lib/hook-BzBeIPL4.js.map +0 -1
  193. package/lib/index-BaOOUFsA.js +0 -412
  194. package/lib/index-BaOOUFsA.js.map +0 -1
  195. package/lib/index-CPvRaBBB.js +0 -713
  196. package/lib/index-CPvRaBBB.js.map +0 -1
  197. package/lib/index-Cpdpun6t.js.map +0 -1
  198. package/lib/index-DLS6fPwU.js +0 -464
  199. package/lib/index-DLS6fPwU.js.map +0 -1
  200. package/lib/jsx-runtime-SV6hXQua.js +0 -3009
  201. package/lib/jsx-runtime-SV6hXQua.js.map +0 -1
  202. package/lib/loglevel-CA34MiFn.js +0 -153
  203. package/lib/loglevel-CA34MiFn.js.map +0 -1
  204. package/lib/util-CCWvaWo7.js +0 -41
  205. package/lib/util-CCWvaWo7.js.map +0 -1
  206. package/src/lib/components/Router.tsx +0 -24
@@ -1 +1 @@
1
- {"version":3,"file":"zudoku.plugin-markdown.js","sources":["../src/lib/plugins/markdown/generateRoutes.tsx","../src/lib/plugins/markdown/index.tsx"],"sourcesContent":["import { Navigate, type RouteObject } from \"react-router-dom\";\nimport { useTopNavigationItem } from \"../../components/context/DevPortalProvider.js\";\nimport { isPathItem } from \"../../components/navigation/util.js\";\nimport { traverseNavigation } from \"../../util/traverseNavigation.js\";\n\nimport {\n MarkdownPluginDefaultOptions,\n MarkdownPluginOptions,\n} from \"./index.js\";\n\nexport const generateRoutes = (\n markdownFiles: MarkdownPluginOptions[\"markdownFiles\"],\n defaultOptions?: MarkdownPluginDefaultOptions,\n): RouteObject[] => {\n const routes = Object.entries(markdownFiles).flatMap(\n ([file, importPromise]) => {\n // @todo we can pass in the folder name and then filter the markdown files based on that path\n const match = file.match(/pages\\/(.*).mdx?$/);\n const path = match?.at(1);\n\n if (!path) return [];\n\n const pathSegments = path.split(\"/\");\n const isIndexFile = pathSegments.at(-1) === \"index\";\n const routePath = isIndexFile\n ? pathSegments.slice(0, -1).join(\"/\")\n : path;\n\n return {\n path: routePath,\n lazy: async () => {\n const { MdxPage } = await import(\"./MdxPage.js\");\n const { default: Component, ...props } = await importPromise();\n return {\n element: (\n <MdxPage\n mdxComponent={Component}\n {...props}\n defaultOptions={defaultOptions}\n />\n ),\n };\n },\n } satisfies RouteObject;\n },\n );\n\n const rootRoutes = Array.from(\n new Set(routes.map((route) => route.path.split(\"/\").at(0))),\n ).map((dir) => ({\n path: `/${dir}`,\n element: <Redirect />,\n }));\n\n return [...routes, ...rootRoutes];\n};\n\nconst Redirect = () => {\n const navItem = useTopNavigationItem();\n\n if (!navItem) return null;\n\n return traverseNavigation(navItem, (node, fullPath) => {\n if (\"children\" in node || !isPathItem(node)) return;\n return <Navigate to={fullPath} replace />;\n });\n};\n","import type { Toc } from \"@stefanprobst/rehype-extract-toc\";\nimport type { MDXProps } from \"mdx/types.js\";\nimport type { DevPortalPlugin } from \"../../core/plugins.js\";\nimport { generateRoutes } from \"./generateRoutes.js\";\n\nexport type MarkdownPluginOptions = {\n markdownFiles: Record<string, () => Promise<MDXImport>>;\n defaultOptions?: MarkdownPluginDefaultOptions;\n};\nexport type MarkdownPluginDefaultOptions = Pick<\n Frontmatter,\n \"toc\" | \"disablePager\"\n>;\n\nexport type Frontmatter = {\n title?: string;\n description?: string;\n category?: string;\n toc?: boolean;\n disablePager?: boolean;\n};\n\nexport type MDXImport = {\n tableOfContents: Toc;\n frontmatter: Frontmatter;\n default: (props: MDXProps) => JSX.Element;\n};\n\nexport const markdownPlugin = ({\n markdownFiles,\n defaultOptions,\n}: MarkdownPluginOptions): DevPortalPlugin => {\n return {\n getRoutes() {\n return generateRoutes(markdownFiles, defaultOptions);\n },\n };\n};\n"],"names":["generateRoutes","markdownFiles","defaultOptions","routes","file","importPromise","match","path","pathSegments","MdxPage","Component","props","jsx","rootRoutes","route","dir","Redirect","navItem","useTopNavigationItem","traverseNavigation","node","fullPath","isPathItem","Navigate","markdownPlugin"],"mappings":";;;;AAUa,MAAAA,IAAiB,CAC5BC,GACAC,MACkB;AAClB,QAAMC,IAAS,OAAO,QAAQF,CAAa,EAAE;AAAA,IAC3C,CAAC,CAACG,GAAMC,CAAa,MAAM;AAEnB,YAAAC,IAAQF,EAAK,MAAM,mBAAmB,GACtCG,IAAOD,KAAA,gBAAAA,EAAO,GAAG;AAEnB,UAAA,CAACC,EAAM,QAAO;AAEZ,YAAAC,IAAeD,EAAK,MAAM,GAAG;AAM5B,aAAA;AAAA,QACL,MANkBC,EAAa,GAAG,EAAE,MAAM,UAExCA,EAAa,MAAM,GAAG,EAAE,EAAE,KAAK,GAAG,IAClCD;AAAA,QAIF,MAAM,YAAY;AAChB,gBAAM,EAAE,SAAAE,EAAA,IAAY,MAAM,OAAO,uBAAc,GACzC,EAAE,SAASC,GAAW,GAAGC,EAAM,IAAI,MAAMN;AACxC,iBAAA;AAAA,YACL,SACEO,gBAAAA,EAAA;AAAA,cAACH;AAAA,cAAA;AAAA,gBACC,cAAcC;AAAA,gBACb,GAAGC;AAAA,gBACJ,gBAAAT;AAAA,cAAA;AAAA,YACF;AAAA,UAAA;AAAA,QAGN;AAAA,MAAA;AAAA,IAEJ;AAAA,EAAA,GAGIW,IAAa,MAAM;AAAA,IACvB,IAAI,IAAIV,EAAO,IAAI,CAACW,MAAUA,EAAM,KAAK,MAAM,GAAG,EAAE,GAAG,CAAC,CAAC,CAAC;AAAA,EAAA,EAC1D,IAAI,CAACC,OAAS;AAAA,IACd,MAAM,IAAIA,CAAG;AAAA,IACb,+BAAUC,GAAS,EAAA;AAAA,EACnB,EAAA;AAEF,SAAO,CAAC,GAAGb,GAAQ,GAAGU,CAAU;AAClC,GAEMG,IAAW,MAAM;AACrB,QAAMC,IAAUC;AAEZ,SAACD,IAEEE,EAAmBF,GAAS,CAACG,GAAMC,MAAa;AACrD,QAAI,gBAAcD,KAAQ,CAACE,EAAWF,CAAI;AAC1C,aAAQR,gBAAAA,EAAAA,IAAAW,GAAA,EAAS,IAAIF,GAAU,SAAO,GAAC,CAAA;AAAA,EAAA,CACxC,IALoB;AAMvB,GCtCaG,IAAiB,CAAC;AAAA,EAC7B,eAAAvB;AAAA,EACA,gBAAAC;AACF,OACS;AAAA,EACL,YAAY;AACH,WAAAF,EAAeC,GAAeC,CAAc;AAAA,EACrD;AAAA;"}
1
+ {"version":3,"file":"zudoku.plugin-markdown.js","sources":[],"sourcesContent":[],"names":[],"mappings":";"}
@@ -1,8 +1,10 @@
1
- import "./jsx-runtime-SV6hXQua.js";
2
- import { o as t } from "./index-Cpdpun6t.js";
1
+ import "./jsx-runtime-CM0TzjGp.js";
2
+ import { o as n } from "./index-BjSy8IQO.js";
3
3
  import "./urql-DMlBWUKL.js";
4
4
  import "virtual:zudoku-openapi-worker";
5
+ import "./MdxComponents-Ev_hBHb2.js";
6
+ import "./router-CcYTwKjf.js";
5
7
  export {
6
- t as openApiPlugin
8
+ n as openApiPlugin
7
9
  };
8
10
  //# sourceMappingURL=zudoku.plugin-openapi.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"zudoku.plugin-openapi.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;"}
1
+ {"version":3,"file":"zudoku.plugin-openapi.js","sources":[],"sourcesContent":[],"names":[],"mappings":";;;;;;"}
@@ -1,12 +1,11 @@
1
- import { j as s } from "./jsx-runtime-SV6hXQua.js";
2
- import { N as i } from "./index-DLS6fPwU.js";
3
- const p = (t) => ({
4
- getRoutes: () => t.redirects.map(({ from: e, to: r, replace: o }) => ({
5
- path: e,
6
- element: /* @__PURE__ */ s.jsx(i, { to: r, replace: o })
1
+ import { b as o } from "./router-CcYTwKjf.js";
2
+ const i = (e) => ({
3
+ getRoutes: () => e.redirects.map(({ from: r, to: t, replace: a }) => ({
4
+ path: r,
5
+ loader: () => o(t)
7
6
  }))
8
7
  });
9
8
  export {
10
- p as redirectPlugin
9
+ i as redirectPlugin
11
10
  };
12
11
  //# sourceMappingURL=zudoku.plugin-redirect.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"zudoku.plugin-redirect.js","sources":["../src/lib/plugins/redirect/index.tsx"],"sourcesContent":["import { Navigate } from \"react-router-dom\";\nimport type { DevPortalPlugin } from \"../../core/plugins.js\";\n\nexport type Redirect = {\n from: string;\n to: string;\n replace?: boolean;\n};\n\nexport const redirectPlugin = (options: {\n redirects: Redirect[];\n}): DevPortalPlugin => {\n return {\n getRoutes: () =>\n options.redirects.map(({ from, to, replace }) => ({\n path: from,\n element: <Navigate to={to} replace={replace} />,\n })),\n };\n};\n"],"names":["redirectPlugin","options","from","to","replace","jsx","Navigate"],"mappings":";;AASa,MAAAA,IAAiB,CAACC,OAGtB;AAAA,EACL,WAAW,MACTA,EAAQ,UAAU,IAAI,CAAC,EAAE,MAAAC,GAAM,IAAAC,GAAI,SAAAC,SAAe;AAAA,IAChD,MAAMF;AAAA,IACN,SAASG,gBAAAA,EAAAA,IAACC,GAAS,EAAA,IAAAH,GAAQ,SAAAC,EAAkB,CAAA;AAAA,EAAA,EAC7C;AAAA;"}
1
+ {"version":3,"file":"zudoku.plugin-redirect.js","sources":["../src/lib/plugins/redirect/index.tsx"],"sourcesContent":["import { redirect } from \"react-router-dom\";\nimport type { DevPortalPlugin } from \"../../core/plugins.js\";\n\nexport type Redirect = {\n from: string;\n to: string;\n replace?: boolean;\n};\n\nexport const redirectPlugin = (options: {\n redirects: Redirect[];\n}): DevPortalPlugin => {\n return {\n getRoutes: () =>\n options.redirects.map(({ from, to, replace }) => ({\n path: from,\n loader: () => redirect(to),\n })),\n };\n};\n"],"names":["redirectPlugin","options","from","to","replace","redirect"],"mappings":";AASa,MAAAA,IAAiB,CAACC,OAGtB;AAAA,EACL,WAAW,MACTA,EAAQ,UAAU,IAAI,CAAC,EAAE,MAAAC,GAAM,IAAAC,GAAI,SAAAC,SAAe;AAAA,IAChD,MAAMF;AAAA,IACN,QAAQ,MAAMG,EAASF,CAAE;AAAA,EAAA,EACzB;AAAA;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zudoku",
3
- "version": "0.3.0-dev.31",
3
+ "version": "0.3.0-dev.33",
4
4
  "type": "module",
5
5
  "files": [
6
6
  "dist",
@@ -64,19 +64,23 @@
64
64
  "dependencies": {
65
65
  "@envelop/core": "5.0.1",
66
66
  "@graphql-typed-document-node/core": "3.2.0",
67
+ "@hiogawa/vite-plugin-ssr-css": "0.0.0",
67
68
  "@lekoarts/rehype-meta-as-attributes": "3.0.1",
68
69
  "@mdx-js/react": "3.0.1",
69
70
  "@mdx-js/rollup": "3.0.1",
70
71
  "@monaco-editor/react": "^4.6.0",
71
72
  "@pothos/core": "3.41.0",
73
+ "@radix-ui/react-collapsible": "1.1.0",
72
74
  "@radix-ui/react-select": "2.1.1",
73
75
  "@radix-ui/react-visually-hidden": "1.1.0",
74
76
  "@sentry/node": "8.11.0",
75
77
  "@stefanprobst/rehype-extract-toc": "2.2.0",
76
78
  "@tailwindcss/typography": "0.5.13",
79
+ "@tanstack/react-query": "5.50.1",
77
80
  "@vitejs/plugin-react": "4.3.1",
78
81
  "autoprefixer": "10.4.19",
79
82
  "chokidar": "^3.6.0",
83
+ "class-variance-authority": "0.7.0",
80
84
  "dotenv": "16.4.5",
81
85
  "express": "4.19.2",
82
86
  "graphql": "16.9.0",
@@ -111,20 +115,20 @@
111
115
  "slugify": "1.6.6",
112
116
  "strip-ansi": "7.1.0",
113
117
  "tailwindcss": "3.4.4",
118
+ "tailwind-merge": "2.3.0",
114
119
  "tiny-invariant": "1.3.3",
115
120
  "ulidx": "^2.3.0",
116
121
  "unist-util-visit": "5.0.0",
117
122
  "urql": "4.1.0",
118
123
  "vite": "5.3.3",
119
124
  "yaml": "2.4.1",
120
- "yargs": "17.7.2"
125
+ "yargs": "17.7.2",
126
+ "zustand": "4.5.4"
121
127
  },
122
128
  "devDependencies": {
123
- "@radix-ui/react-collapsible": "1.1.0",
124
129
  "@radix-ui/react-dialog": "1.1.1",
125
130
  "@radix-ui/react-slot": "1.1.0",
126
131
  "@radix-ui/react-tabs": "1.1.0",
127
- "@tanstack/react-query": "5.50.1",
128
132
  "@types/express": "^4.17.21",
129
133
  "@types/har-format": "^1.2.15",
130
134
  "@types/json-schema": "7.0.15",
@@ -137,7 +141,6 @@
137
141
  "@types/semver": "^7.5.8",
138
142
  "@types/yargs": "^17.0.32",
139
143
  "@zudoku/httpsnippet": "10.0.9",
140
- "class-variance-authority": "0.7.0",
141
144
  "clsx": "2.1.1",
142
145
  "lucide-react": "0.378.0",
143
146
  "oauth4webapi": "2.11.1",
@@ -147,9 +150,7 @@
147
150
  "react-markdown": "9.0.1",
148
151
  "react-router-dom": "6.24.1",
149
152
  "rollup-plugin-visualizer": "^5.12.0",
150
- "tailwind-merge": "2.3.0",
151
- "typescript": "5.5.3",
152
- "zustand": "4.5.4"
153
+ "typescript": "5.5.3"
153
154
  },
154
155
  "peerDependencies": {
155
156
  "react": ">18.0.0",
File without changes
@@ -0,0 +1,64 @@
1
+ import { StrictMode } from "react";
2
+ import { createRoot, hydrateRoot } from "react-dom/client";
3
+ import { HelmetProvider } from "react-helmet-async";
4
+ import {
5
+ createBrowserRouter,
6
+ matchRoutes,
7
+ RouterProvider,
8
+ type RouteObject,
9
+ } from "react-router-dom";
10
+ import "virtual:vite-zudoku-custom-css.css";
11
+ import config from "virtual:zudoku-config";
12
+
13
+ import "virtual:vite-zudoku-custom-css.css";
14
+ import "./main.css";
15
+
16
+ import { getRoutesByConfig } from "./main.js";
17
+
18
+ const routes = getRoutesByConfig(config);
19
+ const root = document.getElementById("root")!;
20
+
21
+ const RootReactElement = ({
22
+ router,
23
+ }: {
24
+ router: ReturnType<typeof createBrowserRouter>;
25
+ }) => (
26
+ <StrictMode>
27
+ <HelmetProvider>
28
+ <RouterProvider router={router} />
29
+ </HelmetProvider>
30
+ </StrictMode>
31
+ );
32
+
33
+ if (root.childElementCount > 0) {
34
+ void hydrate(routes);
35
+ } else {
36
+ void render(routes);
37
+ }
38
+
39
+ async function hydrateLazyRoutes(routes: RouteObject[]) {
40
+ const lazyMatches = matchRoutes(routes, window.location)?.filter(
41
+ (m) => m.route.lazy,
42
+ );
43
+
44
+ if (lazyMatches?.length) {
45
+ await Promise.all(
46
+ lazyMatches.map(async (m) => {
47
+ const routeModule = await m.route.lazy!();
48
+ Object.assign(m.route, { ...routeModule, lazy: undefined });
49
+ }),
50
+ );
51
+ }
52
+ }
53
+
54
+ function render(routes: RouteObject[]) {
55
+ const router = createBrowserRouter(routes);
56
+ createRoot(root).render(<RootReactElement router={router} />);
57
+ }
58
+
59
+ async function hydrate(routes: RouteObject[]) {
60
+ await hydrateLazyRoutes(routes);
61
+ const router = createBrowserRouter(routes);
62
+
63
+ hydrateRoot(root, <RootReactElement router={router} />);
64
+ }
@@ -0,0 +1,158 @@
1
+ import type express from "express";
2
+ import logger from "loglevel";
3
+ import { Transform } from "node:stream";
4
+ import { StrictMode } from "react";
5
+ import { renderToPipeableStream, renderToStaticMarkup } from "react-dom/server";
6
+ import { HelmetData, HelmetProvider } from "react-helmet-async";
7
+ import { isRouteErrorResponse } from "react-router-dom";
8
+ import {
9
+ createStaticHandler,
10
+ createStaticRouter,
11
+ StaticRouterProvider,
12
+ } from "react-router-dom/server.js";
13
+ import "virtual:vite-zudoku-custom-css.css";
14
+ import config from "virtual:zudoku-config";
15
+ import { ServerError } from "../lib/errors/ServerError.js";
16
+ import "./main.css";
17
+ import { getRoutesByConfig } from "./main.js";
18
+
19
+ export const render = async ({
20
+ template,
21
+ expressRequest,
22
+ fetchRequest,
23
+ response,
24
+ }: {
25
+ template: string;
26
+ expressRequest?: express.Request;
27
+ fetchRequest?: Request;
28
+ response: express.Response;
29
+ }) => {
30
+ const routes = getRoutesByConfig(config);
31
+ const { query, dataRoutes } = createStaticHandler(routes);
32
+
33
+ const request = expressRequest
34
+ ? createFetchRequest(expressRequest, response)
35
+ : fetchRequest;
36
+
37
+ if (!request) {
38
+ throw new Error("Either fetchRequest or expressRequest must be provided");
39
+ }
40
+ const context = await query(request);
41
+ let status = 200;
42
+
43
+ if (context instanceof Response) {
44
+ if ([301, 302, 303, 307, 308].includes(context.status)) {
45
+ return response.redirect(
46
+ context.status,
47
+ context.headers.get("Location")!,
48
+ );
49
+ }
50
+
51
+ throw context;
52
+ } else if (context.errors) {
53
+ // when throwing a Response from a loader it will be caught here
54
+ // unfortunately it is not `instanceof Response` for some reason
55
+ const firstError = Object.values(context.errors).find(isRouteErrorResponse);
56
+
57
+ if (firstError?.status) {
58
+ status = firstError.status;
59
+ }
60
+ }
61
+
62
+ const router = createStaticRouter(dataRoutes, context);
63
+ const helmetContext = {} as HelmetData["context"];
64
+
65
+ const { pipe } = renderToPipeableStream(
66
+ <StrictMode>
67
+ <HelmetProvider context={helmetContext}>
68
+ <StaticRouterProvider router={router} context={context} />
69
+ </HelmetProvider>
70
+ </StrictMode>,
71
+ {
72
+ onShellError(error) {
73
+ response.status(500);
74
+ response.set({ "Content-Type": "text/html" });
75
+
76
+ const html = renderToStaticMarkup(<ServerError error={error} />);
77
+
78
+ response.send(html);
79
+ },
80
+ // for SSG we could use onAllReady instead of onShellReady
81
+ // https://react.dev/reference/react-dom/server/renderToPipeableStream#waiting-for-all-content-to-load-for-crawlers-and-static-generation
82
+ onShellReady() {
83
+ response.set({ "Content-Type": "text/html" });
84
+ response.status(status);
85
+
86
+ const transformStream = new Transform({
87
+ transform(chunk, encoding, callback) {
88
+ response.write(chunk, encoding);
89
+ callback();
90
+ },
91
+ });
92
+
93
+ const [htmlStart, htmlEnd] = template.split("<!--app-html-->");
94
+
95
+ response.write(
96
+ htmlStart.replace(
97
+ "<!--app-helmet-->",
98
+ [
99
+ helmetContext.helmet.title.toString(),
100
+ helmetContext.helmet.meta.toString(),
101
+ helmetContext.helmet.link.toString(),
102
+ helmetContext.helmet.style.toString(),
103
+ helmetContext.helmet.script.toString(),
104
+ ].join("\n"),
105
+ ),
106
+ );
107
+
108
+ transformStream.on("finish", () => {
109
+ response.end(htmlEnd);
110
+ });
111
+
112
+ pipe(transformStream);
113
+ },
114
+ onError(error) {
115
+ status = 500;
116
+ logger.error(error);
117
+ },
118
+ },
119
+ );
120
+ };
121
+
122
+ export function createFetchRequest(
123
+ req: express.Request,
124
+ res: express.Response,
125
+ ): Request {
126
+ const origin = `${req.protocol}://${req.get("host")}`;
127
+ // Note: This had to take originalUrl into account for presumably vite's proxying
128
+ const url = new URL(req.originalUrl || req.url, origin);
129
+
130
+ const controller = new AbortController();
131
+ res.on("close", () => controller.abort());
132
+
133
+ const headers = new Headers();
134
+
135
+ for (const [key, values] of Object.entries(req.headers)) {
136
+ if (values) {
137
+ if (Array.isArray(values)) {
138
+ for (const value of values) {
139
+ headers.append(key, value);
140
+ }
141
+ } else {
142
+ headers.set(key, values);
143
+ }
144
+ }
145
+ }
146
+
147
+ const init: RequestInit = {
148
+ method: req.method,
149
+ headers,
150
+ signal: controller.signal,
151
+ };
152
+
153
+ if (req.method !== "GET" && req.method !== "HEAD") {
154
+ init.body = req.body;
155
+ }
156
+
157
+ return new Request(url.href, init);
158
+ }
package/src/app/main.tsx CHANGED
@@ -1,51 +1,73 @@
1
- import { StrictMode } from "react";
2
- import { createRoot } from "react-dom/client";
3
-
4
- // Styles
5
- import "./main.css";
6
-
7
- // Logger
8
- import "../lib/util/logInit.js";
9
-
10
- // Config
11
- import config from "virtual:zudoku-config";
12
-
13
- // Plugins
1
+ import { type RouteObject } from "react-router-dom";
14
2
  import { configuredApiKeysPlugin } from "virtual:zudoku-api-keys-plugin";
15
3
  import { configuredApiPlugins } from "virtual:zudoku-api-plugins";
16
4
  import { configuredAuthProvider } from "virtual:zudoku-auth";
17
5
  import { configuredDocsPlugins } from "virtual:zudoku-docs-plugins";
18
6
  import { configuredRedirectPlugin } from "virtual:zudoku-redirect-plugin";
19
-
20
- // Base React Component
21
7
  import { DevPortal } from "zudoku/components";
8
+ import type { ZudokuConfig } from "../config/config.js";
9
+ import { Layout } from "../lib/components/Layout.js";
10
+ import { isNavigationPlugin } from "../lib/core/plugins.js";
11
+ import { RouterError } from "../lib/errors/RouterError.js";
12
+
13
+ import "virtual:vite-zudoku-custom-css.css";
14
+
15
+ export const convertZudokuConfigToOptions = (config: ZudokuConfig) => {
16
+ return {
17
+ page: {
18
+ logo: config.page?.logo ?? "https://cdn.zudoku.dev/logos/icon.svg",
19
+ pageTitle: "Developer Portal",
20
+ ...config.page,
21
+ },
22
+ metadata: {
23
+ favicon: "https://cdn.zudoku.dev/logos/icon.svg",
24
+ title: "%s | Developer Portal",
25
+ ...config.metadata,
26
+ },
27
+ navigation: config.navigation ?? [],
28
+ authentication: configuredAuthProvider,
29
+ plugins: [
30
+ ...configuredDocsPlugins,
31
+ ...configuredApiPlugins,
32
+ ...(configuredRedirectPlugin ? [configuredRedirectPlugin] : []),
33
+ ...(configuredApiKeysPlugin ? [configuredApiKeysPlugin] : []),
34
+ ...(configuredAuthProvider ? [configuredAuthProvider] : []),
35
+ ],
36
+ };
37
+ };
38
+
39
+ export const getRoutesByConfig = (config: ZudokuConfig): RouteObject[] => {
40
+ const options = convertZudokuConfigToOptions(config);
41
+
42
+ const allPlugins = [
43
+ ...options.plugins,
44
+ ...(options.authentication ? [options.authentication] : []),
45
+ ];
22
46
 
23
- // IMPORTANT: This component must not contain tailwind classes
24
- // This directory is not processed by the tailwind plugin
47
+ const routes = allPlugins
48
+ .flatMap((plugin) => (isNavigationPlugin(plugin) ? plugin.getRoutes() : []))
49
+ .concat({
50
+ path: "*",
51
+ loader: () => {
52
+ throw new Response("Not Found", { status: 404 });
53
+ },
54
+ });
25
55
 
26
- createRoot(document.getElementById("root")!).render(
27
- <StrictMode>
28
- <DevPortal
29
- page={{
30
- logo: config.page?.logo ?? "https://cdn.zudoku.dev/logos/icon.svg",
31
- pageTitle: "Developer Portal",
32
- ...config.page,
33
- }}
34
- metadata={{
35
- favicon: "https://cdn.zudoku.dev/logos/icon.svg",
36
- title: "%s | Developer Portal",
37
- ...config.metadata,
38
- }}
39
- navigation={config.navigation ?? []}
40
- authentication={configuredAuthProvider}
41
- mdxComponents={config.mdx?.components}
42
- plugins={[
43
- ...configuredDocsPlugins,
44
- ...configuredApiPlugins,
45
- configuredRedirectPlugin,
46
- ...(configuredApiKeysPlugin ? [configuredApiKeysPlugin] : []),
47
- ...(configuredAuthProvider ? [configuredAuthProvider] : []),
48
- ]}
49
- />
50
- </StrictMode>,
51
- );
56
+ return [
57
+ {
58
+ element: (
59
+ <DevPortal {...options}>
60
+ <Layout />
61
+ </DevPortal>
62
+ ),
63
+ errorElement: (
64
+ <DevPortal {...options}>
65
+ <Layout>
66
+ <RouterError />
67
+ </Layout>
68
+ </DevPortal>
69
+ ),
70
+ children: routes,
71
+ },
72
+ ];
73
+ };
@@ -2,8 +2,14 @@ import typographyPlugin from "@tailwindcss/typography";
2
2
  import type { Config } from "tailwindcss";
3
3
  import defaultTheme from "tailwindcss/defaultTheme.js";
4
4
 
5
+ const content = [
6
+ "./src/**/*.{js,ts,jsx,tsx,md,mdx}",
7
+ "./node_modules/zudoku/dist/**/*.{js,ts,jsx,tsx,md,mdx}",
8
+ ];
9
+
5
10
  const config: Omit<Config, "content"> = {
6
11
  darkMode: "selector",
12
+ content,
7
13
  theme: {
8
14
  extend: {
9
15
  fontFamily: {
@@ -0,0 +1,22 @@
1
+ import type { RouteObject } from "react-router-dom";
2
+ import config from "virtual:zudoku-config";
3
+ import { getRoutesByConfig } from "./main.js";
4
+
5
+ const routes = getRoutesByConfig(config);
6
+
7
+ const flattenPaths = (routes: RouteObject[], basePath = "") => {
8
+ return routes.reduce<string[]>((acc, route) => {
9
+ if (route.path) {
10
+ const fullPath = `${basePath}/${route.path}`.replace(/\/+/g, "/");
11
+ route.path !== "/" && acc.push(fullPath);
12
+ if (route.children) {
13
+ acc = acc.concat(flattenPaths(route.children, fullPath));
14
+ }
15
+ } else if (route.children) {
16
+ acc = acc.concat(flattenPaths(route.children, basePath));
17
+ }
18
+ return acc;
19
+ }, []);
20
+ };
21
+
22
+ export const paths = flattenPaths(routes);
@@ -9,6 +9,7 @@ const clerkAuth: AuthenticationProviderInitializer<
9
9
  let clerkApi: Clerk;
10
10
 
11
11
  const ensureLoaded = (async () => {
12
+ if (import.meta.env.SSR) return;
12
13
  const { Clerk } = await import("@clerk/clerk-js");
13
14
  clerkApi = new Clerk(clerkPubKey);
14
15
 
@@ -1,8 +1,14 @@
1
1
  import { MDXProvider } from "@mdx-js/react";
2
2
  import { QueryClientProvider } from "@tanstack/react-query";
3
- import { Fragment, memo, Suspense, useEffect, useMemo } from "react";
3
+ import {
4
+ Fragment,
5
+ memo,
6
+ type PropsWithChildren,
7
+ useEffect,
8
+ useMemo,
9
+ } from "react";
4
10
  import { ErrorBoundary } from "react-error-boundary";
5
- import { Helmet, HelmetProvider } from "react-helmet-async";
11
+ import { Helmet } from "react-helmet-async";
6
12
  import {
7
13
  DevPortalContext,
8
14
  queryClient,
@@ -18,9 +24,8 @@ import {
18
24
  import { DevPortalProvider } from "./context/DevPortalProvider.js";
19
25
  import { ThemeProvider } from "./context/ThemeContext.js";
20
26
  import { ViewportAnchorProvider } from "./context/ViewportAnchorContext.js";
21
- import { Router } from "./Router.js";
22
27
 
23
- const DevPortalSystemPaths = {
28
+ export const DevPortalSystemPaths = {
24
29
  Settings: "/settings",
25
30
  } as const;
26
31
 
@@ -28,7 +33,10 @@ export type DevPortalPath =
28
33
  | string
29
34
  | (typeof DevPortalSystemPaths)[keyof typeof DevPortalSystemPaths];
30
35
 
31
- const DevPortalInner = (props: ZudokuContextOptions) => {
36
+ const DevPortalInner = ({
37
+ children,
38
+ ...props
39
+ }: PropsWithChildren<ZudokuContextOptions>) => {
32
40
  const components = useMemo(
33
41
  () => ({ ...DEFAULT_COMPONENTS, ...props.overrides }),
34
42
  [props.overrides],
@@ -52,39 +60,23 @@ const DevPortalInner = (props: ZudokuContextOptions) => {
52
60
 
53
61
  return (
54
62
  <QueryClientProvider client={queryClient}>
55
- <HelmetProvider>
56
- <Helmet>{heads}</Helmet>
57
- <DevPortalProvider value={devPortalContext}>
58
- <MDXProvider components={mdxComponents}>
59
- <ThemeProvider>
60
- <ComponentsProvider value={components}>
61
- <ViewportAnchorProvider>
62
- <Suspense
63
- fallback={
64
- <div className="grid place-items-center h-full">
65
- Loading...
66
- </div>
67
- }
68
- >
69
- <Router
70
- plugins={[
71
- ...(props.plugins ?? []),
72
- ...(props.authentication ? [props.authentication] : []),
73
- ]}
74
- />
75
- </Suspense>
76
- </ViewportAnchorProvider>
77
- </ComponentsProvider>
78
- </ThemeProvider>
79
- </MDXProvider>
80
- </DevPortalProvider>
81
- </HelmetProvider>
63
+ <Helmet>{heads}</Helmet>
64
+ <DevPortalProvider value={devPortalContext}>
65
+ <MDXProvider components={mdxComponents}>
66
+ <ThemeProvider>
67
+ <ComponentsProvider value={components}>
68
+ <ViewportAnchorProvider>{children}</ViewportAnchorProvider>
69
+ </ComponentsProvider>
70
+ </ThemeProvider>
71
+ </MDXProvider>
72
+ </DevPortalProvider>
82
73
  </QueryClientProvider>
83
74
  );
84
75
  };
85
76
 
77
+ const Inner = memo(DevPortalInner);
78
+
86
79
  const DevPortal = (props: ZudokuContextOptions) => {
87
- const Inner = memo(DevPortalInner);
88
80
  return (
89
81
  <ErrorBoundary FallbackComponent={TopLevelError}>
90
82
  <Inner {...props} />
@@ -0,0 +1,28 @@
1
+ import type { ReactNode } from "react";
2
+ import { Link } from "react-router-dom";
3
+ import { CategoryHeading } from "./CategoryHeading.js";
4
+ import { Heading } from "./Heading.js";
5
+ import { ProseClasses } from "./Markdown.js";
6
+
7
+ export const ErrorPage = ({
8
+ title = "An error occurred",
9
+ message,
10
+ category,
11
+ }: {
12
+ title?: ReactNode;
13
+ message?: ReactNode;
14
+ category?: ReactNode;
15
+ }) => {
16
+ return (
17
+ <div className={ProseClasses + " h-full pt-[--padding-content-top]"}>
18
+ {category && <CategoryHeading>{category}</CategoryHeading>}
19
+ {title && (
20
+ <Heading level={1} className="flex gap-3.5 items-center">
21
+ {title}
22
+ </Heading>
23
+ )}
24
+ <p>{message}</p>
25
+ <Link to="/">Go back home</Link>
26
+ </div>
27
+ );
28
+ };
@@ -0,0 +1,19 @@
1
+ import type { ReactNode } from "react";
2
+ import { cn } from "../util/cn.js";
3
+
4
+ export const InlineCode = ({
5
+ className,
6
+ children,
7
+ }: {
8
+ className?: string;
9
+ children: ReactNode;
10
+ }) => (
11
+ <code
12
+ className={cn(
13
+ className,
14
+ "font-mono border border-border p-1 py-0.5 rounded bg-border/50 dark:bg-border/70 whitespace-nowrap",
15
+ )}
16
+ >
17
+ {children}
18
+ </code>
19
+ );