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,92 @@
|
|
|
1
|
+
const SESSION_TIMEOUT = parseInt(process.env.SESSION_TIMEOUT ?? "86400000", 10); // 24 hours default
|
|
2
|
+
/**
|
|
3
|
+
* In-memory session manager
|
|
4
|
+
* WARNING: Sessions are lost on server restart
|
|
5
|
+
* For production, use persistent storage (Redis, Database, etc.)
|
|
6
|
+
*/
|
|
7
|
+
export class SessionManager {
|
|
8
|
+
sessions = new Map();
|
|
9
|
+
constructor() {
|
|
10
|
+
// Cleanup expired sessions every 30 minutes
|
|
11
|
+
setInterval(() => this.cleanupExpiredSessions(), 30 * 60 * 1000);
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Create a new session with automatic expiration
|
|
15
|
+
*/
|
|
16
|
+
createSession(userId, data = {}) {
|
|
17
|
+
// Validate userId
|
|
18
|
+
if (!userId || typeof userId !== "string" || userId.length > 255) {
|
|
19
|
+
throw new Error("Invalid userId");
|
|
20
|
+
}
|
|
21
|
+
const sessionId = this.generateSecureSessionId();
|
|
22
|
+
const now = Date.now();
|
|
23
|
+
const session = {
|
|
24
|
+
userId,
|
|
25
|
+
createdAt: now,
|
|
26
|
+
expiresAt: now + SESSION_TIMEOUT,
|
|
27
|
+
...data,
|
|
28
|
+
};
|
|
29
|
+
this.sessions.set(sessionId, session);
|
|
30
|
+
return sessionId;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Get session with expiration check
|
|
34
|
+
*/
|
|
35
|
+
getSession(sessionId) {
|
|
36
|
+
if (!sessionId) return null;
|
|
37
|
+
const session = this.sessions.get(sessionId);
|
|
38
|
+
if (!session) return null;
|
|
39
|
+
// Check if session expired
|
|
40
|
+
if (Date.now() > session.expiresAt) {
|
|
41
|
+
this.sessions.delete(sessionId);
|
|
42
|
+
return null;
|
|
43
|
+
}
|
|
44
|
+
return session;
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Destroy session immediately
|
|
48
|
+
*/
|
|
49
|
+
destroySession(sessionId) {
|
|
50
|
+
this.sessions.delete(sessionId);
|
|
51
|
+
}
|
|
52
|
+
/**
|
|
53
|
+
* Verify session is valid and return user ID
|
|
54
|
+
*/
|
|
55
|
+
verifySession(sessionId) {
|
|
56
|
+
const session = this.getSession(sessionId);
|
|
57
|
+
return session?.userId ?? null;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Update session expiration
|
|
61
|
+
*/
|
|
62
|
+
refreshSession(sessionId) {
|
|
63
|
+
const session = this.getSession(sessionId);
|
|
64
|
+
if (!session) return false;
|
|
65
|
+
session.expiresAt = Date.now() + SESSION_TIMEOUT;
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Generate cryptographically secure session ID
|
|
70
|
+
*/
|
|
71
|
+
generateSecureSessionId() {
|
|
72
|
+
// In production, use crypto.randomBytes
|
|
73
|
+
const chars =
|
|
74
|
+
"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
|
|
75
|
+
let result = "";
|
|
76
|
+
for (let i = 0; i < 32; i++) {
|
|
77
|
+
result += chars.charAt(Math.floor(Math.random() * chars.length));
|
|
78
|
+
}
|
|
79
|
+
return result;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Clean up expired sessions
|
|
83
|
+
*/
|
|
84
|
+
cleanupExpiredSessions() {
|
|
85
|
+
const now = Date.now();
|
|
86
|
+
for (const [sessionId, session] of this.sessions.entries()) {
|
|
87
|
+
if (now > session.expiresAt) {
|
|
88
|
+
this.sessions.delete(sessionId);
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
export declare class AssetHasher {
|
|
2
|
+
/**
|
|
3
|
+
* Calculate hash of file content
|
|
4
|
+
*/
|
|
5
|
+
static hashContent(content: string | Buffer): string;
|
|
6
|
+
/**
|
|
7
|
+
* Rename file to include hash (e.g. style.css -> style.a1b2c3.css)
|
|
8
|
+
*/
|
|
9
|
+
static hashFile(filePath: string): string;
|
|
10
|
+
}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import { readFileSync, renameSync } from "node:fs";
|
|
3
|
+
import { join, dirname, basename, extname } from "node:path";
|
|
4
|
+
export class AssetHasher {
|
|
5
|
+
/**
|
|
6
|
+
* Calculate hash of file content
|
|
7
|
+
*/
|
|
8
|
+
static hashContent(content) {
|
|
9
|
+
return createHash("md5").update(content).digest("hex").slice(0, 10);
|
|
10
|
+
}
|
|
11
|
+
/**
|
|
12
|
+
* Rename file to include hash (e.g. style.css -> style.a1b2c3.css)
|
|
13
|
+
*/
|
|
14
|
+
static hashFile(filePath) {
|
|
15
|
+
const content = readFileSync(filePath);
|
|
16
|
+
const hash = this.hashContent(content);
|
|
17
|
+
const dir = dirname(filePath);
|
|
18
|
+
const ext = extname(filePath);
|
|
19
|
+
const name = basename(filePath, ext);
|
|
20
|
+
const newName = `${name}.${hash}${ext}`;
|
|
21
|
+
const newPath = join(dir, newName);
|
|
22
|
+
renameSync(filePath, newPath);
|
|
23
|
+
return newName;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
export interface Manifest {
|
|
2
|
+
[key: string]: string;
|
|
3
|
+
}
|
|
4
|
+
export declare class AssetManifest {
|
|
5
|
+
private manifest;
|
|
6
|
+
private manifestPath;
|
|
7
|
+
constructor(distDir: string);
|
|
8
|
+
set(original: string, hashed: string): void;
|
|
9
|
+
get(original: string): string | undefined;
|
|
10
|
+
save(): void;
|
|
11
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { writeFileSync, readFileSync, existsSync } from "node:fs";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
export class AssetManifest {
|
|
4
|
+
manifest = {};
|
|
5
|
+
manifestPath;
|
|
6
|
+
constructor(distDir) {
|
|
7
|
+
this.manifestPath = join(distDir, "manifest.json");
|
|
8
|
+
if (existsSync(this.manifestPath)) {
|
|
9
|
+
this.manifest = JSON.parse(readFileSync(this.manifestPath, "utf8"));
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
set(original, hashed) {
|
|
13
|
+
this.manifest[original] = hashed;
|
|
14
|
+
}
|
|
15
|
+
get(original) {
|
|
16
|
+
return this.manifest[original];
|
|
17
|
+
}
|
|
18
|
+
save() {
|
|
19
|
+
writeFileSync(this.manifestPath, JSON.stringify(this.manifest, null, 2));
|
|
20
|
+
}
|
|
21
|
+
}
|
|
@@ -20,5 +20,5 @@ import type { FrameworkConfig } from "../core/config.js";
|
|
|
20
20
|
* @throws Logs warnings for missing assets or component bundling failures but does not stop the build.
|
|
21
21
|
*/
|
|
22
22
|
export declare function buildSite(opts: {
|
|
23
|
-
|
|
23
|
+
config: FrameworkConfig;
|
|
24
24
|
}): Promise<void>;
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mkdirSync,
|
|
3
|
+
rmSync,
|
|
4
|
+
writeFileSync,
|
|
5
|
+
existsSync,
|
|
6
|
+
copyFileSync,
|
|
7
|
+
readdirSync,
|
|
8
|
+
statSync,
|
|
9
|
+
} from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import esbuild from "esbuild";
|
|
12
|
+
import { createScssCompiler } from "../css/compiler.js";
|
|
13
|
+
import {
|
|
14
|
+
vueEsbuildPlugin,
|
|
15
|
+
svelteEsbuildPlugin,
|
|
16
|
+
} from "../compilers/esbuild-plugins.js";
|
|
17
|
+
import { scanRoutes } from "../core/routes/scan.js";
|
|
18
|
+
import { resolveDistPath } from "../core/paths.js";
|
|
19
|
+
import { log } from "../shared/log.js";
|
|
20
|
+
import { renderRouteToHtml } from "../runtime/render.js";
|
|
21
|
+
/**
|
|
22
|
+
* Recursively copies a directory and all its contents.
|
|
23
|
+
* Used to copy static assets from the source directory to the build output.
|
|
24
|
+
* Creates the destination directory structure as needed.
|
|
25
|
+
*
|
|
26
|
+
* @param src The source directory path.
|
|
27
|
+
* @param dst The destination directory path.
|
|
28
|
+
*/
|
|
29
|
+
function copyDir(src, dst) {
|
|
30
|
+
if (!existsSync(src)) return;
|
|
31
|
+
mkdirSync(dst, { recursive: true });
|
|
32
|
+
for (const name of readdirSync(src)) {
|
|
33
|
+
const sp = join(src, name);
|
|
34
|
+
const dp = join(dst, name);
|
|
35
|
+
const st = statSync(sp);
|
|
36
|
+
if (st.isDirectory()) copyDir(sp, dp);
|
|
37
|
+
else copyFileSync(sp, dp);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* Builds a static site by pre-rendering all routes to HTML files.
|
|
42
|
+
* This is the core static site generation (SSG) function that runs at build time.
|
|
43
|
+
* It performs the following steps:
|
|
44
|
+
* 1. Clears the previous build output directory
|
|
45
|
+
* 2. Discovers all route files in the configured site directory
|
|
46
|
+
* 3. Renders each route to a static HTML file
|
|
47
|
+
* 4. Copies static assets from the source directory
|
|
48
|
+
* 5. Bundles Vue and Svelte components for client-side rehydration
|
|
49
|
+
* 6. Compiles SCSS to CSS for the global stylesheet
|
|
50
|
+
*
|
|
51
|
+
* Routes are rendered with empty req/res objects (SSG mode) to avoid middleware execution.
|
|
52
|
+
* This produces pure static HTML that can be served by any web server.
|
|
53
|
+
* Hydration scripts are still injected if the route has hydrate:true, allowing for
|
|
54
|
+
* optional client-side interactivity in otherwise static pages.
|
|
55
|
+
*
|
|
56
|
+
* @param opts Configuration object.
|
|
57
|
+
* @param opts.config The Jen.js framework configuration.
|
|
58
|
+
* @throws Logs warnings for missing assets or component bundling failures but does not stop the build.
|
|
59
|
+
*/
|
|
60
|
+
export async function buildSite(opts) {
|
|
61
|
+
const { config } = opts;
|
|
62
|
+
// Clear and recreate the dist directory for a clean build.
|
|
63
|
+
const dist = resolveDistPath(config);
|
|
64
|
+
rmSync(dist, { recursive: true, force: true });
|
|
65
|
+
mkdirSync(dist, { recursive: true });
|
|
66
|
+
// Discover all routes and pre-render each to a static HTML file.
|
|
67
|
+
const routes = scanRoutes(config);
|
|
68
|
+
log.info(`Building SSG: ${routes.length} routes`);
|
|
69
|
+
for (const r of routes) {
|
|
70
|
+
// Create a synthetic URL for each route. Used as the request URL during rendering.
|
|
71
|
+
const url = new URL("http://localhost" + r.urlPath);
|
|
72
|
+
// Render the route to HTML. Empty req/res indicates SSG mode (no middleware execution).
|
|
73
|
+
const html = await renderRouteToHtml({
|
|
74
|
+
config,
|
|
75
|
+
route: r,
|
|
76
|
+
req: {},
|
|
77
|
+
res: {},
|
|
78
|
+
url,
|
|
79
|
+
params: {},
|
|
80
|
+
query: {},
|
|
81
|
+
headers: {},
|
|
82
|
+
cookies: {},
|
|
83
|
+
});
|
|
84
|
+
// Calculate output path. Root route goes to index.html, nested routes get their own directories.
|
|
85
|
+
const outPath =
|
|
86
|
+
r.urlPath === "/"
|
|
87
|
+
? join(dist, "index.html")
|
|
88
|
+
: join(dist, r.urlPath.slice(1), "index.html");
|
|
89
|
+
mkdirSync(join(outPath, ".."), { recursive: true });
|
|
90
|
+
writeFileSync(outPath, html, "utf8");
|
|
91
|
+
log.info(`SSG: ${r.urlPath} -> ${outPath}`);
|
|
92
|
+
}
|
|
93
|
+
// Copy static assets from the source assets directory to the built site.
|
|
94
|
+
copyDir(join(process.cwd(), config.siteDir, "assets"), join(dist, "assets"));
|
|
95
|
+
// Bundle Vue and Svelte components found in the site directory.
|
|
96
|
+
// These are transpiled to JavaScript modules for client-side use in interactive pages.
|
|
97
|
+
const siteSourceDir = join(process.cwd(), config.siteDir);
|
|
98
|
+
const vueFiles = readdirSync(siteSourceDir, { recursive: true }).filter(
|
|
99
|
+
(f) => String(f).endsWith(".vue") || String(f).endsWith(".svelte"),
|
|
100
|
+
);
|
|
101
|
+
if (vueFiles.length > 0) {
|
|
102
|
+
log.info(`Found ${vueFiles.length} Vue/Svelte components, bundling...`);
|
|
103
|
+
try {
|
|
104
|
+
await esbuild.build({
|
|
105
|
+
entryPoints: vueFiles.map((f) => join(siteSourceDir, String(f))),
|
|
106
|
+
outdir: join(dist, "components"),
|
|
107
|
+
format: "esm",
|
|
108
|
+
target: "es2022",
|
|
109
|
+
bundle: false,
|
|
110
|
+
plugins: [vueEsbuildPlugin(), svelteEsbuildPlugin()],
|
|
111
|
+
external: ["preact", "vue", "svelte"],
|
|
112
|
+
logLevel: "info",
|
|
113
|
+
});
|
|
114
|
+
log.info("Vue/Svelte components bundled successfully.");
|
|
115
|
+
} catch (err) {
|
|
116
|
+
log.warn(`Failed to bundle Vue/Svelte components: ${err.message}`);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
// Compile the global SCSS file to CSS.
|
|
120
|
+
// This stylesheet is injected into every page and contains framework-wide styles.
|
|
121
|
+
// Minification is enabled for production builds.
|
|
122
|
+
const scssPath = join(process.cwd(), config.css.globalScss);
|
|
123
|
+
if (existsSync(scssPath)) {
|
|
124
|
+
const compiler = createScssCompiler();
|
|
125
|
+
const result = compiler.compile({
|
|
126
|
+
inputPath: scssPath,
|
|
127
|
+
minified: true,
|
|
128
|
+
});
|
|
129
|
+
if (result.error) {
|
|
130
|
+
log.error(`SCSS Compilation Failed: ${result.error}`);
|
|
131
|
+
writeFileSync(join(dist, "styles.css"), "/* SCSS Compilation Failed */");
|
|
132
|
+
} else {
|
|
133
|
+
writeFileSync(join(dist, "styles.css"), result.css);
|
|
134
|
+
log.info(`Compiled global SCSS: ${config.css.globalScss}`);
|
|
135
|
+
}
|
|
136
|
+
} else {
|
|
137
|
+
log.warn(`Global SCSS file not found: ${scssPath}`);
|
|
138
|
+
writeFileSync(join(dist, "styles.css"), "/* No global SCSS found */");
|
|
139
|
+
}
|
|
140
|
+
log.info("Build complete.");
|
|
141
|
+
}
|
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
export interface Island {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
2
|
+
id: string;
|
|
3
|
+
component: string;
|
|
4
|
+
props: any;
|
|
5
5
|
}
|
|
6
6
|
export interface IslandRegistry {
|
|
7
|
-
|
|
7
|
+
islands: Island[];
|
|
8
8
|
}
|
|
9
9
|
/**
|
|
10
10
|
* Creates an empty island registry for a request
|
|
@@ -22,4 +22,7 @@ export declare function extractIslandsFromHtml(html: string): Island[];
|
|
|
22
22
|
/**
|
|
23
23
|
* Inject hydration script into HTML
|
|
24
24
|
*/
|
|
25
|
-
export declare function injectIslandScript(
|
|
25
|
+
export declare function injectIslandScript(
|
|
26
|
+
html: string,
|
|
27
|
+
islands: Island[],
|
|
28
|
+
): string;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates an empty island registry for a request
|
|
3
|
+
*/
|
|
4
|
+
export function createIslandRegistry() {
|
|
5
|
+
return { islands: [] };
|
|
6
|
+
}
|
|
7
|
+
/**
|
|
8
|
+
* Mark a component as an island (placeholder implementation)
|
|
9
|
+
* In a real framework, this would be a decorator or a HOC
|
|
10
|
+
*/
|
|
11
|
+
export function markIsland(name, props) {
|
|
12
|
+
const id = `island-${Math.random().toString(36).slice(2, 9)}`;
|
|
13
|
+
return `<div data-island="${name}" data-props='${JSON.stringify(props)}' id="${id}"></div>`;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* Extract islands from HTML string
|
|
17
|
+
*/
|
|
18
|
+
export function extractIslandsFromHtml(html) {
|
|
19
|
+
const islands = [];
|
|
20
|
+
const regex = /data-island="([^"]+)" data-props='([^']+)' id="([^"]+)"/g;
|
|
21
|
+
let match;
|
|
22
|
+
while ((match = regex.exec(html)) !== null) {
|
|
23
|
+
islands.push({
|
|
24
|
+
component: match[1],
|
|
25
|
+
props: JSON.parse(match[2]),
|
|
26
|
+
id: match[3],
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return islands;
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Inject hydration script into HTML
|
|
33
|
+
*/
|
|
34
|
+
export function injectIslandScript(html, islands) {
|
|
35
|
+
if (islands.length === 0) return html;
|
|
36
|
+
const script = `
|
|
37
|
+
<script type="module">
|
|
38
|
+
import { hydrate } from '/__runtime/hydrate.js';
|
|
39
|
+
const islands = ${JSON.stringify(islands)};
|
|
40
|
+
islands.forEach(i => hydrate(i.component, i.id, i.props));
|
|
41
|
+
</script>
|
|
42
|
+
`;
|
|
43
|
+
return html.replace("</body>", `${script}</body>`);
|
|
44
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
export interface MinifyOptions {
|
|
2
|
+
minifyIdentifiers?: boolean;
|
|
3
|
+
minifySyntax?: boolean;
|
|
4
|
+
minifyWhitespace?: boolean;
|
|
5
|
+
target?: string | string[];
|
|
6
|
+
}
|
|
7
|
+
export declare class Minifier {
|
|
8
|
+
/**
|
|
9
|
+
* Minify JavaScript/TypeScript using esbuild
|
|
10
|
+
*/
|
|
11
|
+
static minifyJs(code: string, options?: MinifyOptions): Promise<string>;
|
|
12
|
+
/**
|
|
13
|
+
* Minify CSS using esbuild
|
|
14
|
+
*/
|
|
15
|
+
static minifyCss(code: string): Promise<string>;
|
|
16
|
+
/**
|
|
17
|
+
* Minify HTML (basic regex/string-based, as esbuild doesn't handle HTML)
|
|
18
|
+
*/
|
|
19
|
+
static minifyHtml(html: string): string;
|
|
20
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
import * as esbuild from "esbuild";
|
|
2
|
+
import { log } from "../shared/log.js";
|
|
3
|
+
export class Minifier {
|
|
4
|
+
/**
|
|
5
|
+
* Minify JavaScript/TypeScript using esbuild
|
|
6
|
+
*/
|
|
7
|
+
static async minifyJs(code, options = {}) {
|
|
8
|
+
try {
|
|
9
|
+
const result = await esbuild.transform(code, {
|
|
10
|
+
loader: "js",
|
|
11
|
+
minify: true,
|
|
12
|
+
legalComments: "none",
|
|
13
|
+
...options,
|
|
14
|
+
});
|
|
15
|
+
return result.code;
|
|
16
|
+
} catch (err) {
|
|
17
|
+
log.error("Minification failed (JS)");
|
|
18
|
+
throw err;
|
|
19
|
+
}
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Minify CSS using esbuild
|
|
23
|
+
*/
|
|
24
|
+
static async minifyCss(code) {
|
|
25
|
+
try {
|
|
26
|
+
const result = await esbuild.transform(code, {
|
|
27
|
+
loader: "css",
|
|
28
|
+
minify: true,
|
|
29
|
+
});
|
|
30
|
+
return result.code;
|
|
31
|
+
} catch (err) {
|
|
32
|
+
log.error("Minification failed (CSS)");
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
/**
|
|
37
|
+
* Minify HTML (basic regex/string-based, as esbuild doesn't handle HTML)
|
|
38
|
+
*/
|
|
39
|
+
static minifyHtml(html) {
|
|
40
|
+
return html
|
|
41
|
+
.replace(/<!--[\s\S]*?-->/g, "") // Remove comments
|
|
42
|
+
.replace(/>\s+</g, "><") // Remove whitespace between tags
|
|
43
|
+
.replace(/\s{2,}/g, " ") // Collapse multiple whitespaces
|
|
44
|
+
.trim();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
import { FrameworkConfig } from "../core/config.js";
|
|
2
|
+
import { RouteEntry } from "../core/routes/scan.js";
|
|
3
|
+
export interface PageRenderContext {
|
|
4
|
+
config: FrameworkConfig;
|
|
5
|
+
route: RouteEntry;
|
|
6
|
+
url: URL;
|
|
7
|
+
params: Record<string, string>;
|
|
8
|
+
query: Record<string, string>;
|
|
9
|
+
headers: Record<string, string>;
|
|
10
|
+
cookies: Record<string, string>;
|
|
11
|
+
}
|
|
12
|
+
export declare class PageRenderer {
|
|
13
|
+
/**
|
|
14
|
+
* Render a route to a full HTML string, including minification if requested
|
|
15
|
+
*/
|
|
16
|
+
static render(ctx: PageRenderContext, minify?: boolean): Promise<string>;
|
|
17
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { renderRouteToHtml } from "../runtime/render.js";
|
|
2
|
+
import { Minifier } from "./minifier.js";
|
|
3
|
+
export class PageRenderer {
|
|
4
|
+
/**
|
|
5
|
+
* Render a route to a full HTML string, including minification if requested
|
|
6
|
+
*/
|
|
7
|
+
static async render(ctx, minify = false) {
|
|
8
|
+
// 1. Core Preact render
|
|
9
|
+
let html = await renderRouteToHtml({
|
|
10
|
+
config: ctx.config,
|
|
11
|
+
route: ctx.route,
|
|
12
|
+
req: {},
|
|
13
|
+
res: {},
|
|
14
|
+
url: ctx.url,
|
|
15
|
+
params: ctx.params,
|
|
16
|
+
query: ctx.query,
|
|
17
|
+
headers: ctx.headers,
|
|
18
|
+
cookies: ctx.cookies,
|
|
19
|
+
});
|
|
20
|
+
// 2. Post-processing (Layout injection, hydration script injection)
|
|
21
|
+
// Note: Hydration logic is handled by island-hydration.ts usually
|
|
22
|
+
// 3. Optional Minification
|
|
23
|
+
if (minify) {
|
|
24
|
+
html = Minifier.minifyHtml(html);
|
|
25
|
+
}
|
|
26
|
+
return html;
|
|
27
|
+
}
|
|
28
|
+
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { FrameworkConfig } from "../core/config.js";
|
|
2
|
+
export interface ProductionBuildConfig {
|
|
3
|
+
config: FrameworkConfig;
|
|
4
|
+
}
|
|
5
|
+
export declare class ProductionBuilder {
|
|
6
|
+
/**
|
|
7
|
+
* Run the production build sequence
|
|
8
|
+
*/
|
|
9
|
+
static build(opts: ProductionBuildConfig): Promise<void>;
|
|
10
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { SSGPipeline } from "./ssg-pipeline.js";
|
|
2
|
+
import { log } from "../shared/log.js";
|
|
3
|
+
export class ProductionBuilder {
|
|
4
|
+
/**
|
|
5
|
+
* Run the production build sequence
|
|
6
|
+
*/
|
|
7
|
+
static async build(opts) {
|
|
8
|
+
log.info("--- PRODUCTION BUILD START ---");
|
|
9
|
+
const pipeline = new SSGPipeline(opts.config);
|
|
10
|
+
await pipeline.run();
|
|
11
|
+
log.info("--- PRODUCTION BUILD COMPLETE ---");
|
|
12
|
+
}
|
|
13
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import { FrameworkConfig } from "../core/config.js";
|
|
2
|
+
export declare class SSGPipeline {
|
|
3
|
+
private config;
|
|
4
|
+
private dist;
|
|
5
|
+
constructor(config: FrameworkConfig);
|
|
6
|
+
/**
|
|
7
|
+
* Run the full SSG Pipeline
|
|
8
|
+
*/
|
|
9
|
+
run(): Promise<void>;
|
|
10
|
+
private prepareDist;
|
|
11
|
+
private processAssets;
|
|
12
|
+
private compileStyles;
|
|
13
|
+
private renderPages;
|
|
14
|
+
private copyRecursive;
|
|
15
|
+
}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import {
|
|
2
|
+
mkdirSync,
|
|
3
|
+
rmSync,
|
|
4
|
+
writeFileSync,
|
|
5
|
+
existsSync,
|
|
6
|
+
copyFileSync,
|
|
7
|
+
readdirSync,
|
|
8
|
+
statSync,
|
|
9
|
+
} from "node:fs";
|
|
10
|
+
import { join } from "node:path";
|
|
11
|
+
import { scanRoutes } from "../core/routes/scan.js";
|
|
12
|
+
import { resolveDistPath } from "../core/paths.js";
|
|
13
|
+
import { log } from "../shared/log.js";
|
|
14
|
+
import { PageRenderer } from "./page-renderer.js";
|
|
15
|
+
import { AssetHasher } from "./asset-hashing.js";
|
|
16
|
+
import { createScssCompiler } from "../css/compiler.js";
|
|
17
|
+
export class SSGPipeline {
|
|
18
|
+
config;
|
|
19
|
+
dist;
|
|
20
|
+
constructor(config) {
|
|
21
|
+
this.config = config;
|
|
22
|
+
this.dist = resolveDistPath(config);
|
|
23
|
+
}
|
|
24
|
+
/**
|
|
25
|
+
* Run the full SSG Pipeline
|
|
26
|
+
*/
|
|
27
|
+
async run() {
|
|
28
|
+
log.info("Starting SSG Pipeline (Enterprise Build)");
|
|
29
|
+
// 1. Prepare dist
|
|
30
|
+
this.prepareDist();
|
|
31
|
+
// 2. Process Assets
|
|
32
|
+
await this.processAssets();
|
|
33
|
+
// 3. Compile Styles
|
|
34
|
+
const cssPath = await this.compileStyles();
|
|
35
|
+
// 4. Render Pages
|
|
36
|
+
await this.renderPages();
|
|
37
|
+
log.info("Pipeline complete.");
|
|
38
|
+
}
|
|
39
|
+
prepareDist() {
|
|
40
|
+
rmSync(this.dist, { recursive: true, force: true });
|
|
41
|
+
mkdirSync(this.dist, { recursive: true });
|
|
42
|
+
}
|
|
43
|
+
async processAssets() {
|
|
44
|
+
const assetDir = join(process.cwd(), this.config.siteDir, "assets");
|
|
45
|
+
const targetDir = join(this.dist, "assets");
|
|
46
|
+
if (existsSync(assetDir)) {
|
|
47
|
+
this.copyRecursive(assetDir, targetDir);
|
|
48
|
+
log.info("Assets copied to dist");
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
async compileStyles() {
|
|
52
|
+
const scssPath = join(process.cwd(), this.config.css.globalScss);
|
|
53
|
+
if (!existsSync(scssPath)) return null;
|
|
54
|
+
const compiler = createScssCompiler();
|
|
55
|
+
const result = compiler.compile({
|
|
56
|
+
inputPath: scssPath,
|
|
57
|
+
minified: true,
|
|
58
|
+
});
|
|
59
|
+
if (result.error) {
|
|
60
|
+
log.error(`SCSS Failed: ${result.error}`);
|
|
61
|
+
return null;
|
|
62
|
+
}
|
|
63
|
+
const cssFile = join(this.dist, "styles.css");
|
|
64
|
+
writeFileSync(cssFile, result.css);
|
|
65
|
+
// Hash the CSS
|
|
66
|
+
const hashedName = AssetHasher.hashFile(cssFile);
|
|
67
|
+
log.info(`Styles compiled and hashed: ${hashedName}`);
|
|
68
|
+
return hashedName;
|
|
69
|
+
}
|
|
70
|
+
async renderPages() {
|
|
71
|
+
const routes = scanRoutes(this.config);
|
|
72
|
+
for (const r of routes) {
|
|
73
|
+
try {
|
|
74
|
+
const url = new URL("http://localhost" + r.urlPath);
|
|
75
|
+
const html = await PageRenderer.render(
|
|
76
|
+
{
|
|
77
|
+
config: this.config,
|
|
78
|
+
route: r,
|
|
79
|
+
url,
|
|
80
|
+
params: {},
|
|
81
|
+
query: {},
|
|
82
|
+
headers: {},
|
|
83
|
+
cookies: {},
|
|
84
|
+
},
|
|
85
|
+
true,
|
|
86
|
+
);
|
|
87
|
+
const outDir = join(
|
|
88
|
+
this.dist,
|
|
89
|
+
r.urlPath === "/" ? "" : r.urlPath.slice(1),
|
|
90
|
+
);
|
|
91
|
+
mkdirSync(outDir, { recursive: true });
|
|
92
|
+
writeFileSync(join(outDir, "index.html"), html);
|
|
93
|
+
log.info(`Rendered ${r.urlPath}`);
|
|
94
|
+
} catch (err) {
|
|
95
|
+
const errorMsg = err instanceof Error ? err.message : String(err);
|
|
96
|
+
log.error(`Failed to render ${r.urlPath}: ${errorMsg}`);
|
|
97
|
+
throw err;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
}
|
|
101
|
+
copyRecursive(src, dst) {
|
|
102
|
+
mkdirSync(dst, { recursive: true });
|
|
103
|
+
for (const name of readdirSync(src)) {
|
|
104
|
+
const sp = join(src, name);
|
|
105
|
+
const dp = join(dst, name);
|
|
106
|
+
if (statSync(sp).isDirectory()) {
|
|
107
|
+
this.copyRecursive(sp, dp);
|
|
108
|
+
} else {
|
|
109
|
+
copyFileSync(sp, dp);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|