eddev 2.2.7 → 2.2.8

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.
Files changed (164) hide show
  1. package/dist/app/entry/MetaTags.d.ts +8 -0
  2. package/dist/app/entry/MetaTags.d.ts.map +1 -0
  3. package/dist/app/entry/MetaTags.js +32 -0
  4. package/dist/app/entry/boot-admin.d.ts +2 -0
  5. package/dist/app/entry/boot-admin.d.ts.map +1 -0
  6. package/dist/app/entry/boot-admin.js +12 -0
  7. package/dist/app/entry/hydration-script.d.ts +2 -0
  8. package/dist/app/entry/hydration-script.d.ts.map +1 -0
  9. package/dist/app/entry/hydration-script.js +18 -0
  10. package/dist/app/entry/spa-root.d.ts +2 -0
  11. package/dist/app/entry/spa-root.d.ts.map +1 -0
  12. package/dist/app/entry/spa-root.js +7 -0
  13. package/dist/app/entry/ssr-root-client.d.ts +7 -0
  14. package/dist/app/entry/ssr-root-client.d.ts.map +1 -0
  15. package/dist/app/entry/ssr-root-client.js +21 -0
  16. package/dist/app/entry/ssr-root.d.ts +11 -0
  17. package/dist/app/entry/ssr-root.d.ts.map +1 -0
  18. package/dist/app/entry/ssr-root.js +22 -0
  19. package/dist/app/lib/admin/installFieldTypes.d.ts +2 -0
  20. package/dist/app/lib/admin/installFieldTypes.d.ts.map +1 -0
  21. package/dist/app/lib/admin/installFieldTypes.js +94 -0
  22. package/dist/app/lib/admin/runWidgets.d.ts +2 -0
  23. package/dist/app/lib/admin/runWidgets.d.ts.map +1 -0
  24. package/dist/app/lib/admin/runWidgets.js +43 -0
  25. package/dist/app/lib/blocks/editor/EditingContext.d.ts +2 -0
  26. package/dist/app/lib/blocks/editor/EditingContext.d.ts.map +1 -0
  27. package/dist/app/lib/blocks/editor/EditingContext.js +31 -0
  28. package/dist/app/lib/devtools/components/DevMenu.d.ts +2 -0
  29. package/dist/app/lib/devtools/components/DevMenu.d.ts.map +1 -0
  30. package/dist/app/lib/devtools/components/DevUI.d.ts +16 -0
  31. package/dist/app/lib/devtools/components/DevUI.d.ts.map +1 -0
  32. package/dist/app/lib/devtools/components/DevUI.js +34 -0
  33. package/dist/app/lib/devtools/components/GridIndicator.d.ts +2 -0
  34. package/dist/app/lib/devtools/components/GridIndicator.d.ts.map +1 -0
  35. package/dist/app/lib/devtools/components/GridIndicator.js +30 -0
  36. package/dist/app/lib/devtools/components/panels/monaco-graphql.worker.d.ts +2 -0
  37. package/dist/app/lib/devtools/components/panels/monaco-graphql.worker.d.ts.map +1 -0
  38. package/dist/app/lib/devtools/components/panels/monaco-graphql.worker.js +9 -0
  39. package/dist/app/lib/devtools/components/ui/Tabs.d.ts +13 -0
  40. package/dist/app/lib/devtools/components/ui/Tabs.d.ts.map +1 -0
  41. package/dist/app/lib/devtools/components/ui/Tabs.js +7 -0
  42. package/dist/app/lib/devtools/index.d.ts +2 -0
  43. package/dist/app/lib/devtools/index.d.ts.map +1 -0
  44. package/dist/app/lib/devtools/index.js +1 -0
  45. package/dist/app/lib/devtools/loader.d.ts +2 -0
  46. package/dist/app/lib/devtools/loader.d.ts.map +1 -0
  47. package/dist/app/lib/devtools/loader.js +25 -0
  48. package/dist/app/lib/devtools/tailwind.config.d.ts +29 -0
  49. package/dist/app/lib/devtools/tailwind.config.d.ts.map +1 -0
  50. package/dist/app/lib/devtools/tailwind.config.js +29 -0
  51. package/dist/app/lib/devtools/useQueryDebug.d.ts +16 -0
  52. package/dist/app/lib/devtools/useQueryDebug.d.ts.map +1 -0
  53. package/dist/app/lib/devtools/useQueryDebug.js +10 -0
  54. package/dist/app/lib/dynamic/index.d.ts +2 -0
  55. package/dist/app/lib/dynamic/index.d.ts.map +1 -0
  56. package/dist/app/lib/dynamic/index.js +1 -0
  57. package/dist/app/lib/integrations/gravityforms/createGravityFormComponent.d.ts +93 -0
  58. package/dist/app/lib/integrations/gravityforms/createGravityFormComponent.d.ts.map +1 -0
  59. package/dist/app/lib/integrations/gravityforms/createGravityFormComponent.js +134 -0
  60. package/dist/app/lib/integrations/gravityforms/field-types.d.ts +141 -0
  61. package/dist/app/lib/integrations/gravityforms/field-types.d.ts.map +1 -0
  62. package/dist/app/lib/integrations/gravityforms/field-types.js +489 -0
  63. package/dist/app/lib/integrations/gravityforms/index.d.ts +5 -0
  64. package/dist/app/lib/integrations/gravityforms/index.d.ts.map +1 -0
  65. package/dist/app/lib/integrations/gravityforms/index.js +4 -0
  66. package/dist/app/lib/integrations/gravityforms/types.d.ts +64 -0
  67. package/dist/app/lib/integrations/gravityforms/types.d.ts.map +1 -0
  68. package/dist/app/lib/integrations/gravityforms/types.js +1 -0
  69. package/dist/app/lib/integrations/gravityforms/useGravityForm.d.ts +75 -0
  70. package/dist/app/lib/integrations/gravityforms/useGravityForm.d.ts.map +1 -0
  71. package/dist/app/lib/integrations/gravityforms/useGravityForm.js +288 -0
  72. package/dist/app/lib/internal/finalize-rpc.d.ts +18 -0
  73. package/dist/app/lib/internal/finalize-rpc.d.ts.map +1 -0
  74. package/dist/app/lib/internal/finalize-rpc.js +3 -0
  75. package/dist/app/lib/internal/index.d.ts +6 -0
  76. package/dist/app/lib/internal/index.d.ts.map +1 -0
  77. package/dist/app/lib/internal/index.js +5 -0
  78. package/dist/app/lib/internal/internal-store.d.ts +10 -0
  79. package/dist/app/lib/internal/internal-store.d.ts.map +1 -0
  80. package/dist/app/lib/internal/internal-store.js +7 -0
  81. package/dist/app/lib/legacy-stitches/createStitches.d.ts +616 -0
  82. package/dist/app/lib/legacy-stitches/createStitches.d.ts.map +1 -0
  83. package/dist/app/lib/legacy-stitches/createStitches.js +439 -0
  84. package/dist/app/lib/legacy-stitches/index.d.ts +2 -0
  85. package/dist/app/lib/legacy-stitches/index.d.ts.map +1 -0
  86. package/dist/app/lib/legacy-stitches/index.js +1 -0
  87. package/dist/app/lib/routing/components/BackButton.d.ts +50 -0
  88. package/dist/app/lib/routing/components/BackButton.d.ts.map +1 -0
  89. package/dist/app/lib/routing/components/BackButton.js +47 -0
  90. package/dist/app/lib/routing/components/ClientOnly.d.ts +13 -0
  91. package/dist/app/lib/routing/components/ClientOnly.d.ts.map +1 -0
  92. package/dist/app/lib/routing/components/ClientOnly.js +14 -0
  93. package/dist/app/lib/routing/components/NativeLinkHandler.d.ts +10 -0
  94. package/dist/app/lib/routing/components/NativeLinkHandler.d.ts.map +1 -0
  95. package/dist/app/lib/routing/components/NativeLinkHandler.js +23 -0
  96. package/dist/app/lib/routing/components/RouteRenderer.d.ts +10 -0
  97. package/dist/app/lib/routing/components/RouteRenderer.d.ts.map +1 -0
  98. package/dist/app/lib/routing/components/RouteRenderer.js +54 -0
  99. package/dist/app/lib/routing/components/SSRRouter.d.ts +12 -0
  100. package/dist/app/lib/routing/components/SSRRouter.d.ts.map +1 -0
  101. package/dist/app/lib/routing/components/SSRRouter.js +15 -0
  102. package/dist/app/lib/routing/hooks/useRestorableState.d.ts +7 -0
  103. package/dist/app/lib/routing/hooks/useRestorableState.d.ts.map +1 -0
  104. package/dist/app/lib/routing/hooks/useRestorableState.js +23 -0
  105. package/dist/app/lib/routing/hooks/useRouteTransition.d.ts +5 -0
  106. package/dist/app/lib/routing/hooks/useRouteTransition.d.ts.map +1 -0
  107. package/dist/app/lib/routing/hooks/useRouteTransition.js +12 -0
  108. package/dist/app/lib/routing/hooks/useSearchParams.d.ts +98 -0
  109. package/dist/app/lib/routing/hooks/useSearchParams.d.ts.map +1 -0
  110. package/dist/app/lib/routing/hooks/useSearchParams.js +131 -0
  111. package/dist/app/lib/routing/index.d.ts +17 -0
  112. package/dist/app/lib/routing/index.d.ts.map +1 -0
  113. package/dist/app/lib/routing/index.js +16 -0
  114. package/dist/app/lib/runtime/index.d.ts +3 -0
  115. package/dist/app/lib/runtime/index.d.ts.map +1 -0
  116. package/dist/app/lib/runtime/index.js +2 -0
  117. package/dist/app/lib/views/defineView.d.ts +5 -0
  118. package/dist/app/lib/views/defineView.d.ts.map +1 -0
  119. package/dist/app/lib/views/defineView.js +3 -0
  120. package/dist/app/lib/views/index.d.ts +2 -0
  121. package/dist/app/lib/views/index.d.ts.map +1 -0
  122. package/dist/app/lib/views/index.js +1 -0
  123. package/dist/app/server/index.d.ts +6 -0
  124. package/dist/app/server/index.d.ts.map +1 -0
  125. package/dist/app/server/index.js +5 -0
  126. package/dist/app/server/proxy-wp-admin.d.ts +3 -0
  127. package/dist/app/server/proxy-wp-admin.d.ts.map +1 -0
  128. package/dist/app/server/proxy-wp-admin.js +138 -0
  129. package/dist/app/server/render-ai-page.d.ts +13 -0
  130. package/dist/app/server/render-ai-page.d.ts.map +1 -0
  131. package/dist/app/server/render-ai-page.js +102 -0
  132. package/dist/app/server/render-ssr-page.d.ts +32 -0
  133. package/dist/app/server/render-ssr-page.d.ts.map +1 -0
  134. package/dist/app/server/render-ssr-page.js +253 -0
  135. package/dist/app/server/rpc.d.ts +33 -0
  136. package/dist/app/server/rpc.d.ts.map +1 -0
  137. package/dist/app/server/rpc.js +18 -0
  138. package/dist/app/server/server-context.d.ts +83 -0
  139. package/dist/app/server/server-context.d.ts.map +1 -0
  140. package/dist/app/server/server-context.js +480 -0
  141. package/dist/app/server/server-custom-config.d.ts +3 -0
  142. package/dist/app/server/server-custom-config.d.ts.map +1 -0
  143. package/dist/app/server/server-custom-config.js +1 -0
  144. package/dist/app/server/utils/content-security.d.ts +26 -0
  145. package/dist/app/server/utils/content-security.d.ts.map +1 -0
  146. package/dist/app/server/utils/content-security.js +124 -0
  147. package/dist/app/server/utils/headers.d.ts +6 -0
  148. package/dist/app/server/utils/headers.d.ts.map +1 -0
  149. package/dist/app/server/utils/headers.js +28 -0
  150. package/dist/app/server/utils/replace-host.d.ts +11 -0
  151. package/dist/app/server/utils/replace-host.d.ts.map +1 -0
  152. package/dist/app/server/utils/replace-host.js +36 -0
  153. package/dist/app/server/utils/swr-cache.d.ts +5 -0
  154. package/dist/app/server/utils/swr-cache.d.ts.map +1 -0
  155. package/dist/app/server/utils/swr-cache.js +31 -0
  156. package/dist/app/utils/hydration-debugger.d.ts +14 -0
  157. package/dist/app/utils/hydration-debugger.d.ts.map +1 -0
  158. package/dist/app/utils/hydration-debugger.js +11 -0
  159. package/dist/app/utils/wp.d.ts +27 -0
  160. package/dist/app/utils/wp.d.ts.map +1 -0
  161. package/dist/app/utils/wp.js +1 -0
  162. package/dist/node/cli/version.d.ts +1 -1
  163. package/dist/node/cli/version.js +1 -1
  164. package/package.json +2 -3
@@ -0,0 +1,480 @@
1
+ import { parseURL, stringifyParsedURL, withQuery, withTrailingSlash } from "ufo";
2
+ import { getCookie, getHeader } from "vinxi/http";
3
+ import { fetchWP } from "../../node/utils/fetch-wp.js";
4
+ import { filterHeader } from "./utils/headers.js";
5
+ import { createUrlReplacer } from "./utils/replace-host.js";
6
+ import { pageCache, queryCache, swr } from "./utils/swr-cache.js";
7
+ import { QueryMonitor } from "../utils/query-monitor.js";
8
+ import chalk from "chalk";
9
+ import { inspect } from "node:util";
10
+ const PROXY_RESPONSE_HEADERS = ["content-type", "set-cookie", /^x-/, "cache-control", /woocommerce/, "location"];
11
+ const PROXY_REQUEST_HEADERS = [
12
+ "content-type",
13
+ "accept",
14
+ "accept-encoding",
15
+ "accept-language",
16
+ "origin",
17
+ "referer",
18
+ "user-agent",
19
+ "authorization",
20
+ "woocommerce-session",
21
+ ];
22
+ const VARIES_HEADERS = ["Authorization", "woocommerce-session"];
23
+ let runtime;
24
+ export class ServerContext {
25
+ dev;
26
+ origin;
27
+ _urlReplacer;
28
+ rpcBases = [];
29
+ config;
30
+ cacheConfig;
31
+ static main;
32
+ constructor(conf) {
33
+ this.dev = conf.dev;
34
+ this.origin = conf.origin;
35
+ this.rpcBases = conf.rpcBases ?? [];
36
+ this.config = conf.config;
37
+ this.cacheConfig = conf.cacheConfig;
38
+ if (conf.replaceUrls) {
39
+ this._urlReplacer = createUrlReplacer(conf.replaceUrls);
40
+ }
41
+ ServerContext.main = this;
42
+ }
43
+ replaceUrls(text, origin) {
44
+ if (this._urlReplacer) {
45
+ return this._urlReplacer(text, origin);
46
+ }
47
+ return text;
48
+ }
49
+ get runtime() {
50
+ return runtime;
51
+ }
52
+ static setRuntime(rt) {
53
+ runtime = rt;
54
+ }
55
+ getOriginUrl(url) {
56
+ const parsed = parseURL(url);
57
+ const parsedOrigin = parseURL(this.origin);
58
+ parsed.host = parsedOrigin.host;
59
+ parsed.protocol = parsedOrigin.protocol;
60
+ return stringifyParsedURL(parsed);
61
+ }
62
+ async fetchOrigin(url, opts) {
63
+ url = this.getOriginUrl(url);
64
+ const fetchOps = { ...opts };
65
+ delete fetchOps.replaceUrls;
66
+ delete fetchOps.newOrigin;
67
+ const response = await fetchWP(url, {
68
+ ...fetchOps,
69
+ });
70
+ if (!response.ok) {
71
+ return response;
72
+ }
73
+ const headers = {};
74
+ response.headers.forEach((value, key) => {
75
+ if (filterHeader(key, PROXY_RESPONSE_HEADERS)) {
76
+ headers[key] = value;
77
+ }
78
+ });
79
+ let text = await response.text();
80
+ if (opts?.replaceUrls) {
81
+ text = this.replaceUrls(text, opts.newOrigin);
82
+ }
83
+ return new Response(text, {
84
+ status: response.status,
85
+ statusText: response.statusText,
86
+ headers,
87
+ });
88
+ }
89
+ debugLogQueryMonitor(kind, uri, monitor) {
90
+ if (!QueryMonitor.hasLogEntries(monitor))
91
+ return;
92
+ let indentLevel = 2;
93
+ const finalOutput = [];
94
+ let label = "";
95
+ if (kind === "props") {
96
+ label = "While fetching props for route '" + uri + "'";
97
+ }
98
+ else if (kind === "query") {
99
+ label = "While querying " + uri + " via REST API";
100
+ }
101
+ else if (kind === "mutation") {
102
+ label = "While mutating " + uri + " via REST API";
103
+ }
104
+ else if (kind === "app") {
105
+ label = "While fetching app data";
106
+ }
107
+ finalOutput.push(chalk.whiteBright("➜ " + label));
108
+ function printEntry(entry) {
109
+ finalOutput.push(indent(indentLevel, chalk.whiteBright("➜ " + entry.file) + " " + chalk.gray(entry.label ? `(${entry.label})` : "")));
110
+ indentLevel += 2;
111
+ if (entry.log && entry.log.length) {
112
+ for (let item of entry.log) {
113
+ let output = "";
114
+ let prefix = "";
115
+ let message = item.message;
116
+ let stack = [];
117
+ if (item.type === "php_error") {
118
+ prefix = chalk.red("PHP Error:");
119
+ }
120
+ else if (item.type === "php_warning") {
121
+ prefix = chalk.yellow("PHP Warning:");
122
+ }
123
+ else if (item.type === "php_notice") {
124
+ prefix = chalk.yellow("PHP Notice:");
125
+ }
126
+ else if (item.type === "GRAPHQL_DEBUG") {
127
+ prefix = chalk.cyan("debug:");
128
+ }
129
+ else if (item.type === "error" && item.extensions?.category === "user") {
130
+ prefix = chalk.red("UserError:");
131
+ }
132
+ else if (item.type === "error") {
133
+ prefix = chalk.red("Error:");
134
+ }
135
+ else if (item.type === "warn") {
136
+ prefix = chalk.yellow("Warning:");
137
+ }
138
+ else {
139
+ prefix = chalk.gray((item.type || "Log") + ":");
140
+ }
141
+ if (Array.isArray(message)) {
142
+ message = message
143
+ .map((part) => {
144
+ if (typeof part !== "string") {
145
+ return inspect(part, { depth: 4, colors: true });
146
+ }
147
+ return part;
148
+ })
149
+ .join(" ");
150
+ }
151
+ else if (typeof message !== "string") {
152
+ message = inspect(message, { depth: 4, colors: true });
153
+ }
154
+ if (item.debugMessage) {
155
+ message += "\n" + chalk.gray(item.debugMessage);
156
+ }
157
+ output += prefix + " " + message;
158
+ if (item.path) {
159
+ stack.push(chalk.gray(" at path " + item.path.join(".")));
160
+ }
161
+ if (item.file) {
162
+ stack.push(chalk.gray(`at ${chalk.white(item.file)} line ${item.line || "??"}`));
163
+ }
164
+ if (item.trace?.length) {
165
+ stack.push(item.trace
166
+ .slice(0, 4)
167
+ .map((line) => chalk.gray(" - " + line.call + " line " + line.line + " in " + line.file))
168
+ .join("\n"));
169
+ }
170
+ if (stack.length > 0) {
171
+ output += indent(2, "\n" + stack.join("\n"));
172
+ }
173
+ finalOutput.push(indent(indentLevel, "➜ " + output));
174
+ }
175
+ }
176
+ for (let child of entry.children ?? []) {
177
+ printEntry(child);
178
+ }
179
+ indentLevel -= 2;
180
+ }
181
+ for (let entry of monitor) {
182
+ printEntry(entry);
183
+ }
184
+ console.log(finalOutput.join("\n"));
185
+ }
186
+ async fetchRouteData(req) {
187
+ /**
188
+ * Calculcate the cache key.
189
+ * For route data, the cache key is the pathname.
190
+ * TODO: Potential support for Vercel draft mode.
191
+ */
192
+ let cacheKey = "fetchRouteData:" + withTrailingSlash(req.pathname.toLowerCase());
193
+ const result = await swr({
194
+ key: cacheKey,
195
+ cache: pageCache,
196
+ forceFresh: this.dev || req.bypass,
197
+ staleWhileRevalidate: 10000,
198
+ getFreshValue: async (ctx) => {
199
+ const fetchUrl = withQuery(withTrailingSlash(req.pathname), {
200
+ _props: "1",
201
+ _ssr: "1",
202
+ _debug: this.dev ? "1" : undefined,
203
+ });
204
+ const result = await this.fetchOrigin(fetchUrl, {
205
+ cache: "no-cache",
206
+ replaceUrls: true,
207
+ newOrigin: req.newOrigin,
208
+ headers: {
209
+ "Content-Type": "application/json",
210
+ Accept: "application/json",
211
+ },
212
+ redirect: "manual",
213
+ });
214
+ const preferredCacheDuration = parseInt(result.headers.get("x-ed-cache-duration") ?? "");
215
+ if (this.cacheConfig.serverless.isr) {
216
+ ctx.metadata.ttl = 5000;
217
+ }
218
+ else if (isFinite(preferredCacheDuration)) {
219
+ ctx.metadata.ttl = preferredCacheDuration * 1000;
220
+ }
221
+ let resultStatus = result.status;
222
+ let resultHeaders = new Headers(result.headers);
223
+ let resultData = {};
224
+ // Special case for redirects
225
+ if (result.headers.has("location")) {
226
+ let location = result.headers.get("location");
227
+ let status = result.status;
228
+ if (this.replaceUrls) {
229
+ location = this.replaceUrls(location);
230
+ }
231
+ return {
232
+ status: 200,
233
+ headers: new Headers({
234
+ "Content-Type": "application/json",
235
+ }),
236
+ data: JSON.stringify({ redirect: location, status: status }),
237
+ };
238
+ }
239
+ try {
240
+ resultData = await result.json();
241
+ }
242
+ catch (err) {
243
+ console.error(`Invalid JSON response from '${fetchUrl}'. An error page will be displayed.`);
244
+ ctx.metadata.ttl = 0;
245
+ return {
246
+ status: 500,
247
+ headers: resultHeaders,
248
+ data: JSON.stringify({
249
+ view: "_error",
250
+ viewData: {
251
+ data: {
252
+ statusCode: 500,
253
+ title: "Internal Server Error",
254
+ userMessage: "An internal server error occurred.",
255
+ report: {
256
+ details: "A JSON parsing error occurred while fetching route data.",
257
+ message: err.message,
258
+ },
259
+ },
260
+ },
261
+ }),
262
+ };
263
+ }
264
+ if (resultData && typeof resultData === "object") {
265
+ resultData.__generated = new Date().toISOString();
266
+ }
267
+ if (resultData.queryMonitor) {
268
+ this.debugLogQueryMonitor("props", req.pathname, resultData.queryMonitor);
269
+ }
270
+ // if (isFinite(preferredCacheDuration)) {
271
+ // const maxAge = isFinite(preferredCacheDuration) ? preferredCacheDuration * 1000 : undefined
272
+ // resultHeaders.set("Cache-Control", `max-age=0, s-maxage=${maxAge}, stale-while-revalidate`)
273
+ // }
274
+ resultHeaders.set("X-Ed-Fetched-At", new Date().toUTCString());
275
+ return {
276
+ status: resultStatus,
277
+ headers: resultHeaders,
278
+ data: JSON.stringify(resultData),
279
+ };
280
+ },
281
+ });
282
+ if (this.cacheConfig.serverless.isr) {
283
+ result.headers.delete("cache-control");
284
+ }
285
+ return new Response(result.data, {
286
+ status: result.status,
287
+ headers: result.headers,
288
+ });
289
+ }
290
+ async fetchAppData(args) {
291
+ const data = await swr({
292
+ key: "fetchAppData",
293
+ cache: pageCache,
294
+ forceFresh: this.dev || args.bypass,
295
+ staleWhileRevalidate: 10000,
296
+ getFreshValue: async (ctx) => {
297
+ const response = await this.fetchOrigin("/_appdata", {
298
+ cache: "no-cache",
299
+ replaceUrls: true,
300
+ newOrigin: args.newOrigin,
301
+ headers: {
302
+ "Content-Type": "application/json",
303
+ Accept: "application/json",
304
+ },
305
+ });
306
+ const result = await response.json();
307
+ const preferredCacheDuration = parseInt(response.headers.get("x-ed-cache-duration") ?? "");
308
+ if (isFinite(preferredCacheDuration)) {
309
+ ctx.metadata.ttl = preferredCacheDuration * 1000;
310
+ }
311
+ // In ISR mode, set a super short TTL to avoid caching, but preventing constant revalidation
312
+ if (this.cacheConfig.serverless.isr) {
313
+ ctx.metadata.ttl = 5000;
314
+ }
315
+ if (result.queryMonitor) {
316
+ this.debugLogQueryMonitor("app", "", result.queryMonitor);
317
+ }
318
+ result.__generated = new Date().toISOString();
319
+ return result;
320
+ },
321
+ });
322
+ return data;
323
+ }
324
+ extractRequestHeaders(req) {
325
+ const headers = {};
326
+ if (req) {
327
+ for (let key of PROXY_REQUEST_HEADERS) {
328
+ if (req[key]) {
329
+ headers[key] = req[key];
330
+ }
331
+ }
332
+ }
333
+ return headers;
334
+ }
335
+ async fetchNamedQuery(req) {
336
+ const url = `/wp-json/ed/v1/query/${req.name.replace(/^\//, "")}?params=${encodeURIComponent(JSON.stringify(req.params))}`;
337
+ const key = `fetchNamedQuery:${req.name}:${JSON.stringify(req.params)}`;
338
+ const fetch = async () => {
339
+ const result = await this.fetchOrigin(url, {
340
+ cache: "no-cache",
341
+ replaceUrls: true,
342
+ headers: {
343
+ ...this.extractRequestHeaders(req.headers),
344
+ "Content-Type": "application/json",
345
+ Accept: "application/json",
346
+ },
347
+ });
348
+ const preferredCacheDuration = parseInt(result.headers.get("x-ed-cache-duration") ?? "");
349
+ let resultStatus = result.status;
350
+ let resultHeaders = result.headers;
351
+ let resultData = await result.json();
352
+ if (resultData && typeof resultData === "object") {
353
+ resultData.__generated = new Date().toISOString();
354
+ }
355
+ resultHeaders.set("X-Ed-Rendered-At", new Date().toUTCString());
356
+ if (resultData.queryMonitor) {
357
+ this.debugLogQueryMonitor("query", req.name, resultData.queryMonitor);
358
+ }
359
+ return {
360
+ status: resultStatus,
361
+ headers: resultHeaders,
362
+ data: JSON.stringify(resultData),
363
+ cacheTime: isFinite(preferredCacheDuration) ? preferredCacheDuration * 1000 : undefined,
364
+ };
365
+ };
366
+ // If headers like 'Authorization' are set, then we shouldn't cache.
367
+ const hasVariedHeaders = VARIES_HEADERS.some((key) => !!req.headers[key]);
368
+ // Get the result, either from cache or by fetching.
369
+ const result = hasVariedHeaders
370
+ ? await fetch()
371
+ : await swr({
372
+ key,
373
+ cache: queryCache,
374
+ forceFresh: this.dev || req.bypass,
375
+ staleWhileRevalidate: 10000,
376
+ getFreshValue: async (ctx) => {
377
+ const result = await fetch();
378
+ ctx.metadata.ttl = result.cacheTime;
379
+ if (this.cacheConfig.serverless.isr) {
380
+ ctx.metadata.ttl = 5000;
381
+ }
382
+ return result;
383
+ },
384
+ });
385
+ if (this.cacheConfig.serverless.isr) {
386
+ result.headers.delete("cache-control");
387
+ }
388
+ return new Response(result.data, {
389
+ status: result.status,
390
+ headers: result.headers,
391
+ });
392
+ }
393
+ async fetchMutation(req) {
394
+ const url = `/wp-json/ed/v1/mutation/${req.name.replace(/^\//, "")}`;
395
+ const response = await this.fetchOrigin(url, {
396
+ method: "POST",
397
+ cache: "no-cache",
398
+ replaceUrls: true,
399
+ headers: {
400
+ ...this.extractRequestHeaders(req.headers),
401
+ "Content-Type": "application/json",
402
+ Accept: "application/json",
403
+ },
404
+ body: JSON.stringify(req.body),
405
+ });
406
+ return new Response(response.body, {
407
+ status: response.status,
408
+ statusText: response.statusText,
409
+ headers: new Headers({
410
+ "Content-Type": "application/json",
411
+ // Do not cache mutation responses
412
+ "Cache-Control": "max-age=0, max-s-age=0",
413
+ "X-Ed-Rendered-At": new Date().toUTCString(),
414
+ }),
415
+ });
416
+ }
417
+ get allowedCorsOrigins() {
418
+ let result = [];
419
+ if (this.config.serverless.endpoints) {
420
+ result.push(...Object.keys(this.config.serverless.endpoints));
421
+ result.push(...Object.values(this.config.serverless.endpoints));
422
+ result = result.filter((origin) => origin !== "*");
423
+ }
424
+ if (this.config.serverless.cors?.origins) {
425
+ result.push(...this.config.serverless.cors.origins.map((origin) => origin.replace(/(https?:\/\/|\/$)/, "")));
426
+ }
427
+ return result;
428
+ }
429
+ shouldBypass(event) {
430
+ const bypassToken = process.env.VERCEL_BYPASS_TOKEN;
431
+ if (!bypassToken)
432
+ return false;
433
+ const cookieName = "__prerender_bypass";
434
+ if (getCookie(event, cookieName) === bypassToken) {
435
+ return true;
436
+ }
437
+ if (getHeader(event, "x-prerender-revalidate") === bypassToken) {
438
+ return true;
439
+ }
440
+ return false;
441
+ }
442
+ getCorsOrigin(originHeader) {
443
+ const parsed = parseURL(originHeader);
444
+ if (this.allowedCorsOrigins.includes(parsed.host)) {
445
+ return originHeader;
446
+ }
447
+ if (this.allowedCorsOrigins.includes("*")) {
448
+ return "*";
449
+ }
450
+ }
451
+ getCorsHeaders(origin) {
452
+ if (!origin)
453
+ return {};
454
+ const allowedOrigin = this.getCorsOrigin(origin);
455
+ if (allowedOrigin) {
456
+ return {
457
+ "Access-Control-Allow-Methods": "OPTIONS,GET,HEAD,PUT,PATCH,POST,DELETE",
458
+ "Access-Control-Allow-Origin": allowedOrigin,
459
+ "Access-Control-Allow-Credentials": "true",
460
+ "Access-Control-Allow-Headers": "*",
461
+ "Access-Control-Expose-Headers": "*",
462
+ };
463
+ }
464
+ return {};
465
+ }
466
+ }
467
+ function indent(count, str) {
468
+ const indent = " ".repeat(count);
469
+ return str
470
+ .split("\n")
471
+ .map((line) => indent + line)
472
+ .join("\n");
473
+ }
474
+ function indentAllButFirst(count, str) {
475
+ const indent = " ".repeat(count);
476
+ return str
477
+ .split("\n")
478
+ .map((line, i) => (i === 0 ? line : indent + line))
479
+ .join("\n");
480
+ }
@@ -0,0 +1,3 @@
1
+ export type ServerConfig = {};
2
+ export declare function defineServerConfig(): void;
3
+ //# sourceMappingURL=server-custom-config.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server-custom-config.d.ts","sourceRoot":"","sources":["../../../src/app/server/server-custom-config.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,YAAY,GAAG,EAAE,CAAA;AAE7B,wBAAgB,kBAAkB,SAAK"}
@@ -0,0 +1 @@
1
+ export function defineServerConfig() { }
@@ -0,0 +1,26 @@
1
+ import type { EDConfig } from "../../../node/project/config";
2
+ import { RouteMetaTag, TrackerTags } from "../../lib/routing";
3
+ declare const CSP_KEYS: readonly ["childSrc", "connectSrc", "defaultSrc", "fencedFrameSrc", "fontSrc", "frameSrc", "imgSrc", "manifestSrc", "mediaSrc", "objectSrc", "scriptSrc", "scriptSrcElem", "scriptSrcAttr", "styleSrc", "styleSrcElem", "styleSrcAttr", "workerSrc", "baseUri", "formAction", "frameAncestors", "reportTo", "requireTrustedTypesFor", "trustedTypes", "upgradeInsecureRequests"];
4
+ export type CSPKey = (typeof CSP_KEYS)[number];
5
+ export type CSPParams = Record<CSPKey, Set<string>>;
6
+ export type ContentSecurityPolicyRequestContext = {
7
+ url: string;
8
+ type: "page";
9
+ tags: RouteMetaTag[];
10
+ };
11
+ export declare class SecureHeaderBuilder {
12
+ protected csp: CSPParams;
13
+ protected headers: Headers;
14
+ private cspEnabled;
15
+ private autodetectCspOrigins;
16
+ private useNonce;
17
+ private commonCspOrigins;
18
+ readonly nonce: string | undefined;
19
+ constructor(config: EDConfig);
20
+ addTrackingTags(tags: TrackerTags): TrackerTags;
21
+ addMetaTags(tags: RouteMetaTag[]): RouteMetaTag[];
22
+ getHeaders(): Headers;
23
+ getCSPHeaderValue(): string | undefined;
24
+ }
25
+ export {};
26
+ //# sourceMappingURL=content-security.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"content-security.d.ts","sourceRoot":"","sources":["../../../../src/app/server/utils/content-security.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,QAAQ,EAAE,MAAM,8BAA8B,CAAA;AAC5D,OAAO,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAA;AAG7D,QAAA,MAAM,QAAQ,kXAyBJ,CAAA;AAEV,MAAM,MAAM,MAAM,GAAG,CAAC,OAAO,QAAQ,CAAC,CAAC,MAAM,CAAC,CAAA;AAE9C,MAAM,MAAM,SAAS,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,MAAM,CAAC,CAAC,CAAA;AAEnD,MAAM,MAAM,mCAAmC,GAAG;IAChD,GAAG,EAAE,MAAM,CAAA;IACX,IAAI,EAAE,MAAM,CAAA;IACZ,IAAI,EAAE,YAAY,EAAE,CAAA;CACrB,CAAA;AAED,qBAAa,mBAAmB;IAC9B,SAAS,CAAC,GAAG,EAAE,SAAS,CAAA;IACxB,SAAS,CAAC,OAAO,EAAE,OAAO,CAAgB;IAE1C,OAAO,CAAC,UAAU,CAAQ;IAC1B,OAAO,CAAC,oBAAoB,CAAO;IACnC,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,gBAAgB,CAAe;IAEvC,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,SAAS,CAAA;gBAEtB,MAAM,EAAE,QAAQ;IAgC5B,eAAe,CAAC,IAAI,EAAE,WAAW,GAAG,WAAW;IAkB/C,WAAW,CAAC,IAAI,EAAE,YAAY,EAAE;IAkBhC,UAAU,IAAI,OAAO;IAWrB,iBAAiB,IAAI,MAAM,GAAG,SAAS;CAexC"}
@@ -0,0 +1,124 @@
1
+ import buildCsp from "content-security-policy-builder";
2
+ const CSP_KEYS = [
3
+ "childSrc",
4
+ "connectSrc",
5
+ "defaultSrc",
6
+ "fencedFrameSrc",
7
+ "fontSrc",
8
+ "frameSrc",
9
+ "imgSrc",
10
+ "manifestSrc",
11
+ "mediaSrc",
12
+ "objectSrc",
13
+ "scriptSrc",
14
+ "scriptSrcElem",
15
+ "scriptSrcAttr",
16
+ "styleSrc",
17
+ "styleSrcElem",
18
+ "styleSrcAttr",
19
+ "workerSrc",
20
+ "baseUri",
21
+ "formAction",
22
+ "frameAncestors",
23
+ "reportTo",
24
+ "requireTrustedTypesFor",
25
+ "trustedTypes",
26
+ "upgradeInsecureRequests",
27
+ ];
28
+ export class SecureHeaderBuilder {
29
+ csp;
30
+ headers = new Headers();
31
+ cspEnabled = false;
32
+ autodetectCspOrigins = true;
33
+ useNonce = false;
34
+ commonCspOrigins = [];
35
+ nonce;
36
+ constructor(config) {
37
+ this.cspEnabled = config.serverless.csp.enabled;
38
+ this.autodetectCspOrigins = config.serverless.csp.autoDetect;
39
+ this.useNonce = config.serverless.csp.nonce;
40
+ this.commonCspOrigins = config.serverless.csp.commonOrigins ?? [];
41
+ if (this.useNonce) {
42
+ this.nonce = crypto.randomUUID();
43
+ }
44
+ // Default CSP header parameters
45
+ this.csp = {};
46
+ for (let key of CSP_KEYS) {
47
+ const defaults = [];
48
+ if (key.match(/Src$/i)) {
49
+ defaults.push("'self'");
50
+ if (this.commonCspOrigins.length) {
51
+ defaults.push(...this.commonCspOrigins);
52
+ }
53
+ if (config.serverless.csp.values) {
54
+ const value = config.serverless.csp.values[key];
55
+ if (value) {
56
+ defaults.push(...value);
57
+ }
58
+ }
59
+ if (this.useNonce && !defaults.includes("'unsafe-inline'")) {
60
+ defaults.push(`'nonce-${this.nonce}'`);
61
+ }
62
+ }
63
+ this.csp[key] = new Set(defaults);
64
+ }
65
+ }
66
+ addTrackingTags(tags) {
67
+ if (!this.autodetectCspOrigins || !this.cspEnabled)
68
+ return tags;
69
+ const handle = (value) => {
70
+ if (value) {
71
+ return value.replaceAll(/<(script|style)/g, (tag) => {
72
+ return tag + ` nonce="${this.nonce}"`;
73
+ });
74
+ }
75
+ };
76
+ return {
77
+ head: handle(tags.head),
78
+ body: handle(tags.body),
79
+ footer: handle(tags.footer),
80
+ };
81
+ }
82
+ addMetaTags(tags) {
83
+ if (!this.autodetectCspOrigins || !this.cspEnabled)
84
+ return tags;
85
+ return tags.map((tag) => {
86
+ if (this.nonce) {
87
+ if (tag.tagName === "script" || tag.tagName === "style") {
88
+ return {
89
+ ...tag,
90
+ attributes: {
91
+ ...tag.attributes,
92
+ nonce: this.nonce,
93
+ },
94
+ };
95
+ }
96
+ }
97
+ return tag;
98
+ });
99
+ }
100
+ getHeaders() {
101
+ const result = new Headers(this.headers);
102
+ const cspHeaderValue = this.getCSPHeaderValue();
103
+ if (cspHeaderValue) {
104
+ result.set("Content-Security-Policy", cspHeaderValue);
105
+ }
106
+ return result;
107
+ }
108
+ getCSPHeaderValue() {
109
+ if (!this.cspEnabled)
110
+ return undefined;
111
+ const directives = [];
112
+ for (let key of CSP_KEYS) {
113
+ if (this.csp[key].size > 0) {
114
+ directives.push([key, Array.from(this.csp[key])]);
115
+ }
116
+ }
117
+ if (directives.length) {
118
+ return buildCsp({
119
+ directives: Object.fromEntries(directives),
120
+ });
121
+ }
122
+ return undefined;
123
+ }
124
+ }
@@ -0,0 +1,6 @@
1
+ export declare function filterHeader(key: string, allowed: (string | RegExp)[]): boolean;
2
+ export declare const BRANDED_HEADERS: {
3
+ "X-Powered-By": string;
4
+ };
5
+ export declare function extractHeaders(rawHeaders: Headers): Record<string, string>;
6
+ //# sourceMappingURL=headers.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"headers.d.ts","sourceRoot":"","sources":["../../../../src/app/server/utils/headers.ts"],"names":[],"mappings":"AAAA,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC,MAAM,GAAG,MAAM,CAAC,EAAE,WAOrE;AAED,eAAO,MAAM,eAAe;;CAE3B,CAAA;AAYD,wBAAgB,cAAc,CAAC,UAAU,EAAE,OAAO,0BAOjD"}
@@ -0,0 +1,28 @@
1
+ export function filterHeader(key, allowed) {
2
+ return allowed.some((allowedKey) => {
3
+ if (allowedKey instanceof RegExp) {
4
+ return allowedKey.test(key);
5
+ }
6
+ return allowedKey === key;
7
+ });
8
+ }
9
+ export const BRANDED_HEADERS = {
10
+ "X-Powered-By": "ed.studio",
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
+ }