@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.
- package/README.md +85 -0
- package/dist/index.js +4105 -3844
- package/dist/index.js.map +1 -1
- package/dist/worker-artifact/app-runtime/index.js +68 -43
- package/dist/worker-artifact/main/8809017061697bf9b90fa4d72f7eb2e0f0e00ad4-q.js.txt +1 -0
- package/dist/worker-artifact/main/index.js +177 -85
- package/dist/worker-artifact/version.json +8 -8
- package/package.json +2 -1
- package/dist/worker-artifact/main/61afaba4cf160e30ef4b71a7ce30a398f71f13e8-q.js.txt +0 -1
|
@@ -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:
|
|
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) =>
|
|
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})},$)}})();
|