veryfront 0.1.129 → 0.1.131
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/esm/cli/auth/login.d.ts.map +1 -1
- package/esm/cli/auth/login.js +11 -0
- package/esm/cli/auth/provider-store.d.ts +20 -0
- package/esm/cli/auth/provider-store.d.ts.map +1 -0
- package/esm/cli/auth/provider-store.js +62 -0
- package/esm/cli/auth/providers/anthropic.d.ts +2 -0
- package/esm/cli/auth/providers/anthropic.d.ts.map +1 -0
- package/esm/cli/auth/providers/anthropic.js +37 -0
- package/esm/cli/auth/providers/openai.d.ts +2 -0
- package/esm/cli/auth/providers/openai.d.ts.map +1 -0
- package/esm/cli/auth/providers/openai.js +35 -0
- package/esm/cli/auth/utils.d.ts +5 -0
- package/esm/cli/auth/utils.d.ts.map +1 -1
- package/esm/cli/auth/utils.js +9 -0
- package/esm/cli/commands/config/command-help.d.ts +3 -0
- package/esm/cli/commands/config/command-help.d.ts.map +1 -0
- package/esm/cli/commands/config/command-help.js +13 -0
- package/esm/cli/commands/config/handler.d.ts +5 -0
- package/esm/cli/commands/config/handler.d.ts.map +1 -0
- package/esm/cli/commands/config/handler.js +70 -0
- package/esm/cli/commands/open/command-help.d.ts +3 -0
- package/esm/cli/commands/open/command-help.d.ts.map +1 -0
- package/esm/cli/commands/open/command-help.js +17 -0
- package/esm/cli/commands/open/command.d.ts +14 -0
- package/esm/cli/commands/open/command.d.ts.map +1 -0
- package/esm/cli/commands/open/command.js +22 -0
- package/esm/cli/commands/open/handler.d.ts +3 -0
- package/esm/cli/commands/open/handler.d.ts.map +1 -0
- package/esm/cli/commands/open/handler.js +29 -0
- package/esm/cli/help/command-definitions.d.ts.map +1 -1
- package/esm/cli/help/command-definitions.js +4 -0
- package/esm/cli/router.d.ts.map +1 -1
- package/esm/cli/router.js +26 -1
- package/esm/deno.js +1 -1
- package/esm/src/channels/control-plane.js +6 -6
- package/esm/src/discovery/handlers/agent-handler.d.ts.map +1 -1
- package/esm/src/discovery/handlers/agent-handler.js +10 -1
- package/esm/src/platform/compat/framework-source-resolver.d.ts +8 -0
- package/esm/src/platform/compat/framework-source-resolver.d.ts.map +1 -1
- package/esm/src/platform/compat/framework-source-resolver.js +77 -1
- package/esm/src/rendering/rsc/client-boot.ts +18 -1
- package/esm/src/server/handlers/preview/markdown-html-generator.d.ts +2 -0
- package/esm/src/server/handlers/preview/markdown-html-generator.d.ts.map +1 -1
- package/esm/src/server/handlers/preview/markdown-html-generator.js +10 -7
- package/esm/src/server/handlers/preview/markdown-preview.handler.d.ts.map +1 -1
- package/esm/src/server/handlers/preview/markdown-preview.handler.js +6 -3
- package/esm/src/server/handlers/request/api/project-discovery.d.ts.map +1 -1
- package/esm/src/server/handlers/request/api/project-discovery.js +16 -5
- package/esm/src/server/handlers/request/api/security-headers.d.ts +1 -0
- package/esm/src/server/handlers/request/api/security-headers.d.ts.map +1 -1
- package/esm/src/server/handlers/request/api/security-headers.js +4 -1
- package/esm/src/server/handlers/request/openapi-docs.handler.d.ts.map +1 -1
- package/esm/src/server/handlers/request/openapi-docs.handler.js +10 -6
- package/esm/src/server/handlers/request/rsc/index.d.ts.map +1 -1
- package/esm/src/server/handlers/request/rsc/index.js +5 -2
- package/esm/src/server/handlers/request/ssr/ssr-response-builder.d.ts.map +1 -1
- package/esm/src/server/handlers/request/ssr/ssr-response-builder.js +12 -2
- package/esm/src/server/handlers/response/not-found.d.ts.map +1 -1
- package/esm/src/server/handlers/response/not-found.js +14 -15
- package/esm/src/server/services/rsc/endpoints/endpoint-router.d.ts +1 -1
- package/esm/src/server/services/rsc/endpoints/endpoint-router.d.ts.map +1 -1
- package/esm/src/server/services/rsc/endpoints/endpoint-router.js +3 -3
- package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.d.ts.map +1 -1
- package/esm/src/server/services/rsc/endpoints/rsc-bundles.generated.js +1 -1
- package/esm/src/server/services/rsc/endpoints/types.d.ts +1 -0
- package/esm/src/server/services/rsc/endpoints/types.d.ts.map +1 -1
- package/esm/src/server/services/rsc/orchestrators/handler.d.ts +1 -1
- package/esm/src/server/services/rsc/orchestrators/handler.d.ts.map +1 -1
- package/esm/src/server/services/rsc/orchestrators/handler.js +2 -2
- package/esm/src/server/services/rsc/orchestrators/page-handler.d.ts +1 -1
- package/esm/src/server/services/rsc/orchestrators/page-handler.d.ts.map +1 -1
- package/esm/src/server/services/rsc/orchestrators/page-handler.js +7 -5
- package/esm/src/transforms/esm/import-parser.d.ts.map +1 -1
- package/esm/src/transforms/esm/import-parser.js +6 -0
- package/esm/src/transforms/pipeline/stages/ssr-vf-modules/path-resolver.d.ts +1 -1
- package/esm/src/transforms/pipeline/stages/ssr-vf-modules/path-resolver.d.ts.map +1 -1
- package/esm/src/transforms/pipeline/stages/ssr-vf-modules/path-resolver.js +10 -66
- package/esm/src/utils/version-constant.d.ts +1 -1
- package/esm/src/utils/version-constant.js +1 -1
- package/package.json +1 -1
- package/src/cli/auth/login.ts +12 -0
- package/src/cli/auth/provider-store.ts +82 -0
- package/src/cli/auth/providers/anthropic.ts +46 -0
- package/src/cli/auth/providers/openai.ts +45 -0
- package/src/cli/auth/utils.ts +10 -0
- package/src/cli/commands/config/command-help.ts +15 -0
- package/src/cli/commands/config/handler.ts +90 -0
- package/src/cli/commands/open/command-help.ts +19 -0
- package/src/cli/commands/open/command.ts +28 -0
- package/src/cli/commands/open/handler.ts +38 -0
- package/src/cli/help/command-definitions.ts +4 -0
- package/src/cli/router.ts +28 -1
- package/src/deno.js +1 -1
- package/src/src/channels/control-plane.ts +6 -6
- package/src/src/discovery/handlers/agent-handler.ts +10 -1
- package/src/src/platform/compat/framework-source-resolver.ts +101 -1
- package/src/src/server/handlers/preview/markdown-html-generator.ts +12 -6
- package/src/src/server/handlers/preview/markdown-preview.handler.ts +6 -3
- package/src/src/server/handlers/request/api/project-discovery.ts +18 -5
- package/src/src/server/handlers/request/api/security-headers.ts +10 -1
- package/src/src/server/handlers/request/openapi-docs.handler.ts +10 -6
- package/src/src/server/handlers/request/rsc/index.ts +5 -2
- package/src/src/server/handlers/request/ssr/ssr-response-builder.ts +16 -2
- package/src/src/server/handlers/response/not-found.ts +14 -15
- package/src/src/server/services/rsc/endpoints/endpoint-router.ts +3 -3
- package/src/src/server/services/rsc/endpoints/rsc-bundles.generated.ts +1 -1
- package/src/src/server/services/rsc/endpoints/types.ts +1 -0
- package/src/src/server/services/rsc/orchestrators/handler.ts +2 -2
- package/src/src/server/services/rsc/orchestrators/page-handler.ts +8 -5
- package/src/src/transforms/esm/import-parser.ts +12 -0
- package/src/src/transforms/pipeline/stages/ssr-vf-modules/path-resolver.ts +10 -69
- package/src/src/utils/version-constant.ts +1 -1
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import { join } from "./path/index.js";
|
|
2
2
|
import { createFileSystem } from "./fs.js";
|
|
3
|
-
import { getFrameworkRootFromMeta } from "./vfs-paths.js";
|
|
3
|
+
import { getFrameworkRoot, getFrameworkRootFromMeta } from "./vfs-paths.js";
|
|
4
4
|
export const FRAMEWORK_ROOT = getFrameworkRootFromMeta(globalThis[Symbol.for("import-meta-ponyfill-esmodule")](import.meta).url);
|
|
5
|
+
export const FRAMEWORK_SRC_DIR = join(FRAMEWORK_ROOT, "src");
|
|
5
6
|
export const FRAMEWORK_EMBEDDED_SRC_DIR = join(FRAMEWORK_ROOT, "dist", "framework-src");
|
|
6
7
|
export const DEFAULT_FRAMEWORK_SOURCE_EXTENSIONS = [
|
|
7
8
|
".tsx.src",
|
|
@@ -31,6 +32,40 @@ export function getFrameworkSourceLookupDirs(extraLookupDirs = []) {
|
|
|
31
32
|
return true;
|
|
32
33
|
});
|
|
33
34
|
}
|
|
35
|
+
export function isFrameworkSourcePath(path) {
|
|
36
|
+
return path.startsWith(`${FRAMEWORK_SRC_DIR}/`) ||
|
|
37
|
+
path.startsWith(`${FRAMEWORK_EMBEDDED_SRC_DIR}/`);
|
|
38
|
+
}
|
|
39
|
+
function expandFrameworkCandidatePaths(candidatePath) {
|
|
40
|
+
const candidates = [candidatePath];
|
|
41
|
+
const candidateRoot = getFrameworkRoot(candidatePath);
|
|
42
|
+
const candidateSrcDir = candidateRoot ? join(candidateRoot, "src") : FRAMEWORK_SRC_DIR;
|
|
43
|
+
const candidateEmbeddedDir = candidateRoot
|
|
44
|
+
? join(candidateRoot, "dist", "framework-src")
|
|
45
|
+
: FRAMEWORK_EMBEDDED_SRC_DIR;
|
|
46
|
+
if (candidatePath.startsWith(`${candidateSrcDir}/`)) {
|
|
47
|
+
const relativePath = candidatePath.slice(candidateSrcDir.length + 1);
|
|
48
|
+
candidates.push(join(candidateEmbeddedDir, relativePath));
|
|
49
|
+
}
|
|
50
|
+
return [...new Set(candidates)];
|
|
51
|
+
}
|
|
52
|
+
async function findExistingFrameworkCandidate(candidatePath, options = {}) {
|
|
53
|
+
const fs = options.fileSystem ?? createFileSystem();
|
|
54
|
+
const exists = options.exists ?? (async (path) => {
|
|
55
|
+
try {
|
|
56
|
+
const stat = await fs.stat(path);
|
|
57
|
+
return stat.isFile;
|
|
58
|
+
}
|
|
59
|
+
catch {
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
});
|
|
63
|
+
for (const candidate of expandFrameworkCandidatePaths(candidatePath)) {
|
|
64
|
+
if (await exists(candidate))
|
|
65
|
+
return candidate;
|
|
66
|
+
}
|
|
67
|
+
return null;
|
|
68
|
+
}
|
|
34
69
|
export async function resolveFrameworkSourcePath(relativePathWithoutExt, options = {}) {
|
|
35
70
|
const fs = options.fileSystem ?? createFileSystem();
|
|
36
71
|
const lookupDirs = getFrameworkSourceLookupDirs(options.extraLookupDirs);
|
|
@@ -60,3 +95,44 @@ export async function resolveFrameworkSourcePath(relativePathWithoutExt, options
|
|
|
60
95
|
}
|
|
61
96
|
return null;
|
|
62
97
|
}
|
|
98
|
+
export async function resolveRelativeFrameworkSourceImport(specifier, fromSourcePath, options = {}) {
|
|
99
|
+
const extensions = options.extensions ?? DEFAULT_FRAMEWORK_SOURCE_EXTENSIONS;
|
|
100
|
+
const fromDir = fromSourcePath.substring(0, fromSourcePath.lastIndexOf("/"));
|
|
101
|
+
const parts = fromDir.split("/").filter(Boolean);
|
|
102
|
+
const importParts = specifier.split("/").filter(Boolean);
|
|
103
|
+
for (const part of importParts) {
|
|
104
|
+
if (part === "..") {
|
|
105
|
+
parts.pop();
|
|
106
|
+
}
|
|
107
|
+
else if (part !== ".") {
|
|
108
|
+
parts.push(part);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
const basePath = "/" + parts.join("/");
|
|
112
|
+
if (/\.(tsx?|jsx?|mjs)$/.test(specifier)) {
|
|
113
|
+
const explicitCandidates = [basePath, `${basePath}.src`];
|
|
114
|
+
if (basePath.endsWith(".js") || basePath.endsWith(".mjs")) {
|
|
115
|
+
const stem = basePath.replace(/\.(?:m?js)$/, "");
|
|
116
|
+
for (const ext of [".ts", ".tsx", ".jsx", ".js", ".mjs"]) {
|
|
117
|
+
explicitCandidates.push(`${stem}${ext}.src`, `${stem}${ext}`);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
for (const candidate of explicitCandidates) {
|
|
121
|
+
const resolved = await findExistingFrameworkCandidate(candidate, options);
|
|
122
|
+
if (resolved)
|
|
123
|
+
return resolved;
|
|
124
|
+
}
|
|
125
|
+
return null;
|
|
126
|
+
}
|
|
127
|
+
for (const ext of extensions) {
|
|
128
|
+
const candidate = await findExistingFrameworkCandidate(basePath + ext, options);
|
|
129
|
+
if (candidate)
|
|
130
|
+
return candidate;
|
|
131
|
+
}
|
|
132
|
+
for (const ext of extensions) {
|
|
133
|
+
const candidate = await findExistingFrameworkCandidate(join(basePath, "index" + ext), options);
|
|
134
|
+
if (candidate)
|
|
135
|
+
return candidate;
|
|
136
|
+
}
|
|
137
|
+
return null;
|
|
138
|
+
}
|
|
@@ -6,6 +6,7 @@
|
|
|
6
6
|
import type { ClientModuleStrategy } from "./client-module-strategy.ts";
|
|
7
7
|
import {
|
|
8
8
|
buildClientModuleUrl,
|
|
9
|
+
type ClientRuntimeHydrationData,
|
|
9
10
|
getHydrationReactImportSpecifiers,
|
|
10
11
|
readHydrationData,
|
|
11
12
|
resolveClientModuleStrategy,
|
|
@@ -58,6 +59,18 @@ export function selectHydrationRoot<T extends HydrationRootCandidate>(
|
|
|
58
59
|
fallback;
|
|
59
60
|
}
|
|
60
61
|
|
|
62
|
+
interface RSCBootDocument {
|
|
63
|
+
getElementById(id: string): Element | null;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
export function shouldAttemptRSCTransport(
|
|
67
|
+
doc: RSCBootDocument,
|
|
68
|
+
hydrationData: ClientRuntimeHydrationData | null,
|
|
69
|
+
): boolean {
|
|
70
|
+
if (hydrationData?.pagePath) return false;
|
|
71
|
+
return !!doc.getElementById(RSC_ROOT_ID);
|
|
72
|
+
}
|
|
73
|
+
|
|
61
74
|
async function tryStream(q: string): Promise<boolean> {
|
|
62
75
|
try {
|
|
63
76
|
const res = await fetch(RSC_PATH_PREFIX + "stream" + q);
|
|
@@ -151,8 +164,12 @@ export async function boot(): Promise<void> {
|
|
|
151
164
|
console.debug?.("[RSC] Found page component in hydration data:", pagePath);
|
|
152
165
|
if (await hydratePageComponent(pagePath, clientModuleStrategy)) {
|
|
153
166
|
console.debug?.("[RSC] Client component hydrated successfully");
|
|
154
|
-
return;
|
|
155
167
|
}
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (!shouldAttemptRSCTransport(document, hydrationData)) {
|
|
172
|
+
return;
|
|
156
173
|
}
|
|
157
174
|
|
|
158
175
|
if (await tryStream(q)) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown-html-generator.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/preview/markdown-html-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;
|
|
1
|
+
{"version":3,"file":"markdown-html-generator.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/preview/markdown-html-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;GAQG;AACH,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAMrD,oDAAoD;AACpD,UAAU,mBAAmB;IAC3B,wDAAwD;IACxD,OAAO,EAAE,MAAM,CAAC;IAChB,kDAAkD;IAClD,KAAK,EAAE,MAAM,CAAC;IACd,yCAAyC;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,iDAAiD;IACjD,OAAO,EAAE,OAAO,CAAC,OAAO,CAAC;IACzB,gDAAgD;IAChD,GAAG,EAAE,GAAG,CAAC;IACT,gDAAgD;IAChD,SAAS,EAAE,MAAM,CAAC;IAClB,sCAAsC;IACtC,QAAQ,EAAE,MAAM,CAAC;IACjB,oCAAoC;IACpC,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAyDD;;;;;;GAMG;AACH,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,mBAAmB,GAAG,MAAM,CA2FzE"}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import { escapeHtml } from "../../../utils/html-escape.js";
|
|
2
|
+
import { buildNonceAttribute } from "../../../html/html-escape.js";
|
|
2
3
|
/**
|
|
3
4
|
* Detect the preferred color theme from request parameters and client hints.
|
|
4
5
|
*
|
|
@@ -23,10 +24,11 @@ function detectTheme(req, url) {
|
|
|
23
24
|
* Generate the studio bridge `<script>` tag.
|
|
24
25
|
* Injected only when embedded in Studio (`studio_embed=true`).
|
|
25
26
|
*/
|
|
26
|
-
function buildStudioScript(url, projectId, filePath) {
|
|
27
|
+
function buildStudioScript(url, projectId, filePath, nonce) {
|
|
27
28
|
const studioEmbed = url.searchParams.get("studio_embed") === "true";
|
|
28
29
|
if (!studioEmbed)
|
|
29
30
|
return "";
|
|
31
|
+
const nonceAttr = buildNonceAttribute(nonce);
|
|
30
32
|
const rawQueryProjectId = url.searchParams.get("vf_project_id")?.trim() || "";
|
|
31
33
|
// Validate query param before using it in bridge config.
|
|
32
34
|
const queryProjectId = /^[a-zA-Z0-9_-]+$/.test(rawQueryProjectId) ? rawQueryProjectId : "";
|
|
@@ -40,8 +42,8 @@ function buildStudioScript(url, projectId, filePath) {
|
|
|
40
42
|
};
|
|
41
43
|
// Escape </script> sequences to prevent XSS breakout from inline JSON
|
|
42
44
|
const safeJson = JSON.stringify(bridgeConfig).replace(/</g, "\\u003c");
|
|
43
|
-
return `<script>window.__VF_BRIDGE_CONFIG__=${safeJson};</script>
|
|
44
|
-
<script type="module" src="/_veryfront/studio-bridge.js"></script>`;
|
|
45
|
+
return `<script${nonceAttr}>window.__VF_BRIDGE_CONFIG__=${safeJson};</script>
|
|
46
|
+
<script type="module" src="/_veryfront/studio-bridge.js"${nonceAttr}></script>`;
|
|
45
47
|
}
|
|
46
48
|
/**
|
|
47
49
|
* Generate a complete HTML document for markdown preview rendering.
|
|
@@ -51,10 +53,11 @@ function buildStudioScript(url, projectId, filePath) {
|
|
|
51
53
|
* studio bridge integration.
|
|
52
54
|
*/
|
|
53
55
|
export function generateMarkdownHtml(options) {
|
|
54
|
-
const { rawHtml, title, description, request, url, projectId, filePath } = options;
|
|
56
|
+
const { rawHtml, title, description, request, url, projectId, filePath, nonce } = options;
|
|
55
57
|
const theme = detectTheme(request, url);
|
|
56
|
-
const studioScript = buildStudioScript(url, projectId, filePath);
|
|
58
|
+
const studioScript = buildStudioScript(url, projectId, filePath, nonce);
|
|
57
59
|
const themeAttrs = theme ? ` data-theme="${theme}" style="color-scheme: ${theme};"` : "";
|
|
60
|
+
const nonceAttr = buildNonceAttribute(nonce);
|
|
58
61
|
return `<!DOCTYPE html>
|
|
59
62
|
<html lang="en"${themeAttrs}>
|
|
60
63
|
<head>
|
|
@@ -75,7 +78,7 @@ export function generateMarkdownHtml(options) {
|
|
|
75
78
|
|
|
76
79
|
${studioScript}
|
|
77
80
|
|
|
78
|
-
<script type="module">
|
|
81
|
+
<script type="module"${nonceAttr}>
|
|
79
82
|
import mermaid from 'https://esm.sh/mermaid@11.4.1?pin=v135';
|
|
80
83
|
|
|
81
84
|
function getMermaidTheme() {
|
|
@@ -135,7 +138,7 @@ export function generateMarkdownHtml(options) {
|
|
|
135
138
|
</script>
|
|
136
139
|
|
|
137
140
|
<!-- Preview HMR -->
|
|
138
|
-
<script src="/_veryfront/preview-hmr.js"></script>
|
|
141
|
+
<script src="/_veryfront/preview-hmr.js"${nonceAttr}></script>
|
|
139
142
|
</body>
|
|
140
143
|
</html>`;
|
|
141
144
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"markdown-preview.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/preview/markdown-preview.handler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAgBnG,qBAAa,sBAAuB,SAAQ,WAAW;IACrD,QAAQ,EAAE,eAAe,CAKvB;IAEI,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;YAmEjE,cAAc;
|
|
1
|
+
{"version":3,"file":"markdown-preview.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/preview/markdown-preview.handler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAgBnG,qBAAa,sBAAuB,SAAQ,WAAW;IACrD,QAAQ,EAAE,eAAe,CAKvB;IAEI,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;YAmEjE,cAAc;CAoF7B"}
|
|
@@ -103,6 +103,7 @@ export class MarkdownPreviewHandler extends BaseHandler {
|
|
|
103
103
|
return this.continue();
|
|
104
104
|
}
|
|
105
105
|
const bundle = await compileMarkdownRuntime("development", ctx.projectDir, body, frontmatter, filePath, "server");
|
|
106
|
+
const responseBuilder = this.createResponseBuilder(ctx);
|
|
106
107
|
const html = generateMarkdownHtml({
|
|
107
108
|
rawHtml: bundle.rawHtml || "",
|
|
108
109
|
title: frontmatter.title != null ? String(frontmatter.title) : filePath,
|
|
@@ -111,15 +112,17 @@ export class MarkdownPreviewHandler extends BaseHandler {
|
|
|
111
112
|
url,
|
|
112
113
|
projectId: ctx.projectSlug || ctx.projectId || "markdown-preview",
|
|
113
114
|
filePath,
|
|
115
|
+
nonce: responseBuilder.nonce,
|
|
114
116
|
});
|
|
115
|
-
|
|
117
|
+
responseBuilder
|
|
116
118
|
.withCache("no-cache")
|
|
117
|
-
.
|
|
119
|
+
.withSecurity(ctx.securityConfig ?? undefined, req);
|
|
120
|
+
const response = responseBuilder.withContentType("text/html; charset=utf-8", html, HTTP_OK);
|
|
118
121
|
logger.debug("Serving markdown preview", {
|
|
119
122
|
filePath,
|
|
120
123
|
htmlLength: html.length,
|
|
121
124
|
});
|
|
122
|
-
return this.respond(
|
|
125
|
+
return this.respond(response);
|
|
123
126
|
}
|
|
124
127
|
catch (error) {
|
|
125
128
|
logger.error("Error rendering markdown", {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"project-discovery.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/api/project-discovery.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"project-discovery.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/api/project-discovery.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AA+DrD;;;;;GAKG;AACH,wBAAsB,sBAAsB,CAAC,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,IAAI,CAAC,CA8D/E"}
|
|
@@ -12,6 +12,21 @@ const logger = serverLogger.component("api-wrapper");
|
|
|
12
12
|
* allows retry on failure (the key is deleted if discovery rejects).
|
|
13
13
|
*/
|
|
14
14
|
const discoveredProjects = new Map();
|
|
15
|
+
function buildDiscoveryConfig(ctx) {
|
|
16
|
+
const ai = ctx.config?.ai;
|
|
17
|
+
const skillDiscoveryEnabled = ai?.skills?.discovery?.enabled ?? true;
|
|
18
|
+
return {
|
|
19
|
+
baseDir: ctx.projectDir,
|
|
20
|
+
toolDirs: ai?.tools?.discovery?.paths ?? ["tools"],
|
|
21
|
+
agentDirs: ai?.agents?.discovery?.paths ?? ["agents"],
|
|
22
|
+
skillDirs: skillDiscoveryEnabled ? (ai?.skills?.discovery?.paths ?? ["skills"]) : [],
|
|
23
|
+
resourceDirs: ["resources"],
|
|
24
|
+
promptDirs: ["prompts"],
|
|
25
|
+
workflowDirs: ["workflows"],
|
|
26
|
+
fsAdapter: ctx.adapter.fs,
|
|
27
|
+
verbose: false,
|
|
28
|
+
};
|
|
29
|
+
}
|
|
15
30
|
/** Build a discovery cache key that incorporates the release/version. */
|
|
16
31
|
function discoveryKey(ctx) {
|
|
17
32
|
const cacheContext = tryGetCacheKeyContext();
|
|
@@ -59,11 +74,7 @@ export async function ensureProjectDiscovery(ctx) {
|
|
|
59
74
|
clearTranspileCache();
|
|
60
75
|
agentRegistry.clear();
|
|
61
76
|
toolRegistry.clear();
|
|
62
|
-
const result = await discoverAll(
|
|
63
|
-
baseDir: ctx.projectDir,
|
|
64
|
-
fsAdapter: ctx.adapter.fs,
|
|
65
|
-
verbose: false,
|
|
66
|
-
});
|
|
77
|
+
const result = await discoverAll(buildDiscoveryConfig(ctx));
|
|
67
78
|
const logData = {
|
|
68
79
|
projectSlug: ctx.projectSlug,
|
|
69
80
|
releaseId: ctx.releaseId,
|
|
@@ -3,4 +3,5 @@ import type { HandlerContext } from "../../types.js";
|
|
|
3
3
|
export declare function buildCSP(ctx: HandlerContext): string;
|
|
4
4
|
export declare function getSecurityHeader(headerName: string, defaultValue: string, ctx: HandlerContext): string;
|
|
5
5
|
export declare function applySecurityHeaders(headers: dntShim.Headers, ctx: HandlerContext, req?: dntShim.Request): void;
|
|
6
|
+
export declare function applySecurityHeadersWithNonce(headers: dntShim.Headers, ctx: HandlerContext, nonce: string, req?: dntShim.Request): void;
|
|
6
7
|
//# sourceMappingURL=security-headers.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"security-headers.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/api/security-headers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAarD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAQpD;AAED,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,cAAc,GAClB,MAAM,CAER;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,OAAO,GAAG,IAAI,
|
|
1
|
+
{"version":3,"file":"security-headers.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/api/security-headers.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AACxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAarD,wBAAgB,QAAQ,CAAC,GAAG,EAAE,cAAc,GAAG,MAAM,CAQpD;AAED,wBAAgB,iBAAiB,CAC/B,UAAU,EAAE,MAAM,EAClB,YAAY,EAAE,MAAM,EACpB,GAAG,EAAE,cAAc,GAClB,MAAM,CAER;AAED,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,EAAE,GAAG,CAAC,EAAE,OAAO,CAAC,OAAO,GAAG,IAAI,CAE/G;AAED,wBAAgB,6BAA6B,CAC3C,OAAO,EAAE,OAAO,CAAC,OAAO,EACxB,GAAG,EAAE,cAAc,EACnB,KAAK,EAAE,MAAM,EACb,GAAG,CAAC,EAAE,OAAO,CAAC,OAAO,GACpB,IAAI,CAaN"}
|
|
@@ -10,7 +10,10 @@ export function getSecurityHeader(headerName, defaultValue, ctx) {
|
|
|
10
10
|
return coreGetSecurityHeader(headerName, defaultValue, ctx.securityConfig, ctx.adapter);
|
|
11
11
|
}
|
|
12
12
|
export function applySecurityHeaders(headers, ctx, req) {
|
|
13
|
-
|
|
13
|
+
applySecurityHeadersWithNonce(headers, ctx, generateNonce(), req);
|
|
14
|
+
}
|
|
15
|
+
export function applySecurityHeadersWithNonce(headers, ctx, nonce, req) {
|
|
16
|
+
coreApplySecurityHeaders(headers, isDev(ctx), nonce, ctx.cspUserHeader ?? null, ctx.securityConfig, ctx.adapter, ctx.parsedDomain?.allowIframeEmbed ?? false);
|
|
14
17
|
if (req) {
|
|
15
18
|
applyCsrfCookie(req, headers, ctx.securityConfig?.csrf);
|
|
16
19
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"openapi-docs.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/request/openapi-docs.handler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAWnG,qBAAa,kBAAmB,SAAQ,WAAW;IACjD,QAAQ,EAAE,eAAe,CAKvB;cAEiB,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO;IAMnF,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"openapi-docs.handler.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/request/openapi-docs.handler.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AAGrD,OAAO,EAAE,WAAW,EAAE,MAAM,qBAAqB,CAAC;AAClD,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AAWnG,qBAAa,kBAAmB,SAAQ,WAAW;IACjD,QAAQ,EAAE,eAAe,CAKvB;cAEiB,YAAY,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO;IAMnF,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IAezE,OAAO,CAAC,gBAAgB;CAwCzB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { BaseHandler } from "../response/base.js";
|
|
2
2
|
import { HTTP_OK, PRIORITY_HIGH_DEV } from "../../../utils/constants/index.js";
|
|
3
|
-
import { escapeHtml } from "../../../html/html-escape.js";
|
|
3
|
+
import { buildNonceAttribute, escapeHtml } from "../../../html/html-escape.js";
|
|
4
4
|
/** Default paths */
|
|
5
5
|
const DEFAULT_DOCS_PATH = "/_docs";
|
|
6
6
|
const DEFAULT_JSON_PATH = "/_openapi.json";
|
|
@@ -21,17 +21,20 @@ export class OpenAPIDocsHandler extends BaseHandler {
|
|
|
21
21
|
handle(req, ctx) {
|
|
22
22
|
if (!this.shouldHandle(req, ctx))
|
|
23
23
|
return Promise.resolve(this.continue());
|
|
24
|
-
const html = this.generateDocsPage(ctx);
|
|
25
24
|
const isDev = !!ctx.isLocalProject;
|
|
26
|
-
const
|
|
25
|
+
const builder = this.createResponseBuilder(ctx);
|
|
26
|
+
const html = this.generateDocsPage(ctx, builder.nonce);
|
|
27
|
+
const response = builder
|
|
27
28
|
.withCache(isDev ? "no-cache" : { maxAge: DOCS_CACHE_MAX_AGE_SECONDS, public: true })
|
|
29
|
+
.withSecurity(ctx.securityConfig ?? undefined, req)
|
|
28
30
|
.withContentType("text/html; charset=utf-8", html, HTTP_OK);
|
|
29
31
|
return Promise.resolve(this.respond(response));
|
|
30
32
|
}
|
|
31
|
-
generateDocsPage(ctx) {
|
|
33
|
+
generateDocsPage(ctx, nonce) {
|
|
32
34
|
const specUrl = ctx.config?.openapi?.paths?.json ?? DEFAULT_JSON_PATH;
|
|
33
35
|
const title = escapeHtml(ctx.config?.openapi?.title ?? "API Documentation");
|
|
34
36
|
const description = escapeHtml(ctx.config?.openapi?.description ?? "");
|
|
37
|
+
const nonceAttr = buildNonceAttribute(nonce);
|
|
35
38
|
const configuration = JSON.stringify({
|
|
36
39
|
theme: "purple",
|
|
37
40
|
layout: "modern",
|
|
@@ -47,7 +50,7 @@ export class OpenAPIDocsHandler extends BaseHandler {
|
|
|
47
50
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
48
51
|
<title>${title}</title>
|
|
49
52
|
${description ? `<meta name="description" content="${description}"/>` : ""}
|
|
50
|
-
<style>
|
|
53
|
+
<style${nonceAttr}>
|
|
51
54
|
body {
|
|
52
55
|
margin: 0;
|
|
53
56
|
padding: 0;
|
|
@@ -59,8 +62,9 @@ export class OpenAPIDocsHandler extends BaseHandler {
|
|
|
59
62
|
id="api-reference"
|
|
60
63
|
data-url="${specUrl}"
|
|
61
64
|
data-configuration='${configuration}'
|
|
65
|
+
${nonce ? `nonce="${escapeHtml(nonce)}"` : ""}
|
|
62
66
|
></script>
|
|
63
|
-
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"></script>
|
|
67
|
+
<script src="https://cdn.jsdelivr.net/npm/@scalar/api-reference"${nonceAttr}></script>
|
|
64
68
|
</body>
|
|
65
69
|
</html>`;
|
|
66
70
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/rsc/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AAGxD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAEf,aAAa,EACd,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/rsc/index.ts"],"names":[],"mappings":"AAAA;;;;GAIG;AACH,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AAGxD,OAAO,EAAE,WAAW,EAAE,MAAM,wBAAwB,CAAC;AACrD,OAAO,KAAK,EACV,cAAc,EACd,eAAe,EAEf,aAAa,EACd,MAAM,gBAAgB,CAAC;AASxB,qBAAa,UAAW,SAAQ,WAAW;IACzC,QAAQ,EAAE,eAAe,CAIvB;IAEF,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;CAqD1E"}
|
|
@@ -7,10 +7,11 @@ import * as dntShim from "../../../../../_dnt.shims.js";
|
|
|
7
7
|
import { BaseHandler } from "../../response/base.js";
|
|
8
8
|
import { isRSCEnabled } from "../../../../utils/index.js";
|
|
9
9
|
import { handleRSCEndpoint } from "../../../services/rsc/endpoints/index.js";
|
|
10
|
-
import {
|
|
10
|
+
import { applySecurityHeadersWithNonce } from "../api/security-headers.js";
|
|
11
11
|
import { applyCORSHeaders } from "../../../../security/index.js";
|
|
12
12
|
import { HTTP_NOT_FOUND, PRIORITY_MEDIUM } from "../../../../utils/constants/index.js";
|
|
13
13
|
import { withSpan } from "../../../../observability/tracing/otlp-setup.js";
|
|
14
|
+
import { generateNonce } from "../../../../security/http/response/security-handler.js";
|
|
14
15
|
export class RSCHandler extends BaseHandler {
|
|
15
16
|
metadata = {
|
|
16
17
|
name: "RSCHandler",
|
|
@@ -29,6 +30,7 @@ export class RSCHandler extends BaseHandler {
|
|
|
29
30
|
if (!isRSCEnabled(ctx.config) && !isHydrationScript && !isDeprecatedEndpoint) {
|
|
30
31
|
return this.respond(new dntShim.Response("Not Found", { status: HTTP_NOT_FOUND }));
|
|
31
32
|
}
|
|
33
|
+
const nonce = generateNonce();
|
|
32
34
|
const res = await handleRSCEndpoint({
|
|
33
35
|
req,
|
|
34
36
|
pathname,
|
|
@@ -36,6 +38,7 @@ export class RSCHandler extends BaseHandler {
|
|
|
36
38
|
projectId: ctx.projectId,
|
|
37
39
|
adapter: ctx.adapter,
|
|
38
40
|
config: ctx.config,
|
|
41
|
+
nonce,
|
|
39
42
|
});
|
|
40
43
|
if (!res) {
|
|
41
44
|
return this.continue();
|
|
@@ -46,7 +49,7 @@ export class RSCHandler extends BaseHandler {
|
|
|
46
49
|
headers,
|
|
47
50
|
config: ctx.securityConfig?.cors,
|
|
48
51
|
});
|
|
49
|
-
|
|
52
|
+
applySecurityHeadersWithNonce(headers, ctx, nonce, req);
|
|
50
53
|
return this.respond(new dntShim.Response(res.body, {
|
|
51
54
|
status: res.status,
|
|
52
55
|
statusText: res.statusText,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ssr-response-builder.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/ssr/ssr-response-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AAGxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAElF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+CAA+C,CAAC;
|
|
1
|
+
{"version":3,"file":"ssr-response-builder.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/handlers/request/ssr/ssr-response-builder.ts"],"names":[],"mappings":"AAAA;;;;;;;GAOG;AACH,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AAGxD,OAAO,KAAK,EAAE,cAAc,EAAE,MAAM,gBAAgB,CAAC;AAGrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,4CAA4C,CAAC;AAElF,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,+CAA+C,CAAC;AAWrF;;;;;GAKG;AACH,wBAAsB,gBAAgB,CACpC,GAAG,EAAE,OAAO,CAAC,OAAO,EACpB,GAAG,EAAE,cAAc,EACnB,MAAM,EAAE,eAAe,EACvB,OAAO,EAAE,eAAe,GACvB,OAAO,CAAC,OAAO,CAAC,QAAQ,CAAC,CAuD3B"}
|
|
@@ -10,6 +10,11 @@ import * as dntShim from "../../../../../_dnt.shims.js";
|
|
|
10
10
|
import { hasMatchingEtag } from "../../utils/etag.js";
|
|
11
11
|
import { getContentType } from "../../utils/content-types.js";
|
|
12
12
|
import { ErrorPages } from "../../../utils/error-html.js";
|
|
13
|
+
import { escapeHtml } from "../../../../html/html-escape.js";
|
|
14
|
+
function addNonceToInlineTags(html, nonce) {
|
|
15
|
+
const escapedNonce = escapeHtml(nonce);
|
|
16
|
+
return html.replace(/<(script|style)\b(?![^>]*\bnonce\s*=)([^>]*)>/giu, `<$1$2 nonce="${escapedNonce}">`);
|
|
17
|
+
}
|
|
13
18
|
/**
|
|
14
19
|
* Build an HTTP response from an SSR render result.
|
|
15
20
|
*
|
|
@@ -41,8 +46,13 @@ export async function buildSSRResponse(req, ctx, result, builder) {
|
|
|
41
46
|
.notModified(result.etag);
|
|
42
47
|
}
|
|
43
48
|
// Buffered response path
|
|
44
|
-
const content = result.html
|
|
45
|
-
|
|
49
|
+
const content = typeof result.html === "string"
|
|
50
|
+
? result.html
|
|
51
|
+
: typeof result.stream === "string"
|
|
52
|
+
? result.stream
|
|
53
|
+
: ErrorPages.serverError();
|
|
54
|
+
const html = addNonceToInlineTags(content, builder.nonce);
|
|
55
|
+
const body = isHeadRequest ? null : html;
|
|
46
56
|
let response = builder
|
|
47
57
|
.withCORS(req, ctx.securityConfig?.cors)
|
|
48
58
|
.withSecurity(ctx.securityConfig ?? undefined, req)
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"not-found.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/response/not-found.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AASnG,qBAAa,eAAgB,SAAQ,WAAW;IAC9C,QAAQ,EAAE,eAAe,CAIvB;IAEF,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"not-found.d.ts","sourceRoot":"","sources":["../../../../../src/src/server/handlers/response/not-found.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,OAAO,MAAM,2BAA2B,CAAC;AACrD,OAAO,EAAE,WAAW,EAAE,MAAM,WAAW,CAAC;AACxC,OAAO,KAAK,EAAE,cAAc,EAAE,eAAe,EAAmB,aAAa,EAAE,MAAM,aAAa,CAAC;AASnG,qBAAa,eAAgB,SAAQ,WAAW;IAC9C,QAAQ,EAAE,eAAe,CAIvB;IAEF,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,OAAO,EAAE,GAAG,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC;IA8BzE,OAAO,CAAC,eAAe;CA4GxB"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { BaseHandler } from "./base.js";
|
|
2
2
|
import { ResponseBuilder } from "../../../security/index.js";
|
|
3
3
|
import { HTTP_INTERNAL_SERVER_ERROR, HTTP_NOT_FOUND, PRIORITY_FALLBACK, } from "../../../utils/constants/index.js";
|
|
4
|
-
import { escapeHtml } from "../../../html/html-escape.js";
|
|
4
|
+
import { buildNonceAttribute, escapeHtml } from "../../../html/html-escape.js";
|
|
5
5
|
export class NotFoundHandler extends BaseHandler {
|
|
6
6
|
metadata = {
|
|
7
7
|
name: "NotFoundHandler",
|
|
@@ -10,35 +10,34 @@ export class NotFoundHandler extends BaseHandler {
|
|
|
10
10
|
};
|
|
11
11
|
handle(req, ctx) {
|
|
12
12
|
const pathname = new URL(req.url).pathname;
|
|
13
|
-
const securityConfig = ctx.securityConfig;
|
|
14
|
-
const corsConfig = ctx.securityConfig?.cors;
|
|
15
13
|
try {
|
|
16
|
-
const
|
|
17
|
-
const
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
14
|
+
const builder = this.createResponseBuilder(ctx);
|
|
15
|
+
const html = this.generate404Html(pathname, builder.nonce);
|
|
16
|
+
const response = builder
|
|
17
|
+
.withCORS(req, ctx.securityConfig?.cors)
|
|
18
|
+
.withSecurity(ctx.securityConfig ?? undefined, req)
|
|
19
|
+
.withCache("no-cache")
|
|
20
|
+
.html(html, HTTP_NOT_FOUND);
|
|
23
21
|
return Promise.resolve(this.respond(response));
|
|
24
22
|
}
|
|
25
23
|
catch (e) {
|
|
26
24
|
this.logDebug("404 fallback error", { error: this.getErrorMessage(e) }, ctx);
|
|
27
25
|
const response = ResponseBuilder.error(HTTP_INTERNAL_SERVER_ERROR, "Internal Server Error", req, {
|
|
28
|
-
securityConfig,
|
|
29
|
-
corsConfig,
|
|
26
|
+
securityConfig: ctx.securityConfig,
|
|
27
|
+
corsConfig: ctx.securityConfig?.cors,
|
|
30
28
|
});
|
|
31
29
|
return Promise.resolve(this.respond(response));
|
|
32
30
|
}
|
|
33
31
|
}
|
|
34
|
-
generate404Html(pathname) {
|
|
32
|
+
generate404Html(pathname, nonce) {
|
|
33
|
+
const nonceAttr = buildNonceAttribute(nonce);
|
|
35
34
|
return `<!DOCTYPE html>
|
|
36
35
|
<html lang="en">
|
|
37
36
|
<head>
|
|
38
37
|
<meta charset="utf-8"/>
|
|
39
38
|
<meta name="viewport" content="width=device-width, initial-scale=1"/>
|
|
40
39
|
<title>404 Not Found</title>
|
|
41
|
-
<style>
|
|
40
|
+
<style${nonceAttr}>
|
|
42
41
|
body {
|
|
43
42
|
font-family: -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif;
|
|
44
43
|
margin: 0;
|
|
@@ -132,7 +131,7 @@ export class NotFoundHandler extends BaseHandler {
|
|
|
132
131
|
</p>
|
|
133
132
|
<div class="actions">
|
|
134
133
|
<a href="/" class="button">Go Home</a>
|
|
135
|
-
<a href="
|
|
134
|
+
<a href=".." class="button secondary">Go Back</a>
|
|
136
135
|
</div>
|
|
137
136
|
</div>
|
|
138
137
|
</body>
|
|
@@ -9,5 +9,5 @@ import type { RSCEndpointParams } from "./types.js";
|
|
|
9
9
|
* @param params - RSC endpoint parameters
|
|
10
10
|
* @returns Response or null if not an RSC endpoint
|
|
11
11
|
*/
|
|
12
|
-
export declare function handleRSCEndpoint({ req, pathname, projectDir, projectId, adapter, config }: RSCEndpointParams): Promise<dntShim.Response | null>;
|
|
12
|
+
export declare function handleRSCEndpoint({ req, pathname, projectDir, projectId, adapter, config, nonce }: RSCEndpointParams): Promise<dntShim.Response | null>;
|
|
13
13
|
//# sourceMappingURL=endpoint-router.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"endpoint-router.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/services/rsc/endpoints/endpoint-router.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AAexD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAKpD;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,EAAE,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,EAAE,iBAAiB,
|
|
1
|
+
{"version":3,"file":"endpoint-router.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/services/rsc/endpoints/endpoint-router.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,OAAO,KAAK,OAAO,MAAM,8BAA8B,CAAC;AAexD,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAKpD;;;;GAIG;AACH,wBAAsB,iBAAiB,CACrC,EAAE,GAAG,EAAE,QAAQ,EAAE,UAAU,EAAE,SAAS,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,EAAE,EAAE,iBAAiB,GAClF,OAAO,CAAC,OAAO,CAAC,QAAQ,GAAG,IAAI,CAAC,CAyHlC"}
|
|
@@ -19,7 +19,7 @@ const rscLog = serverLogger.component("rsc");
|
|
|
19
19
|
* @param params - RSC endpoint parameters
|
|
20
20
|
* @returns Response or null if not an RSC endpoint
|
|
21
21
|
*/
|
|
22
|
-
export async function handleRSCEndpoint({ req, pathname, projectDir, projectId, adapter, config }) {
|
|
22
|
+
export async function handleRSCEndpoint({ req, pathname, projectDir, projectId, adapter, config, nonce }) {
|
|
23
23
|
if (!pathname.startsWith("/_veryfront/rsc/")) {
|
|
24
24
|
return null;
|
|
25
25
|
}
|
|
@@ -51,7 +51,7 @@ export async function handleRSCEndpoint({ req, pathname, projectDir, projectId,
|
|
|
51
51
|
}
|
|
52
52
|
if (sub.startsWith("page/")) {
|
|
53
53
|
metrics.recordRSC("page");
|
|
54
|
-
return handler.handlePage(sub.replace("page/", ""), url.searchParams);
|
|
54
|
+
return handler.handlePage(sub.replace("page/", ""), url.searchParams, nonce);
|
|
55
55
|
}
|
|
56
56
|
if (sub.startsWith("stream/")) {
|
|
57
57
|
metrics.recordRSC("stream");
|
|
@@ -97,7 +97,7 @@ export async function handleRSCEndpoint({ req, pathname, projectDir, projectId,
|
|
|
97
97
|
}
|
|
98
98
|
if (sub === "page") {
|
|
99
99
|
metrics.recordRSC("page");
|
|
100
|
-
return handler.handlePage("/", url.searchParams);
|
|
100
|
+
return handler.handlePage("/", url.searchParams, nonce);
|
|
101
101
|
}
|
|
102
102
|
if (sub === "stream") {
|
|
103
103
|
metrics.recordRSC("stream");
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rsc-bundles.generated.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/services/rsc/endpoints/rsc-bundles.generated.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,kBAAkB,EAAE,
|
|
1
|
+
{"version":3,"file":"rsc-bundles.generated.d.ts","sourceRoot":"","sources":["../../../../../../src/src/server/services/rsc/endpoints/rsc-bundles.generated.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,eAAO,MAAM,kBAAkB,EAAE,MACunrB,CAAC;AAEzprB,eAAO,MAAM,iBAAiB,EAAE,MACgpiB,CAAC"}
|