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.
- package/dist/colors.js +0 -17
- package/dist/create.js +5 -17
- package/dist/generator.js +14 -31
- package/dist/index.js +6 -1
- package/package.json +1 -1
- package/templates/ssr-isr/README.md +77 -0
- package/templates/ssr-isr/build.js +118 -0
- package/templates/ssr-isr/jen.config.ts +109 -0
- package/templates/ssr-isr/jenjs.d.ts +22 -0
- package/templates/ssr-isr/lib/api/(hello).js +9 -0
- package/templates/ssr-isr/lib/auth/cookie-utils.js +79 -0
- package/templates/ssr-isr/lib/auth/index.js +2 -0
- package/templates/ssr-isr/lib/auth/jwt.js +57 -0
- package/templates/ssr-isr/lib/auth/session.js +92 -0
- package/templates/ssr-isr/lib/build/asset-hashing.d.ts +10 -0
- package/templates/ssr-isr/lib/build/asset-hashing.js +25 -0
- package/templates/ssr-isr/lib/build/asset-manifest.d.ts +11 -0
- package/templates/ssr-isr/lib/build/asset-manifest.js +21 -0
- package/templates/{static → ssr-isr}/lib/build/build.d.ts +1 -1
- package/templates/ssr-isr/lib/build/build.js +141 -0
- package/templates/{static → ssr-isr}/lib/build/island-hydration.d.ts +8 -5
- package/templates/ssr-isr/lib/build/island-hydration.js +44 -0
- package/templates/ssr-isr/lib/build/minifier.d.ts +20 -0
- package/templates/ssr-isr/lib/build/minifier.js +46 -0
- package/templates/ssr-isr/lib/build/page-renderer.d.ts +17 -0
- package/templates/ssr-isr/lib/build/page-renderer.js +28 -0
- package/templates/ssr-isr/lib/build/production-build.d.ts +10 -0
- package/templates/ssr-isr/lib/build/production-build.js +13 -0
- package/templates/ssr-isr/lib/build/ssg-pipeline.d.ts +15 -0
- package/templates/ssr-isr/lib/build/ssg-pipeline.js +113 -0
- package/templates/ssr-isr/lib/build-tools/build-site.js +36 -0
- package/templates/ssr-isr/lib/cache/index.js +10 -0
- package/templates/ssr-isr/lib/cache/memory.js +40 -0
- package/templates/ssr-isr/lib/cache/redis.js +61 -0
- package/templates/ssr-isr/lib/cli/banner.js +28 -0
- package/templates/ssr-isr/lib/cli/templates/ssg/jen.config.js +32 -0
- package/templates/ssr-isr/lib/cli/templates/ssg/site/index.js +9 -0
- package/templates/ssr-isr/lib/cli/templates/ssr/jen.config.js +32 -0
- package/templates/ssr-isr/lib/cli/templates/ssr/site/index.js +9 -0
- package/templates/ssr-isr/lib/compilers/esbuild-plugins.js +111 -0
- package/templates/ssr-isr/lib/compilers/svelte.js +44 -0
- package/templates/ssr-isr/lib/compilers/vue.js +90 -0
- package/templates/ssr-isr/lib/core/http.js +71 -0
- package/templates/ssr-isr/lib/core/middleware-hooks.js +97 -0
- package/templates/ssr-isr/lib/core/paths.js +39 -0
- package/templates/ssr-isr/lib/core/routes/match.js +47 -0
- package/templates/ssr-isr/lib/core/routes/scan.js +190 -0
- package/templates/ssr-isr/lib/core/types.js +1 -0
- package/templates/ssr-isr/lib/css/compiler.js +74 -0
- package/templates/ssr-isr/lib/db/connector.js +42 -0
- package/templates/ssr-isr/lib/db/drivers/jdb.js +44 -0
- package/templates/ssr-isr/lib/db/drivers/sql.js +182 -0
- package/templates/ssr-isr/lib/db/index.js +48 -0
- package/templates/ssr-isr/lib/db/types.js +1 -0
- package/templates/ssr-isr/lib/graphql/index.js +52 -0
- package/templates/ssr-isr/lib/graphql/resolvers.js +25 -0
- package/templates/ssr-isr/lib/graphql/schema.js +35 -0
- package/templates/ssr-isr/lib/i18n/en.json +4 -0
- package/templates/ssr-isr/lib/i18n/es.json +4 -0
- package/templates/ssr-isr/lib/i18n/index.js +15 -0
- package/templates/ssr-isr/lib/import/jen-import.js +161 -0
- package/templates/ssr-isr/lib/index.js +116 -0
- package/templates/ssr-isr/lib/jdb/engine.js +275 -0
- package/templates/ssr-isr/lib/jdb/index.js +34 -0
- package/templates/ssr-isr/lib/jdb/types.js +1 -0
- package/templates/ssr-isr/lib/jdb/utils.js +176 -0
- package/templates/{static → ssr-isr}/lib/middleware/builtins/body-parser.js +0 -17
- package/templates/ssr-isr/lib/middleware/builtins/cors.js +54 -0
- package/templates/{static → ssr-isr}/lib/middleware/builtins/logger.js +0 -17
- package/templates/{static → ssr-isr}/lib/middleware/builtins/rate-limit.js +0 -17
- package/templates/{static → ssr-isr}/lib/middleware/builtins/request-id.js +0 -17
- package/templates/{static → ssr-isr}/lib/middleware/builtins/security-headers.js +0 -17
- package/templates/ssr-isr/lib/middleware/context.js +124 -0
- package/templates/{static → ssr-isr}/lib/middleware/decorators.js +0 -17
- package/templates/{static → ssr-isr}/lib/middleware/errors/handler.js +0 -17
- package/templates/ssr-isr/lib/middleware/errors/http-error.js +10 -0
- package/templates/ssr-isr/lib/middleware/kernel.js +85 -0
- package/templates/ssr-isr/lib/middleware/pipeline.js +148 -0
- package/templates/ssr-isr/lib/middleware/registry.js +85 -0
- package/templates/ssr-isr/lib/middleware/response.js +107 -0
- package/templates/ssr-isr/lib/middleware/types.d.ts +1 -0
- package/templates/ssr-isr/lib/middleware/types.js +1 -0
- package/templates/ssr-isr/lib/middleware/utils/matcher.js +13 -0
- package/templates/{static → ssr-isr}/lib/native/bundle.js +0 -17
- package/templates/{static → ssr-isr}/lib/native/dev-server.js +0 -17
- package/templates/{static → ssr-isr}/lib/native/index.js +0 -17
- package/templates/{static → ssr-isr}/lib/native/optimizer.js +0 -17
- package/templates/ssr-isr/lib/native/style-compiler.js +19 -0
- package/templates/ssr-isr/lib/plugin/loader.js +36 -0
- package/templates/ssr-isr/lib/runtime/client-runtime.js +25 -0
- package/templates/ssr-isr/lib/runtime/hmr.js +59 -0
- package/templates/ssr-isr/lib/runtime/hydrate.js +55 -0
- package/templates/ssr-isr/lib/runtime/island-hydration-client.js +146 -0
- package/templates/ssr-isr/lib/runtime/islands.js +110 -0
- package/templates/ssr-isr/lib/runtime/render.js +244 -0
- package/templates/ssr-isr/lib/server/api-routes.js +237 -0
- package/templates/ssr-isr/lib/server/api.js +108 -0
- package/templates/ssr-isr/lib/server/app.js +438 -0
- package/templates/ssr-isr/lib/server/runtimeServe.js +169 -0
- package/templates/ssr-isr/lib/server/ssr.js +202 -0
- package/templates/ssr-isr/lib/shared/log.js +64 -0
- package/templates/ssr-isr/package.json +23 -0
- package/templates/ssr-isr/server.js +128 -0
- package/templates/ssr-isr/site/pages/(index).tsx +11 -0
- package/templates/ssr-isr/site/styles/global.scss +37 -0
- package/templates/ssr-isr/tsconfig.json +39 -0
- package/templates/static/build.js +30 -18
- package/templates/static/jen.config.ts +0 -18
- package/templates/static/jenjs.d.ts +0 -18
- package/templates/static/lib/api/(hello).js +0 -17
- package/templates/static/lib/api/examples/files/[...slug].js +22 -0
- package/templates/static/lib/api/examples/hello.js +11 -0
- package/templates/static/lib/api/examples/posts/[id].js +37 -0
- package/templates/static/lib/api/examples/posts.js +37 -0
- package/templates/static/lib/api/examples/search.js +23 -0
- package/templates/static/lib/api/index.js +41 -0
- package/templates/static/lib/api/loader.js +234 -0
- package/templates/static/lib/api/router.js +259 -0
- package/templates/static/lib/assets/types.js +1 -0
- package/templates/static/lib/auth/cookie-utils.js +3 -16
- package/templates/static/lib/auth/index.js +0 -17
- package/templates/static/lib/auth/jwt.js +0 -17
- package/templates/static/lib/auth/session.js +0 -17
- package/templates/static/lib/build/asset-hashing.js +44 -36
- package/templates/static/lib/build/asset-manifest.js +16 -33
- package/templates/static/lib/build/build.js +270 -125
- package/templates/static/lib/build/bundle-analyzer-ui.js +417 -0
- package/templates/static/lib/build/bundle-analyzer.js +945 -0
- package/templates/static/lib/build/code-splitter.js +194 -0
- package/templates/static/lib/build/feature-analyzer.js +190 -0
- package/templates/static/lib/build/feature-gate.js +257 -0
- package/templates/static/lib/build/island-hydration.js +17 -35
- package/templates/static/lib/build/lazy-loader.js +322 -0
- package/templates/static/lib/build/minifier.js +40 -59
- package/templates/static/lib/build/page-renderer.js +23 -40
- package/templates/static/lib/build/production-build.js +9 -26
- package/templates/static/lib/build/rust-hashing.js +71 -0
- package/templates/static/lib/build/script-optimizer.js +285 -0
- package/templates/static/lib/build/ssg-pipeline.js +100 -106
- package/templates/static/lib/build/vercel-output.js +298 -0
- package/templates/static/lib/build-tools/build-site.js +0 -17
- package/templates/static/lib/cache/index.js +0 -17
- package/templates/static/lib/cache/memory.js +0 -17
- package/templates/static/lib/cache/redis.js +0 -17
- package/templates/static/lib/cli/banner.js +0 -17
- package/templates/static/lib/cli/templates/ssg/jen.config.js +0 -17
- package/templates/static/lib/cli/templates/ssr/jen.config.js +0 -17
- package/templates/static/lib/client/Image.js +42 -0
- package/templates/static/lib/client/Link.js +190 -0
- package/templates/static/lib/client/PWA.js +46 -0
- package/templates/static/lib/client/Seo.js +97 -0
- package/templates/static/lib/client/index.js +9 -0
- package/templates/static/lib/client/useNavigation.js +25 -0
- package/templates/static/lib/client/useRouter.js +64 -0
- package/templates/static/lib/client-routing/Link.js +17 -0
- package/templates/static/lib/client-routing/index.js +19 -0
- package/templates/static/lib/client-routing/router.js +151 -0
- package/templates/static/lib/client-routing/signal.js +147 -0
- package/templates/static/lib/compilers/esbuild-plugins.js +0 -17
- package/templates/static/lib/compilers/svelte.js +0 -17
- package/templates/static/lib/compilers/vue.js +0 -17
- package/templates/static/lib/core/config.js +0 -17
- package/templates/static/lib/core/feature-guard.js +136 -0
- package/templates/static/lib/core/features.js +99 -0
- package/templates/static/lib/core/http.js +0 -17
- package/templates/static/lib/core/layouts/index.js +10 -0
- package/templates/static/lib/core/layouts/render.js +158 -0
- package/templates/static/lib/core/layouts/scan.js +112 -0
- package/templates/static/lib/core/layouts/types.js +1 -0
- package/templates/static/lib/core/lifecycle.js +129 -0
- package/templates/static/lib/core/loader-schema.js +81 -0
- package/templates/static/lib/core/middleware-hooks.js +0 -17
- package/templates/static/lib/core/paths.js +0 -17
- package/templates/static/lib/core/routes/advanced.js +114 -0
- package/templates/static/lib/core/routes/handlers.js +181 -0
- package/templates/static/lib/core/routes/match.js +89 -17
- package/templates/static/lib/core/routes/orchestrator.js +171 -0
- package/templates/static/lib/core/routes/rendering-config.js +131 -0
- package/templates/static/lib/core/routes/scan.js +0 -17
- package/templates/static/lib/core/types.js +0 -17
- package/templates/static/lib/css/compiler.js +1 -18
- package/templates/static/lib/data-fetching/cache.js +223 -0
- package/templates/static/lib/data-fetching/client.js +202 -0
- package/templates/static/lib/data-fetching/feature-guard.js +29 -0
- package/templates/static/lib/data-fetching/graphql.js +265 -0
- package/templates/static/lib/data-fetching/index.js +57 -0
- package/templates/static/lib/data-fetching/rest.js +256 -0
- package/templates/static/lib/data-fetching/server.js +182 -0
- package/templates/static/lib/data-fetching/types.js +5 -0
- package/templates/static/lib/db/connector.js +0 -17
- package/templates/static/lib/db/drivers/jdb.js +0 -17
- package/templates/static/lib/db/drivers/sql.js +0 -17
- package/templates/static/lib/db/index.js +0 -17
- package/templates/static/lib/db/types.js +0 -17
- package/templates/static/lib/devtools/component-tree.js +106 -0
- package/templates/static/lib/devtools/devtools.js +638 -0
- package/templates/static/lib/devtools/event-bus.js +29 -0
- package/templates/static/lib/devtools/event-logger.js +67 -0
- package/templates/static/lib/devtools/index.js +9 -0
- package/templates/static/lib/devtools/integration.js +149 -0
- package/templates/static/lib/devtools/performance.js +84 -0
- package/templates/static/lib/devtools/persistence.js +57 -0
- package/templates/static/lib/devtools/plugins.js +97 -0
- package/templates/static/lib/devtools/search.js +89 -0
- package/templates/static/lib/devtools/ui.js +769 -0
- package/templates/static/lib/features/api/handler.js +10 -0
- package/templates/static/lib/features/api/index.js +5 -0
- package/templates/static/lib/features/api/types.js +4 -0
- package/templates/static/lib/features/middleware/compiled.js +7 -0
- package/templates/static/lib/features/middleware/index.js +5 -0
- package/templates/static/lib/features/middleware/types.js +4 -0
- package/templates/static/lib/fonts/index.js +46 -0
- package/templates/static/lib/fonts/inject.js +125 -0
- package/templates/static/lib/fonts/loader.js +196 -0
- package/templates/static/lib/fonts/types.js +1 -0
- package/templates/static/lib/graphql/index.js +1 -18
- package/templates/static/lib/graphql/resolvers.js +20 -13
- package/templates/static/lib/graphql/schema.js +0 -17
- package/templates/static/lib/i18n/index.js +7 -19
- package/templates/static/lib/import/jen-import.js +1 -18
- package/templates/static/lib/index.js +79 -125
- package/templates/static/lib/jdb/engine.js +0 -17
- package/templates/static/lib/jdb/index.js +1 -18
- package/templates/static/lib/jdb/types.js +0 -17
- package/templates/static/lib/jdb/utils.js +0 -17
- package/templates/static/lib/middleware/builtins/cors.js +3 -16
- package/templates/static/lib/middleware/context.js +0 -17
- package/templates/static/lib/middleware/kernel.js +117 -25
- package/templates/static/lib/middleware/pipeline.js +0 -17
- package/templates/static/lib/middleware/registry.js +0 -17
- package/templates/static/lib/middleware/response.js +0 -17
- package/templates/static/lib/plugin/examples/analytics-plugin.js +183 -0
- package/templates/static/lib/plugin/examples/cdn-upload-plugin.js +94 -0
- package/templates/static/lib/plugin/loader.js +0 -17
- package/templates/static/lib/plugin/plugin-manager.js +177 -0
- package/templates/static/lib/plugin/types.js +28 -0
- package/templates/static/lib/runtime/client-runtime.js +0 -17
- package/templates/static/lib/runtime/hmr.js +0 -17
- package/templates/static/lib/runtime/hydrate.js +0 -17
- package/templates/static/lib/runtime/island-hydration-client.js +0 -17
- package/templates/static/lib/runtime/islands.js +0 -17
- package/templates/static/lib/runtime/render.js +208 -50
- package/templates/static/lib/security/security-config.js +60 -0
- package/templates/static/lib/security/security-middleware.js +229 -0
- package/templates/static/lib/server/api-routes.js +153 -43
- package/templates/static/lib/server/api.js +0 -17
- package/templates/static/lib/server/app.js +539 -223
- package/templates/static/lib/server/isr.js +365 -0
- package/templates/static/lib/server/runtimeServe.js +31 -24
- package/templates/static/lib/server/ssr.js +98 -22
- package/templates/static/lib/server-actions/handler.js +180 -0
- package/templates/static/lib/server-actions/index.js +19 -0
- package/templates/static/lib/server-actions/middleware.js +146 -0
- package/templates/static/lib/server-actions/scan.js +152 -0
- package/templates/static/lib/server-actions/types.js +1 -0
- package/templates/static/lib/server-actions/validators.js +156 -0
- package/templates/static/lib/shared/log.js +19 -20
- package/templates/static/lib/telemetry/api/rate-limiter.js +32 -0
- package/templates/static/lib/telemetry/api/validator.js +67 -0
- package/templates/static/lib/telemetry/client.js +121 -0
- package/templates/static/lib/telemetry/tests/rate-limiter.test.js +46 -0
- package/templates/static/lib/telemetry/tests/validator.test.js +62 -0
- package/templates/static/lib/vendor/glob/glob.js +4766 -0
- package/templates/static/lib/vendor/preact/LICENSE +21 -0
- package/templates/static/lib/vendor/preact/preact.module.js +797 -0
- package/templates/static/lib/vendor/sass/sass.node.mjs +212 -0
- package/templates/static/package.json +4 -0
- package/templates/static/server.js +22 -22
- package/templates/static/site/(home).tsx +0 -18
- package/templates/static/tsconfig.json +5 -1
- package/templates/static/.esbuild/jen.config.js +0 -19
- package/templates/static/lib/build/asset-hashing.d.ts +0 -10
- package/templates/static/lib/build/asset-manifest.d.ts +0 -11
- package/templates/static/lib/build/minifier.d.ts +0 -20
- package/templates/static/lib/build/page-renderer.d.ts +0 -17
- package/templates/static/lib/build/production-build.d.ts +0 -10
- package/templates/static/lib/build/ssg-pipeline.d.ts +0 -15
- package/templates/static/lib/middleware/errors/http-error.js +0 -27
- package/templates/static/lib/middleware/types.js +0 -18
- package/templates/static/lib/middleware/utils/matcher.js +0 -30
- package/templates/static/lib/native/style-compiler.js +0 -36
- /package/templates/{static → ssr-isr}/lib/api/(hello).d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/auth/cookie-utils.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/auth/index.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/auth/jwt.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/auth/session.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/build-tools/build-site.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/cache/index.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/cache/memory.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/cache/redis.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/cli/banner.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/cli/templates/ssg/jen.config.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/cli/templates/ssg/site/index.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/cli/templates/ssr/jen.config.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/cli/templates/ssr/site/index.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/compilers/esbuild-plugins.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/compilers/svelte.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/compilers/vue.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/core/config.d.ts +0 -0
- /package/templates/{static/lib/middleware/types.d.ts → ssr-isr/lib/core/config.js} +0 -0
- /package/templates/{static → ssr-isr}/lib/core/http.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/core/middleware-hooks.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/core/paths.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/core/routes/match.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/core/routes/scan.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/core/types.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/css/compiler.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/db/connector.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/db/drivers/jdb.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/db/drivers/sql.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/db/index.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/db/types.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/graphql/index.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/graphql/resolvers.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/graphql/schema.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/i18n/index.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/import/jen-import.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/index.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/jdb/engine.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/jdb/index.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/jdb/types.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/jdb/utils.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/builtins/body-parser.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/builtins/cors.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/builtins/logger.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/builtins/rate-limit.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/builtins/request-id.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/builtins/security-headers.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/context.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/decorators.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/errors/handler.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/errors/http-error.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/kernel.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/pipeline.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/registry.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/response.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/middleware/utils/matcher.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/native/bundle.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/native/dev-server.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/native/index.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/native/optimizer.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/native/style-compiler.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/plugin/loader.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/runtime/client-runtime.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/runtime/hmr.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/runtime/hydrate.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/runtime/island-hydration-client.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/runtime/islands.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/runtime/render.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/server/api-routes.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/server/api.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/server/app.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/server/runtimeServe.d.ts +0 -0
- /package/templates/{static → ssr-isr}/lib/server/ssr.d.ts +0 -0
- /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;
|