polen 0.10.0-next.12 → 0.10.0-next.14

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 (141) hide show
  1. package/build/api/vite/plugins/build.d.ts.map +1 -1
  2. package/build/api/vite/plugins/build.js +11 -3
  3. package/build/api/vite/plugins/build.js.map +1 -1
  4. package/build/api/vite/plugins/core.d.ts.map +1 -1
  5. package/build/api/vite/plugins/core.js +12 -10
  6. package/build/api/vite/plugins/core.js.map +1 -1
  7. package/build/api/vite/plugins/pages.d.ts.map +1 -1
  8. package/build/api/vite/plugins/pages.js +6 -7
  9. package/build/api/vite/plugins/pages.js.map +1 -1
  10. package/build/api/vite/plugins/serve.d.ts.map +1 -1
  11. package/build/api/vite/plugins/serve.js +47 -7
  12. package/build/api/vite/plugins/serve.js.map +1 -1
  13. package/build/lib/file-router/diagnostic-reporter.js +2 -2
  14. package/build/lib/file-router/diagnostic-reporter.js.map +1 -1
  15. package/build/lib/graphql-document/components/CopyButton.d.ts +19 -0
  16. package/build/lib/graphql-document/components/CopyButton.d.ts.map +1 -0
  17. package/build/lib/graphql-document/components/CopyButton.js +43 -0
  18. package/build/lib/graphql-document/components/CopyButton.js.map +1 -0
  19. package/build/lib/graphql-document/components/GraphQLDocument.d.ts +0 -4
  20. package/build/lib/graphql-document/components/GraphQLDocument.d.ts.map +1 -1
  21. package/build/lib/graphql-document/components/GraphQLDocument.js +52 -83
  22. package/build/lib/graphql-document/components/GraphQLDocument.js.map +1 -1
  23. package/build/lib/graphql-document/components/GraphQLIdentifierPopover.d.ts +33 -0
  24. package/build/lib/graphql-document/components/GraphQLIdentifierPopover.d.ts.map +1 -0
  25. package/build/lib/graphql-document/components/GraphQLIdentifierPopover.js +48 -0
  26. package/build/lib/graphql-document/components/GraphQLIdentifierPopover.js.map +1 -0
  27. package/build/lib/graphql-document/components/IdentifierLink.d.ts +15 -13
  28. package/build/lib/graphql-document/components/IdentifierLink.d.ts.map +1 -1
  29. package/build/lib/graphql-document/components/IdentifierLink.js +51 -117
  30. package/build/lib/graphql-document/components/IdentifierLink.js.map +1 -1
  31. package/build/lib/graphql-document/components/graphql-document-styles.d.ts +5 -0
  32. package/build/lib/graphql-document/components/graphql-document-styles.d.ts.map +1 -0
  33. package/build/lib/graphql-document/components/graphql-document-styles.js +167 -0
  34. package/build/lib/graphql-document/components/graphql-document-styles.js.map +1 -0
  35. package/build/lib/graphql-document/components/index.d.ts +2 -1
  36. package/build/lib/graphql-document/components/index.d.ts.map +1 -1
  37. package/build/lib/graphql-document/components/index.js +2 -1
  38. package/build/lib/graphql-document/components/index.js.map +1 -1
  39. package/build/lib/graphql-document/hooks/use-tooltip-state.d.ts +43 -0
  40. package/build/lib/graphql-document/hooks/use-tooltip-state.d.ts.map +1 -0
  41. package/build/lib/graphql-document/hooks/use-tooltip-state.js +132 -0
  42. package/build/lib/graphql-document/hooks/use-tooltip-state.js.map +1 -0
  43. package/build/lib/graphql-document/positioning-simple.d.ts +0 -5
  44. package/build/lib/graphql-document/positioning-simple.d.ts.map +1 -1
  45. package/build/lib/graphql-document/positioning-simple.js +78 -90
  46. package/build/lib/graphql-document/positioning-simple.js.map +1 -1
  47. package/build/lib/kit-temp.d.ts +103 -0
  48. package/build/lib/kit-temp.d.ts.map +1 -1
  49. package/build/lib/kit-temp.js +236 -2
  50. package/build/lib/kit-temp.js.map +1 -1
  51. package/build/lib/vite-plugin-reactive-data/vite-plugin-reactive-data.d.ts +1 -8
  52. package/build/lib/vite-plugin-reactive-data/vite-plugin-reactive-data.d.ts.map +1 -1
  53. package/build/lib/vite-plugin-reactive-data/vite-plugin-reactive-data.js +48 -53
  54. package/build/lib/vite-plugin-reactive-data/vite-plugin-reactive-data.js.map +1 -1
  55. package/build/package-paths.js +3 -3
  56. package/build/package-paths.js.map +1 -1
  57. package/build/template/components/Link.d.ts +1 -1
  58. package/build/template/components/Link.d.ts.map +1 -1
  59. package/build/template/components/Link.js +14 -5
  60. package/build/template/components/Link.js.map +1 -1
  61. package/build/template/components/content/GraphQLDocumentWithSchema.d.ts.map +1 -1
  62. package/build/template/components/content/GraphQLDocumentWithSchema.js +0 -3
  63. package/build/template/components/content/GraphQLDocumentWithSchema.js.map +1 -1
  64. package/build/template/components/content/GraphQLDocumentWrapper.d.ts.map +1 -1
  65. package/build/template/components/content/GraphQLDocumentWrapper.js +8 -7
  66. package/build/template/components/content/GraphQLDocumentWrapper.js.map +1 -1
  67. package/build/template/components/sidebar/SidebarItem.js +2 -2
  68. package/build/template/entry.client.d.ts.map +1 -1
  69. package/build/template/entry.client.js +0 -3
  70. package/build/template/entry.client.js.map +1 -1
  71. package/build/template/hooks/useClientOnly.d.ts +9 -0
  72. package/build/template/hooks/useClientOnly.d.ts.map +1 -0
  73. package/build/template/hooks/useClientOnly.js +16 -0
  74. package/build/template/hooks/useClientOnly.js.map +1 -0
  75. package/build/template/routes/root.d.ts.map +1 -1
  76. package/build/template/routes/root.js +2 -150
  77. package/build/template/routes/root.js.map +1 -1
  78. package/build/template/server/app.d.ts +8 -1
  79. package/build/template/server/app.d.ts.map +1 -1
  80. package/build/template/server/app.js +21 -21
  81. package/build/template/server/app.js.map +1 -1
  82. package/build/template/server/create-page-html-response.d.ts +7 -0
  83. package/build/template/server/create-page-html-response.d.ts.map +1 -0
  84. package/build/template/server/{render-page.js → create-page-html-response.js} +11 -16
  85. package/build/template/server/create-page-html-response.js.map +1 -0
  86. package/build/template/server/main.js +2 -1
  87. package/build/template/server/main.js.map +1 -1
  88. package/build/template/server/middleware/page.d.ts +4 -0
  89. package/build/template/server/middleware/page.d.ts.map +1 -0
  90. package/build/template/server/middleware/page.js +15 -0
  91. package/build/template/server/middleware/page.js.map +1 -0
  92. package/build/template/server/middleware/unsupported-assets.d.ts +10 -0
  93. package/build/template/server/middleware/unsupported-assets.d.ts.map +1 -0
  94. package/build/template/server/middleware/unsupported-assets.js +21 -0
  95. package/build/template/server/middleware/unsupported-assets.js.map +1 -0
  96. package/build/template/server/ssg/generate.d.ts.map +1 -1
  97. package/build/template/server/ssg/generate.js +33 -34
  98. package/build/template/server/ssg/generate.js.map +1 -1
  99. package/build/template/styles/code-block.css +218 -0
  100. package/package.json +4 -2
  101. package/src/api/singletons/markdown/markdown.test.ts +1 -1
  102. package/src/api/vite/plugins/build.ts +97 -89
  103. package/src/api/vite/plugins/core.ts +15 -10
  104. package/src/api/vite/plugins/pages.ts +9 -7
  105. package/src/api/vite/plugins/serve.ts +62 -9
  106. package/src/lib/file-router/diagnostic-reporter.ts +2 -2
  107. package/src/lib/graphql-document/components/CopyButton.tsx +76 -0
  108. package/src/lib/graphql-document/components/GraphQLDocument.tsx +73 -95
  109. package/src/lib/graphql-document/components/GraphQLIdentifierPopover.tsx +197 -0
  110. package/src/lib/graphql-document/components/IdentifierLink.tsx +105 -166
  111. package/src/lib/graphql-document/components/graphql-document-styles.ts +167 -0
  112. package/src/lib/graphql-document/components/index.ts +2 -1
  113. package/src/lib/graphql-document/hooks/use-tooltip-state.test.ts +76 -0
  114. package/src/lib/graphql-document/hooks/use-tooltip-state.ts +191 -0
  115. package/src/lib/graphql-document/positioning-simple.test.ts +18 -22
  116. package/src/lib/graphql-document/positioning-simple.ts +97 -108
  117. package/src/lib/kit-temp.test.ts +15 -3
  118. package/src/lib/kit-temp.ts +304 -4
  119. package/src/lib/vite-plugin-reactive-data/vite-plugin-reactive-data.ts +52 -58
  120. package/src/package-paths.ts +3 -3
  121. package/src/template/components/Link.tsx +20 -12
  122. package/src/template/components/content/GraphQLDocumentWithSchema.tsx +0 -5
  123. package/src/template/components/content/GraphQLDocumentWrapper.tsx +14 -7
  124. package/src/template/components/sidebar/SidebarItem.tsx +2 -2
  125. package/src/template/entry.client.tsx +0 -3
  126. package/src/template/hooks/useClientOnly.ts +21 -0
  127. package/src/template/routes/root.tsx +0 -159
  128. package/src/template/server/app.ts +33 -23
  129. package/src/template/server/{render-page.tsx → create-page-html-response.ts} +19 -16
  130. package/src/template/server/main.ts +2 -1
  131. package/src/template/server/middleware/page.ts +19 -0
  132. package/src/template/server/middleware/unsupported-assets.ts +25 -0
  133. package/src/template/server/ssg/generate.ts +68 -72
  134. package/build/lib/graphql-document/components/HoverTooltip.d.ts +0 -35
  135. package/build/lib/graphql-document/components/HoverTooltip.d.ts.map +0 -1
  136. package/build/lib/graphql-document/components/HoverTooltip.js +0 -132
  137. package/build/lib/graphql-document/components/HoverTooltip.js.map +0 -1
  138. package/build/template/server/render-page.d.ts +0 -3
  139. package/build/template/server/render-page.d.ts.map +0 -1
  140. package/build/template/server/render-page.js.map +0 -1
  141. package/src/lib/graphql-document/components/HoverTooltip.tsx +0 -282
@@ -4,7 +4,6 @@ import { GrafaidOld } from '#lib/grafaid-old/index'
4
4
  import { createRoute } from '#lib/react-router-aid/react-router-aid'
5
5
  import { Box, Grid } from '@radix-ui/themes'
6
6
  import { Flex, Theme } from '@radix-ui/themes'
7
- import radixStylesUrl from '@radix-ui/themes/styles.css?url'
8
7
  import { Arr } from '@wollybeard/kit'
9
8
  import { useEffect, useState } from 'react'
10
9
  import { Link as LinkReactRouter } from 'react-router'
@@ -24,23 +23,12 @@ import { NotFound } from '../components/NotFound.tsx'
24
23
  import { Sidebar } from '../components/sidebar/Sidebar.tsx'
25
24
  import { ThemeToggle } from '../components/ThemeToggle.tsx'
26
25
  import { ThemeProvider, useTheme } from '../contexts/ThemeContext.tsx'
27
- import entryClientUrl from '../entry.client.jsx?url'
28
26
  import { changelog } from './changelog.tsx'
29
27
  import { index } from './index.tsx'
30
28
  import { reference } from './reference.tsx'
31
29
 
32
- // todo: not needed anymore because not using hono dev vite plugin right?
33
- const reactRefreshPreamble = `
34
- import RefreshRuntime from "/@react-refresh";
35
- RefreshRuntime.injectIntoGlobalHook(window);
36
- window.$RefreshReg$ = () => {};
37
- window.$RefreshSig$ = () => (type) => type;
38
- window.__vite_plugin_react_preamble_installed__ = true;
39
- `
40
-
41
30
  export const Component = () => {
42
31
  const schema = PROJECT_DATA.schema?.versions[0]?.after || null
43
- console.log('Root component - schema:', schema ? 'EXISTS' : 'NULL')
44
32
 
45
33
  // Make schema available globally for MDX components
46
34
  if (typeof window !== 'undefined' && schema) {
@@ -50,15 +38,9 @@ export const Component = () => {
50
38
  return (
51
39
  <html lang='en'>
52
40
  <head>
53
- {import.meta.env.DEV && <script type='module'>{reactRefreshPreamble}</script>}
54
- {import.meta.env.DEV && <script type='module' src='/@vite/client'></script>}
55
41
  <meta charSet='utf-8' />
56
42
  <meta name='viewport' content='width=device-width, initial-scale=1' />
57
43
  <title>{templateVariables.title}</title>
58
- {import.meta.env.DEV && <link rel='stylesheet' href={radixStylesUrl} />}
59
- {/* <link rel='icon' type='image/svg+xml' href={assetUrl('/favicon.svg', PROJECT_DATA.basePath)} /> */}
60
- {/* <link rel='manifest' href={assetUrl('/manifest.json', PROJECT_DATA.basePath)} /> */}
61
- {/* <meta name='theme-color' content='#000000' /> */}
62
44
  </head>
63
45
  <body style={{ margin: 0 }}>
64
46
  <ThemeProvider>
@@ -68,7 +50,6 @@ export const Component = () => {
68
50
  </GraphQLSchemaProvider>
69
51
  </ThemeProvider>
70
52
  <ScrollRestoration />
71
- {import.meta.env.DEV && <script type='module' src={entryClientUrl}></script>}
72
53
  </body>
73
54
  </html>
74
55
  )
@@ -189,146 +170,6 @@ const Layout = () => {
189
170
  px={{ initial: '4', sm: '4', md: '0' }}
190
171
  py={{ initial: '4', sm: '4', md: '0' }}
191
172
  >
192
- <style>
193
- {`
194
- /* Import Inter font */
195
- @import url('https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&display=swap');
196
-
197
- /* Typography improvements */
198
- body {
199
- font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, Cantarell, sans-serif;
200
- -webkit-font-smoothing: antialiased;
201
- -moz-osx-font-smoothing: grayscale;
202
- text-rendering: optimizeLegibility;
203
- font-feature-settings: 'kern', 'liga', 'calt', 'ss01', 'ss02';
204
- }
205
-
206
- /* Improved paragraph spacing */
207
- .prose p {
208
- line-height: 1.7;
209
- margin-bottom: 1.25rem;
210
- }
211
-
212
- .prose h1, .prose h2, .prose h3, .prose h4, .prose h5, .prose h6 {
213
- font-weight: 600;
214
- letter-spacing: -0.02em;
215
- margin-top: 2rem;
216
- margin-bottom: 1rem;
217
- }
218
-
219
- .prose h1 { font-size: 2.25rem; line-height: 1.2; }
220
- .prose h2 { font-size: 1.875rem; line-height: 1.3; }
221
- .prose h3 { font-size: 1.5rem; line-height: 1.4; }
222
- .prose h4 { font-size: 1.25rem; line-height: 1.5; }
223
-
224
- .prose ul, .prose ol {
225
- margin-bottom: 1.25rem;
226
- padding-left: 1.5rem;
227
- }
228
-
229
- .prose li {
230
- margin-bottom: 0.5rem;
231
- line-height: 1.7;
232
- }
233
-
234
- .prose a {
235
- color: var(--accent-9);
236
- text-decoration: none;
237
- border-bottom: 1px solid transparent;
238
- transition: border-color 0.2s;
239
- }
240
-
241
- .prose a:hover {
242
- border-bottom-color: var(--accent-9);
243
- }
244
-
245
- .prose blockquote {
246
- border-left: 4px solid var(--accent-6);
247
- padding-left: 1rem;
248
- margin-left: 0;
249
- font-style: italic;
250
- color: var(--gray-11);
251
- }
252
-
253
- /* Responsive container fixes */
254
- @media (max-width: 768px) {
255
- body {
256
- overflow-x: hidden;
257
- }
258
- }
259
-
260
- /* Ensure proper centering on all screen sizes */
261
- .rt-Grid {
262
- box-sizing: border-box;
263
- }
264
-
265
- /* Shiki code blocks */
266
- pre.shiki {
267
- margin: 0;
268
- padding: 1rem;
269
- border-radius: 8px;
270
- overflow-x: auto;
271
- font-size: 14px;
272
- line-height: 1.6;
273
- background-color: #f6f8fa;
274
- border: 1px solid var(--gray-4);
275
- }
276
-
277
- /* Light mode: use --shiki-light CSS variables from inline styles */
278
- pre.shiki span {
279
- color: var(--shiki-light);
280
- }
281
-
282
- /* Dark mode - Radix Themes uses [data-is-root-theme="dark"] */
283
- [data-is-root-theme="dark"] pre.shiki {
284
- background-color: #1a1b26;
285
- border-color: var(--gray-7);
286
- }
287
-
288
- [data-is-root-theme="dark"] pre.shiki span {
289
- color: var(--shiki-dark);
290
- }
291
-
292
- pre.shiki code {
293
- font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', Consolas, 'Liberation Mono', Menlo, monospace;
294
- background: transparent;
295
- display: block;
296
- }
297
-
298
- /* Inline code */
299
- .prose code:not(pre code) {
300
- background-color: var(--gray-3);
301
- padding: 0.125rem 0.25rem;
302
- border-radius: 0.25rem;
303
- font-size: 0.875em;
304
- font-family: 'JetBrains Mono', 'Fira Code', monospace;
305
- }
306
-
307
- /* Tables */
308
- .prose table {
309
- width: 100%;
310
- border-collapse: collapse;
311
- margin-bottom: 1.5rem;
312
- }
313
-
314
- .prose th {
315
- background-color: var(--gray-3);
316
- font-weight: 600;
317
- text-align: left;
318
- padding: 0.75rem;
319
- border-bottom: 2px solid var(--gray-5);
320
- }
321
-
322
- .prose td {
323
- padding: 0.75rem;
324
- border-bottom: 1px solid var(--gray-4);
325
- }
326
-
327
- .prose tbody tr:last-child td {
328
- border-bottom: none;
329
- }
330
- `}
331
- </style>
332
173
  {header}
333
174
 
334
175
  {/* Desktop Sidebar */}
@@ -1,35 +1,45 @@
1
1
  import { Hono } from '#dep/hono/index'
2
- import { AppleTouchIcon } from '#lib/apple-touch-icon/index'
3
- import { Favicon } from '#lib/favicon/index'
4
2
  import { serveStatic } from '@hono/node-server/serve-static'
5
- import { Http } from '@wollybeard/kit'
6
3
  import PROJECT_DATA from 'virtual:polen/project/data.jsonsuper'
7
- import { renderPage } from './render-page.tsx'
8
- import { view } from './view.ts'
4
+ import viteClientAssetManifest from 'virtual:polen/vite/client/manifest'
5
+ import { injectManifestIntoHtml } from './manifest.ts'
6
+ import { PageMiddleware } from './middleware/page.ts'
7
+ import { UnsupportedAssetsMiddleware } from './middleware/unsupported-assets.ts'
9
8
 
10
- export const app = new Hono.Hono()
9
+ export type HtmlTransformer = (html: string, ctx: Hono.Context) => Promise<string> | string
11
10
 
12
- if (__BUILDING__) {
13
- app.use(
14
- PROJECT_DATA.server.static.route,
15
- serveStatic({ root: PROJECT_DATA.server.static.directory }),
16
- )
11
+ export interface AppHooks {
12
+ transformHtml?: HtmlTransformer[]
17
13
  }
18
14
 
19
- app.all(`*`, async (ctx) => {
20
- const staticHandlerContext = await view.query(ctx.req.raw)
15
+ export interface AppOptions {
16
+ hooks?: AppHooks
17
+ }
21
18
 
22
- if (staticHandlerContext instanceof Response) {
23
- return staticHandlerContext
24
- }
19
+ export const createApp = (options: AppOptions = {}) => {
20
+ const app = new Hono.Hono()
25
21
 
26
- if (Favicon.fileNamePattern.test(ctx.req.path)) {
27
- return Http.Response.notFound
28
- }
22
+ // Collect all HTML transformers
23
+ const htmlTransformers: HtmlTransformer[] = [...(options.hooks?.transformHtml || [])]
24
+
25
+ // Core middleware
26
+ app.use('*', UnsupportedAssetsMiddleware())
29
27
 
30
- if (AppleTouchIcon.fileNamePattern.test(ctx.req.path)) {
31
- return Http.Response.notFound
28
+ // Production-specific setup
29
+ if (__BUILDING__) {
30
+ // Add manifest transformer
31
+ htmlTransformers.push((html, _ctx) => {
32
+ return injectManifestIntoHtml(html, viteClientAssetManifest, PROJECT_DATA.basePath)
33
+ })
34
+
35
+ // Static file serving
36
+ app.use(
37
+ PROJECT_DATA.server.static.route,
38
+ serveStatic({ root: PROJECT_DATA.server.static.directory }),
39
+ )
32
40
  }
33
41
 
34
- return renderPage(staticHandlerContext)
35
- })
42
+ app.all('*', PageMiddleware(htmlTransformers))
43
+
44
+ return app
45
+ }
@@ -1,18 +1,20 @@
1
1
  import { reportError } from '#api/server/report-error'
2
2
  import type { ReactRouter } from '#dep/react-router/index'
3
+ import { React } from '#dep/react/index'
3
4
  import { ResponseInternalServerError } from '#lib/kit-temp'
4
5
  import type { ReactRouterAid } from '#lib/react-router-aid/index'
5
6
  import { Arr } from '@wollybeard/kit'
6
- import { StrictMode } from 'react'
7
7
  import * as ReactDomServer from 'react-dom/server'
8
8
  import { createStaticRouter, StaticRouterProvider } from 'react-router'
9
- import PROJECT_DATA from 'virtual:polen/project/data.jsonsuper'
10
- import viteClientAssetManifest from 'virtual:polen/vite/client/manifest'
11
- import { injectManifestIntoHtml } from './manifest.ts'
12
9
  import { view } from './view.ts'
13
10
 
14
- export const renderPage = (
11
+ interface RenderHooks {
12
+ transformHtml?: (html: string) => Promise<string> | string
13
+ }
14
+
15
+ export const createPageHtmlResponse = async (
15
16
  staticHandlerContext: ReactRouter.StaticHandlerContext,
17
+ hooks?: RenderHooks,
16
18
  ) => {
17
19
  const router = createStaticRouter(view.dataRoutes, staticHandlerContext)
18
20
 
@@ -20,24 +22,25 @@ export const renderPage = (
20
22
 
21
23
  try {
22
24
  html = ReactDomServer.renderToString(
23
- <StrictMode>
24
- <StaticRouterProvider router={router} context={staticHandlerContext} />
25
- </StrictMode>,
25
+ React.createElement(
26
+ React.StrictMode,
27
+ null,
28
+ React.createElement(StaticRouterProvider, {
29
+ router,
30
+ context: staticHandlerContext,
31
+ }),
32
+ ),
26
33
  )
27
34
  } catch (cause) {
28
35
  reportError(new Error(`Failed to server side render the HTML`, { cause }))
29
36
  return ResponseInternalServerError()
30
37
  }
31
38
 
32
- if (__BUILDING__) {
33
- html = injectManifestIntoHtml(html, viteClientAssetManifest, PROJECT_DATA.basePath)
34
- }
39
+ // Create the full HTML document
35
40
 
36
- // todo: what is this?
37
- if (import.meta.env.DEV) {
38
- // const env = ctx.env as { viteDevServer: Vite.ViteDevServer }
39
- // html = await env.viteDevServer.transformIndexHtml(ctx.req.url, html)
40
- // await env.viteDevServer.transformIndexHtml(ctx.req.url, html)
41
+ // Apply HTML transformation hook to the full document
42
+ if (hooks?.transformHtml) {
43
+ html = await hooks.transformHtml(html)
41
44
  }
42
45
 
43
46
  const headers = getRouteHeaders(staticHandlerContext)
@@ -1,6 +1,6 @@
1
1
  import { serve } from '@hono/node-server' // TODO: support non-node platforms.
2
2
  import { neverCase } from '@wollybeard/kit/language'
3
- import { app } from './app.ts'
3
+ import { createApp } from './app.ts'
4
4
  import { generate } from './ssg/generate.ts'
5
5
  import { view } from './view.ts'
6
6
 
@@ -11,6 +11,7 @@ if (__BUILDING__) {
11
11
  break
12
12
  case `ssr`:
13
13
  const port = process.env[`PORT`] ? parseInt(process.env[`PORT`]) : 3001 // todo viteConfigResolved.server.port + 1
14
+ const app = createApp()
14
15
  serve({ fetch: app.fetch, port })
15
16
  break
16
17
  case `spa`:
@@ -0,0 +1,19 @@
1
+ import type { Hono } from '#dep/hono/index'
2
+ import { asyncReduceWith } from '#lib/kit-temp'
3
+ import type { HtmlTransformer } from '../app.ts'
4
+ import { createPageHtmlResponse } from '../create-page-html-response.ts'
5
+ import { view } from '../view.ts'
6
+
7
+ export const PageMiddleware = (transformers: HtmlTransformer[]) => {
8
+ return async (ctx: Hono.Context) => {
9
+ const staticHandlerContext = await view.query(ctx.req.raw)
10
+
11
+ if (staticHandlerContext instanceof Response) {
12
+ return staticHandlerContext
13
+ }
14
+
15
+ return createPageHtmlResponse(staticHandlerContext, {
16
+ transformHtml: asyncReduceWith(transformers, ctx),
17
+ })
18
+ }
19
+ }
@@ -0,0 +1,25 @@
1
+ import type { Hono } from '#dep/hono/index'
2
+ import { AppleTouchIcon } from '#lib/apple-touch-icon/index'
3
+ import { Favicon } from '#lib/favicon/index'
4
+ import { Http } from '@wollybeard/kit'
5
+
6
+ /**
7
+ * Temporary middleware to block unsupported asset requests
8
+ *
9
+ * TODO: Polen should eventually support favicon and apple-touch-icon generation
10
+ * For now, we return 404 immediately to prevent these requests from reaching
11
+ * React Router and causing unnecessary processing or errors.
12
+ */
13
+ export const UnsupportedAssetsMiddleware = (): Hono.MiddlewareHandler => {
14
+ return async (ctx, next) => {
15
+ // Block these asset requests until Polen supports them
16
+ if (
17
+ Favicon.fileNamePattern.test(ctx.req.path)
18
+ || AppleTouchIcon.fileNamePattern.test(ctx.req.path)
19
+ ) {
20
+ return Http.Response.notFound
21
+ }
22
+
23
+ await next()
24
+ }
25
+ }
@@ -1,95 +1,91 @@
1
1
  import { Hono } from '#dep/hono/index'
2
2
  import type { ReactRouter } from '#dep/react-router/index'
3
- import { app } from '#template/server/app'
3
+ import { asyncParallel, chunk } from '#lib/kit-temp'
4
+ import { debugPolen } from '#singletons/debug'
4
5
  import * as NodeFs from 'node:fs/promises'
5
6
  import PROJECT_DATA from 'virtual:polen/project/data.jsonsuper'
6
- import { renderPage } from '../render-page.tsx'
7
+ import viteClientAssetManifest from 'virtual:polen/vite/client/manifest'
8
+ import { createPageHtmlResponse } from '../create-page-html-response.tsx'
9
+ import { injectManifestIntoHtml } from '../manifest.ts'
7
10
  import { getRoutesPaths } from './get-route-paths.ts'
8
11
 
9
12
  export const generate = async (view: ReactRouter.StaticHandler) => {
10
- const handler: Hono.Handler = async (ctx) => {
11
- // For SSG, we need to create a request with the base path prepended
12
- // so React Router can match it correctly
13
- const url = new URL(ctx.req.raw.url)
14
- const basePath = PROJECT_DATA.basePath === '/' ? '' : PROJECT_DATA.basePath.slice(0, -1)
15
-
16
- // Create a new request with the base path prepended to the pathname
17
- const modifiedRequest = new Request(
18
- `${url.protocol}//${url.host}${basePath}${url.pathname}${url.search}`,
19
- {
20
- method: ctx.req.raw.method,
21
- headers: ctx.req.raw.headers,
22
- body: ctx.req.raw.body,
23
- },
24
- )
25
-
26
- const staticHandlerContext = await view.query(modifiedRequest)
27
- if (staticHandlerContext instanceof Response) {
28
- return staticHandlerContext
29
- }
30
- return renderPage(staticHandlerContext)
31
- }
13
+ const debug = debugPolen.sub(`ssg`)
32
14
 
33
15
  const routePaths = getRoutesPaths()
16
+ const totalPaths = routePaths.length
17
+ debug(`start`, { totalPaths })
34
18
 
35
- for (const routePath of routePaths) {
36
- app.get(routePath, handler)
37
- }
19
+ // Process routes in batches using the new utilities
20
+ const batchSize = 50
21
+ const batches = chunk(routePaths, batchSize)
38
22
 
39
- // For large schemas, we need to process in smaller batches to avoid memory issues
40
- const BATCH_SIZE = 50
41
- const totalPaths = routePaths.length
42
- console.log(`[info] Generating ${totalPaths} static pages...`)
23
+ const result = await asyncParallel(
24
+ batches,
25
+ async (batchPaths, batchIndex) => {
26
+ const batchApp = new Hono.Hono()
43
27
 
44
- for (let i = 0; i < totalPaths; i += BATCH_SIZE) {
45
- const batchPaths = routePaths.slice(i, i + BATCH_SIZE)
46
- const batchApp = new Hono.Hono()
28
+ // Create a custom handler for batch processing that includes base path handling
29
+ const batchHandler: Hono.Handler = async (ctx) => {
30
+ // For SSG, we need to create a request with the base path prepended
31
+ const url = new URL(ctx.req.raw.url)
32
+ const basePath = PROJECT_DATA.basePath === '/' ? '' : PROJECT_DATA.basePath.slice(0, -1)
47
33
 
48
- // Create a custom handler for batch processing that includes base path handling
49
- const batchHandler: Hono.Handler = async (ctx) => {
50
- // For SSG, we need to create a request with the base path prepended
51
- const url = new URL(ctx.req.raw.url)
52
- const basePath = PROJECT_DATA.basePath === '/' ? '' : PROJECT_DATA.basePath.slice(0, -1)
34
+ // Create a new request with the base path prepended to the pathname
35
+ const modifiedRequest = new Request(
36
+ `${url.protocol}//${url.host}${basePath}${url.pathname}${url.search}`,
37
+ {
38
+ method: ctx.req.raw.method,
39
+ headers: ctx.req.raw.headers,
40
+ body: ctx.req.raw.body,
41
+ },
42
+ )
53
43
 
54
- // Create a new request with the base path prepended to the pathname
55
- const modifiedRequest = new Request(
56
- `${url.protocol}//${url.host}${basePath}${url.pathname}${url.search}`,
57
- {
58
- method: ctx.req.raw.method,
59
- headers: ctx.req.raw.headers,
60
- body: ctx.req.raw.body,
61
- },
62
- )
44
+ const staticHandlerContext = await view.query(modifiedRequest)
45
+ if (staticHandlerContext instanceof Response) {
46
+ return staticHandlerContext
47
+ }
63
48
 
64
- const staticHandlerContext = await view.query(modifiedRequest)
65
- if (staticHandlerContext instanceof Response) {
66
- return staticHandlerContext
49
+ // SSG uses manifest-based transformation directly
50
+ const transformHtml = (html: string) => {
51
+ return injectManifestIntoHtml(html, viteClientAssetManifest, PROJECT_DATA.basePath)
52
+ }
53
+ return createPageHtmlResponse(staticHandlerContext, { transformHtml })
67
54
  }
68
- return renderPage(staticHandlerContext)
69
- }
70
-
71
- // Register only the routes for this batch
72
- for (const routePath of batchPaths) {
73
- batchApp.get(routePath, batchHandler)
74
- }
75
55
 
76
- console.log(
77
- `[info] Processing batch ${Math.floor(i / BATCH_SIZE) + 1}/${
78
- Math.ceil(totalPaths / BATCH_SIZE)
79
- } (${batchPaths.length} pages)...`,
80
- )
56
+ // Register only the routes for this batch
57
+ for (const routePath of batchPaths) {
58
+ batchApp.get(routePath, batchHandler)
59
+ }
81
60
 
82
- const result = await Hono.SSG.toSSG(batchApp, NodeFs, {
83
- concurrency: 5, // Reduced concurrency for memory efficiency
84
- dir: PROJECT_DATA.paths.relative.build.root,
85
- })
61
+ debug(`batch:start`, {
62
+ batchIndex: batchIndex + 1,
63
+ totalBatches: batches.length,
64
+ pagesInBatch: batchPaths.length,
65
+ })
86
66
 
87
- if (!result.success) {
88
- throw new Error(`Failed to generate static site at batch ${Math.floor(i / BATCH_SIZE) + 1}`, {
89
- cause: result.error,
67
+ const ssgResult = await Hono.SSG.toSSG(batchApp, NodeFs, {
68
+ concurrency: 5, // Reduced concurrency for memory efficiency
69
+ dir: PROJECT_DATA.paths.relative.build.root,
90
70
  })
91
- }
71
+
72
+ if (!ssgResult.success) {
73
+ throw new Error(`Failed to generate static site at batch ${batchIndex + 1}`, {
74
+ cause: ssgResult.error,
75
+ })
76
+ }
77
+
78
+ return ssgResult
79
+ },
80
+ {
81
+ concurrency: 1, // Process batches sequentially to avoid memory issues
82
+ failFast: true, // Stop on first batch failure
83
+ },
84
+ )
85
+
86
+ if (!result.success) {
87
+ throw new Error(`SSG generation failed`, { cause: result.errors[0] })
92
88
  }
93
89
 
94
- console.log(`[info] Successfully generated ${totalPaths} static pages.`)
90
+ debug(`complete`, { totalPaths })
95
91
  }
@@ -1,35 +0,0 @@
1
- import type { React } from '#dep/react/index';
2
- import type { DOMPosition } from '../positioning-simple.ts';
3
- import type { Documentation } from '../schema-integration.ts';
4
- import type { Identifier } from '../types.ts';
5
- /**
6
- * Props for the HoverTooltip component
7
- */
8
- export interface HoverTooltipProps {
9
- /** The identifier being hovered */
10
- identifier: Identifier;
11
- /** Documentation from schema */
12
- documentation: Documentation;
13
- /** Position of the identifier */
14
- position: DOMPosition;
15
- /** Whether this identifier has an error */
16
- hasError?: boolean;
17
- /** Reference URL for "View docs" link */
18
- referenceUrl: string;
19
- /** Callback to close the tooltip */
20
- onClose?: () => void;
21
- /** Callback to navigate to docs */
22
- onNavigate?: () => void;
23
- }
24
- /**
25
- * Tooltip shown on hover over GraphQL identifiers
26
- *
27
- * Displays type information, descriptions, deprecation warnings,
28
- * and links to full documentation.
29
- */
30
- export declare const HoverTooltip: React.FC<HoverTooltipProps>;
31
- /**
32
- * Default styles for hover tooltips
33
- */
34
- export declare const hoverTooltipStyles = "\n.graphql-hover-tooltip {\n /* Tooltip animation */\n animation: graphql-tooltip-fade-in 0.2s ease-out;\n}\n\n@keyframes graphql-tooltip-fade-in {\n from {\n opacity: 0;\n transform: translateY(4px);\n }\n to {\n opacity: 1;\n transform: translateY(0);\n }\n}\n\n/* Ensure tooltips appear above other content */\n.graphql-hover-tooltip .rt-Card {\n box-shadow: 0 10px 38px -10px rgba(22, 23, 24, 0.35), \n 0 10px 20px -15px rgba(22, 23, 24, 0.2);\n}\n";
35
- //# sourceMappingURL=HoverTooltip.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"HoverTooltip.d.ts","sourceRoot":"","sources":["../../../../src/lib/graphql-document/components/HoverTooltip.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,kBAAkB,CAAA;AAG7C,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAA;AAC7D,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,aAAa,CAAA;AAE7C;;GAEG;AACH,MAAM,WAAW,iBAAiB;IAChC,mCAAmC;IACnC,UAAU,EAAE,UAAU,CAAA;IACtB,gCAAgC;IAChC,aAAa,EAAE,aAAa,CAAA;IAC5B,iCAAiC;IACjC,QAAQ,EAAE,WAAW,CAAA;IACrB,2CAA2C;IAC3C,QAAQ,CAAC,EAAE,OAAO,CAAA;IAClB,yCAAyC;IACzC,YAAY,EAAE,MAAM,CAAA;IACpB,oCAAoC;IACpC,OAAO,CAAC,EAAE,MAAM,IAAI,CAAA;IACpB,mCAAmC;IACnC,UAAU,CAAC,EAAE,MAAM,IAAI,CAAA;CACxB;AAED;;;;;GAKG;AACH,eAAO,MAAM,YAAY,EAAE,KAAK,CAAC,EAAE,CAAC,iBAAiB,CA6NpD,CAAA;AAED;;GAEG;AACH,eAAO,MAAM,kBAAkB,yeAsB9B,CAAA"}