cwresdev 0.1.4 → 0.1.6

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cwresdev",
3
- "version": "0.1.4",
3
+ "version": "0.1.6",
4
4
  "description": "",
5
5
  "license": "MIT",
6
6
  "private": false,
package/src/proxy.js CHANGED
@@ -1,12 +1,49 @@
1
1
  const { Readable } = require("node:stream");
2
2
  const { injectLiveReload } = require("./injector");
3
3
 
4
+ let _stagingCookie = "";
5
+
6
+ async function acquireStagingCookie(proxyOrigin) {
7
+ try {
8
+ const res = await fetch(new URL("/contentEnvironment", proxyOrigin).toString(), {
9
+ method: "POST",
10
+ headers: { "Content-Type": "application/json" },
11
+ body: JSON.stringify({ contentEnvironment: "staging" }),
12
+ });
13
+
14
+ if (!res.ok) {
15
+ return "";
16
+ }
17
+
18
+ const cookies = res.headers.getSetCookie() || [];
19
+ const envCookie = cookies.find((c) => c.startsWith("contentEnvironment="));
20
+
21
+ if (envCookie) {
22
+ _stagingCookie = envCookie.split(";")[0];
23
+ }
24
+
25
+ return _stagingCookie;
26
+ } catch (error) {
27
+ return "";
28
+ }
29
+ }
30
+
31
+ function getStagingCookie() {
32
+ return _stagingCookie;
33
+ }
34
+
4
35
  function stripHopByHopHeaders(headers) {
5
36
  const nextHeaders = { ...headers };
6
37
  delete nextHeaders.host;
7
38
  delete nextHeaders.connection;
8
39
  delete nextHeaders["content-length"];
9
40
  delete nextHeaders["transfer-encoding"];
41
+ delete nextHeaders.referer;
42
+ delete nextHeaders.origin;
43
+ delete nextHeaders["sec-fetch-site"];
44
+ delete nextHeaders["sec-fetch-mode"];
45
+ delete nextHeaders["sec-fetch-dest"];
46
+ delete nextHeaders.cookie;
10
47
  return nextHeaders;
11
48
  }
12
49
 
@@ -46,11 +83,17 @@ async function readRequestBody(req) {
46
83
  return Buffer.concat(chunks);
47
84
  }
48
85
 
49
- async function proxyRequest({ req, res, target, injectHtml = false }) {
86
+ async function proxyRequest({ req, res, target, injectHtml = false, injectCookie = false }) {
50
87
  const body = await readRequestBody(req);
88
+ const outHeaders = stripHopByHopHeaders(req.headers);
89
+
90
+ if (injectCookie && _stagingCookie) {
91
+ outHeaders.cookie = _stagingCookie;
92
+ }
93
+
51
94
  const upstream = await fetch(target, {
52
95
  method: req.method,
53
- headers: stripHopByHopHeaders(req.headers),
96
+ headers: outHeaders,
54
97
  body,
55
98
  redirect: "manual",
56
99
  });
@@ -61,10 +104,17 @@ async function proxyRequest({ req, res, target, injectHtml = false }) {
61
104
  "content-encoding",
62
105
  "content-length",
63
106
  "transfer-encoding",
107
+ "set-cookie",
64
108
  ]);
65
109
 
66
110
  applyResponseHeaders(upstream.headers, res, omittedHeaders);
67
111
 
112
+ if (injectCookie) {
113
+ res.setHeader("Cache-Control", "no-cache, no-store, must-revalidate");
114
+ res.setHeader("Pragma", "no-cache");
115
+ res.setHeader("Expires", "0");
116
+ }
117
+
68
118
  if (req.method === "HEAD" || upstream.status === 204 || upstream.status === 304) {
69
119
  res.end();
70
120
  return;
@@ -86,6 +136,8 @@ async function proxyRequest({ req, res, target, injectHtml = false }) {
86
136
  }
87
137
 
88
138
  module.exports = {
139
+ acquireStagingCookie,
89
140
  buildTargetUrl,
141
+ getStagingCookie,
90
142
  proxyRequest,
91
143
  };
package/src/server.js CHANGED
@@ -8,7 +8,7 @@ const { WebSocketServer } = require("ws");
8
8
 
9
9
  const { CLIENT_SCRIPT_ROUTE, getClientScriptSource, injectLiveReload } = require("./injector");
10
10
  const { startPhpServer, stopPhpServer } = require("./php");
11
- const { buildTargetUrl, proxyRequest } = require("./proxy");
11
+ const { acquireStagingCookie, buildTargetUrl, proxyRequest } = require("./proxy");
12
12
 
13
13
  const HTML_EXTENSIONS = new Set([".htm", ".html", ".shtm", ".shtml"]);
14
14
  const MAX_SSI_INCLUDE_DEPTH = 16;
@@ -198,6 +198,10 @@ async function startDevServer(config) {
198
198
  }
199
199
 
200
200
  const logger = createLogger(config.quiet);
201
+
202
+ await acquireStagingCookie(config.proxyOrigin);
203
+ logger.info("[cwrespro] Staging cookie acquired for CDN proxy.");
204
+
201
205
  const packageRoot = path.resolve(__dirname, "..");
202
206
  const phpServer = await startPhpServer({
203
207
  packageRoot,
@@ -238,6 +242,7 @@ async function startDevServer(config) {
238
242
  req,
239
243
  res,
240
244
  target: buildTargetUrl(config.proxyOrigin, req),
245
+ injectCookie: true,
241
246
  });
242
247
  } catch (error) {
243
248
  next(error);
@@ -293,9 +298,51 @@ async function startDevServer(config) {
293
298
  });
294
299
 
295
300
  let reloadTimer = null;
301
+ const ignored = (config.watchIgnored || []).map((pattern) => {
302
+ if (typeof pattern === "function") return pattern;
303
+ if (pattern instanceof RegExp) return pattern;
304
+ if (typeof pattern !== "string") return () => false;
305
+
306
+ const normalized = pattern.replace(/\\/g, "/");
307
+
308
+ // **/segment/** → match paths containing /segment/
309
+ if (normalized.startsWith("**/") && normalized.endsWith("/**")) {
310
+ const segment = normalized.slice(3, -3);
311
+ return (filePath) => filePath.replace(/\\/g, "/").includes(`/${segment}/`);
312
+ }
313
+
314
+ if (normalized.startsWith("**/")) {
315
+ const tail = normalized.slice(3);
316
+
317
+ // **/*suffix → basename ends with suffix (e.g. **/*~)
318
+ if (tail.startsWith("*")) {
319
+ const suffix = tail.slice(1);
320
+ return (filePath) => path.basename(filePath).endsWith(suffix);
321
+ }
322
+
323
+ // **/prefix* → basename starts with prefix (e.g. **/~*)
324
+ if (tail.endsWith("*") && !tail.slice(0, -1).includes("*")) {
325
+ const prefix = tail.slice(0, -1);
326
+ return (filePath) => path.basename(filePath).startsWith(prefix);
327
+ }
328
+
329
+ // **/*.ext → match by extension (e.g. **/*.tmp)
330
+ if (tail.includes("*.")) {
331
+ const ext = tail.slice(tail.indexOf("*.") + 1);
332
+ return (filePath) => path.basename(filePath).endsWith(ext);
333
+ }
334
+
335
+ // **/name or **/dir/name → match end of path (e.g. **/Thumbs.db, **/data/.xml)
336
+ return (filePath) => filePath.replace(/\\/g, "/").endsWith(`/${tail}`);
337
+ }
338
+
339
+ // No glob metacharacters: exact match
340
+ return (filePath) => filePath.replace(/\\/g, "/") === normalized;
341
+ });
342
+
296
343
  const watcher = chokidar.watch(config.docRoot, {
297
344
  ignoreInitial: true,
298
- ignored: config.watchIgnored,
345
+ ignored,
299
346
  });
300
347
 
301
348
  watcher.on("all", (eventName, filePath) => {