zubbl-sdk 1.1.44 → 1.1.45

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.
@@ -4,6 +4,7 @@ export type ZubblConfig = {
4
4
  tenantId: string;
5
5
  appId: string;
6
6
  baseUrl?: string;
7
+ appBaseUrl?: string | null;
7
8
  injectWorkerHeaders?: boolean;
8
9
  workerSecret?: string | null;
9
10
  };
@@ -46,7 +47,24 @@ export declare function createZubblClient(cfg: ZubblConfig): {
46
47
  }) => Promise<{
47
48
  decision: string;
48
49
  status: number;
50
+ allowed: boolean;
51
+ blocked: boolean;
49
52
  data: any;
50
53
  }>;
54
+ testEndpoint: ({ external_user_id, endpoint, method, body, }: {
55
+ external_user_id: string;
56
+ endpoint: string;
57
+ method?: string;
58
+ body?: any;
59
+ }) => Promise<{
60
+ decision: string;
61
+ status: number;
62
+ allowed: boolean;
63
+ blocked: boolean;
64
+ endpoint: string;
65
+ method: string;
66
+ data: any;
67
+ }>;
68
+ createExpressTestHandler: () => (req: any, res: any) => Promise<any>;
51
69
  storage: import("./core/storage").IStorage;
52
70
  };
@@ -7,6 +7,7 @@ export interface ZubblConfig {
7
7
  tenantId: string | null;
8
8
  appId: string | null;
9
9
  baseUrl: string;
10
+ appBaseUrl?: string | null;
10
11
  injectWorkerHeaders?: boolean;
11
12
  workerSecret?: string | null;
12
13
  }
@@ -34,6 +34,7 @@ function createConfigStore(initial) {
34
34
  tenantId: null,
35
35
  appId: null,
36
36
  baseUrl: "https://api.zubbl.com/api",
37
+ appBaseUrl: null,
37
38
  injectWorkerHeaders: false,
38
39
  workerSecret: null,
39
40
  ...initial,
@@ -724,7 +725,101 @@ function createZubblClient(cfg) {
724
725
  headers,
725
726
  });
726
727
  const json = await resp.json().catch(() => ({}));
727
- return { decision: "allow", status: resp.status, data: json };
728
+ const decision = resp.status === 403 || resp.status === 429 ? "block" : resp.ok ? "allow" : "error";
729
+ return {
730
+ decision,
731
+ status: resp.status,
732
+ allowed: decision === "allow",
733
+ blocked: decision === "block",
734
+ data: json,
735
+ };
736
+ }
737
+ async function testEndpoint({ external_user_id, endpoint, method = "POST", body = {}, }) {
738
+ assertInitialized();
739
+ const config = store.get();
740
+ const base = config.appBaseUrl?.replace(/\/$/, "");
741
+ if (!base) {
742
+ throw new Error("[Zubbl SDK] appBaseUrl is required to run endpoint tests");
743
+ }
744
+ if (!endpoint || !endpoint.startsWith("/")) {
745
+ throw new Error("[Zubbl SDK] endpoint must start with /");
746
+ }
747
+ const headers = store.buildHeaders({
748
+ "X-External-User-Id": external_user_id,
749
+ "X-Zubbl-Test-Mode": "live",
750
+ });
751
+ const resp = await httpRequest(`${base}${endpoint}`, {
752
+ method: method.toUpperCase(),
753
+ headers,
754
+ body: ["GET", "HEAD"].includes(method.toUpperCase()) ? undefined : body,
755
+ });
756
+ const text = await resp.text().catch(() => "");
757
+ let data = text;
758
+ try {
759
+ data = text ? JSON.parse(text) : {};
760
+ }
761
+ catch { }
762
+ const decision = resp.status === 403 || resp.status === 429 ? "block" : resp.ok ? "allow" : "error";
763
+ return {
764
+ decision,
765
+ status: resp.status,
766
+ allowed: decision === "allow",
767
+ blocked: decision === "block",
768
+ endpoint,
769
+ method: method.toUpperCase(),
770
+ data,
771
+ };
772
+ }
773
+ function createExpressTestHandler() {
774
+ return async function zubblExpressTestHandler(req, res) {
775
+ try {
776
+ const endpoint = String(req.query?.endpoint || "").trim();
777
+ const method = String(req.query?.method || "POST").toUpperCase();
778
+ const html = String(req.query?.html || "").toLowerCase() === "true";
779
+ const external_user_id = String(req.query?.external_user_id ||
780
+ req.headers?.["x-external-user-id"] ||
781
+ "zubbl-test-user").trim();
782
+ const result = await testEndpoint({
783
+ external_user_id,
784
+ endpoint,
785
+ method,
786
+ body: {},
787
+ });
788
+ if (html) {
789
+ return res
790
+ .status(200)
791
+ .send(`<!doctype html>
792
+ <html>
793
+ <head>
794
+ <title>Zubbl live endpoint test</title>
795
+ <style>
796
+ body { font-family: system-ui, sans-serif; background: #0b1020; color: #fff; padding: 32px; }
797
+ pre { background: #111827; padding: 16px; border-radius: 12px; overflow: auto; }
798
+ .ok { color: #86efac; }
799
+ .block { color: #fca5a5; }
800
+ </style>
801
+ </head>
802
+ <body>
803
+ <h1>Zubbl live endpoint test</h1>
804
+ <p>Endpoint: <code>${result.method} ${result.endpoint}</code></p>
805
+ <p>Status: <strong>${result.status}</strong></p>
806
+ <p>Decision: <strong class="${result.blocked ? "block" : "ok"}">${result.decision}</strong></p>
807
+ <pre>${JSON.stringify(result, null, 2)}</pre>
808
+ </body>
809
+ </html>`);
810
+ }
811
+ return res.status(200).json(result);
812
+ }
813
+ catch (err) {
814
+ const payload = {
815
+ error: err?.message || "Zubbl test failed",
816
+ };
817
+ if (String(req.query?.html || "").toLowerCase() === "true") {
818
+ return res.status(500).send(`<h1>Zubbl test failed</h1><pre>${payload.error}</pre>`);
819
+ }
820
+ return res.status(500).json(payload);
821
+ }
822
+ };
728
823
  }
729
824
  // ---------------------------------------------------------
730
825
  // Public API
@@ -734,6 +829,8 @@ function createZubblClient(cfg) {
734
829
  identifyUser,
735
830
  getTiles,
736
831
  enforce,
832
+ testEndpoint,
833
+ createExpressTestHandler,
737
834
  storage,
738
835
  };
739
836
  }
@@ -1 +1 @@
1
- {"version":3,"file":"zubbl-sdk.cjs.js","sources":["../src/core/config.ts","../src/core/context.ts","../src/core/storage.ts","../src/core/geo.ts","../src/core/signing.ts","../src/utils/signing.ts","../src/core/http.ts","../src/features/identifyUser.ts","../src/features/getTiles.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["// src/core/config.ts\n// -----------------------------------------------------------\n// Universal environment detection + SDK configuration\n// -----------------------------------------------------------\n\nexport const isBrowser =\n typeof window !== \"undefined\" && typeof window.document !== \"undefined\";\n\nexport const isNode =\n typeof process !== \"undefined\" &&\n !!process.versions?.node &&\n !isBrowser;\n\nexport const isWorker =\n typeof self !== \"undefined\" &&\n typeof (self as any).importScripts === \"function\" &&\n !isNode;\n\n// -----------------------------------------------------------\n// Config store factory (no module-scoped state)\n// -----------------------------------------------------------\n\nexport interface ZubblConfig {\n apiKey: string | null;\n signingSecret: string | null; // ✅ used for HMAC signing (never sent over the wire)\n tenantId: string | null;\n appId: string | null;\n baseUrl: string;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n}\n\nfunction assertBrowserSafety(cfg: ZubblConfig) {\n if (isBrowser || isWorker) {\n const key = cfg.apiKey ?? \"\";\n const looksSecret = key.startsWith(\"sk_\") || key.length > 40;\n if (looksSecret) {\n throw new Error(\n \"[Zubbl SDK] Secret or server key detected in browser environment. \" +\n \"Use a public SDK key instead (prefix pk_).\"\n );\n }\n }\n}\n\n/**\n * Creates an isolated configuration store.\n * Each ZubblClient instance owns its own store.\n */\nexport function createConfigStore(initial?: Partial<ZubblConfig>) {\n let current: ZubblConfig = {\n apiKey: null,\n signingSecret: null,\n tenantId: null,\n appId: null,\n baseUrl: \"https://api.zubbl.com/api\",\n injectWorkerHeaders: false,\n workerSecret: null,\n ...initial,\n };\n\n function init(partial: Partial<ZubblConfig>) {\n current = { ...current, ...partial };\n assertBrowserSafety(current);\n }\n\n function get(): Readonly<ZubblConfig> {\n return current;\n }\n\n function buildHeaders(extra: Record<string, string> = {}): Record<string, string> {\n if (!current.tenantId || !current.appId) {\n throw new Error(\"[Zubbl SDK] Not initialized – call init() first.\");\n }\n\n const headers: Record<string, string> = {\n \"X-Tenant-Id\": current.tenantId,\n \"X-App-Id\": current.appId,\n \"Content-Type\": \"application/json\",\n ...extra,\n };\n\n if (current.apiKey) {\n headers.Authorization = `Bearer ${current.apiKey}`;\n }\n\n // ✅ Internal-only: used by httpRequest() to compute signature, then deleted before fetch\n if (current.signingSecret) {\n headers[\"X-Zubbl-Signing-Secret\"] = current.signingSecret;\n } else if (current.apiKey) {\n // If you're using API-key auth, you must also provide signingSecret for Worker-gated endpoints\n throw new Error(\"[Zubbl SDK] Missing signingSecret (required for signed requests)\");\n }\n\n return headers;\n }\n\n return { init, get, buildHeaders };\n}\n\n","// src/core/context.ts\n// -----------------------------------------------------------\n// Adaptive Context Engine — Geo + Stability Enrichment + Persistence\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types\n// -----------------------------------------------------------\ninterface ContextSample {\n path: string;\n method: string;\n ts: number;\n status: number;\n latency: number;\n}\n\ninterface AdaptiveState {\n routes: ContextSample[];\n geo: string;\n stability: number;\n lastGeoChange: number;\n}\n\nconst MAX_HISTORY = 100;\nconst CACHE_KEY = \"zubbl-stability\";\n\nlet state: AdaptiveState = loadStability() ?? {\n routes: [],\n geo: \"unknown\",\n stability: 1.0,\n lastGeoChange: Date.now(),\n};\n\n// -----------------------------------------------------------\n// 💾 Persistence Helpers\n// -----------------------------------------------------------\nfunction loadStability(): AdaptiveState | null {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(CACHE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (!parsed.geo || !parsed.stability) return null;\n return { ...parsed, routes: [] };\n } catch {\n return null;\n }\n}\n\nfunction saveStability() {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n try {\n const payload = {\n geo: state.geo,\n stability: state.stability,\n lastGeoChange: state.lastGeoChange,\n };\n localStorage.setItem(CACHE_KEY, JSON.stringify(payload));\n } catch {\n /* ignore */\n }\n}\n\n// -----------------------------------------------------------\n// 🌍 Geo Detection (Node, Browser, Worker)\n// -----------------------------------------------------------\nexport function detectGeo(): string {\n try {\n if (isBrowser && typeof window !== \"undefined\" && window.navigator?.language) {\n return window.navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isWorker && typeof self !== \"undefined\" && (self as any).navigator?.language) {\n return (self as any).navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isNode && typeof process !== \"undefined\") {\n const envGeo = process.env.ZUBBL_GEO || process.env.GEO;\n if (envGeo && /^[A-Z]{2}$/i.test(envGeo)) return envGeo.toUpperCase();\n return \"GB\";\n }\n\n return \"unknown\";\n } catch (err) {\n console.warn(\"[Zubbl SDK][Geo Detect] Failed:\", err);\n return \"unknown\";\n }\n}\n\n// -----------------------------------------------------------\n// 🧭 Update Geo & Stability (with persistence)\n// -----------------------------------------------------------\nexport function updateGeo(geoHint?: string) {\n const newGeo = geoHint || detectGeo();\n if (newGeo !== state.geo) {\n const now = Date.now();\n const elapsed = (now - state.lastGeoChange) / 1000;\n state.stability = Math.max(0.5, Math.min(1.0, elapsed / 3600));\n state.geo = newGeo;\n state.lastGeoChange = now;\n saveStability();\n } else {\n state.stability = Math.min(1.0, state.stability + 0.01);\n saveStability();\n }\n}\n\n// -----------------------------------------------------------\n// 🧮 Record Context Samples\n// -----------------------------------------------------------\nexport function recordContextSample(\n path: string,\n method: string,\n status: number,\n latency: number\n) {\n state.routes.push({ path, method, ts: Date.now(), status, latency });\n if (state.routes.length > MAX_HISTORY) state.routes.shift();\n updateGeo(); // auto-refresh geo info\n}\n\n// -----------------------------------------------------------\n// 📦 Get Adaptive Headers\n// -----------------------------------------------------------\nexport function getAdaptiveHeaders(): Record<string, string> {\n const currentGeo = detectGeo();\n updateGeo(currentGeo);\n\n const summary = btoa(\n JSON.stringify({\n env: isNode ? \"node\" : isBrowser ? \"browser\" : \"worker\",\n routeCount: state.routes.length,\n lastGeo: state.geo,\n avgLatency:\n state.routes.reduce((a, b) => a + b.latency, 0) /\n Math.max(1, state.routes.length),\n })\n );\n\n return {\n \"X-Zubbl-Context-Summary\": summary,\n \"X-Zubbl-Geo-Stability\": `${state.geo}/${state.stability.toFixed(2)}`,\n };\n}\n\n// -----------------------------------------------------------\n// 🌍 Initialize Geo Context Immediately\n// -----------------------------------------------------------\nupdateGeo(process.env.ZUBBL_GEO);\n\n","// src/core/storage.ts\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// Generic storage interface\nexport interface IStorage {\n get<T>(key: string): T | null;\n set<T>(key: string, value: T, ttlSeconds?: number): void;\n remove(key: string): void;\n}\n\n// ------------------------------------------------------\n// Node (in-memory) implementation\n// ------------------------------------------------------\n\nclass NodeStorage implements IStorage {\n private store = new Map<string, { value: any; expiresAt?: number }>();\n\n get<T>(key: string): T | null {\n const entry = this.store.get(key);\n if (!entry) return null;\n if (entry.expiresAt && entry.expiresAt < Date.now()) {\n this.store.delete(key);\n return null;\n }\n return entry.value as T;\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n this.store.set(key, { value, expiresAt });\n }\n\n remove(key: string): void {\n this.store.delete(key);\n }\n}\n\n// ------------------------------------------------------\n// Browser (localStorage) implementation\n// ------------------------------------------------------\n\nclass BrowserStorage implements IStorage {\n private prefix = \"zubbl_sdk_\";\n\n get<T>(key: string): T | null {\n try {\n const raw = localStorage.getItem(this.prefix + key);\n if (!raw) return null;\n const { value, expiresAt } = JSON.parse(raw);\n if (expiresAt && expiresAt < Date.now()) {\n localStorage.removeItem(this.prefix + key);\n return null;\n }\n return value as T;\n } catch {\n return null;\n }\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n try {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n localStorage.setItem(\n this.prefix + key,\n JSON.stringify({ value, expiresAt })\n );\n } catch (err) {\n // localStorage quota exceeded → silently ignore\n console.warn(\"[Zubbl SDK][Storage] Failed to persist item:\", err);\n }\n }\n\n remove(key: string): void {\n localStorage.removeItem(this.prefix + key);\n }\n}\n\n// ------------------------------------------------------\n// Factory\n// ------------------------------------------------------\n\nexport function createStorage(): IStorage {\n if (isNode) return new NodeStorage();\n if (isBrowser) return new BrowserStorage();\n\n // Fallback: safe no-op storage for tests / fake environments\n return {\n get: () => null,\n set: () => {},\n remove: () => {},\n };\n}\n\n","// -----------------------------------------------------------\n// 🌍 Zubbl Geo Engine — Cloudflare-Native Only (No External Providers)\n// -----------------------------------------------------------\n// Uses Worker-provided request.cf + headers. Free on all plans.\n// Sim/CLI fallback to avoid noise.\n// Aligns with Zubbl GEO Enforcement Whitepaper (Worker layer).\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types (unchanged)\n// -----------------------------------------------------------\nexport interface GeoPrivacy {\n vpn: boolean;\n hosting: boolean;\n}\n\nexport interface GeoInfo {\n ip: string | null;\n country: string;\n asn: string | null;\n privacy: GeoPrivacy;\n}\n\nconst GEO_CACHE_KEY = \"zubbl-geo-cache\";\nconst GEO_TTL_MS = 15 * 60 * 1000; // 15 minutes\n\n// -----------------------------------------------------------\n// 🗃 Cache Helpers (unchanged, browser-only)\n// -----------------------------------------------------------\nfunction loadGeoCache(): GeoInfo | null {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n const raw = localStorage.getItem(GEO_CACHE_KEY);\n if (!raw) return null;\n\n const parsed = JSON.parse(raw) as { data: GeoInfo; timestamp: number };\n if (!parsed.data?.country || Date.now() - parsed.timestamp > GEO_TTL_MS) return null;\n return parsed.data;\n } catch {\n return null;\n }\n}\n\nfunction saveGeoCache(data: GeoInfo): void {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n localStorage.setItem(GEO_CACHE_KEY, JSON.stringify({ data, timestamp: Date.now() }));\n } catch {}\n}\n\n// -----------------------------------------------------------\n// 🧠 Cloudflare-Native Resolver\n// -----------------------------------------------------------\nexport async function getGeoInfo(context: any = {}): Promise<GeoInfo> { // Accept context for Worker/Request\n const cached = loadGeoCache();\n if (cached) return cached;\n\n // Detect sim/CLI (Node runtime, no Worker context)\n const isSimulation = process.env.ZUBBL_SIM_MODE === 'true' || isNode;\n\n // Extract from Worker-provided data (request.cf or enriched headers)\n const headers = context?.request?.headers || new Headers();\n const cf = context?.request?.cf || {}; // request.cf if Worker context available\n\n let country = cf.country || headers.get('CF-IPCountry') || headers.get('X-Zubbl-Geo-Country') || 'XX';\n let asn = cf.asn?.toString() || headers.get('X-Zubbl-ASN') || null;\n let asOrg = cf.asOrganization || headers.get('X-Zubbl-Geo-ASOrg') || null;\n\n// Sim fallback (clean run, no external noise)\nif (isSimulation && country === 'XX') {\n const simCountry =\n process.env.ZUBBL_SIM_COUNTRY ||\n process.env.ZUBBL_SIM_CF_IPCOUNTRY ||\n '';\n\n const simAsn = process.env.ZUBBL_SIM_ASN || '';\n const simAsOrg = process.env.ZUBBL_SIM_ASORG || '';\n\n const finalCountry = simCountry || 'GB';\n const finalAsn = simAsn || '2856';\n const finalAsOrg = simAsOrg || 'British Telecommunications';\n\n console.debug(\n `[Zubbl SDK][Geo][SIM] No Cloudflare data; using SIM defaults: country=${finalCountry}, asn=${finalAsn}`\n );\n\n country = finalCountry;\n asn = finalAsn;\n asOrg = finalAsOrg;\n}\n\nconst geo: GeoInfo = {\n ip: cf.clientIp || headers.get('CF-Connecting-IP') || null,\n country,\n asn,\n privacy: {\n vpn: false,\n hosting: false,\n },\n};\n\n// Optional: Worker can set privacy flags via headers (e.g., X-Zubbl-Privacy-VPN)\ngeo.privacy.vpn = headers.get('X-Zubbl-Privacy-VPN') === 'true';\ngeo.privacy.hosting = headers.get('X-Zubbl-Privacy-Hosting') === 'true';\n\n// SIM env overrides (so Node simulations don't require Worker headers)\nif (isSimulation) {\n if (process.env.ZUBBL_SIM_VPN !== undefined) {\n geo.privacy.vpn = String(process.env.ZUBBL_SIM_VPN).toLowerCase() === 'true';\n }\n if (process.env.ZUBBL_SIM_HOSTING !== undefined) {\n geo.privacy.hosting = String(process.env.ZUBBL_SIM_HOSTING).toLowerCase() === 'true';\n }\n}\n\nsaveGeoCache(geo);\nconsole.debug('[Zubbl SDK][Geo] Resolved (Cloudflare-native):', geo);\n\nreturn geo;\n}\n\n// -----------------------------------------------------------\n// 🧩 Exported Helpers (updated)\n// -----------------------------------------------------------\nexport function clearGeoCache(): void {\n try {\n if (isBrowser && typeof localStorage !== \"undefined\") {\n localStorage.removeItem(GEO_CACHE_KEY);\n }\n } catch {}\n}\n\nexport async function getGeoHeaders(context?: any): Promise<Record<string, string>> {\n const geo = await getGeoInfo(context);\n return {\n \"X-Zubbl-Geo-Country\": geo.country || \"unknown\",\n \"X-Zubbl-ASN\": geo.asn || \"unknown\",\n \"X-Zubbl-IP\": geo.ip || \"\",\n \"X-Zubbl-Privacy-VPN\": String(geo.privacy?.vpn ?? false),\n \"X-Zubbl-Privacy-Hosting\": String(geo.privacy?.hosting ?? false),\n };\n}\n","// -----------------------------------------------------------\n// 🔐 Secure Signing & Nonce Generator\n// -----------------------------------------------------------\n\nimport crypto from \"crypto\";\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Generate UUIDv4 Nonce\n// -----------------------------------------------------------\nexport function generateNonce(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, c => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n// -----------------------------------------------------------\n// Compute SHA256 HMAC signature\n// -----------------------------------------------------------\nexport async function signPayload(payload: string, secret: string): Promise<string> {\n if (isNode) {\n // ✅ Node.js native HMAC\n return crypto.createHmac(\"sha256\", secret).update(payload).digest(\"hex\");\n }\n\n // ✅ Browser / Worker using WebCrypto\n if (typeof window !== \"undefined\" && window.crypto?.subtle) {\n const key = await window.crypto.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n\n const sig = await window.crypto.subtle.sign(\n \"HMAC\",\n key,\n new TextEncoder().encode(payload)\n );\n\n return Array.from(new Uint8Array(sig))\n .map(b => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n throw new Error(\"No crypto implementation available in this environment\");\n}\n\n// -----------------------------------------------------------\n// Attach signing headers to a request (corrected for SDK-12)\n// -----------------------------------------------------------\nexport function attachSigningHeaders(\n url: string,\n method: string,\n headers: Record<string, string> = {},\n body?: any,\n secretKey?: string | null\n): void {\n const nonce = generateNonce();\n\n // Normalize body to a string before hashing\n const normalizedBody =\n typeof body === \"string\"\n ? body\n : body && typeof body === \"object\"\n ? JSON.stringify(body)\n : \"\";\n\n const bodyHash = normalizedBody\n ? crypto.createHash(\"sha256\").update(normalizedBody).digest(\"hex\")\n : \"\";\n\n // Compute canonical string (deterministic)\n const canonical = `${method.toUpperCase()}\\n${url}\\n${nonce}\\n${bodyHash}`;\n\n // Attach nonce and signature headers (in-place)\n headers[\"X-Zubbl-Nonce\"] = nonce;\n\n if (secretKey) {\n const signature = crypto\n .createHmac(\"sha256\", secretKey)\n .update(canonical)\n .digest(\"hex\");\n headers[\"X-Zubbl-Signature\"] = signature;\n }\n}\n","import crypto from \"crypto\";\n\nexport function sha256Hex(input: string): string {\n return crypto.createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\nexport function hmacSha256Hex(secret: string, input: string): string {\n return crypto.createHmac(\"sha256\", secret).update(input).digest(\"hex\");\n}\n\nexport function makeNonce(): string {\n return crypto.randomUUID();\n}\n\nexport function signCanonical(opts: {\n secret: string;\n method: string;\n pathWithQuery: string;\n nonce: string;\n bodyText: string;\n}): string {\n const bodyHash = sha256Hex(opts.bodyText || \"\");\n const canonical =\n `${opts.method.toUpperCase()}\\n${opts.pathWithQuery}\\n${opts.nonce}\\n${bodyHash}`;\n return hmacSha256Hex(opts.secret, canonical);\n}\n","// src/core/http.ts\n// -----------------------------------------------------------\n// HTTP utility (instance-safe)\n// -----------------------------------------------------------\n\nimport { recordContextSample, getAdaptiveHeaders } from \"./context\";\nimport { attachSigningHeaders } from \"./signing\";\nimport { makeNonce, signCanonical } from \"../utils/signing\";\n\n/**\n * Performs a safe HTTP request with adaptive + signing headers.\n * NOTE: no global getConfig() dependency — caller must provide fully resolved URL + headers.\n */\nexport async function httpRequest(url: string, options: RequestInit = {}): Promise<Response> {\n // 🔧 Default timeout lowered for SDK-12 hardening\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 8000);\n\n try {\n const method = (options.method || \"GET\").toUpperCase();\n\n // Keep original body reference for attachSigningHeaders (if you rely on it)\n const originalBody = options.body;\n\n // Normalise headers to a mutable object\n const headers: Record<string, string> = {\n ...((options.headers as Record<string, string>) || {}),\n ...getAdaptiveHeaders(),\n };\n\n // ✅ Keep your existing signing hook (if it adds auth/bearer/etc)\n // NOTE: This does NOT implement the Worker signature gate by itself (that's below).\n attachSigningHeaders(url, method, headers, originalBody);\n\n // Build finalOptions (must exist before we can safely sign exact bytes)\n const finalOptions: RequestInit = {\n ...options,\n method,\n headers,\n signal: controller.signal,\n };\n\n // ---------------------------------------------------------\n // ZUBBL: Worker signature gate (nonce + HMAC signature)\n // ---------------------------------------------------------\n // Worker expects:\n // canonical = METHOD \\n PATH+QUERY \\n NONCE \\n SHA256(bodyText)\n // headers: X-Zubbl-Nonce, X-Zubbl-Signature\n //\n // This is \"Option B\": verify signature + nonce replay protection.\n // ---------------------------------------------------------\n\n const apiKey =\n (headers[\"Authorization\"] || headers[\"authorization\"] || \"\")\n .replace(/^Bearer\\s+/i, \"\")\n .trim();\n\n const signingSecret =\n ((headers as any)[\"X-Zubbl-Signing-Secret\"] as string | undefined)?.trim() || \"\";\n\n if (!apiKey) {\n throw new Error(\"Missing API key (Authorization: Bearer ...) — cannot send requests\");\n }\n\n if (!signingSecret) {\n throw new Error(\"Missing signing secret — cannot sign requests\");\n }\n\n // We must sign the exact bytes we send.\n // If body is an object, stringify it BEFORE signing AND BEFORE sending.\n let bodyText = \"\";\n if (![\"GET\", \"HEAD\"].includes(method)) {\n const b: any = (finalOptions as any).body;\n\n if (b == null) bodyText = \"\";\n else if (typeof b === \"string\") bodyText = b;\n else bodyText = JSON.stringify(b);\n\n // Ensure fetch sends the exact signed string\n (finalOptions as any).body = bodyText;\n }\n\n // Canonical URL must match Worker logic: pathname + search\n const u = new URL(url);\n const pathWithQuery = `${u.pathname}${u.search}`;\n\n const nonce = makeNonce();\n const signature = signCanonical({\n secret: signingSecret,\n method,\n pathWithQuery,\n nonce,\n bodyText,\n });\n\n // Attach signing headers (ensure headers object is mutable)\n (finalOptions.headers as any) = (finalOptions.headers || {}) as any;\n (finalOptions.headers as any)[\"X-Zubbl-Nonce\"] = nonce;\n (finalOptions.headers as any)[\"X-Zubbl-Signature\"] = signature;\n\n // 🔒 Never send the signing secret over the wire (internal-only)\n delete (finalOptions.headers as any)[\"X-Zubbl-Signing-Secret\"];\n\n // Record adaptive context sample (keep your existing behaviour)\n recordContextSample(\"/http\", \"GET\", 200, 123);\n\n const response = await fetch(url, finalOptions);\n\n if (!response.ok && response.status !== 429) {\n let extra = \"\";\n try {\n extra = await response.clone().text();\n if (extra.length > 200) extra = extra.slice(0, 200) + \"...\";\n } catch {}\n console.warn(\n `[Zubbl SDK][HTTP] ${response.status} on ${url}${extra ? ` — ${extra}` : \"\"}`\n );\n }\n\n return response;\n } catch (err: any) {\n console.error(\"[Zubbl SDK][HTTP] Request failed:\", err?.message);\n throw err;\n } finally {\n clearTimeout(timeout);\n }\n}\n","\n\n// src/features/identifyUser.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe identifyUser feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\nconst USER_CACHE_KEY = \"external_user_id\";\nconst USER_TTL = 24 * 60 * 60; // 24h\n\nexport async function identifyUserFeature(\n store: any,\n { email, name }: { email: string; name?: string }\n) {\n if (!email) throw new Error(\"email is required\");\n\n const config = store.get();\n const storage = createStorage();\n\n // ✅ Determine override identity (prefer config.identity which SIM sets)\n const cfgIdentity = (config as any)?.identity;\n const storeIdentity = (store as any)?.identity;\n\n const overrideEnabled =\n (cfgIdentity && cfgIdentity.override === true) ||\n (storeIdentity && storeIdentity.override === true);\n\n const overrideId = overrideEnabled\n ? (cfgIdentity?.id ||\n storeIdentity?.id ||\n (store as any)?.externalUserId ||\n (store as any)?.userId ||\n undefined)\n : undefined;\n\n // Check cache (skip cache when override is enabled, we must honour overrideId)\n if (!overrideId) {\n const cached = storage.get<{ id: string }>(USER_CACHE_KEY);\n if (cached?.id) {\n return { external_user_id: cached.id, cached: true };\n }\n }\n\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use per-instance config store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"Content-Type\": \"application/json\",\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // ✅ If SIM/consumer provided an override external user ID, call the explicit endpoint\n const identifyUrl = overrideId\n ? `${config.baseUrl}/sdk/identify/${encodeURIComponent(String(overrideId))}`\n : `${config.baseUrl}/sdk/identify`;\n\n const resp = await httpRequest(identifyUrl, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ email, name }),\n });\n\n const data = await resp.json().catch(() => ({}));\n const { external_user_id } = data;\n\n if (!external_user_id) {\n throw new Error(\"Backend did not return external_user_id\");\n }\n\n storage.set(USER_CACHE_KEY, { id: external_user_id }, USER_TTL);\n return { external_user_id, cached: false };\n}\n","// src/features/getTiles.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe getTiles feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\n\nconst TILE_CACHE_KEY = \"tiles_cache\";\nconst TILE_TTL_DEFAULT = 10 * 60; // 10 min\n\ninterface TileCacheEntry {\n data: any;\n etag?: string;\n expiresAt: number;\n}\n\nexport async function getTilesFeature(\n store: any,\n { external_user_id, app_id = null, ttlSeconds = TILE_TTL_DEFAULT }: any\n) {\n const config = store.get();\n const storage = createStorage();\n\n const cached = storage.get<TileCacheEntry>(TILE_CACHE_KEY);\n const isFresh = cached && cached.expiresAt > Date.now();\n\n if (isFresh) {\n backgroundRefresh(store, external_user_id, app_id, ttlSeconds);\n return { data: cached.data, fromCache: true };\n }\n\n try {\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use instance store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // Modern endpoint: POST /api/sdk/policies with body (per architecture docs)\nconst payload = {\n tenant_id: config.tenantId,\n app_id: app_id || config.appId!,\n external_user_id,\n};\n\nconst resp = await httpRequest(`${config.baseUrl.replace(/\\/$/, \"\")}/sdk/policies`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n});\n\n if (resp.status === 304 && cached?.data) {\n cached.expiresAt = Date.now() + ttlSeconds * 1000;\n storage.set(TILE_CACHE_KEY, cached, ttlSeconds);\n return { data: cached.data, fromCache: true, status: 304 };\n }\n\n const data = await resp.json();\n console.log('[DEBUG getTiles] Raw tiles response:', JSON.stringify(data, null, 2)); \n const etag = resp.headers.get(\"ETag\") || undefined;\n\n const entry: TileCacheEntry = {\n data,\n etag,\n expiresAt: Date.now() + ttlSeconds * 1000,\n };\n storage.set(TILE_CACHE_KEY, entry, ttlSeconds);\n\n return { data, fromCache: false, status: resp.status };\n } catch (err) {\n if (cached?.data) {\n return { data: cached.data, fromCache: true, error: String(err) };\n }\n throw err;\n }\n}\n\nasync function backgroundRefresh(store: any, external_user_id: string, app_id: string | null, ttlSeconds: number) {\n try {\n await getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n } catch {\n // Silent background failure\n }\n}\n","// src/client.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Final Instance-based Client (Feature Delegation)\n// -----------------------------------------------------------\n\nimport * as ConfigModule from \"./core/config\";\nimport { createStorage } from \"./core/storage\";\nimport { getGeoInfo } from \"./core/geo\";\nimport { httpRequest } from \"./core/http\"; // ✅ ADD THIS\n\n// Feature modules\nimport { identifyUserFeature } from \"./features/identifyUser\";\nimport { getTilesFeature } from \"./features/getTiles\";\n\nexport type ZubblConfig = {\n apiKey: string;\n signingSecret: string;\n tenantId: string;\n appId: string;\n baseUrl?: string;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n};\n\n\n/**\n * Creates a self-contained, instance-based Zubbl client.\n * Each instance owns its own config store and initialization state.\n */\nexport function createZubblClient(cfg: ZubblConfig) {\n const store = ConfigModule.createConfigStore();\n const storage = createStorage();\n let initialized = false;\n\n async function init() {\n if (initialized) return;\n\n // ✅ Validate UUIDs before initializing\n const UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n if (!UUID_PATTERN.test(cfg.tenantId)) {\n throw new Error(`[Zubbl SDK] Invalid tenantId: expected UUID, got \"${cfg.tenantId}\"`);\n }\n\n if (!UUID_PATTERN.test(cfg.appId)) {\n throw new Error(`[Zubbl SDK] Invalid appId: expected UUID, got \"${cfg.appId}\"`);\n }\n\n // Initialize per-client config\n store.init(cfg);\n\n // Optional: GEO bootstrap\n try {\n const geo = await getGeoInfo();\n console.log(`[Zubbl SDK] 🌍 GEO detected: ${geo.country} (ASN ${geo.asn || \"?\"})`);\n } catch (err: any) {\n console.warn(\"[Zubbl SDK] GEO init failed:\", err?.message);\n }\n\n initialized = true;\n }\n\n function assertInitialized() {\n if (!initialized) {\n throw new Error(\"Zubbl client not initialized — call client.init() first\");\n }\n }\n\n // ---------------------------------------------------------\n // User + Tile Operations (delegated to feature modules)\n // ---------------------------------------------------------\n async function identifyUser({ email, name }: { email: string; name?: string }) {\n assertInitialized();\n return identifyUserFeature(store, { email, name });\n }\n\n async function getTiles({\n external_user_id,\n app_id = null,\n ttlSeconds,\n }: {\n external_user_id: string;\n app_id?: string | null;\n ttlSeconds?: number;\n }) {\n assertInitialized();\n return getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n }\n\n // ---------------------------------------------------------\n // Enforcement API (kept inline)\n // ---------------------------------------------------------\n async function enforce({\n external_user_id,\n app_id = null,\n }: {\n external_user_id: string;\n app_id?: string | null;\n }) {\n assertInitialized();\n\n const config = store.get();\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n });\n\n // ✅ IMPORTANT: use signed httpRequest so Worker gate passes\n const url = `${config.baseUrl?.replace(/\\/$/, \"\")}/sdk/test-enforcement`;\n const resp = await httpRequest(url, {\n method: \"POST\",\n headers,\n });\n\n const json = await resp.json().catch(() => ({}));\n return { decision: \"allow\", status: resp.status, data: json };\n }\n\n // ---------------------------------------------------------\n // Public API\n // ---------------------------------------------------------\n return {\n init,\n identifyUser,\n getTiles,\n enforce,\n storage,\n };\n}\n","// src/index.ts\n// -----------------------------------------------------------\n// Zubbl SDK Entry Point — Public Exports\n// -----------------------------------------------------------\n\n// Core factory + environment\nexport * from \"./core/config\";\nexport * from \"./core/context\";\nexport * from \"./core/storage\";\nexport * from \"./core/geo\";\n\n// Avoid duplicate export of ZubblConfig\nexport {\n createZubblClient, // 🔁 change this if your client.ts exports something else\n} from \"./client\";\n\n// Feature modules (optional direct access)\nexport * from \"./features/identifyUser\";\nexport * from \"./features/getTiles\";\n\nconsole.log(\"[Zubbl SDK] ✅ Entry point loaded\");\n"],"names":["ConfigModule.createConfigStore"],"mappings":"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"}
1
+ {"version":3,"file":"zubbl-sdk.cjs.js","sources":["../src/core/config.ts","../src/core/context.ts","../src/core/storage.ts","../src/core/geo.ts","../src/core/signing.ts","../src/utils/signing.ts","../src/core/http.ts","../src/features/identifyUser.ts","../src/features/getTiles.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["// src/core/config.ts\n// -----------------------------------------------------------\n// Universal environment detection + SDK configuration\n// -----------------------------------------------------------\n\nexport const isBrowser =\n typeof window !== \"undefined\" && typeof window.document !== \"undefined\";\n\nexport const isNode =\n typeof process !== \"undefined\" &&\n !!process.versions?.node &&\n !isBrowser;\n\nexport const isWorker =\n typeof self !== \"undefined\" &&\n typeof (self as any).importScripts === \"function\" &&\n !isNode;\n\n// -----------------------------------------------------------\n// Config store factory (no module-scoped state)\n// -----------------------------------------------------------\n\nexport interface ZubblConfig {\n apiKey: string | null;\n signingSecret: string | null; // ✅ used for HMAC signing (never sent over the wire)\n tenantId: string | null;\n appId: string | null;\n baseUrl: string;\n appBaseUrl?: string | null;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n}\n\nfunction assertBrowserSafety(cfg: ZubblConfig) {\n if (isBrowser || isWorker) {\n const key = cfg.apiKey ?? \"\";\n const looksSecret = key.startsWith(\"sk_\") || key.length > 40;\n if (looksSecret) {\n throw new Error(\n \"[Zubbl SDK] Secret or server key detected in browser environment. \" +\n \"Use a public SDK key instead (prefix pk_).\"\n );\n }\n }\n}\n\n/**\n * Creates an isolated configuration store.\n * Each ZubblClient instance owns its own store.\n */\nexport function createConfigStore(initial?: Partial<ZubblConfig>) {\n let current: ZubblConfig = {\n apiKey: null,\n signingSecret: null,\n tenantId: null,\n appId: null,\n baseUrl: \"https://api.zubbl.com/api\",\n appBaseUrl: null,\n injectWorkerHeaders: false,\n workerSecret: null,\n ...initial,\n };\n\n function init(partial: Partial<ZubblConfig>) {\n current = { ...current, ...partial };\n assertBrowserSafety(current);\n }\n\n function get(): Readonly<ZubblConfig> {\n return current;\n }\n\n function buildHeaders(extra: Record<string, string> = {}): Record<string, string> {\n if (!current.tenantId || !current.appId) {\n throw new Error(\"[Zubbl SDK] Not initialized – call init() first.\");\n }\n\n const headers: Record<string, string> = {\n \"X-Tenant-Id\": current.tenantId,\n \"X-App-Id\": current.appId,\n \"Content-Type\": \"application/json\",\n ...extra,\n };\n\n if (current.apiKey) {\n headers.Authorization = `Bearer ${current.apiKey}`;\n }\n\n // ✅ Internal-only: used by httpRequest() to compute signature, then deleted before fetch\n if (current.signingSecret) {\n headers[\"X-Zubbl-Signing-Secret\"] = current.signingSecret;\n } else if (current.apiKey) {\n // If you're using API-key auth, you must also provide signingSecret for Worker-gated endpoints\n throw new Error(\"[Zubbl SDK] Missing signingSecret (required for signed requests)\");\n }\n\n return headers;\n }\n\n return { init, get, buildHeaders };\n}\n\n","// src/core/context.ts\n// -----------------------------------------------------------\n// Adaptive Context Engine — Geo + Stability Enrichment + Persistence\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types\n// -----------------------------------------------------------\ninterface ContextSample {\n path: string;\n method: string;\n ts: number;\n status: number;\n latency: number;\n}\n\ninterface AdaptiveState {\n routes: ContextSample[];\n geo: string;\n stability: number;\n lastGeoChange: number;\n}\n\nconst MAX_HISTORY = 100;\nconst CACHE_KEY = \"zubbl-stability\";\n\nlet state: AdaptiveState = loadStability() ?? {\n routes: [],\n geo: \"unknown\",\n stability: 1.0,\n lastGeoChange: Date.now(),\n};\n\n// -----------------------------------------------------------\n// 💾 Persistence Helpers\n// -----------------------------------------------------------\nfunction loadStability(): AdaptiveState | null {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(CACHE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (!parsed.geo || !parsed.stability) return null;\n return { ...parsed, routes: [] };\n } catch {\n return null;\n }\n}\n\nfunction saveStability() {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n try {\n const payload = {\n geo: state.geo,\n stability: state.stability,\n lastGeoChange: state.lastGeoChange,\n };\n localStorage.setItem(CACHE_KEY, JSON.stringify(payload));\n } catch {\n /* ignore */\n }\n}\n\n// -----------------------------------------------------------\n// 🌍 Geo Detection (Node, Browser, Worker)\n// -----------------------------------------------------------\nexport function detectGeo(): string {\n try {\n if (isBrowser && typeof window !== \"undefined\" && window.navigator?.language) {\n return window.navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isWorker && typeof self !== \"undefined\" && (self as any).navigator?.language) {\n return (self as any).navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isNode && typeof process !== \"undefined\") {\n const envGeo = process.env.ZUBBL_GEO || process.env.GEO;\n if (envGeo && /^[A-Z]{2}$/i.test(envGeo)) return envGeo.toUpperCase();\n return \"GB\";\n }\n\n return \"unknown\";\n } catch (err) {\n console.warn(\"[Zubbl SDK][Geo Detect] Failed:\", err);\n return \"unknown\";\n }\n}\n\n// -----------------------------------------------------------\n// 🧭 Update Geo & Stability (with persistence)\n// -----------------------------------------------------------\nexport function updateGeo(geoHint?: string) {\n const newGeo = geoHint || detectGeo();\n if (newGeo !== state.geo) {\n const now = Date.now();\n const elapsed = (now - state.lastGeoChange) / 1000;\n state.stability = Math.max(0.5, Math.min(1.0, elapsed / 3600));\n state.geo = newGeo;\n state.lastGeoChange = now;\n saveStability();\n } else {\n state.stability = Math.min(1.0, state.stability + 0.01);\n saveStability();\n }\n}\n\n// -----------------------------------------------------------\n// 🧮 Record Context Samples\n// -----------------------------------------------------------\nexport function recordContextSample(\n path: string,\n method: string,\n status: number,\n latency: number\n) {\n state.routes.push({ path, method, ts: Date.now(), status, latency });\n if (state.routes.length > MAX_HISTORY) state.routes.shift();\n updateGeo(); // auto-refresh geo info\n}\n\n// -----------------------------------------------------------\n// 📦 Get Adaptive Headers\n// -----------------------------------------------------------\nexport function getAdaptiveHeaders(): Record<string, string> {\n const currentGeo = detectGeo();\n updateGeo(currentGeo);\n\n const summary = btoa(\n JSON.stringify({\n env: isNode ? \"node\" : isBrowser ? \"browser\" : \"worker\",\n routeCount: state.routes.length,\n lastGeo: state.geo,\n avgLatency:\n state.routes.reduce((a, b) => a + b.latency, 0) /\n Math.max(1, state.routes.length),\n })\n );\n\n return {\n \"X-Zubbl-Context-Summary\": summary,\n \"X-Zubbl-Geo-Stability\": `${state.geo}/${state.stability.toFixed(2)}`,\n };\n}\n\n// -----------------------------------------------------------\n// 🌍 Initialize Geo Context Immediately\n// -----------------------------------------------------------\nupdateGeo(process.env.ZUBBL_GEO);\n\n","// src/core/storage.ts\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// Generic storage interface\nexport interface IStorage {\n get<T>(key: string): T | null;\n set<T>(key: string, value: T, ttlSeconds?: number): void;\n remove(key: string): void;\n}\n\n// ------------------------------------------------------\n// Node (in-memory) implementation\n// ------------------------------------------------------\n\nclass NodeStorage implements IStorage {\n private store = new Map<string, { value: any; expiresAt?: number }>();\n\n get<T>(key: string): T | null {\n const entry = this.store.get(key);\n if (!entry) return null;\n if (entry.expiresAt && entry.expiresAt < Date.now()) {\n this.store.delete(key);\n return null;\n }\n return entry.value as T;\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n this.store.set(key, { value, expiresAt });\n }\n\n remove(key: string): void {\n this.store.delete(key);\n }\n}\n\n// ------------------------------------------------------\n// Browser (localStorage) implementation\n// ------------------------------------------------------\n\nclass BrowserStorage implements IStorage {\n private prefix = \"zubbl_sdk_\";\n\n get<T>(key: string): T | null {\n try {\n const raw = localStorage.getItem(this.prefix + key);\n if (!raw) return null;\n const { value, expiresAt } = JSON.parse(raw);\n if (expiresAt && expiresAt < Date.now()) {\n localStorage.removeItem(this.prefix + key);\n return null;\n }\n return value as T;\n } catch {\n return null;\n }\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n try {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n localStorage.setItem(\n this.prefix + key,\n JSON.stringify({ value, expiresAt })\n );\n } catch (err) {\n // localStorage quota exceeded → silently ignore\n console.warn(\"[Zubbl SDK][Storage] Failed to persist item:\", err);\n }\n }\n\n remove(key: string): void {\n localStorage.removeItem(this.prefix + key);\n }\n}\n\n// ------------------------------------------------------\n// Factory\n// ------------------------------------------------------\n\nexport function createStorage(): IStorage {\n if (isNode) return new NodeStorage();\n if (isBrowser) return new BrowserStorage();\n\n // Fallback: safe no-op storage for tests / fake environments\n return {\n get: () => null,\n set: () => {},\n remove: () => {},\n };\n}\n\n","// -----------------------------------------------------------\n// 🌍 Zubbl Geo Engine — Cloudflare-Native Only (No External Providers)\n// -----------------------------------------------------------\n// Uses Worker-provided request.cf + headers. Free on all plans.\n// Sim/CLI fallback to avoid noise.\n// Aligns with Zubbl GEO Enforcement Whitepaper (Worker layer).\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types (unchanged)\n// -----------------------------------------------------------\nexport interface GeoPrivacy {\n vpn: boolean;\n hosting: boolean;\n}\n\nexport interface GeoInfo {\n ip: string | null;\n country: string;\n asn: string | null;\n privacy: GeoPrivacy;\n}\n\nconst GEO_CACHE_KEY = \"zubbl-geo-cache\";\nconst GEO_TTL_MS = 15 * 60 * 1000; // 15 minutes\n\n// -----------------------------------------------------------\n// 🗃 Cache Helpers (unchanged, browser-only)\n// -----------------------------------------------------------\nfunction loadGeoCache(): GeoInfo | null {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n const raw = localStorage.getItem(GEO_CACHE_KEY);\n if (!raw) return null;\n\n const parsed = JSON.parse(raw) as { data: GeoInfo; timestamp: number };\n if (!parsed.data?.country || Date.now() - parsed.timestamp > GEO_TTL_MS) return null;\n return parsed.data;\n } catch {\n return null;\n }\n}\n\nfunction saveGeoCache(data: GeoInfo): void {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n localStorage.setItem(GEO_CACHE_KEY, JSON.stringify({ data, timestamp: Date.now() }));\n } catch {}\n}\n\n// -----------------------------------------------------------\n// 🧠 Cloudflare-Native Resolver\n// -----------------------------------------------------------\nexport async function getGeoInfo(context: any = {}): Promise<GeoInfo> { // Accept context for Worker/Request\n const cached = loadGeoCache();\n if (cached) return cached;\n\n // Detect sim/CLI (Node runtime, no Worker context)\n const isSimulation = process.env.ZUBBL_SIM_MODE === 'true' || isNode;\n\n // Extract from Worker-provided data (request.cf or enriched headers)\n const headers = context?.request?.headers || new Headers();\n const cf = context?.request?.cf || {}; // request.cf if Worker context available\n\n let country = cf.country || headers.get('CF-IPCountry') || headers.get('X-Zubbl-Geo-Country') || 'XX';\n let asn = cf.asn?.toString() || headers.get('X-Zubbl-ASN') || null;\n let asOrg = cf.asOrganization || headers.get('X-Zubbl-Geo-ASOrg') || null;\n\n// Sim fallback (clean run, no external noise)\nif (isSimulation && country === 'XX') {\n const simCountry =\n process.env.ZUBBL_SIM_COUNTRY ||\n process.env.ZUBBL_SIM_CF_IPCOUNTRY ||\n '';\n\n const simAsn = process.env.ZUBBL_SIM_ASN || '';\n const simAsOrg = process.env.ZUBBL_SIM_ASORG || '';\n\n const finalCountry = simCountry || 'GB';\n const finalAsn = simAsn || '2856';\n const finalAsOrg = simAsOrg || 'British Telecommunications';\n\n console.debug(\n `[Zubbl SDK][Geo][SIM] No Cloudflare data; using SIM defaults: country=${finalCountry}, asn=${finalAsn}`\n );\n\n country = finalCountry;\n asn = finalAsn;\n asOrg = finalAsOrg;\n}\n\nconst geo: GeoInfo = {\n ip: cf.clientIp || headers.get('CF-Connecting-IP') || null,\n country,\n asn,\n privacy: {\n vpn: false,\n hosting: false,\n },\n};\n\n// Optional: Worker can set privacy flags via headers (e.g., X-Zubbl-Privacy-VPN)\ngeo.privacy.vpn = headers.get('X-Zubbl-Privacy-VPN') === 'true';\ngeo.privacy.hosting = headers.get('X-Zubbl-Privacy-Hosting') === 'true';\n\n// SIM env overrides (so Node simulations don't require Worker headers)\nif (isSimulation) {\n if (process.env.ZUBBL_SIM_VPN !== undefined) {\n geo.privacy.vpn = String(process.env.ZUBBL_SIM_VPN).toLowerCase() === 'true';\n }\n if (process.env.ZUBBL_SIM_HOSTING !== undefined) {\n geo.privacy.hosting = String(process.env.ZUBBL_SIM_HOSTING).toLowerCase() === 'true';\n }\n}\n\nsaveGeoCache(geo);\nconsole.debug('[Zubbl SDK][Geo] Resolved (Cloudflare-native):', geo);\n\nreturn geo;\n}\n\n// -----------------------------------------------------------\n// 🧩 Exported Helpers (updated)\n// -----------------------------------------------------------\nexport function clearGeoCache(): void {\n try {\n if (isBrowser && typeof localStorage !== \"undefined\") {\n localStorage.removeItem(GEO_CACHE_KEY);\n }\n } catch {}\n}\n\nexport async function getGeoHeaders(context?: any): Promise<Record<string, string>> {\n const geo = await getGeoInfo(context);\n return {\n \"X-Zubbl-Geo-Country\": geo.country || \"unknown\",\n \"X-Zubbl-ASN\": geo.asn || \"unknown\",\n \"X-Zubbl-IP\": geo.ip || \"\",\n \"X-Zubbl-Privacy-VPN\": String(geo.privacy?.vpn ?? false),\n \"X-Zubbl-Privacy-Hosting\": String(geo.privacy?.hosting ?? false),\n };\n}\n","// -----------------------------------------------------------\n// 🔐 Secure Signing & Nonce Generator\n// -----------------------------------------------------------\n\nimport crypto from \"crypto\";\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Generate UUIDv4 Nonce\n// -----------------------------------------------------------\nexport function generateNonce(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, c => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n// -----------------------------------------------------------\n// Compute SHA256 HMAC signature\n// -----------------------------------------------------------\nexport async function signPayload(payload: string, secret: string): Promise<string> {\n if (isNode) {\n // ✅ Node.js native HMAC\n return crypto.createHmac(\"sha256\", secret).update(payload).digest(\"hex\");\n }\n\n // ✅ Browser / Worker using WebCrypto\n if (typeof window !== \"undefined\" && window.crypto?.subtle) {\n const key = await window.crypto.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n\n const sig = await window.crypto.subtle.sign(\n \"HMAC\",\n key,\n new TextEncoder().encode(payload)\n );\n\n return Array.from(new Uint8Array(sig))\n .map(b => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n throw new Error(\"No crypto implementation available in this environment\");\n}\n\n// -----------------------------------------------------------\n// Attach signing headers to a request (corrected for SDK-12)\n// -----------------------------------------------------------\nexport function attachSigningHeaders(\n url: string,\n method: string,\n headers: Record<string, string> = {},\n body?: any,\n secretKey?: string | null\n): void {\n const nonce = generateNonce();\n\n // Normalize body to a string before hashing\n const normalizedBody =\n typeof body === \"string\"\n ? body\n : body && typeof body === \"object\"\n ? JSON.stringify(body)\n : \"\";\n\n const bodyHash = normalizedBody\n ? crypto.createHash(\"sha256\").update(normalizedBody).digest(\"hex\")\n : \"\";\n\n // Compute canonical string (deterministic)\n const canonical = `${method.toUpperCase()}\\n${url}\\n${nonce}\\n${bodyHash}`;\n\n // Attach nonce and signature headers (in-place)\n headers[\"X-Zubbl-Nonce\"] = nonce;\n\n if (secretKey) {\n const signature = crypto\n .createHmac(\"sha256\", secretKey)\n .update(canonical)\n .digest(\"hex\");\n headers[\"X-Zubbl-Signature\"] = signature;\n }\n}\n","import crypto from \"crypto\";\n\nexport function sha256Hex(input: string): string {\n return crypto.createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\nexport function hmacSha256Hex(secret: string, input: string): string {\n return crypto.createHmac(\"sha256\", secret).update(input).digest(\"hex\");\n}\n\nexport function makeNonce(): string {\n return crypto.randomUUID();\n}\n\nexport function signCanonical(opts: {\n secret: string;\n method: string;\n pathWithQuery: string;\n nonce: string;\n bodyText: string;\n}): string {\n const bodyHash = sha256Hex(opts.bodyText || \"\");\n const canonical =\n `${opts.method.toUpperCase()}\\n${opts.pathWithQuery}\\n${opts.nonce}\\n${bodyHash}`;\n return hmacSha256Hex(opts.secret, canonical);\n}\n","// src/core/http.ts\n// -----------------------------------------------------------\n// HTTP utility (instance-safe)\n// -----------------------------------------------------------\n\nimport { recordContextSample, getAdaptiveHeaders } from \"./context\";\nimport { attachSigningHeaders } from \"./signing\";\nimport { makeNonce, signCanonical } from \"../utils/signing\";\n\n/**\n * Performs a safe HTTP request with adaptive + signing headers.\n * NOTE: no global getConfig() dependency — caller must provide fully resolved URL + headers.\n */\nexport async function httpRequest(url: string, options: RequestInit = {}): Promise<Response> {\n // 🔧 Default timeout lowered for SDK-12 hardening\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 8000);\n\n try {\n const method = (options.method || \"GET\").toUpperCase();\n\n // Keep original body reference for attachSigningHeaders (if you rely on it)\n const originalBody = options.body;\n\n // Normalise headers to a mutable object\n const headers: Record<string, string> = {\n ...((options.headers as Record<string, string>) || {}),\n ...getAdaptiveHeaders(),\n };\n\n // ✅ Keep your existing signing hook (if it adds auth/bearer/etc)\n // NOTE: This does NOT implement the Worker signature gate by itself (that's below).\n attachSigningHeaders(url, method, headers, originalBody);\n\n // Build finalOptions (must exist before we can safely sign exact bytes)\n const finalOptions: RequestInit = {\n ...options,\n method,\n headers,\n signal: controller.signal,\n };\n\n // ---------------------------------------------------------\n // ZUBBL: Worker signature gate (nonce + HMAC signature)\n // ---------------------------------------------------------\n // Worker expects:\n // canonical = METHOD \\n PATH+QUERY \\n NONCE \\n SHA256(bodyText)\n // headers: X-Zubbl-Nonce, X-Zubbl-Signature\n //\n // This is \"Option B\": verify signature + nonce replay protection.\n // ---------------------------------------------------------\n\n const apiKey =\n (headers[\"Authorization\"] || headers[\"authorization\"] || \"\")\n .replace(/^Bearer\\s+/i, \"\")\n .trim();\n\n const signingSecret =\n ((headers as any)[\"X-Zubbl-Signing-Secret\"] as string | undefined)?.trim() || \"\";\n\n if (!apiKey) {\n throw new Error(\"Missing API key (Authorization: Bearer ...) — cannot send requests\");\n }\n\n if (!signingSecret) {\n throw new Error(\"Missing signing secret — cannot sign requests\");\n }\n\n // We must sign the exact bytes we send.\n // If body is an object, stringify it BEFORE signing AND BEFORE sending.\n let bodyText = \"\";\n if (![\"GET\", \"HEAD\"].includes(method)) {\n const b: any = (finalOptions as any).body;\n\n if (b == null) bodyText = \"\";\n else if (typeof b === \"string\") bodyText = b;\n else bodyText = JSON.stringify(b);\n\n // Ensure fetch sends the exact signed string\n (finalOptions as any).body = bodyText;\n }\n\n // Canonical URL must match Worker logic: pathname + search\n const u = new URL(url);\n const pathWithQuery = `${u.pathname}${u.search}`;\n\n const nonce = makeNonce();\n const signature = signCanonical({\n secret: signingSecret,\n method,\n pathWithQuery,\n nonce,\n bodyText,\n });\n\n // Attach signing headers (ensure headers object is mutable)\n (finalOptions.headers as any) = (finalOptions.headers || {}) as any;\n (finalOptions.headers as any)[\"X-Zubbl-Nonce\"] = nonce;\n (finalOptions.headers as any)[\"X-Zubbl-Signature\"] = signature;\n\n // 🔒 Never send the signing secret over the wire (internal-only)\n delete (finalOptions.headers as any)[\"X-Zubbl-Signing-Secret\"];\n\n // Record adaptive context sample (keep your existing behaviour)\n recordContextSample(\"/http\", \"GET\", 200, 123);\n\n const response = await fetch(url, finalOptions);\n\n if (!response.ok && response.status !== 429) {\n let extra = \"\";\n try {\n extra = await response.clone().text();\n if (extra.length > 200) extra = extra.slice(0, 200) + \"...\";\n } catch {}\n console.warn(\n `[Zubbl SDK][HTTP] ${response.status} on ${url}${extra ? ` — ${extra}` : \"\"}`\n );\n }\n\n return response;\n } catch (err: any) {\n console.error(\"[Zubbl SDK][HTTP] Request failed:\", err?.message);\n throw err;\n } finally {\n clearTimeout(timeout);\n }\n}\n","\n\n// src/features/identifyUser.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe identifyUser feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\nconst USER_CACHE_KEY = \"external_user_id\";\nconst USER_TTL = 24 * 60 * 60; // 24h\n\nexport async function identifyUserFeature(\n store: any,\n { email, name }: { email: string; name?: string }\n) {\n if (!email) throw new Error(\"email is required\");\n\n const config = store.get();\n const storage = createStorage();\n\n // ✅ Determine override identity (prefer config.identity which SIM sets)\n const cfgIdentity = (config as any)?.identity;\n const storeIdentity = (store as any)?.identity;\n\n const overrideEnabled =\n (cfgIdentity && cfgIdentity.override === true) ||\n (storeIdentity && storeIdentity.override === true);\n\n const overrideId = overrideEnabled\n ? (cfgIdentity?.id ||\n storeIdentity?.id ||\n (store as any)?.externalUserId ||\n (store as any)?.userId ||\n undefined)\n : undefined;\n\n // Check cache (skip cache when override is enabled, we must honour overrideId)\n if (!overrideId) {\n const cached = storage.get<{ id: string }>(USER_CACHE_KEY);\n if (cached?.id) {\n return { external_user_id: cached.id, cached: true };\n }\n }\n\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use per-instance config store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"Content-Type\": \"application/json\",\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // ✅ If SIM/consumer provided an override external user ID, call the explicit endpoint\n const identifyUrl = overrideId\n ? `${config.baseUrl}/sdk/identify/${encodeURIComponent(String(overrideId))}`\n : `${config.baseUrl}/sdk/identify`;\n\n const resp = await httpRequest(identifyUrl, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ email, name }),\n });\n\n const data = await resp.json().catch(() => ({}));\n const { external_user_id } = data;\n\n if (!external_user_id) {\n throw new Error(\"Backend did not return external_user_id\");\n }\n\n storage.set(USER_CACHE_KEY, { id: external_user_id }, USER_TTL);\n return { external_user_id, cached: false };\n}\n","// src/features/getTiles.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe getTiles feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\n\nconst TILE_CACHE_KEY = \"tiles_cache\";\nconst TILE_TTL_DEFAULT = 10 * 60; // 10 min\n\ninterface TileCacheEntry {\n data: any;\n etag?: string;\n expiresAt: number;\n}\n\nexport async function getTilesFeature(\n store: any,\n { external_user_id, app_id = null, ttlSeconds = TILE_TTL_DEFAULT }: any\n) {\n const config = store.get();\n const storage = createStorage();\n\n const cached = storage.get<TileCacheEntry>(TILE_CACHE_KEY);\n const isFresh = cached && cached.expiresAt > Date.now();\n\n if (isFresh) {\n backgroundRefresh(store, external_user_id, app_id, ttlSeconds);\n return { data: cached.data, fromCache: true };\n }\n\n try {\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use instance store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // Modern endpoint: POST /api/sdk/policies with body (per architecture docs)\nconst payload = {\n tenant_id: config.tenantId,\n app_id: app_id || config.appId!,\n external_user_id,\n};\n\nconst resp = await httpRequest(`${config.baseUrl.replace(/\\/$/, \"\")}/sdk/policies`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n});\n\n if (resp.status === 304 && cached?.data) {\n cached.expiresAt = Date.now() + ttlSeconds * 1000;\n storage.set(TILE_CACHE_KEY, cached, ttlSeconds);\n return { data: cached.data, fromCache: true, status: 304 };\n }\n\n const data = await resp.json();\n console.log('[DEBUG getTiles] Raw tiles response:', JSON.stringify(data, null, 2)); \n const etag = resp.headers.get(\"ETag\") || undefined;\n\n const entry: TileCacheEntry = {\n data,\n etag,\n expiresAt: Date.now() + ttlSeconds * 1000,\n };\n storage.set(TILE_CACHE_KEY, entry, ttlSeconds);\n\n return { data, fromCache: false, status: resp.status };\n } catch (err) {\n if (cached?.data) {\n return { data: cached.data, fromCache: true, error: String(err) };\n }\n throw err;\n }\n}\n\nasync function backgroundRefresh(store: any, external_user_id: string, app_id: string | null, ttlSeconds: number) {\n try {\n await getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n } catch {\n // Silent background failure\n }\n}\n","// src/client.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Final Instance-based Client (Feature Delegation)\n// -----------------------------------------------------------\n\nimport * as ConfigModule from \"./core/config\";\nimport { createStorage } from \"./core/storage\";\nimport { getGeoInfo } from \"./core/geo\";\nimport { httpRequest } from \"./core/http\"; // ✅ ADD THIS\n\n// Feature modules\nimport { identifyUserFeature } from \"./features/identifyUser\";\nimport { getTilesFeature } from \"./features/getTiles\";\n\nexport type ZubblConfig = {\n apiKey: string;\n signingSecret: string;\n tenantId: string;\n appId: string;\n baseUrl?: string;\n appBaseUrl?: string | null;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n};\n\n\n/**\n * Creates a self-contained, instance-based Zubbl client.\n * Each instance owns its own config store and initialization state.\n */\nexport function createZubblClient(cfg: ZubblConfig) {\n const store = ConfigModule.createConfigStore();\n const storage = createStorage();\n let initialized = false;\n\n async function init() {\n if (initialized) return;\n\n // ✅ Validate UUIDs before initializing\n const UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n if (!UUID_PATTERN.test(cfg.tenantId)) {\n throw new Error(`[Zubbl SDK] Invalid tenantId: expected UUID, got \"${cfg.tenantId}\"`);\n }\n\n if (!UUID_PATTERN.test(cfg.appId)) {\n throw new Error(`[Zubbl SDK] Invalid appId: expected UUID, got \"${cfg.appId}\"`);\n }\n\n // Initialize per-client config\n store.init(cfg);\n\n // Optional: GEO bootstrap\n try {\n const geo = await getGeoInfo();\n console.log(`[Zubbl SDK] 🌍 GEO detected: ${geo.country} (ASN ${geo.asn || \"?\"})`);\n } catch (err: any) {\n console.warn(\"[Zubbl SDK] GEO init failed:\", err?.message);\n }\n\n initialized = true;\n }\n\n function assertInitialized() {\n if (!initialized) {\n throw new Error(\"Zubbl client not initialized — call client.init() first\");\n }\n }\n\n // ---------------------------------------------------------\n // User + Tile Operations (delegated to feature modules)\n // ---------------------------------------------------------\n async function identifyUser({ email, name }: { email: string; name?: string }) {\n assertInitialized();\n return identifyUserFeature(store, { email, name });\n }\n\n async function getTiles({\n external_user_id,\n app_id = null,\n ttlSeconds,\n }: {\n external_user_id: string;\n app_id?: string | null;\n ttlSeconds?: number;\n }) {\n assertInitialized();\n return getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n }\n\n // ---------------------------------------------------------\n // Enforcement API (kept inline)\n // ---------------------------------------------------------\n async function enforce({\n external_user_id,\n app_id = null,\n }: {\n external_user_id: string;\n app_id?: string | null;\n }) {\n assertInitialized();\n\n const config = store.get();\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n });\n\n // ✅ IMPORTANT: use signed httpRequest so Worker gate passes\n const url = `${config.baseUrl?.replace(/\\/$/, \"\")}/sdk/test-enforcement`;\n const resp = await httpRequest(url, {\n method: \"POST\",\n headers,\n });\n\n const json = await resp.json().catch(() => ({}));\n\n const decision =\n resp.status === 403 || resp.status === 429 ? \"block\" : resp.ok ? \"allow\" : \"error\";\n\n return {\n decision,\n status: resp.status,\n allowed: decision === \"allow\",\n blocked: decision === \"block\",\n data: json,\n };\n }\n\n async function testEndpoint({\n external_user_id,\n endpoint,\n method = \"POST\",\n body = {},\n }: {\n external_user_id: string;\n endpoint: string;\n method?: string;\n body?: any;\n }) {\n assertInitialized();\n\n const config = store.get();\n const base = config.appBaseUrl?.replace(/\\/$/, \"\");\n\n if (!base) {\n throw new Error(\"[Zubbl SDK] appBaseUrl is required to run endpoint tests\");\n }\n\n if (!endpoint || !endpoint.startsWith(\"/\")) {\n throw new Error(\"[Zubbl SDK] endpoint must start with /\");\n }\n\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n \"X-Zubbl-Test-Mode\": \"live\",\n });\n\n const resp = await httpRequest(`${base}${endpoint}`, {\n method: method.toUpperCase(),\n headers,\n body: [\"GET\", \"HEAD\"].includes(method.toUpperCase()) ? undefined : body,\n });\n\n const text = await resp.text().catch(() => \"\");\n let data: any = text;\n\n try {\n data = text ? JSON.parse(text) : {};\n } catch {}\n\n const decision =\n resp.status === 403 || resp.status === 429 ? \"block\" : resp.ok ? \"allow\" : \"error\";\n\n return {\n decision,\n status: resp.status,\n allowed: decision === \"allow\",\n blocked: decision === \"block\",\n endpoint,\n method: method.toUpperCase(),\n data,\n };\n }\n\n function createExpressTestHandler() {\n return async function zubblExpressTestHandler(req: any, res: any) {\n try {\n const endpoint = String(req.query?.endpoint || \"\").trim();\n const method = String(req.query?.method || \"POST\").toUpperCase();\n const html = String(req.query?.html || \"\").toLowerCase() === \"true\";\n const external_user_id = String(\n req.query?.external_user_id ||\n req.headers?.[\"x-external-user-id\"] ||\n \"zubbl-test-user\"\n ).trim();\n\n const result = await testEndpoint({\n external_user_id,\n endpoint,\n method,\n body: {},\n });\n\n if (html) {\n return res\n .status(200)\n .send(`<!doctype html>\n<html>\n <head>\n <title>Zubbl live endpoint test</title>\n <style>\n body { font-family: system-ui, sans-serif; background: #0b1020; color: #fff; padding: 32px; }\n pre { background: #111827; padding: 16px; border-radius: 12px; overflow: auto; }\n .ok { color: #86efac; }\n .block { color: #fca5a5; }\n </style>\n </head>\n <body>\n <h1>Zubbl live endpoint test</h1>\n <p>Endpoint: <code>${result.method} ${result.endpoint}</code></p>\n <p>Status: <strong>${result.status}</strong></p>\n <p>Decision: <strong class=\"${result.blocked ? \"block\" : \"ok\"}\">${result.decision}</strong></p>\n <pre>${JSON.stringify(result, null, 2)}</pre>\n </body>\n</html>`);\n }\n\n return res.status(200).json(result);\n } catch (err: any) {\n const payload = {\n error: err?.message || \"Zubbl test failed\",\n };\n\n if (String(req.query?.html || \"\").toLowerCase() === \"true\") {\n return res.status(500).send(`<h1>Zubbl test failed</h1><pre>${payload.error}</pre>`);\n }\n\n return res.status(500).json(payload);\n }\n };\n }\n\n // ---------------------------------------------------------\n // Public API\n // ---------------------------------------------------------\n return {\n init,\n identifyUser,\n getTiles,\n enforce,\n testEndpoint,\n createExpressTestHandler,\n storage,\n };\n}\n","// src/index.ts\n// -----------------------------------------------------------\n// Zubbl SDK Entry Point — Public Exports\n// -----------------------------------------------------------\n\n// Core factory + environment\nexport * from \"./core/config\";\nexport * from \"./core/context\";\nexport * from \"./core/storage\";\nexport * from \"./core/geo\";\n\n// Avoid duplicate export of ZubblConfig\nexport {\n createZubblClient, // 🔁 change this if your client.ts exports something else\n} from \"./client\";\n\n// Feature modules (optional direct access)\nexport * from \"./features/identifyUser\";\nexport * from \"./features/getTiles\";\n\nconsole.log(\"[Zubbl SDK] ✅ Entry point loaded\");\n"],"names":["ConfigModule.createConfigStore"],"mappings":"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"}
@@ -32,6 +32,7 @@ function createConfigStore(initial) {
32
32
  tenantId: null,
33
33
  appId: null,
34
34
  baseUrl: "https://api.zubbl.com/api",
35
+ appBaseUrl: null,
35
36
  injectWorkerHeaders: false,
36
37
  workerSecret: null,
37
38
  ...initial,
@@ -722,7 +723,101 @@ function createZubblClient(cfg) {
722
723
  headers,
723
724
  });
724
725
  const json = await resp.json().catch(() => ({}));
725
- return { decision: "allow", status: resp.status, data: json };
726
+ const decision = resp.status === 403 || resp.status === 429 ? "block" : resp.ok ? "allow" : "error";
727
+ return {
728
+ decision,
729
+ status: resp.status,
730
+ allowed: decision === "allow",
731
+ blocked: decision === "block",
732
+ data: json,
733
+ };
734
+ }
735
+ async function testEndpoint({ external_user_id, endpoint, method = "POST", body = {}, }) {
736
+ assertInitialized();
737
+ const config = store.get();
738
+ const base = config.appBaseUrl?.replace(/\/$/, "");
739
+ if (!base) {
740
+ throw new Error("[Zubbl SDK] appBaseUrl is required to run endpoint tests");
741
+ }
742
+ if (!endpoint || !endpoint.startsWith("/")) {
743
+ throw new Error("[Zubbl SDK] endpoint must start with /");
744
+ }
745
+ const headers = store.buildHeaders({
746
+ "X-External-User-Id": external_user_id,
747
+ "X-Zubbl-Test-Mode": "live",
748
+ });
749
+ const resp = await httpRequest(`${base}${endpoint}`, {
750
+ method: method.toUpperCase(),
751
+ headers,
752
+ body: ["GET", "HEAD"].includes(method.toUpperCase()) ? undefined : body,
753
+ });
754
+ const text = await resp.text().catch(() => "");
755
+ let data = text;
756
+ try {
757
+ data = text ? JSON.parse(text) : {};
758
+ }
759
+ catch { }
760
+ const decision = resp.status === 403 || resp.status === 429 ? "block" : resp.ok ? "allow" : "error";
761
+ return {
762
+ decision,
763
+ status: resp.status,
764
+ allowed: decision === "allow",
765
+ blocked: decision === "block",
766
+ endpoint,
767
+ method: method.toUpperCase(),
768
+ data,
769
+ };
770
+ }
771
+ function createExpressTestHandler() {
772
+ return async function zubblExpressTestHandler(req, res) {
773
+ try {
774
+ const endpoint = String(req.query?.endpoint || "").trim();
775
+ const method = String(req.query?.method || "POST").toUpperCase();
776
+ const html = String(req.query?.html || "").toLowerCase() === "true";
777
+ const external_user_id = String(req.query?.external_user_id ||
778
+ req.headers?.["x-external-user-id"] ||
779
+ "zubbl-test-user").trim();
780
+ const result = await testEndpoint({
781
+ external_user_id,
782
+ endpoint,
783
+ method,
784
+ body: {},
785
+ });
786
+ if (html) {
787
+ return res
788
+ .status(200)
789
+ .send(`<!doctype html>
790
+ <html>
791
+ <head>
792
+ <title>Zubbl live endpoint test</title>
793
+ <style>
794
+ body { font-family: system-ui, sans-serif; background: #0b1020; color: #fff; padding: 32px; }
795
+ pre { background: #111827; padding: 16px; border-radius: 12px; overflow: auto; }
796
+ .ok { color: #86efac; }
797
+ .block { color: #fca5a5; }
798
+ </style>
799
+ </head>
800
+ <body>
801
+ <h1>Zubbl live endpoint test</h1>
802
+ <p>Endpoint: <code>${result.method} ${result.endpoint}</code></p>
803
+ <p>Status: <strong>${result.status}</strong></p>
804
+ <p>Decision: <strong class="${result.blocked ? "block" : "ok"}">${result.decision}</strong></p>
805
+ <pre>${JSON.stringify(result, null, 2)}</pre>
806
+ </body>
807
+ </html>`);
808
+ }
809
+ return res.status(200).json(result);
810
+ }
811
+ catch (err) {
812
+ const payload = {
813
+ error: err?.message || "Zubbl test failed",
814
+ };
815
+ if (String(req.query?.html || "").toLowerCase() === "true") {
816
+ return res.status(500).send(`<h1>Zubbl test failed</h1><pre>${payload.error}</pre>`);
817
+ }
818
+ return res.status(500).json(payload);
819
+ }
820
+ };
726
821
  }
727
822
  // ---------------------------------------------------------
728
823
  // Public API
@@ -732,6 +827,8 @@ function createZubblClient(cfg) {
732
827
  identifyUser,
733
828
  getTiles,
734
829
  enforce,
830
+ testEndpoint,
831
+ createExpressTestHandler,
735
832
  storage,
736
833
  };
737
834
  }
@@ -1 +1 @@
1
- {"version":3,"file":"zubbl-sdk.esm.js","sources":["../src/core/config.ts","../src/core/context.ts","../src/core/storage.ts","../src/core/geo.ts","../src/core/signing.ts","../src/utils/signing.ts","../src/core/http.ts","../src/features/identifyUser.ts","../src/features/getTiles.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["// src/core/config.ts\n// -----------------------------------------------------------\n// Universal environment detection + SDK configuration\n// -----------------------------------------------------------\n\nexport const isBrowser =\n typeof window !== \"undefined\" && typeof window.document !== \"undefined\";\n\nexport const isNode =\n typeof process !== \"undefined\" &&\n !!process.versions?.node &&\n !isBrowser;\n\nexport const isWorker =\n typeof self !== \"undefined\" &&\n typeof (self as any).importScripts === \"function\" &&\n !isNode;\n\n// -----------------------------------------------------------\n// Config store factory (no module-scoped state)\n// -----------------------------------------------------------\n\nexport interface ZubblConfig {\n apiKey: string | null;\n signingSecret: string | null; // ✅ used for HMAC signing (never sent over the wire)\n tenantId: string | null;\n appId: string | null;\n baseUrl: string;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n}\n\nfunction assertBrowserSafety(cfg: ZubblConfig) {\n if (isBrowser || isWorker) {\n const key = cfg.apiKey ?? \"\";\n const looksSecret = key.startsWith(\"sk_\") || key.length > 40;\n if (looksSecret) {\n throw new Error(\n \"[Zubbl SDK] Secret or server key detected in browser environment. \" +\n \"Use a public SDK key instead (prefix pk_).\"\n );\n }\n }\n}\n\n/**\n * Creates an isolated configuration store.\n * Each ZubblClient instance owns its own store.\n */\nexport function createConfigStore(initial?: Partial<ZubblConfig>) {\n let current: ZubblConfig = {\n apiKey: null,\n signingSecret: null,\n tenantId: null,\n appId: null,\n baseUrl: \"https://api.zubbl.com/api\",\n injectWorkerHeaders: false,\n workerSecret: null,\n ...initial,\n };\n\n function init(partial: Partial<ZubblConfig>) {\n current = { ...current, ...partial };\n assertBrowserSafety(current);\n }\n\n function get(): Readonly<ZubblConfig> {\n return current;\n }\n\n function buildHeaders(extra: Record<string, string> = {}): Record<string, string> {\n if (!current.tenantId || !current.appId) {\n throw new Error(\"[Zubbl SDK] Not initialized – call init() first.\");\n }\n\n const headers: Record<string, string> = {\n \"X-Tenant-Id\": current.tenantId,\n \"X-App-Id\": current.appId,\n \"Content-Type\": \"application/json\",\n ...extra,\n };\n\n if (current.apiKey) {\n headers.Authorization = `Bearer ${current.apiKey}`;\n }\n\n // ✅ Internal-only: used by httpRequest() to compute signature, then deleted before fetch\n if (current.signingSecret) {\n headers[\"X-Zubbl-Signing-Secret\"] = current.signingSecret;\n } else if (current.apiKey) {\n // If you're using API-key auth, you must also provide signingSecret for Worker-gated endpoints\n throw new Error(\"[Zubbl SDK] Missing signingSecret (required for signed requests)\");\n }\n\n return headers;\n }\n\n return { init, get, buildHeaders };\n}\n\n","// src/core/context.ts\n// -----------------------------------------------------------\n// Adaptive Context Engine — Geo + Stability Enrichment + Persistence\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types\n// -----------------------------------------------------------\ninterface ContextSample {\n path: string;\n method: string;\n ts: number;\n status: number;\n latency: number;\n}\n\ninterface AdaptiveState {\n routes: ContextSample[];\n geo: string;\n stability: number;\n lastGeoChange: number;\n}\n\nconst MAX_HISTORY = 100;\nconst CACHE_KEY = \"zubbl-stability\";\n\nlet state: AdaptiveState = loadStability() ?? {\n routes: [],\n geo: \"unknown\",\n stability: 1.0,\n lastGeoChange: Date.now(),\n};\n\n// -----------------------------------------------------------\n// 💾 Persistence Helpers\n// -----------------------------------------------------------\nfunction loadStability(): AdaptiveState | null {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(CACHE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (!parsed.geo || !parsed.stability) return null;\n return { ...parsed, routes: [] };\n } catch {\n return null;\n }\n}\n\nfunction saveStability() {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n try {\n const payload = {\n geo: state.geo,\n stability: state.stability,\n lastGeoChange: state.lastGeoChange,\n };\n localStorage.setItem(CACHE_KEY, JSON.stringify(payload));\n } catch {\n /* ignore */\n }\n}\n\n// -----------------------------------------------------------\n// 🌍 Geo Detection (Node, Browser, Worker)\n// -----------------------------------------------------------\nexport function detectGeo(): string {\n try {\n if (isBrowser && typeof window !== \"undefined\" && window.navigator?.language) {\n return window.navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isWorker && typeof self !== \"undefined\" && (self as any).navigator?.language) {\n return (self as any).navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isNode && typeof process !== \"undefined\") {\n const envGeo = process.env.ZUBBL_GEO || process.env.GEO;\n if (envGeo && /^[A-Z]{2}$/i.test(envGeo)) return envGeo.toUpperCase();\n return \"GB\";\n }\n\n return \"unknown\";\n } catch (err) {\n console.warn(\"[Zubbl SDK][Geo Detect] Failed:\", err);\n return \"unknown\";\n }\n}\n\n// -----------------------------------------------------------\n// 🧭 Update Geo & Stability (with persistence)\n// -----------------------------------------------------------\nexport function updateGeo(geoHint?: string) {\n const newGeo = geoHint || detectGeo();\n if (newGeo !== state.geo) {\n const now = Date.now();\n const elapsed = (now - state.lastGeoChange) / 1000;\n state.stability = Math.max(0.5, Math.min(1.0, elapsed / 3600));\n state.geo = newGeo;\n state.lastGeoChange = now;\n saveStability();\n } else {\n state.stability = Math.min(1.0, state.stability + 0.01);\n saveStability();\n }\n}\n\n// -----------------------------------------------------------\n// 🧮 Record Context Samples\n// -----------------------------------------------------------\nexport function recordContextSample(\n path: string,\n method: string,\n status: number,\n latency: number\n) {\n state.routes.push({ path, method, ts: Date.now(), status, latency });\n if (state.routes.length > MAX_HISTORY) state.routes.shift();\n updateGeo(); // auto-refresh geo info\n}\n\n// -----------------------------------------------------------\n// 📦 Get Adaptive Headers\n// -----------------------------------------------------------\nexport function getAdaptiveHeaders(): Record<string, string> {\n const currentGeo = detectGeo();\n updateGeo(currentGeo);\n\n const summary = btoa(\n JSON.stringify({\n env: isNode ? \"node\" : isBrowser ? \"browser\" : \"worker\",\n routeCount: state.routes.length,\n lastGeo: state.geo,\n avgLatency:\n state.routes.reduce((a, b) => a + b.latency, 0) /\n Math.max(1, state.routes.length),\n })\n );\n\n return {\n \"X-Zubbl-Context-Summary\": summary,\n \"X-Zubbl-Geo-Stability\": `${state.geo}/${state.stability.toFixed(2)}`,\n };\n}\n\n// -----------------------------------------------------------\n// 🌍 Initialize Geo Context Immediately\n// -----------------------------------------------------------\nupdateGeo(process.env.ZUBBL_GEO);\n\n","// src/core/storage.ts\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// Generic storage interface\nexport interface IStorage {\n get<T>(key: string): T | null;\n set<T>(key: string, value: T, ttlSeconds?: number): void;\n remove(key: string): void;\n}\n\n// ------------------------------------------------------\n// Node (in-memory) implementation\n// ------------------------------------------------------\n\nclass NodeStorage implements IStorage {\n private store = new Map<string, { value: any; expiresAt?: number }>();\n\n get<T>(key: string): T | null {\n const entry = this.store.get(key);\n if (!entry) return null;\n if (entry.expiresAt && entry.expiresAt < Date.now()) {\n this.store.delete(key);\n return null;\n }\n return entry.value as T;\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n this.store.set(key, { value, expiresAt });\n }\n\n remove(key: string): void {\n this.store.delete(key);\n }\n}\n\n// ------------------------------------------------------\n// Browser (localStorage) implementation\n// ------------------------------------------------------\n\nclass BrowserStorage implements IStorage {\n private prefix = \"zubbl_sdk_\";\n\n get<T>(key: string): T | null {\n try {\n const raw = localStorage.getItem(this.prefix + key);\n if (!raw) return null;\n const { value, expiresAt } = JSON.parse(raw);\n if (expiresAt && expiresAt < Date.now()) {\n localStorage.removeItem(this.prefix + key);\n return null;\n }\n return value as T;\n } catch {\n return null;\n }\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n try {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n localStorage.setItem(\n this.prefix + key,\n JSON.stringify({ value, expiresAt })\n );\n } catch (err) {\n // localStorage quota exceeded → silently ignore\n console.warn(\"[Zubbl SDK][Storage] Failed to persist item:\", err);\n }\n }\n\n remove(key: string): void {\n localStorage.removeItem(this.prefix + key);\n }\n}\n\n// ------------------------------------------------------\n// Factory\n// ------------------------------------------------------\n\nexport function createStorage(): IStorage {\n if (isNode) return new NodeStorage();\n if (isBrowser) return new BrowserStorage();\n\n // Fallback: safe no-op storage for tests / fake environments\n return {\n get: () => null,\n set: () => {},\n remove: () => {},\n };\n}\n\n","// -----------------------------------------------------------\n// 🌍 Zubbl Geo Engine — Cloudflare-Native Only (No External Providers)\n// -----------------------------------------------------------\n// Uses Worker-provided request.cf + headers. Free on all plans.\n// Sim/CLI fallback to avoid noise.\n// Aligns with Zubbl GEO Enforcement Whitepaper (Worker layer).\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types (unchanged)\n// -----------------------------------------------------------\nexport interface GeoPrivacy {\n vpn: boolean;\n hosting: boolean;\n}\n\nexport interface GeoInfo {\n ip: string | null;\n country: string;\n asn: string | null;\n privacy: GeoPrivacy;\n}\n\nconst GEO_CACHE_KEY = \"zubbl-geo-cache\";\nconst GEO_TTL_MS = 15 * 60 * 1000; // 15 minutes\n\n// -----------------------------------------------------------\n// 🗃 Cache Helpers (unchanged, browser-only)\n// -----------------------------------------------------------\nfunction loadGeoCache(): GeoInfo | null {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n const raw = localStorage.getItem(GEO_CACHE_KEY);\n if (!raw) return null;\n\n const parsed = JSON.parse(raw) as { data: GeoInfo; timestamp: number };\n if (!parsed.data?.country || Date.now() - parsed.timestamp > GEO_TTL_MS) return null;\n return parsed.data;\n } catch {\n return null;\n }\n}\n\nfunction saveGeoCache(data: GeoInfo): void {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n localStorage.setItem(GEO_CACHE_KEY, JSON.stringify({ data, timestamp: Date.now() }));\n } catch {}\n}\n\n// -----------------------------------------------------------\n// 🧠 Cloudflare-Native Resolver\n// -----------------------------------------------------------\nexport async function getGeoInfo(context: any = {}): Promise<GeoInfo> { // Accept context for Worker/Request\n const cached = loadGeoCache();\n if (cached) return cached;\n\n // Detect sim/CLI (Node runtime, no Worker context)\n const isSimulation = process.env.ZUBBL_SIM_MODE === 'true' || isNode;\n\n // Extract from Worker-provided data (request.cf or enriched headers)\n const headers = context?.request?.headers || new Headers();\n const cf = context?.request?.cf || {}; // request.cf if Worker context available\n\n let country = cf.country || headers.get('CF-IPCountry') || headers.get('X-Zubbl-Geo-Country') || 'XX';\n let asn = cf.asn?.toString() || headers.get('X-Zubbl-ASN') || null;\n let asOrg = cf.asOrganization || headers.get('X-Zubbl-Geo-ASOrg') || null;\n\n// Sim fallback (clean run, no external noise)\nif (isSimulation && country === 'XX') {\n const simCountry =\n process.env.ZUBBL_SIM_COUNTRY ||\n process.env.ZUBBL_SIM_CF_IPCOUNTRY ||\n '';\n\n const simAsn = process.env.ZUBBL_SIM_ASN || '';\n const simAsOrg = process.env.ZUBBL_SIM_ASORG || '';\n\n const finalCountry = simCountry || 'GB';\n const finalAsn = simAsn || '2856';\n const finalAsOrg = simAsOrg || 'British Telecommunications';\n\n console.debug(\n `[Zubbl SDK][Geo][SIM] No Cloudflare data; using SIM defaults: country=${finalCountry}, asn=${finalAsn}`\n );\n\n country = finalCountry;\n asn = finalAsn;\n asOrg = finalAsOrg;\n}\n\nconst geo: GeoInfo = {\n ip: cf.clientIp || headers.get('CF-Connecting-IP') || null,\n country,\n asn,\n privacy: {\n vpn: false,\n hosting: false,\n },\n};\n\n// Optional: Worker can set privacy flags via headers (e.g., X-Zubbl-Privacy-VPN)\ngeo.privacy.vpn = headers.get('X-Zubbl-Privacy-VPN') === 'true';\ngeo.privacy.hosting = headers.get('X-Zubbl-Privacy-Hosting') === 'true';\n\n// SIM env overrides (so Node simulations don't require Worker headers)\nif (isSimulation) {\n if (process.env.ZUBBL_SIM_VPN !== undefined) {\n geo.privacy.vpn = String(process.env.ZUBBL_SIM_VPN).toLowerCase() === 'true';\n }\n if (process.env.ZUBBL_SIM_HOSTING !== undefined) {\n geo.privacy.hosting = String(process.env.ZUBBL_SIM_HOSTING).toLowerCase() === 'true';\n }\n}\n\nsaveGeoCache(geo);\nconsole.debug('[Zubbl SDK][Geo] Resolved (Cloudflare-native):', geo);\n\nreturn geo;\n}\n\n// -----------------------------------------------------------\n// 🧩 Exported Helpers (updated)\n// -----------------------------------------------------------\nexport function clearGeoCache(): void {\n try {\n if (isBrowser && typeof localStorage !== \"undefined\") {\n localStorage.removeItem(GEO_CACHE_KEY);\n }\n } catch {}\n}\n\nexport async function getGeoHeaders(context?: any): Promise<Record<string, string>> {\n const geo = await getGeoInfo(context);\n return {\n \"X-Zubbl-Geo-Country\": geo.country || \"unknown\",\n \"X-Zubbl-ASN\": geo.asn || \"unknown\",\n \"X-Zubbl-IP\": geo.ip || \"\",\n \"X-Zubbl-Privacy-VPN\": String(geo.privacy?.vpn ?? false),\n \"X-Zubbl-Privacy-Hosting\": String(geo.privacy?.hosting ?? false),\n };\n}\n","// -----------------------------------------------------------\n// 🔐 Secure Signing & Nonce Generator\n// -----------------------------------------------------------\n\nimport crypto from \"crypto\";\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Generate UUIDv4 Nonce\n// -----------------------------------------------------------\nexport function generateNonce(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, c => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n// -----------------------------------------------------------\n// Compute SHA256 HMAC signature\n// -----------------------------------------------------------\nexport async function signPayload(payload: string, secret: string): Promise<string> {\n if (isNode) {\n // ✅ Node.js native HMAC\n return crypto.createHmac(\"sha256\", secret).update(payload).digest(\"hex\");\n }\n\n // ✅ Browser / Worker using WebCrypto\n if (typeof window !== \"undefined\" && window.crypto?.subtle) {\n const key = await window.crypto.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n\n const sig = await window.crypto.subtle.sign(\n \"HMAC\",\n key,\n new TextEncoder().encode(payload)\n );\n\n return Array.from(new Uint8Array(sig))\n .map(b => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n throw new Error(\"No crypto implementation available in this environment\");\n}\n\n// -----------------------------------------------------------\n// Attach signing headers to a request (corrected for SDK-12)\n// -----------------------------------------------------------\nexport function attachSigningHeaders(\n url: string,\n method: string,\n headers: Record<string, string> = {},\n body?: any,\n secretKey?: string | null\n): void {\n const nonce = generateNonce();\n\n // Normalize body to a string before hashing\n const normalizedBody =\n typeof body === \"string\"\n ? body\n : body && typeof body === \"object\"\n ? JSON.stringify(body)\n : \"\";\n\n const bodyHash = normalizedBody\n ? crypto.createHash(\"sha256\").update(normalizedBody).digest(\"hex\")\n : \"\";\n\n // Compute canonical string (deterministic)\n const canonical = `${method.toUpperCase()}\\n${url}\\n${nonce}\\n${bodyHash}`;\n\n // Attach nonce and signature headers (in-place)\n headers[\"X-Zubbl-Nonce\"] = nonce;\n\n if (secretKey) {\n const signature = crypto\n .createHmac(\"sha256\", secretKey)\n .update(canonical)\n .digest(\"hex\");\n headers[\"X-Zubbl-Signature\"] = signature;\n }\n}\n","import crypto from \"crypto\";\n\nexport function sha256Hex(input: string): string {\n return crypto.createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\nexport function hmacSha256Hex(secret: string, input: string): string {\n return crypto.createHmac(\"sha256\", secret).update(input).digest(\"hex\");\n}\n\nexport function makeNonce(): string {\n return crypto.randomUUID();\n}\n\nexport function signCanonical(opts: {\n secret: string;\n method: string;\n pathWithQuery: string;\n nonce: string;\n bodyText: string;\n}): string {\n const bodyHash = sha256Hex(opts.bodyText || \"\");\n const canonical =\n `${opts.method.toUpperCase()}\\n${opts.pathWithQuery}\\n${opts.nonce}\\n${bodyHash}`;\n return hmacSha256Hex(opts.secret, canonical);\n}\n","// src/core/http.ts\n// -----------------------------------------------------------\n// HTTP utility (instance-safe)\n// -----------------------------------------------------------\n\nimport { recordContextSample, getAdaptiveHeaders } from \"./context\";\nimport { attachSigningHeaders } from \"./signing\";\nimport { makeNonce, signCanonical } from \"../utils/signing\";\n\n/**\n * Performs a safe HTTP request with adaptive + signing headers.\n * NOTE: no global getConfig() dependency — caller must provide fully resolved URL + headers.\n */\nexport async function httpRequest(url: string, options: RequestInit = {}): Promise<Response> {\n // 🔧 Default timeout lowered for SDK-12 hardening\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 8000);\n\n try {\n const method = (options.method || \"GET\").toUpperCase();\n\n // Keep original body reference for attachSigningHeaders (if you rely on it)\n const originalBody = options.body;\n\n // Normalise headers to a mutable object\n const headers: Record<string, string> = {\n ...((options.headers as Record<string, string>) || {}),\n ...getAdaptiveHeaders(),\n };\n\n // ✅ Keep your existing signing hook (if it adds auth/bearer/etc)\n // NOTE: This does NOT implement the Worker signature gate by itself (that's below).\n attachSigningHeaders(url, method, headers, originalBody);\n\n // Build finalOptions (must exist before we can safely sign exact bytes)\n const finalOptions: RequestInit = {\n ...options,\n method,\n headers,\n signal: controller.signal,\n };\n\n // ---------------------------------------------------------\n // ZUBBL: Worker signature gate (nonce + HMAC signature)\n // ---------------------------------------------------------\n // Worker expects:\n // canonical = METHOD \\n PATH+QUERY \\n NONCE \\n SHA256(bodyText)\n // headers: X-Zubbl-Nonce, X-Zubbl-Signature\n //\n // This is \"Option B\": verify signature + nonce replay protection.\n // ---------------------------------------------------------\n\n const apiKey =\n (headers[\"Authorization\"] || headers[\"authorization\"] || \"\")\n .replace(/^Bearer\\s+/i, \"\")\n .trim();\n\n const signingSecret =\n ((headers as any)[\"X-Zubbl-Signing-Secret\"] as string | undefined)?.trim() || \"\";\n\n if (!apiKey) {\n throw new Error(\"Missing API key (Authorization: Bearer ...) — cannot send requests\");\n }\n\n if (!signingSecret) {\n throw new Error(\"Missing signing secret — cannot sign requests\");\n }\n\n // We must sign the exact bytes we send.\n // If body is an object, stringify it BEFORE signing AND BEFORE sending.\n let bodyText = \"\";\n if (![\"GET\", \"HEAD\"].includes(method)) {\n const b: any = (finalOptions as any).body;\n\n if (b == null) bodyText = \"\";\n else if (typeof b === \"string\") bodyText = b;\n else bodyText = JSON.stringify(b);\n\n // Ensure fetch sends the exact signed string\n (finalOptions as any).body = bodyText;\n }\n\n // Canonical URL must match Worker logic: pathname + search\n const u = new URL(url);\n const pathWithQuery = `${u.pathname}${u.search}`;\n\n const nonce = makeNonce();\n const signature = signCanonical({\n secret: signingSecret,\n method,\n pathWithQuery,\n nonce,\n bodyText,\n });\n\n // Attach signing headers (ensure headers object is mutable)\n (finalOptions.headers as any) = (finalOptions.headers || {}) as any;\n (finalOptions.headers as any)[\"X-Zubbl-Nonce\"] = nonce;\n (finalOptions.headers as any)[\"X-Zubbl-Signature\"] = signature;\n\n // 🔒 Never send the signing secret over the wire (internal-only)\n delete (finalOptions.headers as any)[\"X-Zubbl-Signing-Secret\"];\n\n // Record adaptive context sample (keep your existing behaviour)\n recordContextSample(\"/http\", \"GET\", 200, 123);\n\n const response = await fetch(url, finalOptions);\n\n if (!response.ok && response.status !== 429) {\n let extra = \"\";\n try {\n extra = await response.clone().text();\n if (extra.length > 200) extra = extra.slice(0, 200) + \"...\";\n } catch {}\n console.warn(\n `[Zubbl SDK][HTTP] ${response.status} on ${url}${extra ? ` — ${extra}` : \"\"}`\n );\n }\n\n return response;\n } catch (err: any) {\n console.error(\"[Zubbl SDK][HTTP] Request failed:\", err?.message);\n throw err;\n } finally {\n clearTimeout(timeout);\n }\n}\n","\n\n// src/features/identifyUser.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe identifyUser feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\nconst USER_CACHE_KEY = \"external_user_id\";\nconst USER_TTL = 24 * 60 * 60; // 24h\n\nexport async function identifyUserFeature(\n store: any,\n { email, name }: { email: string; name?: string }\n) {\n if (!email) throw new Error(\"email is required\");\n\n const config = store.get();\n const storage = createStorage();\n\n // ✅ Determine override identity (prefer config.identity which SIM sets)\n const cfgIdentity = (config as any)?.identity;\n const storeIdentity = (store as any)?.identity;\n\n const overrideEnabled =\n (cfgIdentity && cfgIdentity.override === true) ||\n (storeIdentity && storeIdentity.override === true);\n\n const overrideId = overrideEnabled\n ? (cfgIdentity?.id ||\n storeIdentity?.id ||\n (store as any)?.externalUserId ||\n (store as any)?.userId ||\n undefined)\n : undefined;\n\n // Check cache (skip cache when override is enabled, we must honour overrideId)\n if (!overrideId) {\n const cached = storage.get<{ id: string }>(USER_CACHE_KEY);\n if (cached?.id) {\n return { external_user_id: cached.id, cached: true };\n }\n }\n\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use per-instance config store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"Content-Type\": \"application/json\",\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // ✅ If SIM/consumer provided an override external user ID, call the explicit endpoint\n const identifyUrl = overrideId\n ? `${config.baseUrl}/sdk/identify/${encodeURIComponent(String(overrideId))}`\n : `${config.baseUrl}/sdk/identify`;\n\n const resp = await httpRequest(identifyUrl, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ email, name }),\n });\n\n const data = await resp.json().catch(() => ({}));\n const { external_user_id } = data;\n\n if (!external_user_id) {\n throw new Error(\"Backend did not return external_user_id\");\n }\n\n storage.set(USER_CACHE_KEY, { id: external_user_id }, USER_TTL);\n return { external_user_id, cached: false };\n}\n","// src/features/getTiles.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe getTiles feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\n\nconst TILE_CACHE_KEY = \"tiles_cache\";\nconst TILE_TTL_DEFAULT = 10 * 60; // 10 min\n\ninterface TileCacheEntry {\n data: any;\n etag?: string;\n expiresAt: number;\n}\n\nexport async function getTilesFeature(\n store: any,\n { external_user_id, app_id = null, ttlSeconds = TILE_TTL_DEFAULT }: any\n) {\n const config = store.get();\n const storage = createStorage();\n\n const cached = storage.get<TileCacheEntry>(TILE_CACHE_KEY);\n const isFresh = cached && cached.expiresAt > Date.now();\n\n if (isFresh) {\n backgroundRefresh(store, external_user_id, app_id, ttlSeconds);\n return { data: cached.data, fromCache: true };\n }\n\n try {\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use instance store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // Modern endpoint: POST /api/sdk/policies with body (per architecture docs)\nconst payload = {\n tenant_id: config.tenantId,\n app_id: app_id || config.appId!,\n external_user_id,\n};\n\nconst resp = await httpRequest(`${config.baseUrl.replace(/\\/$/, \"\")}/sdk/policies`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n});\n\n if (resp.status === 304 && cached?.data) {\n cached.expiresAt = Date.now() + ttlSeconds * 1000;\n storage.set(TILE_CACHE_KEY, cached, ttlSeconds);\n return { data: cached.data, fromCache: true, status: 304 };\n }\n\n const data = await resp.json();\n console.log('[DEBUG getTiles] Raw tiles response:', JSON.stringify(data, null, 2)); \n const etag = resp.headers.get(\"ETag\") || undefined;\n\n const entry: TileCacheEntry = {\n data,\n etag,\n expiresAt: Date.now() + ttlSeconds * 1000,\n };\n storage.set(TILE_CACHE_KEY, entry, ttlSeconds);\n\n return { data, fromCache: false, status: resp.status };\n } catch (err) {\n if (cached?.data) {\n return { data: cached.data, fromCache: true, error: String(err) };\n }\n throw err;\n }\n}\n\nasync function backgroundRefresh(store: any, external_user_id: string, app_id: string | null, ttlSeconds: number) {\n try {\n await getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n } catch {\n // Silent background failure\n }\n}\n","// src/client.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Final Instance-based Client (Feature Delegation)\n// -----------------------------------------------------------\n\nimport * as ConfigModule from \"./core/config\";\nimport { createStorage } from \"./core/storage\";\nimport { getGeoInfo } from \"./core/geo\";\nimport { httpRequest } from \"./core/http\"; // ✅ ADD THIS\n\n// Feature modules\nimport { identifyUserFeature } from \"./features/identifyUser\";\nimport { getTilesFeature } from \"./features/getTiles\";\n\nexport type ZubblConfig = {\n apiKey: string;\n signingSecret: string;\n tenantId: string;\n appId: string;\n baseUrl?: string;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n};\n\n\n/**\n * Creates a self-contained, instance-based Zubbl client.\n * Each instance owns its own config store and initialization state.\n */\nexport function createZubblClient(cfg: ZubblConfig) {\n const store = ConfigModule.createConfigStore();\n const storage = createStorage();\n let initialized = false;\n\n async function init() {\n if (initialized) return;\n\n // ✅ Validate UUIDs before initializing\n const UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n if (!UUID_PATTERN.test(cfg.tenantId)) {\n throw new Error(`[Zubbl SDK] Invalid tenantId: expected UUID, got \"${cfg.tenantId}\"`);\n }\n\n if (!UUID_PATTERN.test(cfg.appId)) {\n throw new Error(`[Zubbl SDK] Invalid appId: expected UUID, got \"${cfg.appId}\"`);\n }\n\n // Initialize per-client config\n store.init(cfg);\n\n // Optional: GEO bootstrap\n try {\n const geo = await getGeoInfo();\n console.log(`[Zubbl SDK] 🌍 GEO detected: ${geo.country} (ASN ${geo.asn || \"?\"})`);\n } catch (err: any) {\n console.warn(\"[Zubbl SDK] GEO init failed:\", err?.message);\n }\n\n initialized = true;\n }\n\n function assertInitialized() {\n if (!initialized) {\n throw new Error(\"Zubbl client not initialized — call client.init() first\");\n }\n }\n\n // ---------------------------------------------------------\n // User + Tile Operations (delegated to feature modules)\n // ---------------------------------------------------------\n async function identifyUser({ email, name }: { email: string; name?: string }) {\n assertInitialized();\n return identifyUserFeature(store, { email, name });\n }\n\n async function getTiles({\n external_user_id,\n app_id = null,\n ttlSeconds,\n }: {\n external_user_id: string;\n app_id?: string | null;\n ttlSeconds?: number;\n }) {\n assertInitialized();\n return getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n }\n\n // ---------------------------------------------------------\n // Enforcement API (kept inline)\n // ---------------------------------------------------------\n async function enforce({\n external_user_id,\n app_id = null,\n }: {\n external_user_id: string;\n app_id?: string | null;\n }) {\n assertInitialized();\n\n const config = store.get();\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n });\n\n // ✅ IMPORTANT: use signed httpRequest so Worker gate passes\n const url = `${config.baseUrl?.replace(/\\/$/, \"\")}/sdk/test-enforcement`;\n const resp = await httpRequest(url, {\n method: \"POST\",\n headers,\n });\n\n const json = await resp.json().catch(() => ({}));\n return { decision: \"allow\", status: resp.status, data: json };\n }\n\n // ---------------------------------------------------------\n // Public API\n // ---------------------------------------------------------\n return {\n init,\n identifyUser,\n getTiles,\n enforce,\n storage,\n };\n}\n","// src/index.ts\n// -----------------------------------------------------------\n// Zubbl SDK Entry Point — Public Exports\n// -----------------------------------------------------------\n\n// Core factory + environment\nexport * from \"./core/config\";\nexport * from \"./core/context\";\nexport * from \"./core/storage\";\nexport * from \"./core/geo\";\n\n// Avoid duplicate export of ZubblConfig\nexport {\n createZubblClient, // 🔁 change this if your client.ts exports something else\n} from \"./client\";\n\n// Feature modules (optional direct access)\nexport * from \"./features/identifyUser\";\nexport * from \"./features/getTiles\";\n\nconsole.log(\"[Zubbl SDK] ✅ Entry point loaded\");\n"],"names":["ConfigModule.createConfigStore"],"mappings":"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"}
1
+ {"version":3,"file":"zubbl-sdk.esm.js","sources":["../src/core/config.ts","../src/core/context.ts","../src/core/storage.ts","../src/core/geo.ts","../src/core/signing.ts","../src/utils/signing.ts","../src/core/http.ts","../src/features/identifyUser.ts","../src/features/getTiles.ts","../src/client.ts","../src/index.ts"],"sourcesContent":["// src/core/config.ts\n// -----------------------------------------------------------\n// Universal environment detection + SDK configuration\n// -----------------------------------------------------------\n\nexport const isBrowser =\n typeof window !== \"undefined\" && typeof window.document !== \"undefined\";\n\nexport const isNode =\n typeof process !== \"undefined\" &&\n !!process.versions?.node &&\n !isBrowser;\n\nexport const isWorker =\n typeof self !== \"undefined\" &&\n typeof (self as any).importScripts === \"function\" &&\n !isNode;\n\n// -----------------------------------------------------------\n// Config store factory (no module-scoped state)\n// -----------------------------------------------------------\n\nexport interface ZubblConfig {\n apiKey: string | null;\n signingSecret: string | null; // ✅ used for HMAC signing (never sent over the wire)\n tenantId: string | null;\n appId: string | null;\n baseUrl: string;\n appBaseUrl?: string | null;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n}\n\nfunction assertBrowserSafety(cfg: ZubblConfig) {\n if (isBrowser || isWorker) {\n const key = cfg.apiKey ?? \"\";\n const looksSecret = key.startsWith(\"sk_\") || key.length > 40;\n if (looksSecret) {\n throw new Error(\n \"[Zubbl SDK] Secret or server key detected in browser environment. \" +\n \"Use a public SDK key instead (prefix pk_).\"\n );\n }\n }\n}\n\n/**\n * Creates an isolated configuration store.\n * Each ZubblClient instance owns its own store.\n */\nexport function createConfigStore(initial?: Partial<ZubblConfig>) {\n let current: ZubblConfig = {\n apiKey: null,\n signingSecret: null,\n tenantId: null,\n appId: null,\n baseUrl: \"https://api.zubbl.com/api\",\n appBaseUrl: null,\n injectWorkerHeaders: false,\n workerSecret: null,\n ...initial,\n };\n\n function init(partial: Partial<ZubblConfig>) {\n current = { ...current, ...partial };\n assertBrowserSafety(current);\n }\n\n function get(): Readonly<ZubblConfig> {\n return current;\n }\n\n function buildHeaders(extra: Record<string, string> = {}): Record<string, string> {\n if (!current.tenantId || !current.appId) {\n throw new Error(\"[Zubbl SDK] Not initialized – call init() first.\");\n }\n\n const headers: Record<string, string> = {\n \"X-Tenant-Id\": current.tenantId,\n \"X-App-Id\": current.appId,\n \"Content-Type\": \"application/json\",\n ...extra,\n };\n\n if (current.apiKey) {\n headers.Authorization = `Bearer ${current.apiKey}`;\n }\n\n // ✅ Internal-only: used by httpRequest() to compute signature, then deleted before fetch\n if (current.signingSecret) {\n headers[\"X-Zubbl-Signing-Secret\"] = current.signingSecret;\n } else if (current.apiKey) {\n // If you're using API-key auth, you must also provide signingSecret for Worker-gated endpoints\n throw new Error(\"[Zubbl SDK] Missing signingSecret (required for signed requests)\");\n }\n\n return headers;\n }\n\n return { init, get, buildHeaders };\n}\n\n","// src/core/context.ts\n// -----------------------------------------------------------\n// Adaptive Context Engine — Geo + Stability Enrichment + Persistence\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types\n// -----------------------------------------------------------\ninterface ContextSample {\n path: string;\n method: string;\n ts: number;\n status: number;\n latency: number;\n}\n\ninterface AdaptiveState {\n routes: ContextSample[];\n geo: string;\n stability: number;\n lastGeoChange: number;\n}\n\nconst MAX_HISTORY = 100;\nconst CACHE_KEY = \"zubbl-stability\";\n\nlet state: AdaptiveState = loadStability() ?? {\n routes: [],\n geo: \"unknown\",\n stability: 1.0,\n lastGeoChange: Date.now(),\n};\n\n// -----------------------------------------------------------\n// 💾 Persistence Helpers\n// -----------------------------------------------------------\nfunction loadStability(): AdaptiveState | null {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n try {\n const raw = localStorage.getItem(CACHE_KEY);\n if (!raw) return null;\n const parsed = JSON.parse(raw);\n if (!parsed.geo || !parsed.stability) return null;\n return { ...parsed, routes: [] };\n } catch {\n return null;\n }\n}\n\nfunction saveStability() {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n try {\n const payload = {\n geo: state.geo,\n stability: state.stability,\n lastGeoChange: state.lastGeoChange,\n };\n localStorage.setItem(CACHE_KEY, JSON.stringify(payload));\n } catch {\n /* ignore */\n }\n}\n\n// -----------------------------------------------------------\n// 🌍 Geo Detection (Node, Browser, Worker)\n// -----------------------------------------------------------\nexport function detectGeo(): string {\n try {\n if (isBrowser && typeof window !== \"undefined\" && window.navigator?.language) {\n return window.navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isWorker && typeof self !== \"undefined\" && (self as any).navigator?.language) {\n return (self as any).navigator.language.split(\"-\")[1] || \"unknown\";\n }\n\n if (isNode && typeof process !== \"undefined\") {\n const envGeo = process.env.ZUBBL_GEO || process.env.GEO;\n if (envGeo && /^[A-Z]{2}$/i.test(envGeo)) return envGeo.toUpperCase();\n return \"GB\";\n }\n\n return \"unknown\";\n } catch (err) {\n console.warn(\"[Zubbl SDK][Geo Detect] Failed:\", err);\n return \"unknown\";\n }\n}\n\n// -----------------------------------------------------------\n// 🧭 Update Geo & Stability (with persistence)\n// -----------------------------------------------------------\nexport function updateGeo(geoHint?: string) {\n const newGeo = geoHint || detectGeo();\n if (newGeo !== state.geo) {\n const now = Date.now();\n const elapsed = (now - state.lastGeoChange) / 1000;\n state.stability = Math.max(0.5, Math.min(1.0, elapsed / 3600));\n state.geo = newGeo;\n state.lastGeoChange = now;\n saveStability();\n } else {\n state.stability = Math.min(1.0, state.stability + 0.01);\n saveStability();\n }\n}\n\n// -----------------------------------------------------------\n// 🧮 Record Context Samples\n// -----------------------------------------------------------\nexport function recordContextSample(\n path: string,\n method: string,\n status: number,\n latency: number\n) {\n state.routes.push({ path, method, ts: Date.now(), status, latency });\n if (state.routes.length > MAX_HISTORY) state.routes.shift();\n updateGeo(); // auto-refresh geo info\n}\n\n// -----------------------------------------------------------\n// 📦 Get Adaptive Headers\n// -----------------------------------------------------------\nexport function getAdaptiveHeaders(): Record<string, string> {\n const currentGeo = detectGeo();\n updateGeo(currentGeo);\n\n const summary = btoa(\n JSON.stringify({\n env: isNode ? \"node\" : isBrowser ? \"browser\" : \"worker\",\n routeCount: state.routes.length,\n lastGeo: state.geo,\n avgLatency:\n state.routes.reduce((a, b) => a + b.latency, 0) /\n Math.max(1, state.routes.length),\n })\n );\n\n return {\n \"X-Zubbl-Context-Summary\": summary,\n \"X-Zubbl-Geo-Stability\": `${state.geo}/${state.stability.toFixed(2)}`,\n };\n}\n\n// -----------------------------------------------------------\n// 🌍 Initialize Geo Context Immediately\n// -----------------------------------------------------------\nupdateGeo(process.env.ZUBBL_GEO);\n\n","// src/core/storage.ts\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// Generic storage interface\nexport interface IStorage {\n get<T>(key: string): T | null;\n set<T>(key: string, value: T, ttlSeconds?: number): void;\n remove(key: string): void;\n}\n\n// ------------------------------------------------------\n// Node (in-memory) implementation\n// ------------------------------------------------------\n\nclass NodeStorage implements IStorage {\n private store = new Map<string, { value: any; expiresAt?: number }>();\n\n get<T>(key: string): T | null {\n const entry = this.store.get(key);\n if (!entry) return null;\n if (entry.expiresAt && entry.expiresAt < Date.now()) {\n this.store.delete(key);\n return null;\n }\n return entry.value as T;\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n this.store.set(key, { value, expiresAt });\n }\n\n remove(key: string): void {\n this.store.delete(key);\n }\n}\n\n// ------------------------------------------------------\n// Browser (localStorage) implementation\n// ------------------------------------------------------\n\nclass BrowserStorage implements IStorage {\n private prefix = \"zubbl_sdk_\";\n\n get<T>(key: string): T | null {\n try {\n const raw = localStorage.getItem(this.prefix + key);\n if (!raw) return null;\n const { value, expiresAt } = JSON.parse(raw);\n if (expiresAt && expiresAt < Date.now()) {\n localStorage.removeItem(this.prefix + key);\n return null;\n }\n return value as T;\n } catch {\n return null;\n }\n }\n\n set<T>(key: string, value: T, ttlSeconds?: number): void {\n try {\n const expiresAt = ttlSeconds ? Date.now() + ttlSeconds * 1000 : undefined;\n localStorage.setItem(\n this.prefix + key,\n JSON.stringify({ value, expiresAt })\n );\n } catch (err) {\n // localStorage quota exceeded → silently ignore\n console.warn(\"[Zubbl SDK][Storage] Failed to persist item:\", err);\n }\n }\n\n remove(key: string): void {\n localStorage.removeItem(this.prefix + key);\n }\n}\n\n// ------------------------------------------------------\n// Factory\n// ------------------------------------------------------\n\nexport function createStorage(): IStorage {\n if (isNode) return new NodeStorage();\n if (isBrowser) return new BrowserStorage();\n\n // Fallback: safe no-op storage for tests / fake environments\n return {\n get: () => null,\n set: () => {},\n remove: () => {},\n };\n}\n\n","// -----------------------------------------------------------\n// 🌍 Zubbl Geo Engine — Cloudflare-Native Only (No External Providers)\n// -----------------------------------------------------------\n// Uses Worker-provided request.cf + headers. Free on all plans.\n// Sim/CLI fallback to avoid noise.\n// Aligns with Zubbl GEO Enforcement Whitepaper (Worker layer).\n// -----------------------------------------------------------\n\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Types (unchanged)\n// -----------------------------------------------------------\nexport interface GeoPrivacy {\n vpn: boolean;\n hosting: boolean;\n}\n\nexport interface GeoInfo {\n ip: string | null;\n country: string;\n asn: string | null;\n privacy: GeoPrivacy;\n}\n\nconst GEO_CACHE_KEY = \"zubbl-geo-cache\";\nconst GEO_TTL_MS = 15 * 60 * 1000; // 15 minutes\n\n// -----------------------------------------------------------\n// 🗃 Cache Helpers (unchanged, browser-only)\n// -----------------------------------------------------------\nfunction loadGeoCache(): GeoInfo | null {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return null;\n const raw = localStorage.getItem(GEO_CACHE_KEY);\n if (!raw) return null;\n\n const parsed = JSON.parse(raw) as { data: GeoInfo; timestamp: number };\n if (!parsed.data?.country || Date.now() - parsed.timestamp > GEO_TTL_MS) return null;\n return parsed.data;\n } catch {\n return null;\n }\n}\n\nfunction saveGeoCache(data: GeoInfo): void {\n try {\n if (!isBrowser || typeof localStorage === \"undefined\") return;\n localStorage.setItem(GEO_CACHE_KEY, JSON.stringify({ data, timestamp: Date.now() }));\n } catch {}\n}\n\n// -----------------------------------------------------------\n// 🧠 Cloudflare-Native Resolver\n// -----------------------------------------------------------\nexport async function getGeoInfo(context: any = {}): Promise<GeoInfo> { // Accept context for Worker/Request\n const cached = loadGeoCache();\n if (cached) return cached;\n\n // Detect sim/CLI (Node runtime, no Worker context)\n const isSimulation = process.env.ZUBBL_SIM_MODE === 'true' || isNode;\n\n // Extract from Worker-provided data (request.cf or enriched headers)\n const headers = context?.request?.headers || new Headers();\n const cf = context?.request?.cf || {}; // request.cf if Worker context available\n\n let country = cf.country || headers.get('CF-IPCountry') || headers.get('X-Zubbl-Geo-Country') || 'XX';\n let asn = cf.asn?.toString() || headers.get('X-Zubbl-ASN') || null;\n let asOrg = cf.asOrganization || headers.get('X-Zubbl-Geo-ASOrg') || null;\n\n// Sim fallback (clean run, no external noise)\nif (isSimulation && country === 'XX') {\n const simCountry =\n process.env.ZUBBL_SIM_COUNTRY ||\n process.env.ZUBBL_SIM_CF_IPCOUNTRY ||\n '';\n\n const simAsn = process.env.ZUBBL_SIM_ASN || '';\n const simAsOrg = process.env.ZUBBL_SIM_ASORG || '';\n\n const finalCountry = simCountry || 'GB';\n const finalAsn = simAsn || '2856';\n const finalAsOrg = simAsOrg || 'British Telecommunications';\n\n console.debug(\n `[Zubbl SDK][Geo][SIM] No Cloudflare data; using SIM defaults: country=${finalCountry}, asn=${finalAsn}`\n );\n\n country = finalCountry;\n asn = finalAsn;\n asOrg = finalAsOrg;\n}\n\nconst geo: GeoInfo = {\n ip: cf.clientIp || headers.get('CF-Connecting-IP') || null,\n country,\n asn,\n privacy: {\n vpn: false,\n hosting: false,\n },\n};\n\n// Optional: Worker can set privacy flags via headers (e.g., X-Zubbl-Privacy-VPN)\ngeo.privacy.vpn = headers.get('X-Zubbl-Privacy-VPN') === 'true';\ngeo.privacy.hosting = headers.get('X-Zubbl-Privacy-Hosting') === 'true';\n\n// SIM env overrides (so Node simulations don't require Worker headers)\nif (isSimulation) {\n if (process.env.ZUBBL_SIM_VPN !== undefined) {\n geo.privacy.vpn = String(process.env.ZUBBL_SIM_VPN).toLowerCase() === 'true';\n }\n if (process.env.ZUBBL_SIM_HOSTING !== undefined) {\n geo.privacy.hosting = String(process.env.ZUBBL_SIM_HOSTING).toLowerCase() === 'true';\n }\n}\n\nsaveGeoCache(geo);\nconsole.debug('[Zubbl SDK][Geo] Resolved (Cloudflare-native):', geo);\n\nreturn geo;\n}\n\n// -----------------------------------------------------------\n// 🧩 Exported Helpers (updated)\n// -----------------------------------------------------------\nexport function clearGeoCache(): void {\n try {\n if (isBrowser && typeof localStorage !== \"undefined\") {\n localStorage.removeItem(GEO_CACHE_KEY);\n }\n } catch {}\n}\n\nexport async function getGeoHeaders(context?: any): Promise<Record<string, string>> {\n const geo = await getGeoInfo(context);\n return {\n \"X-Zubbl-Geo-Country\": geo.country || \"unknown\",\n \"X-Zubbl-ASN\": geo.asn || \"unknown\",\n \"X-Zubbl-IP\": geo.ip || \"\",\n \"X-Zubbl-Privacy-VPN\": String(geo.privacy?.vpn ?? false),\n \"X-Zubbl-Privacy-Hosting\": String(geo.privacy?.hosting ?? false),\n };\n}\n","// -----------------------------------------------------------\n// 🔐 Secure Signing & Nonce Generator\n// -----------------------------------------------------------\n\nimport crypto from \"crypto\";\nimport { isNode, isBrowser, isWorker } from \"./config\";\n\n// -----------------------------------------------------------\n// Generate UUIDv4 Nonce\n// -----------------------------------------------------------\nexport function generateNonce(): string {\n return \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace(/[xy]/g, c => {\n const r = (Math.random() * 16) | 0;\n const v = c === \"x\" ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n// -----------------------------------------------------------\n// Compute SHA256 HMAC signature\n// -----------------------------------------------------------\nexport async function signPayload(payload: string, secret: string): Promise<string> {\n if (isNode) {\n // ✅ Node.js native HMAC\n return crypto.createHmac(\"sha256\", secret).update(payload).digest(\"hex\");\n }\n\n // ✅ Browser / Worker using WebCrypto\n if (typeof window !== \"undefined\" && window.crypto?.subtle) {\n const key = await window.crypto.subtle.importKey(\n \"raw\",\n new TextEncoder().encode(secret),\n { name: \"HMAC\", hash: \"SHA-256\" },\n false,\n [\"sign\"]\n );\n\n const sig = await window.crypto.subtle.sign(\n \"HMAC\",\n key,\n new TextEncoder().encode(payload)\n );\n\n return Array.from(new Uint8Array(sig))\n .map(b => b.toString(16).padStart(2, \"0\"))\n .join(\"\");\n }\n\n throw new Error(\"No crypto implementation available in this environment\");\n}\n\n// -----------------------------------------------------------\n// Attach signing headers to a request (corrected for SDK-12)\n// -----------------------------------------------------------\nexport function attachSigningHeaders(\n url: string,\n method: string,\n headers: Record<string, string> = {},\n body?: any,\n secretKey?: string | null\n): void {\n const nonce = generateNonce();\n\n // Normalize body to a string before hashing\n const normalizedBody =\n typeof body === \"string\"\n ? body\n : body && typeof body === \"object\"\n ? JSON.stringify(body)\n : \"\";\n\n const bodyHash = normalizedBody\n ? crypto.createHash(\"sha256\").update(normalizedBody).digest(\"hex\")\n : \"\";\n\n // Compute canonical string (deterministic)\n const canonical = `${method.toUpperCase()}\\n${url}\\n${nonce}\\n${bodyHash}`;\n\n // Attach nonce and signature headers (in-place)\n headers[\"X-Zubbl-Nonce\"] = nonce;\n\n if (secretKey) {\n const signature = crypto\n .createHmac(\"sha256\", secretKey)\n .update(canonical)\n .digest(\"hex\");\n headers[\"X-Zubbl-Signature\"] = signature;\n }\n}\n","import crypto from \"crypto\";\n\nexport function sha256Hex(input: string): string {\n return crypto.createHash(\"sha256\").update(input).digest(\"hex\");\n}\n\nexport function hmacSha256Hex(secret: string, input: string): string {\n return crypto.createHmac(\"sha256\", secret).update(input).digest(\"hex\");\n}\n\nexport function makeNonce(): string {\n return crypto.randomUUID();\n}\n\nexport function signCanonical(opts: {\n secret: string;\n method: string;\n pathWithQuery: string;\n nonce: string;\n bodyText: string;\n}): string {\n const bodyHash = sha256Hex(opts.bodyText || \"\");\n const canonical =\n `${opts.method.toUpperCase()}\\n${opts.pathWithQuery}\\n${opts.nonce}\\n${bodyHash}`;\n return hmacSha256Hex(opts.secret, canonical);\n}\n","// src/core/http.ts\n// -----------------------------------------------------------\n// HTTP utility (instance-safe)\n// -----------------------------------------------------------\n\nimport { recordContextSample, getAdaptiveHeaders } from \"./context\";\nimport { attachSigningHeaders } from \"./signing\";\nimport { makeNonce, signCanonical } from \"../utils/signing\";\n\n/**\n * Performs a safe HTTP request with adaptive + signing headers.\n * NOTE: no global getConfig() dependency — caller must provide fully resolved URL + headers.\n */\nexport async function httpRequest(url: string, options: RequestInit = {}): Promise<Response> {\n // 🔧 Default timeout lowered for SDK-12 hardening\n const controller = new AbortController();\n const timeout = setTimeout(() => controller.abort(), 8000);\n\n try {\n const method = (options.method || \"GET\").toUpperCase();\n\n // Keep original body reference for attachSigningHeaders (if you rely on it)\n const originalBody = options.body;\n\n // Normalise headers to a mutable object\n const headers: Record<string, string> = {\n ...((options.headers as Record<string, string>) || {}),\n ...getAdaptiveHeaders(),\n };\n\n // ✅ Keep your existing signing hook (if it adds auth/bearer/etc)\n // NOTE: This does NOT implement the Worker signature gate by itself (that's below).\n attachSigningHeaders(url, method, headers, originalBody);\n\n // Build finalOptions (must exist before we can safely sign exact bytes)\n const finalOptions: RequestInit = {\n ...options,\n method,\n headers,\n signal: controller.signal,\n };\n\n // ---------------------------------------------------------\n // ZUBBL: Worker signature gate (nonce + HMAC signature)\n // ---------------------------------------------------------\n // Worker expects:\n // canonical = METHOD \\n PATH+QUERY \\n NONCE \\n SHA256(bodyText)\n // headers: X-Zubbl-Nonce, X-Zubbl-Signature\n //\n // This is \"Option B\": verify signature + nonce replay protection.\n // ---------------------------------------------------------\n\n const apiKey =\n (headers[\"Authorization\"] || headers[\"authorization\"] || \"\")\n .replace(/^Bearer\\s+/i, \"\")\n .trim();\n\n const signingSecret =\n ((headers as any)[\"X-Zubbl-Signing-Secret\"] as string | undefined)?.trim() || \"\";\n\n if (!apiKey) {\n throw new Error(\"Missing API key (Authorization: Bearer ...) — cannot send requests\");\n }\n\n if (!signingSecret) {\n throw new Error(\"Missing signing secret — cannot sign requests\");\n }\n\n // We must sign the exact bytes we send.\n // If body is an object, stringify it BEFORE signing AND BEFORE sending.\n let bodyText = \"\";\n if (![\"GET\", \"HEAD\"].includes(method)) {\n const b: any = (finalOptions as any).body;\n\n if (b == null) bodyText = \"\";\n else if (typeof b === \"string\") bodyText = b;\n else bodyText = JSON.stringify(b);\n\n // Ensure fetch sends the exact signed string\n (finalOptions as any).body = bodyText;\n }\n\n // Canonical URL must match Worker logic: pathname + search\n const u = new URL(url);\n const pathWithQuery = `${u.pathname}${u.search}`;\n\n const nonce = makeNonce();\n const signature = signCanonical({\n secret: signingSecret,\n method,\n pathWithQuery,\n nonce,\n bodyText,\n });\n\n // Attach signing headers (ensure headers object is mutable)\n (finalOptions.headers as any) = (finalOptions.headers || {}) as any;\n (finalOptions.headers as any)[\"X-Zubbl-Nonce\"] = nonce;\n (finalOptions.headers as any)[\"X-Zubbl-Signature\"] = signature;\n\n // 🔒 Never send the signing secret over the wire (internal-only)\n delete (finalOptions.headers as any)[\"X-Zubbl-Signing-Secret\"];\n\n // Record adaptive context sample (keep your existing behaviour)\n recordContextSample(\"/http\", \"GET\", 200, 123);\n\n const response = await fetch(url, finalOptions);\n\n if (!response.ok && response.status !== 429) {\n let extra = \"\";\n try {\n extra = await response.clone().text();\n if (extra.length > 200) extra = extra.slice(0, 200) + \"...\";\n } catch {}\n console.warn(\n `[Zubbl SDK][HTTP] ${response.status} on ${url}${extra ? ` — ${extra}` : \"\"}`\n );\n }\n\n return response;\n } catch (err: any) {\n console.error(\"[Zubbl SDK][HTTP] Request failed:\", err?.message);\n throw err;\n } finally {\n clearTimeout(timeout);\n }\n}\n","\n\n// src/features/identifyUser.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe identifyUser feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\nconst USER_CACHE_KEY = \"external_user_id\";\nconst USER_TTL = 24 * 60 * 60; // 24h\n\nexport async function identifyUserFeature(\n store: any,\n { email, name }: { email: string; name?: string }\n) {\n if (!email) throw new Error(\"email is required\");\n\n const config = store.get();\n const storage = createStorage();\n\n // ✅ Determine override identity (prefer config.identity which SIM sets)\n const cfgIdentity = (config as any)?.identity;\n const storeIdentity = (store as any)?.identity;\n\n const overrideEnabled =\n (cfgIdentity && cfgIdentity.override === true) ||\n (storeIdentity && storeIdentity.override === true);\n\n const overrideId = overrideEnabled\n ? (cfgIdentity?.id ||\n storeIdentity?.id ||\n (store as any)?.externalUserId ||\n (store as any)?.userId ||\n undefined)\n : undefined;\n\n // Check cache (skip cache when override is enabled, we must honour overrideId)\n if (!overrideId) {\n const cached = storage.get<{ id: string }>(USER_CACHE_KEY);\n if (cached?.id) {\n return { external_user_id: cached.id, cached: true };\n }\n }\n\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use per-instance config store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"Content-Type\": \"application/json\",\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // ✅ If SIM/consumer provided an override external user ID, call the explicit endpoint\n const identifyUrl = overrideId\n ? `${config.baseUrl}/sdk/identify/${encodeURIComponent(String(overrideId))}`\n : `${config.baseUrl}/sdk/identify`;\n\n const resp = await httpRequest(identifyUrl, {\n method: \"POST\",\n headers,\n body: JSON.stringify({ email, name }),\n });\n\n const data = await resp.json().catch(() => ({}));\n const { external_user_id } = data;\n\n if (!external_user_id) {\n throw new Error(\"Backend did not return external_user_id\");\n }\n\n storage.set(USER_CACHE_KEY, { id: external_user_id }, USER_TTL);\n return { external_user_id, cached: false };\n}\n","// src/features/getTiles.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Instance-safe getTiles feature\n// -----------------------------------------------------------\n\nimport { httpRequest } from \"../core/http\";\nimport { createStorage } from \"../core/storage\";\nimport { getAdaptiveHeaders } from \"../core/context\";\nimport { getGeoHeaders } from \"../core/geo\";\n\n\nconst TILE_CACHE_KEY = \"tiles_cache\";\nconst TILE_TTL_DEFAULT = 10 * 60; // 10 min\n\ninterface TileCacheEntry {\n data: any;\n etag?: string;\n expiresAt: number;\n}\n\nexport async function getTilesFeature(\n store: any,\n { external_user_id, app_id = null, ttlSeconds = TILE_TTL_DEFAULT }: any\n) {\n const config = store.get();\n const storage = createStorage();\n\n const cached = storage.get<TileCacheEntry>(TILE_CACHE_KEY);\n const isFresh = cached && cached.expiresAt > Date.now();\n\n if (isFresh) {\n backgroundRefresh(store, external_user_id, app_id, ttlSeconds);\n return { data: cached.data, fromCache: true };\n }\n\n try {\n const adaptiveHeaders = getAdaptiveHeaders();\n const geoHeaders = await getGeoHeaders();\n\n // ✅ Use instance store, not global buildHeaders()\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n ...adaptiveHeaders,\n ...geoHeaders,\n });\n\n // Modern endpoint: POST /api/sdk/policies with body (per architecture docs)\nconst payload = {\n tenant_id: config.tenantId,\n app_id: app_id || config.appId!,\n external_user_id,\n};\n\nconst resp = await httpRequest(`${config.baseUrl.replace(/\\/$/, \"\")}/sdk/policies`, {\n method: \"POST\",\n headers,\n body: JSON.stringify(payload),\n});\n\n if (resp.status === 304 && cached?.data) {\n cached.expiresAt = Date.now() + ttlSeconds * 1000;\n storage.set(TILE_CACHE_KEY, cached, ttlSeconds);\n return { data: cached.data, fromCache: true, status: 304 };\n }\n\n const data = await resp.json();\n console.log('[DEBUG getTiles] Raw tiles response:', JSON.stringify(data, null, 2)); \n const etag = resp.headers.get(\"ETag\") || undefined;\n\n const entry: TileCacheEntry = {\n data,\n etag,\n expiresAt: Date.now() + ttlSeconds * 1000,\n };\n storage.set(TILE_CACHE_KEY, entry, ttlSeconds);\n\n return { data, fromCache: false, status: resp.status };\n } catch (err) {\n if (cached?.data) {\n return { data: cached.data, fromCache: true, error: String(err) };\n }\n throw err;\n }\n}\n\nasync function backgroundRefresh(store: any, external_user_id: string, app_id: string | null, ttlSeconds: number) {\n try {\n await getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n } catch {\n // Silent background failure\n }\n}\n","// src/client.ts\n// -----------------------------------------------------------\n// Zubbl SDK — Final Instance-based Client (Feature Delegation)\n// -----------------------------------------------------------\n\nimport * as ConfigModule from \"./core/config\";\nimport { createStorage } from \"./core/storage\";\nimport { getGeoInfo } from \"./core/geo\";\nimport { httpRequest } from \"./core/http\"; // ✅ ADD THIS\n\n// Feature modules\nimport { identifyUserFeature } from \"./features/identifyUser\";\nimport { getTilesFeature } from \"./features/getTiles\";\n\nexport type ZubblConfig = {\n apiKey: string;\n signingSecret: string;\n tenantId: string;\n appId: string;\n baseUrl?: string;\n appBaseUrl?: string | null;\n injectWorkerHeaders?: boolean;\n workerSecret?: string | null;\n};\n\n\n/**\n * Creates a self-contained, instance-based Zubbl client.\n * Each instance owns its own config store and initialization state.\n */\nexport function createZubblClient(cfg: ZubblConfig) {\n const store = ConfigModule.createConfigStore();\n const storage = createStorage();\n let initialized = false;\n\n async function init() {\n if (initialized) return;\n\n // ✅ Validate UUIDs before initializing\n const UUID_PATTERN =\n /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;\n\n if (!UUID_PATTERN.test(cfg.tenantId)) {\n throw new Error(`[Zubbl SDK] Invalid tenantId: expected UUID, got \"${cfg.tenantId}\"`);\n }\n\n if (!UUID_PATTERN.test(cfg.appId)) {\n throw new Error(`[Zubbl SDK] Invalid appId: expected UUID, got \"${cfg.appId}\"`);\n }\n\n // Initialize per-client config\n store.init(cfg);\n\n // Optional: GEO bootstrap\n try {\n const geo = await getGeoInfo();\n console.log(`[Zubbl SDK] 🌍 GEO detected: ${geo.country} (ASN ${geo.asn || \"?\"})`);\n } catch (err: any) {\n console.warn(\"[Zubbl SDK] GEO init failed:\", err?.message);\n }\n\n initialized = true;\n }\n\n function assertInitialized() {\n if (!initialized) {\n throw new Error(\"Zubbl client not initialized — call client.init() first\");\n }\n }\n\n // ---------------------------------------------------------\n // User + Tile Operations (delegated to feature modules)\n // ---------------------------------------------------------\n async function identifyUser({ email, name }: { email: string; name?: string }) {\n assertInitialized();\n return identifyUserFeature(store, { email, name });\n }\n\n async function getTiles({\n external_user_id,\n app_id = null,\n ttlSeconds,\n }: {\n external_user_id: string;\n app_id?: string | null;\n ttlSeconds?: number;\n }) {\n assertInitialized();\n return getTilesFeature(store, { external_user_id, app_id, ttlSeconds });\n }\n\n // ---------------------------------------------------------\n // Enforcement API (kept inline)\n // ---------------------------------------------------------\n async function enforce({\n external_user_id,\n app_id = null,\n }: {\n external_user_id: string;\n app_id?: string | null;\n }) {\n assertInitialized();\n\n const config = store.get();\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n });\n\n // ✅ IMPORTANT: use signed httpRequest so Worker gate passes\n const url = `${config.baseUrl?.replace(/\\/$/, \"\")}/sdk/test-enforcement`;\n const resp = await httpRequest(url, {\n method: \"POST\",\n headers,\n });\n\n const json = await resp.json().catch(() => ({}));\n\n const decision =\n resp.status === 403 || resp.status === 429 ? \"block\" : resp.ok ? \"allow\" : \"error\";\n\n return {\n decision,\n status: resp.status,\n allowed: decision === \"allow\",\n blocked: decision === \"block\",\n data: json,\n };\n }\n\n async function testEndpoint({\n external_user_id,\n endpoint,\n method = \"POST\",\n body = {},\n }: {\n external_user_id: string;\n endpoint: string;\n method?: string;\n body?: any;\n }) {\n assertInitialized();\n\n const config = store.get();\n const base = config.appBaseUrl?.replace(/\\/$/, \"\");\n\n if (!base) {\n throw new Error(\"[Zubbl SDK] appBaseUrl is required to run endpoint tests\");\n }\n\n if (!endpoint || !endpoint.startsWith(\"/\")) {\n throw new Error(\"[Zubbl SDK] endpoint must start with /\");\n }\n\n const headers = store.buildHeaders({\n \"X-External-User-Id\": external_user_id,\n \"X-Zubbl-Test-Mode\": \"live\",\n });\n\n const resp = await httpRequest(`${base}${endpoint}`, {\n method: method.toUpperCase(),\n headers,\n body: [\"GET\", \"HEAD\"].includes(method.toUpperCase()) ? undefined : body,\n });\n\n const text = await resp.text().catch(() => \"\");\n let data: any = text;\n\n try {\n data = text ? JSON.parse(text) : {};\n } catch {}\n\n const decision =\n resp.status === 403 || resp.status === 429 ? \"block\" : resp.ok ? \"allow\" : \"error\";\n\n return {\n decision,\n status: resp.status,\n allowed: decision === \"allow\",\n blocked: decision === \"block\",\n endpoint,\n method: method.toUpperCase(),\n data,\n };\n }\n\n function createExpressTestHandler() {\n return async function zubblExpressTestHandler(req: any, res: any) {\n try {\n const endpoint = String(req.query?.endpoint || \"\").trim();\n const method = String(req.query?.method || \"POST\").toUpperCase();\n const html = String(req.query?.html || \"\").toLowerCase() === \"true\";\n const external_user_id = String(\n req.query?.external_user_id ||\n req.headers?.[\"x-external-user-id\"] ||\n \"zubbl-test-user\"\n ).trim();\n\n const result = await testEndpoint({\n external_user_id,\n endpoint,\n method,\n body: {},\n });\n\n if (html) {\n return res\n .status(200)\n .send(`<!doctype html>\n<html>\n <head>\n <title>Zubbl live endpoint test</title>\n <style>\n body { font-family: system-ui, sans-serif; background: #0b1020; color: #fff; padding: 32px; }\n pre { background: #111827; padding: 16px; border-radius: 12px; overflow: auto; }\n .ok { color: #86efac; }\n .block { color: #fca5a5; }\n </style>\n </head>\n <body>\n <h1>Zubbl live endpoint test</h1>\n <p>Endpoint: <code>${result.method} ${result.endpoint}</code></p>\n <p>Status: <strong>${result.status}</strong></p>\n <p>Decision: <strong class=\"${result.blocked ? \"block\" : \"ok\"}\">${result.decision}</strong></p>\n <pre>${JSON.stringify(result, null, 2)}</pre>\n </body>\n</html>`);\n }\n\n return res.status(200).json(result);\n } catch (err: any) {\n const payload = {\n error: err?.message || \"Zubbl test failed\",\n };\n\n if (String(req.query?.html || \"\").toLowerCase() === \"true\") {\n return res.status(500).send(`<h1>Zubbl test failed</h1><pre>${payload.error}</pre>`);\n }\n\n return res.status(500).json(payload);\n }\n };\n }\n\n // ---------------------------------------------------------\n // Public API\n // ---------------------------------------------------------\n return {\n init,\n identifyUser,\n getTiles,\n enforce,\n testEndpoint,\n createExpressTestHandler,\n storage,\n };\n}\n","// src/index.ts\n// -----------------------------------------------------------\n// Zubbl SDK Entry Point — Public Exports\n// -----------------------------------------------------------\n\n// Core factory + environment\nexport * from \"./core/config\";\nexport * from \"./core/context\";\nexport * from \"./core/storage\";\nexport * from \"./core/geo\";\n\n// Avoid duplicate export of ZubblConfig\nexport {\n createZubblClient, // 🔁 change this if your client.ts exports something else\n} from \"./client\";\n\n// Feature modules (optional direct access)\nexport * from \"./features/identifyUser\";\nexport * from \"./features/getTiles\";\n\nconsole.log(\"[Zubbl SDK] ✅ Entry point loaded\");\n"],"names":["ConfigModule.createConfigStore"],"mappings":";;AAAA;AACA;AACA;AACA;AAEO,MAAM,SAAS,GACpB,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,MAAM,CAAC,QAAQ,KAAK;AAEvD,MAAM,MAAM,GACjB,OAAO,OAAO,KAAK,WAAW;AAC9B,IAAA,CAAC,CAAC,OAAO,CAAC,QAAQ,EAAE,IAAI;AACxB,IAAA,CAAC;AAEI,MAAM,QAAQ,GACnB,OAAO,IAAI,KAAK,WAAW;AAC3B,IAAA,OAAQ,IAAY,CAAC,aAAa,KAAK,UAAU;AACjD,IAAA,CAAC;AAiBH,SAAS,mBAAmB,CAAC,GAAgB,EAAA;AAC3C,IAAA,IAAI,SAAS,IAAI,QAAQ,EAAE;AACzB,QAAA,MAAM,GAAG,GAAG,GAAG,CAAC,MAAM,IAAI,EAAE;AAC5B,QAAA,MAAM,WAAW,GAAG,GAAG,CAAC,UAAU,CAAC,KAAK,CAAC,IAAI,GAAG,CAAC,MAAM,GAAG,EAAE;QAC5D,IAAI,WAAW,EAAE;YACf,MAAM,IAAI,KAAK,CACb,oEAAoE;AAClE,gBAAA,4CAA4C,CAC/C;QACH;IACF;AACF;AAEA;;;AAGG;AACG,SAAU,iBAAiB,CAAC,OAA8B,EAAA;AAC9D,IAAA,IAAI,OAAO,GAAgB;AACzB,QAAA,MAAM,EAAE,IAAI;AACZ,QAAA,aAAa,EAAE,IAAI;AACnB,QAAA,QAAQ,EAAE,IAAI;AACd,QAAA,KAAK,EAAE,IAAI;AACX,QAAA,OAAO,EAAE,2BAA2B;AACpC,QAAA,UAAU,EAAE,IAAI;AAChB,QAAA,mBAAmB,EAAE,KAAK;AAC1B,QAAA,YAAY,EAAE,IAAI;AAClB,QAAA,GAAG,OAAO;KACX;IAED,SAAS,IAAI,CAAC,OAA6B,EAAA;QACzC,OAAO,GAAG,EAAE,GAAG,OAAO,EAAE,GAAG,OAAO,EAAE;QACpC,mBAAmB,CAAC,OAAO,CAAC;IAC9B;AAEA,IAAA,SAAS,GAAG,GAAA;AACV,QAAA,OAAO,OAAO;IAChB;IAEA,SAAS,YAAY,CAAC,KAAA,GAAgC,EAAE,EAAA;QACtD,IAAI,CAAC,OAAO,CAAC,QAAQ,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE;AACvC,YAAA,MAAM,IAAI,KAAK,CAAC,kDAAkD,CAAC;QACrE;AAEA,QAAA,MAAM,OAAO,GAA2B;YACtC,aAAa,EAAE,OAAO,CAAC,QAAQ;YAC/B,UAAU,EAAE,OAAO,CAAC,KAAK;AACzB,YAAA,cAAc,EAAE,kBAAkB;AAClC,YAAA,GAAG,KAAK;SACT;AAED,QAAA,IAAI,OAAO,CAAC,MAAM,EAAE;YAClB,OAAO,CAAC,aAAa,GAAG,CAAA,OAAA,EAAU,OAAO,CAAC,MAAM,EAAE;QACpD;;AAGA,QAAA,IAAI,OAAO,CAAC,aAAa,EAAE;AACzB,YAAA,OAAO,CAAC,wBAAwB,CAAC,GAAG,OAAO,CAAC,aAAa;QAC3D;AAAO,aAAA,IAAI,OAAO,CAAC,MAAM,EAAE;;AAEzB,YAAA,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC;QACrF;AAEA,QAAA,OAAO,OAAO;IAChB;AAEA,IAAA,OAAO,EAAE,IAAI,EAAE,GAAG,EAAE,YAAY,EAAE;AACpC;;ACpGA;AACA;AACA;AACA;AAsBA,MAAM,WAAW,GAAG,GAAG;AACvB,MAAM,SAAS,GAAG,iBAAiB;AAEnC,IAAI,KAAK,GAAkB,aAAa,EAAE,IAAI;AAC5C,IAAA,MAAM,EAAE,EAAE;AACV,IAAA,GAAG,EAAE,SAAS;AACd,IAAA,SAAS,EAAE,GAAG;AACd,IAAA,aAAa,EAAE,IAAI,CAAC,GAAG,EAAE;CAC1B;AAED;AACA;AACA;AACA,SAAS,aAAa,GAAA;AACpB,IAAA,IAAI,CAAC,SAAS,IAAI,OAAO,YAAY,KAAK,WAAW;AAAE,QAAA,OAAO,IAAI;AAClE,IAAA,IAAI;QACF,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,SAAS,CAAC;AAC3C,QAAA,IAAI,CAAC,GAAG;AAAE,YAAA,OAAO,IAAI;QACrB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;QAC9B,IAAI,CAAC,MAAM,CAAC,GAAG,IAAI,CAAC,MAAM,CAAC,SAAS;AAAE,YAAA,OAAO,IAAI;QACjD,OAAO,EAAE,GAAG,MAAM,EAAE,MAAM,EAAE,EAAE,EAAE;IAClC;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,IAAI;IACb;AACF;AAEA,SAAS,aAAa,GAAA;AACpB,IAAA,IAAI,CAAC,SAAS,IAAI,OAAO,YAAY,KAAK,WAAW;QAAE;AACvD,IAAA,IAAI;AACF,QAAA,MAAM,OAAO,GAAG;YACd,GAAG,EAAE,KAAK,CAAC,GAAG;YACd,SAAS,EAAE,KAAK,CAAC,SAAS;YAC1B,aAAa,EAAE,KAAK,CAAC,aAAa;SACnC;AACD,QAAA,YAAY,CAAC,OAAO,CAAC,SAAS,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC;IAC1D;AAAE,IAAA,MAAM;;IAER;AACF;AAEA;AACA;AACA;SACgB,SAAS,GAAA;AACvB,IAAA,IAAI;AACF,QAAA,IAAI,SAAS,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,MAAM,CAAC,SAAS,EAAE,QAAQ,EAAE;AAC5E,YAAA,OAAO,MAAM,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS;QAC7D;AAEA,QAAA,IAAI,QAAQ,IAAI,OAAO,IAAI,KAAK,WAAW,IAAK,IAAY,CAAC,SAAS,EAAE,QAAQ,EAAE;AAChF,YAAA,OAAQ,IAAY,CAAC,SAAS,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS;QACpE;AAEA,QAAA,IAAI,MAAM,IAAI,OAAO,OAAO,KAAK,WAAW,EAAE;AAC5C,YAAA,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,SAAS,IAAI,OAAO,CAAC,GAAG,CAAC,GAAG;AACvD,YAAA,IAAI,MAAM,IAAI,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC;AAAE,gBAAA,OAAO,MAAM,CAAC,WAAW,EAAE;AACrE,YAAA,OAAO,IAAI;QACb;AAEA,QAAA,OAAO,SAAS;IAClB;IAAE,OAAO,GAAG,EAAE;AACZ,QAAA,OAAO,CAAC,IAAI,CAAC,iCAAiC,EAAE,GAAG,CAAC;AACpD,QAAA,OAAO,SAAS;IAClB;AACF;AAEA;AACA;AACA;AACM,SAAU,SAAS,CAAC,OAAgB,EAAA;AACxC,IAAA,MAAM,MAAM,GAAG,OAAO,IAAI,SAAS,EAAE;AACrC,IAAA,IAAI,MAAM,KAAK,KAAK,CAAC,GAAG,EAAE;AACxB,QAAA,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,EAAE;QACtB,MAAM,OAAO,GAAG,CAAC,GAAG,GAAG,KAAK,CAAC,aAAa,IAAI,IAAI;QAClD,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,OAAO,GAAG,IAAI,CAAC,CAAC;AAC9D,QAAA,KAAK,CAAC,GAAG,GAAG,MAAM;AAClB,QAAA,KAAK,CAAC,aAAa,GAAG,GAAG;AACzB,QAAA,aAAa,EAAE;IACjB;SAAO;AACL,QAAA,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,EAAE,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC;AACvD,QAAA,aAAa,EAAE;IACjB;AACF;AAEA;AACA;AACA;AACM,SAAU,mBAAmB,CACjC,IAAY,EACZ,MAAc,EACd,MAAc,EACd,OAAe,EAAA;IAEf,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,IAAI,EAAE,MAAM,EAAE,EAAE,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,MAAM,EAAE,OAAO,EAAE,CAAC;AACpE,IAAA,IAAI,KAAK,CAAC,MAAM,CAAC,MAAM,GAAG,WAAW;AAAE,QAAA,KAAK,CAAC,MAAM,CAAC,KAAK,EAAE;IAC3D,SAAS,EAAE,CAAC;AACd;AAEA;AACA;AACA;SACgB,kBAAkB,GAAA;AAChC,IAAA,MAAM,UAAU,GAAG,SAAS,EAAE;IAC9B,SAAS,CAAC,UAAU,CAAC;AAErB,IAAA,MAAM,OAAO,GAAG,IAAI,CAClB,IAAI,CAAC,SAAS,CAAC;AACb,QAAA,GAAG,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,SAAS,GAAG,QAAQ;AACvD,QAAA,UAAU,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM;QAC/B,OAAO,EAAE,KAAK,CAAC,GAAG;QAClB,UAAU,EACR,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;YAC/C,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC;AACnC,KAAA,CAAC,CACH;IAED,OAAO;AACL,QAAA,yBAAyB,EAAE,OAAO;AAClC,QAAA,uBAAuB,EAAE,CAAA,EAAG,KAAK,CAAC,GAAG,CAAA,CAAA,EAAI,KAAK,CAAC,SAAS,CAAC,OAAO,CAAC,CAAC,CAAC,CAAA,CAAE;KACtE;AACH;AAEA;AACA;AACA;AACA,SAAS,CAAC,OAAO,CAAC,GAAG,CAAC,SAAS,CAAC;;ACtJhC;AAUA;AACA;AACA;AAEA,MAAM,WAAW,CAAA;AAAjB,IAAA,WAAA,GAAA;AACU,QAAA,IAAA,CAAA,KAAK,GAAG,IAAI,GAAG,EAA8C;IAoBvE;AAlBE,IAAA,GAAG,CAAI,GAAW,EAAA;QAChB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,CAAC;AACjC,QAAA,IAAI,CAAC,KAAK;AAAE,YAAA,OAAO,IAAI;AACvB,QAAA,IAAI,KAAK,CAAC,SAAS,IAAI,KAAK,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE;AACnD,YAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;AACtB,YAAA,OAAO,IAAI;QACb;QACA,OAAO,KAAK,CAAC,KAAU;IACzB;AAEA,IAAA,GAAG,CAAI,GAAW,EAAE,KAAQ,EAAE,UAAmB,EAAA;AAC/C,QAAA,MAAM,SAAS,GAAG,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,IAAI,GAAG,SAAS;AACzE,QAAA,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,GAAG,EAAE,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC;IAC3C;AAEA,IAAA,MAAM,CAAC,GAAW,EAAA;AAChB,QAAA,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,GAAG,CAAC;IACxB;AACD;AAED;AACA;AACA;AAEA,MAAM,cAAc,CAAA;AAApB,IAAA,WAAA,GAAA;QACU,IAAA,CAAA,MAAM,GAAG,YAAY;IAiC/B;AA/BE,IAAA,GAAG,CAAI,GAAW,EAAA;AAChB,QAAA,IAAI;AACF,YAAA,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;AACnD,YAAA,IAAI,CAAC,GAAG;AAAE,gBAAA,OAAO,IAAI;AACrB,YAAA,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC;YAC5C,IAAI,SAAS,IAAI,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,EAAE;gBACvC,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;AAC1C,gBAAA,OAAO,IAAI;YACb;AACA,YAAA,OAAO,KAAU;QACnB;AAAE,QAAA,MAAM;AACN,YAAA,OAAO,IAAI;QACb;IACF;AAEA,IAAA,GAAG,CAAI,GAAW,EAAE,KAAQ,EAAE,UAAmB,EAAA;AAC/C,QAAA,IAAI;AACF,YAAA,MAAM,SAAS,GAAG,UAAU,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,IAAI,GAAG,SAAS;YACzE,YAAY,CAAC,OAAO,CAClB,IAAI,CAAC,MAAM,GAAG,GAAG,EACjB,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,CAAC,CACrC;QACH;QAAE,OAAO,GAAG,EAAE;;AAEZ,YAAA,OAAO,CAAC,IAAI,CAAC,8CAA8C,EAAE,GAAG,CAAC;QACnE;IACF;AAEA,IAAA,MAAM,CAAC,GAAW,EAAA;QAChB,YAAY,CAAC,UAAU,CAAC,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC;IAC5C;AACD;AAED;AACA;AACA;SAEgB,aAAa,GAAA;AAC3B,IAAA,IAAI,MAAM;QAAE,OAAO,IAAI,WAAW,EAAE;AACpC,IAAA,IAAI,SAAS;QAAE,OAAO,IAAI,cAAc,EAAE;;IAG1C,OAAO;AACL,QAAA,GAAG,EAAE,MAAM,IAAI;AACf,QAAA,GAAG,EAAE,MAAK,EAAE,CAAC;AACb,QAAA,MAAM,EAAE,MAAK,EAAE,CAAC;KACjB;AACH;;AC3FA;AACA;AACA;AACA;AACA;AACA;AACA;AAmBA,MAAM,aAAa,GAAG,iBAAiB;AACvC,MAAM,UAAU,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC;AAElC;AACA;AACA;AACA,SAAS,YAAY,GAAA;AACnB,IAAA,IAAI;AACF,QAAA,IAAI,CAAC,SAAS,IAAI,OAAO,YAAY,KAAK,WAAW;AAAE,YAAA,OAAO,IAAI;QAClE,MAAM,GAAG,GAAG,YAAY,CAAC,OAAO,CAAC,aAAa,CAAC;AAC/C,QAAA,IAAI,CAAC,GAAG;AAAE,YAAA,OAAO,IAAI;QAErB,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,GAAG,CAAyC;AACtE,QAAA,IAAI,CAAC,MAAM,CAAC,IAAI,EAAE,OAAO,IAAI,IAAI,CAAC,GAAG,EAAE,GAAG,MAAM,CAAC,SAAS,GAAG,UAAU;AAAE,YAAA,OAAO,IAAI;QACpF,OAAO,MAAM,CAAC,IAAI;IACpB;AAAE,IAAA,MAAM;AACN,QAAA,OAAO,IAAI;IACb;AACF;AAEA,SAAS,YAAY,CAAC,IAAa,EAAA;AACjC,IAAA,IAAI;AACF,QAAA,IAAI,CAAC,SAAS,IAAI,OAAO,YAAY,KAAK,WAAW;YAAE;QACvD,YAAY,CAAC,OAAO,CAAC,aAAa,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,IAAI,EAAE,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,EAAE,CAAC,CAAC;IACtF;IAAE,MAAM,EAAC;AACX;AAEA;AACA;AACA;AACO,eAAe,UAAU,CAAC,UAAe,EAAE,EAAA;AAChD,IAAA,MAAM,MAAM,GAAG,YAAY,EAAE;AAC7B,IAAA,IAAI,MAAM;AAAE,QAAA,OAAO,MAAM;;IAGzB,MAAM,YAAY,GAAG,OAAO,CAAC,GAAG,CAAC,cAAc,KAAK,MAAM,IAAI,MAAM;;IAGpE,MAAM,OAAO,GAAG,OAAO,EAAE,OAAO,EAAE,OAAO,IAAI,IAAI,OAAO,EAAE;IAC1D,MAAM,EAAE,GAAG,OAAO,EAAE,OAAO,EAAE,EAAE,IAAI,EAAE,CAAC;IAEtC,IAAI,OAAO,GAAG,EAAE,CAAC,OAAO,IAAI,OAAO,CAAC,GAAG,CAAC,cAAc,CAAC,IAAI,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,IAAI,IAAI;AACrG,IAAA,IAAI,GAAG,GAAG,EAAE,CAAC,GAAG,EAAE,QAAQ,EAAE,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,IAAI,IAAI;AAClE,IAAY,EAAE,CAAC,cAAc,IAAI,OAAO,CAAC,GAAG,CAAC,mBAAmB,CAAC,IAAI;;AAGvE,IAAA,IAAI,YAAY,IAAI,OAAO,KAAK,IAAI,EAAE;AACpC,QAAA,MAAM,UAAU,GACd,OAAO,CAAC,GAAG,CAAC,iBAAiB;YAC7B,OAAO,CAAC,GAAG,CAAC,sBAAsB;AAClC,YAAA,EAAE;QAEJ,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAC,aAAa,IAAI,EAAE;QAC7B,OAAO,CAAC,GAAG,CAAC,eAAe,IAAI;AAEhD,QAAA,MAAM,YAAY,GAAG,UAAU,IAAI,IAAI;AACvC,QAAA,MAAM,QAAQ,GAAG,MAAM,IAAI,MAAM;QAGjC,OAAO,CAAC,KAAK,CACX,CAAA,sEAAA,EAAyE,YAAY,CAAA,MAAA,EAAS,QAAQ,CAAA,CAAE,CACzG;QAED,OAAO,GAAG,YAAY;QACtB,GAAG,GAAG,QAAQ;IAEhB;AAEA,IAAA,MAAM,GAAG,GAAY;AACnB,QAAA,EAAE,EAAE,EAAE,CAAC,QAAQ,IAAI,OAAO,CAAC,GAAG,CAAC,kBAAkB,CAAC,IAAI,IAAI;QAC1D,OAAO;QACP,GAAG;AACH,QAAA,OAAO,EAAE;AACP,YAAA,GAAG,EAAE,KAAK;AACV,YAAA,OAAO,EAAE,KAAK;AACf,SAAA;KACF;;AAGD,IAAA,GAAG,CAAC,OAAO,CAAC,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC,qBAAqB,CAAC,KAAK,MAAM;AAC/D,IAAA,GAAG,CAAC,OAAO,CAAC,OAAO,GAAG,OAAO,CAAC,GAAG,CAAC,yBAAyB,CAAC,KAAK,MAAM;;IAGvE,IAAI,YAAY,EAAE;QAChB,IAAI,OAAO,CAAC,GAAG,CAAC,aAAa,KAAK,SAAS,EAAE;AAC3C,YAAA,GAAG,CAAC,OAAO,CAAC,GAAG,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM;QAC9E;QACA,IAAI,OAAO,CAAC,GAAG,CAAC,iBAAiB,KAAK,SAAS,EAAE;AAC/C,YAAA,GAAG,CAAC,OAAO,CAAC,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM;QACtF;IACF;IAEA,YAAY,CAAC,GAAG,CAAC;AACjB,IAAA,OAAO,CAAC,KAAK,CAAC,gDAAgD,EAAE,GAAG,CAAC;AAEpE,IAAA,OAAO,GAAG;AACV;AAEA;AACA;AACA;SACgB,aAAa,GAAA;AAC3B,IAAA,IAAI;AACF,QAAA,IAAI,SAAS,IAAI,OAAO,YAAY,KAAK,WAAW,EAAE;AACpD,YAAA,YAAY,CAAC,UAAU,CAAC,aAAa,CAAC;QACxC;IACF;IAAE,MAAM,EAAC;AACX;AAEO,eAAe,aAAa,CAAC,OAAa,EAAA;AAC/C,IAAA,MAAM,GAAG,GAAG,MAAM,UAAU,CAAC,OAAO,CAAC;IACrC,OAAO;AACL,QAAA,qBAAqB,EAAE,GAAG,CAAC,OAAO,IAAI,SAAS;AAC/C,QAAA,aAAa,EAAE,GAAG,CAAC,GAAG,IAAI,SAAS;AACnC,QAAA,YAAY,EAAE,GAAG,CAAC,EAAE,IAAI,EAAE;QAC1B,qBAAqB,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,IAAI,KAAK,CAAC;QACxD,yBAAyB,EAAE,MAAM,CAAC,GAAG,CAAC,OAAO,EAAE,OAAO,IAAI,KAAK,CAAC;KACjE;AACH;;AC/IA;AACA;AACA;AAKA;AACA;AACA;SACgB,aAAa,GAAA;IAC3B,OAAO,sCAAsC,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC,IAAG;AACjE,QAAA,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,MAAM,EAAE,GAAG,EAAE,IAAI,CAAC;AAClC,QAAA,MAAM,CAAC,GAAG,CAAC,KAAK,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC,GAAG,GAAG,IAAI,GAAG;AACzC,QAAA,OAAO,CAAC,CAAC,QAAQ,CAAC,EAAE,CAAC;AACvB,IAAA,CAAC,CAAC;AACJ;AAmCA;AACA;AACA;AACM,SAAU,oBAAoB,CAClC,GAAW,EACX,MAAc,EACd,OAAA,GAAkC,EAAE,EACpC,IAAU,EACV,SAAyB,EAAA;AAEzB,IAAA,MAAM,KAAK,GAAG,aAAa,EAAE;;AAG7B,IAAA,MAAM,cAAc,GAClB,OAAO,IAAI,KAAK;AACd,UAAE;AACF,UAAE,IAAI,IAAI,OAAO,IAAI,KAAK;AAC1B,cAAE,IAAI,CAAC,SAAS,CAAC,IAAI;cACnB,EAAE;IAER,MAAM,QAAQ,GAAG;AACf,UAAE,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,cAAc,CAAC,CAAC,MAAM,CAAC,KAAK;UAC/D,EAAE;;AAGN,IAAkB,CAAA,EAAG,MAAM,CAAC,WAAW,EAAE,CAAA,EAAA,EAAK,GAAG,CAAA,EAAA,EAAK,KAAK,CAAA,EAAA,EAAK,QAAQ;;AAGxE,IAAA,OAAO,CAAC,eAAe,CAAC,GAAG,KAAK;AASlC;;ACtFM,SAAU,SAAS,CAAC,KAAa,EAAA;AACrC,IAAA,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;AAChE;AAEM,SAAU,aAAa,CAAC,MAAc,EAAE,KAAa,EAAA;AACzD,IAAA,OAAO,MAAM,CAAC,UAAU,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC;AACxE;SAEgB,SAAS,GAAA;AACvB,IAAA,OAAO,MAAM,CAAC,UAAU,EAAE;AAC5B;AAEM,SAAU,aAAa,CAAC,IAM7B,EAAA;IACC,MAAM,QAAQ,GAAG,SAAS,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC;IAC/C,MAAM,SAAS,GACb,CAAA,EAAG,IAAI,CAAC,MAAM,CAAC,WAAW,EAAE,CAAA,EAAA,EAAK,IAAI,CAAC,aAAa,KAAK,IAAI,CAAC,KAAK,CAAA,EAAA,EAAK,QAAQ,EAAE;IACnF,OAAO,aAAa,CAAC,IAAI,CAAC,MAAM,EAAE,SAAS,CAAC;AAC9C;;ACzBA;AACA;AACA;AACA;AAMA;;;AAGG;AACI,eAAe,WAAW,CAAC,GAAW,EAAE,UAAuB,EAAE,EAAA;;AAEtE,IAAA,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE;AACxC,IAAA,MAAM,OAAO,GAAG,UAAU,CAAC,MAAM,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC;AAE1D,IAAA,IAAI;AACF,QAAA,MAAM,MAAM,GAAG,CAAC,OAAO,CAAC,MAAM,IAAI,KAAK,EAAE,WAAW,EAAE;;AAGtD,QAAA,MAAM,YAAY,GAAG,OAAO,CAAC,IAAI;;AAGjC,QAAA,MAAM,OAAO,GAA2B;AACtC,YAAA,IAAK,OAAO,CAAC,OAAkC,IAAI,EAAE,CAAC;AACtD,YAAA,GAAG,kBAAkB,EAAE;SACxB;;;QAID,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,CAAC;;AAGxD,QAAA,MAAM,YAAY,GAAgB;AAChC,YAAA,GAAG,OAAO;YACV,MAAM;YACN,OAAO;YACP,MAAM,EAAE,UAAU,CAAC,MAAM;SAC1B;;;;;;;;;;AAYD,QAAA,MAAM,MAAM,GACV,CAAC,OAAO,CAAC,eAAe,CAAC,IAAI,OAAO,CAAC,eAAe,CAAC,IAAI,EAAE;AACxD,aAAA,OAAO,CAAC,aAAa,EAAE,EAAE;AACzB,aAAA,IAAI,EAAE;QAEX,MAAM,aAAa,GACf,OAAe,CAAC,wBAAwB,CAAwB,EAAE,IAAI,EAAE,IAAI,EAAE;QAElF,IAAI,CAAC,MAAM,EAAE;AACX,YAAA,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC;QACvF;QAEA,IAAI,CAAC,aAAa,EAAE;AAClB,YAAA,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC;QAClE;;;QAIA,IAAI,QAAQ,GAAG,EAAE;AACjB,QAAA,IAAI,CAAC,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE;AACrC,YAAA,MAAM,CAAC,GAAS,YAAoB,CAAC,IAAI;YAEzC,IAAI,CAAC,IAAI,IAAI;gBAAE,QAAQ,GAAG,EAAE;iBACvB,IAAI,OAAO,CAAC,KAAK,QAAQ;gBAAE,QAAQ,GAAG,CAAC;;AACvC,gBAAA,QAAQ,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC;;AAGhC,YAAA,YAAoB,CAAC,IAAI,GAAG,QAAQ;QACvC;;AAGA,QAAA,MAAM,CAAC,GAAG,IAAI,GAAG,CAAC,GAAG,CAAC;QACtB,MAAM,aAAa,GAAG,CAAA,EAAG,CAAC,CAAC,QAAQ,CAAA,EAAG,CAAC,CAAC,MAAM,CAAA,CAAE;AAEhD,QAAA,MAAM,KAAK,GAAG,SAAS,EAAE;QACzB,MAAM,SAAS,GAAG,aAAa,CAAC;AAC9B,YAAA,MAAM,EAAE,aAAa;YACrB,MAAM;YACN,aAAa;YACb,KAAK;YACL,QAAQ;AACT,SAAA,CAAC;;QAGD,YAAY,CAAC,OAAe,IAAI,YAAY,CAAC,OAAO,IAAI,EAAE,CAAQ;AAClE,QAAA,YAAY,CAAC,OAAe,CAAC,eAAe,CAAC,GAAG,KAAK;AACrD,QAAA,YAAY,CAAC,OAAe,CAAC,mBAAmB,CAAC,GAAG,SAAS;;AAG9D,QAAA,OAAQ,YAAY,CAAC,OAAe,CAAC,wBAAwB,CAAC;;QAG9D,mBAAmB,CAAC,OAAO,EAAE,KAAK,EAAE,GAAG,EAAE,GAAG,CAAC;QAE7C,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,YAAY,CAAC;QAE/C,IAAI,CAAC,QAAQ,CAAC,EAAE,IAAI,QAAQ,CAAC,MAAM,KAAK,GAAG,EAAE;YAC3C,IAAI,KAAK,GAAG,EAAE;AACd,YAAA,IAAI;gBACF,KAAK,GAAG,MAAM,QAAQ,CAAC,KAAK,EAAE,CAAC,IAAI,EAAE;AACrC,gBAAA,IAAI,KAAK,CAAC,MAAM,GAAG,GAAG;oBAAE,KAAK,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,KAAK;YAC7D;YAAE,MAAM,EAAC;YACT,OAAO,CAAC,IAAI,CACV,CAAA,kBAAA,EAAqB,QAAQ,CAAC,MAAM,CAAA,IAAA,EAAO,GAAG,CAAA,EAAG,KAAK,GAAG,CAAA,GAAA,EAAM,KAAK,CAAA,CAAE,GAAG,EAAE,CAAA,CAAE,CAC9E;QACH;AAEA,QAAA,OAAO,QAAQ;IACjB;IAAE,OAAO,GAAQ,EAAE;QACjB,OAAO,CAAC,KAAK,CAAC,mCAAmC,EAAE,GAAG,EAAE,OAAO,CAAC;AAChE,QAAA,MAAM,GAAG;IACX;YAAU;QACR,YAAY,CAAC,OAAO,CAAC;IACvB;AACF;;AC5HA;AACA;AACA;AACA;AAOA,MAAM,cAAc,GAAG,kBAAkB;AACzC,MAAM,QAAQ,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,CAAC;AAEvB,eAAe,mBAAmB,CACvC,KAAU,EACV,EAAE,KAAK,EAAE,IAAI,EAAoC,EAAA;AAEjD,IAAA,IAAI,CAAC,KAAK;AAAE,QAAA,MAAM,IAAI,KAAK,CAAC,mBAAmB,CAAC;AAEhD,IAAA,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE;AAC1B,IAAA,MAAM,OAAO,GAAG,aAAa,EAAE;;AAG/B,IAAA,MAAM,WAAW,GAAI,MAAc,EAAE,QAAQ;AAC7C,IAAA,MAAM,aAAa,GAAI,KAAa,EAAE,QAAQ;IAE9C,MAAM,eAAe,GACnB,CAAC,WAAW,IAAI,WAAW,CAAC,QAAQ,KAAK,IAAI;SAC5C,aAAa,IAAI,aAAa,CAAC,QAAQ,KAAK,IAAI,CAAC;IAEpD,MAAM,UAAU,GAAG;AACjB,WAAG,WAAW,EAAE,EAAE;AACd,YAAA,aAAa,EAAE,EAAE;AAChB,YAAA,KAAa,EAAE,cAAc;AAC7B,YAAA,KAAa,EAAE,MAAM;AACtB,YAAA,SAAS;UACX,SAAS;;IAGb,IAAI,CAAC,UAAU,EAAE;QACf,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAiB,cAAc,CAAC;AAC1D,QAAA,IAAI,MAAM,EAAE,EAAE,EAAE;YACd,OAAO,EAAE,gBAAgB,EAAE,MAAM,CAAC,EAAE,EAAE,MAAM,EAAE,IAAI,EAAE;QACtD;IACF;AAEA,IAAA,MAAM,eAAe,GAAG,kBAAkB,EAAE;AAC5C,IAAA,MAAM,UAAU,GAAG,MAAM,aAAa,EAAE;;AAGxC,IAAA,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,CAAC;AACjC,QAAA,cAAc,EAAE,kBAAkB;AAClC,QAAA,GAAG,eAAe;AAClB,QAAA,GAAG,UAAU;AACd,KAAA,CAAC;;IAGF,MAAM,WAAW,GAAG;AAClB,UAAE,CAAA,EAAG,MAAM,CAAC,OAAO,CAAA,cAAA,EAAiB,kBAAkB,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC,CAAA;AAC1E,UAAE,CAAA,EAAG,MAAM,CAAC,OAAO,eAAe;AAEpC,IAAA,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,WAAW,EAAE;AAC1C,QAAA,MAAM,EAAE,MAAM;QACd,OAAO;QACP,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;AACtC,KAAA,CAAC;AAEF,IAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;AAChD,IAAA,MAAM,EAAE,gBAAgB,EAAE,GAAG,IAAI;IAEjC,IAAI,CAAC,gBAAgB,EAAE;AACrB,QAAA,MAAM,IAAI,KAAK,CAAC,yCAAyC,CAAC;IAC5D;AAEA,IAAA,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,EAAE,EAAE,EAAE,gBAAgB,EAAE,EAAE,QAAQ,CAAC;AAC/D,IAAA,OAAO,EAAE,gBAAgB,EAAE,MAAM,EAAE,KAAK,EAAE;AAC5C;;AC9EA;AACA;AACA;AACA;AAQA,MAAM,cAAc,GAAG,aAAa;AACpC,MAAM,gBAAgB,GAAG,EAAE,GAAG,EAAE,CAAC;AAQ1B,eAAe,eAAe,CACnC,KAAU,EACV,EAAE,gBAAgB,EAAE,MAAM,GAAG,IAAI,EAAE,UAAU,GAAG,gBAAgB,EAAO,EAAA;AAEvE,IAAA,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE;AAC1B,IAAA,MAAM,OAAO,GAAG,aAAa,EAAE;IAE/B,MAAM,MAAM,GAAG,OAAO,CAAC,GAAG,CAAiB,cAAc,CAAC;AAC1D,IAAA,MAAM,OAAO,GAAG,MAAM,IAAI,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE;IAEvD,IAAI,OAAO,EAAE;QACX,iBAAiB,CAAC,KAAK,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,CAAC;QAC9D,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE;IAC/C;AAEA,IAAA,IAAI;AACF,QAAA,MAAM,eAAe,GAAG,kBAAkB,EAAE;AAC5C,QAAA,MAAM,UAAU,GAAG,MAAM,aAAa,EAAE;;AAGxC,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,CAAC;AACjC,YAAA,oBAAoB,EAAE,gBAAgB;AACtC,YAAA,GAAG,eAAe;AAClB,YAAA,GAAG,UAAU;AACd,SAAA,CAAC;;AAGN,QAAA,MAAM,OAAO,GAAG;YACd,SAAS,EAAE,MAAM,CAAC,QAAQ;AAC1B,YAAA,MAAM,EAAE,MAAM,IAAI,MAAM,CAAC,KAAM;YAC/B,gBAAgB;SACjB;AAED,QAAA,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,MAAM,CAAC,OAAO,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,eAAe,EAAE;AAClF,YAAA,MAAM,EAAE,MAAM;YACd,OAAO;AACP,YAAA,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,OAAO,CAAC;AAC9B,SAAA,CAAC;QAEE,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,IAAI,MAAM,EAAE,IAAI,EAAE;YACvC,MAAM,CAAC,SAAS,GAAG,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,IAAI;YACjD,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,MAAM,EAAE,UAAU,CAAC;AAC/C,YAAA,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,EAAE;QAC5D;AAEA,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE;AAC9B,QAAA,OAAO,CAAC,GAAG,CAAC,sCAAsC,EAAE,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC;AAClF,QAAA,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,SAAS;AAElD,QAAA,MAAM,KAAK,GAAmB;YAC5B,IAAI;YACJ,IAAI;YACJ,SAAS,EAAE,IAAI,CAAC,GAAG,EAAE,GAAG,UAAU,GAAG,IAAI;SAC1C;QACD,OAAO,CAAC,GAAG,CAAC,cAAc,EAAE,KAAK,EAAE,UAAU,CAAC;AAE9C,QAAA,OAAO,EAAE,IAAI,EAAE,SAAS,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,CAAC,MAAM,EAAE;IACxD;IAAE,OAAO,GAAG,EAAE;AACZ,QAAA,IAAI,MAAM,EAAE,IAAI,EAAE;AAChB,YAAA,OAAO,EAAE,IAAI,EAAE,MAAM,CAAC,IAAI,EAAE,SAAS,EAAE,IAAI,EAAE,KAAK,EAAE,MAAM,CAAC,GAAG,CAAC,EAAE;QACnE;AACA,QAAA,MAAM,GAAG;IACX;AACF;AAEA,eAAe,iBAAiB,CAAC,KAAU,EAAE,gBAAwB,EAAE,MAAqB,EAAE,UAAkB,EAAA;AAC9G,IAAA,IAAI;AACF,QAAA,MAAM,eAAe,CAAC,KAAK,EAAE,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACxE;AAAE,IAAA,MAAM;;IAER;AACF;;AC3FA;AACA;AACA;AACA;AAuBA;;;AAGG;AACG,SAAU,iBAAiB,CAAC,GAAgB,EAAA;AAChD,IAAA,MAAM,KAAK,GAAGA,iBAA8B,EAAE;AAC9C,IAAA,MAAM,OAAO,GAAG,aAAa,EAAE;IAC/B,IAAI,WAAW,GAAG,KAAK;AAEvB,IAAA,eAAe,IAAI,GAAA;AACjB,QAAA,IAAI,WAAW;YAAE;;QAGjB,MAAM,YAAY,GAChB,4EAA4E;QAE9E,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE;YACpC,MAAM,IAAI,KAAK,CAAC,CAAA,kDAAA,EAAqD,GAAG,CAAC,QAAQ,CAAA,CAAA,CAAG,CAAC;QACvF;QAEA,IAAI,CAAC,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,KAAK,CAAC,EAAE;YACjC,MAAM,IAAI,KAAK,CAAC,CAAA,+CAAA,EAAkD,GAAG,CAAC,KAAK,CAAA,CAAA,CAAG,CAAC;QACjF;;AAGA,QAAA,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC;;AAGf,QAAA,IAAI;AACF,YAAA,MAAM,GAAG,GAAG,MAAM,UAAU,EAAE;AAC9B,YAAA,OAAO,CAAC,GAAG,CAAC,CAAA,6BAAA,EAAgC,GAAG,CAAC,OAAO,CAAA,MAAA,EAAS,GAAG,CAAC,GAAG,IAAI,GAAG,CAAA,CAAA,CAAG,CAAC;QACpF;QAAE,OAAO,GAAQ,EAAE;YACjB,OAAO,CAAC,IAAI,CAAC,8BAA8B,EAAE,GAAG,EAAE,OAAO,CAAC;QAC5D;QAEA,WAAW,GAAG,IAAI;IACpB;AAEA,IAAA,SAAS,iBAAiB,GAAA;QACxB,IAAI,CAAC,WAAW,EAAE;AAChB,YAAA,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC;QAC5E;IACF;;;;AAKA,IAAA,eAAe,YAAY,CAAC,EAAE,KAAK,EAAE,IAAI,EAAoC,EAAA;AAC3E,QAAA,iBAAiB,EAAE;QACnB,OAAO,mBAAmB,CAAC,KAAK,EAAE,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;IACpD;IAEA,eAAe,QAAQ,CAAC,EACtB,gBAAgB,EAChB,MAAM,GAAG,IAAI,EACb,UAAU,GAKX,EAAA;AACC,QAAA,iBAAiB,EAAE;AACnB,QAAA,OAAO,eAAe,CAAC,KAAK,EAAE,EAAE,gBAAgB,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;IACzE;;;;IAKA,eAAe,OAAO,CAAC,EACrB,gBAAgB,EAChB,MAAM,GAAG,IAAI,GAId,EAAA;AACC,QAAA,iBAAiB,EAAE;AAEnB,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE;AAC1B,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,CAAC;AACjC,YAAA,oBAAoB,EAAE,gBAAgB;AACvC,SAAA,CAAC;;AAGF,QAAA,MAAM,GAAG,GAAG,CAAA,EAAG,MAAM,CAAC,OAAO,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,uBAAuB;AACxE,QAAA,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,EAAE;AAClC,YAAA,MAAM,EAAE,MAAM;YACd,OAAO;AACR,SAAA,CAAC;AAEF,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC;AAEhD,QAAA,MAAM,QAAQ,GACZ,IAAI,CAAC,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,GAAG,OAAO,GAAG,IAAI,CAAC,EAAE,GAAG,OAAO,GAAG,OAAO;QAEpF,OAAO;YACL,QAAQ;YACR,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,QAAQ,KAAK,OAAO;YAC7B,OAAO,EAAE,QAAQ,KAAK,OAAO;AAC7B,YAAA,IAAI,EAAE,IAAI;SACX;IACH;AAEI,IAAA,eAAe,YAAY,CAAC,EAC5B,gBAAgB,EAChB,QAAQ,EACR,MAAM,GAAG,MAAM,EACf,IAAI,GAAG,EAAE,GAMV,EAAA;AACC,QAAA,iBAAiB,EAAE;AAEnB,QAAA,MAAM,MAAM,GAAG,KAAK,CAAC,GAAG,EAAE;AAC1B,QAAA,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,EAAE,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC;QAElD,IAAI,CAAC,IAAI,EAAE;AACT,YAAA,MAAM,IAAI,KAAK,CAAC,0DAA0D,CAAC;QAC7E;QAEA,IAAI,CAAC,QAAQ,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,GAAG,CAAC,EAAE;AAC1C,YAAA,MAAM,IAAI,KAAK,CAAC,wCAAwC,CAAC;QAC3D;AAEA,QAAA,MAAM,OAAO,GAAG,KAAK,CAAC,YAAY,CAAC;AACjC,YAAA,oBAAoB,EAAE,gBAAgB;AACtC,YAAA,mBAAmB,EAAE,MAAM;AAC5B,SAAA,CAAC;QAEF,MAAM,IAAI,GAAG,MAAM,WAAW,CAAC,GAAG,IAAI,CAAA,EAAG,QAAQ,CAAA,CAAE,EAAE;AACnD,YAAA,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE;YAC5B,OAAO;YACP,IAAI,EAAE,CAAC,KAAK,EAAE,MAAM,CAAC,CAAC,QAAQ,CAAC,MAAM,CAAC,WAAW,EAAE,CAAC,GAAG,SAAS,GAAG,IAAI;AACxE,SAAA,CAAC;AAEF,QAAA,MAAM,IAAI,GAAG,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC;QAC9C,IAAI,IAAI,GAAQ,IAAI;AAEpB,QAAA,IAAI;AACF,YAAA,IAAI,GAAG,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,GAAG,EAAE;QACrC;QAAE,MAAM,EAAC;AAET,QAAA,MAAM,QAAQ,GACZ,IAAI,CAAC,MAAM,KAAK,GAAG,IAAI,IAAI,CAAC,MAAM,KAAK,GAAG,GAAG,OAAO,GAAG,IAAI,CAAC,EAAE,GAAG,OAAO,GAAG,OAAO;QAEpF,OAAO;YACL,QAAQ;YACR,MAAM,EAAE,IAAI,CAAC,MAAM;YACnB,OAAO,EAAE,QAAQ,KAAK,OAAO;YAC7B,OAAO,EAAE,QAAQ,KAAK,OAAO;YAC7B,QAAQ;AACR,YAAA,MAAM,EAAE,MAAM,CAAC,WAAW,EAAE;YAC5B,IAAI;SACL;IACH;AAEI,IAAA,SAAS,wBAAwB,GAAA;AACnC,QAAA,OAAO,eAAe,uBAAuB,CAAC,GAAQ,EAAE,GAAQ,EAAA;AAC9D,YAAA,IAAI;AACF,gBAAA,MAAM,QAAQ,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,QAAQ,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE;AACzD,gBAAA,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,MAAM,IAAI,MAAM,CAAC,CAAC,WAAW,EAAE;AAChE,gBAAA,MAAM,IAAI,GAAG,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM;gBACnE,MAAM,gBAAgB,GAAG,MAAM,CAC7B,GAAG,CAAC,KAAK,EAAE,gBAAgB;AACzB,oBAAA,GAAG,CAAC,OAAO,GAAG,oBAAoB,CAAC;AACnC,oBAAA,iBAAiB,CACpB,CAAC,IAAI,EAAE;AAER,gBAAA,MAAM,MAAM,GAAG,MAAM,YAAY,CAAC;oBAChC,gBAAgB;oBAChB,QAAQ;oBACR,MAAM;AACN,oBAAA,IAAI,EAAE,EAAE;AACT,iBAAA,CAAC;gBAEF,IAAI,IAAI,EAAE;AACR,oBAAA,OAAO;yBACJ,MAAM,CAAC,GAAG;AACV,yBAAA,IAAI,CAAC,CAAA;;;;;;;;;;;;;AAaK,uBAAA,EAAA,MAAM,CAAC,MAAM,CAAA,CAAA,EAAI,MAAM,CAAC,QAAQ,CAAA;AAChC,uBAAA,EAAA,MAAM,CAAC,MAAM,CAAA;AACJ,gCAAA,EAAA,MAAM,CAAC,OAAO,GAAG,OAAO,GAAG,IAAI,CAAA,EAAA,EAAK,MAAM,CAAC,QAAQ,CAAA;WAC1E,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,CAAA;;AAElC,OAAA,CAAA,CAAC;gBACC;gBAEA,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,MAAM,CAAC;YACrC;YAAE,OAAO,GAAQ,EAAE;AACjB,gBAAA,MAAM,OAAO,GAAG;AACd,oBAAA,KAAK,EAAE,GAAG,EAAE,OAAO,IAAI,mBAAmB;iBAC3C;AAED,gBAAA,IAAI,MAAM,CAAC,GAAG,CAAC,KAAK,EAAE,IAAI,IAAI,EAAE,CAAC,CAAC,WAAW,EAAE,KAAK,MAAM,EAAE;AAC1D,oBAAA,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,kCAAkC,OAAO,CAAC,KAAK,CAAA,MAAA,CAAQ,CAAC;gBACtF;gBAEA,OAAO,GAAG,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,OAAO,CAAC;YACtC;AACF,QAAA,CAAC;IACH;;;;IAKF,OAAO;QACL,IAAI;QACJ,YAAY;QACZ,QAAQ;QACR,OAAO;QACP,YAAY;QACZ,wBAAwB;QACxB,OAAO;KACR;AACH;;AC/PA;AACA;AACA;AACA;AAEA;AAeA,OAAO,CAAC,GAAG,CAAC,kCAAkC,CAAC;;;;"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "zubbl-sdk",
3
- "version": "1.1.44",
3
+ "version": "1.1.45",
4
4
  "type": "module",
5
5
  "description": "Zubbl SDK for secure policy enforcement (browser, Node, universal)",
6
6
  "main": "dist/zubbl-sdk.cjs.js",