@blotout/qinto-cli 0.1.31 → 0.1.32

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.
@@ -20105,7 +20105,7 @@ var userGeoSchema = external_exports.object({
20105
20105
 
20106
20106
  // ../../../libs/app-envelope/src/envelope.ts
20107
20107
  var ENVELOPE_VERSION = 3;
20108
- var ENVELOPE_ERROR_CODES = ["invalid_arguments"];
20108
+ var ENVELOPE_ERROR_CODES = ["invalid_arguments", "result_too_large", "callee_timeout", "rpc_error"];
20109
20109
  var MAX_INSTALLS_PER_APP = 15;
20110
20110
  var MAX_APPS_PER_DOMAIN = 50;
20111
20111
  var MAX_EMITS_PER_INSTALL = 10;
@@ -20119,6 +20119,7 @@ var MAX_SHARED_CONTEXT_ENTRY_BYTES = 4 * 1024;
20119
20119
  var MAX_PUSH_BYTES = 16 * 1024;
20120
20120
  var MAX_RESPONSE_BYTES = 1024 * 1024;
20121
20121
  var MAX_RPC_BYTES = 128 * 1024;
20122
+ var TRAFFIC_CLASSES = ["hot", "cold"];
20122
20123
  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();
20123
20124
  var installRuleSchema = external_exports.object({
20124
20125
  mode: external_exports.enum(["except", "only"]),
@@ -20203,7 +20204,15 @@ var envelopeRequestSchema = external_exports.object({
20203
20204
  context: external_exports.object({ private: contextEntrySchema.optional(), shared: external_exports.record(external_exports.string().min(1).max(30), contextEntrySchema).optional() }).strict().optional(),
20204
20205
  // RPC depth is capped at 3 by the broker; hook depth at 2 by the emit path.
20205
20206
  depth: external_exports.number().int().min(0).max(3),
20206
- rpc: external_exports.object({ caller: external_exports.string().min(1).max(30).nullable(), fn: external_exports.string().min(1).max(64), args: external_exports.unknown() }).strict().refine((rpc) => {
20207
+ rpc: external_exports.object({
20208
+ caller: external_exports.string().min(1).max(30).nullable(),
20209
+ fn: external_exports.string().min(1).max(64),
20210
+ args: external_exports.unknown(),
20211
+ // Optional on the wire: a site worker predating traffic classes sends none, which means hot.
20212
+ traffic: external_exports.enum(TRAFFIC_CLASSES).optional(),
20213
+ // Cold calls only: the broker mints it so the callee can query its own catalog.
20214
+ queryTicket: external_exports.string().min(1).max(2048).optional()
20215
+ }).strict().refine((rpc) => {
20207
20216
  return new TextEncoder().encode(JSON.stringify(rpc.args ?? null)).length <= MAX_RPC_BYTES;
20208
20217
  }, "RPC args exceed the size cap").optional(),
20209
20218
  action: external_exports.object({
@@ -21286,7 +21295,7 @@ var brokerActive = async (env, input2) => {
21286
21295
  }
21287
21296
  return response.status >= 400 && response.status < 500 ? { kind: "refused" } : { kind: "unknown" };
21288
21297
  };
21289
- var buildAppsClient = (env, envelope) => {
21298
+ var buildAppsClient = (env, envelope, traffic) => {
21290
21299
  const caller = callerSlug(env);
21291
21300
  const subject = envelope.user?.anonId;
21292
21301
  return {
@@ -21303,7 +21312,8 @@ var buildAppsClient = (env, envelope) => {
21303
21312
  fn,
21304
21313
  args,
21305
21314
  ...options?.installId === void 0 ? {} : { installId: options.installId },
21306
- depth: envelope.depth + 1
21315
+ depth: envelope.depth + 1,
21316
+ traffic
21307
21317
  });
21308
21318
  return answer.result;
21309
21319
  },
@@ -21812,10 +21822,14 @@ var buildWorkflowContext = (env, stamp) => {
21812
21822
  const { variables, secrets } = projectInstallValues(parseVariableMaps(env), variableKinds, stamp.ord);
21813
21823
  const { appVariables, appSecrets } = projectAppValues(env, appVariableKinds);
21814
21824
  const install = { id: stamp.installId, label: stamp.installLabel };
21815
- const apps = buildAppsClient(env, {
21816
- ...stamp.anonId === null ? {} : { user: { anonId: stamp.anonId, globalId: null, properties: {} } },
21817
- depth: 0
21818
- });
21825
+ const apps = buildAppsClient(
21826
+ env,
21827
+ {
21828
+ ...stamp.anonId === null ? {} : { user: { anonId: stamp.anonId, globalId: null, properties: {} } },
21829
+ depth: 0
21830
+ },
21831
+ "cold"
21832
+ );
21819
21833
  return {
21820
21834
  env: appEnv(env),
21821
21835
  install,
@@ -21890,7 +21904,8 @@ var buildContext = ({
21890
21904
  pushes,
21891
21905
  captures,
21892
21906
  context,
21893
- currency
21907
+ currency,
21908
+ traffic
21894
21909
  }) => {
21895
21910
  const { variables, secrets } = projectInstallValues(maps, kinds, install.ord);
21896
21911
  const subject = envelope.user?.anonId ?? null;
@@ -21960,7 +21975,7 @@ var buildContext = ({
21960
21975
  observability: buildObservability(install.ord),
21961
21976
  identity: buildIdentity(env),
21962
21977
  currency,
21963
- apps: buildAppsClient(env, envelope)
21978
+ apps: buildAppsClient(env, envelope, traffic)
21964
21979
  };
21965
21980
  };
21966
21981
 
@@ -22081,7 +22096,7 @@ var dispatchSchedule = async (envelope, bundle, env) => {
22081
22096
  observability: buildObservability(install.ord),
22082
22097
  identity: buildIdentity(env),
22083
22098
  currency,
22084
- apps: buildAppsClient(env, { depth: 0 }),
22099
+ apps: buildAppsClient(env, { depth: 0 }, "cold"),
22085
22100
  query: buildQuery({ env, ticket: install.queryTicket, installId: install.id }),
22086
22101
  push: async (userId, message) => {
22087
22102
  await brokerPush(env, {
@@ -22210,7 +22225,7 @@ var buildContext2 = (envelope, env) => {
22210
22225
  observability: buildObservability(install.ord),
22211
22226
  identity: buildIdentity(env),
22212
22227
  currency: buildCurrency(env),
22213
- apps: buildAppsClient(env, { depth: 0 }),
22228
+ apps: buildAppsClient(env, { depth: 0 }, "cold"),
22214
22229
  query: buildQuery({ env, ticket: envelope.tool.queryTicket, installId: install.id }),
22215
22230
  track: buildTrack(env, "tool", install.id),
22216
22231
  fail: (message) => {
@@ -22492,7 +22507,7 @@ var buildContext3 = ({
22492
22507
  observability: buildObservability(install.ord),
22493
22508
  identity: buildIdentity(env),
22494
22509
  currency,
22495
- apps: buildAppsClient(env, { depth: 0 }),
22510
+ apps: buildAppsClient(env, { depth: 0 }, "hot"),
22496
22511
  push: async (userId, message) => {
22497
22512
  await brokerPush(env, {
22498
22513
  userId,
@@ -22741,6 +22756,17 @@ var checkAgainst = async (schema, value) => {
22741
22756
  };
22742
22757
 
22743
22758
  // src/rpc.ts
22759
+ var MAX_RPC_ERROR_MESSAGE_LENGTH = 1024;
22760
+ var rpcQuery = (env, rpc, installId) => {
22761
+ if (rpc.queryTicket !== void 0) {
22762
+ return buildQuery({ env, ticket: rpc.queryTicket, installId });
22763
+ }
22764
+ const reason = (rpc.traffic ?? "hot") === "hot" ? "catalog queries are not available on hot traffic" : "catalog queries are not available on this site until its next deploy";
22765
+ const refuse = async () => {
22766
+ throw new Error(reason);
22767
+ };
22768
+ return { catalog: refuse, analytics: refuse };
22769
+ };
22744
22770
  var dispatchRpc = async (envelope, bundle, env) => {
22745
22771
  if (envelope.installs.length > 1) {
22746
22772
  return jsonError(400, "rpc envelope carries more than one install");
@@ -22768,14 +22794,29 @@ var dispatchRpc = async (envelope, bundle, env) => {
22768
22794
  const currency = buildCurrency(env);
22769
22795
  const subject = envelope.user?.anonId ?? null;
22770
22796
  const ctx = {
22771
- ...buildContext({ env, envelope, site, install, maps, kinds, appScope, emits, pushes, captures, context, currency }),
22797
+ ...buildContext({
22798
+ env,
22799
+ envelope,
22800
+ site,
22801
+ install,
22802
+ maps,
22803
+ kinds,
22804
+ appScope,
22805
+ emits,
22806
+ pushes,
22807
+ captures,
22808
+ context,
22809
+ currency,
22810
+ traffic: rpc.traffic ?? "hot"
22811
+ }),
22772
22812
  context: fetchedContext(
22773
22813
  env,
22774
22814
  (what) => {
22775
22815
  return requireSubject(subject, what);
22776
22816
  },
22777
22817
  context
22778
- )
22818
+ ),
22819
+ query: rpcQuery(env, rpc, install.id)
22779
22820
  };
22780
22821
  let value;
22781
22822
  try {
@@ -22785,17 +22826,19 @@ var dispatchRpc = async (envelope, bundle, env) => {
22785
22826
  } catch (error61) {
22786
22827
  const message = failureMessage(error61);
22787
22828
  console.warn(`rpc failed for install ${install.id}: ${message}`);
22829
+ if (error61?.__qintoRpcError === true) {
22830
+ return json2(200, { v: ENVELOPE_VERSION, error: { code: "rpc_error", message: message.slice(0, MAX_RPC_ERROR_MESSAGE_LENGTH) } });
22831
+ }
22788
22832
  return json2(200, { v: ENVELOPE_VERSION, error: { message } });
22789
22833
  }
22790
22834
  const checked = await checkAgainst(definition.output, value);
22791
22835
  if (!checked.ok) {
22792
22836
  return jsonError(200, failureMessage(`rpc result does not match the output schema: ${checked.message}`));
22793
22837
  }
22794
- const result = checked.value === void 0 ? null : checked.value;
22795
- if (new TextEncoder().encode(JSON.stringify(result)).length > MAX_RPC_BYTES) {
22796
- return jsonError(200, "rpc result exceeds the size cap");
22797
- }
22798
- const body = { v: ENVELOPE_VERSION, rpc: { result } };
22838
+ const body = {
22839
+ v: ENVELOPE_VERSION,
22840
+ rpc: { result: checked.value === void 0 ? null : checked.value }
22841
+ };
22799
22842
  const contextWrites = context.writes();
22800
22843
  if (emits.length > 0 || pushes.length > 0 || captures.length > 0 || contextWrites.length > 0) {
22801
22844
  body.effects = [{ ord: install.ord, emits, pushes, captures, context: contextWrites }];
@@ -22977,7 +23020,7 @@ var dispatchUi = async ({ request, env, versions }) => {
22977
23020
  observability: buildObservability(context.install.ord),
22978
23021
  identity: buildIdentity(env),
22979
23022
  currency: buildCurrency(env),
22980
- apps: buildAppsClient(env, { depth: 0 })
23023
+ apps: buildAppsClient(env, { depth: 0 }, "cold")
22981
23024
  };
22982
23025
  let response;
22983
23026
  try {
@@ -23048,7 +23091,21 @@ var runInstalls = async (envelope, env, invoke) => {
23048
23091
  const pushes = [];
23049
23092
  const captures = [];
23050
23093
  const context = contextCollector();
23051
- const ctx = buildContext({ env, envelope, site, install, maps, kinds, appScope, emits, pushes, captures, context, currency });
23094
+ const ctx = buildContext({
23095
+ env,
23096
+ envelope,
23097
+ site,
23098
+ install,
23099
+ maps,
23100
+ kinds,
23101
+ appScope,
23102
+ emits,
23103
+ pushes,
23104
+ captures,
23105
+ context,
23106
+ currency,
23107
+ traffic: "hot"
23108
+ });
23052
23109
  try {
23053
23110
  await installSpan(install, () => {
23054
23111
  return invoke(ctx, install);
@@ -23113,7 +23170,8 @@ var runTransform = async (envelope, env, action, handler) => {
23113
23170
  pushes,
23114
23171
  captures,
23115
23172
  context,
23116
- currency: buildCurrency(env)
23173
+ currency: buildCurrency(env),
23174
+ traffic: "hot"
23117
23175
  });
23118
23176
  const ctx = {
23119
23177
  ...withoutApps,
@@ -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,ne=e=>{let{categories:t,apps:n}=e;if(typeof t==`object`&&t&&typeof n==`object`&&n)return{categories:t,apps:n}},re=()=>{},S=(e,t)=>{console.error(`[Qinto] A handler of app "${e.slug}" (install "${e.installId}") failed.`,t)},C=(e,t,n)=>{for(let r of t)try{let t=r(n);t instanceof Promise&&t.catch(t=>{S(e,t)})}catch(t){S(e,t)}},w=(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(re)},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)&&C(i,[n],e.sharedContext)}};try{n(a)}catch(e){console.error(`[Qinto] App "${t}" failed to activate install "${r.id}".`,e)}},T=100,E=1024,D=32768,ie=e=>{let t;try{t=JSON.stringify(e)}catch{return}if(!(t===void 0||new TextEncoder().encode(t).length>E))return JSON.parse(t)},ae=e=>{let t={};for(let n of e){if(n.settled!==n.total||n.values.length!==1)continue;let e=ie(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<=D&&(t[n.source.slug]=r)}return Object.keys(t).length===0?void 0:t},oe=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,T)});await Promise.race([Promise.all(o),t]),clearTimeout(e)}return ae(a)},se=(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`))}},ce=(e,t,n,r)=>{let i;try{i=t(n,r)}catch(t){S(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;S(e,TypeError(`A transform hook returned neither nothing, false, nor { installs }.`))},le=(e,t,n,r)=>{let i=r;for(let r of e)for(let e of r.transformHooks){let a=ce(r,e,t,n);if(a===!1)return!1;a!==void 0&&(i=i===void 0?a:se(i,a))}return i},O=(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`))},k=(e,t,n,r)=>r===null?e.slug===t&&(n===void 0||n===e.installId):r.has(e.slug),A=e=>`_appInstalls`in e?e._appInstalls:void 0,j=(e,t,n)=>{if(!b(e.target,t,e.consent))return;let r=(A(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)w(e,t,i,n)},M=(e,t)=>{let n=e;n.consent=t,n.sharedContextConsent=void 0;for(let n of e.instances)C(n,n.consentHandlers,t);e.onConsentSettled?.(t);for(let[t,n]of e.apps)j(e,t,n)},N=async e=>{try{M(e,await e.client.getConsent())}catch(e){console.error(`[Qinto] The apps consent read failed.`,e)}},P=async e=>{if(e.geoRequested||!Object.values(A(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)j(e,t,n)},F=async(e,t,n)=>{e.onPageEvent?.(e.consent);let r=new Set(n?.installIds);return oe(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=>{C(e,e.eventHandlers,t)},report:S})},I=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=le(e.instances,c,s.page.url,l);if(u===!1)return{eventId:o};let d=await F(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 F(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 N(e)}},getAnonId:t.getAnonId,getConsent:t.getConsent,getSession:t.getSession,close:t.close}},L=(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=ne(e),a=r??n.consent;n.sharedContextConsent=r;for(let e of n.instances)b(n.target,e.slug,a)&&C(e,e.sharedContextHandlers,n.sharedContext)},push:e=>{let{app:t,install:n,topic:r,scope:a,to:o}=e,s=a===`site`;if(O(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)k(e,t,n,l)&&b(c.target,e.slug,c.consent)&&C(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)=>{j(o,e,t),o.consent===null&&o.target.config?.consentConfiguration?.enabled===!0&&o.target.config?.apps?.[e]?.category!==`necessary`&&N(o),P(o)};for(let[e,t]of n)j(o,e,t);let s=P(o);return e.config?.consentConfiguration?.enabled===!0&&x(e)?await N(o):o.onConsentSettled?.(o.consent),await s,I(o)}}},R=512,z=864e5,B=e=>Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Object.fromEntries(Object.entries(t).map(([e,t])=>[e,t.value]))])),V=(e,t)=>`qinto:cap:${encodeURIComponent(e)}:${encodeURIComponent(t)}`,H=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>z?null:{at:n.at,anonId:n.anonId,apps:n.apps}}catch{return null}},U=(e,t)=>{try{window.sessionStorage.setItem(e,JSON.stringify(t))}catch{}},W=e=>{try{window.sessionStorage.removeItem(e)}catch{}},ue=e=>{try{return decodeURIComponent(e)}catch{return e}},de=()=>{let e={};for(let t of document.cookie.split(`;`)){let n=t.indexOf(`=`);n>0&&(e[t.slice(0,n).trim()]=ue(t.slice(n+1)))}return e},fe=(e,t)=>{let n={};for(let r of e.queryParams){let e=t.params.get(r);e!==null&&e.length<=R&&(n[r]={value:e,source:`query`})}for(let r of e.cookies){let e=t.cookies[r];e!==void 0&&e.length<=R&&(n[r]={value:e,source:`cookie`})}return n},pe=(e,t)=>{let n={params:new URLSearchParams(window.location.search),cookies:de()},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=fe(a.capture,n);Object.keys(o).length>0&&(r[i]=o)}return r},me=(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},G=(e,t,n,r)=>{let i=V(r,n),a=H(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});U(i,{at:Date.now(),anonId:s,apps:o})},f=null,p=()=>{u+=1,o={},l={},W(i)},m=n=>{if(f=n,!c)return;let r=me(pe(e,n),{...o,...l});if(Object.keys(r).length===0)return;let i=u;l={...l,...r},t(B(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,Se=1e4,X=4096,Ce=8192,we=(e,t,n)=>{let r=n?`${e}?reconnect=1`:e;if(t.url.length>X)return r;let i=new URLSearchParams({url:t.url});t.referrer!==void 0&&t.referrer.length<=X&&i.set(`referrer`,t.referrer),n&&i.set(`reconnect`,`1`);let a=`${e}?${i}`;return a.length<=Ce?a:r},Te=`session not initialized`,Ee=1e3,De=`erased`,Oe=(e,t)=>{let n=Math.min(be*2**e,xe);return Math.round(n/2+n/2*t)},ke=(e,t)=>e.t===`appPush`?(t.onAppPush?.(e),!0):e.t===`sharedContext`&&(t.onSharedContext?.(e),!0),Ae=e=>{let t=`${e.destination.replace(/\/+$/,``)}/open`,n=null,r=null,i=0,a=!1,o=!1,s=null,c=ve({send:e=>n===null||n.readyState!==1?!1:(n.send(JSON.stringify(e)),!0),requestTimeoutMs:e.requestTimeoutMs}),l=t=>{e.onError?.(t)},u=()=>{if(o=!0,document.removeEventListener(`visibilitychange`,p),r!==null&&(clearTimeout(r),r=null),n!==null){let e=n;n=null,e.close()}c.rejectAll(new J(`connection closed`))},d=()=>{document.visibilityState!==`hidden`&&(r=setTimeout(()=>{r=null,f()},Oe(i,Math.random())),i+=1)},f=()=>{let r=ye(we(t,Y(),a));a=!0,n=r;let o;r.onopen=()=>{o=Date.now();let e=s;s=null,c.flush(),e?.resolve()},r.onmessage=t=>{let n=ge(t.data);if(n===null){l(new J(`invalid message`));return}ke(n,e)||(`anonId`in n&&typeof n.anonId==`string`&&e.onAnonId?.(n.anonId),c.deliver(n),n.t===`error`&&n.message===Te&&r.close())},r.onerror=()=>{l(new J(`connection closed`))},r.onclose=e=>{if(n!==r)return;n=null;let t=s;if(t!==null){s=null,u(),t.reject(new J(`connection closed`));return}if(e.code===Ee&&e.reason===De){u();return}o!==void 0&&Date.now()-o>=Se&&(i=0),c.rejectAll(new J(`connection closed`)),d()}},p=()=>{if(document.visibilityState===`hidden`){r!==null&&(clearTimeout(r),r=null);return}n===null&&r===null&&f()};return{connect:()=>new Promise((e,t)=>{s={resolve:e,reject:t},document.addEventListener(`visibilitychange`,p),f()}),submit:e=>o?Promise.reject(new J(`connection closed`)):(n===null&&r===null&&f(),c.submit(e)),close:()=>{u()}}},je=1e4,Me=()=>{let e=0;return()=>(e+=1,`q${e}`)},Ne=(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()}}},Pe=async e=>{let t=Ae({destination:e.destination,requestTimeoutMs:e.requestTimeoutMs??je,onError:e.onError,onAppPush:e.onAppPush,onSharedContext:e.onSharedContext,onAnonId:e.onAnonId});await he(()=>t.connect());let n=Me();return{client:Ne(t,n,e.destination),submitCapture:async e=>await t.submit({t:`capture`,ref:n(),apps:e})}},Fe=(e,t)=>{let n=null,r=L(e,{onConsentSettled:e=>{n?.settled(e)},onConsentMutation:()=>{n?.clear()},onPageEvent:e=>{n?.settled(e)}});return{connect:async i=>{let a=await Pe({...i,onAppPush:r.push,onSharedContext:r.sharedContext,onAnonId:e=>{n?.observedAnon(e)}});n=G(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=Fe(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})},$)}})();