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
@@ -2,118 +2,126 @@ import type { Config } from '#api/config/index'
2
2
  import type { PolenBuildManifest } from '#api/static/manifest'
3
3
  import { Vite } from '#dep/vite/index'
4
4
  import { ViteVirtual } from '#lib/vite-virtual/index'
5
+ import { debugPolen } from '#singletons/debug'
5
6
  import { Fs, Path } from '@wollybeard/kit'
6
7
  import packageJson from '../../../../package.json' with { type: 'json' }
7
8
  import { isKitUnusedExternalImport, isRadixModuleLevelDirective } from '../log-filters.ts'
8
9
  import { polenVirtual } from '../vi.ts'
9
10
 
10
11
  export const Build = (config: Config.Config): Vite.Plugin[] => {
12
+ const debug = debugPolen.sub(`vite-build`)
13
+ debug('construct')
11
14
  // let viteConfigResolved: Vite.ResolvedConfig
12
15
 
13
16
  // const outDir = Path.join(config.paths.project.rootDir, `dist`)
14
17
 
15
- return [Manifest(config), BuildManifest(config), {
16
- name: `polen:build-client`,
17
- apply: `build`,
18
- applyToEnvironment: Vite.isEnvironmentClient,
19
- // HACK: For some reason the ?url import doesn't lead to a rewrite in the build.
20
- // Furthermore we need to rely on the manifest to get its final name because it is
21
- // generated by the client build before the server build.
22
- // However, we still need the asset in development.
23
- // But we cannot exclude the import in build.
24
- // So this does that for us but it is really hacky.
25
- // FIXME
26
- // 1. Raise issue about having ?url lead to expected build path rewrite?
27
- // 2. And: Move asset generation to server build?
28
- // 3. And/or: Use Vite Environments API?
29
- generateBundle(_, bundle, isWrite) {
30
- if (isWrite) {
31
- for (const chunkOrAsset of Object.values(bundle)) {
32
- if (chunkOrAsset.type === `asset` && chunkOrAsset.names.includes(`entry.client.jsx`)) {
33
- // eslint-disable-next-line
34
- delete bundle[chunkOrAsset.fileName]
18
+ return [
19
+ Manifest(config),
20
+ BuildManifest(config),
21
+ {
22
+ name: `polen:build-client`,
23
+ apply: `build`,
24
+ applyToEnvironment: Vite.isEnvironmentClient,
25
+ // HACK: For some reason the ?url import doesn't lead to a rewrite in the build.
26
+ // Furthermore we need to rely on the manifest to get its final name because it is
27
+ // generated by the client build before the server build.
28
+ // However, we still need the asset in development.
29
+ // But we cannot exclude the import in build.
30
+ // So this does that for us but it is really hacky.
31
+ // FIXME
32
+ // 1. Raise issue about having ?url lead to expected build path rewrite?
33
+ // 2. And: Move asset generation to server build?
34
+ // 3. And/or: Use Vite Environments API?
35
+ generateBundle(_, bundle, isWrite) {
36
+ if (isWrite) {
37
+ for (const chunkOrAsset of Object.values(bundle)) {
38
+ if (chunkOrAsset.type === `asset` && chunkOrAsset.names.includes(`entry.client.jsx`)) {
39
+ // eslint-disable-next-line
40
+ delete bundle[chunkOrAsset.fileName]
41
+ }
35
42
  }
36
43
  }
37
- }
38
- },
39
- onLog(_, message) {
40
- if (isRadixModuleLevelDirective(message)) return
41
- if (isKitUnusedExternalImport(message)) return
42
- },
43
- config() {
44
- return {
45
- environments: {
46
- client: {
47
- build: {
48
- manifest: true,
49
- rollupOptions: {
50
- input: [config.paths.framework.template.client.entrypoint],
51
- external: id => id.startsWith(`node:`),
52
- onwarn(message) {
53
- if (isKitUnusedExternalImport(message)) return
44
+ },
45
+ onLog(_, message) {
46
+ if (isRadixModuleLevelDirective(message)) return
47
+ if (isKitUnusedExternalImport(message)) return
48
+ },
49
+ config() {
50
+ return {
51
+ environments: {
52
+ client: {
53
+ build: {
54
+ manifest: true,
55
+ rollupOptions: {
56
+ input: [config.paths.framework.template.client.entrypoint],
57
+ external: id => id.startsWith(`node:`),
58
+ onwarn(message) {
59
+ if (isKitUnusedExternalImport(message)) return
60
+ },
54
61
  },
55
62
  },
56
63
  },
57
64
  },
58
- },
59
- }
65
+ }
66
+ },
60
67
  },
61
- }, {
62
- name: `polen-ssr-build`,
63
- apply: `build`,
64
- applyToEnvironment: Vite.isEnvironmentSsr,
65
- config() {
66
- return {
67
- // Have to configure this here??
68
- // @see https://github.com/vitejs/vite/issues/20098
69
- ssr: {
70
- noExternal: true,
71
- },
72
- environments: {
68
+
69
+ {
70
+ name: `polen-ssr-build`,
71
+ apply: `build`,
72
+ applyToEnvironment: Vite.isEnvironmentSsr,
73
+ config() {
74
+ return {
75
+ // Have to configure this here??
76
+ // @see https://github.com/vitejs/vite/issues/20098
73
77
  ssr: {
74
- build: {
75
- // NO EFFECT (see above)
76
- // Bundle all dependencies instead of externalizing them
77
- // noExternal: true,
78
- // The SSR build will follow the client build, and emptying the dir would lose the output of the client build.
79
- emptyOutDir: false,
80
- rollupOptions: {
81
- input: [config.paths.framework.template.server.entrypoint],
82
- output: {
83
- entryFileNames: config.paths.project.relative.build.relative.serverEntrypoint,
78
+ noExternal: true,
79
+ },
80
+ environments: {
81
+ ssr: {
82
+ build: {
83
+ // NO EFFECT (see above)
84
+ // Bundle all dependencies instead of externalizing them
85
+ // noExternal: true,
86
+ // The SSR build will follow the client build, and emptying the dir would lose the output of the client build.
87
+ emptyOutDir: false,
88
+ rollupOptions: {
89
+ input: [config.paths.framework.template.server.entrypoint],
90
+ output: {
91
+ entryFileNames: config.paths.project.relative.build.relative.serverEntrypoint,
92
+ },
84
93
  },
85
94
  },
86
95
  },
87
96
  },
88
- },
89
- }
90
- },
91
-
92
- onLog(_, message) {
93
- if (isKitUnusedExternalImport(message)) return
94
- },
95
- // generateBundle(_, bundle, isWrite) {
96
- // if (isWrite) {
97
- // for (const chunkOrAsset of Object.values(bundle)) {
98
- // console.log(chunkOrAsset)
99
- // if (chunkOrAsset.type === `chunk`) {
100
- // if (chunkOrAsset.facadeModuleId === viClientManifest.resolved) {
101
- // // eslint-disable-next-line
102
- // delete bundle[chunkOrAsset.fileName]
103
- // }
104
- // }
105
- // }
106
- // }
107
- // },
108
- async closeBundle() {
109
- /**
110
- * clean up the manifest. Was generated by client. For server build. Not needed after (unless debugging).
111
- */
112
- if (!config.advanced.debug) {
113
- await Fs.remove(Path.join(config.paths.project.absolute.build.root, `.vite`))
114
- }
97
+ }
98
+ },
99
+ onLog(_, message) {
100
+ if (isKitUnusedExternalImport(message)) return
101
+ },
102
+ // generateBundle(_, bundle, isWrite) {
103
+ // if (isWrite) {
104
+ // for (const chunkOrAsset of Object.values(bundle)) {
105
+ // console.log(chunkOrAsset)
106
+ // if (chunkOrAsset.type === `chunk`) {
107
+ // if (chunkOrAsset.facadeModuleId === viClientManifest.resolved) {
108
+ // // eslint-disable-next-line
109
+ // delete bundle[chunkOrAsset.fileName]
110
+ // }
111
+ // }
112
+ // }
113
+ // }
114
+ // },
115
+ async closeBundle() {
116
+ /**
117
+ * clean up the manifest. Was generated by client. For server build. Not needed after (unless debugging).
118
+ */
119
+ if (!config.advanced.debug) {
120
+ await Fs.remove(Path.join(config.paths.project.absolute.build.root, `.vite`))
121
+ }
122
+ },
115
123
  },
116
- }]
124
+ ]
117
125
  }
118
126
 
119
127
  const viClientManifest = polenVirtual([`vite`, `client`, `manifest`])
@@ -57,7 +57,7 @@ export const Core = (config: Config.Config): Vite.PluginOption[] => {
57
57
  }))
58
58
  }
59
59
 
60
- const json = VitePluginJson.create({
60
+ const jsonsuper = VitePluginJson.create({
61
61
  codec: {
62
62
  validate: superjson,
63
63
  importPath: import.meta.resolve('#singletons/superjson'),
@@ -85,7 +85,7 @@ export const Core = (config: Config.Config): Vite.PluginOption[] => {
85
85
  name: `polen:internal-import-alias`,
86
86
  enforce: 'pre' as const,
87
87
  resolveId(id, importer) {
88
- const d = debugPolen.sub(`vite-plugin:internal-import-alias`)
88
+ // const debug = debugPolen.sub(`vite-plugin:internal-import-alias`)
89
89
 
90
90
  const isPolenImporter = Boolean(
91
91
  importer
@@ -107,25 +107,24 @@ export const Core = (config: Config.Config): Vite.PluginOption[] => {
107
107
  )
108
108
 
109
109
  if (!isPolenImporter) return null
110
- d(`check candidate`, { id, importer, isPolenImporter })
110
+ // debug(`check candidate`, { id, importer, isPolenImporter })
111
111
 
112
112
  const find = Str.pattern<{ groups: [`path`] }>(/^#(?<path>.+)/)
113
113
  const match = Str.match(id, find)
114
114
  if (!match) return null
115
115
 
116
116
  const to = `${config.paths.framework.sourceDir}/${match.groups.path}${config.paths.framework.sourceExtension}`
117
- d(`did resolve`, { from: id, to })
117
+ // debug(`did resolve`, { from: id, to })
118
118
 
119
119
  return to
120
120
  },
121
121
  },
122
- json,
122
+ jsonsuper,
123
123
  VitePluginReactiveData.create({
124
- moduleId: `virtual:polen/project/data/navbar`,
125
- data: navbarData.value,
124
+ moduleId: `virtual:polen/project/data/navbar.jsonsuper`,
126
125
  codec: superjson,
126
+ data: navbarData.value,
127
127
  name: `polen-navbar`,
128
- moduleType: 'jsonsuper',
129
128
  }),
130
129
  ...Pages({
131
130
  config,
@@ -181,12 +180,18 @@ export const Core = (config: Config.Config): Vite.PluginOption[] => {
181
180
  {
182
181
  identifier: viProjectData,
183
182
  async loader() {
183
+ const debug = debugPolen.sub(`module-project-data`)
184
+
185
+ debug('load', { id: viProjectData.id })
186
+
184
187
  const schema = await readSchema()
185
188
 
186
189
  // ━ Schema presence causes adding some navbar items
187
- const schemaNavbar = navbarData.get('schema')
188
- schemaNavbar.length = 0 // Clear existing
189
190
  if (schema) {
191
+ const schemaNavbar = navbarData.get('schema')
192
+ schemaNavbar.length = 0 // Clear existing
193
+ debug('update navbar', { message: 'for schema' })
194
+
190
195
  // IMPORTANT: Always ensure paths start with '/' for React Router compatibility.
191
196
  // Without the leading slash, React Router treats paths as relative, which causes
192
197
  // hydration mismatches between SSR (where base path is prepended) and client
@@ -14,7 +14,7 @@ import { Arr, Cache, Path, Str } from '@wollybeard/kit'
14
14
  import remarkFrontmatter from 'remark-frontmatter'
15
15
  import remarkGfm from 'remark-gfm'
16
16
 
17
- const debug = debugPolen.sub(`vite-plugin-pages`)
17
+ const debug = debugPolen.sub(`vite-pages`)
18
18
 
19
19
  export const viProjectRoutes = polenVirtual([`project`, `routes.jsx`], { allowPluginProcessing: true })
20
20
  export const viProjectPagesCatalog = polenVirtual([`project`, `data`, 'pages-catalog.jsonsuper'], {
@@ -207,25 +207,27 @@ export const Pages = ({
207
207
  // },
208
208
  async handler(id) {
209
209
  if (id !== viProjectPagesCatalog.resolved) return
210
- debug(`viProjectPagesCatalog`)
210
+ debug(`hook load`)
211
211
 
212
212
  const scanResult = await scanPages()
213
213
 
214
- // Report any diagnostics
215
214
  reportDiagnostics(scanResult.diagnostics)
216
- debug(`Found ${String(scanResult.list.length)} visible pages`)
215
+ debug(`found visible`, { count: scanResult.list.length })
217
216
 
218
217
  //
219
218
  // ━━ Build Navbar
220
219
  //
221
220
 
222
- // Update navbar if provided
223
221
  if (navbarData) {
224
222
  const navbarPages = navbarData.get('pages')
223
+
225
224
  navbarPages.length = 0 // Clear existing
226
225
 
227
- const navbarItems = createNavbar(scanResult.list)
228
- navbarPages.push(...navbarItems)
226
+ const data = createNavbar(scanResult.list)
227
+
228
+ debug('update navbar', data)
229
+
230
+ navbarPages.push(...data)
229
231
  }
230
232
 
231
233
  //
@@ -1,29 +1,80 @@
1
1
  import type { Config } from '#api/config/index'
2
2
  import { reportError } from '#api/server/report-error'
3
- import type { Hono } from '#dep/hono/index'
3
+ import { Hono } from '#dep/hono/index'
4
4
  import type { Vite } from '#dep/vite/index'
5
5
  import { ResponseInternalServerError } from '#lib/kit-temp'
6
6
  import { debugPolen } from '#singletons/debug'
7
7
  import * as HonoNodeServer from '@hono/node-server'
8
- import { Err } from '@wollybeard/kit'
8
+ import { Err, Obj } from '@wollybeard/kit'
9
9
 
10
10
  type App = Hono.Hono
11
11
 
12
+ interface AppOptions {
13
+ hooks?: {
14
+ transformHtml?: Array<(html: string, ctx: Hono.Context) => Promise<string> | string>
15
+ }
16
+ }
17
+
12
18
  interface AppServerModule {
13
- app: App
19
+ createApp: (options: AppOptions) => App
14
20
  }
15
21
 
16
22
  export const Serve = (
17
23
  config: Config.Config,
18
24
  ): Vite.PluginOption => {
19
25
  const debug = debugPolen.sub(`serve`)
26
+ debug('construct')
27
+ const appModulePath = config.paths.framework.template.server.app
28
+
20
29
  let appPromise: Promise<App | Error>
21
30
 
22
- const reloadApp = async ({ server }: { server: Vite.ViteDevServer }): Promise<App | Error> => {
31
+ const isNeedAppLoadOrReload = (server: Vite.ViteDevServer): boolean => {
32
+ const appModule = server.moduleGraph.getModuleById(appModulePath)
33
+ if (!appModule) return true // Not loaded yet
34
+
35
+ // Check if the module or any of its dependencies are invalidated
36
+ const checkInvalidated = (mod: Vite.ModuleNode, visited = new Set<string>()): boolean => {
37
+ console.log(Obj.pick(mod, ['ssrInvalidationState', 'invalidationState', 'lastInvalidationTimestamp']))
38
+ // if (!mod.id || visited.has(mod.id)) return false
39
+ // visited.add(mod.id)
40
+
41
+ // // Check if this module is invalidated
42
+ // if (mod.transformResult === null) return true
43
+
44
+ // // Check all imported modules recursively
45
+ // for (const imported of mod.importedModules) {
46
+ // if (checkInvalidated(imported, visited)) return true
47
+ // }
48
+
49
+ return false
50
+ }
51
+
52
+ return checkInvalidated(appModule)
53
+ }
54
+
55
+ const reloadApp = async (server: Vite.ViteDevServer): Promise<App | Error> => {
23
56
  debug('reloadApp')
57
+
24
58
  return server.ssrLoadModule(config.paths.framework.template.server.app)
25
59
  .then(module => module as AppServerModule)
26
- .then(module => module.app)
60
+ .then(module => {
61
+ return module.createApp({
62
+ hooks: {
63
+ transformHtml: [
64
+ // Inject entry client script for development
65
+ (html: string, _ctx) => {
66
+ const entryClientPath = config.paths.framework.template.client.entrypoint
67
+ const entryClientScript = `<script type="module" src="${entryClientPath}"></script>`
68
+ return html.replace('</body>', `${entryClientScript}</body>`)
69
+ },
70
+ // Apply Vite's transformations
71
+ async (html: string, ctx) => {
72
+ return await server.transformIndexHtml(ctx.req.url, html)
73
+ },
74
+ ],
75
+ },
76
+ })
77
+ })
27
78
  .catch(async (error) => {
28
79
  if (Err.is(error)) {
29
80
  // ━ Clean Stack Trace
@@ -57,12 +108,12 @@ export const Serve = (
57
108
  handleHotUpdate({ server }) {
58
109
  debug('handleHotUpdate')
59
110
  // Reload app server immediately in the background
60
- appPromise = reloadApp({ server })
111
+ appPromise = reloadApp(server)
61
112
  },
62
113
  async configureServer(server) {
63
114
  debug('configureServer')
64
115
  // Initial load
65
- appPromise = reloadApp({ server })
116
+ appPromise = reloadApp(server)
66
117
 
67
118
  return () => {
68
119
  // Remove index.html serving middleware.
@@ -74,6 +125,8 @@ export const Serve = (
74
125
 
75
126
  // Add middleware that runs our entry server
76
127
  server.middlewares.use((req, res, ___next) => {
128
+ debug('request')
129
+ // isNeedAppLoadOrReload(server)
77
130
  void HonoNodeServer.getRequestListener(async request => {
78
131
  // Always await the current app promise
79
132
  const app = await appPromise
@@ -81,8 +134,8 @@ export const Serve = (
81
134
  // Err.log(app)
82
135
  return ResponseInternalServerError()
83
136
  }
84
- const response = await app.fetch(request, { viteDevServer: server })
85
- return response
137
+
138
+ return await app.fetch(request)
86
139
  })(req, res)
87
140
  })
88
141
  }
@@ -13,10 +13,10 @@ export const reportDiagnostics = (diagnostics: Diagnostic[]) => {
13
13
  infos.length > 0 && `${infos.length} info${infos.length === 1 ? '' : 's'}`,
14
14
  ].filter(Boolean).join(', ')
15
15
 
16
- console.warn(`\nšŸ” Polen found ${summary}:\n`)
16
+ console.warn(`\nPolen found ${summary}:\n`)
17
17
 
18
18
  diagnostics.forEach((diagnostic, index) => {
19
- const icon = diagnostic.severity === 'error' ? 'āŒ' : diagnostic.severity === 'warning' ? 'āš ļø ' : 'ā„¹ļø '
19
+ const icon = diagnostic.severity === 'error' ? 'āœ—' : diagnostic.severity === 'warning' ? '⚠' : 'ā“˜'
20
20
  console.warn(`${icon} ${index + 1}. ${diagnostic.message}\n`)
21
21
  })
22
22
  }
@@ -0,0 +1,76 @@
1
+ /**
2
+ * Copy button component for GraphQL documents
3
+ */
4
+
5
+ import type { React } from '#dep/react/index'
6
+ import { React as ReactHooks } from '#dep/react/index'
7
+ import { CheckIcon, CopyIcon } from '@radix-ui/react-icons'
8
+ import { Button } from '@radix-ui/themes'
9
+
10
+ export interface CopyButtonProps {
11
+ /** The text to copy */
12
+ text: string
13
+ /** Optional className */
14
+ className?: string
15
+ /** Size variant */
16
+ size?: '1' | '2' | '3'
17
+ }
18
+
19
+ /**
20
+ * Copy button for GraphQL code blocks
21
+ *
22
+ * Shows a copy icon that changes to a checkmark when clicked
23
+ */
24
+ export const CopyButton: React.FC<CopyButtonProps> = ({
25
+ text,
26
+ className = '',
27
+ size = '1',
28
+ }) => {
29
+ const [copied, setCopied] = ReactHooks.useState(false)
30
+ const timeoutRef = ReactHooks.useRef<NodeJS.Timeout | null>(null)
31
+
32
+ const handleCopy = ReactHooks.useCallback(async (e: React.MouseEvent) => {
33
+ e.preventDefault()
34
+ e.stopPropagation()
35
+
36
+ try {
37
+ await navigator.clipboard.writeText(text)
38
+ setCopied(true)
39
+
40
+ // Clear any existing timeout
41
+ if (timeoutRef.current) {
42
+ clearTimeout(timeoutRef.current)
43
+ }
44
+
45
+ // Reset after 2 seconds
46
+ timeoutRef.current = setTimeout(() => {
47
+ setCopied(false)
48
+ timeoutRef.current = null
49
+ }, 2000)
50
+ } catch (err) {
51
+ console.error('Failed to copy text:', err)
52
+ }
53
+ }, [text])
54
+
55
+ // Cleanup timeout on unmount
56
+ ReactHooks.useEffect(() => {
57
+ return () => {
58
+ if (timeoutRef.current) {
59
+ clearTimeout(timeoutRef.current)
60
+ }
61
+ }
62
+ }, [])
63
+
64
+ return (
65
+ <Button
66
+ size={size}
67
+ variant='ghost'
68
+ className={`graphql-copy-button ${className}`}
69
+ onClick={handleCopy}
70
+ aria-label={copied ? 'Copied!' : 'Copy code'}
71
+ data-copied={copied}
72
+ >
73
+ {copied ? <CheckIcon width='16' height='16' /> : <CopyIcon width='16' height='16' />}
74
+ </Button>
75
+ )
76
+ }