@blotout/qinto-cli 0.1.27 → 0.1.29

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.
@@ -19564,13 +19564,13 @@ var variableSchema = external_exports.object({
19564
19564
  label: external_exports.string().min(1).max(100),
19565
19565
  required: external_exports.boolean().optional(),
19566
19566
  browser: external_exports.boolean().optional(),
19567
- owner: external_exports.enum(["site", "developer"]).optional(),
19567
+ owner: external_exports.enum(["site", "developer", "app"]).optional(),
19568
19568
  helpText: external_exports.string().min(1).max(MAX_VARIABLE_HELP_TEXT).optional(),
19569
19569
  helpUrl: httpsUrl("helpUrl").optional()
19570
19570
  }).strict().refine((variable) => !(variable.kind === "secret" && variable.browser === true), {
19571
19571
  message: "A secret variable can never be browser-exposed"
19572
- }).refine((variable) => !(variable.required === true && variable.owner === "developer"), {
19573
- message: "A developer-owned variable cannot be required"
19572
+ }).refine((variable) => !(variable.required === true && (variable.owner === "developer" || variable.owner === "app")), {
19573
+ message: "A developer- or app-owned variable cannot be required"
19574
19574
  });
19575
19575
  var appVariableSchema = external_exports.object({
19576
19576
  name: external_exports.string().min(1).max(64).regex(VARIABLE_NAME),
@@ -20056,11 +20056,16 @@ var MAX_PUSH_BYTES = 16 * 1024;
20056
20056
  var MAX_RESPONSE_BYTES = 1024 * 1024;
20057
20057
  var MAX_RPC_BYTES = 128 * 1024;
20058
20058
  var installSchema = external_exports.object({ id: external_exports.string().min(1).max(64), ord: external_exports.number().int().min(1), label: external_exports.string().max(100) }).strict();
20059
- var emitSchema = external_exports.object({ type: external_exports.literal("track"), occurredAt: external_exports.number().int().nonnegative().safe(), payload: external_exports.record(external_exports.string(), external_exports.unknown()) }).strict();
20060
20059
  var installRuleSchema = external_exports.object({
20061
20060
  mode: external_exports.enum(["except", "only"]),
20062
20061
  installIds: external_exports.array(external_exports.string().min(1).max(64)).max(MAX_APPS_PER_DOMAIN * MAX_INSTALLS_PER_APP)
20063
20062
  }).strict();
20063
+ var emitSchema = external_exports.object({
20064
+ type: external_exports.literal("track"),
20065
+ occurredAt: external_exports.number().int().nonnegative().safe(),
20066
+ payload: external_exports.record(external_exports.string(), external_exports.unknown()),
20067
+ installs: installRuleSchema.optional()
20068
+ }).strict();
20064
20069
  var pushSchema = external_exports.object({ topic: external_exports.string().min(1).max(64), data: external_exports.unknown(), broadcast: external_exports.enum(PUSH_BROADCASTS).optional() }).strict().refine((push) => {
20065
20070
  return new TextEncoder().encode(JSON.stringify(push.data ?? null)).length <= MAX_PUSH_BYTES;
20066
20071
  }, "Push data exceeds the per-message size cap");
@@ -20083,6 +20088,7 @@ var effectGroupSchema = external_exports.object({
20083
20088
  }).strict();
20084
20089
  var captureValueSchema = external_exports.object({ value: external_exports.string().max(512), createdAt: external_exports.number().int(), updatedAt: external_exports.number().int(), type: external_exports.enum(CAPTURE_TYPES) }).strict();
20085
20090
  var pageSchema = external_exports.object({ url: external_exports.string().min(1).max(4096), referrer: external_exports.string().min(1).max(4096).optional() }).strict();
20091
+ var sessionSchema = external_exports.object({ id: external_exports.string().min(1).max(64), isNew: external_exports.boolean(), startedAt: external_exports.number().int().nonnegative().safe() }).strict();
20086
20092
  var actionContextFields = {
20087
20093
  occurredAt: external_exports.number().int().nonnegative().safe(),
20088
20094
  page: pageSchema.optional(),
@@ -20092,7 +20098,7 @@ var actionContextFields = {
20092
20098
  locale: external_exports.string().min(1).max(64).optional(),
20093
20099
  provenance: external_exports.enum(["edge", "caller"])
20094
20100
  }).strict().optional(),
20095
- session: external_exports.object({ id: external_exports.string().min(1).max(64), isNew: external_exports.boolean(), startedAt: external_exports.number().int().nonnegative().safe() }).strict().optional()
20101
+ session: sessionSchema.optional()
20096
20102
  };
20097
20103
  var actionContextSchema = external_exports.discriminatedUnion("source", [
20098
20104
  external_exports.object({ source: external_exports.literal("browser"), ...actionContextFields }).strict(),
@@ -20113,8 +20119,9 @@ var envelopeRequestSchema = external_exports.object({
20113
20119
  }).strict().optional(),
20114
20120
  consent: external_exports.object({ enabled: external_exports.boolean(), categories: external_exports.record(external_exports.string(), external_exports.boolean()), apps: external_exports.record(external_exports.string(), external_exports.boolean()) }).strict().optional(),
20115
20121
  geo: external_exports.record(external_exports.string(), external_exports.unknown()).optional(),
20116
- // Connect envelopes only: the page the visitor's socket opened from.
20122
+ // Connect envelopes only: the page the visitor's socket opened from, and the visit session it joined.
20117
20123
  page: pageSchema.optional(),
20124
+ session: sessionSchema.optional(),
20118
20125
  // Only what this app captured or wrote for this visitor; `updatedAt` is when the current value
20119
20126
  // was first seen, which is the click time a CAPI `fbc` is built from.
20120
20127
  captures: external_exports.record(external_exports.string().max(64), captureValueSchema).optional(),
@@ -20987,6 +20994,16 @@ var checkEmittedEvent = (event) => {
20987
20994
  }
20988
20995
  return { ...event, occurredAt };
20989
20996
  };
20997
+ var withInstallRule = (emit, installs) => {
20998
+ if (installs === void 0) {
20999
+ return emit;
21000
+ }
21001
+ const parsed = installRuleSchema.safeParse(installs);
21002
+ if (!parsed.success) {
21003
+ throw new Error("an emitted event installs rule must be { mode: except | only, installIds: string[] }");
21004
+ }
21005
+ return { ...emit, installs: parsed.data };
21006
+ };
20990
21007
 
20991
21008
  // src/read-body.ts
20992
21009
  var MAX_ENVELOPE_BYTES = 1024 * 1024;
@@ -21647,6 +21664,41 @@ var asyncContext = (env, subject) => {
21647
21664
  };
21648
21665
  };
21649
21666
 
21667
+ // src/currency.ts
21668
+ var rateBetween = (rates, from, to) => {
21669
+ const source = from.trim().toUpperCase();
21670
+ const target = to.trim().toUpperCase();
21671
+ if (!Object.hasOwn(rates, source) || !Object.hasOwn(rates, target)) {
21672
+ return null;
21673
+ }
21674
+ return rates[source] / rates[target];
21675
+ };
21676
+ var buildCurrency = (env) => {
21677
+ let snapshot;
21678
+ const load = () => {
21679
+ snapshot ??= brokerCurrencyRates(env).catch((error61) => {
21680
+ snapshot = void 0;
21681
+ throw new Error("the platform currency rates are not available", { cause: error61 });
21682
+ });
21683
+ return snapshot;
21684
+ };
21685
+ return {
21686
+ convert: async (amount, from, to) => {
21687
+ const rate = rateBetween((await load()).rates, from, to);
21688
+ return rate === null ? null : amount * rate;
21689
+ },
21690
+ rate: async (from, to) => {
21691
+ return rateBetween((await load()).rates, from, to);
21692
+ },
21693
+ list: async () => {
21694
+ return Object.keys((await load()).rates).sort();
21695
+ },
21696
+ updatedAt: async () => {
21697
+ return new Date((await load()).fetchedAt);
21698
+ }
21699
+ };
21700
+ };
21701
+
21650
21702
  // src/workflow.ts
21651
21703
  var stampParams = (stamp, payload) => {
21652
21704
  return { q: stamp, payload };
@@ -21702,6 +21754,7 @@ var buildWorkflowContext = (env, stamp) => {
21702
21754
  userId: stamp.anonId,
21703
21755
  observability: buildObservability(stamp.ord),
21704
21756
  identity: buildIdentity(env),
21757
+ currency: buildCurrency(env),
21705
21758
  context: asyncContext(env, (what) => {
21706
21759
  return requireSubject(stamp.anonId, what);
21707
21760
  }),
@@ -21787,9 +21840,9 @@ var buildContext = ({
21787
21840
  geo: envelope.geo,
21788
21841
  // Collect one entry past the per-install cap: the platform rejects an over-limit group whole,
21789
21842
  // and the extra entry keeps it visibly over while bounding memory.
21790
- emit: (event) => {
21843
+ emit: (event, options) => {
21791
21844
  requireSubject(subject, "emit");
21792
- const checked = checkEmittedEvent(event);
21845
+ const checked = withInstallRule(checkEmittedEvent(event), options?.installs);
21793
21846
  if (emits.length <= MAX_EMITS_PER_INSTALL) {
21794
21847
  emits.push(checked);
21795
21848
  }
@@ -21837,40 +21890,6 @@ var buildContext = ({
21837
21890
  };
21838
21891
  };
21839
21892
 
21840
- // src/currency.ts
21841
- var rateBetween = (rates, from, to) => {
21842
- const source = from.trim().toUpperCase();
21843
- const target = to.trim().toUpperCase();
21844
- if (!Object.hasOwn(rates, source) || !Object.hasOwn(rates, target)) {
21845
- return null;
21846
- }
21847
- return rates[source] / rates[target];
21848
- };
21849
- var buildCurrency = (env) => {
21850
- let snapshot;
21851
- const load = () => {
21852
- snapshot ??= brokerCurrencyRates(env).catch((error61) => {
21853
- throw new Error("the platform currency rates are not available", { cause: error61 });
21854
- });
21855
- return snapshot;
21856
- };
21857
- return {
21858
- convert: async (amount, from, to) => {
21859
- const rate = rateBetween((await load()).rates, from, to);
21860
- return rate === null ? null : amount * rate;
21861
- },
21862
- rate: async (from, to) => {
21863
- return rateBetween((await load()).rates, from, to);
21864
- },
21865
- list: async () => {
21866
- return Object.keys((await load()).rates).sort();
21867
- },
21868
- updatedAt: async () => {
21869
- return new Date((await load()).fetchedAt);
21870
- }
21871
- };
21872
- };
21873
-
21874
21893
  // src/install-span.ts
21875
21894
  var installSpan = (install, run) => {
21876
21895
  return traced(
@@ -23094,7 +23113,13 @@ var dispatch = async (envelope, versions, env) => {
23094
23113
  if (handler === void 0) {
23095
23114
  return jsonError(200, "missing handler: onConnect");
23096
23115
  }
23097
- return runInstalls(envelope, env, (ctx) => handler({ ...ctx, ...envelope.page === void 0 ? {} : { page: envelope.page } }));
23116
+ return runInstalls(envelope, env, (ctx) => {
23117
+ return handler({
23118
+ ...ctx,
23119
+ ...envelope.page === void 0 ? {} : { page: envelope.page },
23120
+ ...envelope.session === void 0 ? {} : { session: envelope.session }
23121
+ });
23122
+ });
23098
23123
  }
23099
23124
  case "transform": {
23100
23125
  return dispatchTransform(envelope, bundle, env);
@@ -0,0 +1 @@
1
+ (function(){var e=()=>{},t=t=>{t.config?.autoCapture?.pageLoad===!0&&t.q.push([`track`,[`PageView`],e,e])},n=class extends Error{constructor(e){super(e),this.name=`QintoError`}},r=class extends n{constructor(e){super(e),this.name=`QintoTimeoutError`}},i=(e=Date.now())=>`evt_${globalThis.crypto.randomUUID()}_${e}`,a=(e,t)=>{if(e!==void 0)return e;let n=t?.orderId;return typeof n==`string`&&n!==``?n:i()},o=[`necessary`,`functional`,`analytics`,`marketing`,`salesOfData`],s=[`then`,`ready`,`config`],c=()=>{},l=(e,t)=>(...n)=>{let r=new Promise((r,i)=>{e.q.push([t,n,r,i])});return r.catch(c),r},u=e=>{let t=e;return t._q=1,t.q=[],new Proxy(t,{get:(e,n)=>typeof n!=`string`||s.includes(n)||n in t?Reflect.get(t,n):(t[n]=l(t,n),t[n])})},d=()=>{let e=document.currentScript?.dataset.qintoGlobal;return typeof e==`string`&&e!==``?e:`qinto`},f=e=>typeof e==`object`&&!!e&&e._q===1,p=(e=`qinto`)=>{let t=globalThis;if(e in t){let n=t[e];if(!f(n))return null;let r=Array.isArray(n.q)?n:u(n);return r!==n&&Object.defineProperty(t,e,{value:r,writable:!0,enumerable:!0,configurable:!0}),r}let n=u({});return Object.defineProperty(t,e,{value:n,writable:!0,enumerable:!0,configurable:!0}),n},m=(e,t)=>async(r,i)=>{let a=Reflect.get(e,r);if(typeof a!=`function`)throw new n(`[Qinto] ${t}.${r} is not a method of this tag.`);return a.apply(e,Array.from(i))},ee=e=>()=>Promise.reject(e),h=(e,t)=>{let[n,r,i,a]=t;e(n,r).then(i,a)},g=e=>{let t=[];return t.push=(...t)=>{for(let n of t)h(e,n);return 0},t},_=(e,t,n=`window.qinto`)=>{let r=e.ready;if(r!==void 0)return r;let i=e,a=e=>{let t=i.q;i.q=g(e);for(let n of t)h(e,n)},o=t().then(e=>{a(m(e,n))},e=>{throw a(ee(e)),e});return o.catch(c),i.ready=o,o},v=(e,t,n)=>n===void 0||!o.some(e=>e===n)?!1:n===`necessary`||e!==null&&e.categories[n]===!0&&e.apps[t]!==!1,y=(e,t)=>e.config?.gpc===!0&&navigator.globalPrivacyControl===!0&&(t===`marketing`||t===`salesOfData`),b=(e,t,n)=>{let r=e.config?.apps?.[t]?.category;return y(e,r)?!1:e.config?.consentConfiguration?.enabled!==!0||v(n,t,r)},x=e=>Object.values(e.config?.apps??{}).some(e=>e.category!==`necessary`||e.capture!==void 0),te=(e,t,n,r)=>b(e,t,n)?r===void 0||b(e,t,r):!1,S=e=>{let{categories:t,apps:n}=e;if(typeof t==`object`&&t&&typeof n==`object`&&n)return{categories:t,apps:n}},ne=()=>{},C=(e,t)=>{console.error(`[Qinto] A handler of app "${e.slug}" (install "${e.installId}") failed.`,t)},w=(e,t,n)=>{for(let r of t)try{let t=r(n);t instanceof Promise&&t.catch(t=>{C(e,t)})}catch(t){C(e,t)}},T=(e,t,n,r)=>{e.activated.add(r.id);let i={slug:t,installId:r.id,eventHandlers:[],transformHooks:[],consentHandlers:[],pushHandlers:[],sharedContextHandlers:[]};e.instances.push(i);let a={variables:r.variables,install:{id:r.id,label:r.label},getSession:async()=>{let n=await e.client.getSession();return e.target.config?.apps?.[t]?.geo===!0?n:{...n,ip:null,geo:null}},track:(t,n)=>{e.client.track(t,n).catch(ne)},onEvent:e=>{i.eventHandlers.push(e)},onTransform:e=>{if(r.transform!==!0){console.error(`[Qinto] App "${t}" registers a transform hook without declaring browser.hooks: ["transform"].`);return}i.transformHooks.push(e)},onConsent:e=>{i.consentHandlers.push(e)},onPush:e=>{i.pushHandlers.push(e)},fetch:async(n,i)=>{let a=new URL(`${e.client.destination}/app/${t}${n}`);if(!n.startsWith(`/`)||!a.pathname.startsWith(`/app/${t}/`))throw TypeError(`[Qinto] App "${t}" fetched "${n}"; the path must be absolute and stay inside the app.`);let o=new Headers(i?.headers);return o.set(`x-qinto-install`,r.id),fetch(a,{...i,headers:o,credentials:`include`})},onSharedContext:n=>{if(e.target.config?.apps?.[t]?.sharedContext!==!0){console.error(`[Qinto] App "${t}" reads shared context without declaring the sharedContext capability.`);return}i.sharedContextHandlers.push(n),e.sharedContext!==null&&te(e.target,t,e.consent,e.sharedContextConsent)&&w(i,[n],e.sharedContext)}};try{n(a)}catch(e){console.error(`[Qinto] App "${t}" failed to activate install "${r.id}".`,e)}},E=100,D=1024,O=32768,re=e=>{let t;try{t=JSON.stringify(e)}catch{return}if(!(t===void 0||new TextEncoder().encode(t).length>D))return JSON.parse(t)},ie=e=>{let t={};for(let n of e){if(n.settled!==n.total||n.values.length!==1)continue;let e=re(n.values[0]);if(e===void 0)continue;let r={...t[n.source.slug]??{},[n.source.installId]:e},i={...t,[n.source.slug]:r};new TextEncoder().encode(JSON.stringify(i)).length<=O&&(t[n.source.slug]=r)}return Object.keys(t).length===0?void 0:t},ae=async(e,t,{declares:n,notify:r,report:i})=>{let a=[],o=[];for(let s of e){if(!n(s)){r(s);continue}let e={source:s,total:s.eventHandlers.length,settled:0,values:[]};a.push(e);for(let n of s.eventHandlers){let r;try{r=n(t)}catch(t){e.settled+=1,i(s,t);continue}o.push(Promise.resolve(r).then(t=>{e.settled+=1,t!==void 0&&e.values.push(t)},t=>{e.settled+=1,i(s,t)}))}}if(o.length>0){let e,t=new Promise(t=>{e=setTimeout(t,E)});await Promise.race([Promise.all(o),t]),clearTimeout(e)}return ie(a)},oe=(e,t)=>{if(e.mode===`except`&&t.mode===`except`)return{mode:`except`,installIds:[...new Set([...e.installIds,...t.installIds])]};let[n,r]=e.mode===`only`?[e,t]:[t,e],i=new Set(r.installIds);return{mode:`only`,installIds:n.installIds.filter(e=>i.has(e)===(r.mode===`only`))}},se=(e,t,n,r)=>{let i;try{i=t(n,r)}catch(t){C(e,t);return}if(i===void 0||i===!1)return i;let a=i?.installs;if((a?.mode===`except`||a?.mode===`only`)&&Array.isArray(a.installIds))return a;C(e,TypeError(`A transform hook returned neither nothing, false, nor { installs }.`))},ce=(e,t,n,r)=>{let i=r;for(let r of e)for(let e of r.transformHooks){let a=se(r,e,t,n);if(a===!1)return!1;a!==void 0&&(i=i===void 0?a:oe(i,a))}return i},k=(e,t)=>{let{app:n,install:r,topic:i,to:a}=e;return typeof n!=`string`||typeof i!=`string`||r!==void 0&&typeof r!=`string`||t&&!(Array.isArray(a)&&a.every(e=>typeof e==`string`))},A=(e,t,n,r)=>r===null?e.slug===t&&(n===void 0||n===e.installId):r.has(e.slug),j=e=>`_appInstalls`in e?e._appInstalls:void 0,M=(e,t,n)=>{if(!b(e.target,t,e.consent))return;let r=(j(e.target)?.[t]??[]).filter(t=>!e.activated.has(t.id)&&(t.geoFilter!==!0||e.geoAllowed.has(t.id)));if(r.length===0)return;let i=n.factory;if(i===void 0){try{i=n.loader()}catch(e){i=null,console.error(`[Qinto] App "${t}" failed to load.`,e)}e.apps.set(t,{...n,factory:i})}if(i!==null)for(let n of r)T(e,t,i,n)},N=(e,t)=>{let n=e;n.consent=t,n.sharedContextConsent=void 0;for(let n of e.instances)w(n,n.consentHandlers,t);e.onConsentSettled?.(t);for(let[t,n]of e.apps)M(e,t,n)},P=async e=>{try{N(e,await e.client.getConsent())}catch(e){console.error(`[Qinto] The apps consent read failed.`,e)}},F=async e=>{if(e.geoRequested||!Object.values(j(e.target)??{}).some(e=>e.some(e=>e.geoFilter===!0)))return;let t=e;t.geoRequested=!0;try{t.geoAllowed=new Set(await e.client.getGeoInstalls())}catch(e){console.error(`[Qinto] The geo filter read failed; geo-filtered installs stay off on this page.`,e);return}for(let[t,n]of e.apps)M(e,t,n)},I=async(e,t,n)=>{e.onPageEvent?.(e.consent);let r=new Set(n?.installIds);return ae(e.instances.filter(t=>b(e.target,t.slug,e.consent)&&(n===void 0||r.has(t.installId)===(n.mode===`only`))),t,{declares:n=>e.target.config?.apps?.[n.slug]?.eventResults?.includes(t.type)===!0,notify:e=>{w(e,e.eventHandlers,t)},report:C})},L=e=>{let{client:t}=e;return{track:async(n,r,i)=>{let o=a(i?.eventId,r),s=t.actionContext(),c={type:`track`,event:n,eventId:o,properties:r??{}},l=i?.installs,u=ce(e.instances,c,s.page.url,l);if(u===!1)return{eventId:o};let d=await I(e,c,u);return await t.submitTrack({event:n,eventId:o,properties:r,context:s,appResults:d,installs:l}),{eventId:o}},identify:async(n,r)=>{let i=t.actionContext(),a=await I(e,{type:`identify`,event:`identify`,properties:n??{}});return t.submitIdentify({traits:n,id:r,context:i,appResults:a})},alias:t.alias,consent:async n=>{if(await t.submitConsent(n,t.actionContext()),e.onConsentMutation?.(),x(e.target)){let t=e;t.consent=null,await P(e)}},getAnonId:t.getAnonId,getConsent:t.getConsent,getSession:t.getSession,close:t.close}},R=(e,t)=>{let n=new Map,r=null,i=null,a=e=>{let[t,i]=e;if(n.has(t))return;let a={loader:i};n.set(t,a),r?.(t,a)},o=e,s=`_apps`in o?o._apps:void 0,c=Array.isArray(s)?s:[];c.push=(...e)=>{for(let t of e)a(t);return 0},o._apps=c;for(let e of c.splice(0))a(e);return{sharedContext:e=>{let{context:t}=e;if(typeof t!=`object`||!t||Array.isArray(t)){console.error(`[Qinto] The server sent a malformed shared context.`,e);return}let n=i;if(n===null)return;n.sharedContext=t;let r=S(e),a=r??n.consent;n.sharedContextConsent=r;for(let e of n.instances)b(n.target,e.slug,a)&&w(e,e.sharedContextHandlers,n.sharedContext)},push:e=>{let{app:t,install:n,topic:r,scope:a,to:o}=e,s=a===`site`;if(k(e,s)){console.error(`[Qinto] The server sent a malformed app push.`,e);return}let c=i;if(c===null)return;let l=s?new Set(o):null,u={topic:r,data:e.data,from:t};for(let e of c.instances)A(e,t,n,l)&&b(c.target,e.slug,c.consent)&&w(e,e.pushHandlers,u)},connect:async a=>{let o={target:e,client:a,apps:n,instances:[],activated:new Set,consent:null,geoAllowed:new Set,geoRequested:!1,sharedContext:i?.sharedContext??null,sharedContextConsent:i?.sharedContextConsent,onConsentSettled:t?.onConsentSettled,onConsentMutation:t?.onConsentMutation,onPageEvent:t?.onPageEvent};i=o,r=(e,t)=>{M(o,e,t),o.consent===null&&o.target.config?.consentConfiguration?.enabled===!0&&o.target.config?.apps?.[e]?.category!==`necessary`&&P(o),F(o)};for(let[e,t]of n)M(o,e,t);let s=F(o);return e.config?.consentConfiguration?.enabled===!0&&x(e)?await P(o):o.onConsentSettled?.(o.consent),await s,L(o)}}},z=512,B=864e5,V=e=>Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Object.fromEntries(Object.entries(t).map(([e,t])=>[e,t.value]))])),H=(e,t)=>`qinto:cap:${encodeURIComponent(e)}:${encodeURIComponent(t)}`,U=e=>{try{let t=window.sessionStorage.getItem(e);if(t===null)return null;let n=JSON.parse(t);return typeof n.at!=`number`||typeof n.anonId!=`string`||typeof n.apps!=`object`||n.apps===null||Date.now()-n.at>B?null:{at:n.at,anonId:n.anonId,apps:n.apps}}catch{return null}},W=(e,t)=>{try{window.sessionStorage.setItem(e,JSON.stringify(t))}catch{}},G=e=>{try{window.sessionStorage.removeItem(e)}catch{}},le=e=>{try{return decodeURIComponent(e)}catch{return e}},ue=()=>{let e={};for(let t of document.cookie.split(`;`)){let n=t.indexOf(`=`);n>0&&(e[t.slice(0,n).trim()]=le(t.slice(n+1)))}return e},de=(e,t)=>{let n={};for(let r of e.queryParams){let e=t.params.get(r);e!==null&&e.length<=z&&(n[r]={value:e,source:`query`})}for(let r of e.cookies){let e=t.cookies[r];e!==void 0&&e.length<=z&&(n[r]={value:e,source:`cookie`})}return n},fe=(e,t)=>{let n={params:new URLSearchParams(window.location.search),cookies:ue()},r={};for(let[i,a]of Object.entries(e.config?.apps??{})){if(a.capture===void 0||y(e,a.category)||!v(t,i,a.category))continue;let o=de(a.capture,n);Object.keys(o).length>0&&(r[i]=o)}return r},pe=(e,t)=>{let n={};for(let[r,i]of Object.entries(e)){let e=t[r]??{},a={};for(let[t,n]of Object.entries(i))(e[t]?.value!==n.value||e[t]?.source!==n.source)&&(a[t]=n);Object.keys(a).length>0&&(n[r]=a)}return n},me=(e,t,n,r)=>{let i=H(r,n),a=U(i),o=a?.apps??{},s=a?.anonId??null,c=a===null,l={},u=0,d=(e,t)=>{s!==null&&s!==e.anonId&&(o={}),s=e.anonId;let n=new Set(Object.entries(e.accepted).flatMap(([e,t])=>t.map(t=>`${e}\u0000${t}`)));for(let[e,r]of Object.entries(t))for(let[t,i]of Object.entries(r))n.has(`${e}\u0000${t}`)&&(o[e]={...o[e],[t]:i});W(i,{at:Date.now(),anonId:s,apps:o})},f=null,p=()=>{u+=1,o={},l={},G(i)},m=n=>{if(f=n,!c)return;let r=pe(fe(e,n),{...o,...l});if(Object.keys(r).length===0)return;let i=u;l={...l,...r},t(V(r)).then(e=>{i===u&&d(e,r)}).catch(()=>{}).finally(()=>{l={}})};return{settled:e=>{m(e)},needsAnon:()=>!c,observedAnon:e=>{(e===null||s!==null&&s!==e)&&p(),s=e,c=!0,m(f)},clear:p}},K=Symbol.for(`qinto.connectGate`),q=()=>{},he=e=>{let t=globalThis,n=(t[K]??Promise.resolve()).then(e);return t[K]=n.then(q,q),n},J=class extends n{constructor(e){super(e),this.name=`QintoProtocolError`}},ge=e=>{if(typeof e!=`string`)return null;let t;try{t=JSON.parse(e)}catch{return null}if(typeof t!=`object`||!t)return null;let n=t;return n.t===`ack`||n.t===`error`||n.t===`consentState`||n.t===`session`||n.t===`captureAck`||n.t===`geoInstalls`||n.t===`appPush`||n.t===`sharedContext`?t:null},_e=e=>{if(e.t===`consentState`)return{categories:e.categories,apps:e.apps};if(e.t===`session`)return{anonId:e.anonId,globalId:e.globalId,ip:e.ip,geo:e.geo};if(e.t===`captureAck`)return{anonId:e.anonId,accepted:e.accepted};if(e.t===`geoInstalls`)return e.installs},ve=e=>{let t=new Map,n=e=>{let n=t.get(e);if(n!==void 0)return clearTimeout(n.timer),t.delete(e),n};return{submit:n=>new Promise((i,a)=>{let o={frame:n,sent:e.send(n),resolve:i,reject:a,timer:setTimeout(()=>{t.delete(n.ref),a(new r(`The Qinto request timed out.`))},e.requestTimeoutMs)};t.set(n.ref,o)}),flush:()=>{for(let n of t.values())n.sent||=e.send(n.frame)},deliver:e=>{let t=e.ref===void 0?void 0:n(e.ref);if(t!==void 0){if(e.t===`error`){t.reject(new J(e.message));return}t.resolve(_e(e))}},rejectAll:e=>{let n=[...t.values()];t.clear();for(let t of n)clearTimeout(t.timer),t.reject(e)}}},Y=()=>{let e=document.referrer;return{url:window.location.href,...e===``?{}:{referrer:e}}},ye=e=>new WebSocket(e),be=500,xe=3e4,X=4096,Se=8192,Ce=(e,t)=>{if(t.url.length>X)return e;let n=new URLSearchParams({url:t.url});t.referrer!==void 0&&t.referrer.length<=X&&n.set(`referrer`,t.referrer);let r=`${e}?${n}`;return r.length<=Se?r:e},we=`session not initialized`,Te=(e,t)=>{let n=Math.min(be*2**e,xe);return Math.round(n/2+n/2*t)},Ee=(e,t)=>e.t===`appPush`?(t.onAppPush?.(e),!0):e.t===`sharedContext`&&(t.onSharedContext?.(e),!0),De=e=>{let t=`${e.destination.replace(/\/+$/,``)}/open`,n=null,r=null,i=0,a=null,o=ve({send:e=>n===null||n.readyState!==1?!1:(n.send(JSON.stringify(e)),!0),requestTimeoutMs:e.requestTimeoutMs}),s=t=>{e.onError?.(t)},c=()=>{if(r!==null&&(clearTimeout(r),r=null),n!==null){let e=n;n=null,e.close()}o.rejectAll(new J(`connection closed`))},l=()=>{let u=ye(Ce(t,Y()));n=u,u.onopen=()=>{i=0;let e=a;a=null,o.flush(),e?.resolve()},u.onmessage=t=>{let n=ge(t.data);if(n===null){s(new J(`invalid message`));return}Ee(n,e)||(`anonId`in n&&typeof n.anonId==`string`&&e.onAnonId?.(n.anonId),o.deliver(n),n.t===`error`&&n.message===we&&u.close())},u.onerror=()=>{s(new J(`connection closed`))},u.onclose=()=>{if(n!==u)return;n=null;let e=a;if(e!==null){a=null,c(),e.reject(new J(`connection closed`));return}o.rejectAll(new J(`connection closed`)),r=setTimeout(()=>{r=null,l()},Te(i,Math.random())),i+=1}};return{connect:()=>new Promise((e,t)=>{a={resolve:e,reject:t},l()}),submit:e=>o.submit(e),close:()=>{c()}}},Oe=1e4,ke=()=>{let e=0;return()=>(e+=1,`q${e}`)},Ae=(e,t,n)=>{let r=null,i=()=>({occurredAt:Date.now(),page:Y()}),o=async()=>{let n=await e.submit({t:`getSession`,ref:t()});return r=n.anonId,n};return{destination:n.replace(/\/+$/,``),actionContext:i,submitIdentify:async({traits:n,id:r,context:i,appResults:a})=>{await e.submit({t:`identify`,ref:t(),traits:n,id:r,context:i,appResults:a})},submitTrack:async({event:n,eventId:r,properties:i,context:a,appResults:o,installs:s})=>{await e.submit({t:`track`,ref:t(),event:n,eventId:r,properties:i,context:a,appResults:o,installs:s})},submitConsent:async(n,r)=>{await e.submit({t:`consent`,ref:t(),categories:n.categories,apps:n.apps,context:r})},track:async(n,r,o)=>{let s=a(o?.eventId,r);return await e.submit({t:`track`,ref:t(),event:n,eventId:s,properties:r,context:i(),installs:o?.installs}),{eventId:s}},alias:async n=>{await e.submit({t:`alias`,ref:t(),alias:n})},getConsent:async()=>await e.submit({t:`getConsent`,ref:t()}),getGeoInstalls:async()=>await e.submit({t:`getGeoInstalls`,ref:t()}),getSession:o,getAnonId:async()=>(r===null&&await o(),r),close:async()=>{e.close()}}},je=async e=>{let t=De({destination:e.destination,requestTimeoutMs:e.requestTimeoutMs??Oe,onError:e.onError,onAppPush:e.onAppPush,onSharedContext:e.onSharedContext,onAnonId:e.onAnonId});await he(()=>t.connect());let n=ke();return{client:Ae(t,n,e.destination),submitCapture:async e=>await t.submit({t:`capture`,ref:n(),apps:e})}},Me=(e,t)=>{let n=null,r=R(e,{onConsentSettled:e=>{n?.settled(e)},onConsentMutation:()=>{n?.clear()},onPageEvent:e=>{n?.settled(e)}});return{connect:async i=>{let a=await je({...i,onAppPush:r.push,onSharedContext:r.sharedContext,onAnonId:e=>{n?.observedAnon(e)}});n=me(e,a.submitCapture,i.destination,t);let o=await r.connect(a.client);return n.needsAnon()&&n.observedAnon((await a.client.getSession()).anonId),o}}},Z=d(),Q=p(Z),$=`window.${Z}`;if(Q!==null&&Q.ready===void 0){let e=Me(Q,Z);t(Q),_(Q,async()=>{let t=Q.config?.destination;if(typeof t!=`string`||t===``)throw Error(`[Qinto] ${$}.config.destination is missing.`);return e.connect({destination:t})},$)}})();