@patchstack/connect 0.3.21 → 0.3.22

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/protect.d.ts CHANGED
@@ -5,6 +5,8 @@ export interface RuleBundle {
5
5
  firewall: unknown[];
6
6
  whitelists: unknown[];
7
7
  whitelist_keys: Record<string, unknown>;
8
+ /** From the Pulse rules API when present (`block` = enforce, `dry-run` = detect only). */
9
+ enforcement?: "block" | "dry-run";
8
10
  }
9
11
 
10
12
  export type Phase = "request" | "response" | "egress";
@@ -33,7 +35,11 @@ export interface Protection {
33
35
  }
34
36
 
35
37
  export interface CreateProtectionOptions {
36
- /** Default "dry-run". The scaffolded guard sets "block". */
38
+ /**
39
+ * Fallback when the Pulse rules API does not send `enforcement`.
40
+ * Overridden by `PATCHSTACK_MODE` when set, otherwise by API `enforcement`.
41
+ * Default "dry-run". Scaffolded guards pass "block" when env is unset.
42
+ */
37
43
  mode?: "block" | "dry-run";
38
44
  /** Explicit rule bundle (used as the token-less fallback). */
39
45
  rules?: unknown;
package/dist/protect.js CHANGED
@@ -1032,7 +1032,8 @@ var PulseRuleClient = class {
1032
1032
  etag: response.headers?.get?.("etag") ?? null,
1033
1033
  firewall: data.firewall,
1034
1034
  whitelists: Array.isArray(data.whitelists) ? data.whitelists : [],
1035
- whitelist_keys: data.whitelist_keys ?? {}
1035
+ whitelist_keys: data.whitelist_keys ?? {},
1036
+ ...enforcementField(data)
1036
1037
  };
1037
1038
  this.#cache = result;
1038
1039
  this.#etag = result.etag;
@@ -1058,6 +1059,11 @@ var PulseRuleClient = class {
1058
1059
  this.#etag = null;
1059
1060
  }
1060
1061
  };
1062
+ function enforcementField(data) {
1063
+ if (!data || typeof data !== "object") return {};
1064
+ const v = data.enforcement ?? data.mode;
1065
+ return v === "block" || v === "dry-run" ? { enforcement: v } : {};
1066
+ }
1061
1067
 
1062
1068
  // src/protect/engine/fetch.js
1063
1069
  var MAX_BODY_BYTES = 1024 * 1024;
@@ -1785,10 +1791,12 @@ async function resolveRules(options, store) {
1785
1791
  return emptyBundle();
1786
1792
  }
1787
1793
  function normalizeBundle(b) {
1794
+ const enforcement = b?.enforcement ?? b?.mode;
1788
1795
  return {
1789
1796
  firewall: Array.isArray(b.firewall) ? b.firewall : [],
1790
1797
  whitelists: Array.isArray(b.whitelists) ? b.whitelists : [],
1791
- whitelist_keys: b.whitelist_keys ?? {}
1798
+ whitelist_keys: b.whitelist_keys ?? {},
1799
+ ...enforcement === "block" || enforcement === "dry-run" ? { enforcement } : {}
1792
1800
  };
1793
1801
  }
1794
1802
  function emptyBundle() {
@@ -1920,11 +1928,11 @@ function createServerFnGuard({ protection }) {
1920
1928
  };
1921
1929
  }
1922
1930
  async function createProtection(options = {}) {
1923
- const mode = options.mode === "block" ? "block" : "dry-run";
1924
1931
  const onError = options.onError;
1925
1932
  const onDetect = options.onDetect ?? defaultOnDetect;
1926
1933
  const store = makeStore(options);
1927
1934
  const bundle = await resolveRules(options, store);
1935
+ let mode = resolveMode(options, bundle);
1928
1936
  let requestRules;
1929
1937
  let responseRules;
1930
1938
  let egressRules;
@@ -2119,7 +2127,9 @@ async function createProtection(options = {}) {
2119
2127
  return mode === "block";
2120
2128
  };
2121
2129
  const protection = {
2122
- mode,
2130
+ get mode() {
2131
+ return mode;
2132
+ },
2123
2133
  get rules() {
2124
2134
  return { request: requestRules, response: responseRules, egress: egressRules };
2125
2135
  },
@@ -2247,7 +2257,7 @@ async function createProtection(options = {}) {
2247
2257
  let reporter = null;
2248
2258
  if (refreshable && options.siteUuid && options.reportManifest !== false && cwd) {
2249
2259
  try {
2250
- ({ reportManifest: reporter } = await import("./refresh-manifest-XBOGN446.js"));
2260
+ ({ reportManifest: reporter } = await import("./refresh-manifest-OW7WT5A6.js"));
2251
2261
  } catch (err) {
2252
2262
  onError?.(err);
2253
2263
  }
@@ -2260,7 +2270,9 @@ async function createProtection(options = {}) {
2260
2270
  onError?.(err);
2261
2271
  }
2262
2272
  }
2263
- applyBundle(await resolveRules(options, store));
2273
+ const next = await resolveRules(options, store);
2274
+ mode = resolveMode(options, next);
2275
+ applyBundle(next);
2264
2276
  };
2265
2277
  if (live) {
2266
2278
  protection.refresh = () => runRefreshTick();
@@ -2272,6 +2284,14 @@ async function createProtection(options = {}) {
2272
2284
  }
2273
2285
  return protection;
2274
2286
  }
2287
+ function resolveMode(options, bundle) {
2288
+ const env = typeof process !== "undefined" ? process.env?.PATCHSTACK_MODE : void 0;
2289
+ if (env === "block" || env === "dry-run") return env;
2290
+ if (bundle?.enforcement === "block" || bundle?.enforcement === "dry-run") return bundle.enforcement;
2291
+ if (options?.mode === "block") return "block";
2292
+ if (options?.mode === "dry-run") return "dry-run";
2293
+ return "dry-run";
2294
+ }
2275
2295
  function byPhase(rules, phase) {
2276
2296
  return (rules ?? []).filter((r) => (r.phase ?? "request") === phase);
2277
2297
  }