gorsee 0.2.4 → 0.2.6
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/README.md +283 -212
- package/dist-pkg/ai/artifact-lifecycle.d.ts +25 -0
- package/dist-pkg/ai/artifact-lifecycle.js +98 -0
- package/dist-pkg/ai/bridge.d.ts +26 -0
- package/dist-pkg/ai/bridge.js +82 -0
- package/dist-pkg/ai/bundle.d.ts +46 -0
- package/dist-pkg/ai/bundle.js +247 -0
- package/dist-pkg/ai/contracts.d.ts +1 -0
- package/dist-pkg/ai/contracts.js +1 -0
- package/dist-pkg/ai/ide.d.ts +37 -0
- package/dist-pkg/ai/ide.js +56 -0
- package/dist-pkg/ai/index.d.ts +85 -0
- package/dist-pkg/ai/index.js +267 -0
- package/dist-pkg/ai/json.d.ts +6 -0
- package/dist-pkg/ai/json.js +14 -0
- package/dist-pkg/ai/mcp.d.ts +28 -0
- package/dist-pkg/ai/mcp.js +173 -0
- package/dist-pkg/ai/session-pack.d.ts +28 -0
- package/dist-pkg/ai/session-pack.js +57 -0
- package/dist-pkg/ai/store.d.ts +67 -0
- package/dist-pkg/ai/store.js +174 -0
- package/dist-pkg/ai/summary.d.ts +57 -0
- package/dist-pkg/ai/summary.js +148 -0
- package/dist-pkg/ai/watch.d.ts +15 -0
- package/dist-pkg/ai/watch.js +66 -0
- package/dist-pkg/auth/action-tokens.d.ts +50 -0
- package/dist-pkg/auth/action-tokens.js +79 -0
- package/dist-pkg/auth/index.d.ts +70 -0
- package/dist-pkg/auth/index.js +199 -0
- package/dist-pkg/auth/redis-session-store.d.ts +7 -0
- package/dist-pkg/auth/redis-session-store.js +42 -0
- package/dist-pkg/auth/signing.d.ts +4 -0
- package/dist-pkg/auth/signing.js +33 -0
- package/dist-pkg/auth/sqlite-session-store.d.ts +12 -0
- package/dist-pkg/auth/sqlite-session-store.js +83 -0
- package/dist-pkg/auth/store-utils.d.ts +2 -0
- package/dist-pkg/auth/store-utils.js +20 -0
- package/dist-pkg/bin/gorsee.js +2 -0
- package/dist-pkg/build/backends/experimental-rolldown.d.ts +6 -0
- package/dist-pkg/build/backends/experimental-rolldown.js +9 -0
- package/dist-pkg/build/backends/register.d.ts +7 -0
- package/dist-pkg/build/backends/register.js +24 -0
- package/dist-pkg/build/backends/rolldown.d.ts +16 -0
- package/dist-pkg/build/backends/rolldown.js +176 -0
- package/dist-pkg/build/client-backend.d.ts +31 -0
- package/dist-pkg/build/client-backend.js +97 -0
- package/dist-pkg/build/client.d.ts +12 -0
- package/dist-pkg/build/client.js +93 -0
- package/dist-pkg/build/css-modules.d.ts +10 -0
- package/dist-pkg/build/css-modules.js +51 -0
- package/dist-pkg/build/devalue-parse.d.ts +1 -0
- package/dist-pkg/build/devalue-parse.js +1 -0
- package/dist-pkg/build/diagnostics.d.ts +20 -0
- package/dist-pkg/build/diagnostics.js +35 -0
- package/dist-pkg/build/fixtures.d.ts +7 -0
- package/dist-pkg/build/fixtures.js +60 -0
- package/dist-pkg/build/framework-imports.d.ts +4 -0
- package/dist-pkg/build/framework-imports.js +58 -0
- package/dist-pkg/build/init.d.ts +1 -0
- package/dist-pkg/build/init.js +6 -0
- package/dist-pkg/build/manifest.d.ts +3 -0
- package/dist-pkg/build/manifest.js +23 -0
- package/dist-pkg/build/parity.d.ts +32 -0
- package/dist-pkg/build/parity.js +71 -0
- package/dist-pkg/build/plugin.d.ts +11 -0
- package/dist-pkg/build/plugin.js +8 -0
- package/dist-pkg/build/readiness.d.ts +11 -0
- package/dist-pkg/build/readiness.js +18 -0
- package/dist-pkg/build/route-client-transform.d.ts +17 -0
- package/dist-pkg/build/route-client-transform.js +48 -0
- package/dist-pkg/build/route-metadata.d.ts +6 -0
- package/dist-pkg/build/route-metadata.js +8 -0
- package/dist-pkg/build/rpc-transform.d.ts +1 -0
- package/dist-pkg/build/rpc-transform.js +44 -0
- package/dist-pkg/build/server-bundle.d.ts +4 -0
- package/dist-pkg/build/server-bundle.js +261 -0
- package/dist-pkg/build/server-strip.d.ts +2 -0
- package/dist-pkg/build/server-strip.js +32 -0
- package/dist-pkg/build/ssg.d.ts +12 -0
- package/dist-pkg/build/ssg.js +36 -0
- package/dist-pkg/cli/bun-plugin.d.ts +2 -0
- package/dist-pkg/cli/bun-plugin.js +14 -0
- package/dist-pkg/cli/canonical-import-rewrite.d.ts +18 -0
- package/dist-pkg/cli/canonical-import-rewrite.js +94 -0
- package/dist-pkg/cli/canonical-imports.d.ts +8 -0
- package/dist-pkg/cli/canonical-imports.js +131 -0
- package/dist-pkg/cli/check-ast.d.ts +20 -0
- package/dist-pkg/cli/check-ast.js +126 -0
- package/dist-pkg/cli/cmd-ai.d.ts +4 -0
- package/dist-pkg/cli/cmd-ai.js +290 -0
- package/dist-pkg/cli/cmd-build.d.ts +12 -0
- package/dist-pkg/cli/cmd-build.js +198 -0
- package/dist-pkg/cli/cmd-check.d.ts +25 -0
- package/dist-pkg/cli/cmd-check.js +573 -0
- package/dist-pkg/cli/cmd-create.d.ts +6 -0
- package/dist-pkg/cli/cmd-create.js +600 -0
- package/dist-pkg/cli/cmd-deploy.d.ts +6 -0
- package/dist-pkg/cli/cmd-deploy.js +381 -0
- package/dist-pkg/cli/cmd-dev.d.ts +5 -0
- package/dist-pkg/cli/cmd-dev.js +5 -0
- package/dist-pkg/cli/cmd-docs.d.ts +50 -0
- package/dist-pkg/cli/cmd-docs.js +122 -0
- package/dist-pkg/cli/cmd-generate.d.ts +12 -0
- package/dist-pkg/cli/cmd-generate.js +320 -0
- package/dist-pkg/cli/cmd-migrate.d.ts +7 -0
- package/dist-pkg/cli/cmd-migrate.js +42 -0
- package/dist-pkg/cli/cmd-routes.d.ts +6 -0
- package/dist-pkg/cli/cmd-routes.js +24 -0
- package/dist-pkg/cli/cmd-start.d.ts +13 -0
- package/dist-pkg/cli/cmd-start.js +32 -0
- package/dist-pkg/cli/cmd-test.d.ts +20 -0
- package/dist-pkg/cli/cmd-test.js +103 -0
- package/dist-pkg/cli/cmd-typegen.d.ts +7 -0
- package/dist-pkg/cli/cmd-typegen.js +66 -0
- package/dist-pkg/cli/cmd-upgrade.d.ts +38 -0
- package/dist-pkg/cli/cmd-upgrade.js +232 -0
- package/dist-pkg/cli/context.d.ts +4 -0
- package/dist-pkg/cli/context.js +4 -0
- package/dist-pkg/cli/framework-md.d.ts +1 -0
- package/dist-pkg/cli/framework-md.js +391 -0
- package/dist-pkg/cli/index.d.ts +6 -0
- package/dist-pkg/cli/index.js +106 -0
- package/dist-pkg/cli/release-version.d.ts +2 -0
- package/dist-pkg/cli/release-version.js +33 -0
- package/dist-pkg/client.d.ts +16 -0
- package/dist-pkg/client.js +71 -0
- package/dist-pkg/compat.d.ts +1 -0
- package/dist-pkg/compat.js +1 -0
- package/dist-pkg/compiler/analysis-backend.d.ts +20 -0
- package/dist-pkg/compiler/analysis-backend.js +164 -0
- package/dist-pkg/compiler/backends/experimental-oxc.d.ts +6 -0
- package/dist-pkg/compiler/backends/experimental-oxc.js +9 -0
- package/dist-pkg/compiler/backends/oxc.d.ts +16 -0
- package/dist-pkg/compiler/backends/oxc.js +198 -0
- package/dist-pkg/compiler/backends/register.d.ts +7 -0
- package/dist-pkg/compiler/backends/register.js +22 -0
- package/dist-pkg/compiler/fixtures.d.ts +2 -0
- package/dist-pkg/compiler/fixtures.js +118 -0
- package/dist-pkg/compiler/init.d.ts +1 -0
- package/dist-pkg/compiler/init.js +6 -0
- package/dist-pkg/compiler/module-analysis.d.ts +13 -0
- package/dist-pkg/compiler/module-analysis.js +50 -0
- package/dist-pkg/compiler/parity.d.ts +35 -0
- package/dist-pkg/compiler/parity.js +89 -0
- package/dist-pkg/compiler/readiness.d.ts +11 -0
- package/dist-pkg/compiler/readiness.js +18 -0
- package/dist-pkg/compiler/route-facts.d.ts +34 -0
- package/dist-pkg/compiler/route-facts.js +75 -0
- package/dist-pkg/content/index.d.ts +27 -0
- package/dist-pkg/content/index.js +287 -0
- package/dist-pkg/db/index.d.ts +3 -0
- package/dist-pkg/db/index.js +6 -0
- package/dist-pkg/db/migrate.d.ts +7 -0
- package/dist-pkg/db/migrate.js +53 -0
- package/dist-pkg/db/postgres.d.ts +29 -0
- package/dist-pkg/db/postgres.js +59 -0
- package/dist-pkg/db/sqlite.d.ts +10 -0
- package/dist-pkg/db/sqlite.js +22 -0
- package/dist-pkg/deploy/cloudflare.d.ts +8 -0
- package/{src/deploy/cloudflare.ts → dist-pkg/deploy/cloudflare.js} +44 -28
- package/dist-pkg/deploy/conformance.d.ts +21 -0
- package/dist-pkg/deploy/conformance.js +98 -0
- package/dist-pkg/deploy/dockerfile.d.ts +3 -0
- package/{src/deploy/dockerfile.ts → dist-pkg/deploy/dockerfile.js} +8 -10
- package/dist-pkg/deploy/fly.d.ts +3 -0
- package/{src/deploy/fly.ts → dist-pkg/deploy/fly.js} +11 -12
- package/dist-pkg/deploy/index.d.ts +6 -0
- package/dist-pkg/deploy/index.js +26 -0
- package/dist-pkg/deploy/netlify.d.ts +2 -0
- package/{src/deploy/netlify.ts → dist-pkg/deploy/netlify.js} +17 -11
- package/dist-pkg/deploy/runtime.d.ts +2 -0
- package/dist-pkg/deploy/runtime.js +3 -0
- package/dist-pkg/deploy/vercel.d.ts +22 -0
- package/dist-pkg/deploy/vercel.js +53 -0
- package/dist-pkg/dev/error-overlay.d.ts +1 -0
- package/{src/dev/error-overlay.ts → dist-pkg/dev/error-overlay.js} +13 -23
- package/dist-pkg/dev/hmr.d.ts +30 -0
- package/dist-pkg/dev/hmr.js +86 -0
- package/dist-pkg/dev/partial-handler.d.ts +9 -0
- package/dist-pkg/dev/partial-handler.js +24 -0
- package/dist-pkg/dev/request-handler.d.ts +30 -0
- package/dist-pkg/dev/request-handler.js +67 -0
- package/dist-pkg/dev/watcher.d.ts +6 -0
- package/dist-pkg/dev/watcher.js +34 -0
- package/dist-pkg/dev.d.ts +11 -0
- package/dist-pkg/dev.js +268 -0
- package/dist-pkg/env/index.d.ts +3 -0
- package/dist-pkg/env/index.js +57 -0
- package/dist-pkg/errors/catalog.d.ts +9 -0
- package/{src/errors/catalog.ts → dist-pkg/errors/catalog.js} +8 -24
- package/dist-pkg/errors/formatter.d.ts +22 -0
- package/dist-pkg/errors/formatter.js +43 -0
- package/dist-pkg/errors/index.d.ts +2 -0
- package/dist-pkg/errors/index.js +2 -0
- package/dist-pkg/forms/action.d.ts +15 -0
- package/dist-pkg/forms/action.js +20 -0
- package/dist-pkg/forms/index.d.ts +4 -0
- package/dist-pkg/forms/index.js +12 -0
- package/dist-pkg/i18n/index.d.ts +61 -0
- package/dist-pkg/i18n/index.js +147 -0
- package/dist-pkg/index-client.d.ts +1 -0
- package/dist-pkg/index-client.js +1 -0
- package/dist-pkg/index.d.ts +32 -0
- package/dist-pkg/index.js +79 -0
- package/dist-pkg/jsx-runtime-client.d.ts +8 -0
- package/dist-pkg/jsx-runtime-client.js +1 -0
- package/dist-pkg/jsx-runtime.d.ts +13 -0
- package/dist-pkg/jsx-runtime.js +5 -0
- package/dist-pkg/jsx-types-html.d.ts +221 -0
- package/dist-pkg/jsx-types-html.js +0 -0
- package/dist-pkg/log/index.d.ts +8 -0
- package/dist-pkg/log/index.js +55 -0
- package/dist-pkg/plugins/drizzle.d.ts +16 -0
- package/dist-pkg/plugins/drizzle.js +53 -0
- package/dist-pkg/plugins/index.d.ts +62 -0
- package/dist-pkg/plugins/index.js +159 -0
- package/dist-pkg/plugins/lucia.d.ts +26 -0
- package/dist-pkg/plugins/lucia.js +63 -0
- package/dist-pkg/plugins/prisma.d.ts +14 -0
- package/dist-pkg/plugins/prisma.js +60 -0
- package/dist-pkg/plugins/resend.d.ts +21 -0
- package/dist-pkg/plugins/resend.js +45 -0
- package/dist-pkg/plugins/s3.d.ts +18 -0
- package/dist-pkg/plugins/s3.js +63 -0
- package/dist-pkg/plugins/stripe.d.ts +32 -0
- package/dist-pkg/plugins/stripe.js +69 -0
- package/dist-pkg/plugins/tailwind.d.ts +15 -0
- package/dist-pkg/plugins/tailwind.js +58 -0
- package/dist-pkg/prod.d.ts +21 -0
- package/dist-pkg/prod.js +347 -0
- package/dist-pkg/reactive/computed.d.ts +3 -0
- package/dist-pkg/reactive/computed.js +15 -0
- package/dist-pkg/reactive/data.d.ts +25 -0
- package/dist-pkg/reactive/data.js +56 -0
- package/dist-pkg/reactive/diagnostics.d.ts +100 -0
- package/dist-pkg/reactive/diagnostics.js +363 -0
- package/dist-pkg/reactive/effect.d.ts +3 -0
- package/dist-pkg/reactive/effect.js +6 -0
- package/dist-pkg/reactive/index.d.ts +9 -0
- package/dist-pkg/reactive/index.js +18 -0
- package/dist-pkg/reactive/live.d.ts +15 -0
- package/dist-pkg/reactive/live.js +70 -0
- package/dist-pkg/reactive/optimistic.d.ts +20 -0
- package/dist-pkg/reactive/optimistic.js +67 -0
- package/dist-pkg/reactive/resource.d.ts +25 -0
- package/dist-pkg/reactive/resource.js +153 -0
- package/dist-pkg/reactive/signal.d.ts +4 -0
- package/dist-pkg/reactive/signal.js +17 -0
- package/dist-pkg/reactive/store.d.ts +6 -0
- package/dist-pkg/reactive/store.js +19 -0
- package/dist-pkg/router/index.d.ts +2 -0
- package/dist-pkg/router/index.js +2 -0
- package/dist-pkg/router/matcher.d.ts +7 -0
- package/dist-pkg/router/matcher.js +40 -0
- package/dist-pkg/router/scanner.d.ts +14 -0
- package/dist-pkg/router/scanner.js +141 -0
- package/dist-pkg/routes/index.d.ts +1 -0
- package/dist-pkg/routes/index.js +10 -0
- package/dist-pkg/runtime/app-config.d.ts +26 -0
- package/dist-pkg/runtime/app-config.js +69 -0
- package/dist-pkg/runtime/client.d.ts +3 -0
- package/dist-pkg/runtime/client.js +42 -0
- package/dist-pkg/runtime/devtools.d.ts +64 -0
- package/dist-pkg/runtime/devtools.js +132 -0
- package/dist-pkg/runtime/error-boundary.d.ts +6 -0
- package/dist-pkg/runtime/error-boundary.js +17 -0
- package/dist-pkg/runtime/event-replay.d.ts +3 -0
- package/{src/runtime/event-replay.ts → dist-pkg/runtime/event-replay.js} +20 -22
- package/dist-pkg/runtime/event-source.d.ts +7 -0
- package/dist-pkg/runtime/event-source.js +24 -0
- package/dist-pkg/runtime/form.d.ts +24 -0
- package/dist-pkg/runtime/form.js +65 -0
- package/dist-pkg/runtime/head.d.ts +7 -0
- package/dist-pkg/runtime/head.js +90 -0
- package/dist-pkg/runtime/html-escape.d.ts +7 -0
- package/dist-pkg/runtime/html-escape.js +39 -0
- package/dist-pkg/runtime/hydration.d.ts +15 -0
- package/dist-pkg/runtime/hydration.js +103 -0
- package/dist-pkg/runtime/image.d.ts +49 -0
- package/dist-pkg/runtime/image.js +144 -0
- package/dist-pkg/runtime/index.d.ts +17 -0
- package/dist-pkg/runtime/index.js +59 -0
- package/dist-pkg/runtime/island-hydrator.d.ts +12 -0
- package/dist-pkg/runtime/island-hydrator.js +74 -0
- package/dist-pkg/runtime/island.d.ts +19 -0
- package/dist-pkg/runtime/island.js +36 -0
- package/dist-pkg/runtime/jsx-runtime.d.ts +12 -0
- package/dist-pkg/runtime/jsx-runtime.js +176 -0
- package/dist-pkg/runtime/link.d.ts +16 -0
- package/dist-pkg/runtime/link.js +47 -0
- package/dist-pkg/runtime/project.d.ts +37 -0
- package/dist-pkg/runtime/project.js +36 -0
- package/dist-pkg/runtime/renderable.d.ts +6 -0
- package/dist-pkg/runtime/renderable.js +0 -0
- package/dist-pkg/runtime/router.d.ts +47 -0
- package/dist-pkg/runtime/router.js +487 -0
- package/dist-pkg/runtime/server.d.ts +8 -0
- package/dist-pkg/runtime/server.js +71 -0
- package/dist-pkg/runtime/stream.d.ts +29 -0
- package/dist-pkg/runtime/stream.js +106 -0
- package/dist-pkg/runtime/suspense.d.ts +6 -0
- package/dist-pkg/runtime/suspense.js +16 -0
- package/dist-pkg/runtime/typed-routes.d.ts +24 -0
- package/dist-pkg/runtime/typed-routes.js +77 -0
- package/dist-pkg/runtime/validated-form.d.ts +40 -0
- package/dist-pkg/runtime/validated-form.js +120 -0
- package/dist-pkg/security/cors.d.ts +10 -0
- package/dist-pkg/security/cors.js +56 -0
- package/dist-pkg/security/csrf.d.ts +9 -0
- package/dist-pkg/security/csrf.js +53 -0
- package/dist-pkg/security/headers.d.ts +11 -0
- package/dist-pkg/security/headers.js +31 -0
- package/dist-pkg/security/index.d.ts +5 -0
- package/dist-pkg/security/index.js +5 -0
- package/dist-pkg/security/rate-limit.d.ts +10 -0
- package/dist-pkg/security/rate-limit.js +49 -0
- package/dist-pkg/security/redis-rate-limit.d.ts +14 -0
- package/dist-pkg/security/redis-rate-limit.js +23 -0
- package/dist-pkg/server/action.d.ts +21 -0
- package/dist-pkg/server/action.js +64 -0
- package/dist-pkg/server/cache-utils.d.ts +2 -0
- package/dist-pkg/server/cache-utils.js +26 -0
- package/dist-pkg/server/cache.d.ts +33 -0
- package/dist-pkg/server/cache.js +236 -0
- package/dist-pkg/server/compress.d.ts +2 -0
- package/dist-pkg/server/compress.js +77 -0
- package/dist-pkg/server/endpoint-execution.d.ts +28 -0
- package/dist-pkg/server/endpoint-execution.js +37 -0
- package/dist-pkg/server/etag.d.ts +3 -0
- package/dist-pkg/server/etag.js +18 -0
- package/dist-pkg/server/guard.d.ts +16 -0
- package/dist-pkg/server/guard.js +45 -0
- package/dist-pkg/server/html-shell.d.ts +12 -0
- package/dist-pkg/server/html-shell.js +52 -0
- package/dist-pkg/server/index.d.ts +36 -0
- package/dist-pkg/server/index.js +170 -0
- package/dist-pkg/server/jobs.d.ts +41 -0
- package/dist-pkg/server/jobs.js +83 -0
- package/dist-pkg/server/manifest.d.ts +19 -0
- package/dist-pkg/server/manifest.js +36 -0
- package/dist-pkg/server/middleware.d.ts +39 -0
- package/dist-pkg/server/middleware.js +127 -0
- package/dist-pkg/server/mime.d.ts +1 -0
- package/{src/server/mime.ts → dist-pkg/server/mime.js} +6 -17
- package/dist-pkg/server/not-found.d.ts +6 -0
- package/dist-pkg/server/not-found.js +27 -0
- package/dist-pkg/server/page-render.d.ts +29 -0
- package/dist-pkg/server/page-render.js +70 -0
- package/dist-pkg/server/partial-navigation.d.ts +4 -0
- package/dist-pkg/server/partial-navigation.js +16 -0
- package/dist-pkg/server/pipe.d.ts +9 -0
- package/dist-pkg/server/pipe.js +32 -0
- package/dist-pkg/server/redis-cache-store.d.ts +10 -0
- package/dist-pkg/server/redis-cache-store.js +73 -0
- package/dist-pkg/server/redis-client.d.ts +37 -0
- package/dist-pkg/server/redis-client.js +37 -0
- package/dist-pkg/server/request-policy.d.ts +55 -0
- package/dist-pkg/server/request-policy.js +216 -0
- package/dist-pkg/server/request-preflight.d.ts +23 -0
- package/dist-pkg/server/request-preflight.js +46 -0
- package/dist-pkg/server/request-security-policy.d.ts +17 -0
- package/dist-pkg/server/request-security-policy.js +34 -0
- package/dist-pkg/server/request-surface.d.ts +8 -0
- package/dist-pkg/server/request-surface.js +19 -0
- package/dist-pkg/server/route-request.d.ts +31 -0
- package/dist-pkg/server/route-request.js +112 -0
- package/dist-pkg/server/route-response.d.ts +22 -0
- package/dist-pkg/server/route-response.js +61 -0
- package/dist-pkg/server/rpc-hash.d.ts +2 -0
- package/dist-pkg/server/rpc-hash.js +7 -0
- package/dist-pkg/server/rpc-protocol.d.ts +22 -0
- package/dist-pkg/server/rpc-protocol.js +28 -0
- package/dist-pkg/server/rpc-utils.d.ts +2 -0
- package/dist-pkg/server/rpc-utils.js +26 -0
- package/dist-pkg/server/rpc.d.ts +20 -0
- package/dist-pkg/server/rpc.js +147 -0
- package/dist-pkg/server/runtime-dispatch.d.ts +19 -0
- package/dist-pkg/server/runtime-dispatch.js +67 -0
- package/dist-pkg/server/server-execution.d.ts +22 -0
- package/dist-pkg/server/server-execution.js +53 -0
- package/dist-pkg/server/sqlite-cache-store.d.ts +13 -0
- package/dist-pkg/server/sqlite-cache-store.js +88 -0
- package/dist-pkg/server/sse.d.ts +9 -0
- package/dist-pkg/server/sse.js +34 -0
- package/dist-pkg/server/static-file.d.ts +9 -0
- package/dist-pkg/server/static-file.js +43 -0
- package/dist-pkg/server/ws.d.ts +18 -0
- package/dist-pkg/server/ws.js +40 -0
- package/dist-pkg/server-entry.d.ts +19 -0
- package/dist-pkg/server-entry.js +93 -0
- package/dist-pkg/testing/index.d.ts +98 -0
- package/dist-pkg/testing/index.js +257 -0
- package/dist-pkg/types/index.d.ts +4 -0
- package/dist-pkg/types/index.js +4 -0
- package/dist-pkg/types/safe-html.d.ts +7 -0
- package/dist-pkg/types/safe-html.js +19 -0
- package/dist-pkg/types/safe-sql.d.ts +8 -0
- package/dist-pkg/types/safe-sql.js +14 -0
- package/dist-pkg/types/safe-url.d.ts +7 -0
- package/dist-pkg/types/safe-url.js +20 -0
- package/dist-pkg/types/user-input.d.ts +9 -0
- package/dist-pkg/types/user-input.js +3 -0
- package/dist-pkg/unsafe/index.d.ts +12 -0
- package/dist-pkg/unsafe/index.js +6 -0
- package/package.json +110 -45
- package/bin/gorsee.js +0 -2
- package/src/auth/index.ts +0 -178
- package/src/auth/redis-session-store.ts +0 -46
- package/src/auth/sqlite-session-store.ts +0 -98
- package/src/auth/store-utils.ts +0 -21
- package/src/build/client.ts +0 -139
- package/src/build/css-modules.ts +0 -69
- package/src/build/devalue-parse.ts +0 -2
- package/src/build/manifest.ts +0 -34
- package/src/build/route-metadata.ts +0 -12
- package/src/build/rpc-transform.ts +0 -62
- package/src/build/server-strip.ts +0 -87
- package/src/build/ssg.ts +0 -70
- package/src/cli/bun-plugin.ts +0 -58
- package/src/cli/cmd-build.ts +0 -153
- package/src/cli/cmd-check.ts +0 -239
- package/src/cli/cmd-create.ts +0 -328
- package/src/cli/cmd-deploy.ts +0 -149
- package/src/cli/cmd-dev.ts +0 -13
- package/src/cli/cmd-docs.ts +0 -152
- package/src/cli/cmd-generate.ts +0 -155
- package/src/cli/cmd-migrate.ts +0 -53
- package/src/cli/cmd-routes.ts +0 -36
- package/src/cli/cmd-start.ts +0 -30
- package/src/cli/cmd-test.ts +0 -129
- package/src/cli/cmd-typegen.ts +0 -93
- package/src/cli/cmd-upgrade.ts +0 -143
- package/src/cli/context.ts +0 -12
- package/src/cli/framework-md.ts +0 -223
- package/src/cli/index.ts +0 -107
- package/src/client.ts +0 -26
- package/src/db/index.ts +0 -2
- package/src/db/migrate.ts +0 -89
- package/src/db/sqlite.ts +0 -40
- package/src/deploy/index.ts +0 -31
- package/src/deploy/vercel.ts +0 -94
- package/src/dev/hmr.ts +0 -31
- package/src/dev/partial-handler.ts +0 -52
- package/src/dev/request-handler.ts +0 -127
- package/src/dev/watcher.ts +0 -48
- package/src/dev.ts +0 -208
- package/src/env/index.ts +0 -74
- package/src/errors/formatter.ts +0 -63
- package/src/errors/index.ts +0 -2
- package/src/i18n/index.ts +0 -72
- package/src/index-client.ts +0 -4
- package/src/index.ts +0 -43
- package/src/jsx-runtime-client.ts +0 -13
- package/src/jsx-runtime.ts +0 -20
- package/src/jsx-types-html.ts +0 -242
- package/src/log/index.ts +0 -44
- package/src/plugins/drizzle.ts +0 -84
- package/src/plugins/index.ts +0 -86
- package/src/plugins/lucia.ts +0 -111
- package/src/plugins/prisma.ts +0 -85
- package/src/plugins/resend.ts +0 -78
- package/src/plugins/s3.ts +0 -102
- package/src/plugins/stripe.ts +0 -133
- package/src/plugins/tailwind.ts +0 -92
- package/src/prod.ts +0 -252
- package/src/reactive/computed.ts +0 -7
- package/src/reactive/effect.ts +0 -7
- package/src/reactive/index.ts +0 -7
- package/src/reactive/live.ts +0 -97
- package/src/reactive/optimistic.ts +0 -83
- package/src/reactive/resource.ts +0 -138
- package/src/reactive/signal.ts +0 -20
- package/src/reactive/store.ts +0 -36
- package/src/router/index.ts +0 -2
- package/src/router/matcher.ts +0 -53
- package/src/router/scanner.ts +0 -206
- package/src/runtime/client.ts +0 -28
- package/src/runtime/error-boundary.ts +0 -35
- package/src/runtime/form.ts +0 -49
- package/src/runtime/head.ts +0 -113
- package/src/runtime/html-escape.ts +0 -30
- package/src/runtime/hydration.ts +0 -95
- package/src/runtime/image.ts +0 -48
- package/src/runtime/index.ts +0 -12
- package/src/runtime/island-hydrator.ts +0 -84
- package/src/runtime/island.ts +0 -88
- package/src/runtime/jsx-runtime.ts +0 -167
- package/src/runtime/link.ts +0 -45
- package/src/runtime/project.ts +0 -73
- package/src/runtime/router.ts +0 -224
- package/src/runtime/server.ts +0 -102
- package/src/runtime/stream.ts +0 -182
- package/src/runtime/suspense.ts +0 -37
- package/src/runtime/typed-routes.ts +0 -26
- package/src/runtime/validated-form.ts +0 -106
- package/src/security/cors.ts +0 -80
- package/src/security/csrf.ts +0 -85
- package/src/security/headers.ts +0 -50
- package/src/security/index.ts +0 -4
- package/src/security/rate-limit.ts +0 -80
- package/src/server/action.ts +0 -48
- package/src/server/cache-utils.ts +0 -23
- package/src/server/cache.ts +0 -125
- package/src/server/compress.ts +0 -60
- package/src/server/etag.ts +0 -23
- package/src/server/guard.ts +0 -69
- package/src/server/html-shell.ts +0 -69
- package/src/server/index.ts +0 -57
- package/src/server/manifest.ts +0 -36
- package/src/server/middleware.ts +0 -159
- package/src/server/not-found.ts +0 -35
- package/src/server/page-render.ts +0 -123
- package/src/server/pipe.ts +0 -46
- package/src/server/redis-cache-store.ts +0 -87
- package/src/server/redis-client.ts +0 -71
- package/src/server/request-preflight.ts +0 -45
- package/src/server/route-request.ts +0 -72
- package/src/server/rpc-hash.ts +0 -17
- package/src/server/rpc-utils.ts +0 -27
- package/src/server/rpc.ts +0 -177
- package/src/server/sqlite-cache-store.ts +0 -109
- package/src/server/sse.ts +0 -96
- package/src/server/static-file.ts +0 -63
- package/src/server/ws.ts +0 -56
- package/src/server-entry.ts +0 -36
- package/src/testing/index.ts +0 -74
- package/src/types/index.ts +0 -4
- package/src/types/safe-html.ts +0 -32
- package/src/types/safe-sql.ts +0 -28
- package/src/types/safe-url.ts +0 -40
- package/src/types/user-input.ts +0 -12
- package/src/unsafe/index.ts +0 -18
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import { buildRedisKey } from "../server/redis-client.js";
|
|
2
|
+
import { parseRateLimitWindow } from "./rate-limit.js";
|
|
3
|
+
export function createRedisRateLimiter(client, maxRequests, window, options = {}) {
|
|
4
|
+
if (!client.incr || !client.expire)
|
|
5
|
+
throw Error("Redis rate limiter requires incr() and expire() support on the Redis client.");
|
|
6
|
+
const prefix = options.prefix ?? "gorsee:rate-limit", windowMs = parseRateLimitWindow(window);
|
|
7
|
+
return {
|
|
8
|
+
async check(key) {
|
|
9
|
+
const redisKey = buildRedisKey(prefix, key), now = Date.now(), count = await client.incr(redisKey);
|
|
10
|
+
if (count === 1)
|
|
11
|
+
await client.expire(redisKey, Math.max(1, Math.ceil(windowMs / 1000)));
|
|
12
|
+
const ttlMs = client.pttl ? Math.max(0, await client.pttl(redisKey)) : windowMs;
|
|
13
|
+
return {
|
|
14
|
+
allowed: count <= maxRequests,
|
|
15
|
+
remaining: Math.max(0, maxRequests - count),
|
|
16
|
+
resetAt: now + ttlMs
|
|
17
|
+
};
|
|
18
|
+
},
|
|
19
|
+
async reset(key) {
|
|
20
|
+
await client.del(buildRedisKey(prefix, key));
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Context } from "./middleware.js";
|
|
2
|
+
export interface ActionResult<T = unknown> {
|
|
3
|
+
ok: boolean;
|
|
4
|
+
status: number;
|
|
5
|
+
data?: T;
|
|
6
|
+
error?: string;
|
|
7
|
+
fieldErrors?: Record<string, string[]>;
|
|
8
|
+
formErrors?: string[];
|
|
9
|
+
values?: Record<string, string>;
|
|
10
|
+
}
|
|
11
|
+
export type ActionReturn<T = unknown> = T | Response | ActionResult<T>;
|
|
12
|
+
export type ActionFn<T = unknown> = (ctx: Context) => Promise<ActionReturn<T>>;
|
|
13
|
+
export declare function actionSuccess<T>(data?: T, init?: Omit<Partial<ActionResult<T>>, "ok" | "data"> & {
|
|
14
|
+
status?: number;
|
|
15
|
+
}): ActionResult<T>;
|
|
16
|
+
export declare function actionFailure<T = never>(error: string, init?: Omit<Partial<ActionResult<T>>, "ok" | "error"> & {
|
|
17
|
+
status?: number;
|
|
18
|
+
}): ActionResult<T>;
|
|
19
|
+
export declare function defineAction<T = unknown>(fn: ActionFn<T>): ActionFn<T>;
|
|
20
|
+
export declare function handleAction<T>(actionFn: ActionFn<T>, ctx: Context): Promise<ActionResult<T>>;
|
|
21
|
+
export declare function parseFormData(request: Request): Promise<Record<string, string>>;
|
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
function isActionResult(value) {
|
|
2
|
+
if (!value || typeof value !== "object" || Array.isArray(value))
|
|
3
|
+
return !1;
|
|
4
|
+
if ("status" in value || "error" in value || "fieldErrors" in value || "formErrors" in value || "values" in value)
|
|
5
|
+
return !0;
|
|
6
|
+
return "ok" in value && value.ok === !1;
|
|
7
|
+
}
|
|
8
|
+
export function actionSuccess(data, init = {}) {
|
|
9
|
+
return {
|
|
10
|
+
ok: !0,
|
|
11
|
+
status: init.status ?? 200,
|
|
12
|
+
data,
|
|
13
|
+
error: init.error,
|
|
14
|
+
fieldErrors: init.fieldErrors,
|
|
15
|
+
formErrors: init.formErrors,
|
|
16
|
+
values: init.values
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export function actionFailure(error, init = {}) {
|
|
20
|
+
return {
|
|
21
|
+
ok: !1,
|
|
22
|
+
status: init.status ?? 400,
|
|
23
|
+
data: init.data,
|
|
24
|
+
error,
|
|
25
|
+
fieldErrors: init.fieldErrors,
|
|
26
|
+
formErrors: init.formErrors,
|
|
27
|
+
values: init.values
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function normalizeActionResult(result) {
|
|
31
|
+
const status = result.status ?? (result.ok === !1 || result.error ? 400 : 200);
|
|
32
|
+
return {
|
|
33
|
+
ok: result.ok ?? (status < 400 && !result.error),
|
|
34
|
+
status,
|
|
35
|
+
data: result.data,
|
|
36
|
+
error: result.error,
|
|
37
|
+
fieldErrors: result.fieldErrors,
|
|
38
|
+
formErrors: result.formErrors,
|
|
39
|
+
values: result.values
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
export function defineAction(fn) {
|
|
43
|
+
return fn;
|
|
44
|
+
}
|
|
45
|
+
export async function handleAction(actionFn, ctx) {
|
|
46
|
+
try {
|
|
47
|
+
const result = await actionFn(ctx);
|
|
48
|
+
if (result instanceof Response)
|
|
49
|
+
return { ok: result.ok, status: result.status };
|
|
50
|
+
if (isActionResult(result))
|
|
51
|
+
return normalizeActionResult(result);
|
|
52
|
+
return actionSuccess(result);
|
|
53
|
+
} catch (err) {
|
|
54
|
+
const message = err instanceof Error ? err.message : String(err);
|
|
55
|
+
return actionFailure(message, { status: 500 });
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
export async function parseFormData(request) {
|
|
59
|
+
const formData = await request.formData(), result = {};
|
|
60
|
+
for (const [key, value] of formData.entries())
|
|
61
|
+
if (typeof value === "string")
|
|
62
|
+
result[key] = value;
|
|
63
|
+
return result;
|
|
64
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
export function createNamespacedCacheStore(store, namespace) {
|
|
2
|
+
const prefix = `${namespace}:`;
|
|
3
|
+
return {
|
|
4
|
+
get: (key) => store.get(prefix + key),
|
|
5
|
+
set: async (key, entry) => {
|
|
6
|
+
await store.set(prefix + key, entry);
|
|
7
|
+
},
|
|
8
|
+
delete: async (key) => {
|
|
9
|
+
await store.delete(prefix + key);
|
|
10
|
+
},
|
|
11
|
+
clear: async () => {
|
|
12
|
+
const keys = await store.keys();
|
|
13
|
+
for await (const key of keys)
|
|
14
|
+
if (key.startsWith(prefix))
|
|
15
|
+
await store.delete(key);
|
|
16
|
+
},
|
|
17
|
+
keys: async function* () {
|
|
18
|
+
const keys = await store.keys();
|
|
19
|
+
for await (const key of keys) {
|
|
20
|
+
if (!key.startsWith(prefix))
|
|
21
|
+
continue;
|
|
22
|
+
yield key.slice(prefix.length);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
};
|
|
26
|
+
}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type { MiddlewareFn } from "./middleware.js";
|
|
2
|
+
export type CacheMode = "private" | "public" | "shared" | "no-store";
|
|
3
|
+
export interface CacheOptions {
|
|
4
|
+
maxAge: number;
|
|
5
|
+
staleWhileRevalidate?: number;
|
|
6
|
+
mode?: CacheMode;
|
|
7
|
+
vary?: string[];
|
|
8
|
+
includeAuthHeaders?: boolean;
|
|
9
|
+
key?: (url: URL) => string;
|
|
10
|
+
store?: CacheStore;
|
|
11
|
+
}
|
|
12
|
+
type Awaitable<T> = T | Promise<T>;
|
|
13
|
+
export interface CacheEntry {
|
|
14
|
+
body: string;
|
|
15
|
+
headers: Record<string, string>;
|
|
16
|
+
status: number;
|
|
17
|
+
createdAt: number;
|
|
18
|
+
revalidating?: boolean;
|
|
19
|
+
}
|
|
20
|
+
export interface CacheStore {
|
|
21
|
+
get(key: string): Awaitable<CacheEntry | undefined>;
|
|
22
|
+
set(key: string, entry: CacheEntry): Awaitable<void>;
|
|
23
|
+
delete(key: string): Awaitable<void>;
|
|
24
|
+
clear(): Awaitable<void>;
|
|
25
|
+
keys(): Awaitable<Iterable<string> | AsyncIterable<string>>;
|
|
26
|
+
}
|
|
27
|
+
export declare function createMemoryCacheStore(): CacheStore;
|
|
28
|
+
export declare function resolveCacheMode(options: CacheOptions): CacheMode;
|
|
29
|
+
export declare function shouldIncludeAuthHeadersForCache(options: CacheOptions, mode?: CacheMode): boolean;
|
|
30
|
+
export declare function routeCache(options: CacheOptions): MiddlewareFn;
|
|
31
|
+
export declare function invalidateCache(path: string): Promise<void>;
|
|
32
|
+
export declare function clearCache(): Promise<void>;
|
|
33
|
+
export {};
|
|
@@ -0,0 +1,236 @@
|
|
|
1
|
+
import { emitAIEvent } from "../ai/index.js";
|
|
2
|
+
export function createMemoryCacheStore() {
|
|
3
|
+
const store = new Map;
|
|
4
|
+
return {
|
|
5
|
+
get: (key) => store.get(key),
|
|
6
|
+
set: (key, entry) => {
|
|
7
|
+
store.set(key, entry);
|
|
8
|
+
},
|
|
9
|
+
delete: (key) => {
|
|
10
|
+
store.delete(key);
|
|
11
|
+
},
|
|
12
|
+
clear: () => {
|
|
13
|
+
store.clear();
|
|
14
|
+
},
|
|
15
|
+
keys: () => store.keys()
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
const defaultCacheStore = createMemoryCacheStore(), DEFAULT_AUTH_VARY = ["Cookie", "Authorization"], DEFAULT_SURFACE_VARY = ["Accept", "X-Gorsee-Navigate"];
|
|
19
|
+
export function resolveCacheMode(options) {
|
|
20
|
+
if (options.mode)
|
|
21
|
+
return options.mode;
|
|
22
|
+
if (options.includeAuthHeaders === !1)
|
|
23
|
+
return "public";
|
|
24
|
+
return "private";
|
|
25
|
+
}
|
|
26
|
+
export function shouldIncludeAuthHeadersForCache(options, mode = resolveCacheMode(options)) {
|
|
27
|
+
if (typeof options.includeAuthHeaders === "boolean")
|
|
28
|
+
return options.includeAuthHeaders;
|
|
29
|
+
return mode === "private";
|
|
30
|
+
}
|
|
31
|
+
function buildKey(url, vary, request, customKey) {
|
|
32
|
+
const base = customKey ? customKey(url) : url.pathname + url.search;
|
|
33
|
+
if (vary.length === 0)
|
|
34
|
+
return base;
|
|
35
|
+
const varyParts = vary.map((h) => `${h}=${request.headers.get(h) ?? ""}`).join("&");
|
|
36
|
+
return `${base}?__vary=${varyParts}`;
|
|
37
|
+
}
|
|
38
|
+
export function routeCache(options) {
|
|
39
|
+
const {
|
|
40
|
+
maxAge,
|
|
41
|
+
staleWhileRevalidate = 0,
|
|
42
|
+
vary = [],
|
|
43
|
+
key: customKey,
|
|
44
|
+
store = defaultCacheStore
|
|
45
|
+
} = options, mode = resolveCacheMode(options), includeAuthHeaders = shouldIncludeAuthHeadersForCache(options, mode), normalizedVary = normalizeVaryHeaders([
|
|
46
|
+
...DEFAULT_SURFACE_VARY,
|
|
47
|
+
...includeAuthHeaders ? DEFAULT_AUTH_VARY : [],
|
|
48
|
+
...vary
|
|
49
|
+
]);
|
|
50
|
+
return async (ctx, next) => {
|
|
51
|
+
if (ctx.request.method !== "GET")
|
|
52
|
+
return next();
|
|
53
|
+
if (mode === "no-store") {
|
|
54
|
+
const response = await next(), headers = new Headers(response.headers);
|
|
55
|
+
headers.set("Cache-Control", "no-store");
|
|
56
|
+
setVaryHeaderObject(headers, normalizedVary);
|
|
57
|
+
return new Response(response.body, {
|
|
58
|
+
status: response.status,
|
|
59
|
+
statusText: response.statusText,
|
|
60
|
+
headers
|
|
61
|
+
});
|
|
62
|
+
}
|
|
63
|
+
const cacheKey = buildKey(ctx.url, normalizedVary, ctx.request, customKey), entry = await store.get(cacheKey), now = Date.now();
|
|
64
|
+
if (entry) {
|
|
65
|
+
const age = (now - entry.createdAt) / 1000;
|
|
66
|
+
if (age < maxAge) {
|
|
67
|
+
emitAIEvent({
|
|
68
|
+
kind: "cache.hit",
|
|
69
|
+
severity: "info",
|
|
70
|
+
source: "runtime",
|
|
71
|
+
message: "cache hit",
|
|
72
|
+
requestId: typeof ctx.locals.requestId === "string" ? ctx.locals.requestId : void 0,
|
|
73
|
+
traceId: typeof ctx.locals.traceId === "string" ? ctx.locals.traceId : void 0,
|
|
74
|
+
spanId: typeof ctx.locals.spanId === "string" ? ctx.locals.spanId : void 0,
|
|
75
|
+
route: ctx.url.pathname,
|
|
76
|
+
data: { cacheKey, ageSeconds: Math.floor(age), mode }
|
|
77
|
+
});
|
|
78
|
+
return new Response(entry.body, {
|
|
79
|
+
status: entry.status,
|
|
80
|
+
headers: withVaryHeaders(entry.headers, normalizedVary, {
|
|
81
|
+
"X-Cache": "HIT",
|
|
82
|
+
Age: String(Math.floor(age))
|
|
83
|
+
})
|
|
84
|
+
});
|
|
85
|
+
}
|
|
86
|
+
if (age < maxAge + staleWhileRevalidate && !entry.revalidating) {
|
|
87
|
+
entry.revalidating = !0;
|
|
88
|
+
emitAIEvent({
|
|
89
|
+
kind: "cache.stale",
|
|
90
|
+
severity: "warn",
|
|
91
|
+
source: "runtime",
|
|
92
|
+
message: "stale cache entry served",
|
|
93
|
+
requestId: typeof ctx.locals.requestId === "string" ? ctx.locals.requestId : void 0,
|
|
94
|
+
traceId: typeof ctx.locals.traceId === "string" ? ctx.locals.traceId : void 0,
|
|
95
|
+
spanId: typeof ctx.locals.spanId === "string" ? ctx.locals.spanId : void 0,
|
|
96
|
+
route: ctx.url.pathname,
|
|
97
|
+
data: { cacheKey, ageSeconds: Math.floor(age), mode }
|
|
98
|
+
});
|
|
99
|
+
revalidate(cacheKey, store, next);
|
|
100
|
+
return new Response(entry.body, {
|
|
101
|
+
status: entry.status,
|
|
102
|
+
headers: withVaryHeaders(entry.headers, normalizedVary, {
|
|
103
|
+
"X-Cache": "STALE",
|
|
104
|
+
Age: String(Math.floor(age))
|
|
105
|
+
})
|
|
106
|
+
});
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
emitAIEvent({
|
|
110
|
+
kind: "cache.miss",
|
|
111
|
+
severity: "info",
|
|
112
|
+
source: "runtime",
|
|
113
|
+
message: "cache miss",
|
|
114
|
+
requestId: typeof ctx.locals.requestId === "string" ? ctx.locals.requestId : void 0,
|
|
115
|
+
traceId: typeof ctx.locals.traceId === "string" ? ctx.locals.traceId : void 0,
|
|
116
|
+
spanId: typeof ctx.locals.spanId === "string" ? ctx.locals.spanId : void 0,
|
|
117
|
+
route: ctx.url.pathname,
|
|
118
|
+
data: { cacheKey, mode }
|
|
119
|
+
});
|
|
120
|
+
const response = await next();
|
|
121
|
+
if (response.status === 200 && isCacheableResponse(response, mode)) {
|
|
122
|
+
const body = await response.text(), headers = {};
|
|
123
|
+
response.headers.forEach((v, k) => {
|
|
124
|
+
headers[k] = v;
|
|
125
|
+
});
|
|
126
|
+
setVaryHeader(headers, normalizedVary);
|
|
127
|
+
setCacheControlHeader(headers, mode, maxAge, staleWhileRevalidate);
|
|
128
|
+
await store.set(cacheKey, { body, headers, status: response.status, createdAt: now });
|
|
129
|
+
return new Response(body, {
|
|
130
|
+
status: response.status,
|
|
131
|
+
headers: { ...headers, "X-Cache": "MISS" }
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
emitAIEvent({
|
|
135
|
+
kind: "cache.skip",
|
|
136
|
+
severity: "debug",
|
|
137
|
+
source: "runtime",
|
|
138
|
+
message: "response not cached",
|
|
139
|
+
requestId: typeof ctx.locals.requestId === "string" ? ctx.locals.requestId : void 0,
|
|
140
|
+
traceId: typeof ctx.locals.traceId === "string" ? ctx.locals.traceId : void 0,
|
|
141
|
+
spanId: typeof ctx.locals.spanId === "string" ? ctx.locals.spanId : void 0,
|
|
142
|
+
route: ctx.url.pathname,
|
|
143
|
+
data: { cacheKey, status: response.status, mode }
|
|
144
|
+
});
|
|
145
|
+
return response;
|
|
146
|
+
};
|
|
147
|
+
}
|
|
148
|
+
async function revalidate(key, store, next) {
|
|
149
|
+
try {
|
|
150
|
+
const response = await next();
|
|
151
|
+
if (response.status === 200) {
|
|
152
|
+
const body = await response.text(), headers = {};
|
|
153
|
+
response.headers.forEach((v, k) => {
|
|
154
|
+
headers[k] = v;
|
|
155
|
+
});
|
|
156
|
+
await store.set(key, { body, headers, status: response.status, createdAt: Date.now() });
|
|
157
|
+
}
|
|
158
|
+
} catch {
|
|
159
|
+
const entry = await store.get(key);
|
|
160
|
+
if (entry)
|
|
161
|
+
entry.revalidating = !1;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
export async function invalidateCache(path) {
|
|
165
|
+
const keys = await defaultCacheStore.keys();
|
|
166
|
+
for await (const key of keys)
|
|
167
|
+
if (key.startsWith(path))
|
|
168
|
+
await defaultCacheStore.delete(key);
|
|
169
|
+
}
|
|
170
|
+
export async function clearCache() {
|
|
171
|
+
await defaultCacheStore.clear();
|
|
172
|
+
}
|
|
173
|
+
function normalizeVaryHeaders(headers) {
|
|
174
|
+
const seen = new Set, normalized = [];
|
|
175
|
+
for (const header of headers) {
|
|
176
|
+
const trimmed = header.trim();
|
|
177
|
+
if (!trimmed)
|
|
178
|
+
continue;
|
|
179
|
+
const key = trimmed.toLowerCase();
|
|
180
|
+
if (seen.has(key))
|
|
181
|
+
continue;
|
|
182
|
+
seen.add(key);
|
|
183
|
+
normalized.push(canonicalizeHeaderName(trimmed));
|
|
184
|
+
}
|
|
185
|
+
normalized.sort((a, b) => a.localeCompare(b, void 0, { sensitivity: "base" }));
|
|
186
|
+
return normalized;
|
|
187
|
+
}
|
|
188
|
+
function setVaryHeader(headers, vary) {
|
|
189
|
+
if (vary.length === 0)
|
|
190
|
+
return;
|
|
191
|
+
const existing = headers.vary ?? headers.Vary, merged = normalizeVaryHeaders([
|
|
192
|
+
...existing ? existing.split(",") : [],
|
|
193
|
+
...vary
|
|
194
|
+
]);
|
|
195
|
+
headers.Vary = merged.join(", ");
|
|
196
|
+
delete headers.vary;
|
|
197
|
+
}
|
|
198
|
+
function setVaryHeaderObject(headers, vary) {
|
|
199
|
+
if (vary.length === 0)
|
|
200
|
+
return;
|
|
201
|
+
const existing = headers.get("Vary"), merged = normalizeVaryHeaders([
|
|
202
|
+
...existing ? existing.split(",") : [],
|
|
203
|
+
...vary
|
|
204
|
+
]);
|
|
205
|
+
headers.set("Vary", merged.join(", "));
|
|
206
|
+
}
|
|
207
|
+
function withVaryHeaders(headers, vary, extraHeaders) {
|
|
208
|
+
const merged = { ...headers, ...extraHeaders };
|
|
209
|
+
setVaryHeader(merged, vary);
|
|
210
|
+
return merged;
|
|
211
|
+
}
|
|
212
|
+
function isCacheableResponse(response, mode) {
|
|
213
|
+
if (response.headers.has("Set-Cookie"))
|
|
214
|
+
return !1;
|
|
215
|
+
const cacheControl = response.headers.get("Cache-Control")?.toLowerCase() ?? "";
|
|
216
|
+
if (cacheControl.includes("no-store"))
|
|
217
|
+
return !1;
|
|
218
|
+
if (mode === "public" || mode === "shared")
|
|
219
|
+
return !cacheControl.includes("private");
|
|
220
|
+
return !0;
|
|
221
|
+
}
|
|
222
|
+
function setCacheControlHeader(headers, mode, maxAge, staleWhileRevalidate) {
|
|
223
|
+
if (mode === "no-store") {
|
|
224
|
+
headers["Cache-Control"] = "no-store";
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
const directives = [mode === "private" ? "private" : "public", `max-age=${maxAge}`];
|
|
228
|
+
if (mode === "shared")
|
|
229
|
+
directives.push(`s-maxage=${maxAge}`);
|
|
230
|
+
if (staleWhileRevalidate > 0)
|
|
231
|
+
directives.push(`stale-while-revalidate=${staleWhileRevalidate}`);
|
|
232
|
+
headers["Cache-Control"] = directives.join(", ");
|
|
233
|
+
}
|
|
234
|
+
function canonicalizeHeaderName(header) {
|
|
235
|
+
return header.toLowerCase().split("-").map((segment) => segment ? segment[0].toUpperCase() + segment.slice(1) : segment).join("-");
|
|
236
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
const COMPRESSIBLE_TYPES = new Set([
|
|
2
|
+
"text/html",
|
|
3
|
+
"text/css",
|
|
4
|
+
"text/javascript",
|
|
5
|
+
"application/javascript",
|
|
6
|
+
"application/json",
|
|
7
|
+
"text/xml",
|
|
8
|
+
"application/xml",
|
|
9
|
+
"image/svg+xml"
|
|
10
|
+
]);
|
|
11
|
+
function isCompressible(contentType) {
|
|
12
|
+
if (!contentType)
|
|
13
|
+
return !1;
|
|
14
|
+
const type = contentType.split(";")[0].trim();
|
|
15
|
+
return COMPRESSIBLE_TYPES.has(type);
|
|
16
|
+
}
|
|
17
|
+
function parseAcceptedEncodings(header) {
|
|
18
|
+
const accepted = new Map;
|
|
19
|
+
for (const rawEntry of header.split(",")) {
|
|
20
|
+
const entry = rawEntry.trim();
|
|
21
|
+
if (!entry)
|
|
22
|
+
continue;
|
|
23
|
+
const [rawName, ...params] = entry.split(";").map((part) => part.trim()), name = rawName?.toLowerCase();
|
|
24
|
+
if (!name)
|
|
25
|
+
continue;
|
|
26
|
+
const qParam = params.find((part) => part.startsWith("q=")), qValue = qParam ? Number(qParam.slice(2)) : 1;
|
|
27
|
+
if (!Number.isFinite(qValue))
|
|
28
|
+
continue;
|
|
29
|
+
accepted.set(name, Math.max(0, Math.min(qValue, 1)));
|
|
30
|
+
}
|
|
31
|
+
return accepted;
|
|
32
|
+
}
|
|
33
|
+
function resolveEncoding(header) {
|
|
34
|
+
const acceptedEncodings = parseAcceptedEncodings(header), wildcardWeight = acceptedEncodings.get("*"), candidates = ["gzip", "deflate"];
|
|
35
|
+
let best = null;
|
|
36
|
+
for (const encoding of candidates) {
|
|
37
|
+
const weight = acceptedEncodings.get(encoding) ?? wildcardWeight ?? 0;
|
|
38
|
+
if (weight <= 0)
|
|
39
|
+
continue;
|
|
40
|
+
if (!best || weight > best.weight)
|
|
41
|
+
best = { encoding, weight };
|
|
42
|
+
}
|
|
43
|
+
return best?.encoding ?? null;
|
|
44
|
+
}
|
|
45
|
+
export function compress() {
|
|
46
|
+
return async (_ctx, next) => {
|
|
47
|
+
const response = await next(), contentType = response.headers.get("content-type");
|
|
48
|
+
if (!isCompressible(contentType))
|
|
49
|
+
return response;
|
|
50
|
+
if (response.headers.has("content-encoding"))
|
|
51
|
+
return response;
|
|
52
|
+
if (!response.body)
|
|
53
|
+
return response;
|
|
54
|
+
const selectedEncoding = resolveEncoding(_ctx.request.headers.get("accept-encoding") ?? "");
|
|
55
|
+
if (selectedEncoding === "gzip") {
|
|
56
|
+
const compressed = response.body.pipeThrough(new CompressionStream("gzip")), headers = new Headers(response.headers);
|
|
57
|
+
headers.set("Content-Encoding", "gzip");
|
|
58
|
+
headers.delete("Content-Length");
|
|
59
|
+
return new Response(compressed, {
|
|
60
|
+
status: response.status,
|
|
61
|
+
statusText: response.statusText,
|
|
62
|
+
headers
|
|
63
|
+
});
|
|
64
|
+
}
|
|
65
|
+
if (selectedEncoding === "deflate") {
|
|
66
|
+
const compressed = response.body.pipeThrough(new CompressionStream("deflate")), headers = new Headers(response.headers);
|
|
67
|
+
headers.set("Content-Encoding", "deflate");
|
|
68
|
+
headers.delete("Content-Length");
|
|
69
|
+
return new Response(compressed, {
|
|
70
|
+
status: response.status,
|
|
71
|
+
statusText: response.statusText,
|
|
72
|
+
headers
|
|
73
|
+
});
|
|
74
|
+
}
|
|
75
|
+
return response;
|
|
76
|
+
};
|
|
77
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { type Context, type MiddlewareFn } from "./middleware.js";
|
|
2
|
+
import { type RequestExecutionKind, type RequestExecutionPolicy, type RequestMetadata } from "./request-policy.js";
|
|
3
|
+
import { type RequestSecurityPolicy } from "./request-security-policy.js";
|
|
4
|
+
export interface EndpointExecutionTrace {
|
|
5
|
+
requestId?: string;
|
|
6
|
+
traceId?: string;
|
|
7
|
+
spanId?: string;
|
|
8
|
+
parentSpanId?: string;
|
|
9
|
+
}
|
|
10
|
+
export interface EndpointExecutionContext {
|
|
11
|
+
ctx: Context;
|
|
12
|
+
metadata: RequestMetadata;
|
|
13
|
+
requestPolicy: RequestExecutionPolicy;
|
|
14
|
+
securityPolicy: RequestSecurityPolicy;
|
|
15
|
+
}
|
|
16
|
+
export interface EndpointExecutionOptions {
|
|
17
|
+
request: Request;
|
|
18
|
+
kind: RequestExecutionKind;
|
|
19
|
+
params?: Record<string, string>;
|
|
20
|
+
trustedOrigin?: string;
|
|
21
|
+
trustForwardedHeaders?: boolean;
|
|
22
|
+
trustedForwardedHops?: number;
|
|
23
|
+
securityPolicy?: RequestSecurityPolicy;
|
|
24
|
+
middlewares?: MiddlewareFn[];
|
|
25
|
+
trace?: EndpointExecutionTrace;
|
|
26
|
+
handler: (context: EndpointExecutionContext) => Promise<Response>;
|
|
27
|
+
}
|
|
28
|
+
export declare function executeEndpointRequest(options: EndpointExecutionOptions): Promise<Response>;
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import { createContext, runMiddlewareChain } from "./middleware.js";
|
|
2
|
+
import {
|
|
3
|
+
attachRequestMetadata,
|
|
4
|
+
resolveRequestExecutionPolicy,
|
|
5
|
+
resolveRequestMetadata,
|
|
6
|
+
validateRequestPolicy
|
|
7
|
+
} from "./request-policy.js";
|
|
8
|
+
import {
|
|
9
|
+
createRequestSecurityPolicy,
|
|
10
|
+
validateRequestSecurityPolicy
|
|
11
|
+
} from "./request-security-policy.js";
|
|
12
|
+
import { createTraceIds } from "../ai/index.js";
|
|
13
|
+
export async function executeEndpointRequest(options) {
|
|
14
|
+
const trace = options.trace?.requestId && options.trace?.traceId && options.trace?.spanId ? options.trace : createTraceIds(options.trace), securityPolicy = options.securityPolicy ?? createRequestSecurityPolicy({
|
|
15
|
+
trustedOrigin: options.trustedOrigin,
|
|
16
|
+
trustForwardedHeaders: options.trustForwardedHeaders,
|
|
17
|
+
trustedForwardedHops: options.trustedForwardedHops
|
|
18
|
+
}), requestPolicy = resolveRequestExecutionPolicy(options.kind), ctx = createContext(options.request, options.params ?? {}, {
|
|
19
|
+
trustedOrigin: securityPolicy.trustedOrigin
|
|
20
|
+
}), metadata = resolveRequestMetadata(options.request, {
|
|
21
|
+
trustedOrigin: securityPolicy.trustedOrigin,
|
|
22
|
+
kind: options.kind,
|
|
23
|
+
visibility: requestPolicy.visibility,
|
|
24
|
+
trustForwardedHeaders: securityPolicy.trustForwardedHeaders,
|
|
25
|
+
trustedForwardedHops: securityPolicy.trustedForwardedHops
|
|
26
|
+
});
|
|
27
|
+
ctx.locals.requestId = trace.requestId;
|
|
28
|
+
ctx.locals.traceId = trace.traceId;
|
|
29
|
+
ctx.locals.spanId = trace.spanId;
|
|
30
|
+
if (trace.parentSpanId)
|
|
31
|
+
ctx.locals.parentSpanId = trace.parentSpanId;
|
|
32
|
+
attachRequestMetadata(ctx.locals, metadata, requestPolicy);
|
|
33
|
+
const violation = validateRequestSecurityPolicy(metadata, requestPolicy, securityPolicy) ?? validateRequestPolicy(metadata, requestPolicy);
|
|
34
|
+
if (violation)
|
|
35
|
+
return violation;
|
|
36
|
+
return runMiddlewareChain(options.middlewares ?? [], ctx, () => options.handler({ ctx, metadata, requestPolicy, securityPolicy }));
|
|
37
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { stat } from "node:fs/promises";
|
|
2
|
+
export function generateETag(size, mtimeMs) {
|
|
3
|
+
return `W/"${size.toString(16)}-${Math.floor(mtimeMs).toString(16)}"`;
|
|
4
|
+
}
|
|
5
|
+
export async function fileETag(filePath) {
|
|
6
|
+
try {
|
|
7
|
+
const s = await stat(filePath);
|
|
8
|
+
return generateETag(s.size, s.mtimeMs);
|
|
9
|
+
} catch {
|
|
10
|
+
return null;
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
export function isNotModified(request, etag) {
|
|
14
|
+
const ifNoneMatch = request.headers.get("if-none-match");
|
|
15
|
+
if (!ifNoneMatch)
|
|
16
|
+
return !1;
|
|
17
|
+
return ifNoneMatch.split(",").some((t) => t.trim() === etag);
|
|
18
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import type { Context, MiddlewareFn } from "./middleware.js";
|
|
2
|
+
type GuardFn = (ctx: Context) => boolean | Promise<boolean>;
|
|
3
|
+
interface GuardOptions {
|
|
4
|
+
onFail?: (ctx: Context) => Response | Promise<Response>;
|
|
5
|
+
}
|
|
6
|
+
/** Create a guard middleware from a predicate */
|
|
7
|
+
export declare function createGuard(check: GuardFn, options?: GuardOptions): MiddlewareFn;
|
|
8
|
+
/** Guard: require authenticated session */
|
|
9
|
+
export declare function requireAuth(loginPath?: string): MiddlewareFn;
|
|
10
|
+
/** Guard: require specific role (reads from session.data.role) */
|
|
11
|
+
export declare function requireRole(role: string, options?: GuardOptions): MiddlewareFn;
|
|
12
|
+
/** Guard: combine multiple guards (all must pass) */
|
|
13
|
+
export declare function allGuards(...guards: MiddlewareFn[]): MiddlewareFn;
|
|
14
|
+
/** Guard: any one guard passing is sufficient */
|
|
15
|
+
export declare function anyGuard(...guards: MiddlewareFn[]): MiddlewareFn;
|
|
16
|
+
export {};
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
const DEFAULT_DENY = (_ctx) => new Response("Forbidden", { status: 403 });
|
|
2
|
+
export function createGuard(check, options) {
|
|
3
|
+
const onFail = options?.onFail ?? DEFAULT_DENY;
|
|
4
|
+
return async (ctx, next) => {
|
|
5
|
+
if (!await check(ctx))
|
|
6
|
+
return onFail(ctx);
|
|
7
|
+
return next();
|
|
8
|
+
};
|
|
9
|
+
}
|
|
10
|
+
export function requireAuth(loginPath = "/login") {
|
|
11
|
+
return createGuard((ctx) => !!ctx.locals.session, { onFail: (ctx) => ctx.redirect(loginPath) });
|
|
12
|
+
}
|
|
13
|
+
export function requireRole(role, options) {
|
|
14
|
+
return createGuard((ctx) => {
|
|
15
|
+
return ctx.locals.session?.data?.role === role;
|
|
16
|
+
}, options);
|
|
17
|
+
}
|
|
18
|
+
export function allGuards(...guards) {
|
|
19
|
+
return async (ctx, next) => {
|
|
20
|
+
for (const guard of guards) {
|
|
21
|
+
let passed = !1;
|
|
22
|
+
const result = await guard(ctx, async () => {
|
|
23
|
+
passed = !0;
|
|
24
|
+
return new Response(null);
|
|
25
|
+
});
|
|
26
|
+
if (!passed)
|
|
27
|
+
return result;
|
|
28
|
+
}
|
|
29
|
+
return next();
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
export function anyGuard(...guards) {
|
|
33
|
+
return async (ctx, next) => {
|
|
34
|
+
for (const guard of guards) {
|
|
35
|
+
let passed = !1;
|
|
36
|
+
await guard(ctx, async () => {
|
|
37
|
+
passed = !0;
|
|
38
|
+
return new Response(null);
|
|
39
|
+
});
|
|
40
|
+
if (passed)
|
|
41
|
+
return next();
|
|
42
|
+
}
|
|
43
|
+
return new Response("Forbidden", { status: 403 });
|
|
44
|
+
};
|
|
45
|
+
}
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
export interface HTMLWrapOptions {
|
|
2
|
+
title?: string;
|
|
3
|
+
clientScript?: string;
|
|
4
|
+
loaderData?: unknown;
|
|
5
|
+
params?: Record<string, string>;
|
|
6
|
+
cssFiles?: string[];
|
|
7
|
+
headElements?: string[];
|
|
8
|
+
bodyPrefix?: string[];
|
|
9
|
+
bodySuffix?: string[];
|
|
10
|
+
}
|
|
11
|
+
export declare function generateNonce(): string;
|
|
12
|
+
export declare function wrapHTML(body: string, nonce: string | undefined, options?: HTMLWrapOptions): string;
|