create-jen-app 1.2.3 → 1.2.4

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 (355) hide show
  1. package/dist/colors.js +0 -17
  2. package/dist/create.js +5 -17
  3. package/dist/generator.js +14 -31
  4. package/dist/index.js +6 -1
  5. package/package.json +1 -1
  6. package/templates/ssr-isr/README.md +77 -0
  7. package/templates/ssr-isr/build.js +118 -0
  8. package/templates/ssr-isr/jen.config.ts +109 -0
  9. package/templates/ssr-isr/jenjs.d.ts +22 -0
  10. package/templates/ssr-isr/lib/api/(hello).js +9 -0
  11. package/templates/ssr-isr/lib/auth/cookie-utils.js +79 -0
  12. package/templates/ssr-isr/lib/auth/index.js +2 -0
  13. package/templates/ssr-isr/lib/auth/jwt.js +57 -0
  14. package/templates/ssr-isr/lib/auth/session.js +92 -0
  15. package/templates/ssr-isr/lib/build/asset-hashing.d.ts +10 -0
  16. package/templates/ssr-isr/lib/build/asset-hashing.js +25 -0
  17. package/templates/ssr-isr/lib/build/asset-manifest.d.ts +11 -0
  18. package/templates/ssr-isr/lib/build/asset-manifest.js +21 -0
  19. package/templates/{static → ssr-isr}/lib/build/build.d.ts +1 -1
  20. package/templates/ssr-isr/lib/build/build.js +141 -0
  21. package/templates/{static → ssr-isr}/lib/build/island-hydration.d.ts +8 -5
  22. package/templates/ssr-isr/lib/build/island-hydration.js +44 -0
  23. package/templates/ssr-isr/lib/build/minifier.d.ts +20 -0
  24. package/templates/ssr-isr/lib/build/minifier.js +46 -0
  25. package/templates/ssr-isr/lib/build/page-renderer.d.ts +17 -0
  26. package/templates/ssr-isr/lib/build/page-renderer.js +28 -0
  27. package/templates/ssr-isr/lib/build/production-build.d.ts +10 -0
  28. package/templates/ssr-isr/lib/build/production-build.js +13 -0
  29. package/templates/ssr-isr/lib/build/ssg-pipeline.d.ts +15 -0
  30. package/templates/ssr-isr/lib/build/ssg-pipeline.js +113 -0
  31. package/templates/ssr-isr/lib/build-tools/build-site.js +36 -0
  32. package/templates/ssr-isr/lib/cache/index.js +10 -0
  33. package/templates/ssr-isr/lib/cache/memory.js +40 -0
  34. package/templates/ssr-isr/lib/cache/redis.js +61 -0
  35. package/templates/ssr-isr/lib/cli/banner.js +28 -0
  36. package/templates/ssr-isr/lib/cli/templates/ssg/jen.config.js +32 -0
  37. package/templates/ssr-isr/lib/cli/templates/ssg/site/index.js +9 -0
  38. package/templates/ssr-isr/lib/cli/templates/ssr/jen.config.js +32 -0
  39. package/templates/ssr-isr/lib/cli/templates/ssr/site/index.js +9 -0
  40. package/templates/ssr-isr/lib/compilers/esbuild-plugins.js +111 -0
  41. package/templates/ssr-isr/lib/compilers/svelte.js +44 -0
  42. package/templates/ssr-isr/lib/compilers/vue.js +90 -0
  43. package/templates/ssr-isr/lib/core/http.js +71 -0
  44. package/templates/ssr-isr/lib/core/middleware-hooks.js +97 -0
  45. package/templates/ssr-isr/lib/core/paths.js +39 -0
  46. package/templates/ssr-isr/lib/core/routes/match.js +47 -0
  47. package/templates/ssr-isr/lib/core/routes/scan.js +190 -0
  48. package/templates/ssr-isr/lib/core/types.js +1 -0
  49. package/templates/ssr-isr/lib/css/compiler.js +74 -0
  50. package/templates/ssr-isr/lib/db/connector.js +42 -0
  51. package/templates/ssr-isr/lib/db/drivers/jdb.js +44 -0
  52. package/templates/ssr-isr/lib/db/drivers/sql.js +182 -0
  53. package/templates/ssr-isr/lib/db/index.js +48 -0
  54. package/templates/ssr-isr/lib/db/types.js +1 -0
  55. package/templates/ssr-isr/lib/graphql/index.js +52 -0
  56. package/templates/ssr-isr/lib/graphql/resolvers.js +25 -0
  57. package/templates/ssr-isr/lib/graphql/schema.js +35 -0
  58. package/templates/ssr-isr/lib/i18n/en.json +4 -0
  59. package/templates/ssr-isr/lib/i18n/es.json +4 -0
  60. package/templates/ssr-isr/lib/i18n/index.js +15 -0
  61. package/templates/ssr-isr/lib/import/jen-import.js +161 -0
  62. package/templates/ssr-isr/lib/index.js +116 -0
  63. package/templates/ssr-isr/lib/jdb/engine.js +275 -0
  64. package/templates/ssr-isr/lib/jdb/index.js +34 -0
  65. package/templates/ssr-isr/lib/jdb/types.js +1 -0
  66. package/templates/ssr-isr/lib/jdb/utils.js +176 -0
  67. package/templates/{static → ssr-isr}/lib/middleware/builtins/body-parser.js +0 -17
  68. package/templates/ssr-isr/lib/middleware/builtins/cors.js +54 -0
  69. package/templates/{static → ssr-isr}/lib/middleware/builtins/logger.js +0 -17
  70. package/templates/{static → ssr-isr}/lib/middleware/builtins/rate-limit.js +0 -17
  71. package/templates/{static → ssr-isr}/lib/middleware/builtins/request-id.js +0 -17
  72. package/templates/{static → ssr-isr}/lib/middleware/builtins/security-headers.js +0 -17
  73. package/templates/ssr-isr/lib/middleware/context.js +124 -0
  74. package/templates/{static → ssr-isr}/lib/middleware/decorators.js +0 -17
  75. package/templates/{static → ssr-isr}/lib/middleware/errors/handler.js +0 -17
  76. package/templates/ssr-isr/lib/middleware/errors/http-error.js +10 -0
  77. package/templates/ssr-isr/lib/middleware/kernel.js +85 -0
  78. package/templates/ssr-isr/lib/middleware/pipeline.js +148 -0
  79. package/templates/ssr-isr/lib/middleware/registry.js +85 -0
  80. package/templates/ssr-isr/lib/middleware/response.js +107 -0
  81. package/templates/ssr-isr/lib/middleware/types.d.ts +1 -0
  82. package/templates/ssr-isr/lib/middleware/types.js +1 -0
  83. package/templates/ssr-isr/lib/middleware/utils/matcher.js +13 -0
  84. package/templates/{static → ssr-isr}/lib/native/bundle.js +0 -17
  85. package/templates/{static → ssr-isr}/lib/native/dev-server.js +0 -17
  86. package/templates/{static → ssr-isr}/lib/native/index.js +0 -17
  87. package/templates/{static → ssr-isr}/lib/native/optimizer.js +0 -17
  88. package/templates/ssr-isr/lib/native/style-compiler.js +19 -0
  89. package/templates/ssr-isr/lib/plugin/loader.js +36 -0
  90. package/templates/ssr-isr/lib/runtime/client-runtime.js +25 -0
  91. package/templates/ssr-isr/lib/runtime/hmr.js +59 -0
  92. package/templates/ssr-isr/lib/runtime/hydrate.js +55 -0
  93. package/templates/ssr-isr/lib/runtime/island-hydration-client.js +146 -0
  94. package/templates/ssr-isr/lib/runtime/islands.js +110 -0
  95. package/templates/ssr-isr/lib/runtime/render.js +244 -0
  96. package/templates/ssr-isr/lib/server/api-routes.js +237 -0
  97. package/templates/ssr-isr/lib/server/api.js +108 -0
  98. package/templates/ssr-isr/lib/server/app.js +438 -0
  99. package/templates/ssr-isr/lib/server/runtimeServe.js +169 -0
  100. package/templates/ssr-isr/lib/server/ssr.js +202 -0
  101. package/templates/ssr-isr/lib/shared/log.js +64 -0
  102. package/templates/ssr-isr/package.json +23 -0
  103. package/templates/ssr-isr/server.js +128 -0
  104. package/templates/ssr-isr/site/pages/(index).tsx +11 -0
  105. package/templates/ssr-isr/site/styles/global.scss +37 -0
  106. package/templates/ssr-isr/tsconfig.json +39 -0
  107. package/templates/static/build.js +30 -18
  108. package/templates/static/jen.config.ts +0 -18
  109. package/templates/static/jenjs.d.ts +0 -18
  110. package/templates/static/lib/api/(hello).js +0 -17
  111. package/templates/static/lib/api/examples/files/[...slug].js +22 -0
  112. package/templates/static/lib/api/examples/hello.js +11 -0
  113. package/templates/static/lib/api/examples/posts/[id].js +37 -0
  114. package/templates/static/lib/api/examples/posts.js +37 -0
  115. package/templates/static/lib/api/examples/search.js +23 -0
  116. package/templates/static/lib/api/index.js +41 -0
  117. package/templates/static/lib/api/loader.js +234 -0
  118. package/templates/static/lib/api/router.js +259 -0
  119. package/templates/static/lib/assets/types.js +1 -0
  120. package/templates/static/lib/auth/cookie-utils.js +3 -16
  121. package/templates/static/lib/auth/index.js +0 -17
  122. package/templates/static/lib/auth/jwt.js +0 -17
  123. package/templates/static/lib/auth/session.js +0 -17
  124. package/templates/static/lib/build/asset-hashing.js +44 -36
  125. package/templates/static/lib/build/asset-manifest.js +16 -33
  126. package/templates/static/lib/build/build.js +270 -125
  127. package/templates/static/lib/build/bundle-analyzer-ui.js +417 -0
  128. package/templates/static/lib/build/bundle-analyzer.js +945 -0
  129. package/templates/static/lib/build/code-splitter.js +194 -0
  130. package/templates/static/lib/build/feature-analyzer.js +190 -0
  131. package/templates/static/lib/build/feature-gate.js +257 -0
  132. package/templates/static/lib/build/island-hydration.js +17 -35
  133. package/templates/static/lib/build/lazy-loader.js +322 -0
  134. package/templates/static/lib/build/minifier.js +40 -59
  135. package/templates/static/lib/build/page-renderer.js +23 -40
  136. package/templates/static/lib/build/production-build.js +9 -26
  137. package/templates/static/lib/build/rust-hashing.js +71 -0
  138. package/templates/static/lib/build/script-optimizer.js +285 -0
  139. package/templates/static/lib/build/ssg-pipeline.js +100 -106
  140. package/templates/static/lib/build/vercel-output.js +298 -0
  141. package/templates/static/lib/build-tools/build-site.js +0 -17
  142. package/templates/static/lib/cache/index.js +0 -17
  143. package/templates/static/lib/cache/memory.js +0 -17
  144. package/templates/static/lib/cache/redis.js +0 -17
  145. package/templates/static/lib/cli/banner.js +0 -17
  146. package/templates/static/lib/cli/templates/ssg/jen.config.js +0 -17
  147. package/templates/static/lib/cli/templates/ssr/jen.config.js +0 -17
  148. package/templates/static/lib/client/Image.js +42 -0
  149. package/templates/static/lib/client/Link.js +190 -0
  150. package/templates/static/lib/client/PWA.js +46 -0
  151. package/templates/static/lib/client/Seo.js +97 -0
  152. package/templates/static/lib/client/index.js +9 -0
  153. package/templates/static/lib/client/useNavigation.js +25 -0
  154. package/templates/static/lib/client/useRouter.js +64 -0
  155. package/templates/static/lib/client-routing/Link.js +17 -0
  156. package/templates/static/lib/client-routing/index.js +19 -0
  157. package/templates/static/lib/client-routing/router.js +151 -0
  158. package/templates/static/lib/client-routing/signal.js +147 -0
  159. package/templates/static/lib/compilers/esbuild-plugins.js +0 -17
  160. package/templates/static/lib/compilers/svelte.js +0 -17
  161. package/templates/static/lib/compilers/vue.js +0 -17
  162. package/templates/static/lib/core/config.js +0 -17
  163. package/templates/static/lib/core/feature-guard.js +136 -0
  164. package/templates/static/lib/core/features.js +99 -0
  165. package/templates/static/lib/core/http.js +0 -17
  166. package/templates/static/lib/core/layouts/index.js +10 -0
  167. package/templates/static/lib/core/layouts/render.js +158 -0
  168. package/templates/static/lib/core/layouts/scan.js +112 -0
  169. package/templates/static/lib/core/layouts/types.js +1 -0
  170. package/templates/static/lib/core/lifecycle.js +129 -0
  171. package/templates/static/lib/core/loader-schema.js +81 -0
  172. package/templates/static/lib/core/middleware-hooks.js +0 -17
  173. package/templates/static/lib/core/paths.js +0 -17
  174. package/templates/static/lib/core/routes/advanced.js +114 -0
  175. package/templates/static/lib/core/routes/handlers.js +181 -0
  176. package/templates/static/lib/core/routes/match.js +89 -17
  177. package/templates/static/lib/core/routes/orchestrator.js +171 -0
  178. package/templates/static/lib/core/routes/rendering-config.js +131 -0
  179. package/templates/static/lib/core/routes/scan.js +0 -17
  180. package/templates/static/lib/core/types.js +0 -17
  181. package/templates/static/lib/css/compiler.js +1 -18
  182. package/templates/static/lib/data-fetching/cache.js +223 -0
  183. package/templates/static/lib/data-fetching/client.js +202 -0
  184. package/templates/static/lib/data-fetching/feature-guard.js +29 -0
  185. package/templates/static/lib/data-fetching/graphql.js +265 -0
  186. package/templates/static/lib/data-fetching/index.js +57 -0
  187. package/templates/static/lib/data-fetching/rest.js +256 -0
  188. package/templates/static/lib/data-fetching/server.js +182 -0
  189. package/templates/static/lib/data-fetching/types.js +5 -0
  190. package/templates/static/lib/db/connector.js +0 -17
  191. package/templates/static/lib/db/drivers/jdb.js +0 -17
  192. package/templates/static/lib/db/drivers/sql.js +0 -17
  193. package/templates/static/lib/db/index.js +0 -17
  194. package/templates/static/lib/db/types.js +0 -17
  195. package/templates/static/lib/devtools/component-tree.js +106 -0
  196. package/templates/static/lib/devtools/devtools.js +638 -0
  197. package/templates/static/lib/devtools/event-bus.js +29 -0
  198. package/templates/static/lib/devtools/event-logger.js +67 -0
  199. package/templates/static/lib/devtools/index.js +9 -0
  200. package/templates/static/lib/devtools/integration.js +149 -0
  201. package/templates/static/lib/devtools/performance.js +84 -0
  202. package/templates/static/lib/devtools/persistence.js +57 -0
  203. package/templates/static/lib/devtools/plugins.js +97 -0
  204. package/templates/static/lib/devtools/search.js +89 -0
  205. package/templates/static/lib/devtools/ui.js +769 -0
  206. package/templates/static/lib/features/api/handler.js +10 -0
  207. package/templates/static/lib/features/api/index.js +5 -0
  208. package/templates/static/lib/features/api/types.js +4 -0
  209. package/templates/static/lib/features/middleware/compiled.js +7 -0
  210. package/templates/static/lib/features/middleware/index.js +5 -0
  211. package/templates/static/lib/features/middleware/types.js +4 -0
  212. package/templates/static/lib/fonts/index.js +46 -0
  213. package/templates/static/lib/fonts/inject.js +125 -0
  214. package/templates/static/lib/fonts/loader.js +196 -0
  215. package/templates/static/lib/fonts/types.js +1 -0
  216. package/templates/static/lib/graphql/index.js +1 -18
  217. package/templates/static/lib/graphql/resolvers.js +20 -13
  218. package/templates/static/lib/graphql/schema.js +0 -17
  219. package/templates/static/lib/i18n/index.js +7 -19
  220. package/templates/static/lib/import/jen-import.js +1 -18
  221. package/templates/static/lib/index.js +79 -125
  222. package/templates/static/lib/jdb/engine.js +0 -17
  223. package/templates/static/lib/jdb/index.js +1 -18
  224. package/templates/static/lib/jdb/types.js +0 -17
  225. package/templates/static/lib/jdb/utils.js +0 -17
  226. package/templates/static/lib/middleware/builtins/cors.js +3 -16
  227. package/templates/static/lib/middleware/context.js +0 -17
  228. package/templates/static/lib/middleware/kernel.js +117 -25
  229. package/templates/static/lib/middleware/pipeline.js +0 -17
  230. package/templates/static/lib/middleware/registry.js +0 -17
  231. package/templates/static/lib/middleware/response.js +0 -17
  232. package/templates/static/lib/plugin/examples/analytics-plugin.js +183 -0
  233. package/templates/static/lib/plugin/examples/cdn-upload-plugin.js +94 -0
  234. package/templates/static/lib/plugin/loader.js +0 -17
  235. package/templates/static/lib/plugin/plugin-manager.js +177 -0
  236. package/templates/static/lib/plugin/types.js +28 -0
  237. package/templates/static/lib/runtime/client-runtime.js +0 -17
  238. package/templates/static/lib/runtime/hmr.js +0 -17
  239. package/templates/static/lib/runtime/hydrate.js +0 -17
  240. package/templates/static/lib/runtime/island-hydration-client.js +0 -17
  241. package/templates/static/lib/runtime/islands.js +0 -17
  242. package/templates/static/lib/runtime/render.js +208 -50
  243. package/templates/static/lib/security/security-config.js +60 -0
  244. package/templates/static/lib/security/security-middleware.js +229 -0
  245. package/templates/static/lib/server/api-routes.js +153 -43
  246. package/templates/static/lib/server/api.js +0 -17
  247. package/templates/static/lib/server/app.js +539 -223
  248. package/templates/static/lib/server/isr.js +365 -0
  249. package/templates/static/lib/server/runtimeServe.js +31 -24
  250. package/templates/static/lib/server/ssr.js +98 -22
  251. package/templates/static/lib/server-actions/handler.js +180 -0
  252. package/templates/static/lib/server-actions/index.js +19 -0
  253. package/templates/static/lib/server-actions/middleware.js +146 -0
  254. package/templates/static/lib/server-actions/scan.js +152 -0
  255. package/templates/static/lib/server-actions/types.js +1 -0
  256. package/templates/static/lib/server-actions/validators.js +156 -0
  257. package/templates/static/lib/shared/log.js +19 -20
  258. package/templates/static/lib/telemetry/api/rate-limiter.js +32 -0
  259. package/templates/static/lib/telemetry/api/validator.js +67 -0
  260. package/templates/static/lib/telemetry/client.js +121 -0
  261. package/templates/static/lib/telemetry/tests/rate-limiter.test.js +46 -0
  262. package/templates/static/lib/telemetry/tests/validator.test.js +62 -0
  263. package/templates/static/lib/vendor/glob/glob.js +4766 -0
  264. package/templates/static/lib/vendor/preact/LICENSE +21 -0
  265. package/templates/static/lib/vendor/preact/preact.module.js +797 -0
  266. package/templates/static/lib/vendor/sass/sass.node.mjs +212 -0
  267. package/templates/static/package.json +4 -0
  268. package/templates/static/server.js +22 -22
  269. package/templates/static/site/(home).tsx +0 -18
  270. package/templates/static/tsconfig.json +5 -1
  271. package/templates/static/.esbuild/jen.config.js +0 -19
  272. package/templates/static/lib/build/asset-hashing.d.ts +0 -10
  273. package/templates/static/lib/build/asset-manifest.d.ts +0 -11
  274. package/templates/static/lib/build/minifier.d.ts +0 -20
  275. package/templates/static/lib/build/page-renderer.d.ts +0 -17
  276. package/templates/static/lib/build/production-build.d.ts +0 -10
  277. package/templates/static/lib/build/ssg-pipeline.d.ts +0 -15
  278. package/templates/static/lib/middleware/errors/http-error.js +0 -27
  279. package/templates/static/lib/middleware/types.js +0 -18
  280. package/templates/static/lib/middleware/utils/matcher.js +0 -30
  281. package/templates/static/lib/native/style-compiler.js +0 -36
  282. /package/templates/{static → ssr-isr}/lib/api/(hello).d.ts +0 -0
  283. /package/templates/{static → ssr-isr}/lib/auth/cookie-utils.d.ts +0 -0
  284. /package/templates/{static → ssr-isr}/lib/auth/index.d.ts +0 -0
  285. /package/templates/{static → ssr-isr}/lib/auth/jwt.d.ts +0 -0
  286. /package/templates/{static → ssr-isr}/lib/auth/session.d.ts +0 -0
  287. /package/templates/{static → ssr-isr}/lib/build-tools/build-site.d.ts +0 -0
  288. /package/templates/{static → ssr-isr}/lib/cache/index.d.ts +0 -0
  289. /package/templates/{static → ssr-isr}/lib/cache/memory.d.ts +0 -0
  290. /package/templates/{static → ssr-isr}/lib/cache/redis.d.ts +0 -0
  291. /package/templates/{static → ssr-isr}/lib/cli/banner.d.ts +0 -0
  292. /package/templates/{static → ssr-isr}/lib/cli/templates/ssg/jen.config.d.ts +0 -0
  293. /package/templates/{static → ssr-isr}/lib/cli/templates/ssg/site/index.d.ts +0 -0
  294. /package/templates/{static → ssr-isr}/lib/cli/templates/ssr/jen.config.d.ts +0 -0
  295. /package/templates/{static → ssr-isr}/lib/cli/templates/ssr/site/index.d.ts +0 -0
  296. /package/templates/{static → ssr-isr}/lib/compilers/esbuild-plugins.d.ts +0 -0
  297. /package/templates/{static → ssr-isr}/lib/compilers/svelte.d.ts +0 -0
  298. /package/templates/{static → ssr-isr}/lib/compilers/vue.d.ts +0 -0
  299. /package/templates/{static → ssr-isr}/lib/core/config.d.ts +0 -0
  300. /package/templates/{static/lib/middleware/types.d.ts → ssr-isr/lib/core/config.js} +0 -0
  301. /package/templates/{static → ssr-isr}/lib/core/http.d.ts +0 -0
  302. /package/templates/{static → ssr-isr}/lib/core/middleware-hooks.d.ts +0 -0
  303. /package/templates/{static → ssr-isr}/lib/core/paths.d.ts +0 -0
  304. /package/templates/{static → ssr-isr}/lib/core/routes/match.d.ts +0 -0
  305. /package/templates/{static → ssr-isr}/lib/core/routes/scan.d.ts +0 -0
  306. /package/templates/{static → ssr-isr}/lib/core/types.d.ts +0 -0
  307. /package/templates/{static → ssr-isr}/lib/css/compiler.d.ts +0 -0
  308. /package/templates/{static → ssr-isr}/lib/db/connector.d.ts +0 -0
  309. /package/templates/{static → ssr-isr}/lib/db/drivers/jdb.d.ts +0 -0
  310. /package/templates/{static → ssr-isr}/lib/db/drivers/sql.d.ts +0 -0
  311. /package/templates/{static → ssr-isr}/lib/db/index.d.ts +0 -0
  312. /package/templates/{static → ssr-isr}/lib/db/types.d.ts +0 -0
  313. /package/templates/{static → ssr-isr}/lib/graphql/index.d.ts +0 -0
  314. /package/templates/{static → ssr-isr}/lib/graphql/resolvers.d.ts +0 -0
  315. /package/templates/{static → ssr-isr}/lib/graphql/schema.d.ts +0 -0
  316. /package/templates/{static → ssr-isr}/lib/i18n/index.d.ts +0 -0
  317. /package/templates/{static → ssr-isr}/lib/import/jen-import.d.ts +0 -0
  318. /package/templates/{static → ssr-isr}/lib/index.d.ts +0 -0
  319. /package/templates/{static → ssr-isr}/lib/jdb/engine.d.ts +0 -0
  320. /package/templates/{static → ssr-isr}/lib/jdb/index.d.ts +0 -0
  321. /package/templates/{static → ssr-isr}/lib/jdb/types.d.ts +0 -0
  322. /package/templates/{static → ssr-isr}/lib/jdb/utils.d.ts +0 -0
  323. /package/templates/{static → ssr-isr}/lib/middleware/builtins/body-parser.d.ts +0 -0
  324. /package/templates/{static → ssr-isr}/lib/middleware/builtins/cors.d.ts +0 -0
  325. /package/templates/{static → ssr-isr}/lib/middleware/builtins/logger.d.ts +0 -0
  326. /package/templates/{static → ssr-isr}/lib/middleware/builtins/rate-limit.d.ts +0 -0
  327. /package/templates/{static → ssr-isr}/lib/middleware/builtins/request-id.d.ts +0 -0
  328. /package/templates/{static → ssr-isr}/lib/middleware/builtins/security-headers.d.ts +0 -0
  329. /package/templates/{static → ssr-isr}/lib/middleware/context.d.ts +0 -0
  330. /package/templates/{static → ssr-isr}/lib/middleware/decorators.d.ts +0 -0
  331. /package/templates/{static → ssr-isr}/lib/middleware/errors/handler.d.ts +0 -0
  332. /package/templates/{static → ssr-isr}/lib/middleware/errors/http-error.d.ts +0 -0
  333. /package/templates/{static → ssr-isr}/lib/middleware/kernel.d.ts +0 -0
  334. /package/templates/{static → ssr-isr}/lib/middleware/pipeline.d.ts +0 -0
  335. /package/templates/{static → ssr-isr}/lib/middleware/registry.d.ts +0 -0
  336. /package/templates/{static → ssr-isr}/lib/middleware/response.d.ts +0 -0
  337. /package/templates/{static → ssr-isr}/lib/middleware/utils/matcher.d.ts +0 -0
  338. /package/templates/{static → ssr-isr}/lib/native/bundle.d.ts +0 -0
  339. /package/templates/{static → ssr-isr}/lib/native/dev-server.d.ts +0 -0
  340. /package/templates/{static → ssr-isr}/lib/native/index.d.ts +0 -0
  341. /package/templates/{static → ssr-isr}/lib/native/optimizer.d.ts +0 -0
  342. /package/templates/{static → ssr-isr}/lib/native/style-compiler.d.ts +0 -0
  343. /package/templates/{static → ssr-isr}/lib/plugin/loader.d.ts +0 -0
  344. /package/templates/{static → ssr-isr}/lib/runtime/client-runtime.d.ts +0 -0
  345. /package/templates/{static → ssr-isr}/lib/runtime/hmr.d.ts +0 -0
  346. /package/templates/{static → ssr-isr}/lib/runtime/hydrate.d.ts +0 -0
  347. /package/templates/{static → ssr-isr}/lib/runtime/island-hydration-client.d.ts +0 -0
  348. /package/templates/{static → ssr-isr}/lib/runtime/islands.d.ts +0 -0
  349. /package/templates/{static → ssr-isr}/lib/runtime/render.d.ts +0 -0
  350. /package/templates/{static → ssr-isr}/lib/server/api-routes.d.ts +0 -0
  351. /package/templates/{static → ssr-isr}/lib/server/api.d.ts +0 -0
  352. /package/templates/{static → ssr-isr}/lib/server/app.d.ts +0 -0
  353. /package/templates/{static → ssr-isr}/lib/server/runtimeServe.d.ts +0 -0
  354. /package/templates/{static → ssr-isr}/lib/server/ssr.d.ts +0 -0
  355. /package/templates/{static → ssr-isr}/lib/shared/log.d.ts +0 -0
@@ -0,0 +1,298 @@
1
+ /**
2
+ * Vercel Build Output API v3 Integration for Jen.js
3
+ *
4
+ * This module generates the .vercel/output directory structure compatible with
5
+ * Vercel's Build Output API specification. It automatically detects and configures
6
+ * SSR, SSG, and ISR routes with minimal overhead and cold start size.
7
+ *
8
+ * Spec: https://vercel.com/docs/build-output-api/v3
9
+ */
10
+ import { mkdirSync, writeFileSync } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { log } from "../shared/log.js";
13
+ /**
14
+ * Detects rendering mode from route module.
15
+ * Defaults to SSG if not specified.
16
+ */
17
+ export function detectRenderingMode(filePath) {
18
+ // In a real implementation, this would dynamically import the module
19
+ // and read the exported `rendering` property.
20
+ // For now, return "ssg" as default.
21
+ // Extended implementation would require module evaluation.
22
+ return "ssg";
23
+ }
24
+ /**
25
+ * Detects ISR revalidation time from route module.
26
+ * Returns undefined if route is not ISR or doesn't specify revalidate.
27
+ */
28
+ export function detectRevalidateSeconds(filePath) {
29
+ // Similar to detectRenderingMode, this would require module evaluation.
30
+ // Returns 3600 (1 hour) as example default for ISR routes.
31
+ return undefined;
32
+ }
33
+ /**
34
+ * Generates a unique function name from route path.
35
+ * Ensures compatibility with Vercel's naming requirements.
36
+ */
37
+ export function functionNameFromRoute(route) {
38
+ // /posts/:id => posts_id
39
+ // /api/users => api_users
40
+ const name = route.urlPath
41
+ .split("/")
42
+ .filter(Boolean)
43
+ .map((s) => s.replace(/[^a-zA-Z0-9_]/g, "_"))
44
+ .join("_");
45
+ return name || "index";
46
+ }
47
+ /**
48
+ * Converts Jen.js route pattern to Vercel-compatible regex source.
49
+ * Handles dynamic segments and catch-all routes.
50
+ */
51
+ export function convertRoutePattern(route) {
52
+ // Jen.js pattern is already in regex format like "^/posts/([^/]+)/?$"
53
+ // Return as-is since Vercel accepts regex patterns
54
+ return route.pattern;
55
+ }
56
+ /**
57
+ * Main Vercel output builder for a set of routes.
58
+ * Organizes routes by rendering mode and generates all required files.
59
+ */
60
+ export class VercelOutputBuilder {
61
+ outputDir;
62
+ config;
63
+ routes = [];
64
+ ssrRoutes = [];
65
+ ssgRoutes = [];
66
+ isrRoutes = [];
67
+ constructor(outputDir, config) {
68
+ this.outputDir = outputDir;
69
+ this.config = config;
70
+ }
71
+ /**
72
+ * Register a route with its rendering mode.
73
+ * Called during build for each discovered route.
74
+ */
75
+ addRoute(route, mode) {
76
+ const revalidateSeconds =
77
+ mode === "isr"
78
+ ? this.config.rendering.defaultRevalidateSeconds
79
+ : undefined;
80
+ const metadata = { route, mode, revalidateSeconds };
81
+ this.routes.push(metadata);
82
+ if (mode === "ssg") this.ssgRoutes.push(metadata);
83
+ else if (mode === "ssr") this.ssrRoutes.push(metadata);
84
+ else this.isrRoutes.push(metadata);
85
+ }
86
+ /**
87
+ * Generate the complete .vercel/output structure.
88
+ * Must be called after all routes are registered.
89
+ */
90
+ async build() {
91
+ mkdirSync(this.outputDir, { recursive: true });
92
+ // 1. Create static outputs for SSG routes
93
+ if (this.ssgRoutes.length > 0) {
94
+ await this.generateSsgStatics();
95
+ }
96
+ // 2. Generate serverless functions for SSR/ISR routes
97
+ if (this.ssrRoutes.length > 0 || this.isrRoutes.length > 0) {
98
+ await this.generateServerlessFunctions();
99
+ }
100
+ // 3. Generate prerender config for ISR routes
101
+ if (this.isrRoutes.length > 0) {
102
+ this.generatePrerenderConfig();
103
+ }
104
+ // 4. Generate main config.json
105
+ this.generateConfigJson();
106
+ log.info(
107
+ `Vercel output generated: ${this.ssgRoutes.length} SSG, ${this.ssrRoutes.length} SSR, ${this.isrRoutes.length} ISR`,
108
+ );
109
+ }
110
+ /**
111
+ * Generate static HTML files in .vercel/output/static
112
+ */
113
+ async generateSsgStatics() {
114
+ const staticDir = join(this.outputDir, "static");
115
+ mkdirSync(staticDir, { recursive: true });
116
+ for (const { route } of this.ssgRoutes) {
117
+ // Route HTML should be pre-rendered into .vercel/output/static
118
+ // In actual build, would copy from dist/
119
+ const path =
120
+ route.urlPath === "/"
121
+ ? "index.html"
122
+ : `${route.urlPath.slice(1)}/index.html`;
123
+ const filePath = join(staticDir, path);
124
+ mkdirSync(join(filePath, ".."), { recursive: true });
125
+ // Placeholder - actual HTML would come from rendering phase
126
+ writeFileSync(filePath, `<!-- SSG: ${route.urlPath} -->`);
127
+ log.info(`SSG static: ${path}`);
128
+ }
129
+ }
130
+ /**
131
+ * Generate serverless function handlers for SSR/ISR routes.
132
+ * Creates minimal Node.js handler compatible with Vercel.
133
+ */
134
+ async generateServerlessFunctions() {
135
+ const functionsDir = join(this.outputDir, "functions");
136
+ mkdirSync(functionsDir, { recursive: true });
137
+ const allDynamic = [...this.ssrRoutes, ...this.isrRoutes];
138
+ const functions = {};
139
+ for (const { route } of allDynamic) {
140
+ const funcName = functionNameFromRoute(route);
141
+ const funcDir = join(functionsDir, funcName + ".func");
142
+ mkdirSync(funcDir, { recursive: true });
143
+ // Generate handler entry point
144
+ const handler = this.generateHandlerCode(route);
145
+ writeFileSync(join(funcDir, "index.js"), handler);
146
+ // Generate .vc-config.json for Vercel
147
+ const vcConfig = {
148
+ runtime: "nodejs20.x",
149
+ handler: "index.js",
150
+ lazyRoutes: [route.urlPath],
151
+ maxDuration: 30,
152
+ memory: 1024, // Minimal memory for lightweight functions
153
+ };
154
+ writeFileSync(
155
+ join(funcDir, ".vc-config.json"),
156
+ JSON.stringify(vcConfig, null, 2),
157
+ );
158
+ functions[funcName] = vcConfig;
159
+ log.info(`SSR function: ${funcName}`);
160
+ }
161
+ }
162
+ /**
163
+ * Generate minimal handler code for serverless function.
164
+ * Must be compatible with Vercel's Node.js runtime.
165
+ */
166
+ generateHandlerCode(route) {
167
+ return `// Jen.js Vercel Function Handler - ${route.urlPath}
168
+ // Minimal cold-start optimized handler
169
+
170
+ import { render } from '../../../dist/jen-runtime.js';
171
+
172
+ export default async function handler(req, res) {
173
+ try {
174
+ // Parse request
175
+ const url = new URL(req.url || '/', \`http://\${req.headers.host}\`);
176
+ const params = extractParams(req, '${route.pattern}');
177
+
178
+ // Render page
179
+ const html = await render({
180
+ route: '${route.urlPath}',
181
+ params,
182
+ query: url.searchParams,
183
+ headers: req.headers,
184
+ });
185
+
186
+ res.setHeader('content-type', 'text/html; charset=utf-8');
187
+ res.end(html);
188
+ } catch (err) {
189
+ res.status(500).end('Internal Server Error');
190
+ }
191
+ }
192
+
193
+ function extractParams(req, pattern) {
194
+ // Extract path params from URL using route pattern
195
+ const url = new URL(req.url || '/', \`http://\${req.headers.host}\`);
196
+ const match = url.pathname.match(new RegExp(pattern));
197
+ return match ? match.slice(1) : [];
198
+ }`;
199
+ }
200
+ /**
201
+ * Generate prerender-config.json for ISR routes
202
+ */
203
+ generatePrerenderConfig() {
204
+ const prerenderDir = join(this.outputDir, "prerender");
205
+ mkdirSync(prerenderDir, { recursive: true });
206
+ for (const { route, revalidateSeconds } of this.isrRoutes) {
207
+ const configName = route.urlPath.replace(/\//g, "_") || "root";
208
+ const config = {
209
+ version: 1,
210
+ expiration: revalidateSeconds || 3600,
211
+ fallback: null,
212
+ group: "pages",
213
+ };
214
+ writeFileSync(
215
+ join(prerenderDir, `${configName}.json`),
216
+ JSON.stringify(config, null, 2),
217
+ );
218
+ log.info(
219
+ `ISR prerender config: ${route.urlPath} (${revalidateSeconds}s)`,
220
+ );
221
+ }
222
+ }
223
+ /**
224
+ * Generate main config.json for .vercel/output
225
+ */
226
+ generateConfigJson() {
227
+ const config = {
228
+ version: 3,
229
+ routes: [],
230
+ functions: {},
231
+ overrides: {},
232
+ };
233
+ // 1. Add static routes (SSG)
234
+ for (const { route } of this.ssgRoutes) {
235
+ const path =
236
+ route.urlPath === "/" ? "/index.html" : `${route.urlPath}/index.html`;
237
+ config.routes.push({
238
+ src: route.pattern,
239
+ dest: path,
240
+ methods: ["GET"],
241
+ });
242
+ }
243
+ // 2. Add dynamic routes (SSR/ISR)
244
+ for (const { route } of [...this.ssrRoutes, ...this.isrRoutes]) {
245
+ const funcName = functionNameFromRoute(route);
246
+ config.routes.push({
247
+ src: route.pattern,
248
+ dest: `/functions/${funcName}`,
249
+ methods: ["GET", "HEAD"],
250
+ });
251
+ config.functions[funcName] = {
252
+ runtime: "nodejs20.x",
253
+ handler: `functions/${funcName}.func/index.js`,
254
+ maxDuration: 30,
255
+ memory: 1024,
256
+ };
257
+ }
258
+ // 3. Add asset overrides for caching
259
+ const cacheControl = this.config.assets.cacheControl;
260
+ config.overrides["/assets/*"] = {
261
+ path: "/assets/*",
262
+ maxAge: this.parseMaxAge(cacheControl),
263
+ };
264
+ // 4. Fallback for unmatched routes (404 or SSR)
265
+ config.routes.push({
266
+ src: "/(.*)",
267
+ status: 404,
268
+ });
269
+ writeFileSync(
270
+ join(this.outputDir, "config.json"),
271
+ JSON.stringify(config, null, 2),
272
+ );
273
+ log.info(`config.json generated`);
274
+ }
275
+ /**
276
+ * Parse max-age from Cache-Control header
277
+ */
278
+ parseMaxAge(cacheControl) {
279
+ const match = cacheControl.match(/max-age=(\d+)/);
280
+ return match ? parseInt(match[1], 10) : 31536000; // 1 year default
281
+ }
282
+ }
283
+ /**
284
+ * Convenience function to build Vercel output from discovered routes.
285
+ * Typically called from the main build pipeline.
286
+ *
287
+ * @param outputDir Path to .vercel/output directory
288
+ * @param config Framework configuration
289
+ * @param routes All discovered routes
290
+ */
291
+ export async function buildVercelOutput(outputDir, config, routes) {
292
+ const builder = new VercelOutputBuilder(outputDir, config);
293
+ for (const route of routes) {
294
+ const mode = detectRenderingMode(route.filePath);
295
+ builder.addRoute(route, mode);
296
+ }
297
+ await builder.build();
298
+ }
@@ -1,20 +1,3 @@
1
- /*
2
- * This file is part of Jen.js.
3
- * Copyright (C) 2026 oopsio
4
- *
5
- * This program is free software: you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License as published by
7
- * the Free Software Foundation, either version 3 of the License, or
8
- * (at your option) any later version.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
- */
18
1
  // Site build utilities
19
2
  // Migrated from Python src/python/build.py
20
3
  import { copyFileSync, rmSync, mkdirSync, readdirSync } from "node:fs";
@@ -1,20 +1,3 @@
1
- /*
2
- * This file is part of Jen.js.
3
- * Copyright (C) 2026 oopsio
4
- *
5
- * This program is free software: you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License as published by
7
- * the Free Software Foundation, either version 3 of the License, or
8
- * (at your option) any later version.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
- */
18
1
  /**
19
2
  * Cache layer module providing two implementations:
20
3
  * - MemoryCache: In-memory Map-based cache for single-process deployments.
@@ -1,20 +1,3 @@
1
- /*
2
- * This file is part of Jen.js.
3
- * Copyright (C) 2026 oopsio
4
- *
5
- * This program is free software: you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License as published by
7
- * the Free Software Foundation, either version 3 of the License, or
8
- * (at your option) any later version.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
- */
18
1
  /**
19
2
  * In-memory cache implementation using a JavaScript Map.
20
3
  * Stores key-value pairs with optional time-to-live (TTL) expiration.
@@ -1,20 +1,3 @@
1
- /*
2
- * This file is part of Jen.js.
3
- * Copyright (C) 2026 oopsio
4
- *
5
- * This program is free software: you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License as published by
7
- * the Free Software Foundation, either version 3 of the License, or
8
- * (at your option) any later version.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
- */
18
1
  /**
19
2
  * Placeholder Redis cache implementation.
20
3
  * The framework does not include the Redis library; users must install it separately.
@@ -1,20 +1,3 @@
1
- /*
2
- * This file is part of Jen.js.
3
- * Copyright (C) 2026 oopsio
4
- *
5
- * This program is free software: you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License as published by
7
- * the Free Software Foundation, either version 3 of the License, or
8
- * (at your option) any later version.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
- */
18
1
  // Stylized CLI Banner for Jen.js
19
2
  // Matches the visual style requested (Purple/Cyan gradient feel)
20
3
  const RES = "\x1b[0m";
@@ -1,20 +1,3 @@
1
- /*
2
- * This file is part of Jen.js.
3
- * Copyright (C) 2026 oopsio
4
- *
5
- * This program is free software: you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License as published by
7
- * the Free Software Foundation, either version 3 of the License, or
8
- * (at your option) any later version.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
- */
18
1
  const config = {
19
2
  siteDir: "site",
20
3
  distDir: "dist",
@@ -1,20 +1,3 @@
1
- /*
2
- * This file is part of Jen.js.
3
- * Copyright (C) 2026 oopsio
4
- *
5
- * This program is free software: you can redistribute it and/or modify
6
- * it under the terms of the GNU General Public License as published by
7
- * the Free Software Foundation, either version 3 of the License, or
8
- * (at your option) any later version.
9
- *
10
- * This program is distributed in the hope that it will be useful,
11
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
- * GNU General Public License for more details.
14
- *
15
- * You should have received a copy of the GNU General Public License
16
- * along with this program. If not, see <https://www.gnu.org/licenses/>.
17
- */
18
1
  const config = {
19
2
  siteDir: "site",
20
3
  distDir: "dist",
@@ -0,0 +1,42 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "preact/jsx-runtime";
3
+ /**
4
+ * Image component that renders a responsive picture element with lazy loading support
5
+ *
6
+ * @example
7
+ * ```tsx
8
+ * <Image src="/image.png" alt="Description" width={800} height={600} />
9
+ * <Image src="/image.png" alt="Description" loading="eager" className="hero-image" />
10
+ * ```
11
+ *
12
+ * @remarks
13
+ * Future enhancement: Add WebP and AVIF format support via source elements
14
+ * Example with future format support:
15
+ * ```tsx
16
+ * <picture>
17
+ * <source srcSet="image.avif" type="image/avif" />
18
+ * <source srcSet="image.webp" type="image/webp" />
19
+ * <img src="image.png" ... />
20
+ * </picture>
21
+ * ```
22
+ */
23
+ export function Image({
24
+ src,
25
+ alt,
26
+ width,
27
+ height,
28
+ loading = "lazy",
29
+ className,
30
+ }) {
31
+ return _jsx("picture", {
32
+ children: _jsx("img", {
33
+ src: src,
34
+ alt: alt,
35
+ width: width,
36
+ height: height,
37
+ loading: loading,
38
+ className: className,
39
+ decoding: "async",
40
+ }),
41
+ });
42
+ }
@@ -0,0 +1,190 @@
1
+ "use client";
2
+ import { jsx as _jsx } from "preact/jsx-runtime";
3
+ import { useRef, useEffect, useCallback, useState } from "preact/hooks";
4
+ const prefetched = new Set();
5
+ /**
6
+ * Checks if a click event should trigger default browser behavior
7
+ */
8
+ function isModifiedEvent(event) {
9
+ const target = event.currentTarget?.getAttribute("target");
10
+ return (
11
+ (target && target !== "_self") ||
12
+ event.metaKey ||
13
+ event.ctrlKey ||
14
+ event.shiftKey ||
15
+ event.altKey ||
16
+ event.button === 1 // middle click
17
+ );
18
+ }
19
+ /**
20
+ * Checks if URL is internal
21
+ */
22
+ function isLocalUrl(href) {
23
+ if (!href.startsWith("/")) {
24
+ return false;
25
+ }
26
+ try {
27
+ // Ensure it's a valid local URL
28
+ const url = new URL(
29
+ href,
30
+ typeof window !== "undefined" ? window.location.href : "http://localhost",
31
+ );
32
+ return (
33
+ url.hostname ===
34
+ (typeof window !== "undefined" ? window.location.hostname : "localhost")
35
+ );
36
+ } catch {
37
+ return true; // Assume local if parsing fails
38
+ }
39
+ }
40
+ /**
41
+ * Prefetch a page
42
+ */
43
+ function prefetchPage(href) {
44
+ if (typeof window === "undefined" || !isLocalUrl(href)) {
45
+ return;
46
+ }
47
+ if (prefetched.has(href)) {
48
+ return;
49
+ }
50
+ prefetched.add(href);
51
+ // Use Intersection Observer + fetch to prefetch
52
+ const link = document.createElement("link");
53
+ link.rel = "prefetch";
54
+ link.href = href;
55
+ document.head.appendChild(link);
56
+ }
57
+ /**
58
+ * Navigate to URL using client-side routing
59
+ */
60
+ function navigateTo(href, replace = false) {
61
+ if (typeof window === "undefined") {
62
+ return;
63
+ }
64
+ if (!isLocalUrl(href)) {
65
+ if (replace) {
66
+ window.location.replace(href);
67
+ } else {
68
+ window.location.href = href;
69
+ }
70
+ return;
71
+ }
72
+ // Dispatch custom navigation event
73
+ window.dispatchEvent(
74
+ new CustomEvent("jen:navigate", {
75
+ detail: { href, replace },
76
+ }),
77
+ );
78
+ // Fallback: use history API
79
+ if (replace) {
80
+ window.history.replaceState({ href }, "", href);
81
+ } else {
82
+ window.history.pushState({ href }, "", href);
83
+ }
84
+ // Scroll to top if enabled
85
+ window.scrollTo(0, 0);
86
+ }
87
+ /**
88
+ * Handles link click events
89
+ */
90
+ function handleLinkClick(event, href, replace = false, onClick) {
91
+ const target = event.currentTarget;
92
+ // Call custom handler if provided
93
+ if (onClick) {
94
+ onClick(event);
95
+ }
96
+ // Allow modified clicks (meta, ctrl, shift, alt) and downloads
97
+ if (isModifiedEvent(event) || target?.hasAttribute("download")) {
98
+ return;
99
+ }
100
+ // Prevent default for local URLs
101
+ if (isLocalUrl(href)) {
102
+ event.preventDefault();
103
+ navigateTo(href, replace);
104
+ }
105
+ }
106
+ /**
107
+ * Link component for client-side navigation
108
+ *
109
+ * @example
110
+ * ```tsx
111
+ * <Link href="/about">About</Link>
112
+ * <Link href="/blog/post-1" prefetch scroll={false}>Read More</Link>
113
+ * ```
114
+ */
115
+ export function Link({
116
+ href,
117
+ replace = false,
118
+ scroll = true,
119
+ prefetch = true,
120
+ children,
121
+ onClick,
122
+ onMouseEnter,
123
+ onTouchStart,
124
+ ...props
125
+ }) {
126
+ const linkRef = useRef(null);
127
+ const [isVisible, setIsVisible] = useState(false);
128
+ // Set up Intersection Observer for visibility detection
129
+ useEffect(() => {
130
+ if (typeof window === "undefined" || !prefetch) {
131
+ return;
132
+ }
133
+ const observer = new IntersectionObserver(([entry]) => {
134
+ setIsVisible(entry.isIntersecting);
135
+ });
136
+ if (linkRef.current) {
137
+ observer.observe(linkRef.current);
138
+ }
139
+ return () => {
140
+ observer.disconnect();
141
+ };
142
+ }, [prefetch]);
143
+ // Prefetch when visible
144
+ useEffect(() => {
145
+ if (isVisible && prefetch && isLocalUrl(href)) {
146
+ prefetchPage(href);
147
+ }
148
+ }, [isVisible, href, prefetch]);
149
+ // Handle mouse enter for prefetch on hover
150
+ const handleMouseEnter = useCallback(
151
+ (e) => {
152
+ if (onMouseEnter) {
153
+ onMouseEnter(e);
154
+ }
155
+ if (isLocalUrl(href)) {
156
+ prefetchPage(href);
157
+ }
158
+ },
159
+ [href, onMouseEnter],
160
+ );
161
+ // Handle touch start for prefetch on touch
162
+ const handleTouchStart = useCallback(
163
+ (e) => {
164
+ if (onTouchStart) {
165
+ onTouchStart(e);
166
+ }
167
+ if (isLocalUrl(href)) {
168
+ prefetchPage(href);
169
+ }
170
+ },
171
+ [href, onTouchStart],
172
+ );
173
+ // Handle click
174
+ const handleClick = useCallback(
175
+ (e) => {
176
+ handleLinkClick(e, href, replace, onClick);
177
+ },
178
+ [href, replace, onClick],
179
+ );
180
+ return _jsx("a", {
181
+ ref: linkRef,
182
+ href: href,
183
+ onClick: handleClick,
184
+ onMouseEnter: handleMouseEnter,
185
+ onTouchStart: handleTouchStart,
186
+ ...props,
187
+ children: children,
188
+ });
189
+ }
190
+ export default Link;