eddev 2.3.31 → 2.4.0-beta.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/app/entry/ssr-root-client.d.ts +0 -2
- package/dist/app/entry/ssr-root-client.d.ts.map +1 -1
- package/dist/app/lib/blocks/block-debugger.d.ts.map +1 -1
- package/dist/app/lib/blocks/block-debugger.js +19 -2
- package/dist/app/lib/devtools/components/panels/StructurePanel.js +1 -1
- package/dist/app/server/assets.d.ts +45 -0
- package/dist/app/server/assets.d.ts.map +1 -0
- package/dist/app/server/assets.js +15 -0
- package/dist/app/server/index.d.ts +4 -0
- package/dist/app/server/index.d.ts.map +1 -1
- package/dist/app/server/index.js +3 -0
- package/dist/app/server/proxy-wp-admin.d.ts +6 -2
- package/dist/app/server/proxy-wp-admin.d.ts.map +1 -1
- package/dist/app/server/proxy-wp-admin.js +29 -57
- package/dist/app/server/render-ssr-page.d.ts +2 -6
- package/dist/app/server/render-ssr-page.d.ts.map +1 -1
- package/dist/app/server/render-ssr-page.js +9 -8
- package/dist/app/server/rpc-handler.d.ts +14 -0
- package/dist/app/server/rpc-handler.d.ts.map +1 -0
- package/dist/app/server/rpc-handler.js +63 -0
- package/dist/app/server/server-app.d.ts +22 -0
- package/dist/app/server/server-app.d.ts.map +1 -0
- package/dist/app/server/server-app.js +186 -0
- package/dist/app/server/server-context.d.ts +5 -5
- package/dist/app/server/server-context.d.ts.map +1 -1
- package/dist/app/server/server-context.js +21 -13
- package/dist/app/server/utils/fetch-origin.d.ts +13 -0
- package/dist/app/server/utils/fetch-origin.d.ts.map +1 -0
- package/dist/app/server/utils/fetch-origin.js +21 -0
- package/dist/app/server/utils/request.d.ts +20 -0
- package/dist/app/server/utils/request.d.ts.map +1 -0
- package/dist/app/server/utils/request.js +60 -0
- package/dist/node/cli/cli-worker.d.ts +10 -6
- package/dist/node/cli/cli-worker.d.ts.map +1 -1
- package/dist/node/cli/cli-worker.js +7 -14
- package/dist/node/cli/cli.js +37 -43
- package/dist/node/cli/display/CLIApp.d.ts +2 -4
- package/dist/node/cli/display/CLIApp.d.ts.map +1 -1
- package/dist/node/cli/display/CLIApp.js +2 -3
- package/dist/node/cli/version.d.ts +1 -1
- package/dist/node/cli/version.d.ts.map +1 -1
- package/dist/node/cli/version.js +1 -1
- package/dist/node/compiler/app-codegen.d.ts +18 -0
- package/dist/node/compiler/app-codegen.d.ts.map +1 -0
- package/dist/node/compiler/app-codegen.js +473 -0
- package/dist/node/compiler/build-serverless.d.ts +16 -0
- package/dist/node/compiler/build-serverless.d.ts.map +1 -0
- package/dist/node/compiler/build-serverless.js +40 -0
- package/dist/node/compiler/bundler.spa.d.ts +33 -0
- package/dist/node/compiler/bundler.spa.d.ts.map +1 -0
- package/dist/node/compiler/bundler.spa.js +59 -0
- package/dist/node/compiler/dev-css-links.d.ts +25 -0
- package/dist/node/compiler/dev-css-links.d.ts.map +1 -0
- package/dist/node/compiler/dev-css-links.js +87 -0
- package/dist/node/compiler/dev-server.d.ts +2 -0
- package/dist/node/compiler/dev-server.d.ts.map +1 -1
- package/dist/node/compiler/dev-server.js +43 -75
- package/dist/node/compiler/get-vite-config.d.ts +37 -6
- package/dist/node/compiler/get-vite-config.d.ts.map +1 -1
- package/dist/node/compiler/get-vite-config.js +113 -121
- package/dist/node/compiler/serverless-app.d.ts +35 -0
- package/dist/node/compiler/serverless-app.d.ts.map +1 -0
- package/dist/node/compiler/serverless-app.js +332 -0
- package/dist/node/compiler/transforms/block-meta.d.ts +10 -0
- package/dist/node/compiler/transforms/block-meta.d.ts.map +1 -0
- package/dist/node/compiler/transforms/block-meta.js +27 -0
- package/dist/node/compiler/transforms/component-names.d.ts +19 -0
- package/dist/node/compiler/transforms/component-names.d.ts.map +1 -0
- package/dist/node/compiler/transforms/component-names.js +45 -0
- package/dist/node/compiler/transforms/index.d.ts +36 -0
- package/dist/node/compiler/transforms/index.d.ts.map +1 -0
- package/dist/node/compiler/transforms/index.js +80 -0
- package/dist/node/compiler/transforms/types.d.ts +48 -0
- package/dist/node/compiler/transforms/types.d.ts.map +1 -0
- package/dist/node/compiler/transforms/types.js +1 -0
- package/dist/node/project/config.d.ts +1 -1
- package/dist/node/project/config.d.ts.map +1 -1
- package/dist/node/project/config.js +1 -1
- package/dist/node/project/env.js +1 -1
- package/dist/node/project/project-log.d.ts +7 -0
- package/dist/node/project/project-log.d.ts.map +1 -0
- package/dist/node/project/project-log.js +6 -0
- package/dist/node/project/project.d.ts +2 -2
- package/dist/node/project/project.d.ts.map +1 -1
- package/dist/node/project/project.js +3 -3
- package/dist/node/utils/fs.d.ts +70 -69
- package/dist/node/utils/fs.d.ts.map +1 -1
- package/package.json +12 -13
- package/skills/eddev/docs/devtool/cli.mdx +10 -8
- package/tsconfig.node.json +17 -5
- package/types.env.d.ts +1 -1
- package/dist/node/compiler/build-vinxi.d.ts +0 -9
- package/dist/node/compiler/build-vinxi.d.ts.map +0 -1
- package/dist/node/compiler/build-vinxi.js +0 -39
- package/dist/node/compiler/bundler.admin.d.ts +0 -14
- package/dist/node/compiler/bundler.admin.d.ts.map +0 -1
- package/dist/node/compiler/bundler.admin.js +0 -37
- package/dist/node/compiler/bundler.frontend.d.ts +0 -15
- package/dist/node/compiler/bundler.frontend.d.ts.map +0 -1
- package/dist/node/compiler/bundler.frontend.js +0 -51
- package/dist/node/compiler/vinxi-app.d.ts +0 -23
- package/dist/node/compiler/vinxi-app.d.ts.map +0 -1
- package/dist/node/compiler/vinxi-app.js +0 -261
- package/dist/node/compiler/vinxi-codegen.d.ts +0 -13
- package/dist/node/compiler/vinxi-codegen.d.ts.map +0 -1
- package/dist/node/compiler/vinxi-codegen.js +0 -764
|
@@ -0,0 +1,186 @@
|
|
|
1
|
+
import { invalidateByTag } from "@vercel/functions";
|
|
2
|
+
import { withTrailingSlash } from "ufo";
|
|
3
|
+
import { blockManifestReader } from "../lib/internal/read-block-manifest.js";
|
|
4
|
+
import { viewManifestReader } from "../lib/internal/read-view-manifest.js";
|
|
5
|
+
import { proxyWpAdmin } from "./proxy-wp-admin.js";
|
|
6
|
+
import { renderPageForIndexing } from "./render-ai-page.js";
|
|
7
|
+
import { renderPage } from "./render-ssr-page.js";
|
|
8
|
+
import { handleRPCRequest } from "./rpc-handler.js";
|
|
9
|
+
import { ServerContext } from "./server-context.js";
|
|
10
|
+
import { appendSetCookie, getCookie, getRawPath, getRequestHeaders, getRequestURL, withHeaders } from "./utils/request.js";
|
|
11
|
+
const BYPASS_COOKIE = "__prerender_bypass";
|
|
12
|
+
const json = (value, init) => Response.json(value, init);
|
|
13
|
+
const methodNotAllowed = () => new Response("Method Not Allowed", { status: 405 });
|
|
14
|
+
const isGet = (req) => req.method === "GET" || req.method === "HEAD";
|
|
15
|
+
/**
|
|
16
|
+
* The serverless app: route data, named queries and mutations, RPC procedures, WordPress proxying
|
|
17
|
+
* and server-rendered pages. Nitro calls `fetch` for every request that isn't a static asset or
|
|
18
|
+
* handled by a route rule (eg. the `/wp-content/**` proxies).
|
|
19
|
+
*/
|
|
20
|
+
export function createServerApp(opts) {
|
|
21
|
+
ServerContext.setRuntime({ assets: opts.assets });
|
|
22
|
+
async function handleData(req, url) {
|
|
23
|
+
const serverContext = ServerContext.main;
|
|
24
|
+
const path = url.pathname;
|
|
25
|
+
if (path === "/_data/route" || path.startsWith("/_data/route/")) {
|
|
26
|
+
if (!isGet(req))
|
|
27
|
+
return methodNotAllowed();
|
|
28
|
+
const pathname = path.slice("/_data/route".length) || "/";
|
|
29
|
+
return serverContext.fetchRouteData({
|
|
30
|
+
pathname,
|
|
31
|
+
newOrigin: url.origin,
|
|
32
|
+
bypass: serverContext.shouldBypass(req),
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
if (path.startsWith("/_data/query/")) {
|
|
36
|
+
if (!isGet(req))
|
|
37
|
+
return methodNotAllowed();
|
|
38
|
+
// The query name and JSON params are encoded in the raw path: /_data/query/<name>=<params>
|
|
39
|
+
const queryPath = getRawPath(req).replace("/_data/query", "");
|
|
40
|
+
const paramSeparator = queryPath.indexOf("=");
|
|
41
|
+
const id = paramSeparator === -1 ? queryPath : queryPath.slice(0, paramSeparator);
|
|
42
|
+
const paramString = paramSeparator === -1 ? undefined : queryPath.slice(paramSeparator + 1);
|
|
43
|
+
let params = {};
|
|
44
|
+
try {
|
|
45
|
+
params =
|
|
46
|
+
typeof paramString === "string" && paramString.length
|
|
47
|
+
? JSON.parse(decodeURIComponent(paramString.replace(/\/$/, "")))
|
|
48
|
+
: {};
|
|
49
|
+
}
|
|
50
|
+
catch (e) {
|
|
51
|
+
throw new Error("Invalid query parameters");
|
|
52
|
+
}
|
|
53
|
+
return serverContext.fetchNamedQuery({
|
|
54
|
+
name: id,
|
|
55
|
+
params,
|
|
56
|
+
headers: getRequestHeaders(req),
|
|
57
|
+
bypass: serverContext.shouldBypass(req),
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
if (path.startsWith("/_data/manifest/")) {
|
|
61
|
+
if (!isGet(req))
|
|
62
|
+
return methodNotAllowed();
|
|
63
|
+
const id = decodeURIComponent(path.slice("/_data/manifest/".length).replace(/\/$/, ""));
|
|
64
|
+
const assets = id === "handler" ? opts.assets.client : opts.assets.modules[id];
|
|
65
|
+
return json({ id, assets: assets ?? null });
|
|
66
|
+
}
|
|
67
|
+
if (path.startsWith("/_data/mutation/")) {
|
|
68
|
+
if (req.method !== "POST")
|
|
69
|
+
return methodNotAllowed();
|
|
70
|
+
const name = "/" + path.slice("/_data/mutation/".length);
|
|
71
|
+
const body = await req.json();
|
|
72
|
+
return serverContext.fetchMutation({ name, body, headers: getRequestHeaders(req) });
|
|
73
|
+
}
|
|
74
|
+
if (path === "/_data/submit-gf" || path === "/_data/submit-gf/") {
|
|
75
|
+
if (req.method !== "POST")
|
|
76
|
+
return methodNotAllowed();
|
|
77
|
+
const headers = new Headers(req.headers);
|
|
78
|
+
headers.delete("content-length");
|
|
79
|
+
headers.delete("host");
|
|
80
|
+
headers.delete("connection");
|
|
81
|
+
headers.delete("pragma");
|
|
82
|
+
return serverContext.fetchOrigin("/wp-json/ed/v1/gf/submit/", {
|
|
83
|
+
method: "POST",
|
|
84
|
+
headers,
|
|
85
|
+
body: await req.blob(),
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
return new Response("Not Found", { status: 404 });
|
|
89
|
+
}
|
|
90
|
+
async function handleAI(req, url) {
|
|
91
|
+
if (url.pathname !== "/_ai/page" && !url.pathname.startsWith("/_ai/page/")) {
|
|
92
|
+
return new Response("Not Found", { status: 404 });
|
|
93
|
+
}
|
|
94
|
+
if (!isGet(req))
|
|
95
|
+
return methodNotAllowed();
|
|
96
|
+
const pathname = url.pathname.slice("/_ai/page".length) || "/";
|
|
97
|
+
const page = await renderPageForIndexing({ pathname, newOrigin: url.origin });
|
|
98
|
+
return new Response(page.contents, {
|
|
99
|
+
headers: {
|
|
100
|
+
"Content-Type": "text/html; charset=utf-8",
|
|
101
|
+
"Cache-Control": "no-store",
|
|
102
|
+
},
|
|
103
|
+
});
|
|
104
|
+
}
|
|
105
|
+
/** Vercel prerender bypass helpers, used by the WordPress admin toolbar and cache purging. */
|
|
106
|
+
async function handleBypass(req, url) {
|
|
107
|
+
if (!isGet(req))
|
|
108
|
+
return methodNotAllowed();
|
|
109
|
+
const token = process.env.VERCEL_BYPASS_TOKEN;
|
|
110
|
+
const action = url.pathname.replace(/^\/_bypass\/?/, "").replace(/\/$/, "");
|
|
111
|
+
if (action === "enable") {
|
|
112
|
+
if (!token)
|
|
113
|
+
return json(false);
|
|
114
|
+
const headers = new Headers();
|
|
115
|
+
appendSetCookie(headers, BYPASS_COOKIE, token, { expires: new Date(Date.now() + 1000 * 60 * 60 * 24) });
|
|
116
|
+
return json(true, { headers });
|
|
117
|
+
}
|
|
118
|
+
if (action === "disable") {
|
|
119
|
+
const headers = new Headers();
|
|
120
|
+
appendSetCookie(headers, BYPASS_COOKIE, "");
|
|
121
|
+
return json(true, { headers });
|
|
122
|
+
}
|
|
123
|
+
if (action === "check") {
|
|
124
|
+
return json(!!token && getCookie(req, BYPASS_COOKIE) === token);
|
|
125
|
+
}
|
|
126
|
+
if (action === "purge") {
|
|
127
|
+
if (token && req.headers.get("x-prerender-revalidate") === token) {
|
|
128
|
+
await invalidateByTag("data");
|
|
129
|
+
return json(true);
|
|
130
|
+
}
|
|
131
|
+
return json(false);
|
|
132
|
+
}
|
|
133
|
+
return new Response("Not Found", { status: 404 });
|
|
134
|
+
}
|
|
135
|
+
return {
|
|
136
|
+
async fetch(req) {
|
|
137
|
+
const serverContext = ServerContext.main;
|
|
138
|
+
const url = getRequestURL(req);
|
|
139
|
+
await Promise.allSettled([viewManifestReader.preloadAll(), blockManifestReader.preloadAll()]);
|
|
140
|
+
// RPC
|
|
141
|
+
if (serverContext.rpcBases.some((base) => url.pathname.startsWith(base))) {
|
|
142
|
+
return handleRPCRequest(req, opts.rpc);
|
|
143
|
+
}
|
|
144
|
+
// Data API
|
|
145
|
+
if (url.pathname.startsWith("/_data/")) {
|
|
146
|
+
return handleData(req, url);
|
|
147
|
+
}
|
|
148
|
+
// LLM indexing route
|
|
149
|
+
if (url.pathname.startsWith("/_ai/")) {
|
|
150
|
+
return handleAI(req, url);
|
|
151
|
+
}
|
|
152
|
+
// Prerender bypass
|
|
153
|
+
if (url.pathname.startsWith("/_bypass/")) {
|
|
154
|
+
return handleBypass(req, url);
|
|
155
|
+
}
|
|
156
|
+
// Outdated build assets
|
|
157
|
+
if (url.pathname.match(/^\/(_build|_admin)\//)) {
|
|
158
|
+
return new Response("", { status: 404 });
|
|
159
|
+
}
|
|
160
|
+
// Proxy WordPress
|
|
161
|
+
if ((url.pathname.includes(".") && !url.pathname.includes("[")) ||
|
|
162
|
+
url.pathname.startsWith("/graphql") ||
|
|
163
|
+
url.pathname.startsWith("/wp-")) {
|
|
164
|
+
return proxyWpAdmin(req);
|
|
165
|
+
}
|
|
166
|
+
// Enforce trailing slashes
|
|
167
|
+
if (!url.pathname.endsWith("/")) {
|
|
168
|
+
url.pathname = withTrailingSlash(url.pathname);
|
|
169
|
+
return Response.redirect(url, 301);
|
|
170
|
+
}
|
|
171
|
+
// SSR
|
|
172
|
+
const response = await renderPage({
|
|
173
|
+
pathname: url.pathname,
|
|
174
|
+
newOrigin: url.origin,
|
|
175
|
+
hostname: url.hostname,
|
|
176
|
+
bypass: serverContext.shouldBypass(req),
|
|
177
|
+
});
|
|
178
|
+
if (opts.skewProtection) {
|
|
179
|
+
// Pins this browser to the deployment it loaded, so later chunk/data requests hit matching code.
|
|
180
|
+
const { deploymentId } = opts.skewProtection;
|
|
181
|
+
return withHeaders(response, (headers) => appendSetCookie(headers, "__vdpl", deploymentId, { httpOnly: false }));
|
|
182
|
+
}
|
|
183
|
+
return response;
|
|
184
|
+
},
|
|
185
|
+
};
|
|
186
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import {
|
|
1
|
+
import type { ServerAssets } from "./assets.js";
|
|
2
|
+
import { type RequestHeaders } from "./utils/request.js";
|
|
3
3
|
import type { EDCacheConfig, EDConfig } from "../../node/project/config.js";
|
|
4
4
|
import { TrackerTags } from "../lib/routing/types.js";
|
|
5
5
|
import { QueryMonitor } from "../utils/query-monitor.js";
|
|
@@ -13,7 +13,7 @@ export type ServerContextArgs = {
|
|
|
13
13
|
cacheConfig: EDCacheConfig;
|
|
14
14
|
};
|
|
15
15
|
export type ServerContextRuntime = {
|
|
16
|
-
|
|
16
|
+
assets: ServerAssets;
|
|
17
17
|
};
|
|
18
18
|
/**
|
|
19
19
|
* Data returned from WordPress origin /_appdata route
|
|
@@ -53,7 +53,7 @@ export declare class ServerContext {
|
|
|
53
53
|
bypass?: boolean;
|
|
54
54
|
newOrigin?: string;
|
|
55
55
|
}): Promise<ServerAppData>;
|
|
56
|
-
extractRequestHeaders(req?: RequestHeaders):
|
|
56
|
+
extractRequestHeaders(req?: RequestHeaders): Record<string, string>;
|
|
57
57
|
fetchNamedQuery(req: {
|
|
58
58
|
name: string;
|
|
59
59
|
bypass: boolean;
|
|
@@ -66,7 +66,7 @@ export declare class ServerContext {
|
|
|
66
66
|
headers: RequestHeaders;
|
|
67
67
|
}): Promise<Response>;
|
|
68
68
|
get allowedCorsOrigins(): string[];
|
|
69
|
-
shouldBypass(
|
|
69
|
+
shouldBypass(req: Request): boolean;
|
|
70
70
|
getCorsOrigin(originHeader: string): string | undefined;
|
|
71
71
|
getCorsHeaders(origin: string): {
|
|
72
72
|
"Access-Control-Allow-Methods"?: undefined;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server-context.d.ts","sourceRoot":"","sources":["../../../src/app/server/server-context.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"server-context.d.ts","sourceRoot":"","sources":["../../../src/app/server/server-context.ts"],"names":[],"mappings":"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"}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import chalk from "chalk";
|
|
2
2
|
import { inspect } from "node:util";
|
|
3
3
|
import { parseURL, stringifyParsedURL, withQuery, withTrailingSlash } from "ufo";
|
|
4
|
-
import { getCookie
|
|
5
|
-
import {
|
|
4
|
+
import { getCookie } from "./utils/request.js";
|
|
5
|
+
import { fetchOrigin as fetchFromOrigin } from "./utils/fetch-origin.js";
|
|
6
6
|
import { QueryMonitor } from "../utils/query-monitor.js";
|
|
7
7
|
import { filterHeader } from "./utils/headers.js";
|
|
8
8
|
import { createUrlReplacer } from "./utils/replace-host.js";
|
|
@@ -78,18 +78,25 @@ export class ServerContext {
|
|
|
78
78
|
const fetchOps = { ...opts };
|
|
79
79
|
delete fetchOps.replaceUrls;
|
|
80
80
|
delete fetchOps.newOrigin;
|
|
81
|
-
const response = await
|
|
81
|
+
const response = await fetchFromOrigin(url, {
|
|
82
82
|
...fetchOps,
|
|
83
83
|
});
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
const headers =
|
|
84
|
+
// Only pass on allowed headers, for error responses too. The origin's connection headers
|
|
85
|
+
// (transfer-encoding, keep-alive etc.) are forbidden over HTTP/2, and fetch has already decoded the
|
|
86
|
+
// body, so content-length and content-encoding no longer apply.
|
|
87
|
+
const headers = new Headers();
|
|
88
88
|
response.headers.forEach((value, key) => {
|
|
89
89
|
if (filterHeader(key, PROXY_RESPONSE_HEADERS)) {
|
|
90
|
-
headers
|
|
90
|
+
headers.append(key, value);
|
|
91
91
|
}
|
|
92
92
|
});
|
|
93
|
+
if (!response.ok) {
|
|
94
|
+
return new Response(response.body, {
|
|
95
|
+
status: response.status,
|
|
96
|
+
statusText: response.statusText,
|
|
97
|
+
headers,
|
|
98
|
+
});
|
|
99
|
+
}
|
|
93
100
|
let text = await response.text();
|
|
94
101
|
if (opts?.replaceUrls) {
|
|
95
102
|
text = this.replaceUrls(text, opts.newOrigin);
|
|
@@ -343,8 +350,9 @@ export class ServerContext {
|
|
|
343
350
|
const headers = {};
|
|
344
351
|
if (req) {
|
|
345
352
|
for (let key of PROXY_REQUEST_HEADERS) {
|
|
346
|
-
|
|
347
|
-
|
|
353
|
+
const value = req[key];
|
|
354
|
+
if (value) {
|
|
355
|
+
headers[key] = value;
|
|
348
356
|
}
|
|
349
357
|
}
|
|
350
358
|
}
|
|
@@ -442,15 +450,15 @@ export class ServerContext {
|
|
|
442
450
|
}
|
|
443
451
|
return result;
|
|
444
452
|
}
|
|
445
|
-
shouldBypass(
|
|
453
|
+
shouldBypass(req) {
|
|
446
454
|
const bypassToken = process.env.VERCEL_BYPASS_TOKEN;
|
|
447
455
|
if (!bypassToken)
|
|
448
456
|
return false;
|
|
449
457
|
const cookieName = "__prerender_bypass";
|
|
450
|
-
if (getCookie(
|
|
458
|
+
if (getCookie(req, cookieName) === bypassToken) {
|
|
451
459
|
return true;
|
|
452
460
|
}
|
|
453
|
-
if (
|
|
461
|
+
if (req.headers.get("x-prerender-revalidate") === bypassToken) {
|
|
454
462
|
return true;
|
|
455
463
|
}
|
|
456
464
|
return false;
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Fetches from the WordPress origin, adding the eddev API key when origin protection is enabled.
|
|
3
|
+
*
|
|
4
|
+
* Uses the platform's own `fetch` (Node, Vercel, Cloudflare Workers), with normal TLS verification.
|
|
5
|
+
* Local's self-signed certificates are accepted in `eddev dev` and `eddev preview`, which disable TLS
|
|
6
|
+
* verification for the whole process (`NODE_TLS_REJECT_UNAUTHORIZED=0`).
|
|
7
|
+
*
|
|
8
|
+
* The CLI's `fetchWP` (undici, with certificate checks disabled) is deliberately not used here: undici
|
|
9
|
+
* doesn't work in the Workers runtime, and it disabled certificate checks for every request the
|
|
10
|
+
* production server made.
|
|
11
|
+
*/
|
|
12
|
+
export declare function fetchOrigin(url: string | URL, init?: RequestInit): Promise<Response>;
|
|
13
|
+
//# sourceMappingURL=fetch-origin.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"fetch-origin.d.ts","sourceRoot":"","sources":["../../../../src/app/server/utils/fetch-origin.ts"],"names":[],"mappings":"AAEA;;;;;;;;;;GAUG;AACH,wBAAgB,WAAW,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,EAAE,IAAI,GAAE,WAAgB,GAAG,OAAO,CAAC,QAAQ,CAAC,CAUxF"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { apiConfig } from "../../lib/runtime/apiConfig.js";
|
|
2
|
+
/**
|
|
3
|
+
* Fetches from the WordPress origin, adding the eddev API key when origin protection is enabled.
|
|
4
|
+
*
|
|
5
|
+
* Uses the platform's own `fetch` (Node, Vercel, Cloudflare Workers), with normal TLS verification.
|
|
6
|
+
* Local's self-signed certificates are accepted in `eddev dev` and `eddev preview`, which disable TLS
|
|
7
|
+
* verification for the whole process (`NODE_TLS_REJECT_UNAUTHORIZED=0`).
|
|
8
|
+
*
|
|
9
|
+
* The CLI's `fetchWP` (undici, with certificate checks disabled) is deliberately not used here: undici
|
|
10
|
+
* doesn't work in the Workers runtime, and it disabled certificate checks for every request the
|
|
11
|
+
* production server made.
|
|
12
|
+
*/
|
|
13
|
+
export function fetchOrigin(url, init = {}) {
|
|
14
|
+
const headers = new Headers(init.headers);
|
|
15
|
+
// Runtime environment first, then the key baked in at build time (see the generated context.ts)
|
|
16
|
+
const apiKey = (typeof process !== "undefined" ? process.env?.SITE_API_KEY : undefined) || apiConfig.apiKey;
|
|
17
|
+
if (apiKey) {
|
|
18
|
+
headers.set("x-ed-api-key", apiKey);
|
|
19
|
+
}
|
|
20
|
+
return fetch(url, { ...init, headers });
|
|
21
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { serialize as serializeCookie } from "cookie-es";
|
|
2
|
+
/** Request headers as a plain object with lowercase keys. */
|
|
3
|
+
export type RequestHeaders = Record<string, string | undefined>;
|
|
4
|
+
/**
|
|
5
|
+
* The request URL as seen by the visitor. Honours `x-forwarded-proto: https` from a trusted proxy
|
|
6
|
+
* (Vercel, Cloudflare, the local dev HTTPS redirect), matching h3 v1's `getRequestURL` default.
|
|
7
|
+
*/
|
|
8
|
+
export declare function getRequestURL(req: Request): URL;
|
|
9
|
+
/** The raw path and query string of a request, without decoding. */
|
|
10
|
+
export declare function getRawPath(req: Request): string;
|
|
11
|
+
export declare function getRequestHeaders(req: Request): RequestHeaders;
|
|
12
|
+
export declare function getCookie(req: Request, name: string): string | undefined;
|
|
13
|
+
export type CookieOptions = Parameters<typeof serializeCookie>[2];
|
|
14
|
+
/** Appends a `Set-Cookie` header. Defaults the cookie path to `/`. */
|
|
15
|
+
export declare function appendSetCookie(headers: Headers, name: string, value: string, options?: CookieOptions): void;
|
|
16
|
+
/** Request headers suitable for forwarding to another origin. */
|
|
17
|
+
export declare function getProxyRequestHeaders(req: Request): Record<string, string>;
|
|
18
|
+
/** Returns a copy of the response with additional headers, for responses whose headers may be immutable. */
|
|
19
|
+
export declare function withHeaders(response: Response, apply: (headers: Headers) => void): Response;
|
|
20
|
+
//# sourceMappingURL=request.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"request.d.ts","sourceRoot":"","sources":["../../../../src/app/server/utils/request.ts"],"names":[],"mappings":"AAAA,OAAO,EAAyB,SAAS,IAAI,eAAe,EAAE,MAAM,WAAW,CAAA;AAE/E,6DAA6D;AAC7D,MAAM,MAAM,cAAc,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,CAAA;AAE/D;;;GAGG;AACH,wBAAgB,aAAa,CAAC,GAAG,EAAE,OAAO,GAAG,GAAG,CAM/C;AAED,oEAAoE;AACpE,wBAAgB,UAAU,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAG/C;AAED,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,OAAO,GAAG,cAAc,CAM9D;AAED,wBAAgB,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAIxE;AAED,MAAM,MAAM,aAAa,GAAG,UAAU,CAAC,OAAO,eAAe,CAAC,CAAC,CAAC,CAAC,CAAA;AAEjE,sEAAsE;AACtE,wBAAgB,eAAe,CAAC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,EAAE,OAAO,GAAE,aAAkB,QAEzG;AAcD,iEAAiE;AACjE,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAM3E;AAED,4GAA4G;AAC5G,wBAAgB,WAAW,CAAC,QAAQ,EAAE,QAAQ,EAAE,KAAK,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,GAAG,QAAQ,CAI3F"}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import { parse as parseCookies, serialize as serializeCookie } from "cookie-es";
|
|
2
|
+
/**
|
|
3
|
+
* The request URL as seen by the visitor. Honours `x-forwarded-proto: https` from a trusted proxy
|
|
4
|
+
* (Vercel, Cloudflare, the local dev HTTPS redirect), matching h3 v1's `getRequestURL` default.
|
|
5
|
+
*/
|
|
6
|
+
export function getRequestURL(req) {
|
|
7
|
+
const url = new URL(req.url);
|
|
8
|
+
if (req.headers.get("x-forwarded-proto") === "https") {
|
|
9
|
+
url.protocol = "https:";
|
|
10
|
+
}
|
|
11
|
+
return url;
|
|
12
|
+
}
|
|
13
|
+
/** The raw path and query string of a request, without decoding. */
|
|
14
|
+
export function getRawPath(req) {
|
|
15
|
+
const url = new URL(req.url);
|
|
16
|
+
return req.url.slice(url.origin.length) || "/";
|
|
17
|
+
}
|
|
18
|
+
export function getRequestHeaders(req) {
|
|
19
|
+
const headers = {};
|
|
20
|
+
req.headers.forEach((value, name) => {
|
|
21
|
+
headers[name] = value;
|
|
22
|
+
});
|
|
23
|
+
return headers;
|
|
24
|
+
}
|
|
25
|
+
export function getCookie(req, name) {
|
|
26
|
+
const header = req.headers.get("cookie");
|
|
27
|
+
if (!header)
|
|
28
|
+
return undefined;
|
|
29
|
+
return parseCookies(header)[name];
|
|
30
|
+
}
|
|
31
|
+
/** Appends a `Set-Cookie` header. Defaults the cookie path to `/`. */
|
|
32
|
+
export function appendSetCookie(headers, name, value, options = {}) {
|
|
33
|
+
headers.append("set-cookie", serializeCookie(name, value, { path: "/", ...options }));
|
|
34
|
+
}
|
|
35
|
+
/** Headers which shouldn't be forwarded when proxying a request (same list as h3 v1). */
|
|
36
|
+
const IGNORED_PROXY_HEADERS = new Set([
|
|
37
|
+
"transfer-encoding",
|
|
38
|
+
"accept-encoding",
|
|
39
|
+
"connection",
|
|
40
|
+
"keep-alive",
|
|
41
|
+
"upgrade",
|
|
42
|
+
"expect",
|
|
43
|
+
"host",
|
|
44
|
+
"accept",
|
|
45
|
+
]);
|
|
46
|
+
/** Request headers suitable for forwarding to another origin. */
|
|
47
|
+
export function getProxyRequestHeaders(req) {
|
|
48
|
+
const headers = {};
|
|
49
|
+
req.headers.forEach((value, name) => {
|
|
50
|
+
if (!IGNORED_PROXY_HEADERS.has(name))
|
|
51
|
+
headers[name] = value;
|
|
52
|
+
});
|
|
53
|
+
return headers;
|
|
54
|
+
}
|
|
55
|
+
/** Returns a copy of the response with additional headers, for responses whose headers may be immutable. */
|
|
56
|
+
export function withHeaders(response, apply) {
|
|
57
|
+
const headers = new Headers(response.headers);
|
|
58
|
+
apply(headers);
|
|
59
|
+
return new Response(response.body, { status: response.status, statusText: response.statusText, headers });
|
|
60
|
+
}
|
|
@@ -1,13 +1,17 @@
|
|
|
1
1
|
import { Worker } from "node:worker_threads";
|
|
2
|
+
import type { SPATarget } from "../compiler/bundler.spa.js";
|
|
2
3
|
import type { StatefulLog } from "../utils/stateful-log.js";
|
|
3
|
-
type WorkerMode = "
|
|
4
|
+
type WorkerMode = "spa" | "graphql" | "serverless";
|
|
5
|
+
type WorkerOptions = {
|
|
6
|
+
log: StatefulLog<any>;
|
|
7
|
+
mode: WorkerMode;
|
|
8
|
+
verbose: boolean;
|
|
9
|
+
/** For the `spa` mode: which bundles to build */
|
|
10
|
+
spaTargets?: SPATarget[];
|
|
11
|
+
};
|
|
4
12
|
export declare class CLIWorker {
|
|
5
13
|
worker: Worker;
|
|
6
|
-
constructor({ log, mode, verbose }:
|
|
7
|
-
log: StatefulLog<any>;
|
|
8
|
-
mode: WorkerMode;
|
|
9
|
-
verbose: boolean;
|
|
10
|
-
});
|
|
14
|
+
constructor({ log, mode, verbose, spaTargets }: WorkerOptions);
|
|
11
15
|
shutdown(): Promise<void>;
|
|
12
16
|
}
|
|
13
17
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"cli-worker.d.ts","sourceRoot":"","sources":["../../../src/node/cli/cli-worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAwC,MAAM,qBAAqB,CAAA;AAClF,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAG3D,KAAK,UAAU,GAAG,
|
|
1
|
+
{"version":3,"file":"cli-worker.d.ts","sourceRoot":"","sources":["../../../src/node/cli/cli-worker.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAwC,MAAM,qBAAqB,CAAA;AAClF,OAAO,KAAK,EAAE,SAAS,EAAE,MAAM,4BAA4B,CAAA;AAC3D,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAA;AAG3D,KAAK,UAAU,GAAG,KAAK,GAAG,SAAS,GAAG,YAAY,CAAA;AAElD,KAAK,aAAa,GAAG;IACnB,GAAG,EAAE,WAAW,CAAC,GAAG,CAAC,CAAA;IACrB,IAAI,EAAE,UAAU,CAAA;IAChB,OAAO,EAAE,OAAO,CAAA;IAChB,iDAAiD;IACjD,UAAU,CAAC,EAAE,SAAS,EAAE,CAAA;CACzB,CAAA;AAED,qBAAa,SAAS;IACpB,MAAM,EAAE,MAAM,CAAA;gBACF,EAAE,GAAG,EAAE,IAAI,EAAE,OAAO,EAAE,UAAU,EAAE,EAAE,aAAa;IAmCvD,QAAQ;CAGf"}
|
|
@@ -2,11 +2,12 @@ import { Worker, isMainThread, parentPort, workerData } from "node:worker_thread
|
|
|
2
2
|
import { configureCliMode } from "./cli-mode.js";
|
|
3
3
|
export class CLIWorker {
|
|
4
4
|
worker;
|
|
5
|
-
constructor({ log, mode, verbose }) {
|
|
5
|
+
constructor({ log, mode, verbose, spaTargets }) {
|
|
6
6
|
const worker = new Worker(new URL(import.meta.url), {
|
|
7
7
|
workerData: {
|
|
8
8
|
mode,
|
|
9
9
|
verbose,
|
|
10
|
+
spaTargets,
|
|
10
11
|
},
|
|
11
12
|
stdout: true,
|
|
12
13
|
stderr: true,
|
|
@@ -86,23 +87,15 @@ if (!isMainThread) {
|
|
|
86
87
|
parentPort?.postMessage(JSON.stringify({ type: "log", log: serializeLogData(log) }));
|
|
87
88
|
});
|
|
88
89
|
}
|
|
89
|
-
if (mode === "
|
|
90
|
-
const {
|
|
91
|
-
const bundler = new
|
|
90
|
+
if (mode === "spa") {
|
|
91
|
+
const { SPABundler, spaLog } = await import("../compiler/bundler.spa.js");
|
|
92
|
+
const bundler = new SPABundler(project, {
|
|
92
93
|
mode: "development",
|
|
93
94
|
watch: true,
|
|
95
|
+
targets: workerData.spaTargets,
|
|
94
96
|
});
|
|
95
97
|
bundler.start();
|
|
96
|
-
pipeLog(
|
|
97
|
-
}
|
|
98
|
-
else if (mode === "frontend") {
|
|
99
|
-
const { FrontendBundler, frontendLog } = await import("../compiler/bundler.frontend.js");
|
|
100
|
-
const bundler = new FrontendBundler(project, {
|
|
101
|
-
mode: "development",
|
|
102
|
-
watch: true,
|
|
103
|
-
});
|
|
104
|
-
bundler.start();
|
|
105
|
-
pipeLog(frontendLog);
|
|
98
|
+
pipeLog(spaLog);
|
|
106
99
|
}
|
|
107
100
|
else if (mode === "graphql") {
|
|
108
101
|
const { GraphQLGenerator, graphqlLog } = await import("../graphql/graphql-codegen.js");
|