diff --git a/deno.json b/deno.json index 5407c3c8aa..2b7bab785e 100644 --- a/deno.json +++ b/deno.json @@ -493,12 +493,12 @@ "build:storybook": "npm --prefix storybook run build-storybook", "storybook:check": "deno test --no-lock --config=scripts/test.deno.json --no-check --allow-read scripts/storybook/storybook-workbench.test.ts", "lint": "DENO_NO_PACKAGE_JSON=1 deno lint && deno lint --config=scripts/test.deno.json scripts/test/ scripts/build/dnt-polyfill.ts scripts/build/dnt-polyfill.test.ts scripts/build/npm-package-metadata.test.ts scripts/build/prepare-framework-sources.test.ts && deno lint --config=scripts/codemods/deno.json scripts/codemods/", - "lint:ci": "deno task lint && deno task lint:core-deps && deno task lint:cross-runtime-jsr && deno task lint:dependency-boundaries && deno task lint:module-boundaries && deno task lint:extension-contracts && deno task lint:extension-capabilities && deno task lint:ban-test-only && deno task lint:sanitizer-baseline && deno task lint:skipped-tests && deno task lint:chat-ratchets && deno task lint:esm-sh-codemod && deno task lint:test-typecheck && deno task storybook:check && deno task docs:api-reference:check && deno test --frozen --config=scripts/test.deno.json --no-check --allow-read --allow-write scripts/ci/setup-deno-workflow.test.ts scripts/build/generated-artifact-checks.test.ts", + "lint:ci": "deno task lint && deno task lint:core-deps && deno task lint:cross-runtime-jsr && deno task lint:dependency-boundaries && deno task lint:module-boundaries && deno task lint:extension-contracts && deno task lint:extension-capabilities && deno task lint:ban-test-only && deno task lint:sanitizer-baseline && deno task lint:skipped-tests && deno task lint:chat-ratchets && deno task lint:esm-sh-codemod && deno task lint:test-typecheck && deno task storybook:check && deno task docs:api-reference:check && deno task docs:errors:check && deno test --frozen --config=scripts/test.deno.json --no-check --allow-read --allow-write scripts/ci/setup-deno-workflow.test.ts scripts/build/generated-artifact-checks.test.ts", "fmt": "deno fmt src/ cli/ react/ && deno fmt --config=scripts/test.deno.json scripts/test/ scripts/build/dnt-polyfill.ts scripts/build/dnt-polyfill.test.ts scripts/build/prepare-framework-sources.test.ts && deno fmt --config=scripts/codemods/deno.json scripts/codemods/", "fmt:check": "deno fmt --check src/ cli/ react/ && deno fmt --check --config=scripts/test.deno.json scripts/test/ scripts/build/dnt-polyfill.ts scripts/build/dnt-polyfill.test.ts scripts/build/prepare-framework-sources.test.ts && deno fmt --check --config=scripts/codemods/deno.json scripts/codemods/", "typecheck": "deno task generate:manifests:check && deno check src/index.ts cli/main.ts src/server/index.ts src/routing/api/index.ts src/rendering/index.ts src/platform/index.ts src/platform/adapters/index.ts src/build/index.ts src/build/production-build/index.ts src/transforms/index.ts src/config/index.ts src/utils/index.ts src/data/index.ts src/security/index.ts src/middleware/index.ts src/server/handlers/dev/index.ts src/server/handlers/request/api/index.ts src/rendering/cache/index.ts src/rendering/cache/stores/index.ts src/rendering/rsc/actions/index.ts src/html/index.ts src/html/hydration-script-builder/runtime/main.ts src/modules/index.ts src/proxy/main.ts src/react/components/ui/index.ts src/chat/index.ts src/markdown/index.ts src/mdx/index.ts src/fs/index.ts src/oauth/index.ts src/agent/index.ts src/agent/service/route-export.check.ts src/eval/index.ts src/tool/index.ts src/workflow/index.ts src/prompt/index.ts src/resource/index.ts src/runs/index.ts src/mcp/index.ts src/provider/index.ts", - "verify": "deno task generate:manifests:check && deno task fmt:check && deno task lint && deno task lint:style && deno task lint:chat-composability && deno task lint:chat-ratchets && deno task lint:esm-sh-codemod && deno task lint:cli-boundary && deno task lint:wildcard-exports && deno task lint:barrel-jsdoc && deno task lint:ban-test-only && deno task lint:sanitizer-baseline && deno task lint:skipped-tests && deno task lint:ban-zod && deno task lint:core-deps && deno task lint:cross-runtime-jsr && deno task lint:dependency-boundaries && deno task lint:module-boundaries && deno task lint:extension-contracts && deno task lint:extension-capabilities && deno task docs:api-reference:check && deno task docs:validate && deno task typecheck && deno task typecheck:consumer && deno task test && deno task test:scripts && deno task test:e2e:binary", - "verify:quick": "deno task generate:manifests:check && deno task fmt:check && deno task lint && deno task lint:style && deno task lint:chat-composability && deno task lint:chat-ratchets && deno task lint:esm-sh-codemod && deno task lint:cli-boundary && deno task lint:wildcard-exports && deno task lint:barrel-jsdoc && deno task lint:ban-test-only && deno task lint:sanitizer-baseline && deno task lint:skipped-tests && deno task lint:ban-zod && deno task lint:core-deps && deno task lint:cross-runtime-jsr && deno task lint:dependency-boundaries && deno task lint:module-boundaries && deno task lint:extension-contracts && deno task lint:extension-capabilities && deno task docs:api-reference:check && deno task docs:validate && deno task typecheck", + "verify": "deno task generate:manifests:check && deno task fmt:check && deno task lint && deno task lint:style && deno task lint:chat-composability && deno task lint:chat-ratchets && deno task lint:esm-sh-codemod && deno task lint:cli-boundary && deno task lint:wildcard-exports && deno task lint:barrel-jsdoc && deno task lint:ban-test-only && deno task lint:sanitizer-baseline && deno task lint:skipped-tests && deno task lint:ban-zod && deno task lint:core-deps && deno task lint:cross-runtime-jsr && deno task lint:dependency-boundaries && deno task lint:module-boundaries && deno task lint:extension-contracts && deno task lint:extension-capabilities && deno task docs:api-reference:check && deno task docs:errors:check && deno task docs:validate && deno task typecheck && deno task typecheck:consumer && deno task test && deno task test:scripts && deno task test:e2e:binary", + "verify:quick": "deno task generate:manifests:check && deno task fmt:check && deno task lint && deno task lint:style && deno task lint:chat-composability && deno task lint:chat-ratchets && deno task lint:esm-sh-codemod && deno task lint:cli-boundary && deno task lint:wildcard-exports && deno task lint:barrel-jsdoc && deno task lint:ban-test-only && deno task lint:sanitizer-baseline && deno task lint:skipped-tests && deno task lint:ban-zod && deno task lint:core-deps && deno task lint:cross-runtime-jsr && deno task lint:dependency-boundaries && deno task lint:module-boundaries && deno task lint:extension-contracts && deno task lint:extension-capabilities && deno task docs:api-reference:check && deno task docs:errors:check && deno task docs:validate && deno task typecheck", "typecheck:consumer": "deno run --allow-read --allow-run --allow-env --allow-write scripts/typecheck/run-consumer-typecheck.ts", "codemod:chat": "deno run --frozen --config=scripts/codemods/deno.json --allow-read --allow-write --allow-env=BABEL_TYPES_8_BREAKING scripts/codemods/migrate-chat-composition.ts", "codemod:esm-sh": "deno run --frozen --config=scripts/codemods/deno.json --allow-read --allow-write --allow-env=BABEL_TYPES_8_BREAKING scripts/codemods/migrate-esm-sh-imports.ts", @@ -507,6 +507,8 @@ "lint:test-typecheck": "deno run --allow-read --allow-run scripts/lint/check-test-typecheck-baseline.ts", "docs": "deno run --allow-read --allow-write --allow-run --allow-env scripts/docs/generate-api-reference.ts", "docs:api-reference:check": "deno run --allow-read --allow-write --allow-run --allow-env scripts/docs/generate-api-reference.ts --check", + "docs:errors": "deno run --allow-read --allow-write --allow-run --allow-env scripts/docs/generate-error-reference.ts", + "docs:errors:check": "deno run --allow-read --allow-write --allow-run --allow-env scripts/docs/generate-error-reference.ts --check", "docs:coverage": "deno run --allow-read scripts/docs/docs-coverage.ts", "docs:copy": "rm -rf ../../docs/docs/code/api-reference && cp -r docs/api-reference/ ../../docs/docs/code/api-reference/", "docs:validate": "deno run --allow-read scripts/docs/validate-api-reference.ts && deno run --allow-read scripts/docs/validate-guides.ts && deno run --allow-read scripts/docs/validate-public-docs.ts && deno test --config=scripts/test.deno.json --no-check --allow-read scripts/docs/docs-coverage.test.ts && deno test --no-check --allow-read tests/docs/guide-contracts.test.ts tests/docs/guide-content.test.ts && DENO_TESTING=1 deno test --no-check --allow-all tests/docs/guide-examples.test.ts tests/docs/guide-code-examples.test.ts && deno run -A scripts/lint/check-doc-links.ts", diff --git a/docs/api-reference/veryfront/errors.md b/docs/api-reference/veryfront/errors.md index bd2d5a1ac5..8a5bfc9a76 100644 --- a/docs/api-reference/veryfront/errors.md +++ b/docs/api-reference/veryfront/errors.md @@ -83,7 +83,7 @@ throw INVALID_WIDGET.create({ detail: "The widget id is malformed." }); | `ERROR_CATALOG` | | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/catalog/index.ts#L31) | | `ERROR_OVERLAY_ERROR` | | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/error-registry/dev.ts#L27) | | `ERROR_REGISTRY` | Central registry mapping every error slug to its definition. Assembled from the per-category registry fragments. | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/error-registry.ts#L39) | -| `ERROR_SOLUTIONS` | | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/user-friendly/error-catalog.ts#L5) | +| `ERROR_SOLUTIONS` | | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/user-friendly/error-catalog.ts#L6) | | `FALLBACK_EXHAUSTED` | Both primary and fallback operations failed (replaces FallbackExecutionError) | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/error-registry/server.ts#L129) | | `FAST_REFRESH_ERROR` | | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/error-registry/dev.ts#L19) | | `FILE_NOT_FOUND` | | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/error-registry/general.ts#L27) | @@ -235,7 +235,7 @@ throw INVALID_WIDGET.create({ detail: "The widget id is malformed." }); | `RegisteredError` | Registered error with factory method | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/types.ts#L71) | | `RetryWithBackoffOptions` | Options for `retryWithBackoff`. Every `attempt` value passed to `fn` and the hooks below is 0-based (first try = 0), including `wrapFinalError`'s `lastAttempt`. | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/error-handlers.ts#L72) | | `RFC9457Response` | RFC 9457 Problem Details response shape | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/types.ts#L30) | -| `UserFriendlyErrorSolution` | | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/user-friendly/error-catalog.ts#L3) | +| `UserFriendlyErrorSolution` | | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/user-friendly/error-catalog.ts#L4) | | `VeryfrontErrorData` | Discriminated union for serializable error data. | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/veryfront-error.ts#L93) | | `VeryfrontErrorOptions` | Options for VeryfrontError constructor | [source](https://github.com/veryfront/veryfront-code/blob/main/src/errors/types.ts#L132) | diff --git a/docs/guides/errors.md b/docs/guides/errors.md new file mode 100644 index 0000000000..6f8321a7a5 --- /dev/null +++ b/docs/guides/errors.md @@ -0,0 +1,810 @@ +--- +title: "Error reference" +description: "Every error the Veryfront CLI, server, and logs can report, with what it means and what to do next." +order: 46 +--- + +Veryfront reports errors with a stable slug, such as `port-in-use`. The CLI, the +HTTP response body, and the server logs all print that slug alongside a link to +this page, so you can jump straight to the entry for the error you hit. + +Each entry lists the HTTP status the error maps to, the process exit code when +it reaches the CLI, and the first thing to try. + +This page is generated from the framework's error registry, so it always lists +every error the current release can report. + +## Configuration + +Raised while loading or validating project configuration. + +### config-not-found + +Configuration file not found. + +- **HTTP status:** 404 +- **What to do:** Create veryfront.config.js, veryfront.config.ts, or veryfront.config.mjs in the project root + +### config-invalid + +Invalid configuration format. + +- **HTTP status:** 400 +- **What to do:** Check the reported configuration path and validation details + +### config-parse-error + +Failed to parse configuration. + +- **HTTP status:** 400 +- **What to do:** Ensure your configuration file contains valid JavaScript or TypeScript + +### config-validation-error + +Configuration validation failed. + +- **HTTP status:** 422 +- **What to do:** Check the configuration against the schema requirements + +### config-type-error + +Configuration type mismatch. + +- **HTTP status:** 400 +- **What to do:** Ensure configuration values match expected types + +### import-map-invalid + +Invalid import map configuration. + +- **HTTP status:** 400 +- **What to do:** Check your import map syntax and paths + +### cors-config-invalid + +Invalid CORS configuration. + +- **HTTP status:** 400 +- **What to do:** Review CORS settings in your configuration + +### config-validation-failed + +Configuration validation failed. + +- **HTTP status:** 400 +- **What to do:** Check configuration values against requirements + +### webhook-config-invalid + +Invalid webhook configuration. + +- **HTTP status:** 400 +- **What to do:** Check webhook definition fields, target settings, and eventFilter conditions + +### schedule-config-invalid + +Invalid schedule configuration. + +- **HTTP status:** 400 +- **What to do:** Check schedule definition fields, cron expression, target settings, and positive-integer limits + +### trigger-config-invalid + +Invalid trigger configuration. + +- **HTTP status:** 400 +- **What to do:** Check trigger ID format (lowercase, alphanumeric, dots/slashes/hyphens) and ensure all input values are JSON-serializable + +### template-not-found + +Unknown project template. + +- **HTTP status:** 404 +- **CLI exit code:** 2 +- **What to do:** Run 'veryfront init --help' to see the available templates + +## Build + +Raised while compiling, bundling, or transforming project source. + +### build-failed + +Build process failed. + +- **HTTP status:** 500 +- **What to do:** Check the build output for specific errors + +### bundle-error + +Bundle generation failed. + +- **HTTP status:** 500 +- **What to do:** Review bundler output for details + +### typescript-error + +TypeScript compilation error. + +- **HTTP status:** 500 +- **What to do:** Fix TypeScript errors shown in the output + +### mdx-compile-error + +MDX compilation failed. + +- **HTTP status:** 500 +- **What to do:** Check your MDX file syntax + +### asset-optimization-error + +Asset optimization failed. + +- **HTTP status:** 500 +- **What to do:** Check asset file formats and paths + +### ssg-generation-error + +Static site generation failed. + +- **HTTP status:** 500 +- **What to do:** Review SSG configuration and data fetching + +### sourcemap-error + +Source map generation failed. + +- **HTTP status:** 500 +- **What to do:** Check source map configuration + +### compilation-error + +Compilation failed. + +- **HTTP status:** 500 +- **What to do:** Review compiler output for specific errors + +## Runtime + +Raised while executing project code. + +### hydration-mismatch + +Client/server hydration mismatch. + +- **HTTP status:** 500 +- **What to do:** Ensure server and client render the same content + +### render-error + +Component render failed. + +- **HTTP status:** 500 +- **What to do:** Check component for runtime errors + +### component-error + +Component execution error. + +- **HTTP status:** 500 +- **What to do:** Review component logic and props + +### layout-not-found + +Layout component not found. + +- **HTTP status:** 404 +- **What to do:** Ensure layout file exists at the expected path + +### page-not-found + +Page component not found. + +- **HTTP status:** 404 +- **What to do:** Check that the page file exists in the routes directory + +### api-error + +API route handler error. + +- **HTTP status:** 500 +- **What to do:** Review API route handler for errors + +### middleware-error + +Middleware execution error. + +- **HTTP status:** 500 +- **What to do:** Check middleware function for errors + +### trigger-target-not-found + +Trigger target not found. + +- **HTTP status:** 404 +- **What to do:** Ensure the referenced task or workflow ID is registered in the project + +### trigger-execution-failed + +Trigger target execution failed. + +- **HTTP status:** 500 +- **What to do:** Check the task or workflow for errors and review the trigger input + +### trigger-not-supported + +Trigger target type not supported in local runtime. + +- **HTTP status:** 501 +- **What to do:** Use a workflow or task target for local trigger runs; agent targets require the Cloud runtime + +## Routing + +Raised while matching or handling a route. + +### route-conflict + +Conflicting route definitions. + +- **HTTP status:** 409 +- **What to do:** Rename or reorganize conflicting route files + +### invalid-route-file + +Invalid route file structure. + +- **HTTP status:** 400 +- **What to do:** Ensure route file exports required functions + +### route-handler-invalid + +Invalid route handler export. + +- **HTTP status:** 400 +- **What to do:** Export a valid handler function from the route file + +### dynamic-route-error + +Dynamic route parsing failed. + +- **HTTP status:** 500 +- **What to do:** Check dynamic route segment syntax + +### route-params-error + +Route parameters invalid. + +- **HTTP status:** 400 +- **What to do:** Validate route parameter values + +### api-route-error + +API route definition error. + +- **HTTP status:** 500 +- **What to do:** Review API route configuration + +## Modules + +Raised while resolving or loading a module. + +### module-not-found + +Module could not be resolved. + +- **HTTP status:** 404 +- **What to do:** Check the import path and ensure the module is installed + +### import-resolution-error + +Import path resolution failed. + +- **HTTP status:** 500 +- **What to do:** Verify import paths and module configuration + +### circular-dependency + +Circular dependency detected. + +- **HTTP status:** 500 +- **What to do:** Refactor imports to break the circular dependency + +### invalid-import + +Invalid import statement. + +- **HTTP status:** 400 +- **What to do:** Fix import syntax or path + +### dependency-missing + +Required dependency not installed. + +- **HTTP status:** 404 +- **What to do:** Install the missing dependency with your package manager + +### version-mismatch + +Dependency version mismatch. + +- **HTTP status:** 409 +- **What to do:** Update dependencies to compatible versions + +### lockfile-format-mismatch + +Lockfile format is not supported. + +- **HTTP status:** 409 +- **What to do:** Upgrade Veryfront or migrate the lockfile before modifying it + +### lockfile-read-error + +Lockfile could not be read safely. + +- **HTTP status:** 500 +- **What to do:** Check file access or restore a valid lockfile before retrying + +## Server + +Raised by the dev server, the request pipeline, or a backing service. + +### port-in-use + +Server port already in use. + +- **HTTP status:** 409 +- **What to do:** Stop the process using the port, or pick another with: veryfront dev --port \ + +### server-start-error + +Server failed to start. + +- **HTTP status:** 500 +- **What to do:** Check server configuration and port availability + +### cache-error + +Cache operation failed. + +- **HTTP status:** 500 +- **What to do:** Clear the cache and try again + +### file-watch-error + +File watcher error. + +- **HTTP status:** 500 +- **What to do:** Restart the development server + +### request-error + +HTTP request handling error. + +- **HTTP status:** 500 +- **What to do:** Check request handler and middleware + +### service-overloaded + +Service overloaded. + +- **HTTP status:** 503 +- **What to do:** Reduce load or scale up resources + +### project-execution-unavailable + +Project execution unavailable. + +- **HTTP status:** 503 +- **What to do:** Route the project to a dedicated isolated runtime + +### semaphore-timeout + +Semaphore acquire timeout. + +- **HTTP status:** 503 +- **What to do:** Reduce concurrency or increase the semaphore acquire timeout + +### circuit-breaker-open + +Circuit breaker is open. + +- **HTTP status:** 503 +- **What to do:** Wait for the breaker reset timeout before retrying + +### cache-path-mismatch + +Cache path mismatch. + +- **HTTP status:** 500 +- **What to do:** Clear the cache directory and rebuild + +### network-error + +Network operation failed. + +- **HTTP status:** 502 +- **What to do:** Check network connectivity and retry + +### api-client-error + +API client request failed. + +- **HTTP status:** 500 +- **What to do:** Check API connectivity and authentication + +### token-storage-error + +Token storage operation failed. + +- **HTTP status:** 500 +- **What to do:** Check token storage backend and credentials + +### cache-invariant-violation + +Cache path invariant violated. + +- **HTTP status:** 500 +- **What to do:** Clear the cache and rebuild + +### release-not-found + +No active release found. + +- **HTTP status:** 404 +- **What to do:** Deploy the project to create a release for this environment + +### fallback-exhausted + +Primary and fallback operations both failed. + +- **HTTP status:** 500 +- **What to do:** Check service availability and connectivity + +### rag-store-corrupt + +RAG store file is corrupt. + +- **HTTP status:** 500 +- **What to do:** Repair or move the store file aside, then retry; it was not overwritten + +### rag-store-unavailable + +RAG store file is unavailable. + +- **HTTP status:** 500 +- **What to do:** Check storage availability, permissions, and concurrent operations, then retry + +## Server and client boundary + +Raised when server-only and client-only code are mixed incorrectly. + +### client-boundary-violation + +Client boundary rule violation. + +- **HTTP status:** 400 +- **What to do:** Add 'use client' directive or move code to a client component + +### server-only-in-client + +Server-only code in client component. + +- **HTTP status:** 400 +- **What to do:** Move server-only code to a server component + +### client-only-in-server + +Client-only code in server component. + +- **HTTP status:** 400 +- **What to do:** Move client-only code to a client component + +### invalid-use-client + +Invalid 'use client' directive. + +- **HTTP status:** 400 +- **What to do:** Place 'use client' at the top of the file + +### invalid-use-server + +Invalid 'use server' directive. + +- **HTTP status:** 400 +- **What to do:** Place 'use server' at the top of the file or function + +### rsc-payload-error + +RSC payload serialization error. + +- **HTTP status:** 500 +- **What to do:** Ensure props are serializable (no functions, symbols, etc.) + +### ssr-output-limit-exceeded + +SSR output limit exceeded. + +- **HTTP status:** 500 +- **What to do:** Reduce the rendered HTML size or split the response into smaller pages + +## Development tooling + +Raised by the local development workflow. + +### hmr-error + +Hot module replacement error. + +- **HTTP status:** 500 +- **What to do:** Restart the development server + +### dev-server-error + +Development server error. + +- **HTTP status:** 500 +- **What to do:** Check the dev server logs and restart + +### fast-refresh-error + +Fast refresh failed. + +- **HTTP status:** 500 +- **What to do:** Save the file again or restart the dev server + +### error-overlay-error + +Error overlay failed. + +- **HTTP status:** 500 +- **What to do:** Check browser console for details + +### source-map-error + +Source map loading error. + +- **HTTP status:** 500 +- **What to do:** Rebuild or clear cache + +## Deployment + +Raised while building, uploading, or activating a deployment. + +### deployment-error + +Deployment process failed. + +- **HTTP status:** 500 +- **What to do:** Check deployment logs for details + +### platform-error + +Platform-specific error. + +- **HTTP status:** 500 +- **What to do:** Check platform documentation and requirements + +### env-var-missing + +Required environment variable missing. + +- **HTTP status:** 500 +- **What to do:** Set the required environment variable + +### production-build-required + +Production build required. + +- **HTTP status:** 400 +- **What to do:** Run 'veryfront build' before deploying + +### environment-not-found + +Deployment environment not found. + +- **HTTP status:** 404 +- **What to do:** Check environment names with: veryfront config + +### release-missing-version + +Release has no version. + +- **HTTP status:** 500 +- **What to do:** Try again or check the build logs in Studio + +### release-build-timeout + +Release build timed out. + +- **HTTP status:** 408 +- **What to do:** Try again or check the build logs in Studio + +### deployment-verification-timeout + +Deployment verification timed out. + +- **HTTP status:** 408 +- **What to do:** Try again or check the deployment status in Studio + +### push-receipt-missing + +Push receipt not found. + +- **HTTP status:** 400 +- **What to do:** Run: veryfront push --branch main first + +### source-digest-mismatch + +Release source digest mismatch. + +- **HTTP status:** 409 +- **What to do:** Run veryfront push again to re-upload source files + +### preview-hostname-too-long + +Preview hostname too long. + +- **HTTP status:** 400 +- **What to do:** Use a shorter project slug or branch name + +### branch-not-found + +Branch not found. + +- **HTTP status:** 404 +- **What to do:** List branches in Studio or push a new one with: veryfront push --branch \ + +## Agents + +Raised while running an agent, tool, or workflow. + +### agent-error + +Agent operation error. + +- **HTTP status:** 500 +- **What to do:** Check agent configuration and logs + +### agent-not-found + +Agent not found. + +- **HTTP status:** 404 +- **What to do:** Verify the agent ID exists + +### agent-timeout + +Agent operation timed out. + +- **HTTP status:** 408 +- **What to do:** Increase timeout or simplify the request + +### agent-intent-error + +Agent intent parsing error. + +- **HTTP status:** 400 +- **What to do:** Rephrase the request more clearly + +### orchestration-error + +Multi-agent orchestration error. + +- **HTTP status:** 500 +- **What to do:** Check agent coordination logic + +### cost-limit-exceeded + +Cost limit exceeded. + +- **HTTP status:** 429 +- **What to do:** Wait for the budget period to reset or increase the limit + +### tool-id-conflict + +Tool ID conflict. + +- **HTTP status:** 409 +- **What to do:** Use a unique tool ID or rename one of the conflicting tools + +### durable-run-event-persistence-failed + +Durable run event persistence failed. + +- **HTTP status:** 500 +- **What to do:** Correct invalid or oversized event data, or retry after durable event storage recovers + +## General + +Raised anywhere; these are not specific to one subsystem. + +### unknown-error + +Unknown/unclassified error. + +- **HTTP status:** 500 +- **What to do:** Check logs for more details + +### authentication-required + +Authentication required. + +- **HTTP status:** 401 +- **What to do:** Set VERYFRONT_API_TOKEN or run 'veryfront login' + +### permission-denied + +File/resource permission denied. + +- **HTTP status:** 403 +- **What to do:** Check file permissions and access rights + +### file-not-found + +File not found. + +- **HTTP status:** 404 +- **What to do:** Verify the file path exists + +### resource-not-found + +Requested resource not found. + +- **HTTP status:** 404 +- **What to do:** Verify the referenced resource ID or name exists + +### invalid-argument + +Invalid function argument. + +- **HTTP status:** 400 +- **CLI exit code:** 2 +- **What to do:** Check argument types and values + +### timeout-error + +Operation timed out. + +- **HTTP status:** 408 +- **What to do:** Increase timeout or optimize the operation + +### initialization-error + +Initialization failed. + +- **HTTP status:** 500 +- **What to do:** Check initialization requirements and dependencies + +### not-supported + +Feature not supported. + +- **HTTP status:** 501 +- **What to do:** Check documentation for supported features + +### security-violation + +Security violation detected. + +- **HTTP status:** 403 +- **What to do:** Check for path traversal or unauthorized access attempts + +### input-validation-failed + +Input validation failed. + +- **HTTP status:** 400 +- **What to do:** Check request input against validation rules + +### project-source-empty + +Project source is empty. + +- **HTTP status:** 400 +- **What to do:** Add project files or run 'veryfront init' + +### nested-cwd-scope + +Working directory scope nested inside another. + +- **HTTP status:** 500 +- **What to do:** Do the inner work directly in the outer scope's callback instead of opening a second one diff --git a/docs/guides/index.md b/docs/guides/index.md index 392aee9531..4515dc5b1f 100644 --- a/docs/guides/index.md +++ b/docs/guides/index.md @@ -83,3 +83,9 @@ details, see [API reference](../api-reference/index.md). | Run agents as separate services | [Agent service runtime](./agent-service-runtime.md) | | Enable reusable runtime infrastructure | [Extensions](./extensions.md) | | Write, test, and package an extension | [Author extensions](./extension-authoring.md) | + +## Troubleshoot + +| Goal | Guide | +| ----------------------------------- | --------------------------------- | +| Look up an error slug you were shown | [Error reference](./errors.md) | diff --git a/scripts/docs/generate-error-reference.ts b/scripts/docs/generate-error-reference.ts new file mode 100644 index 0000000000..5abfb7fbce --- /dev/null +++ b/scripts/docs/generate-error-reference.ts @@ -0,0 +1,226 @@ +#!/usr/bin/env -S deno run --allow-read --allow-write --allow-run --allow-env +/** + * Error Reference Generator + * + * Every boundary that reports a VeryfrontError prints a documentation URL built + * from the error's slug (see src/errors/diagnostic-policy.ts). That URL has to + * land somewhere real, so the destination page is generated from the same + * registry the URL is built from — the page cannot drift behind a newly + * registered error. + * + * Usage: + * deno task docs:errors (regenerate docs/guides/errors.md) + * deno task docs:errors:check (fail if the committed page is stale) + */ + +import { ERROR_REGISTRY, getAllSlugs } from "../../src/errors/error-registry.ts"; +import { ERROR_DOCS_BASE_URL } from "../../src/errors/diagnostic-policy.ts"; +import type { ErrorCategory } from "../../src/errors/types.ts"; + +const CHECK_MODE = Deno.args.includes("--check"); + +const ROOT = Deno.cwd(); +const OUTPUT_PATH = `${ROOT}/docs/guides/errors.md`; + +/** + * Section heading and blurb per category, in the order they appear on the page. + * Categories are listed explicitly so a new one fails generation loudly rather + * than silently dropping its errors off the page. + */ +const CATEGORY_SECTIONS: ReadonlyArray< + { category: ErrorCategory; title: string; blurb: string } +> = [ + { + category: "CONFIG", + title: "Configuration", + blurb: "Raised while loading or validating project configuration.", + }, + { + category: "BUILD", + title: "Build", + blurb: "Raised while compiling, bundling, or transforming project source.", + }, + { + category: "RUNTIME", + title: "Runtime", + blurb: "Raised while executing project code.", + }, + { + category: "ROUTE", + title: "Routing", + blurb: "Raised while matching or handling a route.", + }, + { + category: "MODULE", + title: "Modules", + blurb: "Raised while resolving or loading a module.", + }, + { + category: "SERVER", + title: "Server", + blurb: "Raised by the dev server, the request pipeline, or a backing service.", + }, + { + category: "BOUNDARY", + title: "Server and client boundary", + blurb: "Raised when server-only and client-only code are mixed incorrectly.", + }, + { + category: "DEV", + title: "Development tooling", + blurb: "Raised by the local development workflow.", + }, + { + category: "DEPLOY", + title: "Deployment", + blurb: "Raised while building, uploading, or activating a deployment.", + }, + { + category: "AGENT", + title: "Agents", + blurb: "Raised while running an agent, tool, or workflow.", + }, + { + category: "GENERAL", + title: "General", + blurb: "Raised anywhere; these are not specific to one subsystem.", + }, +]; + +interface RegistryEntry { + slug: string; + category: ErrorCategory; + status: number; + title: string; + suggestion?: string; + exitCode?: number; +} + +function registryEntries(): RegistryEntry[] { + const registry = ERROR_REGISTRY as unknown as Record; + return getAllSlugs().map((slug) => registry[slug as string]); +} + +/** + * Escape the characters MDX treats as markup. + * + * The published pages are rendered as MDX, so registry text such as + * "--port " would parse as an unclosed JSX tag and fail the docs + * build. A backslash escape renders as the literal character in both MDX and + * plain Markdown. + */ +export function escapeMdxText(value: string): string { + return value.replace(/[<{]/g, "\\$&"); +} + +function renderEntry(entry: RegistryEntry): string { + const lines = [ + `### ${entry.slug}`, + "", + `${escapeMdxText(entry.title)}.`, + "", + `- **HTTP status:** ${entry.status}`, + ]; + if (entry.exitCode !== undefined) { + lines.push(`- **CLI exit code:** ${entry.exitCode}`); + } + if (entry.suggestion) { + lines.push(`- **What to do:** ${escapeMdxText(entry.suggestion)}`); + } + return lines.join("\n"); +} + +function renderPage(): string { + const entries = registryEntries(); + const known = new Set(CATEGORY_SECTIONS.map((section) => section.category)); + const unknown = entries.filter((entry) => !known.has(entry.category)); + if (unknown.length > 0) { + const detail = unknown.map((entry) => `${entry.slug} (${entry.category})`).join(", "); + throw new Error( + `No page section is defined for these error categories: ${detail}. ` + + `Add the category to CATEGORY_SECTIONS in ${import.meta.url}.`, + ); + } + + const blocks: string[] = [ + `--- +title: "Error reference" +description: "Every error the Veryfront CLI, server, and logs can report, with what it means and what to do next." +order: 46 +--- + +Veryfront reports errors with a stable slug, such as \`port-in-use\`. The CLI, the +HTTP response body, and the server logs all print that slug alongside a link to +this page, so you can jump straight to the entry for the error you hit. + +Each entry lists the HTTP status the error maps to, the process exit code when +it reaches the CLI, and the first thing to try. + +This page is generated from the framework's error registry, so it always lists +every error the current release can report.`, + ]; + + for (const section of CATEGORY_SECTIONS) { + const inSection = entries.filter((entry) => entry.category === section.category); + if (inSection.length === 0) continue; + blocks.push(`## ${section.title}\n\n${section.blurb}`); + for (const entry of inSection) blocks.push(renderEntry(entry)); + } + + return `${blocks.join("\n\n")}\n`; +} + +async function formatMarkdown(path: string): Promise { + const command = new Deno.Command("deno", { + args: ["fmt", `--config=${ROOT}/deno.json`, path], + stdout: "null", + stderr: "piped", + }); + const output = await command.output(); + if (!output.success) { + // Silently skipping this would write an unformatted page and, in --check + // mode, compare against an unformatted expectation -- reporting "current" + // for a page that fails `deno fmt --check`. + const stderr = new TextDecoder().decode(output.stderr).trim(); + throw new Error( + `deno fmt failed for ${path} (exit code ${output.code})${stderr ? `:\n${stderr}` : ""}`, + ); + } +} + +// Importing this module (the regression test reuses escapeMdxText) must not +// rewrite the committed page, so generation only runs as a program. +if (import.meta.main) await main(); + +async function main(): Promise { + const page = renderPage(); + + if (CHECK_MODE) { + const tempPath = await Deno.makeTempFile({ + prefix: "veryfront-error-reference-check-", + suffix: ".md", + }); + try { + await Deno.writeTextFile(tempPath, page); + await formatMarkdown(tempPath); + const expected = await Deno.readTextFile(tempPath); + const committed = await Deno.readTextFile(OUTPUT_PATH).catch(() => null); + if (committed !== expected) { + console.error( + "docs/guides/errors.md is stale. Run `deno task docs:errors` and commit the result.", + ); + Deno.exit(1); + } + console.log(`docs/guides/errors.md is current (${getAllSlugs().length} errors).`); + } finally { + await Deno.remove(tempPath).catch(() => {}); + } + return; + } + + await Deno.writeTextFile(OUTPUT_PATH, page); + await formatMarkdown(OUTPUT_PATH); + console.log( + `Wrote docs/guides/errors.md (${getAllSlugs().length} errors, linked from ${ERROR_DOCS_BASE_URL}).`, + ); +} diff --git a/src/errors/README.md b/src/errors/README.md index c9fe7ebf92..9b11dc1f49 100644 --- a/src/errors/README.md +++ b/src/errors/README.md @@ -70,7 +70,7 @@ infrastructure details in user-facing fields. `type` field is the stable documentation URL: ```text -https://veryfront.com/docs/errors/ +https://veryfront.com/docs/code/guides/errors# ``` Choose the response helper based on the boundary: @@ -97,10 +97,9 @@ try { HTTP problem responses use `application/problem+json`. Custom error slugs are credential-scrubbed and encoded as one documentation URL -path segment. Separators, query and fragment markers, percent signs, and -malformed Unicode cannot escape that segment. Exact `.` and `..` slugs fall back -to `unknown-error` so URL normalization cannot leave the error documentation -path. +fragment. Separators, query and fragment markers, percent signs, and malformed +Unicode cannot escape that fragment, so a slug can never change the page the +link points at. Exact `.` and `..` slugs fall back to `unknown-error`. Diagnostic fields, stacks, structured context, serialized problem responses, production log records, and terminal renderings use shared size limits. diff --git a/src/errors/catalog/config-errors.test.ts b/src/errors/catalog/config-errors.test.ts index 1582b96e64..8f1481d2fb 100644 --- a/src/errors/catalog/config-errors.test.ts +++ b/src/errors/catalog/config-errors.test.ts @@ -50,7 +50,7 @@ describe("errors/catalog/config-errors", () => { it("should have docs URLs pointing to veryfront.com", () => { for (const solution of Object.values(CONFIG_ERROR_CATALOG)) { assertEquals( - solution.docs?.startsWith("https://veryfront.com/docs/errors/") ?? false, + solution.docs?.startsWith("https://veryfront.com/docs/code/guides/errors#") ?? false, true, `docs URL should start with veryfront.com for ${solution.slug}`, ); diff --git a/src/errors/catalog/factory.test.ts b/src/errors/catalog/factory.test.ts index 7fdc46dcf6..d21e95bcf3 100644 --- a/src/errors/catalog/factory.test.ts +++ b/src/errors/catalog/factory.test.ts @@ -16,7 +16,7 @@ describe("factory", () => { slug: "config-not-found", title: "Configuration file not found", message: "Veryfront could not find veryfront.config.js", - docs: "https://veryfront.com/docs/errors/config-not-found", + docs: "https://veryfront.com/docs/code/guides/errors#config-not-found", }); }); @@ -33,7 +33,7 @@ describe("factory", () => { "Fix TypeScript errors", "Run build again", ]); - expect(solution.docs).toBe("https://veryfront.com/docs/errors/build-failed"); + expect(solution.docs).toBe("https://veryfront.com/docs/code/guides/errors#build-failed"); }); it("should detach and freeze mutable configuration arrays", () => { @@ -65,7 +65,7 @@ describe("factory", () => { }); expect(solution.example).toBe(example); - expect(solution.docs).toBe("https://veryfront.com/docs/errors/config-invalid"); + expect(solution.docs).toBe("https://veryfront.com/docs/code/guides/errors#config-invalid"); }); it("should create error solution with tips", () => { @@ -76,7 +76,7 @@ describe("factory", () => { }); expect(solution.tips).toEqual(["Use a different port", "Stop the other process"]); - expect(solution.docs).toBe("https://veryfront.com/docs/errors/port-in-use"); + expect(solution.docs).toBe("https://veryfront.com/docs/code/guides/errors#port-in-use"); }); it("should create error solution with relatedErrors", () => { @@ -87,7 +87,9 @@ describe("factory", () => { }); expect(solution.relatedErrors).toEqual(["render-error", "component-error"]); - expect(solution.docs).toBe("https://veryfront.com/docs/errors/hydration-mismatch"); + expect(solution.docs).toBe( + "https://veryfront.com/docs/code/guides/errors#hydration-mismatch", + ); }); it("should auto-generate docs URL from error slug", () => { @@ -96,7 +98,7 @@ describe("factory", () => { message: "The requested module could not be found", }); - expect(solution.docs).toBe("https://veryfront.com/docs/errors/module-not-found"); + expect(solution.docs).toBe("https://veryfront.com/docs/code/guides/errors#module-not-found"); }); it("should allow custom docs URL override", () => { @@ -128,7 +130,7 @@ describe("factory", () => { example: 'fetch("/api/data")', tips: ["Use correct HTTP method"], relatedErrors: ["request-error"], - docs: "https://veryfront.com/docs/errors/api-error", + docs: "https://veryfront.com/docs/code/guides/errors#api-error", }); }); @@ -164,19 +166,19 @@ describe("factory", () => { it("should work with different error slug categories", () => { const cases: Array<[ErrorSlug, string]> = [ - ["config-not-found", "https://veryfront.com/docs/errors/config-not-found"], - ["build-failed", "https://veryfront.com/docs/errors/build-failed"], - ["render-error", "https://veryfront.com/docs/errors/render-error"], - ["route-conflict", "https://veryfront.com/docs/errors/route-conflict"], - ["module-not-found", "https://veryfront.com/docs/errors/module-not-found"], - ["port-in-use", "https://veryfront.com/docs/errors/port-in-use"], + ["config-not-found", "https://veryfront.com/docs/code/guides/errors#config-not-found"], + ["build-failed", "https://veryfront.com/docs/code/guides/errors#build-failed"], + ["render-error", "https://veryfront.com/docs/code/guides/errors#render-error"], + ["route-conflict", "https://veryfront.com/docs/code/guides/errors#route-conflict"], + ["module-not-found", "https://veryfront.com/docs/code/guides/errors#module-not-found"], + ["port-in-use", "https://veryfront.com/docs/code/guides/errors#port-in-use"], [ "client-boundary-violation", - "https://veryfront.com/docs/errors/client-boundary-violation", + "https://veryfront.com/docs/code/guides/errors#client-boundary-violation", ], - ["dev-server-error", "https://veryfront.com/docs/errors/dev-server-error"], - ["deployment-error", "https://veryfront.com/docs/errors/deployment-error"], - ["unknown-error", "https://veryfront.com/docs/errors/unknown-error"], + ["dev-server-error", "https://veryfront.com/docs/code/guides/errors#dev-server-error"], + ["deployment-error", "https://veryfront.com/docs/code/guides/errors#deployment-error"], + ["unknown-error", "https://veryfront.com/docs/code/guides/errors#unknown-error"], ]; for (const [slug, docs] of cases) { @@ -225,7 +227,7 @@ describe("factory", () => { title: "Build failed", message: "The build process encountered errors", steps: ["Check error messages", "Fix TypeScript errors"], - docs: "https://veryfront.com/docs/errors/build-failed", + docs: "https://veryfront.com/docs/code/guides/errors#build-failed", }); }); @@ -237,7 +239,7 @@ describe("factory", () => { ["Create config file"], ); - expect(solution.docs).toBe("https://veryfront.com/docs/errors/config-not-found"); + expect(solution.docs).toBe("https://veryfront.com/docs/code/guides/errors#config-not-found"); }); it("should handle empty steps array", () => { @@ -284,16 +286,22 @@ describe("factory", () => { it("should work with all error slug categories", () => { const cases: Array<[ErrorSlug, string]> = [ - ["config-invalid", "https://veryfront.com/docs/errors/config-invalid"], - ["bundle-error", "https://veryfront.com/docs/errors/bundle-error"], - ["hydration-mismatch", "https://veryfront.com/docs/errors/hydration-mismatch"], - ["invalid-route-file", "https://veryfront.com/docs/errors/invalid-route-file"], - ["import-resolution-error", "https://veryfront.com/docs/errors/import-resolution-error"], - ["hmr-error", "https://veryfront.com/docs/errors/hmr-error"], - ["server-only-in-client", "https://veryfront.com/docs/errors/server-only-in-client"], - ["fast-refresh-error", "https://veryfront.com/docs/errors/fast-refresh-error"], - ["platform-error", "https://veryfront.com/docs/errors/platform-error"], - ["invalid-argument", "https://veryfront.com/docs/errors/invalid-argument"], + ["config-invalid", "https://veryfront.com/docs/code/guides/errors#config-invalid"], + ["bundle-error", "https://veryfront.com/docs/code/guides/errors#bundle-error"], + ["hydration-mismatch", "https://veryfront.com/docs/code/guides/errors#hydration-mismatch"], + ["invalid-route-file", "https://veryfront.com/docs/code/guides/errors#invalid-route-file"], + [ + "import-resolution-error", + "https://veryfront.com/docs/code/guides/errors#import-resolution-error", + ], + ["hmr-error", "https://veryfront.com/docs/code/guides/errors#hmr-error"], + [ + "server-only-in-client", + "https://veryfront.com/docs/code/guides/errors#server-only-in-client", + ], + ["fast-refresh-error", "https://veryfront.com/docs/code/guides/errors#fast-refresh-error"], + ["platform-error", "https://veryfront.com/docs/code/guides/errors#platform-error"], + ["invalid-argument", "https://veryfront.com/docs/code/guides/errors#invalid-argument"], ]; for (const [slug, docs] of cases) { @@ -386,8 +394,8 @@ describe("factory", () => { message: "Config missing", }); - expect(simple.docs).toBe("https://veryfront.com/docs/errors/config-not-found"); - expect(full.docs).toBe("https://veryfront.com/docs/errors/config-not-found"); + expect(simple.docs).toBe("https://veryfront.com/docs/code/guides/errors#config-not-found"); + expect(full.docs).toBe("https://veryfront.com/docs/code/guides/errors#config-not-found"); expect(simple.docs).toBe(full.docs); }); @@ -427,12 +435,12 @@ describe("factory", () => { "Use useEffect for client-only code", ], relatedErrors: ["render-error", "component-error"], - docs: "https://veryfront.com/docs/errors/hydration-mismatch#hydration", + docs: "https://veryfront.com/docs/code/guides/errors#hydration-mismatch", }); expect(runtimeError.relatedErrors?.length).toBe(2); expect(runtimeError.docs).toBe( - "https://veryfront.com/docs/errors/hydration-mismatch#hydration", + "https://veryfront.com/docs/code/guides/errors#hydration-mismatch", ); }); }); diff --git a/src/errors/diagnostic-policy.ts b/src/errors/diagnostic-policy.ts index 64c43b26e9..798cf6eee8 100644 --- a/src/errors/diagnostic-policy.ts +++ b/src/errors/diagnostic-policy.ts @@ -12,7 +12,16 @@ export const ERROR_OUTPUT_MAX_LENGTH_CHARS = 64 * 1_024; /** Maximum source characters accepted for the error-docs path segment. */ export const ERROR_DOCS_SLUG_MAX_LENGTH_CHARS = 256; -export const ERROR_DOCS_BASE_URL = "https://veryfront.com/docs/errors/"; +/** + * Base for every error documentation link printed at a boundary. + * + * Slugs are anchors on one generated reference page, not separate pages: a + * registry entry carries only a title and a one-line suggestion, which is too + * little for a page of its own. docs/guides/errors.md is generated from the + * registry by scripts/docs/generate-error-reference.ts, and + * tests/docs/error-docs-links.test.ts asserts every slug has an anchor there. + */ +export const ERROR_DOCS_BASE_URL = "https://veryfront.com/docs/code/guides/errors#"; const TRUNCATION_MARKER = "...[truncated]"; const UNKNOWN_ERROR_SLUG = "unknown-error"; diff --git a/src/errors/error-registry.test.ts b/src/errors/error-registry.test.ts index f765c9ce2f..bfa5458cc7 100644 --- a/src/errors/error-registry.test.ts +++ b/src/errors/error-registry.test.ts @@ -252,7 +252,7 @@ describe("error-registry", () => { const rfc9457 = error.toRFC9457(); // Required fields - assertEquals(rfc9457.type, "https://veryfront.com/docs/errors/config-not-found"); + assertEquals(rfc9457.type, "https://veryfront.com/docs/code/guides/errors#config-not-found"); assertEquals(rfc9457.title, "Configuration file not found"); assertEquals(rfc9457.status, 404); assertEquals(rfc9457.category, "CONFIG"); @@ -292,7 +292,7 @@ describe("error-registry", () => { assertEquals( rfc9457.type, - `https://veryfront.com/docs/errors/${slug}`, + `https://veryfront.com/docs/code/guides/errors#${slug}`, `RFC 9457 type URI mismatch for ${slug}`, ); } @@ -302,7 +302,10 @@ describe("error-registry", () => { describe("getDocsUrl", () => { it("should return correct documentation URL", () => { const error = CONFIG_NOT_FOUND.create(); - assertEquals(error.getDocsUrl(), "https://veryfront.com/docs/errors/config-not-found"); + assertEquals( + error.getDocsUrl(), + "https://veryfront.com/docs/code/guides/errors#config-not-found", + ); }); it("should match RFC 9457 type field", () => { diff --git a/src/errors/http-error.test.ts b/src/errors/http-error.test.ts index 3a69cba525..6c3a181732 100644 --- a/src/errors/http-error.test.ts +++ b/src/errors/http-error.test.ts @@ -26,7 +26,7 @@ describe("http-error", () => { assertEquals(response.status, 500); assertEquals(response.headers.get("Content-Type"), PROBLEM_JSON_CONTENT_TYPE); - assertEquals(body.type, "https://veryfront.com/docs/errors/unknown-error"); + assertEquals(body.type, "https://veryfront.com/docs/code/guides/errors#unknown-error"); assertEquals(body.instance, "/api/build"); assertEquals(body.detail, undefined); assertEquals(JSON.stringify(body).includes("super-secret"), false); @@ -142,7 +142,7 @@ describe("http-error", () => { const body = await response.json(); assertEquals(response.status, 404); - assertEquals(body.type, "https://veryfront.com/docs/errors/config-not-found"); + assertEquals(body.type, "https://veryfront.com/docs/code/guides/errors#config-not-found"); assertEquals(body.instance, undefined); }); @@ -158,7 +158,7 @@ describe("http-error", () => { const body = await response.json(); assertEquals(response.status, 404); - assertEquals(body.type, "https://veryfront.com/docs/errors/config-not-found"); + assertEquals(body.type, "https://veryfront.com/docs/code/guides/errors#config-not-found"); assertEquals(body.instance, undefined); }); @@ -195,7 +195,7 @@ describe("http-error", () => { const body = await response.json(); assertEquals(response.status, 500); - assertEquals(body.type, "https://veryfront.com/docs/errors/unknown-error"); + assertEquals(body.type, "https://veryfront.com/docs/code/guides/errors#unknown-error"); } }); @@ -211,7 +211,7 @@ describe("http-error", () => { const body = await response.json(); assertEquals(response.status, 500); - assertEquals(body.type, "https://veryfront.com/docs/errors/unknown-error"); + assertEquals(body.type, "https://veryfront.com/docs/code/guides/errors#unknown-error"); assertEquals(body.instance, "/safe"); }); diff --git a/src/errors/http-error.ts b/src/errors/http-error.ts index be7debd626..626e3c43ea 100644 --- a/src/errors/http-error.ts +++ b/src/errors/http-error.ts @@ -137,7 +137,7 @@ export function createErrorHandler() { * [ERROR] {slug} ({category}) - {title} * Detail: {detail} * Suggestion: {suggestion} - * Docs: https://veryfront.com/docs/errors/{slug} + * Docs: https://veryfront.com/docs/code/guides/errors#{slug} */ export function formatErrorLog(error: VeryfrontError): string { const snapshot = snapshotErrorForBoundary(error); diff --git a/src/errors/logging.test.ts b/src/errors/logging.test.ts index e44a9ba3dc..8ac26630c3 100644 --- a/src/errors/logging.test.ts +++ b/src/errors/logging.test.ts @@ -74,7 +74,10 @@ describe("logging", () => { output, "Suggestion: Create veryfront.config.js, veryfront.config.ts, or veryfront.config.mjs in the project root", ); - assertStringIncludes(output, "Docs: https://veryfront.com/docs/errors/config-not-found"); + assertStringIncludes( + output, + "Docs: https://veryfront.com/docs/code/guides/errors#config-not-found", + ); }); it("should include context when provided", () => { @@ -170,7 +173,7 @@ describe("logging", () => { assertEquals(parsed.title, "Configuration file not found"); assertEquals(parsed.detail, "Missing config file"); assertEquals(parsed.status, 404); - assertEquals(parsed.docs, "https://veryfront.com/docs/errors/config-not-found"); + assertEquals(parsed.docs, "https://veryfront.com/docs/code/guides/errors#config-not-found"); assertEquals(typeof parsed.timestamp, "string"); }); diff --git a/src/errors/middleware/cli-error-boundary.test.ts b/src/errors/middleware/cli-error-boundary.test.ts index f79392ad70..13c71834df 100644 --- a/src/errors/middleware/cli-error-boundary.test.ts +++ b/src/errors/middleware/cli-error-boundary.test.ts @@ -55,7 +55,10 @@ describe("cli-error-boundary", () => { assertMatch(output, /Docs:/); const docsLine = output.split("\n").find((line) => line.trimStart().startsWith("Docs:")); - assertEquals(docsLine?.trim(), "Docs: https://veryfront.com/docs/errors/config-not-found"); + assertEquals( + docsLine?.trim(), + "Docs: https://veryfront.com/docs/code/guides/errors#config-not-found", + ); }); it("should honor color-related environment variables by default", () => { diff --git a/src/errors/middleware/cli-error-boundary.ts b/src/errors/middleware/cli-error-boundary.ts index 2d95b67863..9bc3084e92 100644 --- a/src/errors/middleware/cli-error-boundary.ts +++ b/src/errors/middleware/cli-error-boundary.ts @@ -97,7 +97,7 @@ function createColorFormatters(useColor = shouldUseColor()): ColorFormatter { * Format: [slug] title * Detail: {detail} * Suggestion: {suggestion} - * Docs: https://veryfront.com/docs/errors/{slug} + * Docs: https://veryfront.com/docs/code/guides/errors#{slug} * (Stack trace in dev mode) */ export interface CLIErrorFormatOptions { diff --git a/src/errors/middleware/http-error-boundary.test.ts b/src/errors/middleware/http-error-boundary.test.ts index e05d068c91..c15bd6336e 100644 --- a/src/errors/middleware/http-error-boundary.test.ts +++ b/src/errors/middleware/http-error-boundary.test.ts @@ -58,7 +58,7 @@ describe("http-error-boundary", () => { assertEquals(result.response.headers.get("Content-Type"), PROBLEM_JSON_CONTENT_TYPE); const body = await result.response.json(); - assertEquals(body.type, "https://veryfront.com/docs/errors/config-not-found"); + assertEquals(body.type, "https://veryfront.com/docs/code/guides/errors#config-not-found"); assertEquals(body.title, "Configuration file not found"); assertEquals(body.status, 404); assertEquals(body.category, "CONFIG"); @@ -88,7 +88,7 @@ describe("http-error-boundary", () => { assertEquals(result.response.status, 500); const body = await result.response.json(); assertEquals(body.status, 500); - assertEquals(body.type, "https://veryfront.com/docs/errors/unknown-error"); + assertEquals(body.type, "https://veryfront.com/docs/code/guides/errors#unknown-error"); assertEquals(statusReads, 0); }); @@ -107,7 +107,7 @@ describe("http-error-boundary", () => { assertEquals(result.response.headers.get("Content-Type"), PROBLEM_JSON_CONTENT_TYPE); const body = await result.response.json(); - assertEquals(body.type, "https://veryfront.com/docs/errors/unknown-error"); + assertEquals(body.type, "https://veryfront.com/docs/code/guides/errors#unknown-error"); assertEquals(body.status, 500); assertEquals(body.category, "GENERAL"); assertEquals(body.detail, "Something went wrong"); @@ -130,7 +130,7 @@ describe("http-error-boundary", () => { assertExists(result.response); assertEquals(result.response.status, 500); const body = await result.response.json(); - assertEquals(body.type, "https://veryfront.com/docs/errors/unknown-error"); + assertEquals(body.type, "https://veryfront.com/docs/code/guides/errors#unknown-error"); } finally { recorder.recordError = originalRecordError; } @@ -151,7 +151,7 @@ describe("http-error-boundary", () => { assertExists(result.response); assertEquals(result.response.status, 500); const body = await result.response.json(); - assertEquals(body.type, "https://veryfront.com/docs/errors/unknown-error"); + assertEquals(body.type, "https://veryfront.com/docs/code/guides/errors#unknown-error"); } finally { trace.getActiveSpan = originalGetActiveSpan; } @@ -288,7 +288,7 @@ describe("http-error-boundary", () => { assertExists(result.response); assertEquals(result.response.status, 404); const body = await result.response.json(); - assertEquals(body.type, "https://veryfront.com/docs/errors/config-not-found"); + assertEquals(body.type, "https://veryfront.com/docs/code/guides/errors#config-not-found"); assertEquals(body.instance, undefined); assertEquals(urlReads, 0); }); @@ -450,7 +450,7 @@ describe("http-error-boundary", () => { assertExists(result.response); assertEquals(result.response.status, 500); const body = await result.response.json(); - assertEquals(body.type, "https://veryfront.com/docs/errors/unknown-error"); + assertEquals(body.type, "https://veryfront.com/docs/code/guides/errors#unknown-error"); assertEquals(JSON.stringify(body).includes("source-secret"), false); }); @@ -500,7 +500,7 @@ describe("http-error-boundary", () => { assertExists(result.response); assertEquals(result.response.status, 500); const body = await result.response.json(); - assertEquals(body.type, "https://veryfront.com/docs/errors/unknown-error"); + assertEquals(body.type, "https://veryfront.com/docs/code/guides/errors#unknown-error"); }); it("should preserve handler metadata", async () => { diff --git a/src/errors/safe-diagnostics.test.ts b/src/errors/safe-diagnostics.test.ts index a4ebb397ff..ac4a92db1b 100644 --- a/src/errors/safe-diagnostics.test.ts +++ b/src/errors/safe-diagnostics.test.ts @@ -14,6 +14,9 @@ import { } from "./safe-diagnostics.ts"; import { VeryfrontError } from "./types.ts"; +/** Path of the page error slugs anchor into; a slug must never change it. */ +const ERROR_DOCS_PATHNAME = new URL(ERROR_DOCS_BASE_URL).pathname; + describe("safe-diagnostics", () => { it("should neutralize terminal controls and line injection in one diagnostic field", () => { const malicious = "before\x1b]2;owned\x07\x1b[2J\nFAKE SUCCESS"; @@ -33,7 +36,7 @@ describe("safe-diagnostics", () => { assertEquals(sanitized.includes("\r"), false); }); - it("should encode a hostile slug as one credential-scrubbed docs path segment", () => { + it("should encode a hostile slug as one credential-scrubbed docs fragment", () => { const docsUrl = buildErrorDocsUrl( "../admin/path?token=secret#fragment%value\ud800", ); @@ -43,9 +46,14 @@ describe("safe-diagnostics", () => { docsUrl, `${ERROR_DOCS_BASE_URL}..%2Fadmin%2Fpath%3Ftoken%3D%5BREDACTED%5D%23fragment%25value%EF%BF%BD`, ); + // The slug is confined to the fragment: it cannot traverse to another + // path, open a query, or start a second fragment. assertEquals(parsed.search, ""); - assertEquals(parsed.hash, ""); - assert(parsed.pathname.startsWith("/docs/errors/")); + assertEquals(parsed.pathname, ERROR_DOCS_PATHNAME); + assertEquals( + parsed.hash, + "#..%2Fadmin%2Fpath%3Ftoken%3D%5BREDACTED%5D%23fragment%25value%EF%BF%BD", + ); assertEquals(docsUrl.includes("secret"), false); }); @@ -58,11 +66,11 @@ describe("safe-diagnostics", () => { docsUrl, `${ERROR_DOCS_BASE_URL}unknown-error`, ); - assert(parsed.pathname.startsWith("/docs/errors/")); + assertEquals(parsed.pathname, ERROR_DOCS_PATHNAME); } }); - it("should align the bounded boundary slug with its docs path segment", () => { + it("should align the bounded boundary slug with its docs fragment", () => { const error = new VeryfrontError("Vendor error", { slug: `vendor-${"x".repeat(ERROR_DOCS_SLUG_MAX_LENGTH_CHARS + 100)}`, category: "GENERAL", @@ -70,12 +78,10 @@ describe("safe-diagnostics", () => { title: "Vendor error", }); const snapshot = snapshotErrorForBoundary(error); - const docsSegment = new URL(buildErrorDocsUrl(error.slug)).pathname.slice( - "/docs/errors/".length, - ); + const docsFragment = new URL(buildErrorDocsUrl(error.slug)).hash.slice(1); assertEquals(snapshot.slug.length, ERROR_DOCS_SLUG_MAX_LENGTH_CHARS); - assertEquals(decodeURIComponent(docsSegment), snapshot.slug); + assertEquals(decodeURIComponent(docsFragment), snapshot.slug); }); it("should preserve an explicit CLI exit code at the boundary", () => { diff --git a/src/errors/types.test.ts b/src/errors/types.test.ts index d99dc3c17b..da049de078 100644 --- a/src/errors/types.test.ts +++ b/src/errors/types.test.ts @@ -4,6 +4,7 @@ import { describe, it } from "#veryfront/testing/bdd.ts"; import { defineError, isVeryfrontErrorInstance, VeryfrontError } from "./types.ts"; import type { ErrorSlug } from "./error-registry.ts"; import { ERROR_DIAGNOSTIC_MAX_LENGTH_CHARS } from "./safe-diagnostics.ts"; +import { ERROR_DOCS_BASE_URL } from "./diagnostic-policy.ts"; describe("errors/types", () => { describe("defineError", () => { @@ -145,7 +146,7 @@ describe("errors/types", () => { }); const rfc9457 = err.toRFC9457(); - assertEquals(rfc9457.type, "https://veryfront.com/docs/errors/render-error"); + assertEquals(rfc9457.type, "https://veryfront.com/docs/code/guides/errors#render-error"); assertEquals(rfc9457.title, "Render error"); assertEquals(rfc9457.status, 500); assertEquals(rfc9457.category, "RUNTIME"); @@ -168,7 +169,10 @@ describe("errors/types", () => { const problem = err.toRFC9457(); assertEquals(parsedDocsUrl.search, ""); - assertEquals(parsedDocsUrl.hash, ""); + // The hostile slug is confined to the fragment: it cannot change the + // page it points at, nor open a query or a second fragment. + assertEquals(parsedDocsUrl.pathname, new URL(ERROR_DOCS_BASE_URL).pathname); + assertEquals(parsedDocsUrl.hash.slice(1).includes("#"), false); assert(docsUrl.includes("%2F")); assert(docsUrl.includes("%3F")); assert(docsUrl.includes("%23")); diff --git a/src/errors/user-friendly/error-catalog.test.ts b/src/errors/user-friendly/error-catalog.test.ts index 19175a0763..9d7ad7594e 100644 --- a/src/errors/user-friendly/error-catalog.test.ts +++ b/src/errors/user-friendly/error-catalog.test.ts @@ -105,7 +105,7 @@ describe("ERROR_SOLUTIONS", () => { assertExists(sol.docs); assertEquals( sol.docs, - "https://veryfront.com/docs/errors/client-boundary-violation", + "https://veryfront.com/docs/code/guides/errors#client-boundary-violation", ); }); }); diff --git a/src/errors/user-friendly/error-catalog.ts b/src/errors/user-friendly/error-catalog.ts index fa05d5f94b..910e4d3e2d 100644 --- a/src/errors/user-friendly/error-catalog.ts +++ b/src/errors/user-friendly/error-catalog.ts @@ -1,4 +1,5 @@ import type { ErrorSolution as CatalogErrorSolution } from "../catalog/types.ts"; +import { buildErrorDocsUrl } from "../diagnostic-policy.ts"; export type ErrorSolution = Pick; @@ -70,7 +71,7 @@ export default async function ServerComponent() { 'use client'; export default function ClientComponent({ data }) { }`, - docs: "https://veryfront.com/docs/errors/client-boundary-violation", + docs: buildErrorDocsUrl("client-boundary-violation"), }, "import-not-found": { diff --git a/src/server/handlers/request/agent-stream.handler.test.ts b/src/server/handlers/request/agent-stream.handler.test.ts index 423d43c546..e0d8ff9641 100644 --- a/src/server/handlers/request/agent-stream.handler.test.ts +++ b/src/server/handlers/request/agent-stream.handler.test.ts @@ -2953,7 +2953,7 @@ describe("server/handlers/request/agent-stream.handler", () => { assertEquals(result.response.headers.get("content-type"), "application/problem+json"); assertEquals( (await result.response.json()).type, - "https://veryfront.com/docs/errors/permission-denied", + "https://veryfront.com/docs/code/guides/errors#permission-denied", ); assertEquals(discoveryCalls, 0); assertEquals(redirect, "error"); diff --git a/src/server/handlers/request/api/api-handler-wrapper.test.ts b/src/server/handlers/request/api/api-handler-wrapper.test.ts index 0baebd3545..0ea4974d51 100644 --- a/src/server/handlers/request/api/api-handler-wrapper.test.ts +++ b/src/server/handlers/request/api/api-handler-wrapper.test.ts @@ -333,7 +333,7 @@ describe("ApiHandlerWrapper", () => { const problem = await result.response!.json(); assertEquals( problem.type, - "https://veryfront.com/docs/errors/project-execution-unavailable", + "https://veryfront.com/docs/code/guides/errors#project-execution-unavailable", ); }); diff --git a/src/server/handlers/request/module/module.handler.test.ts b/src/server/handlers/request/module/module.handler.test.ts index 35d1e23586..65705f31a0 100644 --- a/src/server/handlers/request/module/module.handler.test.ts +++ b/src/server/handlers/request/module/module.handler.test.ts @@ -249,7 +249,7 @@ describe("server/handlers/request/module/module.handler", () => { assertEquals(result.response?.headers.get("content-type"), "application/problem+json"); assertEquals( (await result.response?.json() as { type?: string }).type, - "https://veryfront.com/docs/errors/project-execution-unavailable", + "https://veryfront.com/docs/code/guides/errors#project-execution-unavailable", ); } @@ -292,7 +292,7 @@ describe("server/handlers/request/module/module.handler", () => { ) : undefined; assertEquals( - type === "https://veryfront.com/docs/errors/project-execution-unavailable", + type === "https://veryfront.com/docs/code/guides/errors#project-execution-unavailable", false, `${pathname} denied execution to a granted host`, ); diff --git a/src/server/handlers/request/ssr/ssr.handler.test.ts b/src/server/handlers/request/ssr/ssr.handler.test.ts index e0d5e9ae55..1b47e07d31 100644 --- a/src/server/handlers/request/ssr/ssr.handler.test.ts +++ b/src/server/handlers/request/ssr/ssr.handler.test.ts @@ -158,7 +158,7 @@ describe("server/handlers/request/ssr/ssr.handler", () => { assertEquals(result.response?.headers.get("content-type"), "application/problem+json"); assertEquals( (await result.response?.json() as { type?: string }).type, - "https://veryfront.com/docs/errors/project-execution-unavailable", + "https://veryfront.com/docs/code/guides/errors#project-execution-unavailable", ); assertEquals(renderCalls, 0); }); diff --git a/src/server/runtime-handler/timeout-manager.test.ts b/src/server/runtime-handler/timeout-manager.test.ts index 86c8fd6f9e..1a4a5ef3e8 100644 --- a/src/server/runtime-handler/timeout-manager.test.ts +++ b/src/server/runtime-handler/timeout-manager.test.ts @@ -68,7 +68,7 @@ describe("timeout-manager", () => { assertEquals(response.status, 403); assertEquals(response.headers.get("content-type"), "application/problem+json"); assertEquals(await response.json(), { - type: "https://veryfront.com/docs/errors/permission-denied", + type: "https://veryfront.com/docs/code/guides/errors#permission-denied", title: "File/resource permission denied", status: 403, detail: "Project credential is not authorized for the requested environment", diff --git a/src/server/services/rsc/endpoints/endpoint-router.test.ts b/src/server/services/rsc/endpoints/endpoint-router.test.ts index b418933757..e6dac77df8 100644 --- a/src/server/services/rsc/endpoints/endpoint-router.test.ts +++ b/src/server/services/rsc/endpoints/endpoint-router.test.ts @@ -230,7 +230,7 @@ describe("server/services/rsc/endpoints/endpoint-router", () => { assertEquals(result?.headers.get("content-type"), "application/problem+json"); assertEquals( (await result?.json() as { type?: string }).type, - "https://veryfront.com/docs/errors/project-execution-unavailable", + "https://veryfront.com/docs/code/guides/errors#project-execution-unavailable", ); }); } diff --git a/src/server/services/rsc/endpoints/rsc-bundles.generated.ts b/src/server/services/rsc/endpoints/rsc-bundles.generated.ts index f2f38d9e1f..f7dcf0e1e0 100644 --- a/src/server/services/rsc/endpoints/rsc-bundles.generated.ts +++ b/src/server/services/rsc/endpoints/rsc-bundles.generated.ts @@ -7,7 +7,7 @@ */ export const CLIENT_BOOT_BUNDLE: string = - 'var at=Object.defineProperty;var ct=(e,t,n)=>t in e?at(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var m=(e,t,n)=>ct(e,typeof t!="symbol"?t+"":t,n);var Ar=Array.prototype.at,Tr=Array.prototype.filter,lt=Array.prototype.join,br=Array.prototype.map,Cr=Array.prototype.pop,dt=Array.prototype.push,wr=Array.prototype.sort,Ae=Reflect.apply;function z(e,t){return Ae(lt,e,[t])}function O(e,t){Ae(dt,e,[t])}var ut="3.2.3",ft=Object.entries;function gt(e){let t=[];if(e?.external?.length&&O(t,`external=${z(e.external,",")}`),O(t,`target=${e?.target??"es2022"}`),e?.deps){let n=[],r=ft(e.deps);for(let o=0;ot||n?.(r,...o)}debug(t,...n){this.log(0,console.debug,`[${this.prefix}] DEBUG: ${t}`,...n)}info(t,...n){this.log(1,console.log,`[${this.prefix}] ${t}`,...n)}warn(t,...n){this.log(2,console.warn,`[${this.prefix}] WARN: ${t}`,...n)}error(t,...n){this.log(3,console.error,`[${this.prefix}] ERROR: ${t}`,...n)}};function wt(){if(typeof window>"u")return 2;let e=globalThis;return e.__VERYFRONT_DEV__||e.__RSC_DEV__?e.__VERYFRONT_DEBUG__||e.__RSC_DEBUG__?0:1:2}var G=wt(),u=new b("RSC",G),eo=new b("PREFETCH",G),to=new b("HYDRATE",G),no=new b("VERYFRONT",G);var Dt="veryfront-hydration-data";function de(e){try{let t=[...e.querySelectorAll(`[id="${Dt}"]`)];if(t.length!==1)return null;let n=e.body;if(!n)return null;let r=t[0];return n.firstElementChild!==r&&r.parentElement!==n||r.tagName?.toLowerCase()!=="script"||r.getAttribute("type")?.trim().toLowerCase()!=="application/json"?null:r}catch{return null}}function C(e=document){try{let t=de(e);return t?JSON.parse(t.textContent||"{}"):null}catch(t){return u.debug("hydration data parse failed",t),null}}function W(e,t){if(!t?.startsWith("on:"))return!1;try{let n=de(e);if(!n)return!1;let r=JSON.parse(n.textContent||"{}");return r.dependencyPinningCacheKey=t,n.textContent=JSON.stringify(r),!0}catch(n){return u.debug("hydration dependency snapshot seed failed",n),!1}}function K(e){return e?.clientModuleStrategy?e.clientModuleStrategy:e?.dev?"fs":"rsc-module"}function Nt(e,t){if(!t)return e;let n=e.includes("?")?"&":"?";return`${e}${n}v=${encodeURIComponent(t)}`}function Y(e,t){if(!t?.startsWith("on:"))return e;let n=e.indexOf("#"),r=n===-1?"":e.slice(n),o=n===-1?e:e.slice(0,n),i=o.indexOf("?"),s=i===-1?o:o.slice(0,i),a=new URLSearchParams(i===-1?"":o.slice(i+1));a.set("pins",t);let l=a.toString();return`${s}${l?`?${l}`:""}${r}`}function Mt(e,t){return Nt(`${Ne}${ae(e)}.js`,t)}function Ot(e,t,n){let r=t?`&v=${encodeURIComponent(t)}`:"";return Y(`${P}module?rel=${encodeURIComponent(e)}${r}`,n)}function L(e){let t=e?.dependencyPinningCacheKey;return t?.startsWith("on:")?{[j]:t}:{}}function It(e){return e.replace(/^\\/+_vf_modules\\//,"").replace(/^\\/+/,"").replace(/\\.js$/,"")}var Pt=/\\.(tsx|ts|jsx|mdx|js)$/;function Ht(e){let t=It(e),n=[e,t];return Pt.test(t)||n.push(`${t}.tsx`,`${t}.ts`,`${t}.jsx`,`${t}.mdx`,`${t}.js`),Array.from(new Set(n))}function Lt(e,t){if(!e)return null;for(let n of Ht(t)){let r=e[n];if(r)return r}return null}function X(e){if(e.strategy==="fs"){let n=e.absPath??e.rel;return n?Y(Mt(n,e.version),e.dependencyPinningCacheKey):null}let t=Lt(e.releaseAssetModules,e.rel);return t||Ot(e.rel,e.version,e.dependencyPinningCacheKey)}function J(e=document,t=I){let n=ce(e);return{react:B("react",n)?"react":be(t),reactDomClient:B("react-dom/client",n)?"react-dom/client":Ce(t)}}function Me(e=document){let t=ce(e);return B("veryfront/router",t)?"veryfront/router":null}var q={reset:"\\x1B[0m",dim:"\\x1B[2m",gray:"\\x1B[90m",red:"\\x1B[31m",green:"\\x1B[32m",yellow:"\\x1B[33m",blue:"\\x1B[34m",magenta:"\\x1B[35m",cyan:"\\x1B[36m"},po={debug:q.gray,info:q.green,warn:q.yellow,error:q.red};var y="[REDACTED]",p=Reflect.apply,Ut=Array.prototype.pop,$t=Array.prototype.push;var mo=Array.prototype,ho=BigInt.prototype.toString,Le=Map,kt=Map.prototype.delete,vt=Map.prototype.get,Ft=Map.prototype.keys,Vt=Map.prototype.set;var _=Object.getOwnPropertyDescriptor,zt=Object.getPrototypeOf,Eo=Object.hasOwn,Ro=Object.prototype,Bt=Set,jt=decodeURIComponent,T=URL,_o=Number.isFinite,xo=Number.isInteger,ue=RegExp.prototype.exec,Gt=_(RegExp.prototype,"global").get,Wt=_(RegExp.prototype,"unicode").get,Kt=String.prototype.charCodeAt,Yt=String.prototype.includes,Xt=String.prototype.indexOf,Oe=String.prototype.slice,Ue=String.prototype.startsWith,$e=String.prototype.toLowerCase,Jt=Set.prototype.add,So=Set.prototype.delete,qt=Set.prototype.has,Zt=zt(new Le().keys()).next,Qt=_(Map.prototype,"size").get,Ao=_(T.prototype,"host").get,To=_(T.prototype,"origin").get,en=_(T.prototype,"password").get,bo=_(T.prototype,"pathname").get,Co=_(T.prototype,"protocol").get,tn=_(T.prototype,"username").get,nn=/[^a-z0-9]/g,rn=/([a-z0-9])([A-Z])/g,on=/([A-Z])([A-Z][a-z])/g,sn=/\\b(?:sk-[A-Za-z0-9._-]{8,}|gh[po]_[A-Za-z0-9._-]{8,}|xox[baprs]-[A-Za-z0-9._-]{8,}|eyJ[A-Za-z0-9._-]{8,})\\b/g;function R(e,t,n){let r=p(Gt,t,[]),o=p(Wt,t,[]),i=0,s=!1,a="";t.lastIndex=0;try{for(;;){let l=p(ue,t,[e]);if(l===null)break;let c=l[0],d=l.index;if(a+=A(e,i,d),a+=typeof n=="string"?n:n(l),i=d+c.length,s=!0,!r)break;c.length===0&&(t.lastIndex=an(e,d,o))}}finally{t.lastIndex=0}return s?a+A(e,i):e}function fe(e){let t=p($e,e,[]);return R(t,nn,"")}function w(e,t){return p(Kt,e,[t])}function an(e,t,n){let r=t+1;if(!n||r>=e.length)return r;let o=w(e,t);if(o<55296||o>56319)return r;let i=w(e,r);return i>=56320&&i<=57343?t+2:r}function A(e,t,n){return n===void 0?p(Oe,e,[t]):p(Oe,e,[t,n])}function cn(e){let t=[],n=0;for(let r=0;r<=e.length;r++){let o=r===e.length?-1:w(e,r);o>=97&&o<=122||o>=48&&o<=57||(r>n&&(t[t.length]=A(e,n,r)),n=r+1)}return t}var Z=["password","passwd","pwd","passphrase","secret","clientsecret","token","apikey","accesskey","privatekey","credential","authheader","authorization","cookie","bearer","jwt","connectionstring","signature","sessionid","sid","otp","mfa","pin","salt","xsrf","csrf"],ln=512,dn=128,U=new Le;var un=256;function fn(e){let t=e.length<=dn;if(t){let o=p(vt,U,[e]);if(o!==void 0)return o}let n=fe(e),r=n==="auth";for(let o=0;!r&&o=ln){let i=p(Ft,U,[]),s=p(Zt,i,[]).value;s!==void 0&&p(kt,U,[s])}p(Vt,U,[e,r])}return r}var Ie=["access_token","accesstoken","refresh_token","api_key","apikey","code","token","secret","client_secret","password","passwd","pwd","state","sig","signature","auth","x-amz-credential","x-amz-signature","x-amz-security-token","x-goog-credential","x-goog-signature"],ke=new Bt;for(let e=0;e=65&&t<=90||t>=97&&t<=122}function ve(e){return hn(e)||e==="_"||e==="$"}function En(e){if(!e)return!1;let t=w(e,0);return ve(e)||t>=48&&t<=57||e==="."||e==="-"}function Fe(e,t){let n=t,r=e[n]===\'"\'||e[n]==="\'"?e[n++]:"";if(!ve(e[n]))return!1;for(n++;En(e[n]);)n++;if(r){if(e[n]!==r)return!1;n++}for(;e[n]===" "||e[n]==="\t";)n++;return e[n]===":"||e[n]==="="}function Ve(e){return e==="\\r"||e===`\n`||e==="}"||e==="]"||mn(e)}function ze(e,t){let n=t;for(;n=e.length||Fe(e,n)}function Rn(e,t){let n=t,r=!0;if(p(Ue,e,[y,t])){let d=t+y.length;if(Pe(e,d))return{end:d,replacement:y};n=d,r=!1}let o=r&&(e[n]===\'"\'||e[n]==="\'"||e[n]==="`")?e[n]:"",i=!1,s=()=>o?`${o}${y}${i?o:""}`:y,a=[],l="",c=-1;for(let d=n;d0&&(f==="}"||f==="]")){if(a[a.length-1]!==f)return{end:e.length,replacement:s()};if(p(Ut,a,[]),d++,a.length===0&&Pe(e,d))return{end:d,replacement:s()};continue}if(a.length>0||!Ve(f)){d++;continue}let E=d;if(d=ze(e,d),d>=e.length||Fe(e,d))return{end:E,replacement:s()}}return{end:e.length,replacement:s()}}function He(e,t,n,r){let o=0,i="";for(let s=p(ue,t,[e]);s;s=p(ue,t,[e])){let a=s[n];if(!_n(a))continue;let l=t.lastIndex,c=r===void 0?void 0:s[r],d=l+y.length;if((c==="?"||c==="&"||c===";")&&p(Ue,e,[y,l])&&e[d]==="#")continue;let f=Rn(e,l);i+=A(e,o,s.index),i+=s[0],i+=f.replacement,o=f.end,t.lastIndex=f.end}return o===0?e:i+A(e,o)}function _n(e){if(e.length>un)return!0;let t=R(e,on,i=>`${i[1]} ${i[2]}`),n=R(t,rn,i=>`${i[1]} ${i[2]}`),r=p($e,n,[]),o=cn(r);for(let i=0;i{let r=n[1],o=n[2],i=p(Xt,o,[":"]);if(i===-1)return`${r}${y}@`;let s=A(o,0,i);return`${r}${s}:${y}@`});return t=R(t,pn,n=>{let r=n[1],o=n[2],i=n[3];return xn(r,o,i)?n[0]:`${r}${o}:${y}@`}),t=R(t,/([?#&;])([-a-z0-9_.%\\[\\]]+)=([^&#;\\s]*)/gi,n=>{let r=n[1],o=n[2],i=Sn(o);return p(qt,ke,[fe(i)])||fn(i)?`${r}${o}=${y}`:n[0]}),t=R(t,/(^|[^a-z0-9_-])((?:set-cookie|cookie)\\s*:\\s*)[^\\r\\n]*/gi,n=>`${n[1]}${n[2]}${y}`),t=R(t,/\\b(authorization\\s*[:=]\\s*)[^\\r\\n]*/gi,n=>`${n[1]}${y}`),t=R(t,/\\b(bearer|basic)(\\s+)(?:"[^"\\r\\n]*"|\'[^\'\\r\\n]*\'|[a-z0-9._~+/=-]+)/gi,n=>`${n[1]}${n[2]}${y}`),t=R(t,sn,y),t=He(t,/(["\'])([_$a-z][a-z0-9_.$-]*)\\1(\\s*[:=]\\s*)/gi,2),t=He(t,/(^|[^a-z0-9_.$-])([_$a-z][a-z0-9_.$-]*)(\\s*[:=]\\s*)/gi,2,1),t}var An=2048;var Oo=64*1024,Tn=256,bn="https://veryfront.com/docs/errors/",Be="...[truncated]",pe="unknown-error";function je(e,t){if(e.length<=t)return e;let n=Math.max(0,t-Be.length);return`${Cn(e,n)}${Be}`}function Cn(e,t){let n=e.slice(0,t),r=n.charCodeAt(n.length-1);return r>=55296&&r<=56319&&(n=n.slice(0,-1)),n}function wn(e){let t="";for(let n=0;n=55296&&r<=56319){let o=e.charCodeAt(n+1);o>=56320&&o<=57343?(t+=e.slice(n,n+2),n++):t+="\\uFFFD";continue}t+=r>=56320&&r<=57343?"\\uFFFD":e.charAt(n)}return t}function D(e){return typeof e!="string"?y:je(ge(e),An)}function Dn(e){let t=typeof e=="string"?ge(e):pe,n=je(t||pe,Tn),r=wn(n);return r==="."||r===".."?pe:r}function Q(e){let t=encodeURIComponent(Dn(e));return`${bn}${t}`}var Ke=Reflect.apply,Nn=Object.freeze,Mn=Object.getOwnPropertyDescriptors,Ge=Number.isFinite,Ye=new WeakSet,On=WeakSet.prototype.add,In=WeakSet.prototype.has,Pn=new Set(["CONFIG","BUILD","RUNTIME","ROUTE","MODULE","SERVER","BOUNDARY","DEV","DEPLOY","AGENT","GENERAL"]);function h(e){let t={...e},n={...t,create(r){let o=r?.message,i=r?.detail,s=r?.cause,a=r?.instance,l=r?.context,c=r?.status??t.status;return new ye(o||i||t.title,{slug:t.slug,category:t.category,status:c,title:t.title,suggestion:t.suggestion,exitCode:t.exitCode,detail:i,cause:s,instance:a,context:l})}};return Nn(n)}var ye=class extends Error{constructor(n,r){super(n);m(this,"slug");m(this,"category");m(this,"status");m(this,"title");m(this,"suggestion");m(this,"exitCode");m(this,"detail");m(this,"cause");m(this,"instance");m(this,"context");Ke(On,Ye,[this]),this.name="VeryfrontError",this.slug=r.slug,this.category=r.category,this.status=r.status,this.title=r.title,this.suggestion=r.suggestion,this.exitCode=r.exitCode,this.detail=r.detail,this.cause=r.cause,this.instance=r.instance,this.context=r.context}toRFC9457(){let n=We(this);return n?{type:Q(n.slug),title:D(n.title),status:n.status,detail:n.detail===void 0?void 0:D(n.detail),instance:n.instance===void 0?void 0:D(n.instance),category:n.category,suggestion:n.suggestion===void 0?void 0:D(n.suggestion),cause:typeof n.cause=="string"?D(n.cause):void 0}:{type:Q("unknown-error"),title:"Unknown/unclassified error",status:500,category:"GENERAL"}}getDocsUrl(){let n=We(this);return Q(n?.slug??"unknown-error")}};function Xe(e){return typeof e=="object"&&e!==null&&Ke(In,Ye,[e])===!0}function We(e){return Xe(e)?Hn(e):null}function Hn(e){try{if(!Xe(e))return null;let t=Mn(e),n=re=>{let M=t[re];return M&&"value"in M?M.value:void 0},r=n("slug"),o=n("category"),i=n("status"),s=n("title"),a=n("message"),l=n("suggestion"),c=n("exitCode"),d=n("detail"),f=n("cause"),E=n("instance"),v=n("context"),x=n("stack");return typeof r!="string"||!Pn.has(o)||typeof i!="number"||!Ge(i)||typeof s!="string"||typeof a!="string"||l!==void 0&&typeof l!="string"||c!==void 0&&(typeof c!="number"||!Ge(c))||d!==void 0&&typeof d!="string"||E!==void 0&&typeof E!="string"||x!==void 0&&typeof x!="string"?null:{slug:r,category:o,status:i,title:s,message:a,suggestion:l,exitCode:c,detail:d,cause:f,instance:E,context:v,stack:x}}catch{return null}}var $o=h({slug:"unknown-error",category:"GENERAL",status:500,title:"Unknown/unclassified error",suggestion:"Check logs for more details"}),ko=h({slug:"authentication-required",category:"GENERAL",status:401,title:"Authentication required",suggestion:"Set VERYFRONT_API_TOKEN or run \'veryfront login\'"}),vo=h({slug:"permission-denied",category:"GENERAL",status:403,title:"File/resource permission denied",suggestion:"Check file permissions and access rights"}),Fo=h({slug:"file-not-found",category:"GENERAL",status:404,title:"File not found",suggestion:"Verify the file path exists"}),Vo=h({slug:"resource-not-found",category:"GENERAL",status:404,title:"Requested resource not found",suggestion:"Verify the referenced resource ID or name exists"}),zo=h({slug:"invalid-argument",category:"GENERAL",status:400,title:"Invalid function argument",suggestion:"Check argument types and values",exitCode:2}),Bo=h({slug:"timeout-error",category:"GENERAL",status:408,title:"Operation timed out",suggestion:"Increase timeout or optimize the operation"}),jo=h({slug:"initialization-error",category:"GENERAL",status:500,title:"Initialization failed",suggestion:"Check initialization requirements and dependencies"}),Go=h({slug:"not-supported",category:"GENERAL",status:501,title:"Feature not supported",suggestion:"Check documentation for supported features"}),Je=h({slug:"security-violation",category:"GENERAL",status:403,title:"Security violation detected",suggestion:"Check for path traversal or unauthorized access attempts"}),Wo=h({slug:"input-validation-failed",category:"GENERAL",status:400,title:"Input validation failed",suggestion:"Check request input against validation rules"}),Ko=h({slug:"project-source-empty",category:"GENERAL",status:400,title:"Project source is empty",suggestion:"Add project files or run \'veryfront init\'"}),Yo=h({slug:"nested-cwd-scope",category:"GENERAL",status:500,title:"Working directory scope nested inside another",suggestion:"Do the inner work directly in the outer scope\'s callback instead of opening a second one"});var Ln=[{source:String.raw`]*>[\\s\\S]*?<\\/script>`,flags:"gi",name:"inline script"},{source:String.raw`javascript:`,flags:"gi",name:"javascript: URL"},{source:String.raw`\\bon\\w+\\s*=`,flags:"gi",name:"event handler attribute"},{source:String.raw`data:\\s*text\\/html`,flags:"gi",name:"data: HTML URL"}];function Un(){return Ln.map(({source:e,flags:t,name:n})=>({pattern:new RegExp(e,t),name:n}))}function $n(){let e=globalThis;return e.__VERYFRONT_DEV__===!0||e.Deno?.env?.get?.("VERYFRONT_ENV")==="development"}function $(e,t={}){let{allowInlineScripts:n=!1,strict:r=!1,warn:o=!0}=t;for(let{pattern:i,name:s}of Un())if(!(n&&s==="inline script")&&(i.lastIndex=0,!!i.test(e)&&(o&&console.warn(`[Security] Suspicious ${s} detected in server HTML`),r||!$n())))throw Je.create({detail:`Potentially unsafe HTML: ${s} detected`});return e}function k(e,t){let n=t==="root"?H:`rsc-slot-${t}`,r=e.getElementById(n);if(r)return r;let o=e.createElement("div");return o.id=n,e.body.appendChild(o),o}function kn(e,t){if(t.type!=="slot")return;let n=k(e,t.id);n.innerHTML=$(String(t.html??""))}function qe(e,t){let n=t.split(`\n`),r=n.pop()??"";for(let o of n){let i=o.trim();if(!i)continue;let s;try{s=JSON.parse(i)}catch(l){u.debug("[client-dom] malformed NDJSON line",{line:i,error:l instanceof Error?l.message:String(l)});continue}if(!s||typeof s!="object")continue;let a=s;if(a.type==="slot"){kn(e,a);try{Vn(e,a.id||"root")}catch(l){u.debug("[client-dom] hydration optional failed",l)}}}return r}function vn(e){return new Promise((t,n)=>{let r=()=>n(new DOMException("aborted","AbortError"));if(e.aborted){r();return}e.addEventListener("abort",r,{once:!0})})}async function Ze(e,t=document,n){let r="body"in e?e:null,o=r?.body??e;if(!o)return;r&&W(t,r.headers.get(j));let i=o.getReader(),s=new TextDecoder,a="",l=!1;try{for(;;){if(n?.aborted)throw new DOMException("aborted","AbortError");let c=i.read(),{done:d,value:f}=n?await Promise.race([c,vn(n)]):await c;if(d){l=!0;break}a+=s.decode(f,{stream:!0}),a=qe(t,a)}a&&qe(t,`${a}\n`)}catch(c){throw c instanceof Error&&c.name==="AbortError"||u.debug("[client-dom] consumeNdjsonStream error",c),c}finally{try{await i.cancel()}catch(c){l||u.debug("[client-dom] reader.cancel failed",c)}try{i.releaseLock()}catch(c){u.debug("[client-dom] reader.releaseLock failed",c)}if(typeof o.cancel=="function")try{await o.cancel()}catch(c){u.debug("[client-dom] stream.cancel failed",c)}if(typeof r?.body?.cancel=="function")try{await r.body.cancel()}catch(c){u.debug("[client-dom] response.body.cancel failed",c)}}}function Fn(e,t){let n=k(e,t),r=[],o=i=>{let s=i;s.dataset?.clientRef&&r.push(s);for(let a of i.children)o(a)};return o(n),r}function Vn(e,t){let n=Fn(e,t);for(let r of n){let o=r.dataset?.clientRef;o&&(r.dataset.hydrated="true",u.debug("[client-dom] marked for hydration",o))}}var zn=new Set(["server","client","html","fragment"]);function Qe(e){if(!e)return[];try{let t=JSON.parse(e);return jn(t)?t.nodes:[]}catch{return[]}}async function he(e,t,n){return await Promise.all(e.map(r=>Bn(r,t,n)))}async function Bn(e,t,n){if(e.type==="html")return e.text??e.html??"";let r=await he(e.children??[],t,n);if(e.type==="fragment"||e.type==="server"&&!e.component)return t.createElement(t.Fragment,{},...r);if(e.type==="server")return t.createElement(e.component,e.props??{},...r);let o=await n(e.component);return o?t.createElement(o,e.props??{},...r):null}function jn(e){return!me(e)||e.version!==1||!Array.isArray(e.nodes)?!1:e.nodes.every(t=>et(t,0))}function et(e,t){return t>100||!me(e)||!zn.has(e.type)||e.type==="html"&&typeof e.html!="string"&&typeof e.text!="string"||e.type==="client"&&typeof e.component!="string"||e.type==="server"&&e.component!==void 0&&typeof e.component!="string"||e.props!==void 0&&!me(e.props)?!1:e.children===void 0?!0:Array.isArray(e.children)&&e.children.every(n=>et(n,t+1))}function me(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Gn(e){if(!e)return{};let t={};for(let[n,r]of Object.entries(e))t[n]=Array.isArray(r)?r.join("/"):r;return t}async function ee(e,t,n=document){try{let r=Me(n);if(!r)return e;let i=(await import(r)).wrapForHydration;return typeof i!="function"?e:i(e,{params:Gn(t?.params),frontmatter:t?.frontmatter??{},data:t?.props??{}})}catch(r){return u.debug("router provider wrap failed",r),e}}var Wn="Unknown dependency snapshot",Kn="export default null; // Unknown dependency snapshot",Ee="__VF_DEPENDENCY_SNAPSHOT_RECOVERY_STARTED__";function Yn(){return globalThis}async function Xn(e){if(e.status!==409)return!1;try{let t=(await e.clone().text()).trim();return t===Wn||t===Kn}catch{return!1}}async function N(e,t=()=>globalThis.location.reload()){if(!await Xn(e))return!1;let n=Yn();if(n[Ee])return!0;n[Ee]=!0;try{t()}catch{return delete n[Ee],!1}return!0}async function te(e,t=globalThis.fetch,n=()=>globalThis.location.reload()){try{let r=new URL(e,"http://veryfront.local").searchParams.getAll("pins");if(r.length!==1||!r[0]?.startsWith("on:"))return!1;let o=await t(e,{cache:"no-store"});return await N(o,n)}catch{return!1}}var Jn=100;function qn(e,t){if(globalThis.__VF_CLIENT_MOD_CACHE??(globalThis.__VF_CLIENT_MOD_CACHE=new Map),globalThis.__VF_CLIENT_MOD_CACHE.size>=Jn){let n=globalThis.__VF_CLIENT_MOD_CACHE.keys().next().value;n&&globalThis.__VF_CLIENT_MOD_CACHE.delete(n)}globalThis.__VF_CLIENT_MOD_CACHE.set(e,t)}function tt(e){let t=e.match(/^\\/app\\/(.+)#([\\w$.-]+)$/);if(t)return{rel:`/${t[1]||""}`,exportName:t[2]||"default"};let n=e.match(/^(\\/_veryfront\\/[^#]+)#([\\w$.-]+)$/);return n?{moduleUrl:n[1],exportName:n[2]||"default"}:(u.debug("hydrate: unrecognised client ref format, skipping",{ref:e}),null)}function Zn(e){let t=e.dataset?.rscProps;if(!t)return{};try{let n=JSON.parse(t);return n&&typeof n=="object"&&!Array.isArray(n)?n:{}}catch(n){return u.debug("hydrate: invalid client boundary props, using empty props",n),{}}}function Qn(e){return Qe(e.dataset?.rscChildren)}function er(e){return"/_veryfront/rsc/manifest"}function tr(e){return L(e)}async function nr(e=document){try{let t=C(e),n=await fetch(er(t),{headers:tr(t)});return n.ok?await n.json():(await N(n),null)}catch{return null}}async function nt(e,t,n,r={}){let o=rr(e,t,n,r.releaseAssetModules),i=t.moduleUrl??t.rel;if(!i)return null;let s=`${i}#${e.hash??""}`;try{let a=globalThis.__VF_CLIENT_MOD_CACHE?.get(s);if(a)return a}catch(a){u.debug("hydrate: cache get failed",a)}if(!o)return null;try{let a=await(r.importModule??(l=>import(l)))(o);try{qn(s,a)}catch(l){u.debug("hydrate: cache set failed",l)}return a}catch(a){return u.debug("hydrate: failed to import module",{moduleUrl:o,error:a}),await(r.recoverSnapshotFailure??te)(o),null}}function rr(e,t,n,r){if(t.moduleUrl)return Y(t.moduleUrl,e.dependencyPinningCacheKey);if(!t.rel)return null;let o=e.graphIds?.client.find(i=>i.rel===t.rel)?.path;return X({strategy:n,rel:t.rel,absPath:o,version:e.hash,dependencyPinningCacheKey:e.dependencyPinningCacheKey,releaseAssetModules:r})}function or(e){let t=Array.from(e.querySelectorAll("[data-client-ref]")),n=new Set(t);return t.filter(r=>{let o=r.parentElement;for(;o;){if(n.has(o))return!1;o=o.parentElement}return!0})}async function rt(e=document){let t=null;try{t=await nr(e)}catch(c){u.debug("hydrate: fetch manifest failed",c)}if(!t){u.debug("hydrate: no manifest");return}let n=or(e);try{let c=globalThis.__VF_MANIFEST_HASH;if(!n.some(f=>f.dataset?.hydrated!=="true")&&c&&t.hash&&c===t.hash)return}catch(c){u.debug("hydrate: hmr hash read failed",c)}if(n.length===0){try{globalThis.__VF_MANIFEST_HASH=t.hash??""}catch(c){u.debug("hydrate: set hash failed",c)}return}let r=C(e),o=K(r),i=r?.releaseAssetModules;try{if(globalThis.__VF_TEST_MODE__){globalThis.__VF_HYDRATE_CALLED=!0,globalThis.__VF_MANIFEST_HASH=t.hash??"";return}}catch(c){u.debug("hydrate: test mode flags failed",c)}let s=J(e,r?.reactVersion),[{default:a},{createRoot:l}]=await Promise.all([import(s.react),import(s.reactDomClient)]);for(let c of n){let d=c.dataset?.clientRef??"";if(!d||c.dataset?.hydrated==="true")continue;let f=tt(d);if(!f)continue;let E=await nt(t,f,o,{releaseAssetModules:i});if(!E)continue;let v=E[f.exportName]??E.default;if(typeof v=="function")try{let x=l(c),re=Zn(c),M=Qn(c),ot=await he(M,{Fragment:a.Fragment,createElement(F,oe,...V){return a.createElement(F,oe,...V)}},async F=>{let oe=t.modules.find(st=>st.id===F),V=t.components?.[F],xe=oe?.clientRef??(V?`${V}#default`:void 0);if(!xe)return null;let ie=tt(xe);if(!ie)return null;let se=await nt(t,ie,o,{releaseAssetModules:i});if(!se)return null;let Se=se[ie.exportName]??se.default;return typeof Se=="function"?Se:null}),it=await ee(a.createElement(v,re,...ot),r,e);x.render(it),c.dataset.hydrated="true"}catch(x){u.warn("hydrate: render failed",x)}}try{globalThis.__VF_MANIFEST_HASH=t.hash??""}catch(c){u.debug("hydrate: set hash failed (post)",c)}}var Re="data-vf-react-head-owner";var ir=2*1024*1024,yi=ir*2;var mi=64*1024,hi=1024*1024,Ei=1024*1024;var Ri=new TextEncoder;async function sr(){let e=C(document),t=J(document,e?.reactVersion),[n,r]=await Promise.all([import(t.react),import(t.reactDomClient)]);return{React:n,ReactDOM:r}}var ar=new Set(["SCRIPT","STYLE","NOSCRIPT","TEMPLATE"]);function _e(e){let t=e.getAttribute("style")??"";return e.hasAttribute("data-veryfront-head")||e.hasAttribute("hidden")||/(?:^|;)\\s*display\\s*:\\s*none(?:\\s*;|$)/i.test(t)||ar.has(e.tagName.toUpperCase())}function cr(e,t){return e.find(n=>n.tagName.toUpperCase()==="DIV"&&!!n.getAttribute("class")?.trim()&&!_e(n))??t}function lr(e,t){return e===t}function dr(e,t){let n=document.createElement("div");n.setAttribute("data-veryfront-hydration-root","page");let r=e.find(o=>!_e(o));r?.parentNode===t?t.insertBefore(n,r):t.appendChild(n);for(let o of e)!_e(o)&&o.parentNode===t&&n.appendChild(o);return n}function ur(e,t){for(let n of e){let r=[...n.hasAttribute(Re)?[n]:[],...n.querySelectorAll(`[${Re}]`)];for(let o of r)t.contains(o)||o.remove()}}function fr(e,t,n=document){return!!t?.pagePath&&typeof e?.__veryfrontRenderPage=="function"&&!!n.getElementById("root")}function gr(e,t){return t?.pagePath?!1:!!e.getElementById(H)}function pr(e=import.meta.url){try{return new URL(e,"http://veryfront.local").searchParams.get("hydrate")==="1"}catch{return!1}}function yr(e){return e==="rsc-module"}function mr(e,t){return e?e.startsWith("?")?e:`?${e}`:""}function hr(e,t,n){return X({strategy:t,rel:e,releaseAssetModules:n?.releaseAssetModules,dependencyPinningCacheKey:n?.dependencyPinningCacheKey})}async function Er(e,t){try{let n=await fetch(P+"stream"+e,{headers:L(t)});if(!n.ok)return await N(n)?"snapshot-conflict":"failure";if(!n.body)return"failure";let r=new AbortController;return addEventListener("pagehide",()=>r.abort(),{once:!0}),await Ze(n,document,r.signal),"success"}catch(n){return u.debug("tryStream failed",n),"failure"}}async function ne(){try{await rt(document)}catch(e){u.debug("hydration failed",e)}}async function Rr(e,t,n){try{let{React:r,ReactDOM:o}=await sr(),i=hr(e,t,n);if(!i)return!1;u.debug("Loading component from:",i);let s;try{s=await import(i)}catch(E){throw await te(i),E}let a=s.default;if(typeof a!="function")return u.debug("Page component is not a function"),!1;let l=Array.from(document.body.children),c=cr(l,document.body),d=lr(c,document.body)?dr(l,document.body):c;ur(l,d);let f=await ee(r.createElement(a,{}),n);return yr(t)?o.createRoot(d).render(f):o.hydrateRoot(d,f,{identifierPrefix:"vf",onRecoverableError:()=>{}}),u.debug("Page component hydrated successfully"),!0}catch(r){return u.error("Page hydration failed",r),!1}}async function _r(e,t){try{let n=await fetch(P+"payload"+e,{headers:L(t)});if(!n.ok)return await N(n)?"snapshot-conflict":"failure";let r=await n.json();if(W(document,r?.dependencyPinningCacheKey),r?.slots){for(let[o,i]of Object.entries(r.slots))k(document,o).innerHTML=$(String(i||""));return"success"}return k(document,H).innerHTML=$(String(r?.html||"")),"success"}catch(n){return u.debug("payload fetch failed",n),"failure"}}async function xr(){try{let e=C(document),t=mr(globalThis.window?.location.search??"",e?.dependencyPinningCacheKey);if(pr()){await ne();return}let n=e?.pagePath,r=K(e);if(n){if(fr(globalThis.window,e,document)){u.debug("Page renderer owns hydration");return}u.debug("Found page component in hydration data:",n),await Rr(n,r,e)&&u.debug("Client component hydrated successfully");return}if(!gr(document,e))return;let o=await Er(t,e);if(o==="snapshot-conflict")return;if(o==="success"){await ne();return}let i=await _r(t,e);if(i==="snapshot-conflict")return;if(i==="success"){await ne();return}await ne()}catch(e){u.error("boot failed",e)}}if(typeof document<"u"){let e=()=>{xr()};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",e,{once:!0}):e()}export{xr as boot,hr as buildPageHydrationModuleUrl,mr as buildRSCTransportQuery,ur as retireAbandonedHeadOwnerMarkers,cr as selectHydrationRoot,gr as shouldAttemptRSCTransport,pr as shouldHydrateOnly,yr as shouldRenderPageComponent,fr as shouldUsePageRendererHydration,lr as shouldWrapPageHydrationRoot};\n'; + 'var at=Object.defineProperty;var ct=(e,t,n)=>t in e?at(e,t,{enumerable:!0,configurable:!0,writable:!0,value:n}):e[t]=n;var m=(e,t,n)=>ct(e,typeof t!="symbol"?t+"":t,n);var Ar=Array.prototype.at,Tr=Array.prototype.filter,lt=Array.prototype.join,br=Array.prototype.map,Cr=Array.prototype.pop,dt=Array.prototype.push,wr=Array.prototype.sort,Ae=Reflect.apply;function z(e,t){return Ae(lt,e,[t])}function O(e,t){Ae(dt,e,[t])}var ut="3.2.3",ft=Object.entries;function gt(e){let t=[];if(e?.external?.length&&O(t,`external=${z(e.external,",")}`),O(t,`target=${e?.target??"es2022"}`),e?.deps){let n=[],r=ft(e.deps);for(let o=0;ot||n?.(r,...o)}debug(t,...n){this.log(0,console.debug,`[${this.prefix}] DEBUG: ${t}`,...n)}info(t,...n){this.log(1,console.log,`[${this.prefix}] ${t}`,...n)}warn(t,...n){this.log(2,console.warn,`[${this.prefix}] WARN: ${t}`,...n)}error(t,...n){this.log(3,console.error,`[${this.prefix}] ERROR: ${t}`,...n)}};function wt(){if(typeof window>"u")return 2;let e=globalThis;return e.__VERYFRONT_DEV__||e.__RSC_DEV__?e.__VERYFRONT_DEBUG__||e.__RSC_DEBUG__?0:1:2}var G=wt(),u=new b("RSC",G),eo=new b("PREFETCH",G),to=new b("HYDRATE",G),no=new b("VERYFRONT",G);var Dt="veryfront-hydration-data";function de(e){try{let t=[...e.querySelectorAll(`[id="${Dt}"]`)];if(t.length!==1)return null;let n=e.body;if(!n)return null;let r=t[0];return n.firstElementChild!==r&&r.parentElement!==n||r.tagName?.toLowerCase()!=="script"||r.getAttribute("type")?.trim().toLowerCase()!=="application/json"?null:r}catch{return null}}function C(e=document){try{let t=de(e);return t?JSON.parse(t.textContent||"{}"):null}catch(t){return u.debug("hydration data parse failed",t),null}}function W(e,t){if(!t?.startsWith("on:"))return!1;try{let n=de(e);if(!n)return!1;let r=JSON.parse(n.textContent||"{}");return r.dependencyPinningCacheKey=t,n.textContent=JSON.stringify(r),!0}catch(n){return u.debug("hydration dependency snapshot seed failed",n),!1}}function K(e){return e?.clientModuleStrategy?e.clientModuleStrategy:e?.dev?"fs":"rsc-module"}function Nt(e,t){if(!t)return e;let n=e.includes("?")?"&":"?";return`${e}${n}v=${encodeURIComponent(t)}`}function Y(e,t){if(!t?.startsWith("on:"))return e;let n=e.indexOf("#"),r=n===-1?"":e.slice(n),o=n===-1?e:e.slice(0,n),i=o.indexOf("?"),s=i===-1?o:o.slice(0,i),a=new URLSearchParams(i===-1?"":o.slice(i+1));a.set("pins",t);let l=a.toString();return`${s}${l?`?${l}`:""}${r}`}function Mt(e,t){return Nt(`${Ne}${ae(e)}.js`,t)}function Ot(e,t,n){let r=t?`&v=${encodeURIComponent(t)}`:"";return Y(`${P}module?rel=${encodeURIComponent(e)}${r}`,n)}function L(e){let t=e?.dependencyPinningCacheKey;return t?.startsWith("on:")?{[j]:t}:{}}function It(e){return e.replace(/^\\/+_vf_modules\\//,"").replace(/^\\/+/,"").replace(/\\.js$/,"")}var Pt=/\\.(tsx|ts|jsx|mdx|js)$/;function Ht(e){let t=It(e),n=[e,t];return Pt.test(t)||n.push(`${t}.tsx`,`${t}.ts`,`${t}.jsx`,`${t}.mdx`,`${t}.js`),Array.from(new Set(n))}function Lt(e,t){if(!e)return null;for(let n of Ht(t)){let r=e[n];if(r)return r}return null}function X(e){if(e.strategy==="fs"){let n=e.absPath??e.rel;return n?Y(Mt(n,e.version),e.dependencyPinningCacheKey):null}let t=Lt(e.releaseAssetModules,e.rel);return t||Ot(e.rel,e.version,e.dependencyPinningCacheKey)}function J(e=document,t=I){let n=ce(e);return{react:B("react",n)?"react":be(t),reactDomClient:B("react-dom/client",n)?"react-dom/client":Ce(t)}}function Me(e=document){let t=ce(e);return B("veryfront/router",t)?"veryfront/router":null}var q={reset:"\\x1B[0m",dim:"\\x1B[2m",gray:"\\x1B[90m",red:"\\x1B[31m",green:"\\x1B[32m",yellow:"\\x1B[33m",blue:"\\x1B[34m",magenta:"\\x1B[35m",cyan:"\\x1B[36m"},po={debug:q.gray,info:q.green,warn:q.yellow,error:q.red};var y="[REDACTED]",p=Reflect.apply,Ut=Array.prototype.pop,$t=Array.prototype.push;var mo=Array.prototype,ho=BigInt.prototype.toString,Le=Map,kt=Map.prototype.delete,vt=Map.prototype.get,Ft=Map.prototype.keys,Vt=Map.prototype.set;var _=Object.getOwnPropertyDescriptor,zt=Object.getPrototypeOf,Eo=Object.hasOwn,Ro=Object.prototype,Bt=Set,jt=decodeURIComponent,T=URL,_o=Number.isFinite,xo=Number.isInteger,ue=RegExp.prototype.exec,Gt=_(RegExp.prototype,"global").get,Wt=_(RegExp.prototype,"unicode").get,Kt=String.prototype.charCodeAt,Yt=String.prototype.includes,Xt=String.prototype.indexOf,Oe=String.prototype.slice,Ue=String.prototype.startsWith,$e=String.prototype.toLowerCase,Jt=Set.prototype.add,So=Set.prototype.delete,qt=Set.prototype.has,Zt=zt(new Le().keys()).next,Qt=_(Map.prototype,"size").get,Ao=_(T.prototype,"host").get,To=_(T.prototype,"origin").get,en=_(T.prototype,"password").get,bo=_(T.prototype,"pathname").get,Co=_(T.prototype,"protocol").get,tn=_(T.prototype,"username").get,nn=/[^a-z0-9]/g,rn=/([a-z0-9])([A-Z])/g,on=/([A-Z])([A-Z][a-z])/g,sn=/\\b(?:sk-[A-Za-z0-9._-]{8,}|gh[po]_[A-Za-z0-9._-]{8,}|xox[baprs]-[A-Za-z0-9._-]{8,}|eyJ[A-Za-z0-9._-]{8,})\\b/g;function R(e,t,n){let r=p(Gt,t,[]),o=p(Wt,t,[]),i=0,s=!1,a="";t.lastIndex=0;try{for(;;){let l=p(ue,t,[e]);if(l===null)break;let c=l[0],d=l.index;if(a+=A(e,i,d),a+=typeof n=="string"?n:n(l),i=d+c.length,s=!0,!r)break;c.length===0&&(t.lastIndex=an(e,d,o))}}finally{t.lastIndex=0}return s?a+A(e,i):e}function fe(e){let t=p($e,e,[]);return R(t,nn,"")}function w(e,t){return p(Kt,e,[t])}function an(e,t,n){let r=t+1;if(!n||r>=e.length)return r;let o=w(e,t);if(o<55296||o>56319)return r;let i=w(e,r);return i>=56320&&i<=57343?t+2:r}function A(e,t,n){return n===void 0?p(Oe,e,[t]):p(Oe,e,[t,n])}function cn(e){let t=[],n=0;for(let r=0;r<=e.length;r++){let o=r===e.length?-1:w(e,r);o>=97&&o<=122||o>=48&&o<=57||(r>n&&(t[t.length]=A(e,n,r)),n=r+1)}return t}var Z=["password","passwd","pwd","passphrase","secret","clientsecret","token","apikey","accesskey","privatekey","credential","authheader","authorization","cookie","bearer","jwt","connectionstring","signature","sessionid","sid","otp","mfa","pin","salt","xsrf","csrf"],ln=512,dn=128,U=new Le;var un=256;function fn(e){let t=e.length<=dn;if(t){let o=p(vt,U,[e]);if(o!==void 0)return o}let n=fe(e),r=n==="auth";for(let o=0;!r&&o=ln){let i=p(Ft,U,[]),s=p(Zt,i,[]).value;s!==void 0&&p(kt,U,[s])}p(Vt,U,[e,r])}return r}var Ie=["access_token","accesstoken","refresh_token","api_key","apikey","code","token","secret","client_secret","password","passwd","pwd","state","sig","signature","auth","x-amz-credential","x-amz-signature","x-amz-security-token","x-goog-credential","x-goog-signature"],ke=new Bt;for(let e=0;e=65&&t<=90||t>=97&&t<=122}function ve(e){return hn(e)||e==="_"||e==="$"}function En(e){if(!e)return!1;let t=w(e,0);return ve(e)||t>=48&&t<=57||e==="."||e==="-"}function Fe(e,t){let n=t,r=e[n]===\'"\'||e[n]==="\'"?e[n++]:"";if(!ve(e[n]))return!1;for(n++;En(e[n]);)n++;if(r){if(e[n]!==r)return!1;n++}for(;e[n]===" "||e[n]==="\t";)n++;return e[n]===":"||e[n]==="="}function Ve(e){return e==="\\r"||e===`\n`||e==="}"||e==="]"||mn(e)}function ze(e,t){let n=t;for(;n=e.length||Fe(e,n)}function Rn(e,t){let n=t,r=!0;if(p(Ue,e,[y,t])){let d=t+y.length;if(Pe(e,d))return{end:d,replacement:y};n=d,r=!1}let o=r&&(e[n]===\'"\'||e[n]==="\'"||e[n]==="`")?e[n]:"",i=!1,s=()=>o?`${o}${y}${i?o:""}`:y,a=[],l="",c=-1;for(let d=n;d0&&(f==="}"||f==="]")){if(a[a.length-1]!==f)return{end:e.length,replacement:s()};if(p(Ut,a,[]),d++,a.length===0&&Pe(e,d))return{end:d,replacement:s()};continue}if(a.length>0||!Ve(f)){d++;continue}let E=d;if(d=ze(e,d),d>=e.length||Fe(e,d))return{end:E,replacement:s()}}return{end:e.length,replacement:s()}}function He(e,t,n,r){let o=0,i="";for(let s=p(ue,t,[e]);s;s=p(ue,t,[e])){let a=s[n];if(!_n(a))continue;let l=t.lastIndex,c=r===void 0?void 0:s[r],d=l+y.length;if((c==="?"||c==="&"||c===";")&&p(Ue,e,[y,l])&&e[d]==="#")continue;let f=Rn(e,l);i+=A(e,o,s.index),i+=s[0],i+=f.replacement,o=f.end,t.lastIndex=f.end}return o===0?e:i+A(e,o)}function _n(e){if(e.length>un)return!0;let t=R(e,on,i=>`${i[1]} ${i[2]}`),n=R(t,rn,i=>`${i[1]} ${i[2]}`),r=p($e,n,[]),o=cn(r);for(let i=0;i{let r=n[1],o=n[2],i=p(Xt,o,[":"]);if(i===-1)return`${r}${y}@`;let s=A(o,0,i);return`${r}${s}:${y}@`});return t=R(t,pn,n=>{let r=n[1],o=n[2],i=n[3];return xn(r,o,i)?n[0]:`${r}${o}:${y}@`}),t=R(t,/([?#&;])([-a-z0-9_.%\\[\\]]+)=([^&#;\\s]*)/gi,n=>{let r=n[1],o=n[2],i=Sn(o);return p(qt,ke,[fe(i)])||fn(i)?`${r}${o}=${y}`:n[0]}),t=R(t,/(^|[^a-z0-9_-])((?:set-cookie|cookie)\\s*:\\s*)[^\\r\\n]*/gi,n=>`${n[1]}${n[2]}${y}`),t=R(t,/\\b(authorization\\s*[:=]\\s*)[^\\r\\n]*/gi,n=>`${n[1]}${y}`),t=R(t,/\\b(bearer|basic)(\\s+)(?:"[^"\\r\\n]*"|\'[^\'\\r\\n]*\'|[a-z0-9._~+/=-]+)/gi,n=>`${n[1]}${n[2]}${y}`),t=R(t,sn,y),t=He(t,/(["\'])([_$a-z][a-z0-9_.$-]*)\\1(\\s*[:=]\\s*)/gi,2),t=He(t,/(^|[^a-z0-9_.$-])([_$a-z][a-z0-9_.$-]*)(\\s*[:=]\\s*)/gi,2,1),t}var An=2048;var Oo=64*1024,Tn=256,bn="https://veryfront.com/docs/code/guides/errors#",Be="...[truncated]",pe="unknown-error";function je(e,t){if(e.length<=t)return e;let n=Math.max(0,t-Be.length);return`${Cn(e,n)}${Be}`}function Cn(e,t){let n=e.slice(0,t),r=n.charCodeAt(n.length-1);return r>=55296&&r<=56319&&(n=n.slice(0,-1)),n}function wn(e){let t="";for(let n=0;n=55296&&r<=56319){let o=e.charCodeAt(n+1);o>=56320&&o<=57343?(t+=e.slice(n,n+2),n++):t+="\\uFFFD";continue}t+=r>=56320&&r<=57343?"\\uFFFD":e.charAt(n)}return t}function D(e){return typeof e!="string"?y:je(ge(e),An)}function Dn(e){let t=typeof e=="string"?ge(e):pe,n=je(t||pe,Tn),r=wn(n);return r==="."||r===".."?pe:r}function Q(e){let t=encodeURIComponent(Dn(e));return`${bn}${t}`}var Ke=Reflect.apply,Nn=Object.freeze,Mn=Object.getOwnPropertyDescriptors,Ge=Number.isFinite,Ye=new WeakSet,On=WeakSet.prototype.add,In=WeakSet.prototype.has,Pn=new Set(["CONFIG","BUILD","RUNTIME","ROUTE","MODULE","SERVER","BOUNDARY","DEV","DEPLOY","AGENT","GENERAL"]);function h(e){let t={...e},n={...t,create(r){let o=r?.message,i=r?.detail,s=r?.cause,a=r?.instance,l=r?.context,c=r?.status??t.status;return new ye(o||i||t.title,{slug:t.slug,category:t.category,status:c,title:t.title,suggestion:t.suggestion,exitCode:t.exitCode,detail:i,cause:s,instance:a,context:l})}};return Nn(n)}var ye=class extends Error{constructor(n,r){super(n);m(this,"slug");m(this,"category");m(this,"status");m(this,"title");m(this,"suggestion");m(this,"exitCode");m(this,"detail");m(this,"cause");m(this,"instance");m(this,"context");Ke(On,Ye,[this]),this.name="VeryfrontError",this.slug=r.slug,this.category=r.category,this.status=r.status,this.title=r.title,this.suggestion=r.suggestion,this.exitCode=r.exitCode,this.detail=r.detail,this.cause=r.cause,this.instance=r.instance,this.context=r.context}toRFC9457(){let n=We(this);return n?{type:Q(n.slug),title:D(n.title),status:n.status,detail:n.detail===void 0?void 0:D(n.detail),instance:n.instance===void 0?void 0:D(n.instance),category:n.category,suggestion:n.suggestion===void 0?void 0:D(n.suggestion),cause:typeof n.cause=="string"?D(n.cause):void 0}:{type:Q("unknown-error"),title:"Unknown/unclassified error",status:500,category:"GENERAL"}}getDocsUrl(){let n=We(this);return Q(n?.slug??"unknown-error")}};function Xe(e){return typeof e=="object"&&e!==null&&Ke(In,Ye,[e])===!0}function We(e){return Xe(e)?Hn(e):null}function Hn(e){try{if(!Xe(e))return null;let t=Mn(e),n=re=>{let M=t[re];return M&&"value"in M?M.value:void 0},r=n("slug"),o=n("category"),i=n("status"),s=n("title"),a=n("message"),l=n("suggestion"),c=n("exitCode"),d=n("detail"),f=n("cause"),E=n("instance"),v=n("context"),x=n("stack");return typeof r!="string"||!Pn.has(o)||typeof i!="number"||!Ge(i)||typeof s!="string"||typeof a!="string"||l!==void 0&&typeof l!="string"||c!==void 0&&(typeof c!="number"||!Ge(c))||d!==void 0&&typeof d!="string"||E!==void 0&&typeof E!="string"||x!==void 0&&typeof x!="string"?null:{slug:r,category:o,status:i,title:s,message:a,suggestion:l,exitCode:c,detail:d,cause:f,instance:E,context:v,stack:x}}catch{return null}}var $o=h({slug:"unknown-error",category:"GENERAL",status:500,title:"Unknown/unclassified error",suggestion:"Check logs for more details"}),ko=h({slug:"authentication-required",category:"GENERAL",status:401,title:"Authentication required",suggestion:"Set VERYFRONT_API_TOKEN or run \'veryfront login\'"}),vo=h({slug:"permission-denied",category:"GENERAL",status:403,title:"File/resource permission denied",suggestion:"Check file permissions and access rights"}),Fo=h({slug:"file-not-found",category:"GENERAL",status:404,title:"File not found",suggestion:"Verify the file path exists"}),Vo=h({slug:"resource-not-found",category:"GENERAL",status:404,title:"Requested resource not found",suggestion:"Verify the referenced resource ID or name exists"}),zo=h({slug:"invalid-argument",category:"GENERAL",status:400,title:"Invalid function argument",suggestion:"Check argument types and values",exitCode:2}),Bo=h({slug:"timeout-error",category:"GENERAL",status:408,title:"Operation timed out",suggestion:"Increase timeout or optimize the operation"}),jo=h({slug:"initialization-error",category:"GENERAL",status:500,title:"Initialization failed",suggestion:"Check initialization requirements and dependencies"}),Go=h({slug:"not-supported",category:"GENERAL",status:501,title:"Feature not supported",suggestion:"Check documentation for supported features"}),Je=h({slug:"security-violation",category:"GENERAL",status:403,title:"Security violation detected",suggestion:"Check for path traversal or unauthorized access attempts"}),Wo=h({slug:"input-validation-failed",category:"GENERAL",status:400,title:"Input validation failed",suggestion:"Check request input against validation rules"}),Ko=h({slug:"project-source-empty",category:"GENERAL",status:400,title:"Project source is empty",suggestion:"Add project files or run \'veryfront init\'"}),Yo=h({slug:"nested-cwd-scope",category:"GENERAL",status:500,title:"Working directory scope nested inside another",suggestion:"Do the inner work directly in the outer scope\'s callback instead of opening a second one"});var Ln=[{source:String.raw`]*>[\\s\\S]*?<\\/script>`,flags:"gi",name:"inline script"},{source:String.raw`javascript:`,flags:"gi",name:"javascript: URL"},{source:String.raw`\\bon\\w+\\s*=`,flags:"gi",name:"event handler attribute"},{source:String.raw`data:\\s*text\\/html`,flags:"gi",name:"data: HTML URL"}];function Un(){return Ln.map(({source:e,flags:t,name:n})=>({pattern:new RegExp(e,t),name:n}))}function $n(){let e=globalThis;return e.__VERYFRONT_DEV__===!0||e.Deno?.env?.get?.("VERYFRONT_ENV")==="development"}function $(e,t={}){let{allowInlineScripts:n=!1,strict:r=!1,warn:o=!0}=t;for(let{pattern:i,name:s}of Un())if(!(n&&s==="inline script")&&(i.lastIndex=0,!!i.test(e)&&(o&&console.warn(`[Security] Suspicious ${s} detected in server HTML`),r||!$n())))throw Je.create({detail:`Potentially unsafe HTML: ${s} detected`});return e}function k(e,t){let n=t==="root"?H:`rsc-slot-${t}`,r=e.getElementById(n);if(r)return r;let o=e.createElement("div");return o.id=n,e.body.appendChild(o),o}function kn(e,t){if(t.type!=="slot")return;let n=k(e,t.id);n.innerHTML=$(String(t.html??""))}function qe(e,t){let n=t.split(`\n`),r=n.pop()??"";for(let o of n){let i=o.trim();if(!i)continue;let s;try{s=JSON.parse(i)}catch(l){u.debug("[client-dom] malformed NDJSON line",{line:i,error:l instanceof Error?l.message:String(l)});continue}if(!s||typeof s!="object")continue;let a=s;if(a.type==="slot"){kn(e,a);try{Vn(e,a.id||"root")}catch(l){u.debug("[client-dom] hydration optional failed",l)}}}return r}function vn(e){return new Promise((t,n)=>{let r=()=>n(new DOMException("aborted","AbortError"));if(e.aborted){r();return}e.addEventListener("abort",r,{once:!0})})}async function Ze(e,t=document,n){let r="body"in e?e:null,o=r?.body??e;if(!o)return;r&&W(t,r.headers.get(j));let i=o.getReader(),s=new TextDecoder,a="",l=!1;try{for(;;){if(n?.aborted)throw new DOMException("aborted","AbortError");let c=i.read(),{done:d,value:f}=n?await Promise.race([c,vn(n)]):await c;if(d){l=!0;break}a+=s.decode(f,{stream:!0}),a=qe(t,a)}a&&qe(t,`${a}\n`)}catch(c){throw c instanceof Error&&c.name==="AbortError"||u.debug("[client-dom] consumeNdjsonStream error",c),c}finally{try{await i.cancel()}catch(c){l||u.debug("[client-dom] reader.cancel failed",c)}try{i.releaseLock()}catch(c){u.debug("[client-dom] reader.releaseLock failed",c)}if(typeof o.cancel=="function")try{await o.cancel()}catch(c){u.debug("[client-dom] stream.cancel failed",c)}if(typeof r?.body?.cancel=="function")try{await r.body.cancel()}catch(c){u.debug("[client-dom] response.body.cancel failed",c)}}}function Fn(e,t){let n=k(e,t),r=[],o=i=>{let s=i;s.dataset?.clientRef&&r.push(s);for(let a of i.children)o(a)};return o(n),r}function Vn(e,t){let n=Fn(e,t);for(let r of n){let o=r.dataset?.clientRef;o&&(r.dataset.hydrated="true",u.debug("[client-dom] marked for hydration",o))}}var zn=new Set(["server","client","html","fragment"]);function Qe(e){if(!e)return[];try{let t=JSON.parse(e);return jn(t)?t.nodes:[]}catch{return[]}}async function he(e,t,n){return await Promise.all(e.map(r=>Bn(r,t,n)))}async function Bn(e,t,n){if(e.type==="html")return e.text??e.html??"";let r=await he(e.children??[],t,n);if(e.type==="fragment"||e.type==="server"&&!e.component)return t.createElement(t.Fragment,{},...r);if(e.type==="server")return t.createElement(e.component,e.props??{},...r);let o=await n(e.component);return o?t.createElement(o,e.props??{},...r):null}function jn(e){return!me(e)||e.version!==1||!Array.isArray(e.nodes)?!1:e.nodes.every(t=>et(t,0))}function et(e,t){return t>100||!me(e)||!zn.has(e.type)||e.type==="html"&&typeof e.html!="string"&&typeof e.text!="string"||e.type==="client"&&typeof e.component!="string"||e.type==="server"&&e.component!==void 0&&typeof e.component!="string"||e.props!==void 0&&!me(e.props)?!1:e.children===void 0?!0:Array.isArray(e.children)&&e.children.every(n=>et(n,t+1))}function me(e){return typeof e=="object"&&e!==null&&!Array.isArray(e)}function Gn(e){if(!e)return{};let t={};for(let[n,r]of Object.entries(e))t[n]=Array.isArray(r)?r.join("/"):r;return t}async function ee(e,t,n=document){try{let r=Me(n);if(!r)return e;let i=(await import(r)).wrapForHydration;return typeof i!="function"?e:i(e,{params:Gn(t?.params),frontmatter:t?.frontmatter??{},data:t?.props??{}})}catch(r){return u.debug("router provider wrap failed",r),e}}var Wn="Unknown dependency snapshot",Kn="export default null; // Unknown dependency snapshot",Ee="__VF_DEPENDENCY_SNAPSHOT_RECOVERY_STARTED__";function Yn(){return globalThis}async function Xn(e){if(e.status!==409)return!1;try{let t=(await e.clone().text()).trim();return t===Wn||t===Kn}catch{return!1}}async function N(e,t=()=>globalThis.location.reload()){if(!await Xn(e))return!1;let n=Yn();if(n[Ee])return!0;n[Ee]=!0;try{t()}catch{return delete n[Ee],!1}return!0}async function te(e,t=globalThis.fetch,n=()=>globalThis.location.reload()){try{let r=new URL(e,"http://veryfront.local").searchParams.getAll("pins");if(r.length!==1||!r[0]?.startsWith("on:"))return!1;let o=await t(e,{cache:"no-store"});return await N(o,n)}catch{return!1}}var Jn=100;function qn(e,t){if(globalThis.__VF_CLIENT_MOD_CACHE??(globalThis.__VF_CLIENT_MOD_CACHE=new Map),globalThis.__VF_CLIENT_MOD_CACHE.size>=Jn){let n=globalThis.__VF_CLIENT_MOD_CACHE.keys().next().value;n&&globalThis.__VF_CLIENT_MOD_CACHE.delete(n)}globalThis.__VF_CLIENT_MOD_CACHE.set(e,t)}function tt(e){let t=e.match(/^\\/app\\/(.+)#([\\w$.-]+)$/);if(t)return{rel:`/${t[1]||""}`,exportName:t[2]||"default"};let n=e.match(/^(\\/_veryfront\\/[^#]+)#([\\w$.-]+)$/);return n?{moduleUrl:n[1],exportName:n[2]||"default"}:(u.debug("hydrate: unrecognised client ref format, skipping",{ref:e}),null)}function Zn(e){let t=e.dataset?.rscProps;if(!t)return{};try{let n=JSON.parse(t);return n&&typeof n=="object"&&!Array.isArray(n)?n:{}}catch(n){return u.debug("hydrate: invalid client boundary props, using empty props",n),{}}}function Qn(e){return Qe(e.dataset?.rscChildren)}function er(e){return"/_veryfront/rsc/manifest"}function tr(e){return L(e)}async function nr(e=document){try{let t=C(e),n=await fetch(er(t),{headers:tr(t)});return n.ok?await n.json():(await N(n),null)}catch{return null}}async function nt(e,t,n,r={}){let o=rr(e,t,n,r.releaseAssetModules),i=t.moduleUrl??t.rel;if(!i)return null;let s=`${i}#${e.hash??""}`;try{let a=globalThis.__VF_CLIENT_MOD_CACHE?.get(s);if(a)return a}catch(a){u.debug("hydrate: cache get failed",a)}if(!o)return null;try{let a=await(r.importModule??(l=>import(l)))(o);try{qn(s,a)}catch(l){u.debug("hydrate: cache set failed",l)}return a}catch(a){return u.debug("hydrate: failed to import module",{moduleUrl:o,error:a}),await(r.recoverSnapshotFailure??te)(o),null}}function rr(e,t,n,r){if(t.moduleUrl)return Y(t.moduleUrl,e.dependencyPinningCacheKey);if(!t.rel)return null;let o=e.graphIds?.client.find(i=>i.rel===t.rel)?.path;return X({strategy:n,rel:t.rel,absPath:o,version:e.hash,dependencyPinningCacheKey:e.dependencyPinningCacheKey,releaseAssetModules:r})}function or(e){let t=Array.from(e.querySelectorAll("[data-client-ref]")),n=new Set(t);return t.filter(r=>{let o=r.parentElement;for(;o;){if(n.has(o))return!1;o=o.parentElement}return!0})}async function rt(e=document){let t=null;try{t=await nr(e)}catch(c){u.debug("hydrate: fetch manifest failed",c)}if(!t){u.debug("hydrate: no manifest");return}let n=or(e);try{let c=globalThis.__VF_MANIFEST_HASH;if(!n.some(f=>f.dataset?.hydrated!=="true")&&c&&t.hash&&c===t.hash)return}catch(c){u.debug("hydrate: hmr hash read failed",c)}if(n.length===0){try{globalThis.__VF_MANIFEST_HASH=t.hash??""}catch(c){u.debug("hydrate: set hash failed",c)}return}let r=C(e),o=K(r),i=r?.releaseAssetModules;try{if(globalThis.__VF_TEST_MODE__){globalThis.__VF_HYDRATE_CALLED=!0,globalThis.__VF_MANIFEST_HASH=t.hash??"";return}}catch(c){u.debug("hydrate: test mode flags failed",c)}let s=J(e,r?.reactVersion),[{default:a},{createRoot:l}]=await Promise.all([import(s.react),import(s.reactDomClient)]);for(let c of n){let d=c.dataset?.clientRef??"";if(!d||c.dataset?.hydrated==="true")continue;let f=tt(d);if(!f)continue;let E=await nt(t,f,o,{releaseAssetModules:i});if(!E)continue;let v=E[f.exportName]??E.default;if(typeof v=="function")try{let x=l(c),re=Zn(c),M=Qn(c),ot=await he(M,{Fragment:a.Fragment,createElement(F,oe,...V){return a.createElement(F,oe,...V)}},async F=>{let oe=t.modules.find(st=>st.id===F),V=t.components?.[F],xe=oe?.clientRef??(V?`${V}#default`:void 0);if(!xe)return null;let ie=tt(xe);if(!ie)return null;let se=await nt(t,ie,o,{releaseAssetModules:i});if(!se)return null;let Se=se[ie.exportName]??se.default;return typeof Se=="function"?Se:null}),it=await ee(a.createElement(v,re,...ot),r,e);x.render(it),c.dataset.hydrated="true"}catch(x){u.warn("hydrate: render failed",x)}}try{globalThis.__VF_MANIFEST_HASH=t.hash??""}catch(c){u.debug("hydrate: set hash failed (post)",c)}}var Re="data-vf-react-head-owner";var ir=2*1024*1024,yi=ir*2;var mi=64*1024,hi=1024*1024,Ei=1024*1024;var Ri=new TextEncoder;async function sr(){let e=C(document),t=J(document,e?.reactVersion),[n,r]=await Promise.all([import(t.react),import(t.reactDomClient)]);return{React:n,ReactDOM:r}}var ar=new Set(["SCRIPT","STYLE","NOSCRIPT","TEMPLATE"]);function _e(e){let t=e.getAttribute("style")??"";return e.hasAttribute("data-veryfront-head")||e.hasAttribute("hidden")||/(?:^|;)\\s*display\\s*:\\s*none(?:\\s*;|$)/i.test(t)||ar.has(e.tagName.toUpperCase())}function cr(e,t){return e.find(n=>n.tagName.toUpperCase()==="DIV"&&!!n.getAttribute("class")?.trim()&&!_e(n))??t}function lr(e,t){return e===t}function dr(e,t){let n=document.createElement("div");n.setAttribute("data-veryfront-hydration-root","page");let r=e.find(o=>!_e(o));r?.parentNode===t?t.insertBefore(n,r):t.appendChild(n);for(let o of e)!_e(o)&&o.parentNode===t&&n.appendChild(o);return n}function ur(e,t){for(let n of e){let r=[...n.hasAttribute(Re)?[n]:[],...n.querySelectorAll(`[${Re}]`)];for(let o of r)t.contains(o)||o.remove()}}function fr(e,t,n=document){return!!t?.pagePath&&typeof e?.__veryfrontRenderPage=="function"&&!!n.getElementById("root")}function gr(e,t){return t?.pagePath?!1:!!e.getElementById(H)}function pr(e=import.meta.url){try{return new URL(e,"http://veryfront.local").searchParams.get("hydrate")==="1"}catch{return!1}}function yr(e){return e==="rsc-module"}function mr(e,t){return e?e.startsWith("?")?e:`?${e}`:""}function hr(e,t,n){return X({strategy:t,rel:e,releaseAssetModules:n?.releaseAssetModules,dependencyPinningCacheKey:n?.dependencyPinningCacheKey})}async function Er(e,t){try{let n=await fetch(P+"stream"+e,{headers:L(t)});if(!n.ok)return await N(n)?"snapshot-conflict":"failure";if(!n.body)return"failure";let r=new AbortController;return addEventListener("pagehide",()=>r.abort(),{once:!0}),await Ze(n,document,r.signal),"success"}catch(n){return u.debug("tryStream failed",n),"failure"}}async function ne(){try{await rt(document)}catch(e){u.debug("hydration failed",e)}}async function Rr(e,t,n){try{let{React:r,ReactDOM:o}=await sr(),i=hr(e,t,n);if(!i)return!1;u.debug("Loading component from:",i);let s;try{s=await import(i)}catch(E){throw await te(i),E}let a=s.default;if(typeof a!="function")return u.debug("Page component is not a function"),!1;let l=Array.from(document.body.children),c=cr(l,document.body),d=lr(c,document.body)?dr(l,document.body):c;ur(l,d);let f=await ee(r.createElement(a,{}),n);return yr(t)?o.createRoot(d).render(f):o.hydrateRoot(d,f,{identifierPrefix:"vf",onRecoverableError:()=>{}}),u.debug("Page component hydrated successfully"),!0}catch(r){return u.error("Page hydration failed",r),!1}}async function _r(e,t){try{let n=await fetch(P+"payload"+e,{headers:L(t)});if(!n.ok)return await N(n)?"snapshot-conflict":"failure";let r=await n.json();if(W(document,r?.dependencyPinningCacheKey),r?.slots){for(let[o,i]of Object.entries(r.slots))k(document,o).innerHTML=$(String(i||""));return"success"}return k(document,H).innerHTML=$(String(r?.html||"")),"success"}catch(n){return u.debug("payload fetch failed",n),"failure"}}async function xr(){try{let e=C(document),t=mr(globalThis.window?.location.search??"",e?.dependencyPinningCacheKey);if(pr()){await ne();return}let n=e?.pagePath,r=K(e);if(n){if(fr(globalThis.window,e,document)){u.debug("Page renderer owns hydration");return}u.debug("Found page component in hydration data:",n),await Rr(n,r,e)&&u.debug("Client component hydrated successfully");return}if(!gr(document,e))return;let o=await Er(t,e);if(o==="snapshot-conflict")return;if(o==="success"){await ne();return}let i=await _r(t,e);if(i==="snapshot-conflict")return;if(i==="success"){await ne();return}await ne()}catch(e){u.error("boot failed",e)}}if(typeof document<"u"){let e=()=>{xr()};document.readyState==="loading"?document.addEventListener("DOMContentLoaded",e,{once:!0}):e()}export{xr as boot,hr as buildPageHydrationModuleUrl,mr as buildRSCTransportQuery,ur as retireAbandonedHeadOwnerMarkers,cr as selectHydrationRoot,gr as shouldAttemptRSCTransport,pr as shouldHydrateOnly,yr as shouldRenderPageComponent,fr as shouldUsePageRendererHydration,lr as shouldWrapPageHydrationRoot};\n'; export const CLIENT_DOM_BUNDLE: string = - 'var Et=Object.defineProperty;var yt=(t,n,e)=>n in t?Et(t,n,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[n]=e;var m=(t,n,e)=>yt(t,typeof n!="symbol"?n+"":n,e);var I={reset:"\\x1B[0m",dim:"\\x1B[2m",gray:"\\x1B[90m",red:"\\x1B[31m",green:"\\x1B[32m",yellow:"\\x1B[33m",blue:"\\x1B[34m",magenta:"\\x1B[35m",cyan:"\\x1B[36m"},Ue={debug:I.gray,info:I.green,warn:I.yellow,error:I.red};var p="[REDACTED]",g=Reflect.apply,xt=Array.prototype.pop,Rt=Array.prototype.push;var ke=Array.prototype,He=BigInt.prototype.toString,v=Map,ht=Map.prototype.delete,_t=Map.prototype.get,St=Map.prototype.keys,At=Map.prototype.set;var R=Object.getOwnPropertyDescriptor,bt=Object.getPrototypeOf,ze=Object.hasOwn,Ve=Object.prototype,Tt=Set,Ct=decodeURIComponent,_=URL,je=Number.isFinite,Fe=Number.isInteger,L=RegExp.prototype.exec,It=R(RegExp.prototype,"global").get,Nt=R(RegExp.prototype,"unicode").get,Ot=String.prototype.charCodeAt,Dt=String.prototype.includes,$t=String.prototype.indexOf,V=String.prototype.slice,B=String.prototype.startsWith,W=String.prototype.toLowerCase,wt=Set.prototype.add,Ge=Set.prototype.delete,Lt=Set.prototype.has,Pt=bt(new v().keys()).next,Ut=R(Map.prototype,"size").get,ve=R(_.prototype,"host").get,Be=R(_.prototype,"origin").get,Mt=R(_.prototype,"password").get,We=R(_.prototype,"pathname").get,Ye=R(_.prototype,"protocol").get,kt=R(_.prototype,"username").get,Ht=/[^a-z0-9]/g,zt=/([a-z0-9])([A-Z])/g,Vt=/([A-Z])([A-Z][a-z])/g,jt=/\\b(?:sk-[A-Za-z0-9._-]{8,}|gh[po]_[A-Za-z0-9._-]{8,}|xox[baprs]-[A-Za-z0-9._-]{8,}|eyJ[A-Za-z0-9._-]{8,})\\b/g;function x(t,n,e){let r=g(It,n,[]),o=g(Nt,n,[]),s=0,i=!1,a="";n.lastIndex=0;try{for(;;){let u=g(L,n,[t]);if(u===null)break;let c=u[0],l=u.index;if(a+=h(t,s,l),a+=typeof e=="string"?e:e(u),s=l+c.length,i=!0,!r)break;c.length===0&&(n.lastIndex=Ft(t,l,o))}}finally{n.lastIndex=0}return i?a+h(t,s):t}function P(t){let n=g(W,t,[]);return x(n,Ht,"")}function S(t,n){return g(Ot,t,[n])}function Ft(t,n,e){let r=n+1;if(!e||r>=t.length)return r;let o=S(t,n);if(o<55296||o>56319)return r;let s=S(t,r);return s>=56320&&s<=57343?n+2:r}function h(t,n,e){return e===void 0?g(V,t,[n]):g(V,t,[n,e])}function Gt(t){let n=[],e=0;for(let r=0;r<=t.length;r++){let o=r===t.length?-1:S(t,r);o>=97&&o<=122||o>=48&&o<=57||(r>e&&(n[n.length]=h(t,e,r)),e=r+1)}return n}var N=["password","passwd","pwd","passphrase","secret","clientsecret","token","apikey","accesskey","privatekey","credential","authheader","authorization","cookie","bearer","jwt","connectionstring","signature","sessionid","sid","otp","mfa","pin","salt","xsrf","csrf"],vt=512,Bt=128,C=new v;var Wt=256;function Yt(t){let n=t.length<=Bt;if(n){let o=g(_t,C,[t]);if(o!==void 0)return o}let e=P(t),r=e==="auth";for(let o=0;!r&&o=vt){let s=g(St,C,[]),i=g(Pt,s,[]).value;i!==void 0&&g(ht,C,[i])}g(At,C,[t,r])}return r}var j=["access_token","accesstoken","refresh_token","api_key","apikey","code","token","secret","client_secret","password","passwd","pwd","state","sig","signature","auth","x-amz-credential","x-amz-signature","x-amz-security-token","x-goog-credential","x-goog-signature"],Y=new Tt;for(let t=0;t=65&&n<=90||n>=97&&n<=122}function K(t){return Zt(t)||t==="_"||t==="$"}function Qt(t){if(!t)return!1;let n=S(t,0);return K(t)||n>=48&&n<=57||t==="."||t==="-"}function X(t,n){let e=n,r=t[e]===\'"\'||t[e]==="\'"?t[e++]:"";if(!K(t[e]))return!1;for(e++;Qt(t[e]);)e++;if(r){if(t[e]!==r)return!1;e++}for(;t[e]===" "||t[e]==="\t";)e++;return t[e]===":"||t[e]==="="}function J(t){return t==="\\r"||t===`\n`||t==="}"||t==="]"||qt(t)}function q(t,n){let e=n;for(;e=t.length||X(t,e)}function te(t,n){let e=n,r=!0;if(g(B,t,[p,n])){let l=n+p.length;if(F(t,l))return{end:l,replacement:p};e=l,r=!1}let o=r&&(t[e]===\'"\'||t[e]==="\'"||t[e]==="`")?t[e]:"",s=!1,i=()=>o?`${o}${p}${s?o:""}`:p,a=[],u="",c=-1;for(let l=e;l0&&(f==="}"||f==="]")){if(a[a.length-1]!==f)return{end:t.length,replacement:i()};if(g(xt,a,[]),l++,a.length===0&&F(t,l))return{end:l,replacement:i()};continue}if(a.length>0||!J(f)){l++;continue}let T=l;if(l=q(t,l),l>=t.length||X(t,l))return{end:T,replacement:i()}}return{end:t.length,replacement:i()}}function G(t,n,e,r){let o=0,s="";for(let i=g(L,n,[t]);i;i=g(L,n,[t])){let a=i[e];if(!ee(a))continue;let u=n.lastIndex,c=r===void 0?void 0:i[r],l=u+p.length;if((c==="?"||c==="&"||c===";")&&g(B,t,[p,u])&&t[l]==="#")continue;let f=te(t,u);s+=h(t,o,i.index),s+=i[0],s+=f.replacement,o=f.end,n.lastIndex=f.end}return o===0?t:s+h(t,o)}function ee(t){if(t.length>Wt)return!0;let n=x(t,Vt,s=>`${s[1]} ${s[2]}`),e=x(n,zt,s=>`${s[1]} ${s[2]}`),r=g(W,e,[]),o=Gt(r);for(let s=0;s{let r=e[1],o=e[2],s=g($t,o,[":"]);if(s===-1)return`${r}${p}@`;let i=h(o,0,s);return`${r}${i}:${p}@`});return n=x(n,Xt,e=>{let r=e[1],o=e[2],s=e[3];return ne(r,o,s)?e[0]:`${r}${o}:${p}@`}),n=x(n,/([?#&;])([-a-z0-9_.%\\[\\]]+)=([^&#;\\s]*)/gi,e=>{let r=e[1],o=e[2],s=re(o);return g(Lt,Y,[P(s)])||Yt(s)?`${r}${o}=${p}`:e[0]}),n=x(n,/(^|[^a-z0-9_-])((?:set-cookie|cookie)\\s*:\\s*)[^\\r\\n]*/gi,e=>`${e[1]}${e[2]}${p}`),n=x(n,/\\b(authorization\\s*[:=]\\s*)[^\\r\\n]*/gi,e=>`${e[1]}${p}`),n=x(n,/\\b(bearer|basic)(\\s+)(?:"[^"\\r\\n]*"|\'[^\'\\r\\n]*\'|[a-z0-9._~+/=-]+)/gi,e=>`${e[1]}${e[2]}${p}`),n=x(n,jt,p),n=G(n,/(["\'])([_$a-z][a-z0-9_.$-]*)\\1(\\s*[:=]\\s*)/gi,2),n=G(n,/(^|[^a-z0-9_.$-])([_$a-z][a-z0-9_.$-]*)(\\s*[:=]\\s*)/gi,2,1),n}var oe=2048;var Ze=64*1024,se=256,ie="https://veryfront.com/docs/errors/",Z="...[truncated]",M="unknown-error";function Q(t,n){if(t.length<=n)return t;let e=Math.max(0,n-Z.length);return`${ae(t,e)}${Z}`}function ae(t,n){let e=t.slice(0,n),r=e.charCodeAt(e.length-1);return r>=55296&&r<=56319&&(e=e.slice(0,-1)),e}function ce(t){let n="";for(let e=0;e=55296&&r<=56319){let o=t.charCodeAt(e+1);o>=56320&&o<=57343?(n+=t.slice(e,e+2),e++):n+="\\uFFFD";continue}n+=r>=56320&&r<=57343?"\\uFFFD":t.charAt(e)}return n}function A(t){return typeof t!="string"?p:Q(U(t),oe)}function ue(t){let n=typeof t=="string"?U(t):M,e=Q(n||M,se),r=ce(e);return r==="."||r===".."?M:r}function O(t){let n=encodeURIComponent(ue(t));return`${ie}${n}`}var nt=Reflect.apply,le=Object.freeze,de=Object.getOwnPropertyDescriptors,tt=Number.isFinite,rt=new WeakSet,ge=WeakSet.prototype.add,fe=WeakSet.prototype.has,pe=new Set(["CONFIG","BUILD","RUNTIME","ROUTE","MODULE","SERVER","BOUNDARY","DEV","DEPLOY","AGENT","GENERAL"]);function E(t){let n={...t},e={...n,create(r){let o=r?.message,s=r?.detail,i=r?.cause,a=r?.instance,u=r?.context,c=r?.status??n.status;return new k(o||s||n.title,{slug:n.slug,category:n.category,status:c,title:n.title,suggestion:n.suggestion,exitCode:n.exitCode,detail:s,cause:i,instance:a,context:u})}};return le(e)}var k=class extends Error{constructor(e,r){super(e);m(this,"slug");m(this,"category");m(this,"status");m(this,"title");m(this,"suggestion");m(this,"exitCode");m(this,"detail");m(this,"cause");m(this,"instance");m(this,"context");nt(ge,rt,[this]),this.name="VeryfrontError",this.slug=r.slug,this.category=r.category,this.status=r.status,this.title=r.title,this.suggestion=r.suggestion,this.exitCode=r.exitCode,this.detail=r.detail,this.cause=r.cause,this.instance=r.instance,this.context=r.context}toRFC9457(){let e=et(this);return e?{type:O(e.slug),title:A(e.title),status:e.status,detail:e.detail===void 0?void 0:A(e.detail),instance:e.instance===void 0?void 0:A(e.instance),category:e.category,suggestion:e.suggestion===void 0?void 0:A(e.suggestion),cause:typeof e.cause=="string"?A(e.cause):void 0}:{type:O("unknown-error"),title:"Unknown/unclassified error",status:500,category:"GENERAL"}}getDocsUrl(){let e=et(this);return O(e?.slug??"unknown-error")}};function ot(t){return typeof t=="object"&&t!==null&&nt(fe,rt,[t])===!0}function et(t){return ot(t)?me(t):null}function me(t){try{if(!ot(t))return null;let n=de(t),e=mt=>{let w=n[mt];return w&&"value"in w?w.value:void 0},r=e("slug"),o=e("category"),s=e("status"),i=e("title"),a=e("message"),u=e("suggestion"),c=e("exitCode"),l=e("detail"),f=e("cause"),T=e("instance"),pt=e("context"),$=e("stack");return typeof r!="string"||!pe.has(o)||typeof s!="number"||!tt(s)||typeof i!="string"||typeof a!="string"||u!==void 0&&typeof u!="string"||c!==void 0&&(typeof c!="number"||!tt(c))||l!==void 0&&typeof l!="string"||T!==void 0&&typeof T!="string"||$!==void 0&&typeof $!="string"?null:{slug:r,category:o,status:s,title:i,message:a,suggestion:u,exitCode:c,detail:l,cause:f,instance:T,context:pt,stack:$}}catch{return null}}var on=E({slug:"unknown-error",category:"GENERAL",status:500,title:"Unknown/unclassified error",suggestion:"Check logs for more details"}),sn=E({slug:"authentication-required",category:"GENERAL",status:401,title:"Authentication required",suggestion:"Set VERYFRONT_API_TOKEN or run \'veryfront login\'"}),an=E({slug:"permission-denied",category:"GENERAL",status:403,title:"File/resource permission denied",suggestion:"Check file permissions and access rights"}),cn=E({slug:"file-not-found",category:"GENERAL",status:404,title:"File not found",suggestion:"Verify the file path exists"}),un=E({slug:"resource-not-found",category:"GENERAL",status:404,title:"Requested resource not found",suggestion:"Verify the referenced resource ID or name exists"}),ln=E({slug:"invalid-argument",category:"GENERAL",status:400,title:"Invalid function argument",suggestion:"Check argument types and values",exitCode:2}),dn=E({slug:"timeout-error",category:"GENERAL",status:408,title:"Operation timed out",suggestion:"Increase timeout or optimize the operation"}),gn=E({slug:"initialization-error",category:"GENERAL",status:500,title:"Initialization failed",suggestion:"Check initialization requirements and dependencies"}),fn=E({slug:"not-supported",category:"GENERAL",status:501,title:"Feature not supported",suggestion:"Check documentation for supported features"}),st=E({slug:"security-violation",category:"GENERAL",status:403,title:"Security violation detected",suggestion:"Check for path traversal or unauthorized access attempts"}),pn=E({slug:"input-validation-failed",category:"GENERAL",status:400,title:"Input validation failed",suggestion:"Check request input against validation rules"}),mn=E({slug:"project-source-empty",category:"GENERAL",status:400,title:"Project source is empty",suggestion:"Add project files or run \'veryfront init\'"}),En=E({slug:"nested-cwd-scope",category:"GENERAL",status:500,title:"Working directory scope nested inside another",suggestion:"Do the inner work directly in the outer scope\'s callback instead of opening a second one"});var Ee=[{source:String.raw`]*>[\\s\\S]*?<\\/script>`,flags:"gi",name:"inline script"},{source:String.raw`javascript:`,flags:"gi",name:"javascript: URL"},{source:String.raw`\\bon\\w+\\s*=`,flags:"gi",name:"event handler attribute"},{source:String.raw`data:\\s*text\\/html`,flags:"gi",name:"data: HTML URL"}];function ye(){return Ee.map(({source:t,flags:n,name:e})=>({pattern:new RegExp(t,n),name:e}))}function xe(){let t=globalThis;return t.__VERYFRONT_DEV__===!0||t.Deno?.env?.get?.("VERYFRONT_ENV")==="development"}function it(t,n={}){let{allowInlineScripts:e=!1,strict:r=!1,warn:o=!0}=n;for(let{pattern:s,name:i}of ye())if(!(e&&i==="inline script")&&(s.lastIndex=0,!!s.test(t)&&(o&&console.warn(`[Security] Suspicious ${i} detected in server HTML`),r||!xe())))throw st.create({detail:`Potentially unsafe HTML: ${i} detected`});return t}var b=class{constructor(n,e){m(this,"prefix",n);m(this,"level",e)}log(n,e,r,...o){this.level>n||e?.(r,...o)}debug(n,...e){this.log(0,console.debug,`[${this.prefix}] DEBUG: ${n}`,...e)}info(n,...e){this.log(1,console.log,`[${this.prefix}] ${n}`,...e)}warn(n,...e){this.log(2,console.warn,`[${this.prefix}] WARN: ${n}`,...e)}error(n,...e){this.log(3,console.error,`[${this.prefix}] ERROR: ${n}`,...e)}};function Re(){if(typeof window>"u")return 2;let t=globalThis;return t.__VERYFRONT_DEV__||t.__RSC_DEV__?t.__VERYFRONT_DEBUG__||t.__RSC_DEBUG__?0:1:2}var D=Re(),y=new b("RSC",D),hn=new b("PREFETCH",D),_n=new b("HYDRATE",D),Sn=new b("VERYFRONT",D);var Tn=Object.freeze({IPV4:"127.0.0.1",IPV6:"::1",HOSTNAME:"localhost"});var he=5e3,_e=1e4,Nn=16*1024*1024,Se=5e3;var Ae=100;var be=Object.freeze([5,10,25,50,75,100,250,500,750,1e3,2500,5e3,7500,1e4]),On=Object.freeze([1,5,10,25,50,100,250,500,1e3,2500,5e3,1e4]),Dn=Object.freeze({server:Object.freeze({port:3e3,hostname:"0.0.0.0"}),timeouts:Object.freeze({default:he,api:3e4,ssr:_e,hmr:3e4,sandbox:Se}),cache:Object.freeze({jit:Object.freeze({maxSize:Ae,tempDirPrefix:"vf-bundle-"})}),metrics:Object.freeze({ssrBoundaries:be})});var d="/_veryfront",H={RSC:`${d}/rsc/`,FS:`${d}/fs/`,MODULES:`${d}/modules/`,PAGES:`${d}/pages/`,DATA:`${d}/data/`,LIB:`${d}/lib/`,CHUNKS:`${d}/chunks/`,CLIENT:`${d}/client/`},ct={HMR_RUNTIME:`${d}/hmr-runtime.js`,HMR:`${d}/hmr.js`,ERROR_OVERLAY:`${d}/error-overlay.js`,DEV_LOADER:`${d}/dev-loader.js`,CLIENT_LOG:`${d}/log`,CLIENT_JS:`${d}/client.js`,ROUTER_JS:`${d}/router.js`,PREFETCH_JS:`${d}/prefetch.js`,MANIFEST_JSON:`${d}/manifest.json`,APP_JS:`${d}/app.js`,RSC_CLIENT:`${d}/rsc/client.js`,RSC_MANIFEST:`${d}/rsc/manifest`,RSC_STREAM:`${d}/rsc/stream`,RSC_PAYLOAD:`${d}/rsc/payload`,RSC_RENDER:`${d}/rsc/render`,RSC_PAGE:`${d}/rsc/page`,RSC_MODULE:`${d}/rsc/module`,RSC_DOM:`${d}/rsc/dom.js`,LIB_CHAT_REACT:`${d}/lib/chat/react.js`,LIB_CHAT_COMPONENTS:`${d}/lib/chat/components.js`,LIB_CHAT_PRIMITIVES:`${d}/lib/chat/primitives.js`};var Te={ROOT:".veryfront",CACHE:".veryfront/cache",KV:".veryfront/kv",LOGS:".veryfront/logs",TMP:".veryfront/tmp"},wn=Te.CACHE;var Ln={HMR_RUNTIME:ct.HMR_RUNTIME,ERROR_OVERLAY:ct.ERROR_OVERLAY};var Ce=H.RSC,Ie=H.FS;var ut="rsc-root",z="x-veryfront-dependency-pins";var Hn=Array.prototype.at,zn=Array.prototype.filter,Vn=Array.prototype.join,jn=Array.prototype.map,Fn=Array.prototype.pop,Gn=Array.prototype.push,vn=Array.prototype.sort;var sr=Object.freeze({react:"","react-dom":"","react-dom/client":"","react-dom/server":"","react/jsx-runtime":"","react/jsx-dev-runtime":""});var Oe="veryfront-hydration-data";function lt(t){try{let n=[...t.querySelectorAll(`[id="${Oe}"]`)];if(n.length!==1)return null;let e=t.body;if(!e)return null;let r=n[0];return e.firstElementChild!==r&&r.parentElement!==e||r.tagName?.toLowerCase()!=="script"||r.getAttribute("type")?.trim().toLowerCase()!=="application/json"?null:r}catch{return null}}function dt(t,n){if(!n?.startsWith("on:"))return!1;try{let e=lt(t);if(!e)return!1;let r=JSON.parse(e.textContent||"{}");return r.dependencyPinningCacheKey=n,e.textContent=JSON.stringify(r),!0}catch(e){return y.debug("hydration dependency snapshot seed failed",e),!1}}function ft(t,n){let e=n==="root"?ut:`rsc-slot-${n}`,r=t.getElementById(e);if(r)return r;let o=t.createElement("div");return o.id=e,t.body.appendChild(o),o}function De(t,n){if(n.type!=="slot")return;let e=ft(t,n.id);e.innerHTML=it(String(n.html??""))}function gt(t,n){let e=n.split(`\n`),r=e.pop()??"";for(let o of e){let s=o.trim();if(!s)continue;let i;try{i=JSON.parse(s)}catch(u){y.debug("[client-dom] malformed NDJSON line",{line:s,error:u instanceof Error?u.message:String(u)});continue}if(!i||typeof i!="object")continue;let a=i;if(a.type==="slot"){De(t,a);try{Le(t,a.id||"root")}catch(u){y.debug("[client-dom] hydration optional failed",u)}}}return r}function $e(t){return new Promise((n,e)=>{let r=()=>e(new DOMException("aborted","AbortError"));if(t.aborted){r();return}t.addEventListener("abort",r,{once:!0})})}async function Tr(t,n=document,e){let r="body"in t?t:null,o=r?.body??t;if(!o)return;r&&dt(n,r.headers.get(z));let s=o.getReader(),i=new TextDecoder,a="",u=!1;try{for(;;){if(e?.aborted)throw new DOMException("aborted","AbortError");let c=s.read(),{done:l,value:f}=e?await Promise.race([c,$e(e)]):await c;if(l){u=!0;break}a+=i.decode(f,{stream:!0}),a=gt(n,a)}a&>(n,`${a}\n`)}catch(c){throw c instanceof Error&&c.name==="AbortError"||y.debug("[client-dom] consumeNdjsonStream error",c),c}finally{try{await s.cancel()}catch(c){u||y.debug("[client-dom] reader.cancel failed",c)}try{s.releaseLock()}catch(c){y.debug("[client-dom] reader.releaseLock failed",c)}if(typeof o.cancel=="function")try{await o.cancel()}catch(c){y.debug("[client-dom] stream.cancel failed",c)}if(typeof r?.body?.cancel=="function")try{await r.body.cancel()}catch(c){y.debug("[client-dom] response.body.cancel failed",c)}}}function we(t,n){let e=ft(t,n),r=[],o=s=>{let i=s;i.dataset?.clientRef&&r.push(i);for(let a of s.children)o(a)};return o(e),r}function Le(t,n){let e=we(t,n);for(let r of e){let o=r.dataset?.clientRef;o&&(r.dataset.hydrated="true",y.debug("[client-dom] marked for hydration",o))}}export{Tr as consumeNdjsonStream,ft as getContainer};\n'; + 'var Et=Object.defineProperty;var yt=(t,n,e)=>n in t?Et(t,n,{enumerable:!0,configurable:!0,writable:!0,value:e}):t[n]=e;var m=(t,n,e)=>yt(t,typeof n!="symbol"?n+"":n,e);var I={reset:"\\x1B[0m",dim:"\\x1B[2m",gray:"\\x1B[90m",red:"\\x1B[31m",green:"\\x1B[32m",yellow:"\\x1B[33m",blue:"\\x1B[34m",magenta:"\\x1B[35m",cyan:"\\x1B[36m"},Ue={debug:I.gray,info:I.green,warn:I.yellow,error:I.red};var p="[REDACTED]",g=Reflect.apply,xt=Array.prototype.pop,Rt=Array.prototype.push;var ke=Array.prototype,He=BigInt.prototype.toString,v=Map,ht=Map.prototype.delete,_t=Map.prototype.get,St=Map.prototype.keys,At=Map.prototype.set;var R=Object.getOwnPropertyDescriptor,bt=Object.getPrototypeOf,ze=Object.hasOwn,Ve=Object.prototype,Tt=Set,Ct=decodeURIComponent,_=URL,je=Number.isFinite,Fe=Number.isInteger,L=RegExp.prototype.exec,It=R(RegExp.prototype,"global").get,Nt=R(RegExp.prototype,"unicode").get,Ot=String.prototype.charCodeAt,Dt=String.prototype.includes,$t=String.prototype.indexOf,V=String.prototype.slice,B=String.prototype.startsWith,W=String.prototype.toLowerCase,wt=Set.prototype.add,Ge=Set.prototype.delete,Lt=Set.prototype.has,Pt=bt(new v().keys()).next,Ut=R(Map.prototype,"size").get,ve=R(_.prototype,"host").get,Be=R(_.prototype,"origin").get,Mt=R(_.prototype,"password").get,We=R(_.prototype,"pathname").get,Ye=R(_.prototype,"protocol").get,kt=R(_.prototype,"username").get,Ht=/[^a-z0-9]/g,zt=/([a-z0-9])([A-Z])/g,Vt=/([A-Z])([A-Z][a-z])/g,jt=/\\b(?:sk-[A-Za-z0-9._-]{8,}|gh[po]_[A-Za-z0-9._-]{8,}|xox[baprs]-[A-Za-z0-9._-]{8,}|eyJ[A-Za-z0-9._-]{8,})\\b/g;function x(t,n,e){let r=g(It,n,[]),o=g(Nt,n,[]),s=0,i=!1,a="";n.lastIndex=0;try{for(;;){let u=g(L,n,[t]);if(u===null)break;let c=u[0],l=u.index;if(a+=h(t,s,l),a+=typeof e=="string"?e:e(u),s=l+c.length,i=!0,!r)break;c.length===0&&(n.lastIndex=Ft(t,l,o))}}finally{n.lastIndex=0}return i?a+h(t,s):t}function P(t){let n=g(W,t,[]);return x(n,Ht,"")}function S(t,n){return g(Ot,t,[n])}function Ft(t,n,e){let r=n+1;if(!e||r>=t.length)return r;let o=S(t,n);if(o<55296||o>56319)return r;let s=S(t,r);return s>=56320&&s<=57343?n+2:r}function h(t,n,e){return e===void 0?g(V,t,[n]):g(V,t,[n,e])}function Gt(t){let n=[],e=0;for(let r=0;r<=t.length;r++){let o=r===t.length?-1:S(t,r);o>=97&&o<=122||o>=48&&o<=57||(r>e&&(n[n.length]=h(t,e,r)),e=r+1)}return n}var N=["password","passwd","pwd","passphrase","secret","clientsecret","token","apikey","accesskey","privatekey","credential","authheader","authorization","cookie","bearer","jwt","connectionstring","signature","sessionid","sid","otp","mfa","pin","salt","xsrf","csrf"],vt=512,Bt=128,C=new v;var Wt=256;function Yt(t){let n=t.length<=Bt;if(n){let o=g(_t,C,[t]);if(o!==void 0)return o}let e=P(t),r=e==="auth";for(let o=0;!r&&o=vt){let s=g(St,C,[]),i=g(Pt,s,[]).value;i!==void 0&&g(ht,C,[i])}g(At,C,[t,r])}return r}var j=["access_token","accesstoken","refresh_token","api_key","apikey","code","token","secret","client_secret","password","passwd","pwd","state","sig","signature","auth","x-amz-credential","x-amz-signature","x-amz-security-token","x-goog-credential","x-goog-signature"],Y=new Tt;for(let t=0;t=65&&n<=90||n>=97&&n<=122}function K(t){return Zt(t)||t==="_"||t==="$"}function Qt(t){if(!t)return!1;let n=S(t,0);return K(t)||n>=48&&n<=57||t==="."||t==="-"}function X(t,n){let e=n,r=t[e]===\'"\'||t[e]==="\'"?t[e++]:"";if(!K(t[e]))return!1;for(e++;Qt(t[e]);)e++;if(r){if(t[e]!==r)return!1;e++}for(;t[e]===" "||t[e]==="\t";)e++;return t[e]===":"||t[e]==="="}function J(t){return t==="\\r"||t===`\n`||t==="}"||t==="]"||qt(t)}function q(t,n){let e=n;for(;e=t.length||X(t,e)}function te(t,n){let e=n,r=!0;if(g(B,t,[p,n])){let l=n+p.length;if(F(t,l))return{end:l,replacement:p};e=l,r=!1}let o=r&&(t[e]===\'"\'||t[e]==="\'"||t[e]==="`")?t[e]:"",s=!1,i=()=>o?`${o}${p}${s?o:""}`:p,a=[],u="",c=-1;for(let l=e;l0&&(f==="}"||f==="]")){if(a[a.length-1]!==f)return{end:t.length,replacement:i()};if(g(xt,a,[]),l++,a.length===0&&F(t,l))return{end:l,replacement:i()};continue}if(a.length>0||!J(f)){l++;continue}let T=l;if(l=q(t,l),l>=t.length||X(t,l))return{end:T,replacement:i()}}return{end:t.length,replacement:i()}}function G(t,n,e,r){let o=0,s="";for(let i=g(L,n,[t]);i;i=g(L,n,[t])){let a=i[e];if(!ee(a))continue;let u=n.lastIndex,c=r===void 0?void 0:i[r],l=u+p.length;if((c==="?"||c==="&"||c===";")&&g(B,t,[p,u])&&t[l]==="#")continue;let f=te(t,u);s+=h(t,o,i.index),s+=i[0],s+=f.replacement,o=f.end,n.lastIndex=f.end}return o===0?t:s+h(t,o)}function ee(t){if(t.length>Wt)return!0;let n=x(t,Vt,s=>`${s[1]} ${s[2]}`),e=x(n,zt,s=>`${s[1]} ${s[2]}`),r=g(W,e,[]),o=Gt(r);for(let s=0;s{let r=e[1],o=e[2],s=g($t,o,[":"]);if(s===-1)return`${r}${p}@`;let i=h(o,0,s);return`${r}${i}:${p}@`});return n=x(n,Xt,e=>{let r=e[1],o=e[2],s=e[3];return ne(r,o,s)?e[0]:`${r}${o}:${p}@`}),n=x(n,/([?#&;])([-a-z0-9_.%\\[\\]]+)=([^&#;\\s]*)/gi,e=>{let r=e[1],o=e[2],s=re(o);return g(Lt,Y,[P(s)])||Yt(s)?`${r}${o}=${p}`:e[0]}),n=x(n,/(^|[^a-z0-9_-])((?:set-cookie|cookie)\\s*:\\s*)[^\\r\\n]*/gi,e=>`${e[1]}${e[2]}${p}`),n=x(n,/\\b(authorization\\s*[:=]\\s*)[^\\r\\n]*/gi,e=>`${e[1]}${p}`),n=x(n,/\\b(bearer|basic)(\\s+)(?:"[^"\\r\\n]*"|\'[^\'\\r\\n]*\'|[a-z0-9._~+/=-]+)/gi,e=>`${e[1]}${e[2]}${p}`),n=x(n,jt,p),n=G(n,/(["\'])([_$a-z][a-z0-9_.$-]*)\\1(\\s*[:=]\\s*)/gi,2),n=G(n,/(^|[^a-z0-9_.$-])([_$a-z][a-z0-9_.$-]*)(\\s*[:=]\\s*)/gi,2,1),n}var oe=2048;var Ze=64*1024,se=256,ie="https://veryfront.com/docs/code/guides/errors#",Z="...[truncated]",M="unknown-error";function Q(t,n){if(t.length<=n)return t;let e=Math.max(0,n-Z.length);return`${ae(t,e)}${Z}`}function ae(t,n){let e=t.slice(0,n),r=e.charCodeAt(e.length-1);return r>=55296&&r<=56319&&(e=e.slice(0,-1)),e}function ce(t){let n="";for(let e=0;e=55296&&r<=56319){let o=t.charCodeAt(e+1);o>=56320&&o<=57343?(n+=t.slice(e,e+2),e++):n+="\\uFFFD";continue}n+=r>=56320&&r<=57343?"\\uFFFD":t.charAt(e)}return n}function A(t){return typeof t!="string"?p:Q(U(t),oe)}function ue(t){let n=typeof t=="string"?U(t):M,e=Q(n||M,se),r=ce(e);return r==="."||r===".."?M:r}function O(t){let n=encodeURIComponent(ue(t));return`${ie}${n}`}var nt=Reflect.apply,le=Object.freeze,de=Object.getOwnPropertyDescriptors,tt=Number.isFinite,rt=new WeakSet,ge=WeakSet.prototype.add,fe=WeakSet.prototype.has,pe=new Set(["CONFIG","BUILD","RUNTIME","ROUTE","MODULE","SERVER","BOUNDARY","DEV","DEPLOY","AGENT","GENERAL"]);function E(t){let n={...t},e={...n,create(r){let o=r?.message,s=r?.detail,i=r?.cause,a=r?.instance,u=r?.context,c=r?.status??n.status;return new k(o||s||n.title,{slug:n.slug,category:n.category,status:c,title:n.title,suggestion:n.suggestion,exitCode:n.exitCode,detail:s,cause:i,instance:a,context:u})}};return le(e)}var k=class extends Error{constructor(e,r){super(e);m(this,"slug");m(this,"category");m(this,"status");m(this,"title");m(this,"suggestion");m(this,"exitCode");m(this,"detail");m(this,"cause");m(this,"instance");m(this,"context");nt(ge,rt,[this]),this.name="VeryfrontError",this.slug=r.slug,this.category=r.category,this.status=r.status,this.title=r.title,this.suggestion=r.suggestion,this.exitCode=r.exitCode,this.detail=r.detail,this.cause=r.cause,this.instance=r.instance,this.context=r.context}toRFC9457(){let e=et(this);return e?{type:O(e.slug),title:A(e.title),status:e.status,detail:e.detail===void 0?void 0:A(e.detail),instance:e.instance===void 0?void 0:A(e.instance),category:e.category,suggestion:e.suggestion===void 0?void 0:A(e.suggestion),cause:typeof e.cause=="string"?A(e.cause):void 0}:{type:O("unknown-error"),title:"Unknown/unclassified error",status:500,category:"GENERAL"}}getDocsUrl(){let e=et(this);return O(e?.slug??"unknown-error")}};function ot(t){return typeof t=="object"&&t!==null&&nt(fe,rt,[t])===!0}function et(t){return ot(t)?me(t):null}function me(t){try{if(!ot(t))return null;let n=de(t),e=mt=>{let w=n[mt];return w&&"value"in w?w.value:void 0},r=e("slug"),o=e("category"),s=e("status"),i=e("title"),a=e("message"),u=e("suggestion"),c=e("exitCode"),l=e("detail"),f=e("cause"),T=e("instance"),pt=e("context"),$=e("stack");return typeof r!="string"||!pe.has(o)||typeof s!="number"||!tt(s)||typeof i!="string"||typeof a!="string"||u!==void 0&&typeof u!="string"||c!==void 0&&(typeof c!="number"||!tt(c))||l!==void 0&&typeof l!="string"||T!==void 0&&typeof T!="string"||$!==void 0&&typeof $!="string"?null:{slug:r,category:o,status:s,title:i,message:a,suggestion:u,exitCode:c,detail:l,cause:f,instance:T,context:pt,stack:$}}catch{return null}}var on=E({slug:"unknown-error",category:"GENERAL",status:500,title:"Unknown/unclassified error",suggestion:"Check logs for more details"}),sn=E({slug:"authentication-required",category:"GENERAL",status:401,title:"Authentication required",suggestion:"Set VERYFRONT_API_TOKEN or run \'veryfront login\'"}),an=E({slug:"permission-denied",category:"GENERAL",status:403,title:"File/resource permission denied",suggestion:"Check file permissions and access rights"}),cn=E({slug:"file-not-found",category:"GENERAL",status:404,title:"File not found",suggestion:"Verify the file path exists"}),un=E({slug:"resource-not-found",category:"GENERAL",status:404,title:"Requested resource not found",suggestion:"Verify the referenced resource ID or name exists"}),ln=E({slug:"invalid-argument",category:"GENERAL",status:400,title:"Invalid function argument",suggestion:"Check argument types and values",exitCode:2}),dn=E({slug:"timeout-error",category:"GENERAL",status:408,title:"Operation timed out",suggestion:"Increase timeout or optimize the operation"}),gn=E({slug:"initialization-error",category:"GENERAL",status:500,title:"Initialization failed",suggestion:"Check initialization requirements and dependencies"}),fn=E({slug:"not-supported",category:"GENERAL",status:501,title:"Feature not supported",suggestion:"Check documentation for supported features"}),st=E({slug:"security-violation",category:"GENERAL",status:403,title:"Security violation detected",suggestion:"Check for path traversal or unauthorized access attempts"}),pn=E({slug:"input-validation-failed",category:"GENERAL",status:400,title:"Input validation failed",suggestion:"Check request input against validation rules"}),mn=E({slug:"project-source-empty",category:"GENERAL",status:400,title:"Project source is empty",suggestion:"Add project files or run \'veryfront init\'"}),En=E({slug:"nested-cwd-scope",category:"GENERAL",status:500,title:"Working directory scope nested inside another",suggestion:"Do the inner work directly in the outer scope\'s callback instead of opening a second one"});var Ee=[{source:String.raw`]*>[\\s\\S]*?<\\/script>`,flags:"gi",name:"inline script"},{source:String.raw`javascript:`,flags:"gi",name:"javascript: URL"},{source:String.raw`\\bon\\w+\\s*=`,flags:"gi",name:"event handler attribute"},{source:String.raw`data:\\s*text\\/html`,flags:"gi",name:"data: HTML URL"}];function ye(){return Ee.map(({source:t,flags:n,name:e})=>({pattern:new RegExp(t,n),name:e}))}function xe(){let t=globalThis;return t.__VERYFRONT_DEV__===!0||t.Deno?.env?.get?.("VERYFRONT_ENV")==="development"}function it(t,n={}){let{allowInlineScripts:e=!1,strict:r=!1,warn:o=!0}=n;for(let{pattern:s,name:i}of ye())if(!(e&&i==="inline script")&&(s.lastIndex=0,!!s.test(t)&&(o&&console.warn(`[Security] Suspicious ${i} detected in server HTML`),r||!xe())))throw st.create({detail:`Potentially unsafe HTML: ${i} detected`});return t}var b=class{constructor(n,e){m(this,"prefix",n);m(this,"level",e)}log(n,e,r,...o){this.level>n||e?.(r,...o)}debug(n,...e){this.log(0,console.debug,`[${this.prefix}] DEBUG: ${n}`,...e)}info(n,...e){this.log(1,console.log,`[${this.prefix}] ${n}`,...e)}warn(n,...e){this.log(2,console.warn,`[${this.prefix}] WARN: ${n}`,...e)}error(n,...e){this.log(3,console.error,`[${this.prefix}] ERROR: ${n}`,...e)}};function Re(){if(typeof window>"u")return 2;let t=globalThis;return t.__VERYFRONT_DEV__||t.__RSC_DEV__?t.__VERYFRONT_DEBUG__||t.__RSC_DEBUG__?0:1:2}var D=Re(),y=new b("RSC",D),hn=new b("PREFETCH",D),_n=new b("HYDRATE",D),Sn=new b("VERYFRONT",D);var Tn=Object.freeze({IPV4:"127.0.0.1",IPV6:"::1",HOSTNAME:"localhost"});var he=5e3,_e=1e4,Nn=16*1024*1024,Se=5e3;var Ae=100;var be=Object.freeze([5,10,25,50,75,100,250,500,750,1e3,2500,5e3,7500,1e4]),On=Object.freeze([1,5,10,25,50,100,250,500,1e3,2500,5e3,1e4]),Dn=Object.freeze({server:Object.freeze({port:3e3,hostname:"0.0.0.0"}),timeouts:Object.freeze({default:he,api:3e4,ssr:_e,hmr:3e4,sandbox:Se}),cache:Object.freeze({jit:Object.freeze({maxSize:Ae,tempDirPrefix:"vf-bundle-"})}),metrics:Object.freeze({ssrBoundaries:be})});var d="/_veryfront",H={RSC:`${d}/rsc/`,FS:`${d}/fs/`,MODULES:`${d}/modules/`,PAGES:`${d}/pages/`,DATA:`${d}/data/`,LIB:`${d}/lib/`,CHUNKS:`${d}/chunks/`,CLIENT:`${d}/client/`},ct={HMR_RUNTIME:`${d}/hmr-runtime.js`,HMR:`${d}/hmr.js`,ERROR_OVERLAY:`${d}/error-overlay.js`,DEV_LOADER:`${d}/dev-loader.js`,CLIENT_LOG:`${d}/log`,CLIENT_JS:`${d}/client.js`,ROUTER_JS:`${d}/router.js`,PREFETCH_JS:`${d}/prefetch.js`,MANIFEST_JSON:`${d}/manifest.json`,APP_JS:`${d}/app.js`,RSC_CLIENT:`${d}/rsc/client.js`,RSC_MANIFEST:`${d}/rsc/manifest`,RSC_STREAM:`${d}/rsc/stream`,RSC_PAYLOAD:`${d}/rsc/payload`,RSC_RENDER:`${d}/rsc/render`,RSC_PAGE:`${d}/rsc/page`,RSC_MODULE:`${d}/rsc/module`,RSC_DOM:`${d}/rsc/dom.js`,LIB_CHAT_REACT:`${d}/lib/chat/react.js`,LIB_CHAT_COMPONENTS:`${d}/lib/chat/components.js`,LIB_CHAT_PRIMITIVES:`${d}/lib/chat/primitives.js`};var Te={ROOT:".veryfront",CACHE:".veryfront/cache",KV:".veryfront/kv",LOGS:".veryfront/logs",TMP:".veryfront/tmp"},wn=Te.CACHE;var Ln={HMR_RUNTIME:ct.HMR_RUNTIME,ERROR_OVERLAY:ct.ERROR_OVERLAY};var Ce=H.RSC,Ie=H.FS;var ut="rsc-root",z="x-veryfront-dependency-pins";var Hn=Array.prototype.at,zn=Array.prototype.filter,Vn=Array.prototype.join,jn=Array.prototype.map,Fn=Array.prototype.pop,Gn=Array.prototype.push,vn=Array.prototype.sort;var sr=Object.freeze({react:"","react-dom":"","react-dom/client":"","react-dom/server":"","react/jsx-runtime":"","react/jsx-dev-runtime":""});var Oe="veryfront-hydration-data";function lt(t){try{let n=[...t.querySelectorAll(`[id="${Oe}"]`)];if(n.length!==1)return null;let e=t.body;if(!e)return null;let r=n[0];return e.firstElementChild!==r&&r.parentElement!==e||r.tagName?.toLowerCase()!=="script"||r.getAttribute("type")?.trim().toLowerCase()!=="application/json"?null:r}catch{return null}}function dt(t,n){if(!n?.startsWith("on:"))return!1;try{let e=lt(t);if(!e)return!1;let r=JSON.parse(e.textContent||"{}");return r.dependencyPinningCacheKey=n,e.textContent=JSON.stringify(r),!0}catch(e){return y.debug("hydration dependency snapshot seed failed",e),!1}}function ft(t,n){let e=n==="root"?ut:`rsc-slot-${n}`,r=t.getElementById(e);if(r)return r;let o=t.createElement("div");return o.id=e,t.body.appendChild(o),o}function De(t,n){if(n.type!=="slot")return;let e=ft(t,n.id);e.innerHTML=it(String(n.html??""))}function gt(t,n){let e=n.split(`\n`),r=e.pop()??"";for(let o of e){let s=o.trim();if(!s)continue;let i;try{i=JSON.parse(s)}catch(u){y.debug("[client-dom] malformed NDJSON line",{line:s,error:u instanceof Error?u.message:String(u)});continue}if(!i||typeof i!="object")continue;let a=i;if(a.type==="slot"){De(t,a);try{Le(t,a.id||"root")}catch(u){y.debug("[client-dom] hydration optional failed",u)}}}return r}function $e(t){return new Promise((n,e)=>{let r=()=>e(new DOMException("aborted","AbortError"));if(t.aborted){r();return}t.addEventListener("abort",r,{once:!0})})}async function Tr(t,n=document,e){let r="body"in t?t:null,o=r?.body??t;if(!o)return;r&&dt(n,r.headers.get(z));let s=o.getReader(),i=new TextDecoder,a="",u=!1;try{for(;;){if(e?.aborted)throw new DOMException("aborted","AbortError");let c=s.read(),{done:l,value:f}=e?await Promise.race([c,$e(e)]):await c;if(l){u=!0;break}a+=i.decode(f,{stream:!0}),a=gt(n,a)}a&>(n,`${a}\n`)}catch(c){throw c instanceof Error&&c.name==="AbortError"||y.debug("[client-dom] consumeNdjsonStream error",c),c}finally{try{await s.cancel()}catch(c){u||y.debug("[client-dom] reader.cancel failed",c)}try{s.releaseLock()}catch(c){y.debug("[client-dom] reader.releaseLock failed",c)}if(typeof o.cancel=="function")try{await o.cancel()}catch(c){y.debug("[client-dom] stream.cancel failed",c)}if(typeof r?.body?.cancel=="function")try{await r.body.cancel()}catch(c){y.debug("[client-dom] response.body.cancel failed",c)}}}function we(t,n){let e=ft(t,n),r=[],o=s=>{let i=s;i.dataset?.clientRef&&r.push(i);for(let a of s.children)o(a)};return o(e),r}function Le(t,n){let e=we(t,n);for(let r of e){let o=r.dataset?.clientRef;o&&(r.dataset.hydrated="true",y.debug("[client-dom] marked for hydration",o))}}export{Tr as consumeNdjsonStream,ft as getContainer};\n'; diff --git a/tests/docs/error-docs-links.test.ts b/tests/docs/error-docs-links.test.ts new file mode 100644 index 0000000000..2385308084 --- /dev/null +++ b/tests/docs/error-docs-links.test.ts @@ -0,0 +1,171 @@ +import { assert, assertEquals } from "#veryfront/testing/assert.ts"; +import { describe, it } from "#veryfront/testing/bdd.ts"; +import { ERROR_REGISTRY, getAllSlugs } from "../../src/errors/error-registry.ts"; +import { buildErrorDocsUrl, ERROR_DOCS_BASE_URL } from "../../src/errors/diagnostic-policy.ts"; +import { escapeMdxText } from "../../scripts/docs/generate-error-reference.ts"; + +/** + * Every error slug the registry can emit is printed to users as a docs URL by + * the CLI, HTTP, and log boundaries. These tests iterate the registry rather + * than sampling known slugs, so adding an error without publishing its + * destination fails here instead of shipping a dead link. + */ + +/** Prefix under which veryfront-code's docs/ tree is published. */ +const PUBLISHED_DOCS_PREFIX = "https://veryfront.com/docs/code/"; + +/** + * Resolve the published error-docs URL back to the repository file that has to + * carry its anchors. Deriving the path (instead of hardcoding it) means moving + * the page without moving ERROR_DOCS_BASE_URL fails this test. + */ +function localFileForDocsBaseUrl(baseUrl: string): string { + const withoutFragment = baseUrl.split("#")[0]; + assert( + withoutFragment.startsWith(PUBLISHED_DOCS_PREFIX), + `ERROR_DOCS_BASE_URL must point into the published veryfront-code docs tree ` + + `(${PUBLISHED_DOCS_PREFIX}...), got: ${baseUrl}`, + ); + const docPath = withoutFragment.slice(PUBLISHED_DOCS_PREFIX.length); + return `docs/${docPath}.md`; +} + +/** + * Anchor ids a Mintlify page exposes. Headings are slugified, and the slugs in + * this registry are already lowercase-and-hyphen, so the heading text is the + * anchor. + */ +function anchorsIn(markdown: string): Set { + const anchors = new Set(); + for (const line of markdown.split("\n")) { + const heading = /^#{2,6}\s+(.+?)\s*$/.exec(line); + if (heading) anchors.add(heading[1].toLowerCase().replace(/\s+/g, "-")); + } + return anchors; +} + +async function* walkTypeScript(dir: string): AsyncGenerator { + for await (const entry of Deno.readDir(dir)) { + const path = `${dir}/${entry.name}`; + if (entry.isDirectory) yield* walkTypeScript(path); + else if (entry.isFile && (path.endsWith(".ts") || path.endsWith(".tsx"))) yield path; + } +} + +describe("error docs links", () => { + it("points every registered slug at a published destination", async () => { + const docFile = localFileForDocsBaseUrl(ERROR_DOCS_BASE_URL); + const markdown = await Deno.readTextFile(docFile); + const anchors = anchorsIn(markdown); + const pagePath = new URL(ERROR_DOCS_BASE_URL.split("#")[0]).pathname; + + const slugs = getAllSlugs(); + assert(slugs.length > 0, "registry must not be empty"); + + const dead: string[] = []; + for (const slug of slugs) { + const url = new URL(buildErrorDocsUrl(slug)); + // The URL must resolve to the published page... + if (url.pathname !== pagePath) { + dead.push(`${slug}: resolves to ${url.pathname}, not ${pagePath}`); + continue; + } + // ...and to a real anchor on it. + const fragment = decodeURIComponent(url.hash.replace(/^#/, "")); + if (!anchors.has(fragment)) { + dead.push(`${slug}: no "#${fragment}" anchor in ${docFile}`); + } + } + + assertEquals( + dead, + [], + `${dead.length} of ${slugs.length} error slugs link to a destination that does not exist:\n` + + dead.join("\n"), + ); + }); + + it("documents the fallback slug used when an error carries no usable slug", async () => { + const docFile = localFileForDocsBaseUrl(ERROR_DOCS_BASE_URL); + const anchors = anchorsIn(await Deno.readTextFile(docFile)); + // diagnostic-policy falls back to "unknown-error" for non-string slugs. + const fragment = decodeURIComponent( + new URL(buildErrorDocsUrl(undefined)).hash.replace(/^#/, ""), + ); + assert( + anchors.has(fragment), + `fallback slug "#${fragment}" has no anchor in ${docFile}`, + ); + }); + + it("does not document anchors for slugs the registry no longer emits", async () => { + const docFile = localFileForDocsBaseUrl(ERROR_DOCS_BASE_URL); + const markdown = await Deno.readTextFile(docFile); + const registered = new Set(getAllSlugs()); + // Slug anchors are the level-3 headings; section headings are level 2. + const slugHeadings = [...markdown.matchAll(/^###\s+(.+?)\s*$/gm)].map((m) => m[1]); + const stale = slugHeadings.filter((heading) => !registered.has(heading)); + assertEquals(stale, [], `documented slugs no longer in the registry: ${stale.join(", ")}`); + }); + + it("escapes registry text that MDX would parse as markup", async () => { + // The published page renders as MDX. Registry text like "--port " + // parses as an unclosed JSX tag and fails the docs build, so the whole + // page must carry no unescaped "<" or "{". + const docFile = localFileForDocsBaseUrl(ERROR_DOCS_BASE_URL); + const markdown = await Deno.readTextFile(docFile); + const unescaped: string[] = []; + markdown.split("\n").forEach((line, index) => { + if (/(^|[^\\])[<{]/.test(line)) unescaped.push(`${docFile}:${index + 1}: ${line.trim()}`); + }); + assertEquals( + unescaped, + [], + `unescaped MDX markup characters would break the docs build:\n${unescaped.join("\n")}`, + ); + }); + + it("builds every shipped error docs link through the shared builder", async () => { + // A hardcoded link bypasses buildErrorDocsUrl and so bypasses every check + // above -- it can rot into a 404 on its own. + const offenders: string[] = []; + const roots = ["src", "cli"]; + for (const root of roots) { + for await (const entry of walkTypeScript(root)) { + if (entry.endsWith(".test.ts") || entry.includes(".generated.")) continue; + const source = await Deno.readTextFile(entry); + for (const line of source.split("\n")) { + // The constant itself and doc comments describing the shape are fine. + if (entry.endsWith("src/errors/diagnostic-policy.ts")) continue; + if (!line.includes("veryfront.com/docs/code/guides/errors#")) continue; + if (line.trimStart().startsWith("*") || line.trimStart().startsWith("//")) continue; + offenders.push(`${entry}: ${line.trim()}`); + } + } + } + assertEquals( + offenders, + [], + `hardcoded error docs links (use buildErrorDocsUrl instead):\n${offenders.join("\n")}`, + ); + }); + + it("documents the title and suggestion the boundaries print for each slug", async () => { + const docFile = localFileForDocsBaseUrl(ERROR_DOCS_BASE_URL); + const markdown = await Deno.readTextFile(docFile); + const missing: string[] = []; + for (const slug of getAllSlugs()) { + const entry = (ERROR_REGISTRY as Record)[slug]; + // Registry text is MDX-escaped on the page (see escapeMdxText), so + // compare against the escaped form the reader actually gets. + if (!markdown.includes(escapeMdxText(entry.title))) missing.push(`${slug}: title`); + if (entry.suggestion && !markdown.includes(escapeMdxText(entry.suggestion))) { + missing.push(`${slug}: suggestion`); + } + } + assertEquals(missing, [], `page is missing registry content:\n${missing.join("\n")}`); + }); +}); diff --git a/tests/docs/guide-contracts.test.ts b/tests/docs/guide-contracts.test.ts index 071e63f19a..491271057d 100644 --- a/tests/docs/guide-contracts.test.ts +++ b/tests/docs/guide-contracts.test.ts @@ -307,6 +307,10 @@ const GUIDE_CONTRACTS: Record = { references: ["../api-reference/veryfront/extensions.md"], snippets: ["defineConfig", "extRedis", "First-party extension areas"], }, + "guides/errors.md": { + references: [], + snippets: ["### port-in-use", "**HTTP status:**", "**What to do:**"], + }, "guides/evals.md": { references: ["../api-reference/veryfront/eval.md"], snippets: [ @@ -811,6 +815,8 @@ describe("published guide contracts", () => { !CONCEPT_FILES.has(filename) && filename !== "getting-started/index.md" && filename !== "guides/index.md" && + // A generated lookup table of error slugs, not a procedure to follow. + filename !== "guides/errors.md" && filename !== "getting-started/installation.md" ) { assertStringIncludes(guide, "## Verify it worked"); diff --git a/tests/e2e/regressions/rsc-proxy-hydration.test.ts b/tests/e2e/regressions/rsc-proxy-hydration.test.ts index 52d53fbd75..a668533106 100644 --- a/tests/e2e/regressions/rsc-proxy-hydration.test.ts +++ b/tests/e2e/regressions/rsc-proxy-hydration.test.ts @@ -271,7 +271,7 @@ async function assertSharedRuntimeExecutionUnavailable( }; assertEquals( problem.type, - "https://veryfront.com/docs/errors/project-execution-unavailable", + "https://veryfront.com/docs/code/guides/errors#project-execution-unavailable", ); assertEquals(problem.status, 503); assertEquals(problem.detail?.startsWith("Shared runtimes"), true);