eddev 2.0.0-beta.1 → 2.0.0-beta.11
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/boot-admin.d.ts +1 -0
- package/dist/app/entry/{main.admin.js → boot-admin.js} +3 -5
- package/dist/app/entry/spa-root.d.ts +1 -0
- package/dist/app/entry/{Root.js → spa-root.js} +4 -4
- package/dist/app/entry/ssr-root-client.d.ts +4 -0
- package/dist/app/entry/ssr-root-client.js +9 -0
- package/dist/app/entry/ssr-root.d.ts +9 -0
- package/dist/app/entry/ssr-root.js +21 -0
- package/dist/app/lib/blocks/ErrorBoundaryFrontend.d.ts +1 -1
- package/dist/app/lib/blocks/editor/ErrorBoundaryEditor.d.ts +1 -1
- package/dist/app/lib/devtools/components/BreakpointIndicator.js +5 -3
- package/dist/app/lib/devtools/dev-tools-store.d.ts +9 -0
- package/dist/app/lib/devtools/dev-tools-store.js +8 -0
- package/dist/app/lib/devtools/hooks/useTailwind.d.ts +120 -121
- package/dist/app/lib/devtools/hooks/useTailwind.js +6 -3
- package/dist/app/lib/devtools/index.d.ts +1 -0
- package/dist/app/lib/devtools/index.js +1 -1
- package/dist/app/lib/hooks/queryUtils.d.ts +4 -1
- package/dist/app/lib/hooks/queryUtils.js +8 -11
- package/dist/app/lib/internal/internal-store.d.ts +0 -2
- package/dist/app/lib/internal/internal-store.js +1 -3
- package/dist/app/lib/routing/components/ClientOnly.d.ts +1 -1
- package/dist/app/lib/routing/loader.js +6 -4
- package/dist/app/server/index.d.ts +3 -0
- package/dist/app/server/index.js +3 -0
- package/dist/app/server/proxy-wp-admin.d.ts +3 -0
- package/dist/app/server/proxy-wp-admin.js +106 -0
- package/dist/app/server/render-ssr-page.d.ts +2 -0
- package/dist/app/server/render-ssr-page.js +22 -0
- package/dist/app/server/server-context.d.ts +34 -0
- package/dist/app/server/server-context.js +116 -0
- package/dist/app/server/utils/headers.d.ts +1 -0
- package/dist/app/server/utils/headers.js +17 -0
- package/dist/app/server/utils/replace-host.d.ts +6 -4
- package/dist/app/server/utils/replace-host.js +58 -11
- package/dist/node/cli/cli-worker.d.ts +1 -1
- package/dist/node/cli/cli-worker.js +3 -0
- package/dist/node/cli/cli.js +45 -14
- package/dist/node/cli/display/CLIApp.d.ts +1 -1
- package/dist/node/cli/display/CLIApp.js +1 -1
- package/dist/node/cli/display/components/LogEntries.d.ts +1 -1
- package/dist/node/cli/display/hooks/useStatefulLog.d.ts +1 -1
- package/dist/node/cli/display/util/colors.d.ts +2 -2
- package/dist/node/cli/version.d.ts +1 -1
- package/dist/node/cli/version.js +1 -1
- package/dist/node/compiler/build-vinxi.d.ts +8 -0
- package/dist/node/compiler/build-vinxi.js +37 -0
- package/dist/node/compiler/bundler.admin.d.ts +1 -1
- package/dist/node/compiler/bundler.admin.js +3 -3
- package/dist/node/compiler/bundler.frontend.d.ts +1 -1
- package/dist/node/compiler/bundler.frontend.js +3 -3
- package/dist/node/compiler/{serverless.dev.d.ts → dev-server.d.ts} +7 -5
- package/dist/node/compiler/dev-server.js +97 -0
- package/dist/node/compiler/get-vite-config.d.ts +19 -0
- package/dist/node/compiler/get-vite-config.js +184 -0
- package/dist/node/compiler/vinxi-app.d.ts +10 -0
- package/dist/node/compiler/vinxi-app.js +121 -0
- package/dist/node/compiler/vinxi-codegen.d.ts +12 -0
- package/dist/node/compiler/vinxi-codegen.js +408 -0
- package/dist/node/graphql/graphql-codegen.d.ts +1 -1
- package/dist/node/graphql/graphql-codegen.js +3 -3
- package/dist/node/graphql/graphql-schema-loader.js +15 -18
- package/dist/node/project/config.js +1 -1
- package/dist/node/project/env.d.ts +1 -1
- package/dist/node/project/env.js +1 -1
- package/dist/node/project/manifest/block-manifest.js +2 -2
- package/dist/node/project/manifest/manifest.d.ts +1 -1
- package/dist/node/project/manifest/manifest.js +1 -1
- package/dist/node/project/manifest/view-manifest.js +2 -2
- package/dist/node/project/project.d.ts +2 -1
- package/dist/node/project/project.js +13 -15
- package/dist/node/project/wp-info.js +0 -2
- package/dist/node/types/view-type.js +3 -4
- package/dist/node/utils/fs-codegen.d.ts +40 -0
- package/dist/node/utils/fs-codegen.js +97 -0
- package/dist/node/utils/fs.js +2 -0
- package/dist/node/utils/{selfSignedCert.js → self-signed-cert.js} +1 -1
- package/dist/node/utils/{statefulLog.js → stateful-log.js} +1 -1
- package/package.json +29 -31
- package/dist/app/entry/Root.d.ts +0 -1
- package/dist/app/entry/main.admin.d.ts +0 -3
- package/dist/app/entry/main.frontend.spa.d.ts +0 -3
- package/dist/app/entry/main.frontend.spa.js +0 -13
- package/dist/app/entry/main.frontend.ssr.d.ts +0 -21
- package/dist/app/entry/main.frontend.ssr.js +0 -79
- package/dist/app/entry/main.serverless.dev.d.ts +0 -4
- package/dist/app/entry/main.serverless.dev.js +0 -21
- package/dist/app/server/create-api-builtin-hono.d.ts +0 -8
- package/dist/app/server/create-api-builtin-hono.js +0 -80
- package/dist/app/server/create-ssr-hono.d.ts +0 -18
- package/dist/app/server/create-ssr-hono.js +0 -104
- package/dist/app/server/utils/index.html.d.ts +0 -2
- package/dist/app/server/utils/index.html.js +0 -14
- package/dist/node/compiler/index.html.d.ts +0 -2
- package/dist/node/compiler/index.html.js +0 -15
- package/dist/node/compiler/serverless.dev.js +0 -215
- package/dist/node/compiler/vite/get-vite-config.d.ts +0 -13
- package/dist/node/compiler/vite/get-vite-config.js +0 -315
- package/dist/node/compiler/vite/plugin-admin.d.ts +0 -4
- package/dist/node/compiler/vite/plugin-admin.js +0 -67
- package/dist/node/compiler/vite/plugin-blocks.d.ts +0 -4
- package/dist/node/compiler/vite/plugin-blocks.js +0 -73
- package/dist/node/compiler/vite/plugin-entry.d.ts +0 -6
- package/dist/node/compiler/vite/plugin-entry.js +0 -16
- package/dist/node/compiler/vite/plugin-resolved-tailwind.d.ts +0 -4
- package/dist/node/compiler/vite/plugin-resolved-tailwind.js +0 -29
- package/dist/node/compiler/vite/plugin-theme.d.ts +0 -4
- package/dist/node/compiler/vite/plugin-theme.js +0 -40
- package/dist/node/compiler/vite/plugin-views.d.ts +0 -4
- package/dist/node/compiler/vite/plugin-views.js +0 -51
- package/dist/node/utils/console.d.ts +0 -21
- package/dist/node/utils/console.js +0 -28
- package/dist/node/utils/unsafe-fetch.d.ts +0 -2
- package/dist/node/utils/unsafe-fetch.js +0 -19
- package/tsup.config.ts +0 -40
- package/types.manifests.d.ts +0 -22
- /package/dist/node/utils/{formatZodError.d.ts → format-zod-error.d.ts} +0 -0
- /package/dist/node/utils/{formatZodError.js → format-zod-error.js} +0 -0
- /package/dist/node/utils/{getRepoInfo.d.ts → get-repo-info.d.ts} +0 -0
- /package/dist/node/utils/{getRepoInfo.js → get-repo-info.js} +0 -0
- /package/dist/node/utils/{highlightCode.d.ts → highlight-code.d.ts} +0 -0
- /package/dist/node/utils/{highlightCode.js → highlight-code.js} +0 -0
- /package/dist/node/utils/{isDeploying.d.ts → is-deploying.d.ts} +0 -0
- /package/dist/node/utils/{isDeploying.js → is-deploying.js} +0 -0
- /package/dist/node/utils/{selfSignedCert.d.ts → self-signed-cert.d.ts} +0 -0
- /package/dist/node/utils/{statefulLog.d.ts → stateful-log.d.ts} +0 -0
- /package/dist/node/utils/{export-extractor.d.ts → ts-export-extractor.d.ts} +0 -0
- /package/dist/node/utils/{export-extractor.js → ts-export-extractor.js} +0 -0
- /package/dist/node/utils/{watchFileTree.d.ts → watch-file-tree.d.ts} +0 -0
- /package/dist/node/utils/{watchFileTree.js → watch-file-tree.js} +0 -0
|
@@ -15,7 +15,7 @@ const fetchGETQuery = async (name, params, opts) => {
|
|
|
15
15
|
headers: opts?.headers,
|
|
16
16
|
};
|
|
17
17
|
if (env.serverless && env.client) {
|
|
18
|
-
url = `/
|
|
18
|
+
url = `/_data/query/${name}`;
|
|
19
19
|
}
|
|
20
20
|
else if (env.serverless) {
|
|
21
21
|
url = joinURL(env.origin ?? "", `/wp-json/ed/v1/query/${name}`);
|
|
@@ -60,14 +60,6 @@ export function createUseQuery(init) {
|
|
|
60
60
|
};
|
|
61
61
|
return hook;
|
|
62
62
|
}
|
|
63
|
-
// & {
|
|
64
|
-
// fetch: (
|
|
65
|
-
// args: OptionalMaybes<TVars>,
|
|
66
|
-
// options?: Omit<FetchInfiniteQueryOptions<TData, QueryError, InfiniteData<TData, string>>, "queryKey" | "queryFn"> & {
|
|
67
|
-
// headers?: Record<string, string>
|
|
68
|
-
// },
|
|
69
|
-
// ) => Promise<TData>
|
|
70
|
-
// }
|
|
71
63
|
function selectByPath(data, path) {
|
|
72
64
|
return path.reduce((acc, key) => (acc ? acc[key] : null), data);
|
|
73
65
|
}
|
|
@@ -109,10 +101,12 @@ export function createUseInfiniteQuery(init) {
|
|
|
109
101
|
const endCursor = selectByPath(data, init.paths.endCursorPath);
|
|
110
102
|
const hasNextPage = selectByPath(data, init.paths.hasNextPagePath);
|
|
111
103
|
const nodes = selectByPath(data, init.paths.nodesPath);
|
|
104
|
+
const total = selectByPath(data, [...init.paths.pageInfoPath, "total"]);
|
|
112
105
|
return {
|
|
113
106
|
nodes,
|
|
114
107
|
hasNextPage,
|
|
115
108
|
endCursor,
|
|
109
|
+
total,
|
|
116
110
|
};
|
|
117
111
|
},
|
|
118
112
|
initialPageParam: "",
|
|
@@ -121,7 +115,10 @@ export function createUseInfiniteQuery(init) {
|
|
|
121
115
|
return lastPage.hasNextPage ? lastPage.endCursor : undefined;
|
|
122
116
|
},
|
|
123
117
|
select(data) {
|
|
124
|
-
return
|
|
118
|
+
return {
|
|
119
|
+
nodes: data.pages.flatMap((page) => page.nodes),
|
|
120
|
+
total: data.pages[data.pages.length - 1]?.total,
|
|
121
|
+
};
|
|
125
122
|
},
|
|
126
123
|
...options,
|
|
127
124
|
...initial,
|
|
@@ -142,7 +139,7 @@ const fetchMutation = async (name, params, opts) => {
|
|
|
142
139
|
};
|
|
143
140
|
if (env.serverless && env.client) {
|
|
144
141
|
// Relative request (in browser)
|
|
145
|
-
url = `/
|
|
142
|
+
url = `/_data/mutation/${name}`;
|
|
146
143
|
}
|
|
147
144
|
else if (env.serverless) {
|
|
148
145
|
// Request to the origin server (server to server)
|
|
@@ -1,9 +1,7 @@
|
|
|
1
1
|
import { FunctionComponent } from "react";
|
|
2
|
-
import { Config as TailwindConfig } from "tailwindcss";
|
|
3
2
|
type BlockManifest = Record<string, FunctionComponent<any>>;
|
|
4
3
|
type Store = {
|
|
5
4
|
blocks: BlockManifest;
|
|
6
|
-
tailwindConfig: TailwindConfig | null;
|
|
7
5
|
};
|
|
8
6
|
export declare const internalStore: Store & {
|
|
9
7
|
set<K extends keyof Store>(key: K, value: Store[K]): void;
|
|
@@ -8,5 +8,5 @@ type Props = PropsWithChildren<{
|
|
|
8
8
|
*
|
|
9
9
|
* The optional 'fallback' prop can be used to show a loading state or placeholder content while the client bundle is loading.
|
|
10
10
|
*/
|
|
11
|
-
export declare function ClientOnly(props: Props): string | number | boolean |
|
|
11
|
+
export declare function ClientOnly(props: Props): string | number | boolean | import("react/jsx-runtime").JSX.Element | Iterable<import("react").ReactNode> | null;
|
|
12
12
|
export {};
|
|
@@ -31,10 +31,12 @@ export class RouteLoader {
|
|
|
31
31
|
const origin = parseURL(sampleUrl);
|
|
32
32
|
let propsPath = withTrailingSlash(pathname);
|
|
33
33
|
let query = {};
|
|
34
|
-
if (
|
|
35
|
-
|
|
36
|
-
query
|
|
37
|
-
query["
|
|
34
|
+
if (env.serverless && env.client) {
|
|
35
|
+
propsPath = "/_data/route" + propsPath;
|
|
36
|
+
query = {};
|
|
37
|
+
// query["_debug"] = opts.debug ? "1" : "0"
|
|
38
|
+
// query["_props"] = opts.appData ? "all" : "1"
|
|
39
|
+
// query["_ssr"] = "1"
|
|
38
40
|
}
|
|
39
41
|
else {
|
|
40
42
|
query["_debug"] = opts.debug ? "1" : "0";
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
/// <reference types="vinxi/types/server" />
|
|
2
|
+
import { splitSetCookieString } from "cookie-es";
|
|
3
|
+
import { getProxyRequestHeaders, getRequestURL, getWebRequest } from "vinxi/http";
|
|
4
|
+
import { getManifest } from "vinxi/manifest";
|
|
5
|
+
export async function proxyWpAdmin(event, serverContext) {
|
|
6
|
+
const replaceUrls = serverContext.replaceUrls;
|
|
7
|
+
const req = getWebRequest(event);
|
|
8
|
+
const proxyUrl = serverContext.getOriginUrl(getRequestURL(event).href);
|
|
9
|
+
// Prepare request headers to be sent to the origin server
|
|
10
|
+
const proxyHeaders = getProxyRequestHeaders(event);
|
|
11
|
+
proxyHeaders["X-ED-Dev-Proxy"] = "true";
|
|
12
|
+
// Forward the request to the origin server
|
|
13
|
+
const response = await fetch(proxyUrl, {
|
|
14
|
+
method: req.method,
|
|
15
|
+
referrer: req.referrer,
|
|
16
|
+
referrerPolicy: req.referrerPolicy,
|
|
17
|
+
headers: proxyHeaders,
|
|
18
|
+
body: req.method.match(/get|head|options/i) ? undefined : await req.blob(),
|
|
19
|
+
redirect: "manual",
|
|
20
|
+
cache: "no-cache",
|
|
21
|
+
});
|
|
22
|
+
const contentType = response.headers.get("content-type");
|
|
23
|
+
let body;
|
|
24
|
+
let res = { status: response.status, statusText: response.statusText, headers: new Headers() };
|
|
25
|
+
const cookies = [];
|
|
26
|
+
response.headers.forEach((value, key) => {
|
|
27
|
+
if (key === "content-encoding" || key === "content-length" || key === "transfer-encoding") {
|
|
28
|
+
return;
|
|
29
|
+
}
|
|
30
|
+
if (key === "set-cookie") {
|
|
31
|
+
cookies.push(...splitSetCookieString(value));
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
if (key === "location" && replaceUrls) {
|
|
35
|
+
value = replaceUrls(value);
|
|
36
|
+
}
|
|
37
|
+
res.headers.set(key, value);
|
|
38
|
+
});
|
|
39
|
+
// Set cookies in the response headers
|
|
40
|
+
// TODO: May need to rewrite cookie domain here before setting.
|
|
41
|
+
if (cookies.length > 0) {
|
|
42
|
+
for (const cookie of cookies) {
|
|
43
|
+
res.headers.append("set-cookie", cookie);
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
// Replace URLs pointing to the origin server from the response itself
|
|
47
|
+
// This is only done for text-based content types, like application/json, text/plain, text/html etc
|
|
48
|
+
if (contentType?.match(/(application|text)\//)) {
|
|
49
|
+
if (replaceUrls) {
|
|
50
|
+
body = replaceUrls((await response.text()) ?? "");
|
|
51
|
+
}
|
|
52
|
+
// If the content type is text/html, inject the Vite assets into the response — assuming the placeholder comments are found
|
|
53
|
+
if (contentType.startsWith("text/html")) {
|
|
54
|
+
const clientManifest = getManifest("admin");
|
|
55
|
+
const assets = await clientManifest.inputs[clientManifest.handler].assets();
|
|
56
|
+
body = body.replace("<!---VITE_HEADER--->", () => assets.map((asset) => renderAsset(asset)).join("\n"));
|
|
57
|
+
body = body.replace("<!---VITE_FOOTER--->", () => renderAsset({
|
|
58
|
+
tag: "script",
|
|
59
|
+
attrs: {
|
|
60
|
+
type: "module",
|
|
61
|
+
src: clientManifest.inputs[clientManifest.handler].output.path,
|
|
62
|
+
},
|
|
63
|
+
children: "",
|
|
64
|
+
}));
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
// Otherwise just stream the response as is
|
|
69
|
+
body = response.body;
|
|
70
|
+
}
|
|
71
|
+
return new Response(body, res);
|
|
72
|
+
}
|
|
73
|
+
function printElement(element, props, innerText) {
|
|
74
|
+
if (typeof innerText === "string") {
|
|
75
|
+
return `<${element}${Object.entries(props)
|
|
76
|
+
.map(([key, value]) => ` ${key}="${value}"`)
|
|
77
|
+
.join("")}>${innerText}</${element}>`;
|
|
78
|
+
}
|
|
79
|
+
else {
|
|
80
|
+
return `<${element}${Object.entries(props)
|
|
81
|
+
.map(([key, value]) => ` ${key}="${value}"`)
|
|
82
|
+
.join("")} />`;
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
function renderAsset({ tag, attrs: { key, ...attrs } = {}, children, }) {
|
|
86
|
+
switch (tag) {
|
|
87
|
+
case "script":
|
|
88
|
+
if (attrs.src) {
|
|
89
|
+
return printElement("script", { ...attrs, key: attrs.src }, "");
|
|
90
|
+
}
|
|
91
|
+
else {
|
|
92
|
+
return printElement("script", {
|
|
93
|
+
...attrs,
|
|
94
|
+
key: key,
|
|
95
|
+
}, children ?? "");
|
|
96
|
+
}
|
|
97
|
+
case "link":
|
|
98
|
+
return printElement("link", { ...attrs, key: key });
|
|
99
|
+
case "style":
|
|
100
|
+
return printElement("style", {
|
|
101
|
+
...attrs,
|
|
102
|
+
key: key,
|
|
103
|
+
}, children ?? "");
|
|
104
|
+
}
|
|
105
|
+
return "";
|
|
106
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
|
+
import { renderAsset } from "@vinxi/react";
|
|
3
|
+
import { Suspense } from "react";
|
|
4
|
+
import { renderToPipeableStream } from "react-dom/server";
|
|
5
|
+
import { getManifest } from "vinxi/manifest";
|
|
6
|
+
import { SSRRoot } from "../entry/ssr-root.js";
|
|
7
|
+
import { RouteLoader } from "../lib/routing/loader.js";
|
|
8
|
+
export async function renderPageToSSRStream(pathname, initialData) {
|
|
9
|
+
const clientManifest = getManifest("client");
|
|
10
|
+
const assets = await clientManifest.inputs[clientManifest.handler].assets();
|
|
11
|
+
const jsx = (_jsx(SSRRoot, { assets: _jsx(Suspense, { children: assets.map((m) => renderAsset(m)) }), pathname: pathname, initialData: initialData, loader: new RouteLoader() }));
|
|
12
|
+
const stream = await new Promise(async (resolve) => {
|
|
13
|
+
const stream = renderToPipeableStream(jsx, {
|
|
14
|
+
onShellReady() {
|
|
15
|
+
resolve(stream);
|
|
16
|
+
},
|
|
17
|
+
bootstrapModules: [clientManifest.inputs[clientManifest.handler].output.path],
|
|
18
|
+
bootstrapScriptContent: `window.manifest = ${JSON.stringify(await clientManifest.json())}; window._PAGE_DATA = ${JSON.stringify(initialData)}`,
|
|
19
|
+
});
|
|
20
|
+
});
|
|
21
|
+
return stream;
|
|
22
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import { UrlReplacerConf } from "./utils/replace-host.js";
|
|
2
|
+
import { RequestHeaders } from "vinxi/http";
|
|
3
|
+
export type ServerContextArgs = {
|
|
4
|
+
dev: boolean;
|
|
5
|
+
origin: string;
|
|
6
|
+
replaceUrls?: UrlReplacerConf;
|
|
7
|
+
};
|
|
8
|
+
export declare class ServerContext {
|
|
9
|
+
dev: boolean;
|
|
10
|
+
origin: string;
|
|
11
|
+
replaceUrls?: (text: string) => string;
|
|
12
|
+
constructor(conf: ServerContextArgs);
|
|
13
|
+
getOriginUrl(url: string): string;
|
|
14
|
+
fetchOrigin(url: string, opts?: RequestInit & {
|
|
15
|
+
replaceUrls?: boolean;
|
|
16
|
+
}): Promise<Response>;
|
|
17
|
+
fetchRouteData(req: {
|
|
18
|
+
pathname: string;
|
|
19
|
+
query?: Record<string, any>;
|
|
20
|
+
headers?: RequestHeaders;
|
|
21
|
+
withAppData?: boolean;
|
|
22
|
+
}): Promise<Response>;
|
|
23
|
+
extractRequestHeaders(req?: RequestHeaders): Partial<Record<import("vinxi/http").HTTPHeaderName, string | undefined>>;
|
|
24
|
+
fetchNamedQuery(req: {
|
|
25
|
+
name: string;
|
|
26
|
+
params: object;
|
|
27
|
+
headers: RequestHeaders;
|
|
28
|
+
}): Promise<Response>;
|
|
29
|
+
fetchMutation(req: {
|
|
30
|
+
name: string;
|
|
31
|
+
body: object;
|
|
32
|
+
headers: RequestHeaders;
|
|
33
|
+
}): Promise<Response>;
|
|
34
|
+
}
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
import { parseURL, stringifyParsedURL, withQuery } from "ufo";
|
|
2
|
+
import { filterHeader } from "./utils/headers.js";
|
|
3
|
+
import { createUrlReplacer } from "./utils/replace-host.js";
|
|
4
|
+
const PROXY_RESPONSE_HEADERS = ["content-type", "set-cookie", /^x-/, "cache-control"];
|
|
5
|
+
const PROXY_REQUEST_HEADERS = [
|
|
6
|
+
"content-type",
|
|
7
|
+
"accept",
|
|
8
|
+
"accept-encoding",
|
|
9
|
+
"accept-language",
|
|
10
|
+
"origin",
|
|
11
|
+
"referer",
|
|
12
|
+
"user-agent",
|
|
13
|
+
"authorization",
|
|
14
|
+
];
|
|
15
|
+
export class ServerContext {
|
|
16
|
+
dev;
|
|
17
|
+
origin;
|
|
18
|
+
replaceUrls;
|
|
19
|
+
constructor(conf) {
|
|
20
|
+
this.dev = conf.dev;
|
|
21
|
+
this.origin = conf.origin;
|
|
22
|
+
if (conf.replaceUrls) {
|
|
23
|
+
this.replaceUrls = createUrlReplacer(conf.replaceUrls);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
getOriginUrl(url) {
|
|
27
|
+
const parsed = parseURL(url);
|
|
28
|
+
const parsedOrigin = parseURL(env.origin);
|
|
29
|
+
parsed.host = parsedOrigin.host;
|
|
30
|
+
parsed.protocol = parsedOrigin.protocol;
|
|
31
|
+
return stringifyParsedURL(parsed);
|
|
32
|
+
}
|
|
33
|
+
async fetchOrigin(url, opts) {
|
|
34
|
+
url = this.getOriginUrl(url);
|
|
35
|
+
const response = await fetch(url, {
|
|
36
|
+
...opts,
|
|
37
|
+
headers: {
|
|
38
|
+
"Content-Type": "application/json",
|
|
39
|
+
Accept: "application/json",
|
|
40
|
+
...opts?.headers,
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
if (!response.ok) {
|
|
44
|
+
return response;
|
|
45
|
+
}
|
|
46
|
+
const headers = {};
|
|
47
|
+
response.headers.forEach((value, key) => {
|
|
48
|
+
if (filterHeader(key, PROXY_RESPONSE_HEADERS)) {
|
|
49
|
+
headers[key] = value;
|
|
50
|
+
}
|
|
51
|
+
});
|
|
52
|
+
let text = await response.text();
|
|
53
|
+
if (opts?.replaceUrls && this.replaceUrls) {
|
|
54
|
+
text = this.replaceUrls(text);
|
|
55
|
+
}
|
|
56
|
+
return new Response(text, {
|
|
57
|
+
status: response.status,
|
|
58
|
+
statusText: response.statusText,
|
|
59
|
+
headers,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
async fetchRouteData(req) {
|
|
63
|
+
const fetchUrl = withQuery(req.pathname, {
|
|
64
|
+
...req.query,
|
|
65
|
+
_props: req.withAppData ? "all" : "1",
|
|
66
|
+
_ssr: "1",
|
|
67
|
+
_debug: this.dev ? "1" : undefined,
|
|
68
|
+
});
|
|
69
|
+
return this.fetchOrigin(fetchUrl, {
|
|
70
|
+
cache: "no-cache",
|
|
71
|
+
replaceUrls: true,
|
|
72
|
+
headers: {
|
|
73
|
+
"Content-Type": "application/json",
|
|
74
|
+
Accept: "application/json",
|
|
75
|
+
...this.extractRequestHeaders(req.headers),
|
|
76
|
+
},
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
extractRequestHeaders(req) {
|
|
80
|
+
const headers = {};
|
|
81
|
+
if (req) {
|
|
82
|
+
for (let key of PROXY_REQUEST_HEADERS) {
|
|
83
|
+
if (req[key]) {
|
|
84
|
+
headers[key] = req[key];
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
return headers;
|
|
89
|
+
}
|
|
90
|
+
async fetchNamedQuery(req) {
|
|
91
|
+
const url = `/wp-json/ed/v1/query/${req.name}?params=${encodeURIComponent(JSON.stringify(req.params))}`;
|
|
92
|
+
return this.fetchOrigin(url, {
|
|
93
|
+
cache: "no-cache",
|
|
94
|
+
replaceUrls: true,
|
|
95
|
+
headers: {
|
|
96
|
+
...this.extractRequestHeaders(req.headers),
|
|
97
|
+
"Content-Type": "application/json",
|
|
98
|
+
Accept: "application/json",
|
|
99
|
+
},
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
async fetchMutation(req) {
|
|
103
|
+
const url = `/wp-json/ed/v1/mutation/${req.name}`;
|
|
104
|
+
return this.fetchOrigin(url, {
|
|
105
|
+
method: "POST",
|
|
106
|
+
cache: "no-cache",
|
|
107
|
+
replaceUrls: true,
|
|
108
|
+
headers: {
|
|
109
|
+
...this.extractRequestHeaders(req.headers),
|
|
110
|
+
"Content-Type": "application/json",
|
|
111
|
+
Accept: "application/json",
|
|
112
|
+
},
|
|
113
|
+
body: JSON.stringify(req.body),
|
|
114
|
+
});
|
|
115
|
+
}
|
|
116
|
+
}
|
|
@@ -9,3 +9,20 @@ export function filterHeader(key, allowed) {
|
|
|
9
9
|
export const BRANDED_HEADERS = {
|
|
10
10
|
"X-Powered-By": "ed.studio",
|
|
11
11
|
};
|
|
12
|
+
const IGNORE_REQUEST_HEADERS = [
|
|
13
|
+
"host",
|
|
14
|
+
"connection",
|
|
15
|
+
"accept-encoding",
|
|
16
|
+
"accept-language",
|
|
17
|
+
"origin",
|
|
18
|
+
"referer",
|
|
19
|
+
"user-agent",
|
|
20
|
+
];
|
|
21
|
+
export function extractHeaders(rawHeaders) {
|
|
22
|
+
const headers = {};
|
|
23
|
+
rawHeaders.forEach((value, key) => {
|
|
24
|
+
headers[key] = value;
|
|
25
|
+
});
|
|
26
|
+
IGNORE_REQUEST_HEADERS.forEach((key) => delete headers[key]);
|
|
27
|
+
return headers;
|
|
28
|
+
}
|
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
export type UrlReplacerConf = {
|
|
2
2
|
from: string;
|
|
3
3
|
to: string;
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
4
|
+
/** A dictionary of prefixes (eg /wp-content), and whether to replace them (true/false) */
|
|
5
|
+
prefixes: {
|
|
6
|
+
prefix: string;
|
|
7
|
+
replace: boolean;
|
|
8
|
+
}[];
|
|
7
9
|
};
|
|
8
|
-
export declare function createUrlReplacer(conf: UrlReplacerConf): (
|
|
10
|
+
export declare function createUrlReplacer(conf: UrlReplacerConf): (text: string) => string;
|
|
@@ -1,14 +1,61 @@
|
|
|
1
1
|
export function createUrlReplacer(conf) {
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
const
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
2
|
+
// Create a regular expression to match the URL
|
|
3
|
+
// Note that that the regex doesn't necessarily match the entire URL
|
|
4
|
+
const lookup = new RegExp(conf.from.replace(/https?[:\\\/]+/, "https?[:\\/\\\\]+") + "([a-z0-9\\-_/\\\\]+)", "ig");
|
|
5
|
+
return (text) => {
|
|
6
|
+
return text.replace(lookup, (url) => {
|
|
7
|
+
// Strip out the origin, to create a relative path
|
|
8
|
+
const path = url.replace(/https?:[\/\\]+[^\/\\]+/, "");
|
|
9
|
+
const isEscaped = url.includes(":\\/\\/");
|
|
10
|
+
const key = "/" +
|
|
11
|
+
path
|
|
12
|
+
.split(/[\/\\]+/g)
|
|
13
|
+
.filter((v) => v)
|
|
14
|
+
.join("/");
|
|
15
|
+
for (let item of conf.prefixes) {
|
|
16
|
+
if (key.startsWith(item.prefix)) {
|
|
17
|
+
if (item.replace) {
|
|
18
|
+
return url;
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
return path;
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
return path;
|
|
26
|
+
// if (path.startsWith("/wp-content/uploads/")) {
|
|
27
|
+
// if (!conf.ignoreUploads) {
|
|
28
|
+
// return path
|
|
29
|
+
// } else {
|
|
30
|
+
// return url
|
|
31
|
+
// }
|
|
32
|
+
// // } else if (path.startsWith("/wp-content/themes/")) {
|
|
33
|
+
// // if (settings?.uploads === "proxy") {
|
|
34
|
+
// // return path
|
|
35
|
+
// // } else if (settings?.uploads === "remote") {
|
|
36
|
+
// // return url
|
|
37
|
+
// // }
|
|
38
|
+
// // } else if (path.startsWith("/wp-content/plugins/")) {
|
|
39
|
+
// // if (settings?.uploads === "proxy") {
|
|
40
|
+
// // return path
|
|
41
|
+
// // } else if (settings?.uploads === "remote") {
|
|
42
|
+
// // return url
|
|
43
|
+
// // }
|
|
44
|
+
// } else {
|
|
45
|
+
// return path
|
|
46
|
+
// }
|
|
47
|
+
});
|
|
13
48
|
};
|
|
49
|
+
// const from = conf.from
|
|
50
|
+
// const to = conf.to
|
|
51
|
+
// const https = conf.https
|
|
52
|
+
// const ignoreUploads = conf.ignoreUploads
|
|
53
|
+
// const ignorePlugins = conf.ignorePlugins
|
|
54
|
+
// const replaceTargetString = from.replaceAll(/https?:/g, "https?:").replaceAll("/", "\\/")
|
|
55
|
+
// const replaceTargetEscapedString = from.replaceAll(/https?:/g, "https?:").replaceAll("/", "\\\\/")
|
|
56
|
+
// const replaceTarget = new RegExp(replaceTargetString, "g")
|
|
57
|
+
// const replaceTargetEscaped = new RegExp(replaceTargetEscapedString, "g")
|
|
58
|
+
// return (value: string) => {
|
|
59
|
+
// return value.replaceAll(replaceTarget, to).replace(replaceTargetEscaped, to.replaceAll("/", "\\/"))
|
|
60
|
+
// }
|
|
14
61
|
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { Worker } from "node:worker_threads";
|
|
2
|
-
import { StatefulLog } from "../utils/
|
|
2
|
+
import { StatefulLog } from "../utils/stateful-log.js";
|
|
3
3
|
type WorkerMode = "admin" | "frontend" | "graphql" | "serverless";
|
|
4
4
|
export declare class CLIWorker {
|
|
5
5
|
worker: Worker;
|
|
@@ -46,6 +46,8 @@ export class CLIWorker {
|
|
|
46
46
|
}
|
|
47
47
|
if (!isMainThread) {
|
|
48
48
|
const mode = workerData.mode;
|
|
49
|
+
/** Ignore self-signed certificate errors in dev mode */
|
|
50
|
+
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0";
|
|
49
51
|
configureCliMode({
|
|
50
52
|
interactive: true,
|
|
51
53
|
readonly: false,
|
|
@@ -84,6 +86,7 @@ if (!isMainThread) {
|
|
|
84
86
|
}
|
|
85
87
|
function pipeLog(log) {
|
|
86
88
|
log.subscribe((log) => {
|
|
89
|
+
// We ignore SSL errors in dev mode.
|
|
87
90
|
parentPort?.postMessage(JSON.stringify({ type: "log", log: serializeLogData(log) }));
|
|
88
91
|
});
|
|
89
92
|
}
|
package/dist/node/cli/cli.js
CHANGED
|
@@ -2,9 +2,10 @@ import chalk from "chalk";
|
|
|
2
2
|
import { Command } from "commander";
|
|
3
3
|
import { setDefaultResultOrder } from "dns";
|
|
4
4
|
import { config as importDotEnv } from "dotenv";
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
7
|
-
import {
|
|
5
|
+
import { adminLog } from "../compiler/bundler.admin.js";
|
|
6
|
+
import { frontendLog } from "../compiler/bundler.frontend.js";
|
|
7
|
+
import { DevServer, serverlessLog } from "../compiler/dev-server.js";
|
|
8
|
+
import { createVinxiCodegen } from "../compiler/vinxi-codegen.js";
|
|
8
9
|
import { graphqlLog } from "../graphql/graphql-codegen.js";
|
|
9
10
|
import { BuildInfoWriter } from "../project/eddev-build-file.js";
|
|
10
11
|
import { Project, projectLog } from "../project/project.js";
|
|
@@ -14,6 +15,8 @@ import { configureCliMode } from "./cli-mode.js";
|
|
|
14
15
|
import { CLIWorker } from "./cli-worker.js";
|
|
15
16
|
import { bootCLIUI } from "./display/boot-cli-app.js";
|
|
16
17
|
import { VERSION } from "./version.js";
|
|
18
|
+
import { buildVinxi } from "../compiler/build-vinxi.js";
|
|
19
|
+
import { createConsole } from "../utils/stateful-log.js";
|
|
17
20
|
importDotEnv();
|
|
18
21
|
const program = new Command()
|
|
19
22
|
.version(VERSION)
|
|
@@ -24,12 +27,13 @@ const init = (verbose) => {
|
|
|
24
27
|
};
|
|
25
28
|
program
|
|
26
29
|
.command("dev")
|
|
27
|
-
.description("
|
|
28
|
-
.option("-
|
|
29
|
-
.option("-m, --mode <mode>", 'Defaults to all modes, but use "frontend", "admin" or "graphql" to run in just one mode', undefined)
|
|
30
|
+
.description("Run in dev mode")
|
|
31
|
+
.option("-m, --mode <mode>", "Comma separated list of modes, or a single mode.", "frontend,admin,graphql,serverless")
|
|
30
32
|
.option("--verbose", "Show extra debugging info", false)
|
|
31
33
|
.action(async (options) => {
|
|
32
|
-
process.env
|
|
34
|
+
process.env["NODE_ENV"] = "development";
|
|
35
|
+
/** Ignore self-signed certificate errors in dev mode */
|
|
36
|
+
process.env["NODE_TLS_REJECT_UNAUTHORIZED"] = "0";
|
|
33
37
|
serverlessLog.info(chalk.yellowBright(`⚡️ ED. Stack v${VERSION}`));
|
|
34
38
|
const tasks = {
|
|
35
39
|
admin: !options.mode || options.mode.includes("admin"),
|
|
@@ -66,6 +70,15 @@ program
|
|
|
66
70
|
const infoWriter = new BuildInfoWriter(project);
|
|
67
71
|
infoWriter.watch();
|
|
68
72
|
infoWriter.write();
|
|
73
|
+
if (tasks.admin || tasks.frontend) {
|
|
74
|
+
const spaStaging = createVinxiCodegen({
|
|
75
|
+
mode: "development",
|
|
76
|
+
project,
|
|
77
|
+
serverless: false,
|
|
78
|
+
endpoint: "",
|
|
79
|
+
});
|
|
80
|
+
spaStaging.runAndWatch();
|
|
81
|
+
}
|
|
69
82
|
// Boot up admin in a worker
|
|
70
83
|
if (tasks.admin) {
|
|
71
84
|
new CLIWorker({
|
|
@@ -88,6 +101,9 @@ program
|
|
|
88
101
|
serverlessLog.log(...args);
|
|
89
102
|
};
|
|
90
103
|
console.error = (...args) => {
|
|
104
|
+
// We ignore SSL errors in dev mode.
|
|
105
|
+
if (typeof args[0] === "string" && args[0].includes("NODE_TLS_REJECT_UNAUTHORIZED"))
|
|
106
|
+
return;
|
|
91
107
|
serverlessLog.error(...args);
|
|
92
108
|
};
|
|
93
109
|
console.warn = (...args) => {
|
|
@@ -96,7 +112,14 @@ program
|
|
|
96
112
|
console.info = (...args) => {
|
|
97
113
|
serverlessLog.info(...args);
|
|
98
114
|
};
|
|
99
|
-
|
|
115
|
+
const serverlessStaging = createVinxiCodegen({
|
|
116
|
+
mode: "development",
|
|
117
|
+
project,
|
|
118
|
+
serverless: true,
|
|
119
|
+
endpoint: "",
|
|
120
|
+
});
|
|
121
|
+
await serverlessStaging.runAndWatch();
|
|
122
|
+
new DevServer(project, {
|
|
100
123
|
mode: "development",
|
|
101
124
|
});
|
|
102
125
|
}
|
|
@@ -125,17 +148,25 @@ program
|
|
|
125
148
|
watch: false,
|
|
126
149
|
rootDir: process.cwd(),
|
|
127
150
|
});
|
|
151
|
+
const console = createConsole("build");
|
|
128
152
|
// Load the project info
|
|
129
153
|
const project = await Project.create({
|
|
130
154
|
rootDir: process.cwd(),
|
|
131
155
|
});
|
|
156
|
+
const buildServerless = options.serverless || process.env.VERCEL;
|
|
157
|
+
if (buildServerless) {
|
|
158
|
+
await buildVinxi({
|
|
159
|
+
project,
|
|
160
|
+
console,
|
|
161
|
+
});
|
|
162
|
+
}
|
|
132
163
|
// Load the compiler
|
|
133
|
-
new AdminBundler(project, {
|
|
134
|
-
|
|
135
|
-
})
|
|
136
|
-
new FrontendBundler(project, {
|
|
137
|
-
|
|
138
|
-
})
|
|
164
|
+
// new AdminBundler(project, {
|
|
165
|
+
// mode: "development",
|
|
166
|
+
// })
|
|
167
|
+
// new FrontendBundler(project, {
|
|
168
|
+
// mode: "production",
|
|
169
|
+
// })
|
|
139
170
|
});
|
|
140
171
|
program
|
|
141
172
|
.command("info")
|