@blotout/qinto-cli 0.1.18 → 0.1.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.js +1660 -1638
- package/dist/index.js.map +1 -1
- package/dist/worker-artifact/README.md +1 -1
- package/dist/worker-artifact/app-runtime/index.js +46 -9
- package/dist/worker-artifact/main/7bc13565a6fa9d520d0ebed788d11591e8db5b44-q.js.txt +1 -0
- package/dist/worker-artifact/main/index.js +136 -58
- package/dist/worker-artifact/version.json +8 -8
- package/package.json +1 -1
- package/dist/worker-artifact/main/b6b625dbf1615da405354d9b8813ffcc4e753b93-q.js.txt +0 -1
|
@@ -18959,7 +18959,7 @@ var uniqueOrIssue = (ctx, values, path, label) => {
|
|
|
18959
18959
|
seen.add(value);
|
|
18960
18960
|
}
|
|
18961
18961
|
};
|
|
18962
|
-
var PLATFORM_ZONES = ["blotout.io", "qinto.tech"];
|
|
18962
|
+
var PLATFORM_ZONES = ["platform.blotout.io", "qinto-api.blotout.io", "appui.blotout.io", "mcp.blotout.io", "qinto.tech"];
|
|
18963
18963
|
var isPlatformHost = (host) => {
|
|
18964
18964
|
return PLATFORM_ZONES.some((zone) => host === zone || host.endsWith(`.${zone}`));
|
|
18965
18965
|
};
|
|
@@ -19528,10 +19528,13 @@ var variableSchema = external_exports.object({
|
|
|
19528
19528
|
label: external_exports.string().min(1).max(100),
|
|
19529
19529
|
required: external_exports.boolean().optional(),
|
|
19530
19530
|
browser: external_exports.boolean().optional(),
|
|
19531
|
+
owner: external_exports.enum(["site", "developer"]).optional(),
|
|
19531
19532
|
helpText: external_exports.string().min(1).max(MAX_VARIABLE_HELP_TEXT).optional(),
|
|
19532
19533
|
helpUrl: httpsUrl("helpUrl").optional()
|
|
19533
19534
|
}).strict().refine((variable) => !(variable.kind === "secret" && variable.browser === true), {
|
|
19534
19535
|
message: "A secret variable can never be browser-exposed"
|
|
19536
|
+
}).refine((variable) => !(variable.required === true && variable.owner === "developer"), {
|
|
19537
|
+
message: "A developer-owned variable cannot be required"
|
|
19535
19538
|
});
|
|
19536
19539
|
var appVariableSchema = external_exports.object({
|
|
19537
19540
|
name: external_exports.string().min(1).max(64).regex(VARIABLE_NAME),
|
|
@@ -19994,6 +19997,7 @@ var MAX_PUSHES_PER_INSTALL = 10;
|
|
|
19994
19997
|
var MAX_CAPTURE_WRITES_PER_INSTALL = 10;
|
|
19995
19998
|
var CONTEXT_LEVELS = ["private", "shared"];
|
|
19996
19999
|
var PUSH_BROADCASTS = ["install", "app", "site"];
|
|
20000
|
+
var ACTION_SOURCES = ["website", "api", "app", "scheduled", "webhook", "tool", "workflow"];
|
|
19997
20001
|
var MAX_PRIVATE_CONTEXT_ENTRY_BYTES = 32 * 1024;
|
|
19998
20002
|
var MAX_SHARED_CONTEXT_ENTRY_BYTES = 4 * 1024;
|
|
19999
20003
|
var MAX_PUSH_BYTES = 16 * 1024;
|
|
@@ -20069,6 +20073,9 @@ var envelopeRequestSchema = external_exports.object({
|
|
|
20069
20073
|
userId: external_exports.string().min(1).max(64),
|
|
20070
20074
|
payload: external_exports.record(external_exports.string(), external_exports.unknown()),
|
|
20071
20075
|
receivedAt: external_exports.number().int(),
|
|
20076
|
+
// Optional on the wire: an app worker redeploys before its site worker, so this reader must
|
|
20077
|
+
// accept an envelope a site worker predating the field produces.
|
|
20078
|
+
source: external_exports.enum(ACTION_SOURCES).optional(),
|
|
20072
20079
|
context: actionContextSchema.optional(),
|
|
20073
20080
|
browser: external_exports.record(external_exports.string().min(1).max(64), external_exports.unknown()).optional(),
|
|
20074
20081
|
origin: external_exports.object({ app: external_exports.string().min(1).max(30), install: external_exports.number().int().min(1), depth: external_exports.number().int().min(0) }).strict().optional()
|
|
@@ -20951,6 +20958,18 @@ var brokerPush = async (env, input2) => {
|
|
|
20951
20958
|
data: input2.data
|
|
20952
20959
|
});
|
|
20953
20960
|
};
|
|
20961
|
+
var brokerTrack = async (env, input2) => {
|
|
20962
|
+
await askBroker(env, `apps.track ${input2.event.payload["event"]}`, {
|
|
20963
|
+
v: ENVELOPE_VERSION,
|
|
20964
|
+
kind: "track",
|
|
20965
|
+
slug: callerSlug(env),
|
|
20966
|
+
key: env.QINTO_INTERNAL_KEY,
|
|
20967
|
+
source: input2.source,
|
|
20968
|
+
userId: input2.userId,
|
|
20969
|
+
installId: input2.installId,
|
|
20970
|
+
event: input2.event
|
|
20971
|
+
});
|
|
20972
|
+
};
|
|
20954
20973
|
var brokerContextRead = async (env, userId) => {
|
|
20955
20974
|
const answer = await askBroker(env, "apps.context read", {
|
|
20956
20975
|
v: ENVELOPE_VERSION,
|
|
@@ -21065,6 +21084,18 @@ var buildAppsClient = (env, envelope) => {
|
|
|
21065
21084
|
};
|
|
21066
21085
|
};
|
|
21067
21086
|
|
|
21087
|
+
// src/emitted-event.ts
|
|
21088
|
+
var checkEmittedEvent = (event) => {
|
|
21089
|
+
if (event.type !== "track") {
|
|
21090
|
+
throw new Error("only track events may be emitted");
|
|
21091
|
+
}
|
|
21092
|
+
const occurredAt = event.occurredAt ?? Date.now();
|
|
21093
|
+
if (!Number.isSafeInteger(occurredAt) || occurredAt < 0) {
|
|
21094
|
+
throw new Error("an emitted event occurredAt must be non-negative Unix milliseconds");
|
|
21095
|
+
}
|
|
21096
|
+
return { ...event, occurredAt };
|
|
21097
|
+
};
|
|
21098
|
+
|
|
21068
21099
|
// src/oauth.ts
|
|
21069
21100
|
var EXPIRY_FLOOR_MS = 1e3;
|
|
21070
21101
|
var read = (env, id, ord, now) => {
|
|
@@ -21550,6 +21581,9 @@ var buildWorkflowContext = (env, stamp) => {
|
|
|
21550
21581
|
broadcast: message.broadcast
|
|
21551
21582
|
});
|
|
21552
21583
|
},
|
|
21584
|
+
track: async (userId, event) => {
|
|
21585
|
+
await brokerTrack(env, { source: "workflow", userId, installId: install.id, event: checkEmittedEvent(event) });
|
|
21586
|
+
},
|
|
21553
21587
|
apps
|
|
21554
21588
|
};
|
|
21555
21589
|
};
|
|
@@ -21623,15 +21657,9 @@ var buildContext = ({
|
|
|
21623
21657
|
// and the extra entry keeps it visibly over while bounding memory.
|
|
21624
21658
|
emit: (event) => {
|
|
21625
21659
|
requireSubject(subject, "emit");
|
|
21626
|
-
|
|
21627
|
-
throw new Error("only track events may be emitted");
|
|
21628
|
-
}
|
|
21629
|
-
const occurredAt = event.occurredAt ?? Date.now();
|
|
21630
|
-
if (!Number.isSafeInteger(occurredAt) || occurredAt < 0) {
|
|
21631
|
-
throw new Error("an emitted event occurredAt must be non-negative Unix milliseconds");
|
|
21632
|
-
}
|
|
21660
|
+
const checked = checkEmittedEvent(event);
|
|
21633
21661
|
if (emits.length <= MAX_EMITS_PER_INSTALL) {
|
|
21634
|
-
emits.push(
|
|
21662
|
+
emits.push(checked);
|
|
21635
21663
|
}
|
|
21636
21664
|
},
|
|
21637
21665
|
push: (message) => {
|
|
@@ -21802,6 +21830,9 @@ var dispatchSchedule = async (envelope, bundle, env) => {
|
|
|
21802
21830
|
broadcast: message.broadcast
|
|
21803
21831
|
});
|
|
21804
21832
|
},
|
|
21833
|
+
track: async (userId, event2) => {
|
|
21834
|
+
await brokerTrack(env, { source: "scheduled", userId, installId: install.id, event: checkEmittedEvent(event2) });
|
|
21835
|
+
},
|
|
21805
21836
|
context: (userId) => {
|
|
21806
21837
|
return asyncContext(env, () => {
|
|
21807
21838
|
return userId;
|
|
@@ -21919,6 +21950,9 @@ var buildContext2 = (envelope, env) => {
|
|
|
21919
21950
|
identity: buildIdentity(env),
|
|
21920
21951
|
apps: buildAppsClient(env, { depth: 0 }),
|
|
21921
21952
|
query: buildQuery({ env, ticket: envelope.tool.queryTicket, installId: install.id }),
|
|
21953
|
+
track: async (userId, event) => {
|
|
21954
|
+
await brokerTrack(env, { source: "tool", userId, installId: install.id, event: checkEmittedEvent(event) });
|
|
21955
|
+
},
|
|
21922
21956
|
fail: (message) => {
|
|
21923
21957
|
return { kind: "tool_error", message: truncate(message) };
|
|
21924
21958
|
}
|
|
@@ -22181,6 +22215,9 @@ var buildContext3 = ({
|
|
|
22181
22215
|
broadcast: message.broadcast
|
|
22182
22216
|
});
|
|
22183
22217
|
},
|
|
22218
|
+
track: async (userId, event) => {
|
|
22219
|
+
await brokerTrack(env, { source: "webhook", userId, installId: install.id, event: checkEmittedEvent(event) });
|
|
22220
|
+
},
|
|
22184
22221
|
context: (userId) => {
|
|
22185
22222
|
return asyncContext(env, () => {
|
|
22186
22223
|
return userId;
|
|
@@ -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))},h=e=>()=>Promise.reject(e),g=(e,t)=>{let[n,r,i,a]=t;e(n,r).then(i,a)},ee=e=>{let t=[];return t.push=(...t)=>{for(let n of t)g(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=ee(e);for(let n of t)g(e,n)},o=t().then(e=>{a(m(e,n))},e=>{throw a(h(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=()=>{},te=100,ne=1024,b=32768,x=(e,t,n)=>e.target.config?.consentConfiguration?.enabled!==!0||v(n,t,e.target.config?.apps?.[t]?.category),S=e=>Object.values(e.config?.apps??{}).some(e=>e.category!==`necessary`||e.capture!==void 0),C=(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`))},re=(e,t,n,r)=>r===null?e.slug===t&&(n===void 0||n===e.installId):r.has(e.slug),w=(e,t)=>{console.error(`[Qinto] A handler of app "${e.slug}" (install "${e.installId}") failed.`,t)},T=(e,t,n)=>{for(let r of t)try{let t=r(n);t instanceof Promise&&t.catch(t=>{w(e,t)})}catch(t){w(e,t)}},ie=(e,t,n,r)=>{e.activated.add(r.id);let i={slug:t,installId:r.id,eventHandlers:[],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(y)},onEvent:e=>{i.eventHandlers.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&&ae(e,t)&&T(i,[n],e.sharedContext)}};try{n(a)}catch(e){console.error(`[Qinto] App "${t}" failed to activate install "${r.id}".`,e)}},E=(e,t,n)=>{if(!x(e,t,e.consent))return;let r=((`_appInstalls`in e.target?e.target._appInstalls:void 0)?.[t]??[]).filter(t=>!e.activated.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)ie(e,t,i,n)},ae=(e,t)=>x(e,t,e.consent)?e.sharedContextConsent===void 0||x(e,t,e.sharedContextConsent):!1,D=e=>{let{categories:t,apps:n}=e;if(typeof t==`object`&&t&&typeof n==`object`&&n)return{categories:t,apps:n}},O=(e,t)=>{let n=e;n.consent=t,n.sharedContextConsent=void 0;for(let n of e.instances)T(n,n.consentHandlers,t);e.onConsentSettled?.(t);for(let[t,n]of e.apps)E(e,t,n)},k=async e=>{try{O(e,await e.client.getConsent())}catch(e){console.error(`[Qinto] The apps consent read failed.`,e)}},A=e=>{let t;try{t=JSON.stringify(e)}catch{return}if(!(t===void 0||new TextEncoder().encode(t).length>ne))return JSON.parse(t)},j=e=>{let t={};for(let n of e){if(n.settled!==n.total||n.values.length!==1)continue;let e=A(n.values[0]);if(e===void 0)continue;let r={...t[n.instance.slug]??{},[n.instance.installId]:e},i={...t,[n.instance.slug]:r};new TextEncoder().encode(JSON.stringify(i)).length<=b&&(t[n.instance.slug]=r)}return Object.keys(t).length===0?void 0:t},M=async(e,t)=>{e.onPageEvent?.(e.consent);let n=[],r=[];for(let i of e.instances){if(!x(e,i.slug,e.consent))continue;if(e.target.config?.apps?.[i.slug]?.eventResults?.includes(t.type)!==!0){T(i,i.eventHandlers,t);continue}let a={instance:i,total:i.eventHandlers.length,settled:0,values:[]};n.push(a);for(let e of i.eventHandlers){let n;try{n=e(t)}catch(e){a.settled+=1,w(i,e);continue}r.push(Promise.resolve(n).then(e=>{a.settled+=1,e!==void 0&&a.values.push(e)},e=>{a.settled+=1,w(i,e)}))}}if(r.length>0){let e=y,t=new Promise(t=>{e=t}),n=setTimeout(e,te);await Promise.race([Promise.all(r),t]),clearTimeout(n)}return j(n)},N=e=>{let{client:t}=e;return{track:async(n,r,i)=>{let o=a(i?.eventId,r),s=t.actionContext(),c=await M(e,{type:`track`,event:n,eventId:o,properties:r??{}});return await t.submitTrack({event:n,eventId:o,properties:r,context:s,appResults:c}),{eventId:o}},identify:async(n,r)=>{let i=t.actionContext(),a=await M(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?.(),S(e.target)){let t=e;t.consent=null,await k(e)}},getAnonId:t.getAnonId,getConsent:t.getConsent,getSession:t.getSession,close:t.close}},P=(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=D(e),a=r??n.consent;n.sharedContextConsent=r;for(let e of n.instances)x(n,e.slug,a)&&T(e,e.sharedContextHandlers,n.sharedContext)},push:e=>{let{app:t,install:n,topic:r,scope:a,to:o}=e,s=a===`site`;if(C(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)re(e,t,n,l)&&x(c,e.slug,c.consent)&&T(e,e.pushHandlers,u)},connect:async a=>{let o={target:e,client:a,apps:n,instances:[],activated:new Set,consent:null,sharedContext:i?.sharedContext??null,sharedContextConsent:i?.sharedContextConsent,onConsentSettled:t?.onConsentSettled,onConsentMutation:t?.onConsentMutation,onPageEvent:t?.onPageEvent};i=o,r=(e,t)=>{E(o,e,t),o.consent===null&&o.target.config?.consentConfiguration?.enabled===!0&&o.target.config?.apps?.[e]?.category!==`necessary`&&k(o)};for(let[e,t]of n)E(o,e,t);return e.config?.consentConfiguration?.enabled===!0&&S(e)?await k(o):o.onConsentSettled?.(o.consent),N(o)}}},F=512,I=864e5,L=e=>Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Object.fromEntries(Object.entries(t).map(([e,t])=>[e,t.value]))])),R=(e,t)=>`qinto:cap:${encodeURIComponent(e)}:${encodeURIComponent(t)}`,z=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>I?null:{at:n.at,anonId:n.anonId,apps:n.apps}}catch{return null}},B=(e,t)=>{try{window.sessionStorage.setItem(e,JSON.stringify(t))}catch{}},V=e=>{try{window.sessionStorage.removeItem(e)}catch{}},H=e=>{try{return decodeURIComponent(e)}catch{return e}},U=()=>{let e={};for(let t of document.cookie.split(`;`)){let n=t.indexOf(`=`);n>0&&(e[t.slice(0,n).trim()]=H(t.slice(n+1)))}return e},W=(e,t)=>{let n={};for(let r of e.queryParams){let e=t.params.get(r);e!==null&&e.length<=F&&(n[r]={value:e,source:`query`})}for(let r of e.cookies){let e=t.cookies[r];e!==void 0&&e.length<=F&&(n[r]={value:e,source:`cookie`})}return n},G=(e,t)=>{let n={params:new URLSearchParams(window.location.search),cookies:U()},r={};for(let[i,a]of Object.entries(e.config?.apps??{})){if(a.capture===void 0||!v(t,i,a.category))continue;let e=W(a.capture,n);Object.keys(e).length>0&&(r[i]=e)}return r},K=(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},oe=(e,t,n,r)=>{let i=R(r,n),a=z(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});B(i,{at:Date.now(),anonId:s,apps:o})},f=null,p=()=>{u+=1,o={},l={},V(i)},m=n=>{if(f=n,!c)return;let r=K(G(e,n),{...o,...l});if(Object.keys(r).length===0)return;let i=u;l={...l,...r},t(L(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}},q=Symbol.for(`qinto.connectGate`),J=()=>{},se=e=>{let t=globalThis,n=(t[q]??Promise.resolve()).then(e);return t[q]=n.then(J,J),n},Y=class extends n{constructor(e){super(e),this.name=`QintoProtocolError`}},ce=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===`appPush`||n.t===`sharedContext`?t:null},le=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}},ue=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 Y(e.message));return}t.resolve(le(e))}},rejectAll:e=>{let n=[...t.values()];t.clear();for(let t of n)clearTimeout(t.timer),t.reject(e)}}},de=e=>new WebSocket(e),fe=500,pe=3e4,me=`session not initialized`,he=(e,t)=>{let n=Math.min(fe*2**e,pe);return Math.round(n/2+n/2*t)},ge=(e,t)=>e.t===`appPush`?(t.onAppPush?.(e),!0):e.t===`sharedContext`&&(t.onSharedContext?.(e),!0),X=e=>{let t=`${e.destination.replace(/\/+$/,``)}/open`,n=null,r=null,i=0,a=null,o=ue({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 Y(`connection closed`))},l=()=>{let u=de(t);n=u,u.onopen=()=>{i=0;let e=a;a=null,o.flush(),e?.resolve()},u.onmessage=t=>{let n=ce(t.data);if(n===null){s(new Y(`invalid message`));return}ge(n,e)||(`anonId`in n&&typeof n.anonId==`string`&&e.onAnonId?.(n.anonId),o.deliver(n),n.t===`error`&&n.message===me&&u.close())},u.onerror=()=>{s(new Y(`connection closed`))},u.onclose=()=>{if(n!==u)return;n=null;let e=a;if(e!==null){a=null,c(),e.reject(new Y(`connection closed`));return}o.rejectAll(new Y(`connection closed`)),r=setTimeout(()=>{r=null,l()},he(i,Math.random())),i+=1}};return{connect:()=>new Promise((e,t)=>{a={resolve:e,reject:t},l()}),submit:e=>o.submit(e),close:()=>{c()}}},_e=1e4,ve=()=>{let e=0;return()=>(e+=1,`q${e}`)},ye=(e,t,n)=>{let r=null,i=()=>{let e=document.referrer;return{occurredAt:Date.now(),page:{url:window.location.href,...e===``?{}:{referrer:e}}}},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})=>{await e.submit({t:`track`,ref:t(),event:n,eventId:r,properties:i,context:a,appResults:o})},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()}),{eventId:s}},alias:async n=>{await e.submit({t:`alias`,ref:t(),alias:n})},getConsent:async()=>await e.submit({t:`getConsent`,ref:t()}),getSession:o,getAnonId:async()=>(r===null&&await o(),r),close:async()=>{e.close()}}},be=async e=>{let t=X({destination:e.destination,requestTimeoutMs:e.requestTimeoutMs??_e,onError:e.onError,onAppPush:e.onAppPush,onSharedContext:e.onSharedContext,onAnonId:e.onAnonId});await se(()=>t.connect());let n=ve();return{client:ye(t,n,e.destination),submitCapture:async e=>await t.submit({t:`capture`,ref:n(),apps:e})}},xe=(e,t)=>{let n=null,r=P(e,{onConsentSettled:e=>{n?.settled(e)},onConsentMutation:()=>{n?.clear()},onPageEvent:e=>{n?.settled(e)}});return{connect:async i=>{let a=await be({...i,onAppPush:r.push,onSharedContext:r.sharedContext,onAnonId:e=>{n?.observedAnon(e)}});n=oe(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=xe(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})},$)}})();
|
|
@@ -20360,7 +20360,7 @@ var uniqueOrIssue = /* @__PURE__ */ __name((ctx, values, path, label) => {
|
|
|
20360
20360
|
seen.add(value);
|
|
20361
20361
|
}
|
|
20362
20362
|
}, "uniqueOrIssue");
|
|
20363
|
-
var PLATFORM_ZONES = ["blotout.io", "qinto.tech"];
|
|
20363
|
+
var PLATFORM_ZONES = ["platform.blotout.io", "qinto-api.blotout.io", "appui.blotout.io", "mcp.blotout.io", "qinto.tech"];
|
|
20364
20364
|
var isPlatformHost = /* @__PURE__ */ __name((host) => {
|
|
20365
20365
|
return PLATFORM_ZONES.some((zone) => host === zone || host.endsWith(`.${zone}`));
|
|
20366
20366
|
}, "isPlatformHost");
|
|
@@ -20992,10 +20992,13 @@ var variableSchema = external_exports.object({
|
|
|
20992
20992
|
label: external_exports.string().min(1).max(100),
|
|
20993
20993
|
required: external_exports.boolean().optional(),
|
|
20994
20994
|
browser: external_exports.boolean().optional(),
|
|
20995
|
+
owner: external_exports.enum(["site", "developer"]).optional(),
|
|
20995
20996
|
helpText: external_exports.string().min(1).max(MAX_VARIABLE_HELP_TEXT).optional(),
|
|
20996
20997
|
helpUrl: httpsUrl("helpUrl").optional()
|
|
20997
20998
|
}).strict().refine((variable) => !(variable.kind === "secret" && variable.browser === true), {
|
|
20998
20999
|
message: "A secret variable can never be browser-exposed"
|
|
21000
|
+
}).refine((variable) => !(variable.required === true && variable.owner === "developer"), {
|
|
21001
|
+
message: "A developer-owned variable cannot be required"
|
|
20999
21002
|
});
|
|
21000
21003
|
var appVariableSchema = external_exports.object({
|
|
21001
21004
|
name: external_exports.string().min(1).max(64).regex(VARIABLE_NAME),
|
|
@@ -21467,6 +21470,8 @@ var MAX_CAPTURE_WRITES_PER_INSTALL = 10;
|
|
|
21467
21470
|
var MAX_CONTEXT_WRITES_PER_INSTALL = 2;
|
|
21468
21471
|
var CONTEXT_LEVELS = ["private", "shared"];
|
|
21469
21472
|
var PUSH_BROADCASTS = ["install", "app", "site"];
|
|
21473
|
+
var ACTION_SOURCES = ["website", "api", "app", "scheduled", "webhook", "tool", "workflow"];
|
|
21474
|
+
var APP_HANDLER_SOURCES = ["scheduled", "webhook", "tool", "workflow"];
|
|
21470
21475
|
var MAX_PRIVATE_CONTEXT_ENTRY_BYTES = 32 * 1024;
|
|
21471
21476
|
var MAX_SHARED_CONTEXT_ENTRY_BYTES = 4 * 1024;
|
|
21472
21477
|
var MAX_PUSH_BYTES = 16 * 1024;
|
|
@@ -21542,6 +21547,9 @@ var envelopeRequestSchema = external_exports.object({
|
|
|
21542
21547
|
userId: external_exports.string().min(1).max(64),
|
|
21543
21548
|
payload: external_exports.record(external_exports.string(), external_exports.unknown()),
|
|
21544
21549
|
receivedAt: external_exports.number().int(),
|
|
21550
|
+
// Optional on the wire: an app worker redeploys before its site worker, so this reader must
|
|
21551
|
+
// accept an envelope a site worker predating the field produces.
|
|
21552
|
+
source: external_exports.enum(ACTION_SOURCES).optional(),
|
|
21545
21553
|
context: actionContextSchema.optional(),
|
|
21546
21554
|
browser: external_exports.record(external_exports.string().min(1).max(64), external_exports.unknown()).optional(),
|
|
21547
21555
|
origin: external_exports.object({ app: external_exports.string().min(1).max(30), install: external_exports.number().int().min(1), depth: external_exports.number().int().min(0) }).strict().optional()
|
|
@@ -26868,7 +26876,6 @@ var submitAction = /* @__PURE__ */ __name(async (env, userId, args, request) =>
|
|
|
26868
26876
|
...args,
|
|
26869
26877
|
userId: resolved.id,
|
|
26870
26878
|
identifier: resolved.identifier,
|
|
26871
|
-
source: "http",
|
|
26872
26879
|
receivedAt,
|
|
26873
26880
|
context: serverActionContext(args.context, receivedAt),
|
|
26874
26881
|
geo: request?.cf,
|
|
@@ -27159,6 +27166,90 @@ var lookupPersonForApp = /* @__PURE__ */ __name(async (env, slug, id, afterRowId
|
|
|
27159
27166
|
return page === null ? null : personOf(globalId, page);
|
|
27160
27167
|
}, "lookupPersonForApp");
|
|
27161
27168
|
|
|
27169
|
+
// src/apps/broker-fields.ts
|
|
27170
|
+
var identityFields = {
|
|
27171
|
+
// Derived, never a literal: the client stamps ENVELOPE_VERSION on every body, so a hardcoded
|
|
27172
|
+
// number here silently 400s the whole channel the next time the envelope version moves.
|
|
27173
|
+
v: external_exports.literal(ENVELOPE_VERSION),
|
|
27174
|
+
slug: external_exports.string().min(1).max(30),
|
|
27175
|
+
key: external_exports.string().min(1)
|
|
27176
|
+
};
|
|
27177
|
+
|
|
27178
|
+
// src/apps/emit-payload.ts
|
|
27179
|
+
var emitPayloadSchema = external_exports.object({
|
|
27180
|
+
event: external_exports.string().min(1),
|
|
27181
|
+
eventId: external_exports.string().min(1).optional(),
|
|
27182
|
+
properties: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
|
|
27183
|
+
}).strict();
|
|
27184
|
+
var emittedEventId = /* @__PURE__ */ __name((eventId, properties2) => {
|
|
27185
|
+
if (eventId !== void 0) {
|
|
27186
|
+
return eventId;
|
|
27187
|
+
}
|
|
27188
|
+
const orderId = properties2?.["orderId"];
|
|
27189
|
+
if (typeof orderId === "string" && orderId !== "") {
|
|
27190
|
+
return orderId;
|
|
27191
|
+
}
|
|
27192
|
+
return `evt_${ulid3()}`;
|
|
27193
|
+
}, "emittedEventId");
|
|
27194
|
+
|
|
27195
|
+
// src/apps/rate-limit.ts
|
|
27196
|
+
var limiterAbsenceLogged = false;
|
|
27197
|
+
var rateLimited = /* @__PURE__ */ __name(async (env, key, binding = "BROKER_RATE_LIMITER") => {
|
|
27198
|
+
const limiter = env[binding];
|
|
27199
|
+
if (limiter === void 0) {
|
|
27200
|
+
if (!limiterAbsenceLogged) {
|
|
27201
|
+
limiterAbsenceLogged = true;
|
|
27202
|
+
addSpanEvent("rate limiter binding is absent; limits are off", { level: "warn", attrs: { binding } });
|
|
27203
|
+
}
|
|
27204
|
+
return false;
|
|
27205
|
+
}
|
|
27206
|
+
const outcome = await limiter.limit({ key });
|
|
27207
|
+
return !outcome.success;
|
|
27208
|
+
}, "rateLimited");
|
|
27209
|
+
|
|
27210
|
+
// src/apps/broker-track.ts
|
|
27211
|
+
var trackBody = external_exports.object({
|
|
27212
|
+
...identityFields,
|
|
27213
|
+
kind: external_exports.literal("track"),
|
|
27214
|
+
source: external_exports.enum(APP_HANDLER_SOURCES),
|
|
27215
|
+
userId: external_exports.string().min(1).max(64),
|
|
27216
|
+
installId: external_exports.string().min(1).max(64),
|
|
27217
|
+
event: emitSchema
|
|
27218
|
+
}).strict();
|
|
27219
|
+
var handleTrack = /* @__PURE__ */ __name(async (env, body) => {
|
|
27220
|
+
const app2 = siteRegistry().registry.apps[body.slug];
|
|
27221
|
+
if (app2 === void 0) {
|
|
27222
|
+
return Response.json({ error: "forbidden" }, { status: 403 });
|
|
27223
|
+
}
|
|
27224
|
+
if (!app2.installs.some((install) => install.active && install.id === body.installId)) {
|
|
27225
|
+
return Response.json({ error: "invalid_install" }, { status: 400 });
|
|
27226
|
+
}
|
|
27227
|
+
const parsed = emitPayloadSchema.safeParse(body.event.payload);
|
|
27228
|
+
if (!parsed.success) {
|
|
27229
|
+
return Response.json({ error: "invalid_event" }, { status: 400 });
|
|
27230
|
+
}
|
|
27231
|
+
if (!isCanonicalId(body.userId)) {
|
|
27232
|
+
return Response.json({ error: "invalid_user" }, { status: 400 });
|
|
27233
|
+
}
|
|
27234
|
+
if (await rateLimited(env, `${body.slug}:${body.installId}:track`)) {
|
|
27235
|
+
return Response.json({ error: "rate_limited" }, { status: 429 });
|
|
27236
|
+
}
|
|
27237
|
+
const site = ownSite(env);
|
|
27238
|
+
if (!await anonStub(env, body.userId).appAllowed(body.slug, site, currentTraceContext())) {
|
|
27239
|
+
return Response.json({ error: "forbidden" }, { status: 403 });
|
|
27240
|
+
}
|
|
27241
|
+
const { event, eventId, properties: properties2 } = parsed.data;
|
|
27242
|
+
const action = buildAction({
|
|
27243
|
+
type: "track",
|
|
27244
|
+
userId: body.userId,
|
|
27245
|
+
source: body.source,
|
|
27246
|
+
payload: { event, eventId: emittedEventId(eventId, properties2), properties: properties2 ?? {} },
|
|
27247
|
+
context: { source: "app", occurredAt: body.event.occurredAt, offline: false, replay: false }
|
|
27248
|
+
});
|
|
27249
|
+
await ingest(env, action, site);
|
|
27250
|
+
return Response.json({ accepted: true }, { status: 202 });
|
|
27251
|
+
}, "handleTrack");
|
|
27252
|
+
|
|
27162
27253
|
// src/id-graph/anon/context.ts
|
|
27163
27254
|
var LEVEL_KINDS = {
|
|
27164
27255
|
private: { kv: "context_private_kv", text: "context_private_text" },
|
|
@@ -27596,6 +27687,7 @@ var eventAction = /* @__PURE__ */ __name((target, trigger, snapshot) => {
|
|
|
27596
27687
|
userId: snapshot.anonId,
|
|
27597
27688
|
payload: trigger.action.payload,
|
|
27598
27689
|
receivedAt: trigger.action.receivedAt,
|
|
27690
|
+
source: trigger.action.source,
|
|
27599
27691
|
...buckets.includes("eventContext") && trigger.action.context !== void 0 ? { context: trigger.action.context } : {},
|
|
27600
27692
|
...trigger.action.browserResults?.[target.slug] === void 0 ? {} : { browser: trigger.action.browserResults[target.slug] },
|
|
27601
27693
|
...trigger.action.origin !== void 0 ? { origin: trigger.action.origin } : {}
|
|
@@ -27633,21 +27725,6 @@ var buildEnvelope = /* @__PURE__ */ __name((target, trigger, snapshot, context)
|
|
|
27633
27725
|
...trigger.kind === "event" ? { action: eventAction(target, trigger, snapshot) } : {}
|
|
27634
27726
|
};
|
|
27635
27727
|
}, "buildEnvelope");
|
|
27636
|
-
var emitPayloadSchema = external_exports.object({
|
|
27637
|
-
event: external_exports.string().min(1),
|
|
27638
|
-
eventId: external_exports.string().min(1).optional(),
|
|
27639
|
-
properties: external_exports.record(external_exports.string(), external_exports.unknown()).optional()
|
|
27640
|
-
}).strict();
|
|
27641
|
-
var emittedEventId = /* @__PURE__ */ __name((eventId, properties2) => {
|
|
27642
|
-
if (eventId !== void 0) {
|
|
27643
|
-
return eventId;
|
|
27644
|
-
}
|
|
27645
|
-
const orderId = properties2?.["orderId"];
|
|
27646
|
-
if (typeof orderId === "string" && orderId !== "") {
|
|
27647
|
-
return orderId;
|
|
27648
|
-
}
|
|
27649
|
-
return `evt_${ulid3()}`;
|
|
27650
|
-
}, "emittedEventId");
|
|
27651
27728
|
var ingestEmit = /* @__PURE__ */ __name(async (ingest2, { slug, ord, depth, emit, anonId, geo, host, context }) => {
|
|
27652
27729
|
const parsed = emitPayloadSchema.safeParse(emit.payload);
|
|
27653
27730
|
if (!parsed.success) {
|
|
@@ -27826,31 +27903,9 @@ var invokeApp = /* @__PURE__ */ __name(async (env, input2) => {
|
|
|
27826
27903
|
);
|
|
27827
27904
|
}, "invokeApp");
|
|
27828
27905
|
|
|
27829
|
-
// src/apps/rate-limit.ts
|
|
27830
|
-
var limiterAbsenceLogged = false;
|
|
27831
|
-
var rateLimited = /* @__PURE__ */ __name(async (env, key, binding = "BROKER_RATE_LIMITER") => {
|
|
27832
|
-
const limiter = env[binding];
|
|
27833
|
-
if (limiter === void 0) {
|
|
27834
|
-
if (!limiterAbsenceLogged) {
|
|
27835
|
-
limiterAbsenceLogged = true;
|
|
27836
|
-
addSpanEvent("rate limiter binding is absent; limits are off", { level: "warn", attrs: { binding } });
|
|
27837
|
-
}
|
|
27838
|
-
return false;
|
|
27839
|
-
}
|
|
27840
|
-
const outcome = await limiter.limit({ key });
|
|
27841
|
-
return !outcome.success;
|
|
27842
|
-
}, "rateLimited");
|
|
27843
|
-
|
|
27844
27906
|
// src/apps/broker.ts
|
|
27845
27907
|
var MAX_RPC_DEPTH = 3;
|
|
27846
27908
|
var BROKER_PATHS = ["/__qinto/push", "/__qinto/rpc"];
|
|
27847
|
-
var identityFields = {
|
|
27848
|
-
// Derived, never a literal: the client stamps ENVELOPE_VERSION on every body, so a hardcoded
|
|
27849
|
-
// number here silently 400s the whole channel the next time the envelope version moves.
|
|
27850
|
-
v: external_exports.literal(ENVELOPE_VERSION),
|
|
27851
|
-
slug: external_exports.string().min(1).max(30),
|
|
27852
|
-
key: external_exports.string().min(1)
|
|
27853
|
-
};
|
|
27854
27909
|
var pushBody = external_exports.object({
|
|
27855
27910
|
...identityFields,
|
|
27856
27911
|
kind: external_exports.literal("push"),
|
|
@@ -27920,7 +27975,8 @@ var brokerBody = external_exports.discriminatedUnion("kind", [
|
|
|
27920
27975
|
contextReadBody,
|
|
27921
27976
|
contextWriteBody,
|
|
27922
27977
|
factsReadBody,
|
|
27923
|
-
identityReadBody
|
|
27978
|
+
identityReadBody,
|
|
27979
|
+
trackBody
|
|
27924
27980
|
]);
|
|
27925
27981
|
var BODY_ENVELOPE_ALLOWANCE_BYTES = 2 * 1024;
|
|
27926
27982
|
var MAX_BODY_BYTES = MAX_RPC_BYTES + BODY_ENVELOPE_ALLOWANCE_BYTES;
|
|
@@ -28307,6 +28363,9 @@ var handleBroker = /* @__PURE__ */ __name(async (request, env) => {
|
|
|
28307
28363
|
case "identityRead": {
|
|
28308
28364
|
return handleIdentityRead(env, body);
|
|
28309
28365
|
}
|
|
28366
|
+
case "track": {
|
|
28367
|
+
return handleTrack(env, body);
|
|
28368
|
+
}
|
|
28310
28369
|
}
|
|
28311
28370
|
}, "handleBroker");
|
|
28312
28371
|
var brokerRoutes = new Hono2();
|
|
@@ -28749,6 +28808,7 @@ var requireScope = /* @__PURE__ */ __name((bit) => {
|
|
|
28749
28808
|
if ((entry.mask & bit) === 0) {
|
|
28750
28809
|
return c.json({ error: "forbidden" }, 403);
|
|
28751
28810
|
}
|
|
28811
|
+
c.set("actionSource", entry.app === null ? "api" : "app");
|
|
28752
28812
|
return next();
|
|
28753
28813
|
};
|
|
28754
28814
|
}, "requireScope");
|
|
@@ -30461,14 +30521,14 @@ var open2 = /* @__PURE__ */ __name(async (c) => {
|
|
|
30461
30521
|
|
|
30462
30522
|
// browser-artifact/meta.json
|
|
30463
30523
|
var meta_default = {
|
|
30464
|
-
version: "0.1.
|
|
30465
|
-
gitSha: "
|
|
30466
|
-
builtAt: "2026-09-
|
|
30467
|
-
hash: "
|
|
30524
|
+
version: "0.1.10",
|
|
30525
|
+
gitSha: "f21182929c88fa0748f575164bde781b31f4fbdd",
|
|
30526
|
+
builtAt: "2026-09-23T15:34:39.048Z",
|
|
30527
|
+
hash: "d1804e7914363626fed0280696cad5e06728b899e23c8a5ee6dcced3b67cf831"
|
|
30468
30528
|
};
|
|
30469
30529
|
|
|
30470
30530
|
// src/paths/q-js.ts
|
|
30471
|
-
import qScript from "./
|
|
30531
|
+
import qScript from "./7bc13565a6fa9d520d0ebed788d11591e8db5b44-q.js.txt";
|
|
30472
30532
|
|
|
30473
30533
|
// src/apps-q.ts
|
|
30474
30534
|
import appsQScript from "./apps-q.json";
|
|
@@ -30599,7 +30659,12 @@ var definition2 = createRoute({
|
|
|
30599
30659
|
});
|
|
30600
30660
|
var alias = createApiRouter().openapi(definition2, async (c) => {
|
|
30601
30661
|
const body = c.req.valid("json");
|
|
30602
|
-
const id = await submitAction(
|
|
30662
|
+
const id = await submitAction(
|
|
30663
|
+
c.env,
|
|
30664
|
+
body.identifier,
|
|
30665
|
+
{ type: "alias", source: c.get("actionSource"), payload: { alias: body.alias } },
|
|
30666
|
+
c.req.raw
|
|
30667
|
+
);
|
|
30603
30668
|
return respond(c, acceptedResponse, { ok: true, id });
|
|
30604
30669
|
});
|
|
30605
30670
|
|
|
@@ -30701,7 +30766,7 @@ var consent = createApiRouter().openapi(definition4, async (c) => {
|
|
|
30701
30766
|
const id = await submitAction(
|
|
30702
30767
|
c.env,
|
|
30703
30768
|
identifier,
|
|
30704
|
-
{ type: "consent", payload: { categories: categories ?? {}, apps: apps ?? {} }, context },
|
|
30769
|
+
{ type: "consent", source: c.get("actionSource"), payload: { categories: categories ?? {}, apps: apps ?? {} }, context },
|
|
30705
30770
|
c.req.raw
|
|
30706
30771
|
);
|
|
30707
30772
|
return respond(c, acceptedResponse, { ok: true, id });
|
|
@@ -30800,7 +30865,12 @@ var definition6 = createRoute({
|
|
|
30800
30865
|
});
|
|
30801
30866
|
var identify = createApiRouter().openapi(definition6, async (c) => {
|
|
30802
30867
|
const { identifier, traits, context } = c.req.valid("json");
|
|
30803
|
-
const id = await submitAction(
|
|
30868
|
+
const id = await submitAction(
|
|
30869
|
+
c.env,
|
|
30870
|
+
identifier,
|
|
30871
|
+
{ type: "identify", source: c.get("actionSource"), payload: { traits: traits ?? {} }, context },
|
|
30872
|
+
c.req.raw
|
|
30873
|
+
);
|
|
30804
30874
|
return respond(c, acceptedResponse, { ok: true, id });
|
|
30805
30875
|
});
|
|
30806
30876
|
|
|
@@ -30950,7 +31020,7 @@ var session = createApiRouter().openapi(definition9, async (c) => {
|
|
|
30950
31020
|
});
|
|
30951
31021
|
|
|
30952
31022
|
// src/paths/v1/track.ts
|
|
30953
|
-
var
|
|
31023
|
+
var trackBody2 = external_exports.object({
|
|
30954
31024
|
identifier: identifierField2,
|
|
30955
31025
|
event: external_exports.string().min(1).openapi({
|
|
30956
31026
|
description: "Name of the event the user performed.",
|
|
@@ -30982,7 +31052,7 @@ var definition10 = createRoute({
|
|
|
30982
31052
|
body: {
|
|
30983
31053
|
required: true,
|
|
30984
31054
|
description: "The event to record.",
|
|
30985
|
-
content: { "application/json": { schema:
|
|
31055
|
+
content: { "application/json": { schema: trackBody2 } }
|
|
30986
31056
|
}
|
|
30987
31057
|
},
|
|
30988
31058
|
responses: {
|
|
@@ -30999,7 +31069,7 @@ var track = createApiRouter().openapi(definition10, async (c) => {
|
|
|
30999
31069
|
const id = await submitAction(
|
|
31000
31070
|
c.env,
|
|
31001
31071
|
identifier,
|
|
31002
|
-
{ type: "track", payload: { event, eventId, properties: properties2 ?? {} }, context },
|
|
31072
|
+
{ type: "track", source: c.get("actionSource"), payload: { event, eventId, properties: properties2 ?? {} }, context },
|
|
31003
31073
|
c.req.raw
|
|
31004
31074
|
);
|
|
31005
31075
|
return respond(c, acceptedResponse, { ok: true, id });
|
|
@@ -31111,6 +31181,13 @@ var FanOut = class extends WorkerEntrypoint2 {
|
|
|
31111
31181
|
// src/apps/storage-link-site.ts
|
|
31112
31182
|
import { WorkerEntrypoint as WorkerEntrypoint3 } from "cloudflare:workers";
|
|
31113
31183
|
|
|
31184
|
+
// src/apps/action-source.ts
|
|
31185
|
+
var LEGACY_SOURCES = { ws: "website", http: "api" };
|
|
31186
|
+
var withCurrentSource = /* @__PURE__ */ __name((action) => {
|
|
31187
|
+
const current = LEGACY_SOURCES[action.source];
|
|
31188
|
+
return current === void 0 ? action : { ...action, source: current };
|
|
31189
|
+
}, "withCurrentSource");
|
|
31190
|
+
|
|
31114
31191
|
// src/apps/transform.ts
|
|
31115
31192
|
var TRANSFORM_TIMEOUT_MS = 500;
|
|
31116
31193
|
var TRANSFORM_CHAIN_BUDGET_MS = 1e3;
|
|
@@ -31312,10 +31389,11 @@ var StorageLinkSite = class extends WorkerEntrypoint3 {
|
|
|
31312
31389
|
__name(this, "StorageLinkSite");
|
|
31313
31390
|
}
|
|
31314
31391
|
fanOut(job) {
|
|
31315
|
-
|
|
31392
|
+
const trigger = job.trigger.kind === "event" ? { ...job.trigger, action: withCurrentSource(job.trigger.action) } : job.trigger;
|
|
31393
|
+
runFanOut(this.env, this.ctx, { ...job, trigger });
|
|
31316
31394
|
}
|
|
31317
31395
|
transform(input2) {
|
|
31318
|
-
return runTransformChain(this.env, { ...input2, dataPoints: createDataPointBudget() });
|
|
31396
|
+
return runTransformChain(this.env, { ...input2, action: withCurrentSource(input2.action), dataPoints: createDataPointBudget() });
|
|
31319
31397
|
}
|
|
31320
31398
|
describe() {
|
|
31321
31399
|
return describeSite(this.env);
|
|
@@ -32199,7 +32277,7 @@ var updateGeo = /* @__PURE__ */ __name((storage, geo, observedAt) => {
|
|
|
32199
32277
|
record2[key] = { value, observedAt };
|
|
32200
32278
|
mutated = true;
|
|
32201
32279
|
if (GEO_SERIES_KEY_SET.has(key)) {
|
|
32202
|
-
insertFact(storage.sql, { ...projectionFact(entry.key), value: entry.value, source: "
|
|
32280
|
+
insertFact(storage.sql, { ...projectionFact(entry.key), value: entry.value, source: "website", observedAt: entry.observedAt });
|
|
32203
32281
|
appended.push(entry);
|
|
32204
32282
|
}
|
|
32205
32283
|
}
|
|
@@ -32610,7 +32688,7 @@ var actionFromFrame = /* @__PURE__ */ __name((frame, userId, connection = {}) =>
|
|
|
32610
32688
|
type: "identify",
|
|
32611
32689
|
userId,
|
|
32612
32690
|
identifier,
|
|
32613
|
-
source: "
|
|
32691
|
+
source: "website",
|
|
32614
32692
|
payload: { traits: frame.traits ?? {} },
|
|
32615
32693
|
context: browserActionContext(frame.context, host, session2),
|
|
32616
32694
|
browserResults: frame.appResults,
|
|
@@ -32622,7 +32700,7 @@ var actionFromFrame = /* @__PURE__ */ __name((frame, userId, connection = {}) =>
|
|
|
32622
32700
|
return buildAction({
|
|
32623
32701
|
type: "track",
|
|
32624
32702
|
userId,
|
|
32625
|
-
source: "
|
|
32703
|
+
source: "website",
|
|
32626
32704
|
payload: { event: frame.event, eventId: frame.eventId, properties: frame.properties ?? {} },
|
|
32627
32705
|
context: browserActionContext(frame.context, host, session2),
|
|
32628
32706
|
browserResults: frame.appResults,
|
|
@@ -32631,13 +32709,13 @@ var actionFromFrame = /* @__PURE__ */ __name((frame, userId, connection = {}) =>
|
|
|
32631
32709
|
});
|
|
32632
32710
|
}
|
|
32633
32711
|
case "alias": {
|
|
32634
|
-
return buildAction({ type: "alias", userId, source: "
|
|
32712
|
+
return buildAction({ type: "alias", userId, source: "website", payload: { alias: frame.alias }, geo, host });
|
|
32635
32713
|
}
|
|
32636
32714
|
case "consent": {
|
|
32637
32715
|
return buildAction({
|
|
32638
32716
|
type: "consent",
|
|
32639
32717
|
userId,
|
|
32640
|
-
source: "
|
|
32718
|
+
source: "website",
|
|
32641
32719
|
payload: { categories: frame.categories ?? {}, apps: frame.apps ?? {} },
|
|
32642
32720
|
context: browserActionContext(frame.context, host, session2),
|
|
32643
32721
|
geo,
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"main": {
|
|
3
|
-
"version": "0.1.
|
|
4
|
-
"gitSha": "
|
|
5
|
-
"builtAt": "2026-09-
|
|
3
|
+
"version": "0.1.4",
|
|
4
|
+
"gitSha": "84a03b1ccdff814840f560c7efd0f72837454227",
|
|
5
|
+
"builtAt": "2026-09-24T14:23:50.391Z",
|
|
6
6
|
"compatibilityDate": "2026-06-23",
|
|
7
7
|
"compatibilityFlags": [
|
|
8
8
|
"nodejs_compat"
|
|
@@ -10,8 +10,8 @@
|
|
|
10
10
|
"mainModule": "index.js",
|
|
11
11
|
"modules": [
|
|
12
12
|
{
|
|
13
|
-
"name": "
|
|
14
|
-
"path": "main/
|
|
13
|
+
"name": "7bc13565a6fa9d520d0ebed788d11591e8db5b44-q.js.txt",
|
|
14
|
+
"path": "main/7bc13565a6fa9d520d0ebed788d11591e8db5b44-q.js.txt",
|
|
15
15
|
"contentType": "text/plain"
|
|
16
16
|
},
|
|
17
17
|
{
|
|
@@ -39,9 +39,9 @@
|
|
|
39
39
|
]
|
|
40
40
|
},
|
|
41
41
|
"app-runtime": {
|
|
42
|
-
"version": "0.1.
|
|
43
|
-
"gitSha": "
|
|
44
|
-
"builtAt": "2026-09-
|
|
42
|
+
"version": "0.1.2",
|
|
43
|
+
"gitSha": "5c24e6442ad668125bba59aaec084adb43b70d1d",
|
|
44
|
+
"builtAt": "2026-09-24T14:23:53.656Z",
|
|
45
45
|
"compatibilityDate": "2026-06-23",
|
|
46
46
|
"compatibilityFlags": [
|
|
47
47
|
"nodejs_compat"
|
package/package.json
CHANGED
|
@@ -1 +0,0 @@
|
|
|
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))},h=e=>()=>Promise.reject(e),g=(e,t)=>{let[n,r,i,a]=t;e(n,r).then(i,a)},ee=e=>{let t=[];return t.push=(...t)=>{for(let n of t)g(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=ee(e);for(let n of t)g(e,n)},o=t().then(e=>{a(m(e,n))},e=>{throw a(h(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=()=>{},te=100,ne=1024,b=32768,x=(e,t,n)=>e.target.config?.consentConfiguration?.enabled!==!0||v(n,t,e.target.config?.apps?.[t]?.category),S=e=>Object.values(e.config?.apps??{}).some(e=>e.category!==`necessary`||e.capture!==void 0),C=(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`))},re=(e,t,n,r)=>r===null?e.slug===t&&(n===void 0||n===e.installId):r.has(e.slug),w=(e,t)=>{console.error(`[Qinto] A handler of app "${e.slug}" (install "${e.installId}") failed.`,t)},T=(e,t,n)=>{for(let r of t)try{let t=r(n);t instanceof Promise&&t.catch(t=>{w(e,t)})}catch(t){w(e,t)}},ie=(e,t,n,r)=>{e.activated.add(r.id);let i={slug:t,installId:r.id,eventHandlers:[],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(y)},onEvent:e=>{i.eventHandlers.push(e)},onConsent:e=>{i.consentHandlers.push(e)},onPush:e=>{i.pushHandlers.push(e)},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&&ae(e,t)&&T(i,[n],e.sharedContext)}};try{n(a)}catch(e){console.error(`[Qinto] App "${t}" failed to activate install "${r.id}".`,e)}},E=(e,t,n)=>{if(!x(e,t,e.consent))return;let r=((`_appInstalls`in e.target?e.target._appInstalls:void 0)?.[t]??[]).filter(t=>!e.activated.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)ie(e,t,i,n)},ae=(e,t)=>x(e,t,e.consent)?e.sharedContextConsent===void 0||x(e,t,e.sharedContextConsent):!1,D=e=>{let{categories:t,apps:n}=e;if(typeof t==`object`&&t&&typeof n==`object`&&n)return{categories:t,apps:n}},O=(e,t)=>{let n=e;n.consent=t,n.sharedContextConsent=void 0;for(let n of e.instances)T(n,n.consentHandlers,t);e.onConsentSettled?.(t);for(let[t,n]of e.apps)E(e,t,n)},k=async e=>{try{O(e,await e.client.getConsent())}catch(e){console.error(`[Qinto] The apps consent read failed.`,e)}},A=e=>{let t;try{t=JSON.stringify(e)}catch{return}if(!(t===void 0||new TextEncoder().encode(t).length>ne))return JSON.parse(t)},j=e=>{let t={};for(let n of e){if(n.settled!==n.total||n.values.length!==1)continue;let e=A(n.values[0]);if(e===void 0)continue;let r={...t[n.instance.slug]??{},[n.instance.installId]:e},i={...t,[n.instance.slug]:r};new TextEncoder().encode(JSON.stringify(i)).length<=b&&(t[n.instance.slug]=r)}return Object.keys(t).length===0?void 0:t},M=async(e,t)=>{e.onPageEvent?.(e.consent);let n=[],r=[];for(let i of e.instances){if(!x(e,i.slug,e.consent))continue;if(e.target.config?.apps?.[i.slug]?.eventResults?.includes(t.type)!==!0){T(i,i.eventHandlers,t);continue}let a={instance:i,total:i.eventHandlers.length,settled:0,values:[]};n.push(a);for(let e of i.eventHandlers){let n;try{n=e(t)}catch(e){a.settled+=1,w(i,e);continue}r.push(Promise.resolve(n).then(e=>{a.settled+=1,e!==void 0&&a.values.push(e)},e=>{a.settled+=1,w(i,e)}))}}if(r.length>0){let e=y,t=new Promise(t=>{e=t}),n=setTimeout(e,te);await Promise.race([Promise.all(r),t]),clearTimeout(n)}return j(n)},N=e=>{let{client:t}=e;return{track:async(n,r,i)=>{let o=a(i?.eventId,r),s=t.actionContext(),c=await M(e,{type:`track`,event:n,eventId:o,properties:r??{}});return await t.submitTrack({event:n,eventId:o,properties:r,context:s,appResults:c}),{eventId:o}},identify:async(n,r)=>{let i=t.actionContext(),a=await M(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?.(),S(e.target)){let t=e;t.consent=null,await k(e)}},getAnonId:t.getAnonId,getConsent:t.getConsent,getSession:t.getSession,close:t.close}},P=(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=D(e),a=r??n.consent;n.sharedContextConsent=r;for(let e of n.instances)x(n,e.slug,a)&&T(e,e.sharedContextHandlers,n.sharedContext)},push:e=>{let{app:t,install:n,topic:r,scope:a,to:o}=e,s=a===`site`;if(C(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)re(e,t,n,l)&&x(c,e.slug,c.consent)&&T(e,e.pushHandlers,u)},connect:async a=>{let o={target:e,client:a,apps:n,instances:[],activated:new Set,consent:null,sharedContext:i?.sharedContext??null,sharedContextConsent:i?.sharedContextConsent,onConsentSettled:t?.onConsentSettled,onConsentMutation:t?.onConsentMutation,onPageEvent:t?.onPageEvent};i=o,r=(e,t)=>{E(o,e,t),o.consent===null&&o.target.config?.consentConfiguration?.enabled===!0&&o.target.config?.apps?.[e]?.category!==`necessary`&&k(o)};for(let[e,t]of n)E(o,e,t);return e.config?.consentConfiguration?.enabled===!0&&S(e)?await k(o):o.onConsentSettled?.(o.consent),N(o)}}},F=512,I=864e5,L=e=>Object.fromEntries(Object.entries(e).map(([e,t])=>[e,Object.fromEntries(Object.entries(t).map(([e,t])=>[e,t.value]))])),R=(e,t)=>`qinto:cap:${encodeURIComponent(e)}:${encodeURIComponent(t)}`,z=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>I?null:{at:n.at,anonId:n.anonId,apps:n.apps}}catch{return null}},B=(e,t)=>{try{window.sessionStorage.setItem(e,JSON.stringify(t))}catch{}},V=e=>{try{window.sessionStorage.removeItem(e)}catch{}},H=e=>{try{return decodeURIComponent(e)}catch{return e}},U=()=>{let e={};for(let t of document.cookie.split(`;`)){let n=t.indexOf(`=`);n>0&&(e[t.slice(0,n).trim()]=H(t.slice(n+1)))}return e},W=(e,t)=>{let n={};for(let r of e.queryParams){let e=t.params.get(r);e!==null&&e.length<=F&&(n[r]={value:e,source:`query`})}for(let r of e.cookies){let e=t.cookies[r];e!==void 0&&e.length<=F&&(n[r]={value:e,source:`cookie`})}return n},G=(e,t)=>{let n={params:new URLSearchParams(window.location.search),cookies:U()},r={};for(let[i,a]of Object.entries(e.config?.apps??{})){if(a.capture===void 0||!v(t,i,a.category))continue;let e=W(a.capture,n);Object.keys(e).length>0&&(r[i]=e)}return r},K=(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},oe=(e,t,n,r)=>{let i=R(r,n),a=z(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});B(i,{at:Date.now(),anonId:s,apps:o})},f=null,p=()=>{u+=1,o={},l={},V(i)},m=n=>{if(f=n,!c)return;let r=K(G(e,n),{...o,...l});if(Object.keys(r).length===0)return;let i=u;l={...l,...r},t(L(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}},q=Symbol.for(`qinto.connectGate`),J=()=>{},se=e=>{let t=globalThis,n=(t[q]??Promise.resolve()).then(e);return t[q]=n.then(J,J),n},Y=class extends n{constructor(e){super(e),this.name=`QintoProtocolError`}},ce=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===`appPush`||n.t===`sharedContext`?t:null},le=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}},ue=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 Y(e.message));return}t.resolve(le(e))}},rejectAll:e=>{let n=[...t.values()];t.clear();for(let t of n)clearTimeout(t.timer),t.reject(e)}}},de=e=>new WebSocket(e),fe=500,pe=3e4,me=`session not initialized`,he=(e,t)=>{let n=Math.min(fe*2**e,pe);return Math.round(n/2+n/2*t)},ge=(e,t)=>e.t===`appPush`?(t.onAppPush?.(e),!0):e.t===`sharedContext`&&(t.onSharedContext?.(e),!0),X=e=>{let t=`${e.destination.replace(/\/+$/,``)}/open`,n=null,r=null,i=0,a=null,o=ue({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 Y(`connection closed`))},l=()=>{let u=de(t);n=u,u.onopen=()=>{i=0;let e=a;a=null,o.flush(),e?.resolve()},u.onmessage=t=>{let n=ce(t.data);if(n===null){s(new Y(`invalid message`));return}ge(n,e)||(`anonId`in n&&typeof n.anonId==`string`&&e.onAnonId?.(n.anonId),o.deliver(n),n.t===`error`&&n.message===me&&u.close())},u.onerror=()=>{s(new Y(`connection closed`))},u.onclose=()=>{if(n!==u)return;n=null;let e=a;if(e!==null){a=null,c(),e.reject(new Y(`connection closed`));return}o.rejectAll(new Y(`connection closed`)),r=setTimeout(()=>{r=null,l()},he(i,Math.random())),i+=1}};return{connect:()=>new Promise((e,t)=>{a={resolve:e,reject:t},l()}),submit:e=>o.submit(e),close:()=>{c()}}},_e=1e4,ve=()=>{let e=0;return()=>(e+=1,`q${e}`)},ye=(e,t)=>{let n=`qinto:visit:${e.replace(/\/+$/,``)}:${t}`,r,i=!1;try{let e=sessionStorage.getItem(n),t=e===null?null:JSON.parse(e);t===null||typeof t.id!=`string`||!/^vis_[0-9a-f-]{36}$/.test(t.id)||!Number.isSafeInteger(t.startedAt)||t.startedAt<0?(r={id:`vis_${crypto.randomUUID()}`,startedAt:Date.now()},sessionStorage.setItem(n,JSON.stringify(r)),i=!0):r={id:t.id,startedAt:t.startedAt}}catch{r={id:`vis_${crypto.randomUUID()}`,startedAt:Date.now()},i=!0}return()=>{let e={...r,isNew:i};return i=!1,e}},be=(e,t,n,r)=>{let i=null,o=ye(n,r),s=()=>{let e=document.referrer;return{occurredAt:Date.now(),page:{url:window.location.href,...e===``?{}:{referrer:e}},session:o()}},c=async()=>{let n=await e.submit({t:`getSession`,ref:t()});return i=n.anonId,n};return{actionContext:s,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})=>{await e.submit({t:`track`,ref:t(),event:n,eventId:r,properties:i,context:a,appResults:o})},submitConsent:async(n,r)=>{await e.submit({t:`consent`,ref:t(),categories:n.categories,apps:n.apps,context:r})},track:async(n,r,i)=>{let o=a(i?.eventId,r);return await e.submit({t:`track`,ref:t(),event:n,eventId:o,properties:r,context:s()}),{eventId:o}},alias:async n=>{await e.submit({t:`alias`,ref:t(),alias:n})},getConsent:async()=>await e.submit({t:`getConsent`,ref:t()}),getSession:c,getAnonId:async()=>(i===null&&await c(),i),close:async()=>{e.close()}}},xe=async e=>{let t=X({destination:e.destination,requestTimeoutMs:e.requestTimeoutMs??_e,onError:e.onError,onAppPush:e.onAppPush,onSharedContext:e.onSharedContext,onAnonId:e.onAnonId});await se(()=>t.connect());let n=ve();return{client:be(t,n,e.destination,e.globalName),submitCapture:async e=>await t.submit({t:`capture`,ref:n(),apps:e})}},Se=(e,t)=>{let n=null,r=P(e,{onConsentSettled:e=>{n?.settled(e)},onConsentMutation:()=>{n?.clear()},onPageEvent:e=>{n?.settled(e)}});return{connect:async i=>{let a=await xe({...i,globalName:t,onAppPush:r.push,onSharedContext:r.sharedContext,onAnonId:e=>{n?.observedAnon(e)}});n=oe(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=Se(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})},$)}})();
|