@patchstack/connect 0.3.14 → 0.3.16

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.js CHANGED
@@ -899,6 +899,64 @@ var RuleEngine = class {
899
899
  }
900
900
  };
901
901
 
902
+ // src/protect/engine/pulse-client.js
903
+ var DEFAULT_BASE_URL2 = "https://api.patchstack.com/monitor/pulse";
904
+ var DEFAULT_CACHE_TTL2 = 3e5;
905
+ var PulseRuleClient = class {
906
+ #siteUuid;
907
+ #baseUrl;
908
+ #cacheTtl;
909
+ #cache = null;
910
+ #cacheTime = null;
911
+ constructor({ siteUuid, baseUrl, cacheTtl } = {}) {
912
+ this.#siteUuid = siteUuid ?? process.env.PATCHSTACK_SITE_UUID;
913
+ this.#baseUrl = baseUrl ?? process.env.PATCHSTACK_PULSE_RULES_URL ?? DEFAULT_BASE_URL2;
914
+ this.#cacheTtl = cacheTtl ?? DEFAULT_CACHE_TTL2;
915
+ if (!this.#siteUuid) {
916
+ throw new Error("Patchstack site UUID is required. Pass { siteUuid } or set PATCHSTACK_SITE_UUID.");
917
+ }
918
+ }
919
+ async getRules() {
920
+ const now = Date.now();
921
+ if (this.#cache && this.#cacheTime && now - this.#cacheTime < this.#cacheTtl) {
922
+ return this.#cache;
923
+ }
924
+ const url = `${this.#baseUrl}/rules/${encodeURIComponent(this.#siteUuid)}`;
925
+ try {
926
+ const response = await fetch(url, {
927
+ method: "GET",
928
+ headers: { Accept: "application/json" },
929
+ signal: AbortSignal.timeout(3e4)
930
+ });
931
+ if (!response.ok) {
932
+ return { success: false, error: `API returned ${response.status}`, firewall: [], whitelists: [], whitelist_keys: {} };
933
+ }
934
+ const data = await response.json();
935
+ const result = {
936
+ success: true,
937
+ firewall: Array.isArray(data.firewall) ? data.firewall : [],
938
+ whitelists: Array.isArray(data.whitelists) ? data.whitelists : [],
939
+ whitelist_keys: data.whitelist_keys ?? {}
940
+ };
941
+ this.#cache = result;
942
+ this.#cacheTime = now;
943
+ return result;
944
+ } catch (err) {
945
+ return {
946
+ success: false,
947
+ error: err.name === "TimeoutError" ? "Request timed out" : err.message,
948
+ firewall: [],
949
+ whitelists: [],
950
+ whitelist_keys: {}
951
+ };
952
+ }
953
+ }
954
+ clearCache() {
955
+ this.#cache = null;
956
+ this.#cacheTime = null;
957
+ }
958
+ };
959
+
902
960
  // src/protect/engine/fetch.js
903
961
  async function fromFetchRequest(request) {
904
962
  const url = new URL(request.url);
@@ -1521,8 +1579,25 @@ function leakResponse() {
1521
1579
  });
1522
1580
  }
1523
1581
  async function resolveRules(options) {
1524
- if (options.rules) {
1525
- return normalizeBundle(options.rules);
1582
+ if (options.siteUuid) {
1583
+ const client = new PulseRuleClient({ siteUuid: options.siteUuid, baseUrl: options.pulseRulesUrl });
1584
+ const res = await client.getRules();
1585
+ if (res.success) {
1586
+ const bundle = normalizeBundle(res);
1587
+ cacheWrite(options.cacheDir, bundle);
1588
+ return bundle;
1589
+ }
1590
+ const cached = cacheRead(options.cacheDir);
1591
+ if (cached) {
1592
+ options.onError?.(new Error(`pulse rule fetch failed (${res.error}); using cached bundle`));
1593
+ return normalizeBundle(cached);
1594
+ }
1595
+ if (options.rules) {
1596
+ options.onError?.(new Error(`pulse rule fetch failed (${res.error}); using bundled fallback`));
1597
+ return normalizeBundle(options.rules);
1598
+ }
1599
+ options.onError?.(new Error(`pulse rule fetch failed (${res.error}); no cache \u2014 running with no rules`));
1600
+ return emptyBundle();
1526
1601
  }
1527
1602
  if (options.token) {
1528
1603
  const client = new PatchstackRuleClient({ token: options.token, baseUrl: options.baseUrl });
@@ -1540,6 +1615,9 @@ async function resolveRules(options) {
1540
1615
  options.onError?.(new Error(`rule fetch failed (${res.error}); no cache \u2014 running with no rules`));
1541
1616
  return emptyBundle();
1542
1617
  }
1618
+ if (options.rules) {
1619
+ return normalizeBundle(options.rules);
1620
+ }
1543
1621
  return emptyBundle();
1544
1622
  }
1545
1623
  function normalizeBundle(b) {
@@ -1590,6 +1668,7 @@ function defaultOnDetect({ phase, mode, category, rule, message }) {
1590
1668
  }
1591
1669
  export {
1592
1670
  GUARD_PATH,
1671
+ PulseRuleClient,
1593
1672
  createProtection,
1594
1673
  createServerFnGuard,
1595
1674
  createSupabaseGuard